-- the designated type. Otherwise freezing the access type does not freeze
-- the designated type.
- function Should_Freeze_Type
- (Typ : Entity_Id; E : Entity_Id; N : Node_Id) return Boolean;
- -- If Typ is in the current scope, then return True.
- -- N is a node whose source location corresponds to the freeze point.
- -- ??? Expression functions (represented by E) shouldn't freeze types in
- -- general, but our current expansion and freezing model requires an early
- -- freezing when the dispatch table is needed or when building an aggregate
- -- with a subtype of Typ, so return True also in this case.
- -- Note that expression function completions do freeze and are
- -- handled in Sem_Ch6.Analyze_Expression_Function.
-
- ------------------------
- -- Should_Freeze_Type --
- ------------------------
-
- function Should_Freeze_Type
- (Typ : Entity_Id; E : Entity_Id; N : Node_Id) return Boolean
- is
- function Is_Dispatching_Call_Or_Aggregate
- (N : Node_Id) return Traverse_Result;
- -- Return Abandon if N is a dispatching call to a subprogram
- -- declared in the same scope as Typ or an aggregate whose type
- -- is Typ.
-
- --------------------------------------
- -- Is_Dispatching_Call_Or_Aggregate --
- --------------------------------------
-
- function Is_Dispatching_Call_Or_Aggregate
- (N : Node_Id) return Traverse_Result is
- begin
- if Nkind (N) = N_Function_Call
- and then Present (Controlling_Argument (N))
- and then Scope (Entity (Original_Node (Name (N))))
- = Scope (Typ)
- then
- return Abandon;
- elsif Nkind (N) in N_Aggregate
- | N_Extension_Aggregate
- | N_Delta_Aggregate
- and then Base_Type (Etype (N)) = Base_Type (Typ)
- then
- return Abandon;
- else
- return OK;
- end if;
- end Is_Dispatching_Call_Or_Aggregate;
-
- -------------------------
- -- Need_Dispatch_Table --
- -------------------------
-
- function Need_Dispatch_Table is new
- Traverse_Func (Is_Dispatching_Call_Or_Aggregate);
- -- Return Abandon if the input expression requires access to
- -- Typ's dispatch table.
-
- Decl : constant Node_Id :=
- (if No (E) then E else Original_Node (Unit_Declaration_Node (E)));
-
- -- Start of processing for Should_Freeze_Type
-
- begin
- return Within_Scope (Typ, Current_Scope)
- or else (Nkind (N) = N_Subprogram_Renaming_Declaration
- and then Present (Corresponding_Formal_Spec (N)))
- or else (Present (Decl)
- and then Nkind (Decl) = N_Expression_Function
- and then Need_Dispatch_Table (Expression (Decl)) = Abandon);
- end Should_Freeze_Type;
-
procedure Process_Default_Expressions
(E : Entity_Id;
After : in out Node_Id);
-- attribute definition clause occurs, then these two flags are reset in
-- any case, so call will have no effect.
+ function Should_Freeze_Type
+ (Typ : Entity_Id;
+ E : Entity_Id;
+ N : Node_Id) return Boolean;
+ -- True if Typ should be frozen when the profile of E is being frozen at N.
+
+ -- ??? Expression functions that are not completions shouldn't freeze types
+ -- but our current expansion and freezing model requires an early freezing
+ -- when the tag of Typ is needed or for an aggregate with a subtype of Typ,
+ -- so we return True in these cases.
+
procedure Undelay_Type (T : Entity_Id);
-- T is a type of a component that we know to be an Itype. We don't want
-- this to have a Freeze_Node, so ensure it doesn't. Do the same for any
end if;
end Set_SSO_From_Default;
+ ------------------------
+ -- Should_Freeze_Type --
+ ------------------------
+
+ function Should_Freeze_Type
+ (Typ : Entity_Id;
+ E : Entity_Id;
+ N : Node_Id) return Boolean
+ is
+ Decl : constant Node_Id := Original_Node (Unit_Declaration_Node (E));
+
+ function Is_Dispatching_Call_Or_Tagged_Result_Or_Aggregate
+ (N : Node_Id) return Traverse_Result;
+ -- Return Abandon if N is a dispatching call to a subprogram
+ -- declared in the same scope as Typ, or a tagged result that
+ -- needs specific expansion, or an aggregate whose type is Typ.
+
+ function Check_Freezing is new
+ Traverse_Func (Is_Dispatching_Call_Or_Tagged_Result_Or_Aggregate);
+ -- Return Abandon if the input expression requires freezing Typ
+
+ function Within_Simple_Return_Statement (N : Node_Id) return Boolean;
+ -- Determine whether N is the expression of a simple return statement,
+ -- or the dependent expression of a conditional expression which is
+ -- the expression of a simple return statement, including recursively.
+
+ -------------------------------------------------------
+ -- Is_Dispatching_Call_Or_Tagged_Result_Or_Aggregate --
+ -------------------------------------------------------
+
+ function Is_Dispatching_Call_Or_Tagged_Result_Or_Aggregate
+ (N : Node_Id) return Traverse_Result
+ is
+ begin
+ if Nkind (N) = N_Function_Call
+ and then Present (Controlling_Argument (N))
+ and then Scope (Entity (Original_Node (Name (N)))) = Scope (Typ)
+ then
+ return Abandon;
+
+ -- The expansion done in Expand_Simple_Function_Return will assign
+ -- the tag to the result in this case.
+
+ elsif Is_Conversion_Or_Reference_To_Formal (N)
+ and then Within_Simple_Return_Statement (N)
+ and then Etype (N) = Typ
+ and then Is_Tagged_Type (Typ)
+ and then not Is_Class_Wide_Type (Typ)
+ then
+ return Abandon;
+
+ elsif Nkind (N) in N_Aggregate
+ | N_Delta_Aggregate
+ | N_Extension_Aggregate
+ and then Base_Type (Etype (N)) = Base_Type (Typ)
+ then
+ return Abandon;
+
+ else
+ return OK;
+ end if;
+ end Is_Dispatching_Call_Or_Tagged_Result_Or_Aggregate;
+
+ ------------------------------------
+ -- Within_Simple_Return_Statement --
+ ------------------------------------
+
+ function Within_Simple_Return_Statement (N : Node_Id) return Boolean is
+ Par : constant Node_Id := Parent (N);
+
+ begin
+ if Nkind (Par) = N_Simple_Return_Statement then
+ return True;
+
+ elsif Nkind (Par) = N_Case_Expression_Alternative then
+ return Within_Simple_Return_Statement (Parent (Par));
+
+ elsif Nkind (Par) = N_If_Expression
+ and then N /= First (Expressions (Par))
+ then
+ return Within_Simple_Return_Statement (Par);
+
+ else
+ return False;
+ end if;
+ end Within_Simple_Return_Statement;
+
+ -- Start of processing for Should_Freeze_Type
+
+ begin
+ return Within_Scope (Typ, Current_Scope)
+ or else (Nkind (N) = N_Subprogram_Renaming_Declaration
+ and then Present (Corresponding_Formal_Spec (N)))
+ or else (Present (Decl)
+ and then Nkind (Decl) = N_Expression_Function
+ and then Check_Freezing (Expression (Decl)) = Abandon);
+ end Should_Freeze_Type;
+
------------------
-- Undelay_Type --
------------------