summaryrefslogtreecommitdiff
path: root/gcc/ada/sem_util.adb
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/ada/sem_util.adb')
-rw-r--r--gcc/ada/sem_util.adb279
1 files changed, 254 insertions, 25 deletions
diff --git a/gcc/ada/sem_util.adb b/gcc/ada/sem_util.adb
index f97dbb4adb1..6a5e5f1a1fd 100644
--- a/gcc/ada/sem_util.adb
+++ b/gcc/ada/sem_util.adb
@@ -981,6 +981,27 @@ package body Sem_Util is
Set_Has_Fully_Qualified_Name (Elab_Ent);
end Build_Elaboration_Entity;
+ --------------------------------
+ -- Build_Explicit_Dereference --
+ --------------------------------
+
+ procedure Build_Explicit_Dereference
+ (Expr : Node_Id;
+ Disc : Entity_Id)
+ is
+ Loc : constant Source_Ptr := Sloc (Expr);
+ begin
+ Set_Is_Overloaded (Expr, False);
+ Rewrite (Expr,
+ Make_Explicit_Dereference (Loc,
+ Prefix =>
+ Make_Selected_Component (Loc,
+ Prefix => Relocate_Node (Expr),
+ Selector_Name => New_Occurrence_Of (Disc, Loc))));
+ Set_Etype (Prefix (Expr), Etype (Disc));
+ Set_Etype (Expr, Designated_Type (Etype (Disc)));
+ end Build_Explicit_Dereference;
+
-----------------------------------
-- Cannot_Raise_Constraint_Error --
-----------------------------------
@@ -1360,7 +1381,7 @@ package body Sem_Util is
return;
end if;
- -- Ada 2012 AI04-0144-2: Dangerous order dependence. Actuals in nested
+ -- Ada 2012 AI05-0144-2: Dangerous order dependence. Actuals in nested
-- calls within a construct have been collected. If one of them is
-- writable and overlaps with another one, evaluation of the enclosing
-- construct is nondeterministic. This is illegal in Ada 2012, but is
@@ -4168,6 +4189,15 @@ package body Sem_Util is
end if;
end Get_Actual_Subtype_If_Available;
+ ------------------------
+ -- Get_Body_From_Stub --
+ ------------------------
+
+ function Get_Body_From_Stub (N : Node_Id) return Node_Id is
+ begin
+ return Proper_Body (Unit (Library_Unit (N)));
+ end Get_Body_From_Stub;
+
-------------------------------
-- Get_Default_External_Name --
-------------------------------
@@ -4271,11 +4301,15 @@ package body Sem_Util is
if List_Length (Args) = 4 then
Res := Pick (Args, 4);
- else
+ elsif List_Length (Args) = 3 then
Res := Pick (Args, 3);
+
if Chars (Res) /= Name_Ensures then
Res := Empty;
end if;
+
+ else
+ Res := Empty;
end if;
return Res;
@@ -4430,8 +4464,14 @@ package body Sem_Util is
Res : Node_Id;
begin
- Res := Pick (Args, 3);
- if Chars (Res) /= Name_Requires then
+ if List_Length (Args) >= 3 then
+ Res := Pick (Args, 3);
+
+ if Chars (Res) /= Name_Requires then
+ Res := Empty;
+ end if;
+
+ else
Res := Empty;
end if;
@@ -7125,6 +7165,51 @@ package body Sem_Util is
end if;
end Is_Fully_Initialized_Variant;
+ -----------------
+ -- Is_Iterator --
+ -----------------
+
+ function Is_Iterator (Typ : Entity_Id) return Boolean is
+ Ifaces_List : Elist_Id;
+ Iface_Elmt : Elmt_Id;
+ Iface : Entity_Id;
+
+ begin
+ if Is_Class_Wide_Type (Typ)
+ and then
+ (Chars (Etype (Typ)) = Name_Forward_Iterator
+ or else
+ Chars (Etype (Typ)) = Name_Reversible_Iterator)
+ and then
+ Is_Predefined_File_Name
+ (Unit_File_Name (Get_Source_Unit (Etype (Typ))))
+ then
+ return True;
+
+ elsif not Is_Tagged_Type (Typ) or else not Is_Derived_Type (Typ) then
+ return False;
+
+ else
+ Collect_Interfaces (Typ, Ifaces_List);
+
+ Iface_Elmt := First_Elmt (Ifaces_List);
+ while Present (Iface_Elmt) loop
+ Iface := Node (Iface_Elmt);
+ if Chars (Iface) = Name_Forward_Iterator
+ and then
+ Is_Predefined_File_Name
+ (Unit_File_Name (Get_Source_Unit (Iface)))
+ then
+ return True;
+ end if;
+
+ Next_Elmt (Iface_Elmt);
+ end loop;
+
+ return False;
+ end if;
+ end Is_Iterator;
+
------------
-- Is_LHS --
------------
@@ -7351,7 +7436,20 @@ package body Sem_Util is
-- but we still want to allow the conversion if it converts a variable).
elsif Original_Node (AV) /= AV then
- return Is_OK_Variable_For_Out_Formal (Original_Node (AV));
+
+ -- In Ada2012, the explicit dereference may be a rewritten call to a
+ -- Reference function.
+
+ if Ada_Version >= Ada_2012
+ and then Nkind (Original_Node (AV)) = N_Function_Call
+ and then
+ Has_Implicit_Dereference (Etype (Name (Original_Node (AV))))
+ then
+ return True;
+
+ else
+ return Is_OK_Variable_For_Out_Formal (Original_Node (AV));
+ end if;
-- All other non-variables are rejected
@@ -7584,9 +7682,9 @@ package body Sem_Util is
begin
-- Verify that prefix is analyzed and has the proper form. Note that
- -- the attributes Elab_Spec, Elab_Body, and UET_Address, which also
- -- produce the address of an entity, do not analyze their prefix
- -- because they denote entities that are not necessarily visible.
+ -- the attributes Elab_Spec, Elab_Body, Elab_Subp_Body and UET_Address,
+ -- which also produce the address of an entity, do not analyze their
+ -- prefix because they denote entities that are not necessarily visible.
-- Neither of them can apply to a protected type.
return Ada_Version >= Ada_2005
@@ -7755,6 +7853,50 @@ package body Sem_Util is
return False;
end Is_Renamed_Entry;
+ ----------------------------
+ -- Is_Reversible_Iterator --
+ ----------------------------
+
+ function Is_Reversible_Iterator (Typ : Entity_Id) return Boolean is
+ Ifaces_List : Elist_Id;
+ Iface_Elmt : Elmt_Id;
+ Iface : Entity_Id;
+
+ begin
+ if Is_Class_Wide_Type (Typ)
+ and then Chars (Etype (Typ)) = Name_Reversible_Iterator
+ and then
+ Is_Predefined_File_Name
+ (Unit_File_Name (Get_Source_Unit (Etype (Typ))))
+ then
+ return True;
+
+ elsif not Is_Tagged_Type (Typ)
+ or else not Is_Derived_Type (Typ)
+ then
+ return False;
+
+ else
+ Collect_Interfaces (Typ, Ifaces_List);
+
+ Iface_Elmt := First_Elmt (Ifaces_List);
+ while Present (Iface_Elmt) loop
+ Iface := Node (Iface_Elmt);
+ if Chars (Iface) = Name_Reversible_Iterator
+ and then
+ Is_Predefined_File_Name
+ (Unit_File_Name (Get_Source_Unit (Iface)))
+ then
+ return True;
+ end if;
+
+ Next_Elmt (Iface_Elmt);
+ end loop;
+ end if;
+
+ return False;
+ end Is_Reversible_Iterator;
+
----------------------
-- Is_Selector_Name --
----------------------
@@ -7939,6 +8081,22 @@ package body Sem_Util is
or else Nkind (N) = N_Procedure_Call_Statement;
end Is_Statement;
+ --------------------------------------------------
+ -- Is_Subprogram_Stub_Without_Prior_Declaration --
+ --------------------------------------------------
+
+ function Is_Subprogram_Stub_Without_Prior_Declaration
+ (N : Node_Id) return Boolean
+ is
+ begin
+ -- A subprogram stub without prior declaration serves as declaration for
+ -- the actual subprogram body. As such, it has an attached defining
+ -- entity of E_[Generic_]Function or E_[Generic_]Procedure.
+
+ return Nkind (N) = N_Subprogram_Body_Stub
+ and then Ekind (Defining_Entity (N)) /= E_Subprogram_Body;
+ end Is_Subprogram_Stub_Without_Prior_Declaration;
+
---------------------------------
-- Is_Synchronized_Tagged_Type --
---------------------------------
@@ -8349,6 +8507,19 @@ package body Sem_Util is
end if;
end Is_Volatile_Object;
+ ---------------------------
+ -- Itype_Has_Declaration --
+ ---------------------------
+
+ function Itype_Has_Declaration (Id : Entity_Id) return Boolean is
+ begin
+ pragma Assert (Is_Itype (Id));
+ return Present (Parent (Id))
+ and then Nkind_In (Parent (Id), N_Full_Type_Declaration,
+ N_Subtype_Declaration)
+ and then Defining_Entity (Parent (Id)) = Id;
+ end Itype_Has_Declaration;
+
-------------------------
-- Kill_Current_Values --
-------------------------
@@ -10335,6 +10506,13 @@ package body Sem_Util is
P : constant Node_Id := Prefix (Exp);
begin
+ -- In formal verification mode, keep track of all reads and
+ -- writes through explicit dereferences.
+
+ if ALFA_Mode then
+ ALFA.Generate_Dereference (N, 'm');
+ end if;
+
if Nkind (P) = N_Selected_Component
and then Present (
Entry_Formal (Entity (Selector_Name (P))))
@@ -10525,8 +10703,14 @@ package body Sem_Util is
-- Start of processing for Object_Access_Level
begin
- if Is_Entity_Name (Obj) then
- E := Entity (Obj);
+ if Nkind (Obj) = N_Defining_Identifier
+ or else Is_Entity_Name (Obj)
+ then
+ if Nkind (Obj) = N_Defining_Identifier then
+ E := Obj;
+ else
+ E := Entity (Obj);
+ end if;
if Is_Prival (E) then
E := Prival_Link (E);
@@ -11677,10 +11861,10 @@ package body Sem_Util is
-- Set_Current_Entity --
------------------------
- -- The given entity is to be set as the currently visible definition
- -- of its associated name (i.e. the Node_Id associated with its name).
- -- All we have to do is to get the name from the identifier, and
- -- then set the associated Node_Id to point to the given entity.
+ -- The given entity is to be set as the currently visible definition of its
+ -- associated name (i.e. the Node_Id associated with its name). All we have
+ -- to do is to get the name from the identifier, and then set the
+ -- associated Node_Id to point to the given entity.
procedure Set_Current_Entity (E : Entity_Id) is
begin
@@ -12336,21 +12520,56 @@ package body Sem_Util is
function Unique_Defining_Entity (N : Node_Id) return Entity_Id is
begin
- case Nkind (N) is
- when N_Package_Body =>
- return Corresponding_Spec (N);
+ return Unique_Entity (Defining_Entity (N));
+ end Unique_Defining_Entity;
+
+ -------------------
+ -- Unique_Entity --
+ -------------------
+
+ function Unique_Entity (E : Entity_Id) return Entity_Id is
+ U : Entity_Id := E;
+ P : Node_Id;
+
+ begin
+ case Ekind (E) is
+ when Type_Kind =>
+ if Present (Full_View (E)) then
+ U := Full_View (E);
+ end if;
+
+ when E_Package_Body =>
+ P := Parent (E);
+
+ if Nkind (P) = N_Defining_Program_Unit_Name then
+ P := Parent (P);
+ end if;
+
+ U := Corresponding_Spec (P);
- when N_Subprogram_Body =>
- if Acts_As_Spec (N) then
- return Defining_Entity (N);
+ when E_Subprogram_Body =>
+ P := Parent (E);
+
+ if Nkind (P) = N_Defining_Program_Unit_Name then
+ P := Parent (P);
+ end if;
+
+ P := Parent (P);
+
+ if Nkind (P) = N_Subprogram_Body_Stub then
+ if Present (Library_Unit (P)) then
+ U := Get_Body_From_Stub (P);
+ end if;
else
- return Corresponding_Spec (N);
+ U := Corresponding_Spec (P);
end if;
when others =>
- return Defining_Entity (N);
+ null;
end case;
- end Unique_Defining_Entity;
+
+ return U;
+ end Unique_Entity;
-----------------
-- Unique_Name --
@@ -12378,11 +12597,15 @@ package body Sem_Util is
end if;
end Get_Scoped_Name;
+ -- Start of processing for Unique_Name
+
begin
if E = Standard_Standard then
return Get_Name_String (Name_Standard);
- elsif Scope (E) = Standard_Standard then
+ elsif Scope (E) = Standard_Standard
+ and then not (Ekind (E) = E_Package or else Is_Subprogram (E))
+ then
return Get_Name_String (Name_Standard) & "__" &
Get_Name_String (Chars (E));
@@ -12428,7 +12651,13 @@ package body Sem_Util is
and then Nkind (N) not in N_Generic_Renaming_Declaration
loop
N := Parent (N);
- pragma Assert (Present (N));
+
+ -- We don't use Assert here, because that causes an infinite loop
+ -- when assertions are turned off. Better to crash.
+
+ if No (N) then
+ raise Program_Error;
+ end if;
end loop;
return N;