aboutsummaryrefslogtreecommitdiff
path: root/gcc/ada/sem_prag.adb
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/ada/sem_prag.adb')
-rw-r--r--gcc/ada/sem_prag.adb182
1 files changed, 182 insertions, 0 deletions
diff --git a/gcc/ada/sem_prag.adb b/gcc/ada/sem_prag.adb
index c391e27..b9172cd 100644
--- a/gcc/ada/sem_prag.adb
+++ b/gcc/ada/sem_prag.adb
@@ -26343,6 +26343,187 @@ package body Sem_Prag is
Check_Valid_Configuration_Pragma;
Use_VADS_Size := True;
+ ----------------------------
+ -- User_Aspect_Definition --
+ ----------------------------
+
+ -- pragma User_Aspect_Definition
+ -- (Identifier, {, Identifier [(Identifier {, Identifier})]});
+
+ when Pragma_User_Aspect_Definition =>
+ GNAT_Pragma;
+ Check_Valid_Configuration_Pragma;
+ declare
+ Arg : Node_Id :=
+ First (Pragma_Argument_Associations (N));
+ User_Aspect_Name : constant Name_Id := Chars (Expression (Arg));
+ Expr : Node_Id;
+ Aspect : Aspect_Id;
+ begin
+ if Get_Aspect_Id (User_Aspect_Name) /= No_Aspect then
+ Error_Pragma_Arg
+ ("User-defined aspect name for pragma% is the name " &
+ "of an existing aspect", Arg);
+ end if;
+
+ Next (Arg); -- skip first argument, the name of the aspect
+
+ while Present (Arg) loop
+ Expr := Expression (Arg);
+ case Nkind (Expr) is
+ when N_Identifier =>
+ Aspect := Get_Aspect_Id (Chars (Expr));
+ if Aspect in Boolean_Aspects
+ and not Is_Representation_Aspect (Aspect)
+ then
+ -- If we allowed representation aspects such as
+ -- Pack here, then User_Aspect itself would need
+ -- to be a representation aspect.
+
+ null;
+ elsif Aspect = No_Aspect and then
+ Present (User_Aspect_Support.Registered_UAD_Pragma
+ (User_Aspect_Name))
+ then
+ null;
+ else
+ Error_Pragma_Arg
+ ("unparameterized argument for pragma% must be " &
+ "either a Boolean-valued non-representation " &
+ "aspect or user-defined", Arg);
+ end if;
+ when N_Indexed_Component =>
+ Aspect := Get_Aspect_Id (Chars (Prefix (Expr)));
+
+ -- Aspect should be an aspect that takes
+ -- identifier arguments that do not refer to
+ -- declarations, but rather to undeclared entities
+ -- such as GNATProve or No_Secondary_Stack for
+ -- which the notion of visibility does not apply.
+
+ case Aspect is
+ when Aspect_Annotate =>
+ if List_Length (Expressions (Expr)) /= 2 then
+ Error_Pragma_Arg
+ ("Annotate argument for pragma% takes " &
+ "two parameters", Arg);
+ end if;
+
+ when Aspect_Local_Restrictions =>
+ null;
+
+ when others =>
+ Error_Pragma_Arg
+ ("parameterized argument for pragma% must be " &
+ "Annotate or Local_Restrictions aspect", Arg);
+ end case;
+ when others =>
+ raise Program_Error; -- parsing error
+ end case;
+ Next (Arg);
+ end loop;
+
+ declare
+ Registered : constant Node_Id :=
+ User_Aspect_Support.Registered_UAD_Pragma
+ (User_Aspect_Name);
+
+ -- Given two User_Aspect_Definition pragmas with
+ -- matching names for the first argument, check that
+ -- subsequent arguments also match; complain if they differ.
+ procedure Check_UAD_Conformance
+ (New_Pragma, Old_Pragma : Node_Id);
+
+ ---------------------------
+ -- Check_UAD_Conformance --
+ ---------------------------
+
+ procedure Check_UAD_Conformance
+ (New_Pragma, Old_Pragma : Node_Id)
+ is
+ Old_Arg : Node_Id :=
+ First (Pragma_Argument_Associations (Old_Pragma));
+ New_Arg : Node_Id :=
+ First (Pragma_Argument_Associations (New_Pragma));
+ OK : Boolean := True;
+
+ function Same_Chars (Id1, Id2 : Node_Id) return Boolean
+ is (Chars (Id1) = Chars (Id2));
+
+ function Same_Identifier_List (Id1, Id2 : Node_Id)
+ return Boolean
+ is (if No (Id1) and No (Id2) then True
+ elsif No (Id1) or No (Id2) then False
+ else (Same_Chars (Id1, Id2) and then
+ Same_Identifier_List (Next (Id1), Next (Id2))));
+ begin
+ -- We could skip the first argument pair since those
+ -- are already known to match (or we wouldn't be
+ -- calling this procedure).
+
+ while Present (Old_Arg) or Present (New_Arg) loop
+ if Present (Old_Arg) /= Present (New_Arg) then
+ OK := False;
+ elsif Nkind (Expression (Old_Arg)) /=
+ Nkind (Expression (New_Arg))
+ then
+ OK := False;
+ else
+ case Nkind (Expression (Old_Arg)) is
+ when N_Identifier =>
+ OK := Same_Chars (Expression (Old_Arg),
+ Expression (New_Arg));
+
+ when N_Indexed_Component =>
+ OK := Same_Chars
+ (Prefix (Expression (Old_Arg)),
+ Prefix (Expression (New_Arg)))
+ and then Same_Identifier_List
+ (First (Expressions
+ (Expression (Old_Arg))),
+ First (Expressions
+ (Expression (New_Arg))));
+
+ when others =>
+ OK := False;
+ pragma Assert (False);
+ end case;
+ end if;
+
+ if not OK then
+ Error_Msg_Sloc := Sloc (Old_Pragma);
+ Error_Msg_N
+ ("Nonconforming definitions for user-defined " &
+ "aspect #", New_Pragma);
+ return;
+ end if;
+
+ Next (Old_Arg);
+ Next (New_Arg);
+ end loop;
+ end Check_UAD_Conformance;
+ begin
+ if Present (Registered) then
+ -- If we have already seen a UAD pragma with this name,
+ -- then check that the two pragmas conform (which means
+ -- that the new pragma is redundant and can be ignored).
+
+ -- ??? We could also perform a similar bind-time check,
+ -- since it is possible that an incompatible pair of
+ -- UAD pragmas might not be detected by this check.
+ -- This could arise if no unit's compilation closure
+ -- includes both of the two. The major downside of
+ -- failing to detect this case is possible confusion
+ -- for human readers.
+
+ Check_UAD_Conformance (New_Pragma => N,
+ Old_Pragma => Registered);
+ else
+ User_Aspect_Support.Register_UAD_Pragma (N);
+ end if;
+ end;
+ end;
+
---------------------
-- Validity_Checks --
---------------------
@@ -32675,6 +32856,7 @@ package body Sem_Prag is
Pragma_Unsuppress => 0,
Pragma_Unused => 0,
Pragma_Use_VADS_Size => 0,
+ Pragma_User_Aspect_Definition => 0,
Pragma_Validity_Checks => 0,
Pragma_Volatile => 0,
Pragma_Volatile_Components => 0,