-- --
-- B o d y --
-- --
--- Copyright (C) 1992-2007, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2008, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
with Einfo; use Einfo;
with Elists; use Elists;
with Errout; use Errout;
+with Exp_Ch3; use Exp_Ch3;
with Exp_Ch7; use Exp_Ch7;
+with Exp_Disp; use Exp_Disp;
with Exp_Pakd; use Exp_Pakd;
with Exp_Util; use Exp_Util;
with Exp_Tss; use Exp_Tss;
-- setting of Debug_Info_Needed for the entity. This flag is set if
-- the entity comes from source, or if we are in Debug_Generated_Code
-- mode or if the -gnatdV debug flag is set. However, it never sets
- -- the flag if Debug_Info_Off is set.
-
- procedure Set_Debug_Info_Needed (T : Entity_Id);
- -- Sets the Debug_Info_Needed flag on entity T if not already set, and
- -- also on any entities that are needed by T (for an object, the type
- -- of the object is needed, and for a type, the subsidiary types are
- -- needed -- see body for details). Never has any effect on T if the
- -- Debug_Info_Off flag is set.
+ -- the flag if Debug_Info_Off is set. This procedure also ensures that
+ -- subsidiary entities have the flag set as required.
procedure Undelay_Type (T : Entity_Id);
-- T is a type of a component that we know to be an Itype.
O_Formal : Entity_Id;
Param_Spec : Node_Id;
+ Pref : Node_Id := Empty;
+ -- If the renamed entity is a primitive operation given in prefix form,
+ -- the prefix is the target object and it has to be added as the first
+ -- actual in the generated call.
+
begin
- -- Determine the entity being renamed, which is the target of the
- -- call statement. If the name is an explicit dereference, this is
- -- a renaming of a subprogram type rather than a subprogram. The
- -- name itself is fully analyzed.
+ -- Determine the entity being renamed, which is the target of the call
+ -- statement. If the name is an explicit dereference, this is a renaming
+ -- of a subprogram type rather than a subprogram. The name itself is
+ -- fully analyzed.
if Nkind (Nam) = N_Selected_Component then
Old_S := Entity (Selector_Name (Nam));
if Is_Entity_Name (Nam) then
- -- If the renamed entity is a predefined operator, retain full
- -- name to ensure its visibility.
+ -- If the renamed entity is a predefined operator, retain full name
+ -- to ensure its visibility.
if Ekind (Old_S) = E_Operator
and then Nkind (Nam) = N_Expanded_Name
end if;
else
- Call_Name := New_Copy (Name (N));
+ if Nkind (Nam) = N_Selected_Component
+ and then Present (First_Formal (Old_S))
+ and then
+ (Is_Controlling_Formal (First_Formal (Old_S))
+ or else Is_Class_Wide_Type (Etype (First_Formal (Old_S))))
+ then
+
+ -- Retrieve the target object, to be added as a first actual
+ -- in the call.
+
+ Call_Name := New_Occurrence_Of (Old_S, Loc);
+ Pref := Prefix (Nam);
+
+ else
+ Call_Name := New_Copy (Name (N));
+ end if;
-- The original name may have been overloaded, but
-- is fully resolved now.
Set_Is_Overloaded (Call_Name, False);
end if;
- -- For simple renamings, subsequent calls can be expanded directly
- -- as called to the renamed entity. The body must be generated in
- -- any case for calls they may appear elsewhere.
+ -- For simple renamings, subsequent calls can be expanded directly as
+ -- called to the renamed entity. The body must be generated in any case
+ -- for calls they may appear elsewhere.
if (Ekind (Old_S) = E_Function
or else Ekind (Old_S) = E_Procedure)
Formal := First_Formal (Defining_Entity (Decl));
- if Present (Formal) then
+ if Present (Pref) then
+ declare
+ Pref_Type : constant Entity_Id := Etype (Pref);
+ Form_Type : constant Entity_Id := Etype (First_Formal (Old_S));
+
+ begin
+
+ -- The controlling formal may be an access parameter, or the
+ -- actual may be an access value, so adjust accordingly.
+
+ if Is_Access_Type (Pref_Type)
+ and then not Is_Access_Type (Form_Type)
+ then
+ Actuals := New_List
+ (Make_Explicit_Dereference (Loc, Relocate_Node (Pref)));
+
+ elsif Is_Access_Type (Form_Type)
+ and then not Is_Access_Type (Pref)
+ then
+ Actuals := New_List
+ (Make_Attribute_Reference (Loc,
+ Attribute_Name => Name_Access,
+ Prefix => Relocate_Node (Pref)));
+ else
+ Actuals := New_List (Pref);
+ end if;
+ end;
+
+ elsif Present (Formal) then
Actuals := New_List;
+ else
+ Actuals := No_List;
+ end if;
+
+ if Present (Formal) then
while Present (Formal) loop
Append (New_Reference_To (Formal, Loc), Actuals);
Next_Formal (Formal);
end loop;
end if;
- -- If the renamed entity is an entry, inherit its profile. For
- -- other renamings as bodies, both profiles must be subtype
- -- conformant, so it is not necessary to replace the profile given
- -- in the declaration. However, default values that are aggregates
- -- are rewritten when partially analyzed, so we recover the original
- -- aggregate to insure that subsequent conformity checking works.
- -- Similarly, if the default expression was constant-folded, recover
- -- the original expression.
+ -- If the renamed entity is an entry, inherit its profile. For other
+ -- renamings as bodies, both profiles must be subtype conformant, so it
+ -- is not necessary to replace the profile given in the declaration.
+ -- However, default values that are aggregates are rewritten when
+ -- partially analyzed, so we recover the original aggregate to insure
+ -- that subsequent conformity checking works. Similarly, if the default
+ -- expression was constant-folded, recover the original expression.
Formal := First_Formal (Defining_Entity (Decl));
end if;
-- Link the body to the entity whose declaration it completes. If
- -- the body is analyzed when the renamed entity is frozen, it may be
- -- necessary to restore the proper scope (see package Exp_Ch13).
+ -- the body is analyzed when the renamed entity is frozen, it may
+ -- be necessary to restore the proper scope (see package Exp_Ch13).
if Nkind (N) = N_Subprogram_Renaming_Declaration
and then Present (Corresponding_Spec (N))
if Present (Addr) then
Expr := Expression (Addr);
- -- If we have no initialization of any kind, then we don't
- -- need to place any restrictions on the address clause, because
- -- the object will be elaborated after the address clause is
- -- evaluated. This happens if the declaration has no initial
- -- expression, or the type has no implicit initialization, or
- -- the object is imported.
+ -- If we have no initialization of any kind, then we don't need to
+ -- place any restrictions on the address clause, because the object
+ -- will be elaborated after the address clause is evaluated. This
+ -- happens if the declaration has no initial expression, or the type
+ -- has no implicit initialization, or the object is imported.
- -- The same holds for all initialized scalar types and all
- -- access types. Packed bit arrays of size up to 64 are
- -- represented using a modular type with an initialization
- -- (to zero) and can be processed like other initialized
- -- scalar types.
+ -- The same holds for all initialized scalar types and all access
+ -- types. Packed bit arrays of size up to 64 are represented using a
+ -- modular type with an initialization (to zero) and can be processed
+ -- like other initialized scalar types.
-- If the type is controlled, code to attach the object to a
-- finalization chain is generated at the point of declaration,
then
null;
- -- Otherwise, we require the address clause to be constant
- -- because the call to the initialization procedure (or the
- -- attach code) has to happen at the point of the declaration.
+ -- Otherwise, we require the address clause to be constant because
+ -- the call to the initialization procedure (or the attach code) has
+ -- to happen at the point of the declaration.
else
Check_Constant_Address_Clause (Expr, E);
if Size_Known_At_Compile_Time (T) then
return True;
+ -- Always True for scalar types. This is true even for generic formal
+ -- scalar types. We used to return False in the latter case, but the
+ -- size is known at compile time, even in the template, we just do
+ -- not know the exact size but that's not the point of this routine.
+
elsif Is_Scalar_Type (T)
or else Is_Task_Type (T)
then
- return not Is_Generic_Type (T);
+ return True;
+
+ -- Array types
elsif Is_Array_Type (T) then
+
+ -- String literals always have known size, and we can set it
+
if Ekind (T) = E_String_Literal_Subtype then
Set_Small_Size (T, Component_Size (T)
* String_Literal_Length (T));
return True;
+ -- Unconstrained types never have known at compile time size
+
elsif not Is_Constrained (T) then
return False;
- -- Don't do any recursion on type with error posted, since
- -- we may have a malformed type that leads us into a loop
+ -- Don't do any recursion on type with error posted, since we may
+ -- have a malformed type that leads us into a loop.
elsif Error_Posted (T) then
return False;
+ -- Otherwise if component size unknown, then array size unknown
+
elsif not Size_Known (Component_Type (T)) then
return False;
end if;
- -- Check for all indexes static, and also compute possible
- -- size (in case it is less than 32 and may be packable).
+ -- Check for all indexes static, and also compute possible size
+ -- (in case it is less than 32 and may be packable).
declare
Esiz : Uint := Component_Size (T);
return True;
end;
+ -- Access types always have known at compile time sizes
+
elsif Is_Access_Type (T) then
return True;
+ -- For non-generic private types, go to underlying type if present
+
elsif Is_Private_Type (T)
and then not Is_Generic_Type (T)
and then Present (Underlying_Type (T))
then
- -- Don't do any recursion on type with error posted, since
- -- we may have a malformed type that leads us into a loop
+ -- Don't do any recursion on type with error posted, since we may
+ -- have a malformed type that leads us into a loop.
if Error_Posted (T) then
return False;
return Size_Known (Underlying_Type (T));
end if;
+ -- Record types
+
elsif Is_Record_Type (T) then
-- A class-wide type is never considered to have a known size
then
return False;
- -- Don't do any recursion on type with error posted, since
- -- we may have a malformed type that leads us into a loop
+ -- Don't do any recursion on type with error posted, since we may
+ -- have a malformed type that leads us into a loop.
elsif Error_Posted (T) then
return False;
-- Now look at the components of the record
declare
- -- The following two variables are used to keep track of
- -- the size of packed records if we can tell the size of
- -- the packed record in the front end. Packed_Size_Known
- -- is True if so far we can figure out the size. It is
- -- initialized to True for a packed record, unless the
- -- record has discriminants. The reason we eliminate the
- -- discriminated case is that we don't know the way the
- -- back end lays out discriminated packed records. If
- -- Packed_Size_Known is True, then Packed_Size is the
- -- size in bits so far.
+ -- The following two variables are used to keep track of the
+ -- size of packed records if we can tell the size of the packed
+ -- record in the front end. Packed_Size_Known is True if so far
+ -- we can figure out the size. It is initialized to True for a
+ -- packed record, unless the record has discriminants. The
+ -- reason we eliminate the discriminated case is that we don't
+ -- know the way the back end lays out discriminated packed
+ -- records. If Packed_Size_Known is True, then Packed_Size is
+ -- the size in bits so far.
Packed_Size_Known : Boolean :=
Is_Packed (T)
-- discriminant.
-- This is because gigi computes the size by doing a
- -- substituation of the appropriate discriminant value in
+ -- substitution of the appropriate discriminant value in
-- the size expression for the base type, and gigi is not
-- clever enough to evaluate the resulting expression (which
-- involves a call to rep_to_pos) at compile time.
end;
end if;
- -- Clearly size of record is not known if the size of
- -- one of the components is not known.
+ -- Clearly size of record is not known if the size of one of
+ -- the components is not known.
if not Size_Known (Ctyp) then
return False;
return True;
end;
+ -- All other cases, size not known at compile time
+
else
return False;
end if;
procedure Check_Debug_Info_Needed (T : Entity_Id) is
begin
- if Needs_Debug_Info (T) or else Debug_Info_Off (T) then
+ if Debug_Info_Off (T) then
return;
elsif Comes_From_Source (T)
or else Debug_Generated_Code
or else Debug_Flag_VV
+ or else Needs_Debug_Info (T)
then
Set_Debug_Info_Needed (T);
end if;
New_N :=
Make_Object_Declaration (Loc,
Defining_Identifier => Temp,
- Object_definition => New_Occurrence_Of (Typ, Loc),
- Expression => Relocate_Node (E));
+ Object_Definition => New_Occurrence_Of (Typ, Loc),
+ Expression => Relocate_Node (E));
Insert_Before (Parent (E), New_N);
Analyze (New_N);
Set_Expression (Parent (E), New_Occurrence_Of (Temp, Loc));
- -- To prevent the temporary from being constant-folded (which
- -- would lead to the same piecemeal assignment on the original
- -- target) indicate to the back-end that the temporary is a
- -- variable with real storage. See description of this flag
- -- in Einfo, and the notes on N_Assignment_Statement and
- -- N_Object_Declaration in Sinfo.
+ -- To prevent the temporary from being constant-folded (which would
+ -- lead to the same piecemeal assignment on the original target)
+ -- indicate to the back-end that the temporary is a variable with
+ -- real storage. See description of this flag in Einfo, and the notes
+ -- on N_Assignment_Statement and N_Object_Declaration in Sinfo.
Set_Is_True_Constant (Temp, False);
end if;
Decl : Node_Id;
procedure Freeze_All_Ent (From : Entity_Id; After : in out Node_Id);
- -- This is the internal recursive routine that does freezing of
- -- entities (but NOT the analysis of default expressions, which
- -- should not be recursive, we don't want to analyze those till
- -- we are sure that ALL the types are frozen).
+ -- This is the internal recursive routine that does freezing of entities
+ -- (but NOT the analysis of default expressions, which should not be
+ -- recursive, we don't want to analyze those till we are sure that ALL
+ -- the types are frozen).
--------------------
-- Freeze_All_Ent --
Lastn : Node_Id;
procedure Process_Flist;
- -- If freeze nodes are present, insert and analyze, and reset
- -- cursor for next insertion.
+ -- If freeze nodes are present, insert and analyze, and reset cursor
+ -- for next insertion.
-------------------
-- Process_Flist --
while Present (E) loop
-- If the entity is an inner package which is not a package
- -- renaming, then its entities must be frozen at this point.
- -- Note that such entities do NOT get frozen at the end of
- -- the nested package itself (only library packages freeze).
+ -- renaming, then its entities must be frozen at this point. Note
+ -- that such entities do NOT get frozen at the end of the nested
+ -- package itself (only library packages freeze).
-- Same is true for task declarations, where anonymous records
-- created for entry parameters must be frozen.
End_Scope;
-- For a derived tagged type, we must ensure that all the
- -- primitive operations of the parent have been frozen, so
- -- that their addresses will be in the parent's dispatch table
- -- at the point it is inherited.
+ -- primitive operations of the parent have been frozen, so that
+ -- their addresses will be in the parent's dispatch table at the
+ -- point it is inherited.
elsif Ekind (E) = E_Record_Type
and then Is_Tagged_Type (E)
Process_Flist;
end if;
- -- If an incomplete type is still not frozen, this may be
- -- a premature freezing because of a body declaration that
- -- follows. Indicate where the freezing took place.
+ -- If an incomplete type is still not frozen, this may be a
+ -- premature freezing because of a body declaration that follows.
+ -- Indicate where the freezing took place.
- -- If the freezing is caused by the end of the current
- -- declarative part, it is a Taft Amendment type, and there
- -- is no error.
+ -- If the freezing is caused by the end of the current declarative
+ -- part, it is a Taft Amendment type, and there is no error.
if not Is_Frozen (E)
and then Ekind (E) = E_Incomplete_Type
-- We also add finalization chains to access types whose designated
-- types are controlled. This is normally done when freezing the type,
-- but this misses recursive type definitions where the later members
- -- of the recursion introduce controlled components (e.g. 5624-001).
+ -- of the recursion introduce controlled components.
-- Loop through entities
procedure Check_Current_Instance (Comp_Decl : Node_Id) is
+ Rec_Type : constant Entity_Id :=
+ Scope (Defining_Identifier (Comp_Decl));
+
+ Decl : constant Node_Id := Parent (Rec_Type);
+
function Process (N : Node_Id) return Traverse_Result;
-- Process routine to apply check to given node
begin
case Nkind (N) is
when N_Attribute_Reference =>
- if (Attribute_Name (N) = Name_Access
+ if (Attribute_Name (N) = Name_Access
or else
Attribute_Name (N) = Name_Unchecked_Access)
and then Is_Entity_Name (Prefix (N))
-- Start of processing for Check_Current_Instance
begin
- Traverse (Comp_Decl);
+ -- In Ada95, the (imprecise) rule is that the current instance of a
+ -- limited type is aliased. In Ada2005, limitedness must be explicit:
+ -- either a tagged type, or a limited record.
+
+ if Is_Limited_Type (Rec_Type)
+ and then
+ (Ada_Version < Ada_05
+ or else Is_Tagged_Type (Rec_Type))
+ then
+ return;
+
+ elsif Nkind (Decl) = N_Full_Type_Declaration
+ and then Limited_Present (Type_Definition (Decl))
+ then
+ return;
+
+ else
+ Traverse (Comp_Decl);
+ end if;
end Check_Current_Instance;
------------------------
procedure Freeze_Record_Type (Rec : Entity_Id) is
Comp : Entity_Id;
IR : Node_Id;
- Junk : Boolean;
ADC : Node_Id;
Prev : Entity_Id;
+ Junk : Boolean;
+ pragma Warnings (Off, Junk);
+
Unplaced_Component : Boolean := False;
-- Set True if we find at least one component with no component
-- clause (used to warn about useless Pack pragmas).
Inner : Node_Id;
begin
Inner := N;
-
loop
if Nkind (Inner) = N_Allocator then
return Inner;
-
elsif Nkind (Inner) = N_Qualified_Expression then
Inner := Expression (Inner);
-
else
return Empty;
end if;
then
declare
Will_Be_Frozen : Boolean := False;
- S : Entity_Id := Scope (Rec);
+ S : Entity_Id;
begin
-- We have a pretty bad kludge here. Suppose Rec is subtype
-- do, then mark that Comp'Base will actually be frozen. If
-- so, we merely undelay it.
+ S := Scope (Rec);
while Present (S) loop
if Is_Subprogram (S) then
Will_Be_Frozen := True;
end if;
end;
- -- If the component is an access type with an allocator as
- -- default value, the designated type will be frozen by the
- -- corresponding expression in init_proc. In order to place the
- -- freeze node for the designated type before that for the
- -- current record type, freeze it now.
+ -- If the component is an access type with an allocator as default
+ -- value, the designated type will be frozen by the corresponding
+ -- expression in init_proc. In order to place the freeze node for
+ -- the designated type before that for the current record type,
+ -- freeze it now.
-- Same process if the component is an array of access types,
-- initialized with an aggregate. If the designated type is
- -- private, it cannot contain allocators, and it is premature to
- -- freeze the type, so we check for this as well.
+ -- private, it cannot contain allocators, and it is premature
+ -- to freeze the type, so we check for this as well.
elsif Is_Access_Type (Etype (Comp))
and then Present (Parent (Comp))
Error_Msg_N
("\?since no component clauses were specified", ADC);
- -- Here is where we do Ada 2005 processing for bit order (the
- -- Ada 95 case was already taken care of above).
+ -- Here is where we do Ada 2005 processing for bit order (the Ada
+ -- 95 case was already taken care of above).
elsif Ada_Version >= Ada_05 then
Adjust_Record_For_Reverse_Bit_Order (Rec);
end if;
end if;
+ -- Set OK_To_Reorder_Components depending on debug flags
+
+ if Rec = Base_Type (Rec)
+ and then Convention (Rec) = Convention_Ada
+ then
+ if (Has_Discriminants (Rec) and then Debug_Flag_Dot_V)
+ or else
+ (not Has_Discriminants (Rec) and then Debug_Flag_Dot_R)
+ then
+ Set_OK_To_Reorder_Components (Rec);
+ end if;
+ end if;
+
-- Check for useless pragma Pack when all components placed. We only
-- do this check for record types, not subtypes, since a subtype may
-- have all its components placed, and it still makes perfectly good
- -- sense to pack other subtypes or the parent type.
+ -- sense to pack other subtypes or the parent type. We do not give
+ -- this warning if Optimize_Alignment is set to Space, since the
+ -- pragma Pack does have an effect in this case (it always resets
+ -- the alignment to one).
if Ekind (Rec) = E_Record_Type
and then Is_Packed (Rec)
and then not Unplaced_Component
+ and then Optimize_Alignment /= 'S'
then
- -- Reset packed status. Probably not necessary, but we do it
- -- so that there is no chance of the back end doing something
- -- strange with this redundant indication of packing.
+ -- Reset packed status. Probably not necessary, but we do it so
+ -- that there is no chance of the back end doing something strange
+ -- with this redundant indication of packing.
Set_Is_Packed (Rec, False);
Set_Has_Unchecked_Union (Rec);
end if;
- if Has_Per_Object_Constraint (Comp)
- and then not Is_Limited_Type (Rec)
- then
+ if Has_Per_Object_Constraint (Comp) then
+
-- Scan component declaration for likely misuses of current
-- instance, either in a constraint or a default expression.
-- Generate warning for applying C or C++ convention to a record
-- with discriminants. This is suppressed for the unchecked union
- -- case, since the whole point in this case is interface C.
+ -- case, since the whole point in this case is interface C. We also
+ -- do not generate this within instantiations, since we will have
+ -- generated a message on the template.
if Has_Discriminants (E)
and then not Is_Unchecked_Union (E)
- and then not Warnings_Off (E)
- and then not Warnings_Off (Base_Type (E))
and then (Convention (E) = Convention_C
or else
Convention (E) = Convention_CPP)
and then Comes_From_Source (E)
+ and then not In_Instance
+ and then not Has_Warnings_Off (E)
+ and then not Has_Warnings_Off (Base_Type (E))
then
declare
Cprag : constant Node_Id := Get_Rep_Pragma (E, Name_Convention);
-- Similarly, an inlined instance body may make reference to global
-- entities, but these references cannot be the proper freezing point
- -- for them, and in the absence of inlining freezing will take place
- -- in their own scope. Normally instance bodies are analyzed after
- -- the enclosing compilation, and everything has been frozen at the
- -- proper place, but with front-end inlining an instance body is
- -- compiled before the end of the enclosing scope, and as a result
- -- out-of-order freezing must be prevented.
+ -- for them, and in the absence of inlining freezing will take place in
+ -- their own scope. Normally instance bodies are analyzed after the
+ -- enclosing compilation, and everything has been frozen at the proper
+ -- place, but with front-end inlining an instance body is compiled
+ -- before the end of the enclosing scope, and as a result out-of-order
+ -- freezing must be prevented.
elsif Front_End_Inlining
and then In_Instance_Body
if not Is_Internal (E) then
declare
F_Type : Entity_Id;
+ R_Type : Entity_Id;
Warn_Node : Node_Id;
- function Is_Fat_C_Ptr_Type (T : Entity_Id) return Boolean;
- -- Determines if given type entity is a fat pointer type
- -- used as an argument type or return type to a subprogram
- -- with C or C++ convention set.
-
- --------------------------
- -- Is_Fat_C_Access_Type --
- --------------------------
-
- function Is_Fat_C_Ptr_Type (T : Entity_Id) return Boolean is
- begin
- return (Convention (E) = Convention_C
- or else
- Convention (E) = Convention_CPP)
- and then Is_Access_Type (T)
- and then Esize (T) > Ttypes.System_Address_Size;
- end Is_Fat_C_Ptr_Type;
-
begin
-- Loop through formals
end if;
end if;
- -- Check bad use of fat C pointer
+ -- Check suspicious parameter for C function. These tests
+ -- apply only to exported/imported subprograms.
- if Warn_On_Export_Import and then
- Is_Fat_C_Ptr_Type (F_Type)
+ if Warn_On_Export_Import
+ and then Comes_From_Source (E)
+ and then (Convention (E) = Convention_C
+ or else
+ Convention (E) = Convention_CPP)
+ and then (Is_Imported (E) or else Is_Exported (E))
+ and then Convention (E) /= Convention (Formal)
+ and then not Has_Warnings_Off (E)
+ and then not Has_Warnings_Off (F_Type)
+ and then not Has_Warnings_Off (Formal)
then
Error_Msg_Qual_Level := 1;
- Error_Msg_N
- ("?type of & does not correspond to C pointer",
- Formal);
+
+ -- Check suspicious use of fat C pointer
+
+ if Is_Access_Type (F_Type)
+ and then Esize (F_Type) > Ttypes.System_Address_Size
+ then
+ Error_Msg_N
+ ("?type of & does not correspond "
+ & "to C pointer!", Formal);
+
+ -- Check suspicious return of boolean
+
+ elsif Root_Type (F_Type) = Standard_Boolean
+ and then Convention (F_Type) = Convention_Ada
+ then
+ Error_Msg_N
+ ("?& is an 8-bit Ada Boolean, "
+ & "use char in C!", Formal);
+
+ -- Check suspicious tagged type
+
+ elsif (Is_Tagged_Type (F_Type)
+ or else (Is_Access_Type (F_Type)
+ and then
+ Is_Tagged_Type
+ (Designated_Type (F_Type))))
+ and then Convention (E) = Convention_C
+ then
+ Error_Msg_N
+ ("?& is a tagged type which does not "
+ & "correspond to any C type!", Formal);
+
+ -- Check wrong convention subprogram pointer
+
+ elsif Ekind (F_Type) = E_Access_Subprogram_Type
+ and then not Has_Foreign_Convention (F_Type)
+ then
+ Error_Msg_N
+ ("?subprogram pointer & should "
+ & "have foreign convention!", Formal);
+ Error_Msg_Sloc := Sloc (F_Type);
+ Error_Msg_NE
+ ("\?add Convention pragma to declaration of &#",
+ Formal, F_Type);
+ end if;
+
Error_Msg_Qual_Level := 0;
end if;
-- Check for unconstrained array in exported foreign
-- convention case.
- if Convention (E) in Foreign_Convention
+ if Has_Foreign_Convention (E)
and then not Is_Imported (E)
and then Is_Array_Type (F_Type)
and then not Is_Constrained (F_Type)
Next_Formal (Formal);
end loop;
- -- Check return type
+ -- Case of function
if Ekind (E) = E_Function then
- Freeze_And_Append (Etype (E), Loc, Result);
+
+ -- Freeze return type
+
+ R_Type := Etype (E);
+ Freeze_And_Append (R_Type, Loc, Result);
+
+ -- Check suspicious return type for C function
if Warn_On_Export_Import
- and then Is_Fat_C_Ptr_Type (Etype (E))
+ and then (Convention (E) = Convention_C
+ or else
+ Convention (E) = Convention_CPP)
+ and then (Is_Imported (E) or else Is_Exported (E))
then
- Error_Msg_N
- ("?return type of& does not correspond to C pointer",
- E);
+ -- Check suspicious return of fat C pointer
+
+ if Is_Access_Type (R_Type)
+ and then Esize (R_Type) > Ttypes.System_Address_Size
+ and then not Has_Warnings_Off (E)
+ and then not Has_Warnings_Off (R_Type)
+ then
+ Error_Msg_N
+ ("?return type of& does not "
+ & "correspond to C pointer!", E);
+
+ -- Check suspicious return of boolean
+
+ elsif Root_Type (R_Type) = Standard_Boolean
+ and then Convention (R_Type) = Convention_Ada
+ and then not Has_Warnings_Off (E)
+ and then not Has_Warnings_Off (R_Type)
+ then
+ Error_Msg_N
+ ("?return type of & is an 8-bit "
+ & "Ada Boolean, use char in C!", E);
+
+ -- Check suspicious return tagged type
+
+ elsif (Is_Tagged_Type (R_Type)
+ or else (Is_Access_Type (R_Type)
+ and then
+ Is_Tagged_Type
+ (Designated_Type (R_Type))))
+ and then Convention (E) = Convention_C
+ and then not Has_Warnings_Off (E)
+ and then not Has_Warnings_Off (R_Type)
+ then
+ Error_Msg_N
+ ("?return type of & does not "
+ & "correspond to C type!", E);
+
+ -- Check return of wrong convention subprogram pointer
- elsif Is_Array_Type (Etype (E))
+ elsif Ekind (R_Type) = E_Access_Subprogram_Type
+ and then not Has_Foreign_Convention (R_Type)
+ and then not Has_Warnings_Off (E)
+ and then not Has_Warnings_Off (R_Type)
+ then
+ Error_Msg_N
+ ("?& should return a foreign "
+ & "convention subprogram pointer", E);
+ Error_Msg_Sloc := Sloc (R_Type);
+ Error_Msg_NE
+ ("\?add Convention pragma to declaration of& #",
+ E, R_Type);
+ end if;
+ end if;
+
+ if Is_Array_Type (Etype (E))
and then not Is_Constrained (Etype (E))
and then not Is_Imported (E)
- and then Convention (E) in Foreign_Convention
+ and then Has_Foreign_Convention (E)
and then Warn_On_Export_Import
+ and then not Has_Warnings_Off (E)
+ and then not Has_Warnings_Off (Etype (E))
then
Error_Msg_N
("?foreign convention function& should not " &
- "return unconstrained array", E);
+ "return unconstrained array!", E);
-- Ada 2005 (AI-326): Check wrong use of tagged
-- incomplete type
Validate_Object_Declaration (Declaration_Node (E));
- -- If there is an address clause, check it is valid
+ -- If there is an address clause, check that it is valid
Check_Address_Clause (E);
- -- For imported objects, set Is_Public unless there is also
- -- an address clause, which means that there is no external
- -- symbol needed for the Import (Is_Public may still be set
- -- for other unrelated reasons). Note that we delayed this
- -- processing till freeze time so that we can be sure not
- -- to set the flag if there is an address clause. If there
- -- is such a clause, then the only purpose of the Import
- -- pragma is to suppress implicit initialization.
+ -- If the object needs any kind of default initialization, an
+ -- error must be issued if No_Default_Initialization applies.
+ -- The check doesn't apply to imported objects, which are not
+ -- ever default initialized, and is why the check is deferred
+ -- until freezing, at which point we know if Import applies.
+
+ if not Is_Imported (E)
+ and then not Has_Init_Expression (Declaration_Node (E))
+ and then
+ ((Has_Non_Null_Base_Init_Proc (Etype (E))
+ and then not No_Initialization (Declaration_Node (E))
+ and then not Is_Value_Type (Etype (E))
+ and then not Suppress_Init_Proc (Etype (E)))
+ or else
+ (Needs_Simple_Initialization (Etype (E))
+ and then not Is_Internal (E)))
+ then
+ Check_Restriction
+ (No_Default_Initialization, Declaration_Node (E));
+ end if;
+
+ -- For imported objects, set Is_Public unless there is also an
+ -- address clause, which means that there is no external symbol
+ -- needed for the Import (Is_Public may still be set for other
+ -- unrelated reasons). Note that we delayed this processing
+ -- till freeze time so that we can be sure not to set the flag
+ -- if there is an address clause. If there is such a clause,
+ -- then the only purpose of the Import pragma is to suppress
+ -- implicit initialization.
if Is_Imported (E)
and then No (Address_Clause (E))
then
Error_Msg_N
("stand alone atomic constant must be " &
- "imported ('R'M C.6(13))", E);
+ "imported (RM C.6(13))", E);
elsif Has_Rep_Pragma (E, Name_Volatile)
or else
-- Case of a type or subtype being frozen
else
- -- Check preelaborable initialization for full type completing a
- -- private type for which pragma Preelaborable_Initialization given.
-
- if Must_Have_Preelab_Init (E)
- and then not Has_Preelaborable_Initialization (E)
- then
- Error_Msg_N
- ("full view of & does not have preelaborable initialization", E);
- end if;
+ -- We used to check here that a full type must have preelaborable
+ -- initialization if it completes a private type specified with
+ -- pragma Preelaborable_Intialization, but that missed cases where
+ -- the types occur within a generic package, since the freezing
+ -- that occurs within a containing scope generally skips traversal
+ -- of a generic unit's declarations (those will be frozen within
+ -- instances). This check was moved to Analyze_Package_Specification.
-- The type may be defined in a generic unit. This can occur when
-- freezing a generic function that returns the type (which is
end;
end if;
- -- If ancestor subtype present, freeze that first.
- -- Note that this will also get the base type frozen.
+ -- If ancestor subtype present, freeze that first. Note that this
+ -- will also get the base type frozen.
Atype := Ancestor_Subtype (E);
if Present (Atype) then
Freeze_And_Append (Atype, Loc, Result);
- -- Otherwise freeze the base type of the entity before
- -- freezing the entity itself (RM 13.14(15)).
+ -- Otherwise freeze the base type of the entity before freezing
+ -- the entity itself (RM 13.14(15)).
elsif E /= Base_Type (E) then
Freeze_And_Append (Base_Type (E), Loc, Result);
-- processing is only done for base types, since all the
-- representation aspects involved are type-related. This
-- is not just an optimization, if we start processing the
- -- subtypes, they intefere with the settings on the base
+ -- subtypes, they interfere with the settings on the base
-- type (this is because Is_Packed has a slightly different
-- meaning before and after freezing).
and then Known_RM_Size (E)
then
declare
+ SizC : constant Node_Id := Size_Clause (E);
+
Discard : Boolean;
- SizC : constant Node_Id := Size_Clause (E);
+ pragma Warnings (Off, Discard);
begin
-- It is not clear if it is possible to have no size
-- Size information of packed array type is copied to the
-- array type, since this is really the representation. But
- -- do not override explicit existing size values.
+ -- do not override explicit existing size values. If the
+ -- ancestor subtype is constrained the packed_array_type
+ -- will be inherited from it, but the size may have been
+ -- provided already, and must not be overridden either.
- if not Has_Size_Clause (E) then
+ if not Has_Size_Clause (E)
+ and then
+ (No (Ancestor_Subtype (E))
+ or else not Has_Size_Clause (Ancestor_Subtype (E)))
+ then
Set_Esize (E, Esize (Packed_Array_Type (E)));
Set_RM_Size (E, RM_Size (Packed_Array_Type (E)));
end if;
end if;
end if;
- -- For non-packed arrays set the alignment of the array
- -- to the alignment of the component type if it is unknown.
- -- Skip this in the atomic case, since atomic arrays may
- -- need larger alignments.
+ -- For non-packed arrays set the alignment of the array to the
+ -- alignment of the component type if it is unknown. Skip this
+ -- in atomic case (atomic arrays may need larger alignments).
if not Is_Packed (E)
and then Unknown_Alignment (E)
end;
end if;
- -- The equivalent type associated with a class-wide subtype
- -- needs to be frozen to ensure that its layout is done.
- -- Class-wide subtypes are currently only frozen on targets
- -- requiring front-end layout (see New_Class_Wide_Subtype
- -- and Make_CW_Equivalent_Type in exp_util.adb).
+ -- The equivalent type associated with a class-wide subtype needs
+ -- to be frozen to ensure that its layout is done. Class-wide
+ -- subtypes are currently only frozen on targets requiring
+ -- front-end layout (see New_Class_Wide_Subtype and
+ -- Make_CW_Equivalent_Type in exp_util.adb).
if Ekind (E) = E_Class_Wide_Subtype
and then Present (Equivalent_Type (E))
end if;
-- For a record (sub)type, freeze all the component types (RM
- -- 13.14(15). We test for E_Record_(sub)Type here, rather than
- -- using Is_Record_Type, because we don't want to attempt the
- -- freeze for the case of a private type with record extension
- -- (we will do that later when the full type is frozen).
+ -- 13.14(15). We test for E_Record_(sub)Type here, rather than using
+ -- Is_Record_Type, because we don't want to attempt the freeze for
+ -- the case of a private type with record extension (we will do that
+ -- later when the full type is frozen).
elsif Ekind (E) = E_Record_Type
or else Ekind (E) = E_Record_Subtype
Freeze_Record_Type (E);
-- For a concurrent type, freeze corresponding record type. This
- -- does not correpond to any specific rule in the RM, but the
+ -- does not correspond to any specific rule in the RM, but the
-- record type is essentially part of the concurrent type.
-- Freeze as well all local entities. This includes record types
-- created for entry parameter blocks, and whatever local entities
Set_Entity (F_Node, E);
else
- -- {Incomplete,Private}_Subtypes
- -- with Full_Views constrained by discriminants
+ -- {Incomplete,Private}_Subtypes with Full_Views
+ -- constrained by discriminants.
Set_Has_Delayed_Freeze (E, False);
Set_Freeze_Node (E, Empty);
Size_Known_At_Compile_Time (Full_View (E)));
-- Size information is copied from the full view to the
- -- incomplete or private view for consistency
+ -- incomplete or private view for consistency.
-- We skip this is the full view is not a type. This is very
-- strange of course, and can only happen as a result of
Freeze_Subprogram (E);
-- Ada 2005 (AI-326): Check wrong use of tag incomplete type
- --
+
-- type T is tagged;
-- type Acc is access function (X : T) return T; -- ERROR
if Is_Pure_Unit_Access_Type (E)
and then (Ada_Version < Ada_05
- or else not No_Pool_Assigned (E))
+ or else not No_Pool_Assigned (E))
then
Error_Msg_N ("named access type not allowed in pure unit", E);
+
+ if Ada_Version >= Ada_05 then
+ Error_Msg_N
+ ("\would be legal if Storage_Size of 0 given?", E);
+
+ elsif No_Pool_Assigned (E) then
+ Error_Msg_N
+ ("\would be legal in Ada 2005?", E);
+
+ else
+ Error_Msg_N
+ ("\would be legal in Ada 2005 if "
+ & "Storage_Size of 0 given?", E);
+ end if;
end if;
end if;
-- AI-117), which will have occurred earlier (in Derive_Subprogram
-- and New_Overloaded_Entity). Here we set the convention of
-- primitives that are still convention Ada, which will ensure
- -- that any new primitives inherit the type's convention.
- -- Class-wide types can have a foreign convention inherited from
- -- their specific type, but are excluded from this since they
- -- don't have any associated primitives.
+ -- that any new primitives inherit the type's convention. Class-
+ -- wide types can have a foreign convention inherited from their
+ -- specific type, but are excluded from this since they don't have
+ -- any associated primitives.
if Is_Tagged_Type (E)
and then not Is_Class_Wide_Type (E)
if Has_Size_Clause (E)
and then not Size_Known_At_Compile_Time (E)
then
- -- Supress this message if errors posted on E, even if we are
+ -- Suppress this message if errors posted on E, even if we are
-- in all errors mode, since this is often a junk message
if not Error_Posted (E) then
procedure Freeze_Enumeration_Type (Typ : Entity_Id) is
begin
+ -- By default, if no size clause is present, an enumeration type with
+ -- Convention C is assumed to interface to a C enum, and has integer
+ -- size. This applies to types. For subtypes, verify that its base
+ -- type has no size clause either.
+
if Has_Foreign_Convention (Typ)
and then not Has_Size_Clause (Typ)
+ and then not Has_Size_Clause (Base_Type (Typ))
and then Esize (Typ) < Standard_Integer_Size
then
Init_Esize (Typ, Standard_Integer_Size);
+
else
+ -- If the enumeration type interfaces to C, and it has a size clause
+ -- that specifies less than int size, it warrants a warning. The
+ -- user may intend the C type to be an enum or a char, so this is
+ -- not by itself an error that the Ada compiler can detect, but it
+ -- it is a worth a heads-up. For Boolean and Character types we
+ -- assume that the programmer has the proper C type in mind.
+
+ if Convention (Typ) = Convention_C
+ and then Has_Size_Clause (Typ)
+ and then Esize (Typ) /= Esize (Standard_Integer)
+ and then not Is_Boolean_Type (Typ)
+ and then not Is_Character_Type (Typ)
+ then
+ Error_Msg_N
+ ("C enum types have the size of a C int?", Size_Clause (Typ));
+ end if;
+
Adjust_Esize_For_Alignment (Typ);
end if;
end Freeze_Enumeration_Type;
-----------------------
procedure Freeze_Expression (N : Node_Id) is
- In_Def_Exp : constant Boolean := In_Default_Expression;
- Typ : Entity_Id;
- Nam : Entity_Id;
- Desig_Typ : Entity_Id;
- P : Node_Id;
- Parent_P : Node_Id;
+ In_Spec_Exp : constant Boolean := In_Spec_Expression;
+ Typ : Entity_Id;
+ Nam : Entity_Id;
+ Desig_Typ : Entity_Id;
+ P : Node_Id;
+ Parent_P : Node_Id;
Freeze_Outside : Boolean := False;
-- This flag is set true if the entity must be frozen outside the
-- make sure that we actually have a real expression (if we have
-- a subtype indication, we can't test Is_Static_Expression!)
- if In_Def_Exp
+ if In_Spec_Exp
and then Nkind (N) in N_Subexpr
and then not Is_Static_Expression (N)
then
-- For either of these cases, we skip the freezing
- if not In_Default_Expression
+ if not In_Spec_Expression
and then Nkind (N) = N_Identifier
and then (Present (Entity (N)))
then
and then Is_Enumeration_Type (Etype (N))
then
-- If enumeration literal appears directly as the choice,
- -- do not freeze (this is the normal non-overloade case)
+ -- do not freeze (this is the normal non-overloaded case)
if Nkind (Parent (N)) = N_Component_Association
and then First (Choices (Parent (N))) = N
-- static type, and the freeze scope needs to be the outer scope, not
-- the scope of the subprogram with the default parameter.
- -- For default expressions in generic units, the Move_Freeze_Nodes
- -- mechanism (see sem_ch12.adb) takes care of placing them at the proper
- -- place, after the generic unit.
+ -- For default expressions and other spec expressions in generic units,
+ -- the Move_Freeze_Nodes mechanism (see sem_ch12.adb) takes care of
+ -- placing them at the proper place, after the generic unit.
- if (In_Def_Exp and not Inside_A_Generic)
+ if (In_Spec_Exp and not Inside_A_Generic)
or else Freeze_Outside
or else (Is_Type (Current_Scope)
and then (not Is_Concurrent_Type (Current_Scope)
end if;
-- Now we have the right place to do the freezing. First, a special
- -- adjustment, if we are in default expression analysis mode, these
- -- freeze actions must not be thrown away (normally all inserted actions
- -- are thrown away in this mode. However, the freeze actions are from
- -- static expressions and one of the important reasons we are doing this
+ -- adjustment, if we are in spec-expression analysis mode, these freeze
+ -- actions must not be thrown away (normally all inserted actions are
+ -- thrown away in this mode. However, the freeze actions are from static
+ -- expressions and one of the important reasons we are doing this
-- special analysis is to get these freeze actions. Therefore we turn
- -- off the In_Default_Expression mode to propagate these freeze actions.
+ -- off the In_Spec_Expression mode to propagate these freeze actions.
-- This also means they get properly analyzed and expanded.
- In_Default_Expression := False;
+ In_Spec_Expression := False;
-- Freeze the designated type of an allocator (RM 13.14(13))
Freeze_Before (P, Nam);
end if;
- In_Default_Expression := In_Def_Exp;
+ -- Restore In_Spec_Expression flag
+
+ In_Spec_Expression := In_Spec_Exp;
end Freeze_Expression;
-----------------------------
-- case of both bounds negative, because the sign will be dealt
-- with anyway. Furthermore we can't just go making such a bound
-- symmetrical, since in a twos-complement system, there is an
- -- extra negative value which could not be accomodated on the
+ -- extra negative value which could not be accommodated on the
-- positive side.
if Typ = Btyp
if UR_Is_Negative (Loval_Incl_EP) then
Loval_Excl_EP := Loval_Incl_EP + Small;
+
+ -- If the value went from negative to zero, then we have the
+ -- case where Loval_Incl_EP is the model number just below
+ -- zero, so we want to stick to the negative value for the
+ -- base type to maintain the condition that the size will
+ -- include signed values.
+
+ if Typ = Btyp
+ and then UR_Is_Zero (Loval_Excl_EP)
+ then
+ Loval_Excl_EP := Loval_Incl_EP;
+ end if;
+
else
Loval_Excl_EP := Loval_Incl_EP;
end if;
-- be inlined. This is consistent with the restriction against using
-- 'Access or 'Address on an Inline_Always subprogram.
- if Is_Dispatching_Operation (E) and then Is_Always_Inlined (E) then
+ if Is_Dispatching_Operation (E)
+ and then Has_Pragma_Inline_Always (E)
+ then
Error_Msg_N
("pragma Inline_Always not allowed for dispatching subprograms", E);
end if;
+
+ -- Because of the implicit representation of inherited predefined
+ -- operators in the front-end, the overriding status of the operation
+ -- may be affected when a full view of a type is analyzed, and this is
+ -- not captured by the analysis of the corresponding type declaration.
+ -- Therefore the correctness of a not-overriding indicator must be
+ -- rechecked when the subprogram is frozen.
+
+ if Nkind (E) = N_Defining_Operator_Symbol
+ and then not Error_Posted (Parent (E))
+ then
+ Check_Overriding_Indicator (E, Empty, Is_Primitive (E));
+ end if;
end Freeze_Subprogram;
----------------------
Next_Formal (Formal);
end loop;
-
end Process_Default_Expressions;
----------------------------------------
end if;
end Set_Component_Alignment_If_Not_Set;
- ---------------------------
- -- Set_Debug_Info_Needed --
- ---------------------------
-
- procedure Set_Debug_Info_Needed (T : Entity_Id) is
- begin
- if No (T)
- or else Needs_Debug_Info (T)
- or else Debug_Info_Off (T)
- then
- return;
- else
- Set_Needs_Debug_Info (T);
- end if;
-
- if Is_Object (T) then
- Set_Debug_Info_Needed (Etype (T));
-
- elsif Is_Type (T) then
- Set_Debug_Info_Needed (Etype (T));
-
- if Is_Record_Type (T) then
- declare
- Ent : Entity_Id := First_Entity (T);
- begin
- while Present (Ent) loop
- Set_Debug_Info_Needed (Ent);
- Next_Entity (Ent);
- end loop;
- end;
-
- elsif Is_Array_Type (T) then
- Set_Debug_Info_Needed (Component_Type (T));
-
- declare
- Indx : Node_Id := First_Index (T);
- begin
- while Present (Indx) loop
- Set_Debug_Info_Needed (Etype (Indx));
- Indx := Next_Index (Indx);
- end loop;
- end;
-
- if Is_Packed (T) then
- Set_Debug_Info_Needed (Packed_Array_Type (T));
- end if;
-
- elsif Is_Access_Type (T) then
- Set_Debug_Info_Needed (Directly_Designated_Type (T));
-
- elsif Is_Private_Type (T) then
- Set_Debug_Info_Needed (Full_View (T));
-
- elsif Is_Protected_Type (T) then
- Set_Debug_Info_Needed (Corresponding_Record_Type (T));
- end if;
- end if;
- end Set_Debug_Info_Needed;
-
------------------
-- Undelay_Type --
------------------
if Present (Decl)
and then Nkind (Decl) = N_Pragma
- and then Chars (Decl) = Name_Import
+ and then Pragma_Name (Decl) = Name_Import
then
return;
end if;