diff options
author | Yannick Moy <moy@adacore.com> | 2019-07-09 07:53:45 +0000 |
---|---|---|
committer | Pierre-Marie de Rodat <pmderodat@gcc.gnu.org> | 2019-07-09 07:53:45 +0000 |
commit | 995d28c7551ce6a65bd34355169106aab9ee65b6 (patch) | |
tree | aad0e457523bfb411fb26a2edf8c00da9765613e /gcc | |
parent | 578d5941ee23743c28959d84fd5f6eec09c7734d (diff) | |
download | gcc-995d28c7551ce6a65bd34355169106aab9ee65b6.zip gcc-995d28c7551ce6a65bd34355169106aab9ee65b6.tar.gz gcc-995d28c7551ce6a65bd34355169106aab9ee65b6.tar.bz2 |
[Ada] Handle implicit moves in SPARK ownership pointer support
Allocator expressions and sub-expressions of (extension) aggregates are
implicitly the source of assignments in Ada. Thus, they should be moved
when of a deep type when checking ownership rules in SPARK.
There is no impact on compilation.
2019-07-09 Yannick Moy <moy@adacore.com>
gcc/ada/
* sem_spark.adb (Check_Expression): Handle correctly implicit
assignments as part of allocators and (extension) aggregates.
(Get_Root_Object): Adapt for new path expressions.
(Is_Path_Expression): Return True for (extension) aggregate.
From-SVN: r273271
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ada/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/ada/sem_spark.adb | 208 |
2 files changed, 167 insertions, 48 deletions
diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index c0ba4af..86b02b3 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,10 @@ +2019-07-09 Yannick Moy <moy@adacore.com> + + * sem_spark.adb (Check_Expression): Handle correctly implicit + assignments as part of allocators and (extension) aggregates. + (Get_Root_Object): Adapt for new path expressions. + (Is_Path_Expression): Return True for (extension) aggregate. + 2019-07-09 Piotr Trojanek <trojanek@adacore.com> * einfo.ads: Fix a typo. diff --git a/gcc/ada/sem_spark.adb b/gcc/ada/sem_spark.adb index 6f27d20..bbd7279 100644 --- a/gcc/ada/sem_spark.adb +++ b/gcc/ada/sem_spark.adb @@ -1436,6 +1436,13 @@ package body Sem_SPARK is function Is_Type_Name (Expr : Node_Id) return Boolean; -- Detect when a path expression is in fact a type name + procedure Move_Expression (Expr : Node_Id); + -- Some subexpressions are only analyzed in Move mode. This is a + -- specialized version of Check_Expression for that case. + + procedure Move_Expression_List (L : List_Id); + -- Call Move_Expression on every expression in the list L + procedure Read_Expression (Expr : Node_Id); -- Most subexpressions are only analyzed in Read mode. This is a -- specialized version of Check_Expression for that case. @@ -1459,6 +1466,36 @@ package body Sem_SPARK is end Is_Type_Name; --------------------- + -- Move_Expression -- + --------------------- + + -- Distinguish the case where the argument is a path expression that + -- needs explicit moving. + + procedure Move_Expression (Expr : Node_Id) is + begin + if Is_Path_Expression (Expr) then + Check_Expression (Expr, Move); + else + Read_Expression (Expr); + end if; + end Move_Expression; + + -------------------------- + -- Move_Expression_List -- + -------------------------- + + procedure Move_Expression_List (L : List_Id) is + N : Node_Id; + begin + N := First (L); + while Present (N) loop + Move_Expression (N); + Next (N); + end loop; + end Move_Expression_List; + + --------------------- -- Read_Expression -- --------------------- @@ -1489,7 +1526,26 @@ package body Sem_SPARK is -- Local subprograms + function Is_Singleton_Choice (Choices : List_Id) return Boolean; + -- Return whether Choices is a singleton choice + procedure Read_Param (Formal : Entity_Id; Actual : Node_Id); + -- Call Read_Expression on the actual + + ------------------------- + -- Is_Singleton_Choice -- + ------------------------- + + function Is_Singleton_Choice (Choices : List_Id) return Boolean is + Choice : constant Node_Id := First (Choices); + begin + return List_Length (Choices) = 1 + and then Nkind (Choice) /= N_Others_Choice + and then not Nkind_In (Choice, N_Subtype_Indication, N_Range) + and then not + (Nkind_In (Choice, N_Identifier, N_Expanded_Name) + and then Is_Type (Entity (Choice))); + end Is_Singleton_Choice; ---------------- -- Read_Param -- @@ -1526,8 +1582,11 @@ package body Sem_SPARK is Read_Indexes (Prefix (Expr)); Read_Expression (Discrete_Range (Expr)); + -- The argument of an allocator is moved as part of the implicit + -- assignment. + when N_Allocator => - Read_Expression (Expression (Expr)); + Move_Expression (Expression (Expr)); when N_Function_Call => Read_Params (Expr); @@ -1539,6 +1598,91 @@ package body Sem_SPARK is => Read_Indexes (Expression (Expr)); + when N_Aggregate => + declare + Assocs : constant List_Id := Component_Associations (Expr); + CL : List_Id; + Assoc : Node_Id := Nlists.First (Assocs); + Choice : Node_Id; + + begin + -- The subexpressions of an aggregate are moved as part + -- of the implicit assignments. Handle the positional + -- components first. + + Move_Expression_List (Expressions (Expr)); + + -- Handle the named components next. + + while Present (Assoc) loop + CL := Choices (Assoc); + + -- For an array aggregate, we should also check that the + -- expressions used in choices are readable. + + if Is_Array_Type (Etype (Expr)) then + Choice := Nlists.First (CL); + while Present (Choice) loop + if Nkind (Choice) /= N_Others_Choice then + Read_Expression (Choice); + end if; + Next (Choice); + end loop; + end if; + + -- There can be only one element for a value of deep type + -- in order to avoid aliasing. + + if Is_Deep (Etype (Expression (Assoc))) + and then not Is_Singleton_Choice (CL) + then + Error_Msg_F ("singleton choice required" + & " to prevent aliasing", First (CL)); + end if; + + -- The subexpressions of an aggregate are moved as part + -- of the implicit assignments. + + Move_Expression (Expression (Assoc)); + + Next (Assoc); + end loop; + end; + + when N_Extension_Aggregate => + declare + Exprs : constant List_Id := Expressions (Expr); + Assocs : constant List_Id := Component_Associations (Expr); + CL : List_Id; + Assoc : Node_Id := Nlists.First (Assocs); + + begin + Move_Expression (Ancestor_Part (Expr)); + + -- No positional components allowed at this stage + + if Present (Exprs) then + raise Program_Error; + end if; + + while Present (Assoc) loop + CL := Choices (Assoc); + + -- Only singleton components allowed at this stage + + if not Is_Singleton_Choice (CL) then + raise Program_Error; + end if; + + -- The subexpressions of an aggregate are moved as part + -- of the implicit assignments. + + Move_Expression (Expression (Assoc)); + + Next (Assoc); + end loop; + end; + when others => raise Program_Error; end case; @@ -1759,45 +1903,6 @@ package body Sem_SPARK is Read_Expression (Condition (Expr)); end; - when N_Aggregate => - declare - Assocs : constant List_Id := Component_Associations (Expr); - Assoc : Node_Id := First (Assocs); - CL : List_Id; - Choice : Node_Id; - - begin - while Present (Assoc) loop - - -- An array aggregate with a single component association - -- may have a nonstatic choice expression that needs to be - -- analyzed. This can only occur for a single choice that - -- is not the OTHERS one. - - if Is_Array_Type (Etype (Expr)) then - CL := Choices (Assoc); - if List_Length (CL) = 1 then - Choice := First (CL); - if Nkind (Choice) /= N_Others_Choice then - Read_Expression (Choice); - end if; - end if; - end if; - - -- The expression in the component association also needs to - -- be analyzed. - - Read_Expression (Expression (Assoc)); - Next (Assoc); - end loop; - - Read_Expression_List (Expressions (Expr)); - end; - - when N_Extension_Aggregate => - Read_Expression (Ancestor_Part (Expr)); - Read_Expression_List (Expressions (Expr)); - when N_Character_Literal | N_Numeric_Or_String_Literal | N_Operator_Symbol @@ -1818,9 +1923,11 @@ package body Sem_SPARK is -- Path expressions are handled before this point - when N_Allocator + when N_Aggregate + | N_Allocator | N_Expanded_Name | N_Explicit_Dereference + | N_Extension_Aggregate | N_Function_Call | N_Identifier | N_Indexed_Component @@ -3283,7 +3390,7 @@ package body Sem_SPARK is return (R => Unfolded, Tree_Access => C); end; - -- For a non-terminal path, we get the permission tree of its + -- For a nonterminal path, we get the permission tree of its -- prefix, and then get the subtree associated with the extension, -- if unfolded. If folded, we return the permission associated with -- children. @@ -3389,9 +3496,12 @@ package body Sem_SPARK is => return Get_Root_Object (Prefix (Expr), Through_Traversal); - -- There is no root object for an allocator or NULL + -- There is no root object for an (extension) aggregate, allocator, + -- or NULL. - when N_Allocator + when N_Aggregate + | N_Allocator + | N_Extension_Aggregate | N_Null => return Empty; @@ -3596,10 +3706,12 @@ package body Sem_SPARK is when N_Null => return True; - -- Object returned by a allocator or function call corresponds to - -- a path. + -- Object returned by an (extension) aggregate, an allocator, or + -- a function call corresponds to a path. - when N_Allocator + when N_Aggregate + | N_Allocator + | N_Extension_Aggregate | N_Function_Call => return True; @@ -4763,7 +4875,7 @@ package body Sem_SPARK is return C; end; - -- For a non-terminal path, we set the permission tree of its prefix, + -- For a nonterminal path, we set the permission tree of its prefix, -- and then we extract from the returned pointer the subtree and -- assign an adequate permission to it, if unfolded. If folded, -- we unroll the tree one level. |