-- --
-- B o d y --
-- --
--- Copyright (C) 1992-2003 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- --
--- ware Foundation; either version 2, or (at your option) any later ver- --
+-- ware Foundation; either version 3, or (at your option) any later ver- --
-- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
-- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
-- for more details. You should have received a copy of the GNU General --
--- Public License distributed with GNAT; see file COPYING. If not, write --
--- to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, --
--- MA 02111-1307, USA. --
+-- Public License distributed with GNAT; see file COPYING3. If not, go to --
+-- http://www.gnu.org/licenses for a complete copy of the license. --
-- --
-- GNAT was originally developed by the GNAT team at New York University. --
-- Extensive contributions were provided by Ada Core Technologies Inc. --
with Exp_Util; use Exp_Util;
with Freeze; use Freeze;
with Itypes; use Itypes;
+with Lib; use Lib;
with Lib.Xref; use Lib.Xref;
with Namet; use Namet;
+with Namet.Sp; use Namet.Sp;
with Nmake; use Nmake;
with Nlists; use Nlists;
with Opt; use Opt;
with Sem; use Sem;
with Sem_Cat; use Sem_Cat;
-with Sem_Ch8; use Sem_Ch8;
+with Sem_Ch3; use Sem_Ch3;
with Sem_Ch13; use Sem_Ch13;
with Sem_Eval; use Sem_Eval;
with Sem_Res; use Sem_Res;
with Tbuild; use Tbuild;
with Uintp; use Uintp;
-with GNAT.Spelling_Checker; use GNAT.Spelling_Checker;
-
package body Sem_Aggr is
type Case_Bounds is record
-- statement of variant part will usually be small and probably in near
-- sorted order.
+ procedure Check_Can_Never_Be_Null (Typ : Entity_Id; Expr : Node_Id);
+ -- Ada 2005 (AI-231): Check bad usage of null for a component for which
+ -- null exclusion (NOT NULL) is specified. Typ can be an E_Array_Type for
+ -- the array case (the component type of the array will be used) or an
+ -- E_Component/E_Discriminant entity in the record case, in which case the
+ -- type of the component will be used for the test. If Typ is any other
+ -- kind of entity, the call is ignored. Expr is the component node in the
+ -- aggregate which is known to have a null value. A warning message will be
+ -- issued if the component is null excluding.
+ --
+ -- It would be better to pass the proper type for Typ ???
+
+ procedure Check_Expr_OK_In_Limited_Aggregate (Expr : Node_Id);
+ -- Check that Expr is either not limited or else is one of the cases of
+ -- expressions allowed for a limited component association (namely, an
+ -- aggregate, function call, or <> notation). Report error for violations.
+
------------------------------------------------------
-- Subprograms used for RECORD AGGREGATE Processing --
------------------------------------------------------
-- N is the N_Aggregate node.
-- Typ is the record type for the aggregate resolution
--
- -- While performing the semantic checks, this procedure
- -- builds a new Component_Association_List where each record field
- -- appears alone in a Component_Choice_List along with its corresponding
- -- expression. The record fields in the Component_Association_List
- -- appear in the same order in which they appear in the record type Typ.
+ -- While performing the semantic checks, this procedure builds a new
+ -- Component_Association_List where each record field appears alone in a
+ -- Component_Choice_List along with its corresponding expression. The
+ -- record fields in the Component_Association_List appear in the same order
+ -- in which they appear in the record type Typ.
--
- -- Once this new Component_Association_List is built and all the
- -- semantic checks performed, the original aggregate subtree is replaced
- -- with the new named record aggregate just built. Note that the subtree
- -- substitution is performed with Rewrite so as to be
- -- able to retrieve the original aggregate.
+ -- Once this new Component_Association_List is built and all the semantic
+ -- checks performed, the original aggregate subtree is replaced with the
+ -- new named record aggregate just built. Note that subtree substitution is
+ -- performed with Rewrite so as to be able to retrieve the original
+ -- aggregate.
--
-- The aggregate subtree manipulation performed by Resolve_Record_Aggregate
-- yields the aggregate format expected by Gigi. Typically, this kind of
-- tree manipulations are done in the expander. However, because the
- -- semantic checks that need to be performed on record aggregates really
- -- go hand in hand with the record aggregate normalization, the aggregate
+ -- semantic checks that need to be performed on record aggregates really go
+ -- hand in hand with the record aggregate normalization, the aggregate
-- subtree transformation is performed during resolution rather than
- -- expansion. Had we decided otherwise we would have had to duplicate
- -- most of the code in the expansion procedure Expand_Record_Aggregate.
- -- Note, however, that all the expansion concerning aggegates for tagged
- -- records is done in Expand_Record_Aggregate.
+ -- expansion. Had we decided otherwise we would have had to duplicate most
+ -- of the code in the expansion procedure Expand_Record_Aggregate. Note,
+ -- however, that all the expansion concerning aggregates for tagged records
+ -- is done in Expand_Record_Aggregate.
--
-- The algorithm of Resolve_Record_Aggregate proceeds as follows:
--
-- should we not find such values or should they be duplicated.
--
-- 7. We then make sure no illegal component names appear in the
- -- record aggegate and make sure that the type of the record
+ -- record aggregate and make sure that the type of the record
-- components appearing in a same choice list is the same.
-- Finally we ensure that the others choice, if present, is
-- used to provide the value of at least a record component.
-- quadratic in the size of the association list.
procedure Check_Misspelled_Component
- (Elements : Elist_Id;
- Component : Node_Id);
+ (Elements : Elist_Id;
+ Component : Node_Id);
-- Give possible misspelling diagnostic if Component is likely to be
-- a misspelling of one of the components of the Assoc_List.
- -- This is called by Resolv_Aggr_Expr after producing
+ -- This is called by Resolve_Aggr_Expr after producing
-- an invalid component error message.
procedure Check_Static_Discriminated_Subtype (T : Entity_Id; V : Node_Id);
Index : Node_Id;
Index_Constr : Node_Id;
Component_Typ : Entity_Id;
- Others_Allowed : Boolean)
- return Boolean;
+ Others_Allowed : Boolean) return Boolean;
-- This procedure performs the semantic checks for an array aggregate.
-- True is returned if the aggregate resolution succeeds.
+ --
-- The procedure works by recursively checking each nested aggregate.
- -- Specifically, after checking a sub-aggreate nested at the i-th level
+ -- Specifically, after checking a sub-aggregate nested at the i-th level
-- we recursively check all the subaggregates at the i+1-st level (if any).
-- Note that for aggregates analysis and resolution go hand in hand.
-- Aggregate analysis has been delayed up to here and it is done while
-- appears last in the sub-aggregate. Check that we do not have
-- positional and named components in the array sub-aggregate (unless
-- the named association is an others choice). Finally if an others
- -- choice is present, make sure it is allowed in the aggregate contex.
+ -- choice is present, make sure it is allowed in the aggregate context.
--
-- 2. If the array sub-aggregate contains discrete_choices:
--
-- those defined by the aggregate. When this routine is invoked
-- Resolve_Array_Aggregate has already processed aggregate N. Thus the
-- Aggregate_Bounds of each sub-aggregate, is an N_Range node giving the
- -- sub-aggregate bounds. When building the aggegate itype, this function
+ -- sub-aggregate bounds. When building the aggregate itype, this function
-- traverses the array aggregate N collecting such Aggregate_Bounds and
-- constructs the proper array aggregate itype.
--
-- This is really expansion activity, so make sure that expansion
-- is on and is allowed.
- if not Expander_Active or else In_Default_Expression then
+ if not Expander_Active or else In_Spec_Expression then
return;
end if;
Apply_Scalar_Range_Check (Exp, Check_Typ);
end if;
+ -- Verify that target type is also scalar, to prevent view anomalies
+ -- in instantiations.
+
elsif (Is_Scalar_Type (Exp_Typ)
- or else Nkind (Exp) = N_String_Literal)
+ or else Nkind (Exp) = N_String_Literal)
+ and then Is_Scalar_Type (Check_Typ)
and then Exp_Typ /= Check_Typ
then
if Is_Entity_Name (Exp)
Analyze_And_Resolve (Exp, Check_Typ);
Check_Unset_Reference (Exp);
end if;
+
+ -- Ada 2005 (AI-230): Generate a conversion to an anonymous access
+ -- component's type to force the appropriate accessibility checks.
+
+ -- Ada 2005 (AI-231): Generate conversion to the null-excluding
+ -- type to force the corresponding run-time check
+
+ elsif Is_Access_Type (Check_Typ)
+ and then ((Is_Local_Anonymous_Access (Check_Typ))
+ or else (Can_Never_Be_Null (Check_Typ)
+ and then not Can_Never_Be_Null (Exp_Typ)))
+ then
+ Rewrite (Exp, Convert_To (Check_Typ, Relocate_Node (Exp)));
+ Analyze_And_Resolve (Exp, Check_Typ);
+ Check_Unset_Reference (Exp);
end if;
end Aggregate_Constraint_Checks;
return Entity_Id
is
Aggr_Dimension : constant Pos := Number_Dimensions (Typ);
- -- Number of aggregate index dimensions.
+ -- Number of aggregate index dimensions
Aggr_Range : array (1 .. Aggr_Dimension) of Node_Id := (others => Empty);
- -- Constrained N_Range of each index dimension in our aggregate itype.
+ -- Constrained N_Range of each index dimension in our aggregate itype
Aggr_Low : array (1 .. Aggr_Dimension) of Node_Id := (others => Empty);
Aggr_High : array (1 .. Aggr_Dimension) of Node_Id := (others => Empty);
- -- Low and High bounds for each index dimension in our aggregate itype.
+ -- Low and High bounds for each index dimension in our aggregate itype
Is_Fully_Positional : Boolean := True;
-- (sub-)aggregate N. This procedure collects the constrained N_Range
-- nodes corresponding to each index dimension of our aggregate itype.
-- These N_Range nodes are collected in Aggr_Range above.
+ --
-- Likewise collect in Aggr_Low & Aggr_High above the low and high
-- bounds of each index dimension. If, when collecting, two bounds
-- corresponding to the same dimension are static and found to differ,
procedure Collect_Aggr_Bounds (N : Node_Id; Dim : Pos) is
This_Range : constant Node_Id := Aggregate_Bounds (N);
- -- The aggregate range node of this specific sub-aggregate.
+ -- The aggregate range node of this specific sub-aggregate
This_Low : constant Node_Id := Low_Bound (Aggregate_Bounds (N));
This_High : constant Node_Id := High_Bound (Aggregate_Bounds (N));
- -- The aggregate bounds of this specific sub-aggregate.
+ -- The aggregate bounds of this specific sub-aggregate
Assoc : Node_Id;
Expr : Node_Id;
elsif Expr_Value (This_Low) /= Expr_Value (Aggr_Low (Dim)) then
Set_Raises_Constraint_Error (N);
- Error_Msg_N ("Sub-aggregate low bound mismatch?", N);
- Error_Msg_N ("Constraint_Error will be raised at run-time?",
- N);
+ Error_Msg_N ("sub-aggregate low bound mismatch?", N);
+ Error_Msg_N
+ ("\Constraint_Error will be raised at run-time?", N);
end if;
end if;
Expr_Value (This_High) /= Expr_Value (Aggr_High (Dim))
then
Set_Raises_Constraint_Error (N);
- Error_Msg_N ("Sub-aggregate high bound mismatch?", N);
- Error_Msg_N ("Constraint_Error will be raised at run-time?",
- N);
+ Error_Msg_N ("sub-aggregate high bound mismatch?", N);
+ Error_Msg_N
+ ("\Constraint_Error will be raised at run-time?", N);
end if;
end if;
end if;
-- the final itype of the overall aggregate
Index_Constraints : constant List_Id := New_List;
- -- The list of index constraints of the aggregate itype.
+ -- The list of index constraints of the aggregate itype
-- Start of processing for Array_Aggr_Subtype
Set_Parent (Index_Constraints, N);
Collect_Aggr_Bounds (N, 1);
- -- Build the list of constrained indices of our aggregate itype.
+ -- Build the list of constrained indices of our aggregate itype
for J in 1 .. Aggr_Dimension loop
Create_Index : declare
Index_Typ : Entity_Id;
begin
- -- Construct the Index subtype
+ -- Construct the Index subtype, and associate it with the range
+ -- construct that generates it.
- Index_Typ := Create_Itype (Subtype_Kind (Ekind (Index_Base)), N);
+ Index_Typ :=
+ Create_Itype (Subtype_Kind (Ekind (Index_Base)), Aggr_Range (J));
Set_Etype (Index_Typ, Index_Base);
Set_First_Index (Itype, First (Index_Constraints));
Set_Is_Constrained (Itype, True);
Set_Is_Internal (Itype, True);
- Init_Size_Align (Itype);
-- A simple optimization: purely positional aggregates of static
-- components should be passed to gigi unexpanded whenever possible,
-- and we must not generate a freeze node for the type, or else it
-- will appear incomplete to gigi.
- if Is_Packed (Itype) and then not In_Default_Expression
+ if Is_Packed (Itype) and then not In_Spec_Expression
and then Expander_Active
then
Freeze_Itype (Itype, N);
--------------------------------
procedure Check_Misspelled_Component
- (Elements : Elist_Id;
- Component : Node_Id)
+ (Elements : Elist_Id;
+ Component : Node_Id)
is
Max_Suggestions : constant := 2;
-- misspellings, these misspellings will be suggested as
-- possible correction.
- Get_Name_String (Chars (Component));
-
- declare
- S : constant String (1 .. Name_Len) :=
- Name_Buffer (1 .. Name_Len);
-
- begin
-
- Component_Elmt := First_Elmt (Elements);
-
- while Nr_Of_Suggestions <= Max_Suggestions
- and then Present (Component_Elmt)
- loop
+ Component_Elmt := First_Elmt (Elements);
+ while Nr_Of_Suggestions <= Max_Suggestions
+ and then Present (Component_Elmt)
+ loop
+ if Is_Bad_Spelling_Of
+ (Chars (Node (Component_Elmt)),
+ Chars (Component))
+ then
+ Nr_Of_Suggestions := Nr_Of_Suggestions + 1;
- Get_Name_String (Chars (Node (Component_Elmt)));
+ case Nr_Of_Suggestions is
+ when 1 => Suggestion_1 := Node (Component_Elmt);
+ when 2 => Suggestion_2 := Node (Component_Elmt);
+ when others => exit;
+ end case;
+ end if;
- if Is_Bad_Spelling_Of (Name_Buffer (1 .. Name_Len), S) then
- Nr_Of_Suggestions := Nr_Of_Suggestions + 1;
+ Next_Elmt (Component_Elmt);
+ end loop;
- case Nr_Of_Suggestions is
- when 1 => Suggestion_1 := Node (Component_Elmt);
- when 2 => Suggestion_2 := Node (Component_Elmt);
- when others => exit;
- end case;
- end if;
+ -- Report at most two suggestions
- Next_Elmt (Component_Elmt);
- end loop;
+ if Nr_Of_Suggestions = 1 then
+ Error_Msg_NE
+ ("\possible misspelling of&", Component, Suggestion_1);
- -- Report at most two suggestions
+ elsif Nr_Of_Suggestions = 2 then
+ Error_Msg_Node_2 := Suggestion_2;
+ Error_Msg_NE
+ ("\possible misspelling of& or&", Component, Suggestion_1);
+ end if;
+ end Check_Misspelled_Component;
- if Nr_Of_Suggestions = 1 then
- Error_Msg_NE ("\possible misspelling of&",
- Component, Suggestion_1);
+ ----------------------------------------
+ -- Check_Expr_OK_In_Limited_Aggregate --
+ ----------------------------------------
- elsif Nr_Of_Suggestions = 2 then
- Error_Msg_Node_2 := Suggestion_2;
- Error_Msg_NE ("\possible misspelling of& or&",
- Component, Suggestion_1);
+ procedure Check_Expr_OK_In_Limited_Aggregate (Expr : Node_Id) is
+ begin
+ if Is_Limited_Type (Etype (Expr))
+ and then Comes_From_Source (Expr)
+ and then not In_Instance_Body
+ then
+ if not OK_For_Limited_Init (Expr) then
+ Error_Msg_N ("initialization not allowed for limited types", Expr);
+ Explain_Limited_Type (Etype (Expr), Expr);
end if;
- end;
- end Check_Misspelled_Component;
+ end if;
+ end Check_Expr_OK_In_Limited_Aggregate;
----------------------------------------
-- Check_Static_Discriminated_Subtype --
end if;
Comp := First_Component (T);
-
while Present (Comp) loop
-
if Is_Scalar_Type (Etype (Comp)) then
null;
null;
elsif Is_Array_Type (Etype (Comp)) then
-
if Is_Bit_Packed_Array (Etype (Comp)) then
return;
end if;
Ind := First_Index (Etype (Comp));
-
while Present (Ind) loop
-
if Nkind (Ind) /= N_Range
or else Nkind (Low_Bound (Ind)) /= N_Integer_Literal
or else Nkind (High_Bound (Ind)) /= N_Integer_Literal
Next_Component (Comp);
end loop;
- -- On exit, all components have statically known sizes.
+ -- On exit, all components have statically known sizes
Set_Size_Known_At_Compile_Time (T);
end Check_Static_Discriminated_Subtype;
C := Get_String_Char (Str, J);
Set_Character_Literal_Name (C);
- C_Node := Make_Character_Literal (P, Name_Find, C);
+ C_Node :=
+ Make_Character_Literal (P,
+ Chars => Name_Find,
+ Char_Literal_Value => UI_From_CC (C));
Set_Etype (C_Node, Any_Character);
Append_To (Exprs, C_Node);
Error_Msg_CRT ("aggregate", N);
end if;
- if Is_Limited_Composite (Typ) then
- Error_Msg_N ("aggregate type cannot have limited component", N);
- Explain_Limited_Type (Typ, N);
+ -- Ada 2005 (AI-287): Limited aggregates allowed
- -- Ada0Y (AI-287): Limited aggregates allowed
-
- elsif Is_Limited_Type (Typ)
- and not Extensions_Allowed
- then
+ if Is_Limited_Type (Typ) and then Ada_Version < Ada_05 then
Error_Msg_N ("aggregate type cannot be limited", N);
Explain_Limited_Type (Typ, N);
-- First a special test, for the case of a positional aggregate
-- of characters which can be replaced by a string literal.
+
-- Do not perform this transformation if this was a string literal
-- to start with, whose components needed constraint checks, or if
-- the component type is non-static, because it will require those
-- checks and be transformed back into an aggregate.
if Number_Dimensions (Typ) = 1
- and then
- (Root_Type (Component_Type (Typ)) = Standard_Character
- or else
- Root_Type (Component_Type (Typ)) = Standard_Wide_Character)
+ and then Is_Standard_Character_Type (Component_Type (Typ))
and then No (Component_Associations (N))
and then not Is_Limited_Composite (Typ)
and then not Is_Private_Composite (Typ)
Expr := First (Expressions (N));
while Present (Expr) loop
- Store_String_Char (Char_Literal_Value (Expr));
+ Store_String_Char (UI_To_CC (Char_Literal_Value (Expr)));
Next (Expr);
end loop;
Aggr_Typ : constant Entity_Id := Etype (Typ);
-- This is the unconstrained array type, which is the type
- -- against which the aggregate is to be resoved. Typ itself
+ -- against which the aggregate is to be resolved. Typ itself
-- is the array type of the context which may not be the same
-- subtype as the subtype for the final aggregate.
-- in which the array aggregate occurs. If the context does not
-- permit it, or the aggregate type is unconstrained, an others
-- choice is not allowed.
- --
+
+ -- If expansion is disabled (generic context, or semantics-only
+ -- mode) actual subtypes cannot be constructed, and the type of
+ -- an object may be its unconstrained nominal type. However, if
+ -- the context is an assignment, we assume that "others" is
+ -- allowed, because the target of the assignment will have a
+ -- constrained subtype when fully compiled.
+
-- Note that there is no node for Explicit_Actual_Parameter.
-- To test for this context we therefore have to test for node
-- N_Parameter_Association which itself appears only if there is a
-- formal parameter. Consequently we also need to test for
-- N_Procedure_Call_Statement or N_Function_Call.
- Set_Etype (N, Aggr_Typ); -- may be overridden later on.
+ Set_Etype (N, Aggr_Typ); -- may be overridden later on
if Is_Constrained (Typ) and then
(Pkind = N_Assignment_Statement or else
Pkind = N_Procedure_Call_Statement or else
Pkind = N_Generic_Association or else
Pkind = N_Formal_Object_Declaration or else
- Pkind = N_Return_Statement or else
+ Pkind = N_Simple_Return_Statement or else
Pkind = N_Object_Declaration or else
Pkind = N_Component_Declaration or else
Pkind = N_Parameter_Specification or else
Component_Typ => Component_Type (Typ),
Others_Allowed => True);
+ elsif not Expander_Active
+ and then Pkind = N_Assignment_Statement
+ then
+ Aggr_Resolved :=
+ Resolve_Array_Aggregate
+ (N,
+ Index => First_Index (Aggr_Typ),
+ Index_Constr => First_Index (Typ),
+ Component_Typ => Component_Type (Typ),
+ Others_Allowed => True);
else
Aggr_Resolved :=
Resolve_Array_Aggregate
Set_Etype (N, Aggr_Subtyp);
end Array_Aggregate;
+ elsif Is_Private_Type (Typ)
+ and then Present (Full_View (Typ))
+ and then In_Inlined_Body
+ and then Is_Composite_Type (Full_View (Typ))
+ then
+ Resolve (N, Full_View (Typ));
+
else
Error_Msg_N ("illegal context for aggregate", N);
-
end if;
-- If we can determine statically that the evaluation of the
Index : Node_Id;
Index_Constr : Node_Id;
Component_Typ : Entity_Id;
- Others_Allowed : Boolean)
- return Boolean
+ Others_Allowed : Boolean) return Boolean
is
Loc : constant Source_Ptr := Sloc (N);
-- warning if not and sets the Raises_Constraint_Error Flag in N.
function Dynamic_Or_Null_Range (L, H : Node_Id) return Boolean;
- -- Returns True if range L .. H is dynamic or null.
+ -- Returns True if range L .. H is dynamic or null
procedure Get (Value : out Uint; From : Node_Id; OK : out Boolean);
-- Given expression node From, this routine sets OK to False if it
function Resolve_Aggr_Expr
(Expr : Node_Id;
- Single_Elmt : Boolean)
- return Boolean;
- -- Resolves aggregate expression Expr. Returs False if resolution
+ Single_Elmt : Boolean) return Boolean;
+ -- Resolves aggregate expression Expr. Returns False if resolution
-- fails. If Single_Elmt is set to False, the expression Expr may be
-- used to initialize several array aggregate elements (this can
-- happen for discrete choices such as "L .. H => Expr" or the others
if OK_BH and then OK_AH and then Val_BH < Val_AH then
Set_Raises_Constraint_Error (N);
Error_Msg_N ("upper bound out of range?", AH);
- Error_Msg_N ("Constraint_Error will be raised at run-time?", AH);
+ Error_Msg_N ("\Constraint_Error will be raised at run-time?", AH);
-- You need to set AH to BH or else in the case of enumerations
-- indices we will not be able to resolve the aggregate bounds.
Val_AL : Uint;
Val_AH : Uint;
- OK_L : Boolean;
- OK_H : Boolean;
+ OK_L : Boolean;
+ OK_H : Boolean;
+
OK_AL : Boolean;
- OK_AH : Boolean;
+ OK_AH : Boolean;
+ pragma Warnings (Off, OK_AL);
+ pragma Warnings (Off, OK_AH);
begin
if Raises_Constraint_Error (N)
if Range_Len < Len then
Set_Raises_Constraint_Error (N);
- Error_Msg_N ("Too many elements?", N);
- Error_Msg_N ("Constraint_Error will be raised at run-time?", N);
+ Error_Msg_N ("too many elements?", N);
+ Error_Msg_N ("\Constraint_Error will be raised at run-time?", N);
end if;
end Check_Length;
function Resolve_Aggr_Expr
(Expr : Node_Id;
- Single_Elmt : Boolean)
- return Boolean
+ Single_Elmt : Boolean) return Boolean
is
Nxt_Ind : constant Node_Id := Next_Index (Index);
Nxt_Ind_Constr : constant Node_Id := Next_Index (Index_Constr);
- -- Index is the current index corresponding to the expresion.
+ -- Index is the current index corresponding to the expression
Resolution_OK : Boolean := True;
- -- Set to False if resolution of the expression failed.
+ -- Set to False if resolution of the expression failed
begin
-- If the array type against which we are resolving the aggregate
if Is_Character_Type (Component_Typ)
and then No (Next_Index (Nxt_Ind))
- and then (Nkind (Expr) = N_String_Literal
- or else Nkind (Expr) = N_Operator_Symbol)
+ and then Nkind_In (Expr, N_String_Literal, N_Operator_Symbol)
then
-- A string literal used in a multidimensional array
-- aggregate in place of the final one-dimensional
-- aggregate must not be enclosed in parentheses.
if Paren_Count (Expr) /= 0 then
- Error_Msg_N ("No parenthesis allowed here", Expr);
+ Error_Msg_N ("no parenthesis allowed here", Expr);
end if;
Make_String_Into_Aggregate (Expr);
end if;
end if;
+ -- Ada 2005 (AI-231): Propagate the type to the nested aggregate.
+ -- Required to check the null-exclusion attribute (if present).
+ -- This value may be overridden later on.
+
+ Set_Etype (Expr, Etype (N));
+
Resolution_OK := Resolve_Array_Aggregate
(Expr, Nxt_Ind, Nxt_Ind_Constr, Component_Typ, Others_Allowed);
elsif Single_Elmt
or else not Expander_Active
- or else In_Default_Expression
+ or else In_Spec_Expression
then
Analyze_And_Resolve (Expr, Component_Typ);
+ Check_Expr_OK_In_Limited_Aggregate (Expr);
Check_Non_Static_Context (Expr);
Aggregate_Constraint_Checks (Expr, Component_Typ);
Check_Unset_Reference (Expr);
Choice : Node_Id;
Expr : Node_Id;
- Who_Cares : Node_Id;
+ Discard : Node_Id;
+ pragma Warnings (Off, Discard);
Aggr_Low : Node_Id := Empty;
Aggr_High : Node_Id := Empty;
- -- The actual low and high bounds of this sub-aggegate
+ -- The actual low and high bounds of this sub-aggregate
Choices_Low : Node_Id := Empty;
Choices_High : Node_Id := Empty;
-- The lowest and highest discrete choices values for a named aggregate
Nb_Elements : Uint := Uint_0;
- -- The number of elements in a positional aggegate
+ -- The number of elements in a positional aggregate
Others_Present : Boolean := False;
return Failure;
end if;
- if Ada_83
+ if Ada_Version = Ada_83
and then Assoc /= First (Component_Associations (N))
- and then (Nkind (Parent (N)) = N_Assignment_Statement
- or else
- Nkind (Parent (N)) = N_Object_Declaration)
+ and then Nkind_In (Parent (N), N_Assignment_Statement,
+ N_Object_Declaration)
then
Error_Msg_N
("(Ada 83) illegal context for OTHERS choice", N);
-- STEP 2: Process named components
if No (Expressions (N)) then
-
if Others_Present then
Case_Table_Size := Nb_Choices - 1;
else
-- in the current association.
begin
- -- STEP 2 (A): Check discrete choices validity.
+ -- STEP 2 (A): Check discrete choices validity
Assoc := First (Component_Associations (N));
while Present (Assoc) loop
-
Prev_Nb_Discrete_Choices := Nb_Discrete_Choices;
Choice := First (Choices (Assoc));
loop
return Failure;
end if;
+ -- Case of subtype indication
+
elsif Nkind (Choice) = N_Subtype_Indication then
Resolve_Discrete_Subtype_Indication (Choice, Index_Base);
Get_Index_Bounds (Choice, Low, High);
Check_Bounds (S_Low, S_High, Low, High);
- else -- Choice is a range or an expression
+ -- Case of range or expression
+
+ else
Resolve (Choice, Index_Base);
Check_Unset_Reference (Choice);
Check_Non_Static_Context (Choice);
if Etype (Choice) = Any_Type then
return Failure;
- -- If the discrete choice raises CE get its original bounds.
+ -- If the discrete choice raises CE get its original bounds
elsif Nkind (Choice) = N_Raise_Constraint_Error then
Set_Raises_Constraint_Error (N);
Next (Choice);
if No (Choice) then
+
-- Check if we have a single discrete choice and whether
-- this discrete choice specifies a single value.
end if;
end loop;
- -- Ada0Y (AI-287): In case of default initialized component
+ -- Ada 2005 (AI-231)
+
+ if Ada_Version >= Ada_05
+ and then Known_Null (Expression (Assoc))
+ then
+ Check_Can_Never_Be_Null (Etype (N), Expression (Assoc));
+ end if;
+
+ -- Ada 2005 (AI-287): In case of default initialized component
-- we delay the resolution to the expansion phase
if Box_Present (Assoc) then
- -- Ada0Y (AI-287): In case of default initialization of a
- -- component the expander will generate calls to the
- -- corresponding initialization subprogram.
+ -- Ada 2005 (AI-287): In case of default initialization
+ -- of a component the expander will generate calls to
+ -- the corresponding initialization subprogram.
- if Present (Base_Init_Proc (Etype (Component_Typ)))
- or else Has_Task (Base_Type (Component_Typ))
- then
- null;
- else
- Error_Msg_N
- ("(Ada 0Y): no value supplied for this component",
- Assoc);
- end if;
+ null;
elsif not Resolve_Aggr_Expr (Expression (Assoc),
Single_Elmt => Single_Choice)
return Failure;
elsif not Others_Present then
-
Hi_Val := Expr_Value (Table (J).Choice_Hi);
Lo_Val := Expr_Value (Table (J + 1).Choice_Lo);
Choices_High := Table (Nb_Discrete_Choices).Choice_Hi;
end if;
+ -- If Others is present, then bounds of aggregate come from the
+ -- index constraint (not the choices in the aggregate itself).
+
if Others_Present then
Get_Index_Bounds (Index_Constr, Aggr_Low, Aggr_High);
+ -- No others clause present
+
else
+ -- Special processing if others allowed and not present. This
+ -- means that the bounds of the aggregate come from the index
+ -- constraint (and the length must match).
+
+ if Others_Allowed then
+ Get_Index_Bounds (Index_Constr, Aggr_Low, Aggr_High);
+
+ -- If others allowed, and no others present, then the array
+ -- should cover all index values. If it does not, we will
+ -- get a length check warning, but there is two cases where
+ -- an additional warning is useful:
+
+ -- If we have no positional components, and the length is
+ -- wrong (which we can tell by others being allowed with
+ -- missing components), and the index type is an enumeration
+ -- type, then issue appropriate warnings about these missing
+ -- components. They are only warnings, since the aggregate
+ -- is fine, it's just the wrong length. We skip this check
+ -- for standard character types (since there are no literals
+ -- and it is too much trouble to concoct them), and also if
+ -- any of the bounds have not-known-at-compile-time values.
+
+ -- Another case warranting a warning is when the length is
+ -- right, but as above we have an index type that is an
+ -- enumeration, and the bounds do not match. This is a
+ -- case where dubious sliding is allowed and we generate
+ -- a warning that the bounds do not match.
+
+ if No (Expressions (N))
+ and then Nkind (Index) = N_Range
+ and then Is_Enumeration_Type (Etype (Index))
+ and then not Is_Standard_Character_Type (Etype (Index))
+ and then Compile_Time_Known_Value (Aggr_Low)
+ and then Compile_Time_Known_Value (Aggr_High)
+ and then Compile_Time_Known_Value (Choices_Low)
+ and then Compile_Time_Known_Value (Choices_High)
+ then
+ declare
+ ALo : constant Node_Id := Expr_Value_E (Aggr_Low);
+ AHi : constant Node_Id := Expr_Value_E (Aggr_High);
+ CLo : constant Node_Id := Expr_Value_E (Choices_Low);
+ CHi : constant Node_Id := Expr_Value_E (Choices_High);
+
+ Ent : Entity_Id;
+
+ begin
+ -- Warning case one, missing values at start/end. Only
+ -- do the check if the number of entries is too small.
+
+ if (Enumeration_Pos (CHi) - Enumeration_Pos (CLo))
+ <
+ (Enumeration_Pos (AHi) - Enumeration_Pos (ALo))
+ then
+ Error_Msg_N
+ ("missing index value(s) in array aggregate?", N);
+
+ -- Output missing value(s) at start
+
+ if Chars (ALo) /= Chars (CLo) then
+ Ent := Prev (CLo);
+
+ if Chars (ALo) = Chars (Ent) then
+ Error_Msg_Name_1 := Chars (ALo);
+ Error_Msg_N ("\ %?", N);
+ else
+ Error_Msg_Name_1 := Chars (ALo);
+ Error_Msg_Name_2 := Chars (Ent);
+ Error_Msg_N ("\ % .. %?", N);
+ end if;
+ end if;
+
+ -- Output missing value(s) at end
+
+ if Chars (AHi) /= Chars (CHi) then
+ Ent := Next (CHi);
+
+ if Chars (AHi) = Chars (Ent) then
+ Error_Msg_Name_1 := Chars (Ent);
+ Error_Msg_N ("\ %?", N);
+ else
+ Error_Msg_Name_1 := Chars (Ent);
+ Error_Msg_Name_2 := Chars (AHi);
+ Error_Msg_N ("\ % .. %?", N);
+ end if;
+ end if;
+
+ -- Warning case 2, dubious sliding. The First_Subtype
+ -- test distinguishes between a constrained type where
+ -- sliding is not allowed (so we will get a warning
+ -- later that Constraint_Error will be raised), and
+ -- the unconstrained case where sliding is permitted.
+
+ elsif (Enumeration_Pos (CHi) - Enumeration_Pos (CLo))
+ =
+ (Enumeration_Pos (AHi) - Enumeration_Pos (ALo))
+ and then Chars (ALo) /= Chars (CLo)
+ and then
+ not Is_Constrained (First_Subtype (Etype (N)))
+ then
+ Error_Msg_N
+ ("bounds of aggregate do not match target?", N);
+ end if;
+ end;
+ end if;
+ end if;
+
+ -- If no others, aggregate bounds come from aggregate
+
Aggr_Low := Choices_Low;
Aggr_High := Choices_High;
end if;
while Present (Expr) loop
Nb_Elements := Nb_Elements + 1;
+ -- Ada 2005 (AI-231)
+
+ if Ada_Version >= Ada_05
+ and then Known_Null (Expr)
+ then
+ Check_Can_Never_Be_Null (Etype (N), Expr);
+ end if;
+
if not Resolve_Aggr_Expr (Expr, Single_Elmt => True) then
return Failure;
end if;
if Others_Present then
Assoc := Last (Component_Associations (N));
- -- Ada0Y (AI-287): In case of default initialized component
+ -- Ada 2005 (AI-231)
+
+ if Ada_Version >= Ada_05
+ and then Known_Null (Assoc)
+ then
+ Check_Can_Never_Be_Null (Etype (N), Expression (Assoc));
+ end if;
+
+ -- Ada 2005 (AI-287): In case of default initialized component
-- we delay the resolution to the expansion phase.
if Box_Present (Assoc) then
- -- Ada0Y (AI-287): In case of default initialization of a
- -- component the expander will generate calls to the
- -- corresponding initialization subprogram.
+ -- Ada 2005 (AI-287): In case of default initialization
+ -- of a component the expander will generate calls to
+ -- the corresponding initialization subprogram.
- if Present (Base_Init_Proc (Etype (Component_Typ))) then
- null;
- else
- Error_Msg_N
- ("(Ada 0Y): no value supplied for these components",
- Assoc);
- end if;
+ null;
elsif not Resolve_Aggr_Expr (Expression (Assoc),
Single_Elmt => False)
else
if Others_Allowed then
- Get_Index_Bounds (Index_Constr, Aggr_Low, Who_Cares);
+ Get_Index_Bounds (Index_Constr, Aggr_Low, Discard);
else
Aggr_Low := Index_Typ_Low;
end if;
Check_Length (Aggr_Low, Aggr_High, Nb_Elements);
Check_Length (Index_Typ_Low, Index_Typ_High, Nb_Elements);
Check_Length (Index_Base_Low, Index_Base_High, Nb_Elements);
-
end if;
if Raises_Constraint_Error (Aggr_Low)
-- Do not duplicate Aggr_High if Aggr_High = Aggr_Low + Nb_Elements
-- since the addition node returned by Add is not yet analyzed. Attach
-- to tree and analyze first. Reset analyzed flag to insure it will get
- -- analyzed when it is a literal bound whose type must be properly
- -- set.
+ -- analyzed when it is a literal bound whose type must be properly set.
if Others_Present or else Nb_Discrete_Choices > 0 then
Aggr_High := Duplicate_Subexpr (Aggr_High);
I : Interp_Index;
It : Interp;
+ function Valid_Limited_Ancestor (Anc : Node_Id) return Boolean;
+ -- If the type is limited, verify that the ancestor part is a legal
+ -- expression (aggregate or function call, including 'Input)) that
+ -- does not require a copy, as specified in 7.5 (2).
+
function Valid_Ancestor_Type return Boolean;
-- Verify that the type of the ancestor part is a non-private ancestor
- -- of the expected type.
+ -- of the expected type, which must be a type extension.
+
+ ----------------------------
+ -- Valid_Limited_Ancestor --
+ ----------------------------
+
+ function Valid_Limited_Ancestor (Anc : Node_Id) return Boolean is
+ begin
+ if Is_Entity_Name (Anc)
+ and then Is_Type (Entity (Anc))
+ then
+ return True;
+
+ elsif Nkind_In (Anc, N_Aggregate, N_Function_Call) then
+ return True;
+
+ elsif Nkind (Anc) = N_Attribute_Reference
+ and then Attribute_Name (Anc) = Name_Input
+ then
+ return True;
+
+ elsif
+ Nkind (Anc) = N_Qualified_Expression
+ then
+ return Valid_Limited_Ancestor (Expression (Anc));
+
+ else
+ return False;
+ end if;
+ end Valid_Limited_Ancestor;
-------------------------
-- Valid_Ancestor_Type --
Imm_Type := Etype (Base_Type (Imm_Type));
end loop;
- if Etype (Imm_Type) /= Base_Type (A_Type) then
+ if not Is_Derived_Type (Base_Type (Typ))
+ or else Etype (Imm_Type) /= Base_Type (A_Type)
+ then
Error_Msg_NE ("expect ancestor type of &", A, Typ);
return False;
else
elsif Is_Limited_Type (Typ) then
- -- Ada0Y (AI-287): Limited aggregates are allowed
+ -- Ada 2005 (AI-287): Limited aggregates are allowed
- if Extensions_Allowed then
- null;
- else
+ if Ada_Version < Ada_05 then
Error_Msg_N ("aggregate type cannot be limited", N);
Explain_Limited_Type (Typ, N);
return;
+
+ elsif Valid_Limited_Ancestor (A) then
+ null;
+
+ else
+ Error_Msg_N
+ ("limited ancestor part must be aggregate or function call", A);
end if;
elsif Is_Class_Wide_Type (Typ) then
elsif Nkind (A) /= N_Aggregate then
if Is_Overloaded (A) then
A_Type := Any_Type;
- Get_First_Interp (A, I, It);
+ Get_First_Interp (A, I, It);
while Present (It.Typ) loop
-
if Is_Tagged_Type (It.Typ)
and then not Is_Limited_Type (It.Typ)
then
-- less which ancestor). It is not possible to determine the
-- required components of the extension part.
+ -- This check implements AI-306, which in fact was motivated
+ -- by an ACT query to the ARG after this test was added.
+
Error_Msg_N ("ancestor part must be statically tagged", A);
else
Resolve_Record_Aggregate (N, Typ);
end if;
else
- Error_Msg_N (" No unique type for this aggregate", A);
+ Error_Msg_N ("no unique type for this aggregate", A);
end if;
end Resolve_Extension_Aggregate;
------------------------------
procedure Resolve_Record_Aggregate (N : Node_Id; Typ : Entity_Id) is
+ Assoc : Node_Id;
+ -- N_Component_Association node belonging to the input aggregate N
+
+ Expr : Node_Id;
+ Positional_Expr : Node_Id;
+ Component : Entity_Id;
+ Component_Elmt : Elmt_Id;
+
+ Components : constant Elist_Id := New_Elmt_List;
+ -- Components is the list of the record components whose value must
+ -- be provided in the aggregate. This list does include discriminants.
+
New_Assoc_List : constant List_Id := New_List;
New_Assoc : Node_Id;
-- New_Assoc_List is the newly built list of N_Component_Association
--
-- This variable is updated as a side effect of function Get_Value
- Mbox_Present : Boolean := False;
- Others_Mbox : Boolean := False;
- -- Ada0Y (AI-287): Variables used in case of default initialization to
- -- provide a functionality similar to Others_Etype. Mbox_Present
+ Is_Box_Present : Boolean := False;
+ Others_Box : Boolean := False;
+ -- Ada 2005 (AI-287): Variables used in case of default initialization
+ -- to provide a functionality similar to Others_Etype. Box_Present
-- indicates that the component takes its default initialization;
- -- Others_Mbox indicates that at least one component takes its default
+ -- Others_Box indicates that at least one component takes its default
-- initialization. Similar to Others_Etype, they are also updated as a
-- side effect of function Get_Value.
procedure Add_Association
- (Component : Entity_Id;
- Expr : Node_Id;
- Box_Present : Boolean := False);
+ (Component : Entity_Id;
+ Expr : Node_Id;
+ Is_Box_Present : Boolean := False);
-- Builds a new N_Component_Association node which associates
-- Component to expression Expr and adds it to the new association
-- list New_Assoc_List being built.
---------------------
procedure Add_Association
- (Component : Entity_Id;
- Expr : Node_Id;
- Box_Present : Boolean := False)
+ (Component : Entity_Id;
+ Expr : Node_Id;
+ Is_Box_Present : Boolean := False)
is
Choice_List : constant List_Id := New_List;
New_Assoc : Node_Id;
Make_Component_Association (Sloc (Expr),
Choices => Choice_List,
Expression => Expr,
- Box_Present => Box_Present);
+ Box_Present => Is_Box_Present);
Append (New_Assoc, New_Assoc_List);
end Add_Association;
return True;
end if;
- -- Now look to see if Discr was specified in the ancestor part.
-
- Orig_Discr := Original_Record_Component (Discr);
- D := First_Discriminant (Ancestor_Typ);
+ -- Now look to see if Discr was specified in the ancestor part
if Ancestor_Is_Subtyp then
D_Val := First_Elmt (Discriminant_Constraint (Entity (Ancestor)));
end if;
+ Orig_Discr := Original_Record_Component (Discr);
+
+ D := First_Discriminant (Ancestor_Typ);
while Present (D) loop
- -- If Ancestor has already specified Disc value than
- -- insert its value in the final aggregate.
+
+ -- If Ancestor has already specified Disc value than insert its
+ -- value in the final aggregate.
if Original_Record_Component (D) = Orig_Discr then
if Ancestor_Is_Subtyp then
Expr : Node_Id := Empty;
Selector_Name : Node_Id;
- procedure Check_Non_Limited_Type;
- -- Relax check to allow the default initialization of limited types.
- -- For example:
- -- record
- -- C : Lim := (..., others => <>);
- -- end record;
-
- ----------------------------
- -- Check_Non_Limited_Type --
- ----------------------------
-
- procedure Check_Non_Limited_Type is
- begin
- if Is_Limited_Type (Etype (Compon))
- and then Comes_From_Source (Compon)
- and then not In_Instance_Body
- then
- -- Ada0Y (AI-287): Limited aggregates are allowed
-
- if Extensions_Allowed
- and then Present (Expression (Assoc))
- and then Nkind (Expression (Assoc)) = N_Aggregate
- then
- null;
- else
- Error_Msg_N
- ("initialization not allowed for limited types", N);
- Explain_Limited_Type (Etype (Compon), Compon);
- end if;
-
- end if;
- end Check_Non_Limited_Type;
-
- -- Start of processing for Get_Value
-
begin
- Mbox_Present := False;
+ Is_Box_Present := False;
if Present (From) then
Assoc := First (From);
-- indispensable otherwise, because each one must be
-- expanded individually to preserve side-effects.
- -- Ada0Y (AI-287): In case of default initialization of
- -- components, we duplicate the corresponding default
- -- expression (from the record type declaration).
+ -- Ada 2005 (AI-287): In case of default initialization
+ -- of components, we duplicate the corresponding default
+ -- expression (from the record type declaration). The
+ -- copy must carry the sloc of the association (not the
+ -- original expression) to prevent spurious elaboration
+ -- checks when the default includes function calls.
if Box_Present (Assoc) then
- Others_Mbox := True;
- Mbox_Present := True;
+ Others_Box := True;
+ Is_Box_Present := True;
if Expander_Active then
- return New_Copy_Tree (Expression (Parent (Compon)));
+ return
+ New_Copy_Tree
+ (Expression (Parent (Compon)),
+ New_Sloc => Sloc (Assoc));
else
return Expression (Parent (Compon));
end if;
else
- Check_Non_Limited_Type;
-
if Present (Others_Etype) and then
Base_Type (Others_Etype) /= Base_Type (Etype
(Compon))
elsif Chars (Compon) = Chars (Selector_Name) then
if No (Expr) then
+ -- Ada 2005 (AI-231)
+
+ if Ada_Version >= Ada_05
+ and then Known_Null (Expression (Assoc))
+ then
+ Check_Can_Never_Be_Null (Compon, Expression (Assoc));
+ end if;
+
-- We need to duplicate the expression when several
-- components are grouped together with a "|" choice.
-- For instance "filed1 | filed2 => Expr"
+ -- Ada 2005 (AI-287)
+
if Box_Present (Assoc) then
- Mbox_Present := True;
+ Is_Box_Present := True;
-- Duplicate the default expression of the component
- -- from the record type declaration
+ -- from the record type declaration, so a new copy
+ -- can be attached to the association.
- if Present (Next (Selector_Name)) then
- Expr := New_Copy_Tree
- (Expression (Parent (Compon)));
- else
- Expr := Expression (Parent (Compon));
- end if;
+ -- Note that we always copy the default expression,
+ -- even when the association has a single choice, in
+ -- order to create a proper association for the
+ -- expanded aggregate.
- else
- Check_Non_Limited_Type;
+ Expr := New_Copy_Tree (Expression (Parent (Compon)));
+ else
if Present (Next (Selector_Name)) then
Expr := New_Copy_Tree (Expression (Assoc));
else
function Has_Expansion_Delayed (Expr : Node_Id) return Boolean is
Kind : constant Node_Kind := Nkind (Expr);
-
begin
- return ((Kind = N_Aggregate
- or else Kind = N_Extension_Aggregate)
+ return (Nkind_In (Kind, N_Aggregate, N_Extension_Aggregate)
and then Present (Etype (Expr))
and then Is_Record_Type (Etype (Expr))
and then Expansion_Delayed (Expr))
-
or else (Kind = N_Qualified_Expression
and then Has_Expansion_Delayed (Expression (Expr)));
end Has_Expansion_Delayed;
Expr_Type := Etype (Component);
-- Otherwise we have to pick up the new type of the component from
- -- the new costrained subtype of the aggregate. In fact components
+ -- the new constrained subtype of the aggregate. In fact components
-- which are of a composite type might be constrained by a
-- discriminant, and we want to resolve Expr against the subtype were
-- all discriminant occurrences are replaced with their actual value.
-- For each range in an array type where a discriminant has been
-- replaced with the constraint, check that this range is within
- -- the range of the base type. This checks is done in the
- -- init proc for regular objects, but has to be done here for
+ -- the range of the base type. This checks is done in the init
+ -- proc for regular objects, but has to be done here for
-- aggregates since no init proc is called for them.
if Is_Array_Type (Expr_Type) then
declare
- Index : Node_Id := First_Index (Expr_Type);
- -- Range of the current constrained index in the array.
+ Index : Node_Id;
+ -- Range of the current constrained index in the array
- Orig_Index : Node_Id := First_Index (Etype (Component));
+ Orig_Index : Node_Id := First_Index (Etype (Component));
-- Range corresponding to the range Index above in the
-- original unconstrained record type. The bounds of this
-- range may be governed by discriminants.
-- range checks.
begin
+ Index := First_Index (Expr_Type);
while Present (Index) loop
if Depends_On_Discriminant (Orig_Index) then
Apply_Range_Check (Index, Etype (Unconstr_Index));
end if;
Analyze_And_Resolve (Expr, Expr_Type);
+ Check_Expr_OK_In_Limited_Aggregate (Expr);
Check_Non_Static_Context (Expr);
Check_Unset_Reference (Expr);
end if;
end Resolve_Aggr_Expr;
- -- Resolve_Record_Aggregate local variables
-
- Assoc : Node_Id;
- -- N_Component_Association node belonging to the input aggregate N
-
- Expr : Node_Id;
- Positional_Expr : Node_Id;
- Component : Entity_Id;
- Component_Elmt : Elmt_Id;
-
- Components : constant Elist_Id := New_Elmt_List;
- -- Components is the list of the record components whose value must
- -- be provided in the aggregate. This list does include discriminants.
-
-- Start of processing for Resolve_Record_Aggregate
begin
-- STEP 1: abstract type and null record verification
- if Is_Abstract (Typ) then
+ if Is_Abstract_Type (Typ) then
Error_Msg_N ("type of aggregate cannot be abstract", N);
end if;
Error_Msg_N ("OTHERS must appear last in an aggregate",
Selector_Name);
return;
+
+ -- (Ada2005): If this is an association with a box,
+ -- indicate that the association need not represent
+ -- any component.
+
+ elsif Box_Present (Assoc) then
+ Others_Box := True;
end if;
else
while Present (Discrim) and then Present (Positional_Expr) loop
if Discr_Present (Discrim) then
Resolve_Aggr_Expr (Positional_Expr, Discrim);
+
+ -- Ada 2005 (AI-231)
+
+ if Ada_Version >= Ada_05
+ and then Known_Null (Positional_Expr)
+ then
+ Check_Can_Never_Be_Null (Discrim, Positional_Expr);
+ end if;
+
Next (Positional_Expr);
end if;
-- in sem_ch3 and here rather than have a copy of the code which is a
-- maintenance nightmare.
- -- ??? Performace WARNING. The current implementation creates a new
+ -- ??? Performance WARNING. The current implementation creates a new
-- itype for all aggregates whose base type is discriminated.
-- This means that for record aggregates nested inside an array
-- aggregate we will create a new itype for each record aggregate
- -- if the array cmponent type has discriminants. For large aggregates
+ -- if the array component type has discriminants. For large aggregates
-- this may be a problem. What should be done in this case is
-- to reuse itypes as much as possible.
Subtype_Indication => Indic);
Set_Parent (Subtyp_Decl, Parent (N));
- -- Itypes must be analyzed with checks off (see itypes.ads).
+ -- Itypes must be analyzed with checks off (see itypes.ads)
Analyze (Subtyp_Decl, Suppress => All_Checks);
else
Root_Typ := Root_Type (Typ);
- if Nkind (Parent (Base_Type (Root_Typ)))
- = N_Private_Type_Declaration
+ if Nkind (Parent (Base_Type (Root_Typ))) =
+ N_Private_Type_Declaration
then
Error_Msg_NE
("type of aggregate has private ancestor&!",
Parent_Typ := Base_Type (Typ);
while Parent_Typ /= Root_Typ loop
-
Prepend_Elmt (Parent_Typ, To => Parent_Typ_List);
Parent_Typ := Etype (Parent_Typ);
end if;
end loop;
- -- Now collect components from all other ancestors.
+ -- Now collect components from all other ancestors
Parent_Elmt := First_Elmt (Parent_Typ_List);
while Present (Parent_Elmt) loop
Component := Node (Component_Elmt);
Resolve_Aggr_Expr (Positional_Expr, Component);
+ -- Ada 2005 (AI-231)
+
+ if Ada_Version >= Ada_05
+ and then Known_Null (Positional_Expr)
+ then
+ Check_Can_Never_Be_Null (Component, Positional_Expr);
+ end if;
+
if Present (Get_Value (Component, Component_Associations (N))) then
Error_Msg_NE
("more than one value supplied for Component &", N, Component);
Component := Node (Component_Elmt);
Expr := Get_Value (Component, Component_Associations (N), True);
- if Mbox_Present and then Is_Limited_Type (Etype (Component)) then
+ -- Note: The previous call to Get_Value sets the value of the
+ -- variable Is_Box_Present.
+
+ -- Ada 2005 (AI-287): Handle components with default initialization.
+ -- Note: This feature was originally added to Ada 2005 for limited
+ -- but it was finally allowed with any type.
+
+ if Is_Box_Present then
+ Check_Box_Component : declare
+ Ctyp : constant Entity_Id := Etype (Component);
+
+ begin
+ -- If there is a default expression for the aggregate, copy
+ -- it into a new association.
+
+ -- If the component has an initialization procedure (IP) we
+ -- pass the component to the expander, which will generate
+ -- the call to such IP.
+
+ -- If the component has discriminants, their values must
+ -- be taken from their subtype. This is indispensable for
+ -- constraints that are given by the current instance of an
+ -- enclosing type, to allow the expansion of the aggregate
+ -- to replace the reference to the current instance by the
+ -- target object of the aggregate.
+
+ if Present (Parent (Component))
+ and then
+ Nkind (Parent (Component)) = N_Component_Declaration
+ and then Present (Expression (Parent (Component)))
+ then
+ Expr :=
+ New_Copy_Tree (Expression (Parent (Component)),
+ New_Sloc => Sloc (N));
+
+ Add_Association
+ (Component => Component,
+ Expr => Expr);
+ Set_Has_Self_Reference (N);
+
+ -- A box-defaulted access component gets the value null. Also
+ -- included are components of private types whose underlying
+ -- type is an access type. In either case set the type of the
+ -- literal, for subsequent use in semantic checks.
+
+ elsif Present (Underlying_Type (Ctyp))
+ and then Is_Access_Type (Underlying_Type (Ctyp))
+ then
+ if not Is_Private_Type (Ctyp) then
+ Expr := Make_Null (Sloc (N));
+ Set_Etype (Expr, Ctyp);
+ Add_Association
+ (Component => Component,
+ Expr => Expr);
+
+ -- If the component's type is private with an access type as
+ -- its underlying type then we have to create an unchecked
+ -- conversion to satisfy type checking.
+
+ else
+ declare
+ Qual_Null : constant Node_Id :=
+ Make_Qualified_Expression (Sloc (N),
+ Subtype_Mark =>
+ New_Occurrence_Of
+ (Underlying_Type (Ctyp), Sloc (N)),
+ Expression => Make_Null (Sloc (N)));
+
+ Convert_Null : constant Node_Id :=
+ Unchecked_Convert_To
+ (Ctyp, Qual_Null);
+
+ begin
+ Analyze_And_Resolve (Convert_Null, Ctyp);
+ Add_Association
+ (Component => Component, Expr => Convert_Null);
+ end;
+ end if;
+
+ elsif Has_Non_Null_Base_Init_Proc (Ctyp)
+ or else not Expander_Active
+ then
+ if Is_Record_Type (Ctyp)
+ and then Has_Discriminants (Ctyp)
+ then
+ -- We build a partially initialized aggregate with the
+ -- values of the discriminants and box initialization
+ -- for the rest, if other components are present.
+
+ declare
+ Loc : constant Source_Ptr := Sloc (N);
+ Assoc : Node_Id;
+ Discr : Entity_Id;
+ Discr_Elmt : Elmt_Id;
+ Discr_Val : Node_Id;
+ Expr : Node_Id;
+
+ begin
+ Expr := Make_Aggregate (Loc, New_List, New_List);
+
+ Discr_Elmt :=
+ First_Elmt (Discriminant_Constraint (Ctyp));
+ while Present (Discr_Elmt) loop
+ Discr_Val := Node (Discr_Elmt);
+
+ -- The constraint may be given by a discriminant
+ -- of the enclosing type, in which case we have
+ -- to retrieve its value, which is part of the
+ -- current aggregate.
+
+ if Is_Entity_Name (Discr_Val)
+ and then
+ Ekind (Entity (Discr_Val)) = E_Discriminant
+ then
+ Discr := Entity (Discr_Val);
+
+ Assoc := First (New_Assoc_List);
+ while Present (Assoc) loop
+ if Present
+ (Entity (First (Choices (Assoc))))
+ and then
+ Entity (First (Choices (Assoc))) = Discr
+ then
+ Discr_Val := Expression (Assoc);
+ exit;
+ end if;
+ Next (Assoc);
+ end loop;
+ end if;
+
+ Append
+ (New_Copy_Tree (Discr_Val), Expressions (Expr));
+
+ -- If the discriminant constraint is a current
+ -- instance, mark the current aggregate so that
+ -- the self-reference can be expanded later.
+
+ if Nkind (Discr_Val) = N_Attribute_Reference
+ and then Is_Entity_Name (Prefix (Discr_Val))
+ and then Is_Type (Entity (Prefix (Discr_Val)))
+ and then Etype (N) = Entity (Prefix (Discr_Val))
+ then
+ Set_Has_Self_Reference (N);
+ end if;
+
+ Next_Elmt (Discr_Elmt);
+ end loop;
+
+ declare
+ Comp : Entity_Id;
+
+ begin
+ -- Look for a component that is not a discriminant
+ -- before creating an others box association.
+
+ Comp := First_Component (Ctyp);
+ while Present (Comp) loop
+ if Ekind (Comp) = E_Component then
+ Append
+ (Make_Component_Association (Loc,
+ Choices =>
+ New_List (Make_Others_Choice (Loc)),
+ Expression => Empty,
+ Box_Present => True),
+ Component_Associations (Expr));
+ exit;
+ end if;
+
+ Next_Component (Comp);
+ end loop;
+ end;
+
+ Add_Association
+ (Component => Component,
+ Expr => Expr);
+ end;
+
+ else
+ Add_Association
+ (Component => Component,
+ Expr => Empty,
+ Is_Box_Present => True);
+ end if;
- -- Ada0Y (AI-287): In case of default initialization of a limited
- -- component we pass the limited component to the expander. The
- -- expander will generate calls to the corresponding initiali-
- -- zation subprograms.
+ -- Otherwise we only need to resolve the expression if the
+ -- component has partially initialized values (required to
+ -- expand the corresponding assignments and run-time checks).
- Add_Association
- (Component => Component,
- Expr => Empty,
- Box_Present => True);
+ elsif Present (Expr)
+ and then Is_Partially_Initialized_Type (Ctyp)
+ then
+ Resolve_Aggr_Expr (Expr, Component);
+ end if;
+ end Check_Box_Component;
elsif No (Expr) then
- Error_Msg_NE ("no value supplied for component &!", N, Component);
+
+ -- Ignore hidden components associated with the position of the
+ -- interface tags: these are initialized dynamically.
+
+ if not Present (Related_Type (Component)) then
+ Error_Msg_NE
+ ("no value supplied for component &!", N, Component);
+ end if;
+
else
Resolve_Aggr_Expr (Expr, Component);
end if;
Selectr : Node_Id;
-- Selector name
- Typech : Entity_Id;
+ Typech : Entity_Id;
-- Type of first component in choice list
begin
if Nkind (Selectr) = N_Others_Choice then
- -- Ada0Y (AI-287): others choice may have expression or mbox
+ -- Ada 2005 (AI-287): others choice may have expression or box
if No (Others_Etype)
- and then not Others_Mbox
+ and then not Others_Box
then
Error_Msg_N
("OTHERS must represent at least one component", Selectr);
end loop;
-- If no association, this is not a legal component of
- -- of the type in question, except if this is an internal
- -- component supplied by a previous expansion.
+ -- of the type in question, except if its association
+ -- is provided with a box.
if No (New_Assoc) then
if Box_Present (Parent (Selectr)) then
- null;
+
+ -- This may still be a bogus component with a box. Scan
+ -- list of components to verify that a component with
+ -- that name exists.
+
+ declare
+ C : Entity_Id;
+
+ begin
+ C := First_Component (Typ);
+ while Present (C) loop
+ if Chars (C) = Chars (Selectr) then
+
+ -- If the context is an extension aggregate,
+ -- the component must not be inherited from
+ -- the ancestor part of the aggregate.
+
+ if Nkind (N) /= N_Extension_Aggregate
+ or else
+ Scope (Original_Record_Component (C)) /=
+ Etype (Ancestor_Part (N))
+ then
+ exit;
+ end if;
+ end if;
+
+ Next_Component (C);
+ end loop;
+
+ if No (C) then
+ Error_Msg_Node_2 := Typ;
+ Error_Msg_N ("& is not a component of}", Selectr);
+ end if;
+ end;
elsif Chars (Selectr) /= Name_uTag
and then Chars (Selectr) /= Name_uParent
then
if not Has_Discriminants (Typ) then
Error_Msg_Node_2 := Typ;
- Error_Msg_N
- ("& is not a component of}",
- Selectr);
+ Error_Msg_N ("& is not a component of}", Selectr);
else
Error_Msg_N
("& is not a component of the aggregate subtype",
end Step_8;
end Resolve_Record_Aggregate;
+ -----------------------------
+ -- Check_Can_Never_Be_Null --
+ -----------------------------
+
+ procedure Check_Can_Never_Be_Null (Typ : Entity_Id; Expr : Node_Id) is
+ Comp_Typ : Entity_Id;
+
+ begin
+ pragma Assert
+ (Ada_Version >= Ada_05
+ and then Present (Expr)
+ and then Known_Null (Expr));
+
+ case Ekind (Typ) is
+ when E_Array_Type =>
+ Comp_Typ := Component_Type (Typ);
+
+ when E_Component |
+ E_Discriminant =>
+ Comp_Typ := Etype (Typ);
+
+ when others =>
+ return;
+ end case;
+
+ if Can_Never_Be_Null (Comp_Typ) then
+
+ -- Here we know we have a constraint error. Note that we do not use
+ -- Apply_Compile_Time_Constraint_Error here to the Expr, which might
+ -- seem the more natural approach. That's because in some cases the
+ -- components are rewritten, and the replacement would be missed.
+
+ Insert_Action
+ (Compile_Time_Constraint_Error
+ (Expr,
+ "(Ada 2005) null not allowed in null-excluding component?"),
+ Make_Raise_Constraint_Error (Sloc (Expr),
+ Reason => CE_Access_Check_Failed));
+
+ -- Set proper type for bogus component (why is this needed???)
+
+ Set_Etype (Expr, Comp_Typ);
+ Set_Analyzed (Expr);
+ end if;
+ end Check_Can_Never_Be_Null;
+
---------------------
-- Sort_Case_Table --
---------------------
begin
K := L;
-
while K /= U loop
T := Case_Table (K + 1);
- J := K + 1;
+ J := K + 1;
while J /= L
and then Expr_Value (Case_Table (J - 1).Choice_Lo) >
Expr_Value (T.Choice_Lo)