aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ada/exp_prag.adb25
-rw-r--r--gcc/ada/sem_prag.adb61
-rw-r--r--gcc/ada/snames.ads-tmpl1
-rw-r--r--gcc/testsuite/gnat.dg/loopvar.adb2
4 files changed, 64 insertions, 25 deletions
diff --git a/gcc/ada/exp_prag.adb b/gcc/ada/exp_prag.adb
index 0fe8bff..bf2d297 100644
--- a/gcc/ada/exp_prag.adb
+++ b/gcc/ada/exp_prag.adb
@@ -2694,10 +2694,15 @@ package body Exp_Prag is
-- If pragma is not enabled, rewrite as Null statement. If pragma is
-- disabled, it has already been rewritten as a Null statement.
--
- -- Likewise, do this in CodePeer mode, because the expanded code is too
+ -- Likewise, ignore structural variants for execution.
+ --
+ -- Also do this in CodePeer mode, because the expanded code is too
-- complicated for CodePeer to analyse.
- if Is_Ignored (N) or else CodePeer_Mode then
+ if Is_Ignored (N)
+ or else Chars (Last_Var) = Name_Structural
+ or else CodePeer_Mode
+ then
Rewrite (N, Make_Null_Statement (Loc));
Analyze (N);
return;
@@ -3058,10 +3063,12 @@ package body Exp_Prag is
Loc : constant Source_Ptr := Sloc (Prag);
- Aggr : Node_Id;
+ Aggr : constant Node_Id :=
+ Expression (First (Pragma_Argument_Associations (Prag)));
Formal_Map : Elist_Id;
Last : Node_Id;
- Last_Variant : Node_Id;
+ Last_Variant : constant Node_Id :=
+ Nlists.Last (Component_Associations (Aggr));
Proc_Bod : Node_Id;
Proc_Decl : Node_Id;
Proc_Id : Entity_Id;
@@ -3069,14 +3076,15 @@ package body Exp_Prag is
Variant : Node_Id;
begin
- -- Do nothing if pragma is not present or is disabled
+ -- Do nothing if pragma is not present or is disabled.
+ -- Also ignore structural variants for execution.
- if Is_Ignored (Prag) then
+ if Is_Ignored (Prag)
+ or else Chars (Nlists.Last (Choices (Last_Variant))) = Name_Structural
+ then
return;
end if;
- Aggr := Expression (First (Pragma_Argument_Associations (Prag)));
-
-- The expansion of Subprogram Variant is quite distributed as it
-- produces various statements to capture and compare the arguments.
-- To preserve the original context, set the Is_Assertion_Expr flag.
@@ -3115,7 +3123,6 @@ package body Exp_Prag is
Last := Proc_Decl;
Curr_Decls := New_List;
- Last_Variant := Nlists.Last (Component_Associations (Aggr));
Variant := First (Component_Associations (Aggr));
while Present (Variant) loop
diff --git a/gcc/ada/sem_prag.adb b/gcc/ada/sem_prag.adb
index 9ef3a06..57a74db 100644
--- a/gcc/ada/sem_prag.adb
+++ b/gcc/ada/sem_prag.adb
@@ -19423,7 +19423,8 @@ package body Sem_Prag is
if Chars (Variant) = No_Name then
Error_Pragma_Arg_Ident ("expect name `Increases`", Variant);
- elsif Chars (Variant) not in Name_Decreases | Name_Increases
+ elsif Chars (Variant) not in
+ Name_Decreases | Name_Increases | Name_Structural
then
declare
Name : String := Get_Name_String (Chars (Variant));
@@ -19448,11 +19449,24 @@ package body Sem_Prag is
Error_Pragma_Arg_Ident
("expect name `Decreases`", Variant);
+ elsif Name'Length >= 4
+ and then Name (1 .. 4) = "stru"
+ then
+ Error_Pragma_Arg_Ident
+ ("expect name `Structural`", Variant);
+
else
Error_Pragma_Arg_Ident
- ("expect name `Increases` or `Decreases`", Variant);
+ ("expect name `Increases`, `Decreases`,"
+ & " or `Structural`", Variant);
end if;
end;
+
+ elsif Chars (Variant) = Name_Structural
+ and then List_Length (Pragma_Argument_Associations (N)) > 1
+ then
+ Error_Pragma_Arg_Ident
+ ("Structural variant shall be the only variant", Variant);
end if;
-- Preanalyze_Assert_Expression, but without enforcing any of
@@ -19460,9 +19474,12 @@ package body Sem_Prag is
Preanalyze_Assert_Expression (Expression (Variant));
- -- Expression of a discrete type is allowed
+ -- Expression of a discrete type is allowed. Nothing to
+ -- check for structural variants.
- if Is_Discrete_Type (Etype (Expression (Variant))) then
+ if Chars (Variant) = Name_Structural
+ or else Is_Discrete_Type (Etype (Expression (Variant)))
+ then
null;
-- Expression of a Big_Integer type (or its ghost variant) is
@@ -24227,13 +24244,16 @@ package body Sem_Prag is
-- Subprogram_Variant --
------------------------
- -- pragma Subprogram_Variant ( SUBPROGRAM_VARIANT_ITEM
- -- {, SUBPROGRAM_VARIANT_ITEM } );
-
- -- SUBPROGRAM_VARIANT_ITEM ::=
- -- CHANGE_DIRECTION => discrete_EXPRESSION
+ -- pragma Subprogram_Variant ( SUBPROGRAM_VARIANT_LIST );
- -- CHANGE_DIRECTION ::= Increases | Decreases
+ -- SUBPROGRAM_VARIANT_LIST ::= STRUCTURAL_SUBPROGRAM_VARIANT_ITEM
+ -- | NUMERIC_SUBPROGRAM_VARIANT_ITEMS
+ -- NUMERIC_SUBPROGRAM_VARIANT_ITEMS ::=
+ -- NUMERIC_SUBPROGRAM_VARIANT_ITEM
+ -- {, NUMERIC_SUBPROGRAM_VARIANT_ITEM}
+ -- NUMERIC_SUBPROGRAM_VARIANT_ITEM ::= CHANGE_DIRECTION => EXPRESSION
+ -- STRUCTURAL_SUBPROGRAM_VARIANT_ITEM ::= Structural => EXPRESSION
+ -- CHANGE_DIRECTION ::= Increases | Decreases
-- Characteristics:
@@ -29435,9 +29455,9 @@ package body Sem_Prag is
-- Check placement of OTHERS if available (SPARK RM 6.1.3(1))
if Nkind (Direction) = N_Identifier then
- if Chars (Direction) /= Name_Decreases
- and then
- Chars (Direction) /= Name_Increases
+ if Chars (Direction) not in Name_Decreases
+ | Name_Increases
+ | Name_Structural
then
Error_Msg_N ("wrong direction", Direction);
end if;
@@ -29452,9 +29472,12 @@ package body Sem_Prag is
Preanalyze_Assert_Expression (Expr);
- -- Expression of a discrete type is allowed
+ -- Expression of a discrete type is allowed. Nothing more to check
+ -- for structural variants.
- if Is_Discrete_Type (Etype (Expr)) then
+ if Is_Discrete_Type (Etype (Expr))
+ or else Chars (Direction) = Name_Structural
+ then
null;
-- Expression of a Big_Integer type (or its ghost variant) is only
@@ -29561,6 +29584,14 @@ package body Sem_Prag is
Variant := First (Component_Associations (Variants));
while Present (Variant) loop
Analyze_Variant (Variant);
+
+ if Chars (First (Choices (Variant))) = Name_Structural
+ and then List_Length (Component_Associations (Variants)) > 1
+ then
+ Error_Msg_N
+ ("Structural variant shall be the only variant", Variant);
+ end if;
+
Next (Variant);
end loop;
diff --git a/gcc/ada/snames.ads-tmpl b/gcc/ada/snames.ads-tmpl
index fa7ac8a..5f7d6b7 100644
--- a/gcc/ada/snames.ads-tmpl
+++ b/gcc/ada/snames.ads-tmpl
@@ -875,6 +875,7 @@ package Snames is
Name_Static : constant Name_Id := N + $;
Name_Stack_Size : constant Name_Id := N + $;
Name_Strict : constant Name_Id := N + $;
+ Name_Structural : constant Name_Id := N + $;
Name_Subunit_File_Name : constant Name_Id := N + $;
Name_Suppressible : constant Name_Id := N + $;
Name_Synchronous : constant Name_Id := N + $;
diff --git a/gcc/testsuite/gnat.dg/loopvar.adb b/gcc/testsuite/gnat.dg/loopvar.adb
index f85402a..e98d20d 100644
--- a/gcc/testsuite/gnat.dg/loopvar.adb
+++ b/gcc/testsuite/gnat.dg/loopvar.adb
@@ -9,7 +9,7 @@ begin
pragma Loop_Variant (J + 1); -- { dg-error "expect name \"Increases\"" }
pragma Loop_Variant (incr => -J + 1); -- { dg-error "expect name \"Increases\"" }
pragma Loop_Variant (decr => -J + 1); -- { dg-error "expect name \"Decreases\"" }
- pragma Loop_Variant (foof => -J + 1); -- { dg-error "expect name \"Increases\" or \"Decreases\"" }
+ pragma Loop_Variant (foof => -J + 1); -- { dg-error "expect name \"Increases\", \"Decreases\", or \"Structural\"" }
J := J + 2;
end loop;
end Loopvar;