summaryrefslogtreecommitdiff
path: root/gcc/ada/sem_attr.adb
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/ada/sem_attr.adb')
-rw-r--r--gcc/ada/sem_attr.adb255
1 files changed, 253 insertions, 2 deletions
diff --git a/gcc/ada/sem_attr.adb b/gcc/ada/sem_attr.adb
index 4118087d5f6..7ed94b4d91a 100644
--- a/gcc/ada/sem_attr.adb
+++ b/gcc/ada/sem_attr.adb
@@ -30,6 +30,7 @@ with Casing; use Casing;
with Checks; use Checks;
with Debug; use Debug;
with Einfo; use Einfo;
+with Elists; use Elists;
with Errout; use Errout;
with Eval_Fat;
with Exp_Dist; use Exp_Dist;
@@ -375,6 +376,10 @@ package body Sem_Attr is
pragma No_Return (Error_Attr);
-- Like Error_Attr, but error is posted at the start of the prefix
+ procedure S14_Attribute;
+ -- Called for all attributes defined for formal verification to check
+ -- that the S14_Extensions flag is set.
+
procedure Standard_Attribute (Val : Int);
-- Used to process attributes whose prefix is package Standard which
-- yield values of type Universal_Integer. The attribute reference
@@ -1950,6 +1955,18 @@ package body Sem_Attr is
Set_Etype (N, Standard_Boolean);
end Legal_Formal_Attribute;
+ -------------------
+ -- S14_Attribute --
+ -------------------
+
+ procedure S14_Attribute is
+ begin
+ if not Formal_Extensions then
+ Error_Attr
+ ("attribute % requires the use of debug switch -gnatd.V", N);
+ end if;
+ end S14_Attribute;
+
------------------------
-- Standard_Attribute --
------------------------
@@ -3584,6 +3601,231 @@ package body Sem_Attr is
("prefix of % attribute must be a protected object");
end if;
+ ----------------
+ -- Loop_Entry --
+ ----------------
+
+ when Attribute_Loop_Entry => Loop_Entry : declare
+ procedure Check_References_In_Prefix (Loop_Id : Entity_Id);
+ -- Inspect the prefix for any uses of entities declared within the
+ -- related loop. Loop_Id denotes the loop identifier.
+
+ --------------------------------
+ -- Check_References_In_Prefix --
+ --------------------------------
+
+ procedure Check_References_In_Prefix (Loop_Id : Entity_Id) is
+ Loop_Decl : constant Node_Id := Label_Construct (Parent (Loop_Id));
+
+ function Check_Reference (Nod : Node_Id) return Traverse_Result;
+ -- Determine whether a reference mentions an entity declared
+ -- within the related loop.
+
+ function Declared_Within (Nod : Node_Id) return Boolean;
+ -- Determine whether Nod appears in the subtree of Loop_Decl
+
+ ---------------------
+ -- Check_Reference --
+ ---------------------
+
+ function Check_Reference (Nod : Node_Id) return Traverse_Result is
+ begin
+ if Nkind (Nod) = N_Identifier
+ and then Present (Entity (Nod))
+ and then Declared_Within (Declaration_Node (Entity (Nod)))
+ then
+ Error_Attr
+ ("prefix of attribute % cannot reference local entities",
+ Nod);
+ return Abandon;
+ else
+ return OK;
+ end if;
+ end Check_Reference;
+
+ procedure Check_References is new Traverse_Proc (Check_Reference);
+
+ ---------------------
+ -- Declared_Within --
+ ---------------------
+
+ function Declared_Within (Nod : Node_Id) return Boolean is
+ Stmt : Node_Id;
+
+ begin
+ Stmt := Nod;
+ while Present (Stmt) loop
+ if Stmt = Loop_Decl then
+ return True;
+
+ -- Prevent the search from going too far
+
+ elsif Nkind_In (Stmt, N_Entry_Body,
+ N_Package_Body,
+ N_Package_Declaration,
+ N_Protected_Body,
+ N_Subprogram_Body,
+ N_Task_Body)
+ then
+ exit;
+ end if;
+
+ Stmt := Parent (Stmt);
+ end loop;
+
+ return False;
+ end Declared_Within;
+
+ -- Start of processing for Check_Prefix_For_Local_References
+
+ begin
+ Check_References (P);
+ end Check_References_In_Prefix;
+
+ -- Local variables
+
+ Enclosing_Loop : Node_Id;
+ In_Loop_Assertion : Boolean := False;
+ Loop_Id : Entity_Id := Empty;
+ Scop : Entity_Id;
+ Stmt : Node_Id;
+
+ -- Start of processing for Loop_Entry
+
+ begin
+ S14_Attribute;
+ Check_E1;
+ Analyze (E1);
+
+ -- The prefix must denote an object
+
+ if not Is_Object_Reference (P) then
+ Error_Attr_P ("prefix of attribute % must denote an object");
+ end if;
+
+ -- The prefix cannot be of a limited type because the expansion of
+ -- Loop_Entry must create a constant initialized by the evaluated
+ -- prefix.
+
+ if Is_Immutably_Limited_Type (Etype (P)) then
+ Error_Attr_P ("prefix of attribute % cannot be limited");
+ end if;
+
+ -- The sole argument of a Loop_Entry must be a loop name
+
+ if Is_Entity_Name (E1) then
+ Loop_Id := Entity (E1);
+ end if;
+
+ if No (Loop_Id)
+ or else Ekind (Loop_Id) /= E_Loop
+ or else not In_Open_Scopes (Loop_Id)
+ then
+ Error_Attr ("argument of % must be a valid loop name", E1);
+ return;
+ end if;
+
+ -- Climb the parent chain to verify the location of the attribute and
+ -- find the enclosing loop.
+
+ Stmt := N;
+ while Present (Stmt) loop
+
+ -- Locate the enclosing Loop_Assertion pragma (if any). Note that
+ -- when Loop_Assertion is expanded, we must look for an Assertion
+ -- pragma.
+
+ if Nkind (Original_Node (Stmt)) = N_Pragma
+ and then
+ (Pragma_Name (Original_Node (Stmt)) = Name_Assert
+ or else
+ Pragma_Name (Original_Node (Stmt)) = Name_Loop_Assertion)
+ then
+ In_Loop_Assertion := True;
+
+ -- Locate the enclosing loop (if any). Note that Ada 2012 array
+ -- iteration may be expanded into several nested loops, we are
+ -- interested in the outermost one which has the loop identifier.
+
+ elsif Nkind (Stmt) = N_Loop_Statement
+ and then Present (Identifier (Stmt))
+ then
+ Enclosing_Loop := Stmt;
+ exit;
+
+ -- Prevent the search from going too far
+
+ elsif Nkind_In (Stmt, N_Entry_Body,
+ N_Package_Body,
+ N_Package_Declaration,
+ N_Protected_Body,
+ N_Subprogram_Body,
+ N_Task_Body)
+ then
+ exit;
+ end if;
+
+ Stmt := Parent (Stmt);
+ end loop;
+
+ -- Loop_Entry must appear within a Loop_Assertion pragma
+
+ if not In_Loop_Assertion then
+ Error_Attr
+ ("attribute % must appear within pragma Loop_Assertion", N);
+ end if;
+
+ -- A Loop_Entry that applies to a given loop statement shall not
+ -- appear within a body of accept statement, if this construct is
+ -- itself enclosed by the given loop statement.
+
+ for J in reverse 0 .. Scope_Stack.Last loop
+ Scop := Scope_Stack.Table (J).Entity;
+
+ if Ekind (Scop) = E_Loop and then Scop = Loop_Id then
+ exit;
+
+ elsif Ekind_In (Scop, E_Block, E_Loop, E_Return_Statement) then
+ null;
+
+ else
+ Error_Attr
+ ("cannot appear in program unit or accept statement", N);
+ exit;
+ end if;
+ end loop;
+
+ -- The prefix cannot mention entities declared within the related
+ -- loop because they will not be visible once the prefix is moved
+ -- outside the loop.
+
+ Check_References_In_Prefix (Loop_Id);
+
+ -- The prefix must denote a static entity if the pragma does not
+ -- apply to the innermost enclosing loop statement.
+
+ if Present (Enclosing_Loop)
+ and then Entity (Identifier (Enclosing_Loop)) /= Loop_Id
+ and then not Is_Entity_Name (P)
+ then
+ Error_Attr_P ("prefix of attribute % must denote an entity");
+ end if;
+
+ Set_Etype (N, Etype (P));
+
+ -- Associate the attribute with its related loop
+
+ if No (Loop_Entry_Attributes (Loop_Id)) then
+ Set_Loop_Entry_Attributes (Loop_Id, New_Elmt_List);
+ end if;
+
+ -- A Loop_Entry may be [pre]analyzed several times, depending on the
+ -- context. Ensure that it appears only once in the attributes list
+ -- of the related loop.
+
+ Append_Unique_Elmt (N, Loop_Entry_Attributes (Loop_Id));
+ end Loop_Entry;
+
-------------
-- Machine --
-------------
@@ -6517,7 +6759,7 @@ package body Sem_Attr is
when Attribute_Denorm =>
Fold_Uint
- (N, UI_From_Int (Boolean'Pos (Denorm_On_Target)), True);
+ (N, UI_From_Int (Boolean'Pos (Has_Denormals (P_Type))), True);
---------------------
-- Descriptor_Size --
@@ -6989,6 +7231,15 @@ package body Sem_Attr is
end;
end Length;
+ ----------------
+ -- Loop_Entry --
+ ----------------
+
+ -- This null processing requires an explanatory comment???
+
+ when Attribute_Loop_Entry =>
+ null;
+
-------------
-- Machine --
-------------
@@ -7631,7 +7882,7 @@ package body Sem_Attr is
when Attribute_Signed_Zeros =>
Fold_Uint
- (N, UI_From_Int (Boolean'Pos (Signed_Zeros_On_Target)), Static);
+ (N, UI_From_Int (Boolean'Pos (Has_Signed_Zeros (P_Type))), Static);
----------
-- Size --