-- --
-- B o d y --
-- --
--- Copyright (C) 1992-2007, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2009, 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 Errout; use Errout;
with Exp_Tss; use Exp_Tss;
with Exp_Util; use Exp_Util;
-with Layout; use Layout;
with Lib; use Lib;
with Lib.Xref; use Lib.Xref;
with Namet; use Namet;
with Rident; use Rident;
with Rtsfind; use Rtsfind;
with Sem; use Sem;
+with Sem_Aux; use Sem_Aux;
+with Sem_Ch3; use Sem_Ch3;
with Sem_Ch8; use Sem_Ch8;
with Sem_Eval; use Sem_Eval;
with Sem_Res; use Sem_Res;
procedure Alignment_Check_For_Esize_Change (Typ : Entity_Id);
-- This routine is called after setting the Esize of type entity Typ.
- -- The purpose is to deal with the situation where an aligment has been
+ -- The purpose is to deal with the situation where an alignment has been
-- inherited from a derived type that is no longer appropriate for the
-- new Esize value. In this case, we reset the Alignment to unknown.
procedure Check_Component_Overlap (C1_Ent, C2_Ent : Entity_Id);
-- Given two entities for record components or discriminants, checks
- -- if they hav overlapping component clauses and issues errors if so.
+ -- if they have overlapping component clauses and issues errors if so.
function Get_Alignment_Value (Expr : Node_Id) return Uint;
-- Given the expression for an alignment value, returns the corresponding
-- Attributes that do not specify a representation characteristic are
-- operational attributes.
- function Address_Aliased_Entity (N : Node_Id) return Entity_Id;
- -- If expression N is of the form E'Address, return E
-
procedure New_Stream_Subprogram
(N : Node_Id;
Ent : Entity_Id;
-- call to Validate_Unchecked_Conversions does the actual error
-- checking and posting of warnings. The reason for this delayed
-- processing is to take advantage of back-annotations of size and
- -- alignment values peformed by the back end.
+ -- alignment values performed by the back end.
+
+ -- Note: the reason we store a Source_Ptr value instead of a Node_Id
+ -- is that by the time Validate_Unchecked_Conversions is called, Sprint
+ -- will already have modified all Sloc values if the -gnatD option is set.
type UC_Entry is record
- Enode : Node_Id; -- node used for posting warnings
- Source : Entity_Id; -- source type for unchecked conversion
- Target : Entity_Id; -- target type for unchecked conversion
+ Eloc : Source_Ptr; -- node used for posting warnings
+ Source : Entity_Id; -- source type for unchecked conversion
+ Target : Entity_Id; -- target type for unchecked conversion
end record;
package Unchecked_Conversions is new Table.Table (
Y : Entity_Id;
-- The entity of the object being overlaid
+
+ Off : Boolean;
+ -- Whether the address is offseted within Y
end record;
package Address_Clause_Checks is new Table.Table (
Table_Increment => 200,
Table_Name => "Address_Clause_Checks");
- ----------------------------
- -- Address_Aliased_Entity --
- ----------------------------
-
- function Address_Aliased_Entity (N : Node_Id) return Entity_Id is
- begin
- if Nkind (N) = N_Attribute_Reference
- and then Attribute_Name (N) = Name_Address
- then
- declare
- Nam : Node_Id := Prefix (N);
- begin
- while False
- or else Nkind (Nam) = N_Selected_Component
- or else Nkind (Nam) = N_Indexed_Component
- loop
- Nam := Prefix (Nam);
- end loop;
-
- if Is_Entity_Name (Nam) then
- return Entity (Nam);
- end if;
- end;
- end if;
-
- return Empty;
- end Address_Aliased_Entity;
-
-----------------------------------------
-- Adjust_Record_For_Reverse_Bit_Order --
-----------------------------------------
Comp := First_Component_Or_Discriminant (R);
while Present (Comp) loop
declare
- CC : constant Node_Id := Component_Clause (Comp);
- Fbit : constant Uint := Static_Integer (First_Bit (CC));
+ CC : constant Node_Id := Component_Clause (Comp);
begin
if Present (CC) then
+ declare
+ Fbit : constant Uint := Static_Integer (First_Bit (CC));
- -- Case of component with size > max machine scalar
-
- if Esize (Comp) > Max_Machine_Scalar_Size then
+ begin
+ -- Case of component with size > max machine scalar
- -- Must begin on byte boundary
+ if Esize (Comp) > Max_Machine_Scalar_Size then
- if Fbit mod SSU /= 0 then
- Error_Msg_N
- ("illegal first bit value for reverse bit order",
- First_Bit (CC));
- Error_Msg_Uint_1 := SSU;
- Error_Msg_Uint_2 := Max_Machine_Scalar_Size;
+ -- Must begin on byte boundary
- Error_Msg_N
- ("\must be a multiple of ^ if size greater than ^",
- First_Bit (CC));
+ if Fbit mod SSU /= 0 then
+ Error_Msg_N
+ ("illegal first bit value for reverse bit order",
+ First_Bit (CC));
+ Error_Msg_Uint_1 := SSU;
+ Error_Msg_Uint_2 := Max_Machine_Scalar_Size;
- -- Must end on byte boundary
+ Error_Msg_N
+ ("\must be a multiple of ^ if size greater than ^",
+ First_Bit (CC));
- elsif Esize (Comp) mod SSU /= 0 then
- Error_Msg_N
- ("illegal last bit value for reverse bit order",
- Last_Bit (CC));
- Error_Msg_Uint_1 := SSU;
- Error_Msg_Uint_2 := Max_Machine_Scalar_Size;
+ -- Must end on byte boundary
- Error_Msg_N
- ("\must be a multiple of ^ if size greater than ^",
- Last_Bit (CC));
+ elsif Esize (Comp) mod SSU /= 0 then
+ Error_Msg_N
+ ("illegal last bit value for reverse bit order",
+ Last_Bit (CC));
+ Error_Msg_Uint_1 := SSU;
+ Error_Msg_Uint_2 := Max_Machine_Scalar_Size;
- -- OK, give warning if enabled
+ Error_Msg_N
+ ("\must be a multiple of ^ if size greater than ^",
+ Last_Bit (CC));
- elsif Warn_On_Reverse_Bit_Order then
- Error_Msg_N
- ("multi-byte field specified with non-standard"
- & " Bit_Order?", CC);
+ -- OK, give warning if enabled
- if Bytes_Big_Endian then
- Error_Msg_N
- ("\bytes are not reversed "
- & "(component is big-endian)?", CC);
- else
+ elsif Warn_On_Reverse_Bit_Order then
Error_Msg_N
- ("\bytes are not reversed "
- & "(component is little-endian)?", CC);
+ ("multi-byte field specified with non-standard"
+ & " Bit_Order?", CC);
+
+ if Bytes_Big_Endian then
+ Error_Msg_N
+ ("\bytes are not reversed "
+ & "(component is big-endian)?", CC);
+ else
+ Error_Msg_N
+ ("\bytes are not reversed "
+ & "(component is little-endian)?", CC);
+ end if;
end if;
- end if;
- -- Case where size is not greater than max machine scalar.
- -- For now, we just count these.
+ -- Case where size is not greater than max machine
+ -- scalar. For now, we just count these.
- else
- Num_CC := Num_CC + 1;
- end if;
+ else
+ Num_CC := Num_CC + 1;
+ end if;
+ end;
end if;
end;
declare
Comps : array (0 .. Num_CC) of Entity_Id;
- -- Array to collect component and discrimninant entities. The data
+ -- Array to collect component and discriminant entities. The data
-- starts at index 1, the 0'th entry is for the sort routine.
function CP_Lt (Op1, Op2 : Natural) return Boolean;
-- 1 .. 4 3 .. 6 1 3
-- 4 .. 7 0 .. 3 4 0
- -- The general rule is that the first bit is is obtained by
+ -- The general rule is that the first bit is obtained by
-- subtracting the old ending bit from machine scalar size - 1.
for C in Start .. Stop loop
if Warn_On_Reverse_Bit_Order then
Error_Msg_Uint_1 := MSS;
Error_Msg_N
- ("?reverse bit order in machine " &
- "scalar of length^", First_Bit (CC));
+ ("info: reverse bit order in machine " &
+ "scalar of length^?", First_Bit (CC));
Error_Msg_Uint_1 := NFB;
Error_Msg_Uint_2 := NLB;
if Bytes_Big_Endian then
Error_Msg_NE
- ("?\big-endian range for component & is ^ .. ^",
+ ("?\info: big-endian range for "
+ & "component & is ^ .. ^",
First_Bit (CC), Comp);
else
Error_Msg_NE
- ("?\little-endian range for component & is ^ .. ^",
+ ("?\info: little-endian range "
+ & "for component & is ^ .. ^",
First_Bit (CC), Comp);
end if;
end if;
-- definition clause that is the preferred approach in Ada 95.
procedure Analyze_At_Clause (N : Node_Id) is
+ CS : constant Boolean := Comes_From_Source (N);
+
begin
+ -- This is an obsolescent feature
+
Check_Restriction (No_Obsolescent_Features, N);
if Warn_On_Obsolescent_Feature then
("\use address attribute definition clause instead?", N);
end if;
+ -- Rewrite as address clause
+
Rewrite (N,
Make_Attribute_Definition_Clause (Sloc (N),
Name => Identifier (N),
Chars => Name_Address,
Expression => Expression (N)));
+
+ -- We preserve Comes_From_Source, since logically the clause still
+ -- comes from the source program even though it is changed in form.
+
+ Set_Comes_From_Source (N, CS);
+
+ -- Analyze rewritten clause
+
Analyze_Attribute_Definition_Clause (N);
end Analyze_At_Clause;
-- Common processing for 'Read, 'Write, 'Input and 'Output attribute
-- definition clauses.
+ -----------------------------------
+ -- Analyze_Stream_TSS_Definition --
+ -----------------------------------
+
procedure Analyze_Stream_TSS_Definition (TSS_Nam : TSS_Name_Type) is
Subp : Entity_Id := Empty;
I : Interp_Index;
return Base_Type (Typ) = Base_Type (Ent)
and then No (Next_Formal (F));
-
end Has_Good_Profile;
-- Start of processing for Analyze_Stream_TSS_Definition
-- Start of processing for Analyze_Attribute_Definition_Clause
begin
+ -- Process Ignore_Rep_Clauses option
+
if Ignore_Rep_Clauses then
- Rewrite (N, Make_Null_Statement (Sloc (N)));
- return;
+ case Id is
+
+ -- The following should be ignored. They do not affect legality
+ -- and may be target dependent. The basic idea of -gnatI is to
+ -- ignore any rep clauses that may be target dependent but do not
+ -- affect legality (except possibly to be rejected because they
+ -- are incompatible with the compilation target).
+
+ when Attribute_Alignment |
+ Attribute_Bit_Order |
+ Attribute_Component_Size |
+ Attribute_Machine_Radix |
+ Attribute_Object_Size |
+ Attribute_Size |
+ Attribute_Small |
+ Attribute_Stream_Size |
+ Attribute_Value_Size =>
+
+ Rewrite (N, Make_Null_Statement (Sloc (N)));
+ return;
+
+ -- The following should not be ignored, because in the first place
+ -- they are reasonably portable, and should not cause problems in
+ -- compiling code from another target, and also they do affect
+ -- legality, e.g. failing to provide a stream attribute for a
+ -- type may make a program illegal.
+
+ when Attribute_External_Tag |
+ Attribute_Input |
+ Attribute_Output |
+ Attribute_Read |
+ Attribute_Storage_Pool |
+ Attribute_Storage_Size |
+ Attribute_Write =>
+ null;
+
+ -- Other cases are errors, which will be caught below
+
+ when others =>
+ null;
+ end case;
end if;
Analyze (Nam);
-- Address attribute definition clause
when Attribute_Address => Address : begin
+
+ -- A little error check, catch for X'Address use X'Address;
+
+ if Nkind (Nam) = N_Identifier
+ and then Nkind (Expr) = N_Attribute_Reference
+ and then Attribute_Name (Expr) = Name_Address
+ and then Nkind (Prefix (Expr)) = N_Identifier
+ and then Chars (Nam) = Chars (Prefix (Expr))
+ then
+ Error_Msg_NE
+ ("address for & is self-referencing", Prefix (Expr), Ent);
+ return;
+ end if;
+
+ -- Not that special case, carry on with analysis of expression
+
Analyze_And_Resolve (Expr, RTE (RE_Address));
+ -- Even when ignoring rep clauses we need to indicate that the
+ -- entity has an address clause and thus it is legal to declare
+ -- it imported.
+
+ if Ignore_Rep_Clauses then
+ if Ekind (U_Ent) = E_Variable
+ or else Ekind (U_Ent) = E_Constant
+ then
+ Record_Rep_Item (U_Ent, N);
+ end if;
+
+ return;
+ end if;
+
if Present (Address_Clause (U_Ent)) then
Error_Msg_N ("address already given for &", Nam);
Ekind (U_Ent) = E_Constant
then
declare
- Expr : constant Node_Id := Expression (N);
- Aent : constant Entity_Id := Address_Aliased_Entity (Expr);
- Ent_Y : constant Entity_Id := Find_Overlaid_Object (N);
+ Expr : constant Node_Id := Expression (N);
+ O_Ent : Entity_Id;
+ Off : Boolean;
begin
- -- Exported variables cannot have an address clause,
- -- because this cancels the effect of the pragma Export
+ -- Exported variables cannot have an address clause, because
+ -- this cancels the effect of the pragma Export.
if Is_Exported (U_Ent) then
Error_Msg_N
("cannot export object with address clause", Nam);
return;
+ end if;
+
+ Find_Overlaid_Entity (N, O_Ent, Off);
-- Overlaying controlled objects is erroneous
- elsif Present (Aent)
- and then (Has_Controlled_Component (Etype (Aent))
- or else Is_Controlled (Etype (Aent)))
+ if Present (O_Ent)
+ and then (Has_Controlled_Component (Etype (O_Ent))
+ or else Is_Controlled (Etype (O_Ent)))
then
Error_Msg_N
("?cannot overlay with controlled object", Expr);
Reason => PE_Overlaid_Controlled_Object));
return;
- elsif Present (Aent)
+ elsif Present (O_Ent)
and then Ekind (U_Ent) = E_Constant
- and then Ekind (Aent) /= E_Constant
+ and then not Is_Constant_Object (O_Ent)
then
Error_Msg_N ("constant overlays a variable?", Expr);
-- We mark a possible modification of a variable with an
-- address clause, since it is likely aliasing is occurring.
- Note_Possible_Modification (Nam);
+ Note_Possible_Modification (Nam, Sure => False);
-- Here we are checking for explicit overlap of one variable
-- by another, and if we find this then mark the overlapped
-- variable as also being volatile to prevent unwanted
- -- optimizations.
+ -- optimizations. This is a significant pessimization so
+ -- avoid it when there is an offset, i.e. when the object
+ -- is composite; they cannot be optimized easily anyway.
- if Present (Ent_Y) then
- Set_Treat_As_Volatile (Ent_Y);
+ if Present (O_Ent)
+ and then Is_Object (O_Ent)
+ and then not Off
+ then
+ Set_Treat_As_Volatile (O_Ent);
end if;
-- Legality checks on the address clause for initialized
Set_Has_Delayed_Freeze (U_Ent);
+ -- If an initialization call has been generated for this
+ -- object, it needs to be deferred to after the freeze node
+ -- we have just now added, otherwise GIGI will see a
+ -- reference to the variable (as actual to the IP call)
+ -- before its definition.
+
+ declare
+ Init_Call : constant Node_Id := Find_Init_Call (U_Ent, N);
+ begin
+ if Present (Init_Call) then
+ Remove (Init_Call);
+ Append_Freeze_Action (U_Ent, Init_Call);
+ end if;
+ end;
+
if Is_Exported (U_Ent) then
Error_Msg_N
("& cannot be exported if an address clause is given",
-- the variable, it is somewhere else.
Kill_Size_Check_Code (U_Ent);
- end;
- -- If the address clause is of the form:
+ -- If the address clause is of the form:
- -- for X'Address use Y'Address
+ -- for Y'Address use X'Address
- -- or
+ -- or
- -- Const : constant Address := Y'Address;
- -- ...
- -- for X'Address use Const;
+ -- Const : constant Address := X'Address;
+ -- ...
+ -- for Y'Address use Const;
- -- then we make an entry in the table for checking the size and
- -- alignment of the overlaying variable. We defer this check
- -- till after code generation to take full advantage of the
- -- annotation done by the back end. This entry is only made if
- -- we have not already posted a warning about size/alignment
- -- (some warnings of this type are posted in Checks).
+ -- then we make an entry in the table for checking the size
+ -- and alignment of the overlaying variable. We defer this
+ -- check till after code generation to take full advantage
+ -- of the annotation done by the back end. This entry is
+ -- only made if the address clause comes from source.
- if Address_Clause_Overlay_Warnings then
- declare
- Ent_X : Entity_Id := Empty;
- Ent_Y : Entity_Id := Empty;
+ if Address_Clause_Overlay_Warnings
+ and then Comes_From_Source (N)
+ and then Present (O_Ent)
+ and then Is_Object (O_Ent)
+ then
+ Address_Clause_Checks.Append ((N, U_Ent, O_Ent, Off));
- begin
- Ent_Y := Find_Overlaid_Object (N);
+ -- If variable overlays a constant view, and we are
+ -- warning on overlays, then mark the variable as
+ -- overlaying a constant (we will give warnings later
+ -- if this variable is assigned).
- if Present (Ent_Y) and then Is_Entity_Name (Name (N)) then
- Ent_X := Entity (Name (N));
- Address_Clause_Checks.Append ((N, Ent_X, Ent_Y));
+ if Is_Constant_Object (O_Ent)
+ and then Ekind (U_Ent) = E_Variable
+ then
+ Set_Overlays_Constant (U_Ent);
end if;
- end;
- end if;
+ end if;
+ end;
-- Not a valid entity for an address clause
-- Alignment attribute definition clause
- when Attribute_Alignment => Alignment_Block : declare
+ when Attribute_Alignment => Alignment : declare
Align : constant Uint := Get_Alignment_Value (Expr);
begin
elsif Align /= No_Uint then
Set_Has_Alignment_Clause (U_Ent);
Set_Alignment (U_Ent, Align);
+
+ -- For an array type, U_Ent is the first subtype. In that case,
+ -- also set the alignment of the anonymous base type so that
+ -- other subtypes (such as the itypes for aggregates of the
+ -- type) also receive the expected alignment.
+
+ if Is_Array_Type (U_Ent) then
+ Set_Alignment (Base_Type (U_Ent), Align);
+ end if;
end if;
- end Alignment_Block;
+ end Alignment;
---------------
-- Bit_Order --
if Has_Component_Size_Clause (Btype) then
Error_Msg_N
- ("component size clase for& previously given", Nam);
+ ("component size clause for& previously given", Nam);
elsif Csize /= No_Uint then
Check_Size (Expr, Component_Type (Btype), Csize, Biased);
-- that will be used to represent the biased subtype that
-- reflects the biased representation of components. We need
-- this subtype to get proper conversions on referencing
- -- elements of the array.
-
- if Biased then
- New_Ctyp :=
- Make_Defining_Identifier (Loc,
- Chars => New_External_Name (Chars (U_Ent), 'C', 0, 'T'));
-
- Decl :=
- Make_Subtype_Declaration (Loc,
- Defining_Identifier => New_Ctyp,
- Subtype_Indication =>
- New_Occurrence_Of (Component_Type (Btype), Loc));
-
- Set_Parent (Decl, N);
- Analyze (Decl, Suppress => All_Checks);
-
- Set_Has_Delayed_Freeze (New_Ctyp, False);
- Set_Esize (New_Ctyp, Csize);
- Set_RM_Size (New_Ctyp, Csize);
- Init_Alignment (New_Ctyp);
- Set_Has_Biased_Representation (New_Ctyp, True);
- Set_Is_Itype (New_Ctyp, True);
- Set_Associated_Node_For_Itype (New_Ctyp, U_Ent);
-
- Set_Component_Type (Btype, New_Ctyp);
+ -- elements of the array. Note that component size clauses
+ -- are ignored in VM mode.
+
+ if VM_Target = No_VM then
+ if Biased then
+ New_Ctyp :=
+ Make_Defining_Identifier (Loc,
+ Chars =>
+ New_External_Name (Chars (U_Ent), 'C', 0, 'T'));
+
+ Decl :=
+ Make_Subtype_Declaration (Loc,
+ Defining_Identifier => New_Ctyp,
+ Subtype_Indication =>
+ New_Occurrence_Of (Component_Type (Btype), Loc));
+
+ Set_Parent (Decl, N);
+ Analyze (Decl, Suppress => All_Checks);
+
+ Set_Has_Delayed_Freeze (New_Ctyp, False);
+ Set_Esize (New_Ctyp, Csize);
+ Set_RM_Size (New_Ctyp, Csize);
+ Init_Alignment (New_Ctyp);
+ Set_Has_Biased_Representation (New_Ctyp, True);
+ Set_Is_Itype (New_Ctyp, True);
+ Set_Associated_Node_For_Itype (New_Ctyp, U_Ent);
+
+ Set_Component_Type (Btype, New_Ctyp);
+
+ if Warn_On_Biased_Representation then
+ Error_Msg_N
+ ("?component size clause forces biased "
+ & "representation", N);
+ end if;
+ end if;
+
+ Set_Component_Size (Btype, Csize);
+
+ -- For VM case, we ignore component size clauses
+
+ else
+ -- Give a warning unless we are in GNAT mode, in which case
+ -- the warning is suppressed since it is not useful.
+
+ if not GNAT_Mode then
+ Error_Msg_N
+ ("?component size ignored in this configuration", N);
+ end if;
end if;
- Set_Component_Size (Btype, Csize);
Set_Has_Component_Size_Clause (Btype, True);
Set_Has_Non_Standard_Rep (Btype, True);
end if;
if VM_Target = No_VM then
Set_Has_External_Tag_Rep_Clause (U_Ent);
- elsif not Inspector_Mode then
+ else
Error_Msg_Name_1 := Attr;
Error_Msg_N
("% attribute unsupported in this configuration", Nam);
or else Has_Small_Clause (U_Ent)
then
Check_Size (Expr, Etyp, Size, Biased);
- Set_Has_Biased_Representation (U_Ent, Biased);
+ Set_Has_Biased_Representation (U_Ent, Biased);
+
+ if Biased and Warn_On_Biased_Representation then
+ Error_Msg_N
+ ("?size clause forces biased representation", N);
+ end if;
end if;
-- For types set RM_Size and Esize if possible
Set_Has_Small_Clause (U_Ent);
Set_Has_Small_Clause (Implicit_Base);
Set_Has_Non_Standard_Rep (Implicit_Base);
- Set_Discrete_RM_Size (U_Ent);
end if;
end Small;
Analyze_And_Resolve
(Expr, Class_Wide_Type (RTE (RE_Root_Storage_Pool)));
+ if not Denotes_Variable (Expr) then
+ Error_Msg_N ("storage pool must be a variable", Expr);
+ return;
+ end if;
+
if Nkind (Expr) = N_Type_Conversion then
T := Etype (Expression (Expr));
else
-- The Stack_Bounded_Pool is used internally for implementing
-- access types with a Storage_Size. Since it only work
-- properly when used on one specific type, we need to check
- -- that it is not highjacked improperly:
+ -- that it is not hijacked improperly:
-- type T is access Integer;
-- for T'Storage_Size use n;
-- type Q is access Float;
if Is_Elementary_Type (U_Ent) then
Check_Size (Expr, U_Ent, Size, Biased);
Set_Has_Biased_Representation (U_Ent, Biased);
+
+ if Biased and Warn_On_Biased_Representation then
+ Error_Msg_N
+ ("?value size clause forces biased representation", N);
+ end if;
end if;
Set_RM_Size (U_Ent, Size);
while Present (Decl) loop
DeclO := Original_Node (Decl);
if Comes_From_Source (DeclO)
- and then Nkind (DeclO) /= N_Pragma
- and then Nkind (DeclO) /= N_Use_Package_Clause
- and then Nkind (DeclO) /= N_Use_Type_Clause
- and then Nkind (DeclO) /= N_Implicit_Label_Declaration
+ and not Nkind_In (DeclO, N_Pragma,
+ N_Use_Package_Clause,
+ N_Use_Type_Clause,
+ N_Implicit_Label_Declaration)
then
Error_Msg_N
("this declaration not allowed in machine code subprogram",
while Present (Stmt) loop
StmtO := Original_Node (Stmt);
if Comes_From_Source (StmtO)
- and then Nkind (StmtO) /= N_Pragma
- and then Nkind (StmtO) /= N_Label
- and then Nkind (StmtO) /= N_Code_Statement
+ and then not Nkind_In (StmtO, N_Pragma,
+ N_Label,
+ N_Code_Statement)
then
Error_Msg_N
("this statement is not allowed in machine code subprogram",
-- Don't allow rep clause for standard [wide_[wide_]]character
- elsif Root_Type (Enumtype) = Standard_Character
- or else Root_Type (Enumtype) = Standard_Wide_Character
- or else Root_Type (Enumtype) = Standard_Wide_Wide_Character
- then
+ elsif Is_Standard_Character_Type (Enumtype) then
Error_Msg_N ("enumeration rep clause not allowed for this type", N);
return;
Analyze (Expression (N));
end Analyze_Free_Statement;
+ ---------------------------
+ -- Analyze_Freeze_Entity --
+ ---------------------------
+
+ procedure Analyze_Freeze_Entity (N : Node_Id) is
+ E : constant Entity_Id := Entity (N);
+
+ begin
+ -- For tagged types covering interfaces add internal entities that link
+ -- the primitives of the interfaces with the primitives that cover them.
+
+ -- Note: These entities were originally generated only when generating
+ -- code because their main purpose was to provide support to initialize
+ -- the secondary dispatch tables. They are now generated also when
+ -- compiling with no code generation to provide ASIS the relationship
+ -- between interface primitives and tagged type primitives.
+
+ if Ada_Version >= Ada_05
+ and then Ekind (E) = E_Record_Type
+ and then Is_Tagged_Type (E)
+ and then not Is_Interface (E)
+ and then Has_Interfaces (E)
+ then
+ Add_Internal_Interface_Entities (E);
+ end if;
+ end Analyze_Freeze_Entity;
+
------------------------------------------
-- Analyze_Record_Representation_Clause --
------------------------------------------
Hbit : Uint := Uint_0;
Comp : Entity_Id;
Ocomp : Entity_Id;
+ Pcomp : Entity_Id;
Biased : Boolean;
Max_Bit_So_Far : Uint;
-- are monotonically increasing, then we can skip the circuit for
-- checking for overlap, since no overlap is possible.
+ Tagged_Parent : Entity_Id := Empty;
+ -- This is set in the case of a derived tagged type for which we have
+ -- Is_Fully_Repped_Tagged_Type True (indicating that all components are
+ -- positioned by record representation clauses). In this case we must
+ -- check for overlap between components of this tagged type, and the
+ -- components of its parent. Tagged_Parent will point to this parent
+ -- type. For all other cases Tagged_Parent is left set to Empty.
+
+ Parent_Last_Bit : Uint;
+ -- Relevant only if Tagged_Parent is set, Parent_Last_Bit indicates the
+ -- last bit position for any field in the parent type. We only need to
+ -- check overlap for fields starting below this point.
+
Overlap_Check_Required : Boolean;
-- Used to keep track of whether or not an overlap check is required
end;
end if;
- -- Clear any existing component clauses for the type (this happens with
- -- derived types, where we are now overriding the original).
+ -- For untagged types, clear any existing component clauses for the
+ -- type. If the type is derived, this is what allows us to override
+ -- a rep clause for the parent. For type extensions, the representation
+ -- of the inherited components is inherited, so we want to keep previous
+ -- component clauses for completeness.
- Comp := First_Component_Or_Discriminant (Rectype);
- while Present (Comp) loop
- Set_Component_Clause (Comp, Empty);
- Next_Component_Or_Discriminant (Comp);
- end loop;
+ if not Is_Tagged_Type (Rectype) then
+ Comp := First_Component_Or_Discriminant (Rectype);
+ while Present (Comp) loop
+ Set_Component_Clause (Comp, Empty);
+ Next_Component_Or_Discriminant (Comp);
+ end loop;
+ end if;
+
+ -- See if we have a fully repped derived tagged type
+
+ declare
+ PS : constant Entity_Id := Parent_Subtype (Rectype);
+
+ begin
+ if Present (PS) and then Is_Fully_Repped_Tagged_Type (PS) then
+ Tagged_Parent := PS;
+
+ -- Find maximum bit of any component of the parent type
+
+ Parent_Last_Bit := UI_From_Int (System_Address_Size - 1);
+ Pcomp := First_Entity (Tagged_Parent);
+ while Present (Pcomp) loop
+ if Ekind (Pcomp) = E_Discriminant
+ or else
+ Ekind (Pcomp) = E_Component
+ then
+ if Component_Bit_Offset (Pcomp) /= No_Uint
+ and then Known_Static_Esize (Pcomp)
+ then
+ Parent_Last_Bit :=
+ UI_Max
+ (Parent_Last_Bit,
+ Component_Bit_Offset (Pcomp) + Esize (Pcomp) - 1);
+ end if;
+
+ Next_Entity (Pcomp);
+ end if;
+ end loop;
+ end if;
+ end;
-- All done if no component clauses
Set_Normalized_Position_Max (Fent, Uint_0);
Init_Esize (Fent, System_Address_Size);
- Set_Component_Clause (Fent,
+ Set_Component_Clause (Fent,
Make_Component_Clause (Loc,
Component_Name =>
Make_Identifier (Loc,
-- The only pragma of interest is Complete_Representation
- if Chars (CC) = Name_Complete_Representation then
+ if Pragma_Name (CC) = Name_Complete_Representation then
CR_Pragma := CC;
end if;
Error_Msg_N
("first bit cannot be negative", First_Bit (CC));
+ -- The Last_Bit specified in a component clause must not be
+ -- less than the First_Bit minus one (RM-13.5.1(10)).
+
+ elsif Lbit < Fbit - 1 then
+ Error_Msg_N
+ ("last bit cannot be less than first bit minus one",
+ Last_Bit (CC));
+
-- Values look OK, so find the corresponding record component
-- Even though the syntax allows an attribute reference for
-- implementation-defined components, GNAT does not allow the
("component clause is for non-existent field", CC);
elsif Present (Component_Clause (Comp)) then
- Error_Msg_Sloc := Sloc (Component_Clause (Comp));
- Error_Msg_N
- ("component clause previously given#", CC);
+
+ -- Diagnose duplicate rep clause, or check consistency
+ -- if this is an inherited component. In a double fault,
+ -- there may be a duplicate inconsistent clause for an
+ -- inherited component.
+
+ if Scope (Original_Record_Component (Comp)) = Rectype
+ or else Parent (Component_Clause (Comp)) = N
+ then
+ Error_Msg_Sloc := Sloc (Component_Clause (Comp));
+ Error_Msg_N ("component clause previously given#", CC);
+
+ else
+ declare
+ Rep1 : constant Node_Id := Component_Clause (Comp);
+ begin
+ if Intval (Position (Rep1)) /=
+ Intval (Position (CC))
+ or else Intval (First_Bit (Rep1)) /=
+ Intval (First_Bit (CC))
+ or else Intval (Last_Bit (Rep1)) /=
+ Intval (Last_Bit (CC))
+ then
+ Error_Msg_N ("component clause inconsistent "
+ & "with representation of ancestor", CC);
+ elsif Warn_On_Redundant_Constructs then
+ Error_Msg_N ("?redundant component clause "
+ & "for inherited component!", CC);
+ end if;
+ end;
+ end if;
+
+ -- Normal case where this is the first component clause we
+ -- have seen for this entity, so set it up properly.
else
-- Make reference for field in record rep clause and set
then
Error_Msg_NE
("component overlaps tag field of&",
- CC, Rectype);
+ Component_Name (CC), Rectype);
end if;
-- This information is also set in the corresponding
Set_Has_Biased_Representation (Comp, Biased);
+ if Biased and Warn_On_Biased_Representation then
+ Error_Msg_F
+ ("?component clause forces biased "
+ & "representation", CC);
+ end if;
+
if Present (Ocomp) then
Set_Component_Clause (Ocomp, CC);
Set_Component_Bit_Offset (Ocomp, Fbit);
Error_Msg_N ("component size is negative", CC);
end if;
end if;
+
+ -- If OK component size, check parent type overlap if
+ -- this component might overlap a parent field.
+
+ if Present (Tagged_Parent)
+ and then Fbit <= Parent_Last_Bit
+ then
+ Pcomp := First_Entity (Tagged_Parent);
+ while Present (Pcomp) loop
+ if (Ekind (Pcomp) = E_Discriminant
+ or else
+ Ekind (Pcomp) = E_Component)
+ and then not Is_Tag (Pcomp)
+ and then Chars (Pcomp) /= Name_uParent
+ then
+ Check_Component_Overlap (Comp, Pcomp);
+ end if;
+
+ Next_Entity (Pcomp);
+ end loop;
+ end if;
end if;
end if;
end if;
end loop;
-- Now that we have processed all the component clauses, check for
- -- overlap. We have to leave this till last, since the components
- -- can appear in any arbitrary order in the representation clause.
+ -- overlap. We have to leave this till last, since the components can
+ -- appear in any arbitrary order in the representation clause.
-- We do not need this check if all specified ranges were monotonic,
-- as recorded by Overlap_Check_Required being False at this stage.
- -- This first section checks if there are any overlapping entries
- -- at all. It does this by sorting all entries and then seeing if
- -- there are any overlaps. If there are none, then that is decisive,
- -- but if there are overlaps, they may still be OK (they may result
- -- from fields in different variants).
+ -- This first section checks if there are any overlapping entries at
+ -- all. It does this by sorting all entries and then seeing if there are
+ -- any overlaps. If there are none, then that is decisive, but if there
+ -- are overlaps, they may still be OK (they may result from fields in
+ -- different variants).
if Overlap_Check_Required then
Overlap_Check1 : declare
OC_Fbit : array (0 .. Ccount) of Uint;
- -- First-bit values for component clauses, the value is the
- -- offset of the first bit of the field from start of record.
- -- The zero entry is for use in sorting.
+ -- First-bit values for component clauses, the value is the offset
+ -- of the first bit of the field from start of record. The zero
+ -- entry is for use in sorting.
OC_Lbit : array (0 .. Ccount) of Uint;
- -- Last-bit values for component clauses, the value is the
- -- offset of the last bit of the field from start of record.
- -- The zero entry is for use in sorting.
+ -- Last-bit values for component clauses, the value is the offset
+ -- of the last bit of the field from start of record. The zero
+ -- entry is for use in sorting.
OC_Count : Natural := 0;
-- Count of entries in OC_Fbit and OC_Lbit
package Sorting is new GNAT.Heap_Sort_G (OC_Move, OC_Lt);
+ -----------
+ -- OC_Lt --
+ -----------
+
function OC_Lt (Op1, Op2 : Natural) return Boolean is
begin
return OC_Fbit (Op1) < OC_Fbit (Op2);
end OC_Lt;
+ -------------
+ -- OC_Move --
+ -------------
+
procedure OC_Move (From : Natural; To : Natural) is
begin
OC_Fbit (To) := OC_Fbit (From);
OC_Lbit (To) := OC_Lbit (From);
end OC_Move;
+ -- Start of processing for Overlap_Check
+
begin
CC := First (Component_Clauses (N));
while Present (CC) loop
end Overlap_Check1;
end if;
- -- If Overlap_Check_Required is still True, then we have to do
- -- the full scale overlap check, since we have at least two fields
- -- that do overlap, and we need to know if that is OK since they
- -- are in the same variant, or whether we have a definite problem
+ -- If Overlap_Check_Required is still True, then we have to do the full
+ -- scale overlap check, since we have at least two fields that do
+ -- overlap, and we need to know if that is OK since they are in
+ -- different variant, or whether we have a definite problem.
if Overlap_Check_Required then
Overlap_Check2 : declare
-- Loop through all components in record. For each component check
-- for overlap with any of the preceding elements on the component
- -- list containing the component, and also, if the component is in
+ -- list containing the component and also, if the component is in
-- a variant, check against components outside the case structure.
-- This latter test is repeated recursively up the variant tree.
Component_List_Loop : loop
-- If derived type definition, go to full declaration
- -- If at outer level, check discriminants if there are any
+ -- If at outer level, check discriminants if there are any.
if Nkind (Clist) = N_Derived_Type_Definition then
Clist := Parent (Clist);
-- Outer level of record definition, check discriminants
- if Nkind (Clist) = N_Full_Type_Declaration
- or else Nkind (Clist) = N_Private_Type_Declaration
+ if Nkind_In (Clist, N_Full_Type_Declaration,
+ N_Private_Type_Declaration)
then
if Has_Discriminants (Defining_Identifier (Clist)) then
C2_Ent :=
First_Discriminant (Defining_Identifier (Clist));
-
while Present (C2_Ent) loop
exit when C1_Ent = C2_Ent;
Check_Component_Overlap (C1_Ent, C2_Ent);
-- be a variant, in which case its parent is a variant part,
-- and the parent of the variant part is a component list
-- whose components must all be checked against the current
- -- component for overlap.
+ -- component for overlap).
if Nkind (Parent (Clist)) = N_Variant then
Clist := Parent (Parent (Parent (Clist)));
-- Check for possible discriminant part in record, this is
-- treated essentially as another level in the recursion.
- -- For this case we have the parent of the component list
- -- is the record definition, and its parent is the full
- -- type declaration which contains the discriminant
- -- specifications.
+ -- For this case the parent of the component list is the
+ -- record definition, and its parent is the full type
+ -- declaration containing the discriminant specifications.
elsif Nkind (Parent (Clist)) = N_Record_Definition then
Clist := Parent (Parent ((Clist)));
-- If neither of these two cases, we are at the top of
- -- the tree
+ -- the tree.
else
exit Component_List_Loop;
end Overlap_Check2;
end if;
- -- For records that have component clauses for all components, and
- -- whose size is less than or equal to 32, we need to know the size
- -- in the front end to activate possible packed array processing
- -- where the component type is a record.
+ -- For records that have component clauses for all components, and whose
+ -- size is less than or equal to 32, we need to know the size in the
+ -- front end to activate possible packed array processing where the
+ -- component type is a record.
- -- At this stage Hbit + 1 represents the first unused bit from all
- -- the component clauses processed, so if the component clauses are
+ -- At this stage Hbit + 1 represents the first unused bit from all the
+ -- component clauses processed, so if the component clauses are
-- complete, then this is the length of the record.
- -- For records longer than System.Storage_Unit, and for those where
- -- not all components have component clauses, the back end determines
- -- the length (it may for example be appopriate to round up the size
- -- to some convenient boundary, based on alignment considerations etc).
+ -- For records longer than System.Storage_Unit, and for those where not
+ -- all components have component clauses, the back end determines the
+ -- length (it may for example be appropriate to round up the size
+ -- to some convenient boundary, based on alignment considerations, etc).
- if Unknown_RM_Size (Rectype)
- and then Hbit + 1 <= 32
- then
- -- Nothing to do if at least one component with no component clause
+ if Unknown_RM_Size (Rectype) and then Hbit + 1 <= 32 then
+
+ -- Nothing to do if at least one component has no component clause
Comp := First_Component_Or_Discriminant (Rectype);
while Present (Comp) loop
-- If no Complete_Representation pragma, warn if missing components
- elsif Warn_On_Unrepped_Components
- and then not Warnings_Off (Rectype)
- then
+ elsif Warn_On_Unrepped_Components then
declare
Num_Repped_Components : Nat := 0;
Num_Unrepped_Components : Nat := 0;
-- We are only interested in the case where there is at least one
-- unrepped component, and at least half the components have rep
-- clauses. We figure that if less than half have them, then the
- -- partial rep clause is really intentional.
+ -- partial rep clause is really intentional. If the component
+ -- type has no underlying type set at this point (as for a generic
+ -- formal type), we don't know enough to give a warning on the
+ -- component.
if Num_Unrepped_Components > 0
and then Num_Unrepped_Components < Num_Repped_Components
Comp := First_Component_Or_Discriminant (Rectype);
while Present (Comp) loop
if No (Component_Clause (Comp))
+ and then Comes_From_Source (Comp)
+ and then Present (Underlying_Type (Etype (Comp)))
and then (Is_Scalar_Type (Underlying_Type (Etype (Comp)))
or else Size_Known_At_Compile_Time
(Underlying_Type (Etype (Comp))))
+ and then not Has_Warnings_Off (Rectype)
then
Error_Msg_Sloc := Sloc (Comp);
Error_Msg_NE
if Present (Component_Clause (C1_Ent))
and then Present (Component_Clause (C2_Ent))
then
- -- Exclude odd case where we have two tag fields in the same
- -- record, both at location zero. This seems a bit strange,
- -- but it seems to happen in some circumstances ???
+ -- Exclude odd case where we have two tag fields in the same record,
+ -- both at location zero. This seems a bit strange, but it seems to
+ -- happen in some circumstances ???
if Chars (C1_Ent) = Name_uTag
and then Chars (C2_Ent) = Name_uTag
U_Ent : Entity_Id)
is
procedure Check_At_Constant_Address (Nod : Node_Id);
- -- Checks that the given node N represents a name whose 'Address
- -- is constant (in the same sense as OK_Constant_Address_Clause,
- -- i.e. the address value is the same at the point of declaration
- -- of U_Ent and at the time of elaboration of the address clause.
+ -- Checks that the given node N represents a name whose 'Address is
+ -- constant (in the same sense as OK_Constant_Address_Clause, i.e. the
+ -- address value is the same at the point of declaration of U_Ent and at
+ -- the time of elaboration of the address clause.
procedure Check_Expr_Constants (Nod : Node_Id);
- -- Checks that Nod meets the requirements for a constant address
- -- clause in the sense of the enclosing procedure.
+ -- Checks that Nod meets the requirements for a constant address clause
+ -- in the sense of the enclosing procedure.
procedure Check_List_Constants (Lst : List_Id);
-- Check that all elements of list Lst meet the requirements for a
Error_Msg_NE
("invalid address clause for initialized object &!",
Nod, U_Ent);
- Error_Msg_Name_1 := Chars (Entity (Nod));
- Error_Msg_Name_2 := Chars (U_Ent);
- Error_Msg_N
- ("\% must be defined before % (RM 13.1(22))!",
- Nod);
+ Error_Msg_Node_2 := U_Ent;
+ Error_Msg_NE
+ ("\& must be defined before & (RM 13.1(22))!",
+ Nod, Entity (Nod));
end if;
elsif Nkind (Nod) = N_Selected_Component then
-- If the node is an object declaration without initial
-- value, some code has been expanded, and the expression
-- is not constant, even if the constituents might be
- -- acceptable, as in A'Address + offset.
+ -- acceptable, as in A'Address + offset.
if Ekind (Ent) = E_Variable
- and then Nkind (Declaration_Node (Ent))
- = N_Object_Declaration
+ and then
+ Nkind (Declaration_Node (Ent)) = N_Object_Declaration
and then
No (Expression (Declaration_Node (Ent)))
then
or else
Ekind (Ent) = E_In_Parameter
then
- -- This is the case where we must have Ent defined
- -- before U_Ent. Clearly if they are in different
- -- units this requirement is met since the unit
- -- containing Ent is already processed.
+ -- This is the case where we must have Ent defined before
+ -- U_Ent. Clearly if they are in different units this
+ -- requirement is met since the unit containing Ent is
+ -- already processed.
if not In_Same_Source_Unit (Ent, U_Ent) then
return;
- -- Otherwise location of Ent must be before the
- -- location of U_Ent, that's what prior defined means.
+ -- Otherwise location of Ent must be before the location
+ -- of U_Ent, that's what prior defined means.
elsif Sloc (Ent) < Loc_U_Ent then
return;
Error_Msg_NE
("invalid address clause for initialized object &!",
Nod, U_Ent);
- Error_Msg_Name_1 := Chars (Ent);
- Error_Msg_Name_2 := Chars (U_Ent);
- Error_Msg_N
- ("\% must be defined before % (RM 13.1(22))!",
- Nod);
+ Error_Msg_Node_2 := U_Ent;
+ Error_Msg_NE
+ ("\& must be defined before & (RM 13.1(22))!",
+ Nod, Ent);
end if;
elsif Nkind (Original_Node (Nod)) = N_Function_Call then
Nod, U_Ent);
if Comes_From_Source (Ent) then
- Error_Msg_Name_1 := Chars (Ent);
- Error_Msg_N
- ("\reference to variable% not allowed"
- & " (RM 13.1(22))!", Nod);
+ Error_Msg_NE
+ ("\reference to variable& not allowed"
+ & " (RM 13.1(22))!", Nod, Ent);
else
Error_Msg_N
("non-static expression not allowed"
when N_Null =>
return;
- when N_Binary_Op | N_And_Then | N_Or_Else | N_Membership_Test =>
+ when N_Binary_Op | N_Short_Circuit | N_Membership_Test =>
Check_Expr_Constants (Left_Opnd (Nod));
Check_Expr_Constants (Right_Opnd (Nod));
when N_Unchecked_Type_Conversion =>
Check_Expr_Constants (Expression (Nod));
- -- If this is a rewritten unchecked conversion, subtypes
- -- in this node are those created within the instance.
- -- To avoid order of elaboration issues, replace them
- -- with their base types. Note that address clauses can
- -- cause order of elaboration problems because they are
- -- elaborated by the back-end at the point of definition,
- -- and may mention entities declared in between (as long
- -- as everything is static). It is user-friendly to allow
- -- unchecked conversions in this context.
+ -- If this is a rewritten unchecked conversion, subtypes in
+ -- this node are those created within the instance. To avoid
+ -- order of elaboration issues, replace them with their base
+ -- types. Note that address clauses can cause order of
+ -- elaboration problems because they are elaborated by the
+ -- back-end at the point of definition, and may mention
+ -- entities declared in between (as long as everything is
+ -- static). It is user-friendly to allow unchecked conversions
+ -- in this context.
if Nkind (Original_Node (Nod)) = N_Function_Call then
Set_Etype (Expression (Nod),
if Siz < M then
-- Size is less than minimum size, but one possibility remains
- -- that we can manage with the new size if we bias the type
+ -- that we can manage with the new size if we bias the type.
M := UI_From_Int (Minimum_Size (UT, Biased => True));
else
declare
Id : constant Attribute_Id := Get_Attribute_Id (Chars (N));
-
begin
- return Id = Attribute_Input
+ return Id = Attribute_Input
or else Id = Attribute_Output
or else Id = Attribute_Read
or else Id = Attribute_Write
-- we have short and long addresses, and it is possible for an access
-- type to have a short address size (and thus be less than the size
-- of System.Address itself). We simply skip the check for VMS, and
- -- leave the back end to do the check.
+ -- leave it to the back end to do the check.
elsif Is_Access_Type (T) then
if OpenVMS_On_Target then
elsif Is_Discrete_Type (T) then
- -- The following loop is looking for the nearest compile time
- -- known bounds following the ancestor subtype chain. The idea
- -- is to find the most restrictive known bounds information.
+ -- The following loop is looking for the nearest compile time known
+ -- bounds following the ancestor subtype chain. The idea is to find
+ -- the most restrictive known bounds information.
Ancest := T;
loop
end loop;
-- Fixed-point types. We can't simply use Expr_Value to get the
- -- Corresponding_Integer_Value values of the bounds, since these
- -- do not get set till the type is frozen, and this routine can
- -- be called before the type is frozen. Similarly the test for
- -- bounds being static needs to include the case where we have
- -- unanalyzed real literals for the same reason.
+ -- Corresponding_Integer_Value values of the bounds, since these do not
+ -- get set till the type is frozen, and this routine can be called
+ -- before the type is frozen. Similarly the test for bounds being static
+ -- needs to include the case where we have unanalyzed real literals for
+ -- the same reason.
elsif Is_Fixed_Point_Type (T) then
- -- The following loop is looking for the nearest compile time
- -- known bounds following the ancestor subtype chain. The idea
- -- is to find the most restrictive known bounds information.
+ -- The following loop is looking for the nearest compile time known
+ -- bounds following the ancestor subtype chain. The idea is to find
+ -- the most restrictive known bounds information.
Ancest := T;
loop
return 0;
end if;
+ -- Note: In the following two tests for LoSet and HiSet, it may
+ -- seem redundant to test for N_Real_Literal here since normally
+ -- one would assume that the test for the value being known at
+ -- compile time includes this case. However, there is a glitch.
+ -- If the real literal comes from folding a non-static expression,
+ -- then we don't consider any non- static expression to be known
+ -- at compile time if we are in configurable run time mode (needed
+ -- in some cases to give a clearer definition of what is and what
+ -- is not accepted). So the test is indeed needed. Without it, we
+ -- would set neither Lo_Set nor Hi_Set and get an infinite loop.
+
if not LoSet then
if Nkind (Type_Low_Bound (Ancest)) = N_Real_Literal
or else Compile_Time_Known_Value (Type_Low_Bound (Ancest))
-- Fall through with Hi and Lo set. Deal with biased case
- if (Biased and then not Is_Fixed_Point_Type (T))
+ if (Biased
+ and then not Is_Fixed_Point_Type (T)
+ and then not (Is_Enumeration_Type (T)
+ and then Has_Non_Standard_Rep (T)))
or else Has_Biased_Representation (T)
then
Hi := Hi - Lo;
end if;
-- Signed case. Note that we consider types like range 1 .. -1 to be
- -- signed for the purpose of computing the size, since the bounds
- -- have to be accomodated in the base type.
+ -- signed for the purpose of computing the size, since the bounds have
+ -- to be accommodated in the base type.
if Lo < 0 or else Hi < 0 then
S := 1;
return True;
end if;
- -- Otherwise check for incompleted type
+ -- Otherwise check for incomplete type
if Is_Incomplete_Or_Private_Type (T)
and then No (Underlying_Type (T))
("representation item must be after full type declaration", N);
return True;
- -- If the type has incompleted components, a representation clause is
+ -- If the type has incomplete components, a representation clause is
-- illegal but stream attributes and Convention pragmas are correct.
elsif Has_Private_Component (T) then
end if;
end if;
- -- No error, link item into head of chain of rep items for the entity
+ -- No error, link item into head of chain of rep items for the entity,
+ -- but avoid chaining if we have an overloadable entity, and the pragma
+ -- is one that can apply to multiple overloaded entities.
+
+ if Is_Overloadable (T)
+ and then Nkind (N) = N_Pragma
+ then
+ declare
+ Pname : constant Name_Id := Pragma_Name (N);
+ begin
+ if Pname = Name_Convention or else
+ Pname = Name_Import or else
+ Pname = Name_Export or else
+ Pname = Name_External or else
+ Pname = Name_Interface
+ then
+ return False;
+ end if;
+ end;
+ end if;
Record_Rep_Item (T, N);
return False;
return not Has_Non_Standard_Rep (T2);
end if;
- -- Here the two types both have non-standard representation, and we
- -- need to determine if they have the same non-standard representation
+ -- Here the two types both have non-standard representation, and we need
+ -- to determine if they have the same non-standard representation.
-- For arrays, we simply need to test if the component sizes are the
-- same. Pragma Pack is reflected in modified component sizes, so this
end if;
end Same_Rep;
- -- Start processing for Record_Case
+ -- Start of processing for Record_Case
begin
if Has_Discriminants (T1) then
-- For enumeration types, we must check each literal to see if the
-- representation is the same. Note that we do not permit enumeration
- -- reprsentation clauses for Character and Wide_Character, so these
+ -- representation clauses for Character and Wide_Character, so these
-- cases were already dealt with.
elsif Is_Enumeration_Type (T1) then
ACCR : Address_Clause_Check_Record
renames Address_Clause_Checks.Table (J);
+ Expr : Node_Id;
+
X_Alignment : Uint;
Y_Alignment : Uint;
if not Address_Warning_Posted (ACCR.N) then
- -- Get alignments. Really we should always have the alignment
- -- of the objects properly back annotated, but right now the
- -- back end fails to back annotate for address clauses???
+ Expr := Original_Node (Expression (ACCR.N));
- if Known_Alignment (ACCR.X) then
- X_Alignment := Alignment (ACCR.X);
- else
- X_Alignment := Alignment (Etype (ACCR.X));
- end if;
+ -- Get alignments
- if Known_Alignment (ACCR.Y) then
- Y_Alignment := Alignment (ACCR.Y);
- else
- Y_Alignment := Alignment (Etype (ACCR.Y));
- end if;
+ X_Alignment := Alignment (ACCR.X);
+ Y_Alignment := Alignment (ACCR.Y);
-- Similarly obtain sizes
- if Known_Esize (ACCR.X) then
- X_Size := Esize (ACCR.X);
- else
- X_Size := Esize (Etype (ACCR.X));
- end if;
-
- if Known_Esize (ACCR.Y) then
- Y_Size := Esize (ACCR.Y);
- else
- Y_Size := Esize (Etype (ACCR.Y));
- end if;
+ X_Size := Esize (ACCR.X);
+ Y_Size := Esize (ACCR.Y);
-- Check for large object overlaying smaller one
and then X_Size > Uint_0
and then X_Size > Y_Size
then
+ Error_Msg_NE
+ ("?& overlays smaller object", ACCR.N, ACCR.X);
Error_Msg_N
- ("?size for overlaid object is too small", ACCR.N);
+ ("\?program execution may be erroneous", ACCR.N);
Error_Msg_Uint_1 := X_Size;
Error_Msg_NE
("\?size of & is ^", ACCR.N, ACCR.X);
Error_Msg_NE
("\?size of & is ^", ACCR.N, ACCR.Y);
- -- Check for inadequate alignment. Again the defensive check
- -- on Y_Alignment should not be needed, but because of the
- -- failure in back end annotation, we can have an alignment
- -- of 0 here???
+ -- Check for inadequate alignment, both of the base object
+ -- and of the offset, if any.
- -- Note: we do not check alignments if we gave a size
- -- warning, since it would likely be redundant.
+ -- Note: we do not check the alignment if we gave a size
+ -- warning, since it would likely be redundant.
elsif Y_Alignment /= Uint_0
- and then Y_Alignment < X_Alignment
+ and then (Y_Alignment < X_Alignment
+ or else (ACCR.Off
+ and then
+ Nkind (Expr) = N_Attribute_Reference
+ and then
+ Attribute_Name (Expr) = Name_Address
+ and then
+ Has_Compatible_Alignment
+ (ACCR.X, Prefix (Expr))
+ /= Known_Compatible))
then
Error_Msg_NE
("?specified address for& may be inconsistent "
Error_Msg_NE
("\?alignment of & is ^",
ACCR.N, ACCR.Y);
+ if Y_Alignment >= X_Alignment then
+ Error_Msg_N
+ ("\?but offset is not multiple of alignment",
+ ACCR.N);
+ end if;
end if;
end if;
end;
Target := Ancestor_Subtype (Etype (Act_Unit));
- -- If either type is generic, the instantiation happens within a
- -- generic unit, and there is nothing to check. The proper check
+ -- If either type is generic, the instantiation happens within a generic
+ -- unit, and there is nothing to check. The proper check
-- will happen when the enclosing generic is instantiated.
if Is_Generic_Type (Source) or else Is_Generic_Type (Target) then
and then Convention (Target) /= Convention (Source)
and then Warn_On_Unchecked_Conversion
then
- Error_Msg_N
- ("?conversion between pointers with different conventions!", N);
+ -- Give warnings for subprogram pointers only on most targets. The
+ -- exception is VMS, where data pointers can have different lengths
+ -- depending on the pointer convention.
+
+ if Is_Access_Subprogram_Type (Target)
+ or else Is_Access_Subprogram_Type (Source)
+ or else OpenVMS_On_Target
+ then
+ Error_Msg_N
+ ("?conversion between pointers with different conventions!", N);
+ end if;
end if;
- -- Make entry in unchecked conversion table for later processing
- -- by Validate_Unchecked_Conversions, which will check sizes and
- -- alignments (using values set by the back-end where possible).
- -- This is only done if the appropriate warning is active
+ -- Warn if one of the operands is Ada.Calendar.Time. Do not emit a
+ -- warning when compiling GNAT-related sources.
+
+ if Warn_On_Unchecked_Conversion
+ and then not In_Predefined_Unit (N)
+ and then RTU_Loaded (Ada_Calendar)
+ and then
+ (Chars (Source) = Name_Time
+ or else
+ Chars (Target) = Name_Time)
+ then
+ -- If Ada.Calendar is loaded and the name of one of the operands is
+ -- Time, there is a good chance that this is Ada.Calendar.Time.
+
+ declare
+ Calendar_Time : constant Entity_Id :=
+ Full_View (RTE (RO_CA_Time));
+ begin
+ pragma Assert (Present (Calendar_Time));
+
+ if Source = Calendar_Time
+ or else Target = Calendar_Time
+ then
+ Error_Msg_N
+ ("?representation of 'Time values may change between " &
+ "'G'N'A'T versions", N);
+ end if;
+ end;
+ end if;
+
+ -- Make entry in unchecked conversion table for later processing by
+ -- Validate_Unchecked_Conversions, which will check sizes and alignments
+ -- (using values set by the back-end where possible). This is only done
+ -- if the appropriate warning is active.
if Warn_On_Unchecked_Conversion then
Unchecked_Conversions.Append
(New_Val => UC_Entry'
- (Enode => N,
+ (Eloc => Sloc (N),
Source => Source,
Target => Target));
end if;
end if;
- -- If unchecked conversion to access type, and access type is
- -- declared in the same unit as the unchecked conversion, then
- -- set the No_Strict_Aliasing flag (no strict aliasing is
- -- implicit in this situation).
+ -- If unchecked conversion to access type, and access type is declared
+ -- in the same unit as the unchecked conversion, then set the
+ -- No_Strict_Aliasing flag (no strict aliasing is implicit in this
+ -- situation).
if Is_Access_Type (Target) and then
In_Same_Source_Unit (Target, N)
-- Generate N_Validate_Unchecked_Conversion node for back end in
-- case the back end needs to perform special validation checks.
- -- Shouldn't this be in exp_ch13, since the check only gets done
+ -- Shouldn't this be in Exp_Ch13, since the check only gets done
-- if we have full expansion and the back end is called ???
Vnode :=
Set_Source_Type (Vnode, Source);
Set_Target_Type (Vnode, Target);
- -- If the unchecked conversion node is in a list, just insert before
- -- it. If not we have some strange case, not worth bothering about.
+ -- If the unchecked conversion node is in a list, just insert before it.
+ -- If not we have some strange case, not worth bothering about.
if Is_List_Member (N) then
Insert_After (N, Vnode);
declare
T : UC_Entry renames Unchecked_Conversions.Table (N);
- Enode : constant Node_Id := T.Enode;
- Source : constant Entity_Id := T.Source;
- Target : constant Entity_Id := T.Target;
+ Eloc : constant Source_Ptr := T.Eloc;
+ Source : constant Entity_Id := T.Source;
+ Target : constant Entity_Id := T.Target;
Source_Siz : Uint;
Target_Siz : Uint;
begin
- -- This validation check, which warns if we have unequal sizes
- -- for unchecked conversion, and thus potentially implementation
+ -- This validation check, which warns if we have unequal sizes for
+ -- unchecked conversion, and thus potentially implementation
-- dependent semantics, is one of the few occasions on which we
- -- use the official RM size instead of Esize. See description
- -- in Einfo "Handling of Type'Size Values" for details.
+ -- use the official RM size instead of Esize. See description in
+ -- Einfo "Handling of Type'Size Values" for details.
if Serious_Errors_Detected = 0
and then Known_Static_RM_Size (Source)
and then Known_Static_RM_Size (Target)
+
+ -- Don't do the check if warnings off for either type, note the
+ -- deliberate use of OR here instead of OR ELSE to get the flag
+ -- Warnings_Off_Used set for both types if appropriate.
+
+ and then not (Has_Warnings_Off (Source)
+ or
+ Has_Warnings_Off (Target))
then
Source_Siz := RM_Size (Source);
Target_Siz := RM_Size (Target);
if Source_Siz /= Target_Siz then
- Error_Msg_N
+ Error_Msg
("?types for unchecked conversion have different sizes!",
- Enode);
+ Eloc);
if All_Errors_Mode then
Error_Msg_Name_1 := Chars (Source);
Error_Msg_Uint_1 := Source_Siz;
Error_Msg_Name_2 := Chars (Target);
Error_Msg_Uint_2 := Target_Siz;
- Error_Msg_N
- ("\size of % is ^, size of % is ^?", Enode);
+ Error_Msg ("\size of % is ^, size of % is ^?", Eloc);
Error_Msg_Uint_1 := UI_Abs (Source_Siz - Target_Siz);
and then Is_Discrete_Type (Target)
then
if Source_Siz > Target_Siz then
- Error_Msg_N
+ Error_Msg
("\?^ high order bits of source will be ignored!",
- Enode);
+ Eloc);
elsif Is_Unsigned_Type (Source) then
- Error_Msg_N
+ Error_Msg
("\?source will be extended with ^ high order " &
- "zero bits?!", Enode);
+ "zero bits?!", Eloc);
else
- Error_Msg_N
+ Error_Msg
("\?source will be extended with ^ high order " &
"sign bits!",
- Enode);
+ Eloc);
end if;
elsif Source_Siz < Target_Siz then
if Is_Discrete_Type (Target) then
if Bytes_Big_Endian then
- Error_Msg_N
+ Error_Msg
("\?target value will include ^ undefined " &
"low order bits!",
- Enode);
+ Eloc);
else
- Error_Msg_N
+ Error_Msg
("\?target value will include ^ undefined " &
"high order bits!",
- Enode);
+ Eloc);
end if;
else
- Error_Msg_N
+ Error_Msg
("\?^ trailing bits of target value will be " &
- "undefined!", Enode);
+ "undefined!", Eloc);
end if;
else pragma Assert (Source_Siz > Target_Siz);
- Error_Msg_N
+ Error_Msg
("\?^ trailing bits of source will be ignored!",
- Enode);
+ Eloc);
end if;
end if;
end if;
begin
if Source_Align < Target_Align
and then not Is_Tagged_Type (D_Source)
+
+ -- Suppress warning if warnings suppressed on either
+ -- type or either designated type. Note the use of
+ -- OR here instead of OR ELSE. That is intentional,
+ -- we would like to set flag Warnings_Off_Used in
+ -- all types for which warnings are suppressed.
+
+ and then not (Has_Warnings_Off (D_Source)
+ or
+ Has_Warnings_Off (D_Target)
+ or
+ Has_Warnings_Off (Source)
+ or
+ Has_Warnings_Off (Target))
then
Error_Msg_Uint_1 := Target_Align;
Error_Msg_Uint_2 := Source_Align;
+ Error_Msg_Node_1 := D_Target;
Error_Msg_Node_2 := D_Source;
- Error_Msg_NE
+ Error_Msg
("?alignment of & (^) is stricter than " &
- "alignment of & (^)!", Enode, D_Target);
-
- if All_Errors_Mode then
- Error_Msg_N
- ("\?resulting access value may have invalid " &
- "alignment!", Enode);
- end if;
+ "alignment of & (^)!", Eloc);
+ Error_Msg
+ ("\?resulting access value may have invalid " &
+ "alignment!", Eloc);
end if;
end;
end if;