summaryrefslogtreecommitdiff
path: root/gcc/ada/sem_ch8.adb
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/ada/sem_ch8.adb')
-rw-r--r--gcc/ada/sem_ch8.adb248
1 files changed, 113 insertions, 135 deletions
diff --git a/gcc/ada/sem_ch8.adb b/gcc/ada/sem_ch8.adb
index 4fdef1cdac2..27ccc2d3d1e 100644
--- a/gcc/ada/sem_ch8.adb
+++ b/gcc/ada/sem_ch8.adb
@@ -2069,11 +2069,20 @@ package body Sem_Ch8 is
if Is_Incomplete_Or_Private_Type (Etype (F))
and then No (Underlying_Type (Etype (F)))
- and then not Is_Generic_Type (Etype (F))
then
- Error_Msg_NE
- ("type& must be frozen before this point",
- Instantiation_Node, Etype (F));
+
+ -- Exclude generic types, or types derived from them.
+ -- They will be frozen in the enclosing instance.
+
+ if Is_Generic_Type (Etype (F))
+ or else Is_Generic_Type (Root_Type (Etype (F)))
+ then
+ null;
+ else
+ Error_Msg_NE
+ ("type& must be frozen before this point",
+ Instantiation_Node, Etype (F));
+ end if;
end if;
F := Next_Formal (F);
@@ -2816,7 +2825,7 @@ package body Sem_Ch8 is
-- The following is illegal, because F hides whatever other F may
-- be around:
- -- function F (..) renames F;
+ -- function F (...) renames F;
elsif Old_S = New_S
or else (Nkind (Nam) /= N_Expanded_Name
@@ -2824,6 +2833,10 @@ package body Sem_Ch8 is
then
Error_Msg_N ("subprogram cannot rename itself", N);
+ -- This is illegal even if we use a selector:
+ -- function F (...) renames Pkg.F;
+ -- because F is still hidden.
+
elsif Nkind (Nam) = N_Expanded_Name
and then Entity (Prefix (Nam)) = Current_Scope
and then Chars (Selector_Name (Nam)) = Chars (New_S)
@@ -3287,14 +3300,14 @@ package body Sem_Ch8 is
------------------------
procedure Attribute_Renaming (N : Node_Id) is
- Loc : constant Source_Ptr := Sloc (N);
- Nam : constant Node_Id := Name (N);
- Spec : constant Node_Id := Specification (N);
- New_S : constant Entity_Id := Defining_Unit_Name (Spec);
- Aname : constant Name_Id := Attribute_Name (Nam);
+ Loc : constant Source_Ptr := Sloc (N);
+ Nam : constant Node_Id := Name (N);
+ Spec : constant Node_Id := Specification (N);
+ New_S : constant Entity_Id := Defining_Unit_Name (Spec);
+ Aname : constant Name_Id := Attribute_Name (Nam);
- Form_Num : Nat := 0;
- Expr_List : List_Id := No_List;
+ Form_Num : Nat := 0;
+ Expr_List : List_Id := No_List;
Attr_Node : Node_Id;
Body_Node : Node_Id;
@@ -3305,12 +3318,12 @@ package body Sem_Ch8 is
-- This procedure is called in the context of subprogram renaming, and
-- thus the attribute must be one that is a subprogram. All of those
- -- have at least one formal parameter, with the singular exception of
- -- AST_Entry (which is a real oddity, it is odd that this can be renamed
- -- at all!)
+ -- have at least one formal parameter, with the exceptions of AST_Entry
+ -- (which is a real oddity, it is odd that this can be renamed at all!)
+ -- and the GNAT attribute 'Img, which GNAT treats as renameable.
if not Is_Non_Empty_List (Parameter_Specifications (Spec)) then
- if Aname /= Name_AST_Entry then
+ if Aname /= Name_AST_Entry and then Aname /= Name_Img then
Error_Msg_N
("subprogram renaming an attribute must have formals", N);
return;
@@ -3329,8 +3342,8 @@ package body Sem_Ch8 is
-- there are no subtypes involved.
Rewrite (Parameter_Type (Param_Spec),
- New_Reference_To
- (Base_Type (Entity (Parameter_Type (Param_Spec))), Loc));
+ New_Reference_To
+ (Base_Type (Entity (Parameter_Type (Param_Spec))), Loc));
end if;
if No (Expr_List) then
@@ -3480,10 +3493,20 @@ package body Sem_Ch8 is
and then Etype (Nam) /= RTE (RE_AST_Handler)
then
declare
- P : constant Entity_Id := Prefix (Nam);
+ P : constant Node_Id := Prefix (Nam);
begin
- Find_Type (P);
+ -- The prefix of 'Img is an object that is evaluated for each call
+ -- of the function that renames it.
+
+ if Aname = Name_Img then
+ Preanalyze_And_Resolve (P);
+
+ -- For all other attribute renamings, the prefix is a subtype
+
+ else
+ Find_Type (P);
+ end if;
if Is_Tagged_Type (Etype (P)) then
Ensure_Freeze_Node (Etype (P));
@@ -5859,7 +5882,7 @@ package body Sem_Ch8 is
-- Selector name cannot be a character literal or an operator symbol in
-- SPARK, except for the operator symbol in a renaming.
- if Restriction_Check_Required (SPARK) then
+ if Restriction_Check_Required (SPARK_05) then
if Nkind (Selector_Name (N)) = N_Character_Literal then
Check_SPARK_Restriction
("character literal cannot be prefixed", N);
@@ -6199,7 +6222,7 @@ package body Sem_Ch8 is
-- Selector name is restricted in SPARK
if Nkind (N) = N_Expanded_Name
- and then Restriction_Check_Required (SPARK)
+ and then Restriction_Check_Required (SPARK_05)
then
if Is_Subprogram (P_Name) then
Check_SPARK_Restriction
@@ -7641,121 +7664,26 @@ package body Sem_Ch8 is
-- Restore_Scope_Stack --
-------------------------
- procedure Restore_Scope_Stack (Handle_Use : Boolean := True) is
- E : Entity_Id;
- S : Entity_Id;
- Comp_Unit : Node_Id;
- In_Child : Boolean := False;
- Full_Vis : Boolean := True;
- SS_Last : constant Int := Scope_Stack.Last;
+ procedure Restore_Scope_Stack
+ (List : Elist_Id;
+ Handle_Use : Boolean := True)
+ is
+ SS_Last : constant Int := Scope_Stack.Last;
+ Elmt : Elmt_Id;
begin
- -- Restore visibility of previous scope stack, if any
-
- for J in reverse 0 .. Scope_Stack.Last loop
- exit when Scope_Stack.Table (J).Entity = Standard_Standard
- or else No (Scope_Stack.Table (J).Entity);
-
- S := Scope_Stack.Table (J).Entity;
-
- if not Is_Hidden_Open_Scope (S) then
-
- -- If the parent scope is hidden, its entities are hidden as
- -- well, unless the entity is the instantiation currently
- -- being analyzed.
-
- if not Is_Hidden_Open_Scope (Scope (S))
- or else not Analyzed (Parent (S))
- or else Scope (S) = Standard_Standard
- then
- Set_Is_Immediately_Visible (S, True);
- end if;
-
- E := First_Entity (S);
- while Present (E) loop
- if Is_Child_Unit (E) then
- if not From_With_Type (E) then
- Set_Is_Immediately_Visible (E,
- Is_Visible_Lib_Unit (E) or else In_Open_Scopes (E));
-
- else
- pragma Assert
- (Nkind (Parent (E)) = N_Defining_Program_Unit_Name
- and then
- Nkind (Parent (Parent (E))) =
- N_Package_Specification);
- Set_Is_Immediately_Visible (E,
- Limited_View_Installed (Parent (Parent (E))));
- end if;
- else
- Set_Is_Immediately_Visible (E, True);
- end if;
-
- Next_Entity (E);
-
- if not Full_Vis and then Is_Package_Or_Generic_Package (S) then
-
- -- We are in the visible part of the package scope
-
- exit when E = First_Private_Entity (S);
- end if;
- end loop;
-
- -- The visibility of child units (siblings of current compilation)
- -- must be restored in any case. Their declarations may appear
- -- after the private part of the parent.
-
- if not Full_Vis then
- while Present (E) loop
- if Is_Child_Unit (E) then
- Set_Is_Immediately_Visible (E,
- Is_Visible_Lib_Unit (E) or else In_Open_Scopes (E));
- end if;
-
- Next_Entity (E);
- end loop;
- end if;
- end if;
+ -- Restore visibility of previous scope stack, if any, using the list
+ -- we saved (we use Remove, since this list will not be used again).
- if Is_Child_Unit (S)
- and not In_Child -- check only for current unit
- then
- In_Child := True;
-
- -- Restore visibility of parents according to whether the child
- -- is private and whether we are in its visible part.
-
- Comp_Unit := Parent (Unit_Declaration_Node (S));
-
- if Nkind (Comp_Unit) = N_Compilation_Unit
- and then Private_Present (Comp_Unit)
- then
- Full_Vis := True;
-
- elsif Is_Package_Or_Generic_Package (S)
- and then (In_Private_Part (S) or else In_Package_Body (S))
- then
- Full_Vis := True;
-
- -- if S is the scope of some instance (which has already been
- -- seen on the stack) it does not affect the visibility of
- -- other scopes.
-
- elsif Is_Hidden_Open_Scope (S) then
- null;
-
- elsif Ekind_In (S, E_Procedure, E_Function)
- and then Has_Completion (S)
- then
- Full_Vis := True;
- else
- Full_Vis := False;
- end if;
- else
- Full_Vis := True;
- end if;
+ loop
+ Elmt := Last_Elmt (List);
+ exit when Elmt = No_Elmt;
+ Set_Is_Immediately_Visible (Node (Elmt));
+ Remove_Last_Elmt (List);
end loop;
+ -- Restore use clauses
+
if SS_Last >= Scope_Stack.First
and then Scope_Stack.Table (SS_Last).Entity /= Standard_Standard
and then Handle_Use
@@ -7768,11 +7696,58 @@ package body Sem_Ch8 is
-- Save_Scope_Stack --
----------------------
- procedure Save_Scope_Stack (Handle_Use : Boolean := True) is
+ -- Save_Scope_Stack/Restore_Scope_Stack were originally designed to avoid
+ -- consuming any memory. That is, Save_Scope_Stack took care of removing
+ -- from immediate visibility entities and Restore_Scope_Stack took care
+ -- of restoring their visibility analyzing the context of each entity. The
+ -- problem of such approach is that it was fragile and caused unexpected
+ -- visibility problems, and indeed one test was found where there was a
+ -- real problem.
+
+ -- Furthermore, the following experiment was carried out:
+
+ -- - Save_Scope_Stack was modified to store in an Elist1 all those
+ -- entities whose attribute Is_Immediately_Visible is modified
+ -- from True to False.
+
+ -- - Restore_Scope_Stack was modified to store in another Elist2
+ -- all the entities whose attribute Is_Immediately_Visible is
+ -- modified from False to True.
+
+ -- - Extra code was added to verify that all the elements of Elist1
+ -- are found in Elist2
+
+ -- This test shows that there may be more occurrences of this problem which
+ -- have not yet been detected. As a result, we replaced that approach by
+ -- the current one in which Save_Scope_Stack returns the list of entities
+ -- whose visibility is changed, and that list is passed to Restore_Scope_
+ -- Stack to undo that change. This approach is simpler and safer, although
+ -- it consumes more memory.
+
+ function Save_Scope_Stack (Handle_Use : Boolean := True) return Elist_Id is
+ Result : constant Elist_Id := New_Elmt_List;
E : Entity_Id;
S : Entity_Id;
SS_Last : constant Int := Scope_Stack.Last;
+ procedure Remove_From_Visibility (E : Entity_Id);
+ -- If E is immediately visible then append it to the result and remove
+ -- it temporarily from visibility.
+
+ ----------------------------
+ -- Remove_From_Visibility --
+ ----------------------------
+
+ procedure Remove_From_Visibility (E : Entity_Id) is
+ begin
+ if Is_Immediately_Visible (E) then
+ Append_Elmt (E, Result);
+ Set_Is_Immediately_Visible (E, False);
+ end if;
+ end Remove_From_Visibility;
+
+ -- Start of processing for Save_Scope_Stack
+
begin
if SS_Last >= Scope_Stack.First
and then Scope_Stack.Table (SS_Last).Entity /= Standard_Standard
@@ -7790,16 +7765,19 @@ package body Sem_Ch8 is
or else No (Scope_Stack.Table (J).Entity);
S := Scope_Stack.Table (J).Entity;
- Set_Is_Immediately_Visible (S, False);
+
+ Remove_From_Visibility (S);
E := First_Entity (S);
while Present (E) loop
- Set_Is_Immediately_Visible (E, False);
+ Remove_From_Visibility (E);
Next_Entity (E);
end loop;
end loop;
end if;
+
+ return Result;
end Save_Scope_Stack;
-------------