-- --
-- B o d y --
-- --
--- Copyright (C) 1992-2005 Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2007, 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, 51 Franklin Street, Fifth Floor, --
--- Boston, MA 02110-1301, 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 Ada.Characters.Latin_1; use Ada.Characters.Latin_1;
with Atree; use Atree;
+with Casing; use Casing;
with Checks; use Checks;
with Einfo; use Einfo;
with Errout; use Errout;
with Eval_Fat;
+with Exp_Dist; use Exp_Dist;
with Exp_Util; use Exp_Util;
with Expander; use Expander;
with Freeze; use Freeze;
with Lib; use Lib;
with Lib.Xref; use Lib.Xref;
-with Namet; use Namet;
with Nlists; use Nlists;
with Nmake; use Nmake;
with Opt; use Opt;
with Stand; use Stand;
with Sinfo; use Sinfo;
with Sinput; use Sinput;
-with Snames; use Snames;
-with Stand;
with Stringt; use Stringt;
+with Style;
+with Stylesw; use Stylesw;
with Targparm; use Targparm;
with Ttypes; use Ttypes;
with Ttypef; use Ttypef;
-- trouble with cascaded errors.
-- The following array is the list of attributes defined in the Ada 83 RM
+ -- that are not included in Ada 95, but still get recognized in GNAT.
Attribute_83 : constant Attribute_Class_Array := Attribute_Class_Array'(
Attribute_Address |
Attribute_Width => True,
others => False);
+ -- The following array is the list of attributes defined in the Ada 2005
+ -- RM which are not defined in Ada 95. These are recognized in Ada 95 mode,
+ -- but in Ada 95 they are considered to be implementation defined.
+
+ Attribute_05 : constant Attribute_Class_Array := Attribute_Class_Array'(
+ Attribute_Machine_Rounding |
+ Attribute_Priority |
+ Attribute_Stream_Size |
+ Attribute_Wide_Wide_Width => True,
+ others => False);
+
+ -- The following array contains all attributes that imply a modification
+ -- of their prefixes or result in an access value. Such prefixes can be
+ -- considered as lvalues.
+
+ Attribute_Name_Implies_Lvalue_Prefix : constant Attribute_Class_Array :=
+ Attribute_Class_Array'(
+ Attribute_Access |
+ Attribute_Address |
+ Attribute_Input |
+ Attribute_Read |
+ Attribute_Unchecked_Access |
+ Attribute_Unrestricted_Access => True,
+ others => False);
+
-----------------------
-- Local_Subprograms --
-----------------------
-- no arguments is used when the caller has already generated the
-- required error messages.
+ procedure Error_Attr_P (Msg : String);
+ pragma No_Return (Error_Attr);
+ -- Like Error_Attr, but error is posted at the start of the prefix
+
procedure Standard_Attribute (Val : Int);
-- Used to process attributes whose prefix is package Standard which
-- yield values of type Universal_Integer. The attribute reference
-- the type of the prefix. If prefix is overloaded, so it the
-- node itself. The result is stored in Acc_Type.
+ function OK_Self_Reference return Boolean;
+ -- An access reference whose prefix is a type can legally appear
+ -- within an aggregate, where it is obtained by expansion of
+ -- a defaulted aggregate. The enclosing aggregate that contains
+ -- the self-referenced is flagged so that the self-reference can
+ -- be expanded into a reference to the target object (see exp_aggr).
+
------------------------------
-- Build_Access_Object_Type --
------------------------------
function Build_Access_Object_Type (DT : Entity_Id) return Entity_Id is
- Typ : Entity_Id;
-
+ Typ : constant Entity_Id :=
+ New_Internal_Entity
+ (E_Access_Attribute_Type, Current_Scope, Loc, 'A');
begin
- if Aname = Name_Unrestricted_Access then
- Typ :=
- New_Internal_Entity
- (E_Allocator_Type, Current_Scope, Loc, 'A');
- else
- Typ :=
- New_Internal_Entity
- (E_Access_Attribute_Type, Current_Scope, Loc, 'A');
- end if;
-
Set_Etype (Typ, Typ);
Init_Size_Align (Typ);
Set_Is_Itype (Typ);
Index : Interp_Index;
It : Interp;
+ procedure Check_Local_Access (E : Entity_Id);
+ -- Deal with possible access to local subprogram. If we have such
+ -- an access, we set a flag to kill all tracked values on any call
+ -- because this access value may be passed around, and any called
+ -- code might use it to access a local procedure which clobbers a
+ -- tracked value.
+
function Get_Kind (E : Entity_Id) return Entity_Kind;
-- Distinguish between access to regular/protected subprograms
+ ------------------------
+ -- Check_Local_Access --
+ ------------------------
+
+ procedure Check_Local_Access (E : Entity_Id) is
+ begin
+ if not Is_Library_Level_Entity (E) then
+ Set_Suppress_Value_Tracking_On_Call (Current_Scope);
+ end if;
+ end Check_Local_Access;
+
--------------
-- Get_Kind --
--------------
Set_Etype (N, Any_Type);
if not Is_Overloaded (P) then
+ Check_Local_Access (Entity (P));
+
if not Is_Intrinsic_Subprogram (Entity (P)) then
Acc_Type :=
New_Internal_Entity
else
Get_First_Interp (P, Index, It);
while Present (It.Nam) loop
+ Check_Local_Access (It.Nam);
+
if not Is_Intrinsic_Subprogram (It.Nam) then
Acc_Type :=
New_Internal_Entity
end loop;
end if;
+ -- Cannot be applied to intrinsic. Looking at the tests above,
+ -- the only way Etype (N) can still be set to Any_Type is if
+ -- Is_Intrinsic_Subprogram was True for some referenced entity.
+
if Etype (N) = Any_Type then
- Error_Attr ("prefix of % attribute cannot be intrinsic", P);
+ Error_Attr_P ("prefix of % attribute cannot be intrinsic");
end if;
end Build_Access_Subprogram_Type;
+ ----------------------
+ -- OK_Self_Reference --
+ ----------------------
+
+ function OK_Self_Reference return Boolean is
+ Par : Node_Id;
+
+ begin
+ Par := Parent (N);
+ while Present (Par)
+ and then
+ (Nkind (Par) = N_Component_Association
+ or else Nkind (Par) in N_Subexpr)
+ loop
+ if Nkind (Par) = N_Aggregate
+ or else Nkind (Par) = N_Extension_Aggregate
+ then
+ if Etype (Par) = Typ then
+ Set_Has_Self_Reference (Par);
+ return True;
+ end if;
+ end if;
+
+ Par := Parent (Par);
+ end loop;
+
+ -- No enclosing aggregate, or not a self-reference
+
+ return False;
+ end OK_Self_Reference;
+
-- Start of processing for Analyze_Access_Attribute
begin
Check_E0;
if Nkind (P) = N_Character_Literal then
- Error_Attr
- ("prefix of % attribute cannot be enumeration literal", P);
+ Error_Attr_P
+ ("prefix of % attribute cannot be enumeration literal");
end if;
-- Case of access to subprogram
end if;
if Is_Always_Inlined (Entity (P)) then
- Error_Attr
- ("prefix of % attribute cannot be Inline_Always subprogram",
- P);
+ Error_Attr_P
+ ("prefix of % attribute cannot be Inline_Always subprogram");
+ end if;
+
+ if Aname = Name_Unchecked_Access then
+ Error_Attr ("attribute% cannot be applied to a subprogram", P);
end if;
-- Build the appropriate subprogram type
and then Is_Overloadable (Entity (Selector_Name (P)))
then
if Ekind (Entity (Selector_Name (P))) = E_Entry then
- Error_Attr ("prefix of % attribute must be subprogram", P);
+ Error_Attr_P ("prefix of % attribute must be subprogram");
end if;
Build_Access_Subprogram_Type (Selector_Name (P));
end if;
-- Deal with incorrect reference to a type, but note that some
- -- accesses are allowed (references to the current type instance).
+ -- accesses are allowed: references to the current type instance,
+ -- or in Ada 2005 self-referential pointer in a default-initialized
+ -- aggregate.
if Is_Entity_Name (P) then
- Scop := Current_Scope;
Typ := Entity (P);
+ -- The reference may appear in an aggregate that has been expanded
+ -- into a loop. Locate scope of type definition, if any.
+
+ Scop := Current_Scope;
+ while Ekind (Scop) = E_Loop loop
+ Scop := Scope (Scop);
+ end loop;
+
if Is_Type (Typ) then
-- OK if we are within the scope of a limited type
loop
Q := Parent (Q);
end loop;
+
if Present (Q) then
Set_Has_Per_Object_Constraint (
Defining_Identifier (Q), True);
end;
if Nkind (P) = N_Expanded_Name then
- Error_Msg_N
+ Error_Msg_F
("current instance prefix must be a direct name", P);
end if;
elsif Is_Task_Type (Typ) then
null;
+ -- OK if self-reference in an aggregate in Ada 2005, and
+ -- the reference comes from a copied default expression.
+
+ -- Note that we check legality of self-reference even if the
+ -- expression comes from source, e.g. when a single component
+ -- association in an aggregate has a box association.
+
+ elsif Ada_Version >= Ada_05
+ and then OK_Self_Reference
+ then
+ null;
+
-- Otherwise we have an error case
else
declare
Index : Interp_Index;
It : Interp;
-
begin
Set_Etype (N, Any_Type);
Get_First_Interp (P, Index, It);
-
while Present (It.Typ) loop
Acc_Type := Build_Access_Object_Type (It.Typ);
Add_One_Interp (N, Acc_Type, Acc_Type);
end;
end if;
- -- If we have an access to an object, and the attribute comes
- -- from source, then set the object as potentially source modified.
- -- We do this because the resulting access pointer can be used to
- -- modify the variable, and we might not detect this, leading to
- -- some junk warnings.
+ -- Special cases when prefix is entity name
if Is_Entity_Name (P) then
+
+ -- If we have an access to an object, and the attribute comes from
+ -- source, then set the object as potentially source modified. We
+ -- do this because the resulting access pointer can be used to
+ -- modify the variable, and we might not detect this, leading to
+ -- some junk warnings.
+
Set_Never_Set_In_Source (Entity (P), False);
+
+ -- Mark entity as address taken, and kill current values
+
+ Set_Address_Taken (Entity (P));
+ Kill_Current_Values (Entity (P));
end if;
- -- Check for aliased view unless unrestricted case. We allow
- -- a nonaliased prefix when within an instance because the
- -- prefix may have been a tagged formal object, which is
- -- defined to be aliased even when the actual might not be
- -- (other instance cases will have been caught in the generic).
- -- Similarly, within an inlined body we know that the attribute
- -- is legal in the original subprogram, and therefore legal in
- -- the expansion.
+ -- Check for aliased view unless unrestricted case. We allow a
+ -- nonaliased prefix when within an instance because the prefix may
+ -- have been a tagged formal object, which is defined to be aliased
+ -- even when the actual might not be (other instance cases will have
+ -- been caught in the generic). Similarly, within an inlined body we
+ -- know that the attribute is legal in the original subprogram, and
+ -- therefore legal in the expansion.
if Aname /= Name_Unrestricted_Access
and then not Is_Aliased_View (P)
and then not In_Instance
and then not In_Inlined_Body
then
- Error_Attr ("prefix of % attribute must be aliased", P);
+ Error_Attr_P ("prefix of % attribute must be aliased");
end if;
end Analyze_Access_Attribute;
-- recovery behavior.
Error_Msg_Name_1 := Aname;
- Error_Msg_N
+ Error_Msg_F
("prefix for % attribute must be constrained array", P);
end if;
else
if Is_Private_Type (P_Type) then
- Error_Attr
- ("prefix for % attribute may not be private type", P);
+ Error_Attr_P ("prefix for % attribute may not be private type");
elsif Is_Access_Type (P_Type)
and then Is_Array_Type (Designated_Type (P_Type))
and then Is_Entity_Name (P)
and then Is_Type (Entity (P))
then
- Error_Attr ("prefix of % attribute cannot be access type", P);
+ Error_Attr_P ("prefix of % attribute cannot be access type");
elsif Attr_Id = Attribute_First
or else
Error_Attr ("invalid prefix for % attribute", P);
else
- Error_Attr ("prefix for % attribute must be array", P);
+ Error_Attr_P ("prefix for % attribute must be array");
end if;
end if;
Error_Attr ("invalid dimension number for array type", E1);
end if;
end if;
+
+ if (Style_Check and Style_Check_Array_Attribute_Index)
+ and then Comes_From_Source (N)
+ then
+ Style.Check_Array_Attribute_Index (N, E1, D);
+ end if;
end Check_Array_Type;
-------------------------
and then
Ekind (Entity (Selector_Name (P))) /= E_Discriminant)
then
- Error_Attr
- ("prefix for % attribute must be selected component", P);
+ Error_Attr_P ("prefix for % attribute must be selected component");
end if;
end Check_Component;
Check_Type;
if not Is_Decimal_Fixed_Point_Type (P_Type) then
- Error_Attr
- ("prefix of % attribute must be decimal type", P);
+ Error_Attr_P ("prefix of % attribute must be decimal type");
end if;
end Check_Decimal_Fixed_Point_Type;
Check_Type;
if not Is_Discrete_Type (P_Type) then
- Error_Attr ("prefix of % attribute must be discrete type", P);
+ Error_Attr_P ("prefix of % attribute must be discrete type");
end if;
end Check_Discrete_Type;
procedure Check_Enum_Image is
Lit : Entity_Id;
-
begin
if Is_Enumeration_Type (P_Base_Type) then
Lit := First_Literal (P_Base_Type);
Check_Type;
if not Is_Fixed_Point_Type (P_Type) then
- Error_Attr ("prefix of % attribute must be fixed point type", P);
+ Error_Attr_P ("prefix of % attribute must be fixed point type");
end if;
end Check_Fixed_Point_Type;
Check_Type;
if not Is_Floating_Point_Type (P_Type) then
- Error_Attr ("prefix of % attribute must be float type", P);
+ Error_Attr_P ("prefix of % attribute must be float type");
end if;
end Check_Floating_Point_Type;
Check_Type;
if not Is_Integer_Type (P_Type) then
- Error_Attr ("prefix of % attribute must be integer type", P);
+ Error_Attr_P ("prefix of % attribute must be integer type");
end if;
end Check_Integer_Type;
procedure Check_Library_Unit is
begin
if not Is_Compilation_Unit (Entity (P)) then
- Error_Attr ("prefix of % attribute must be library unit", P);
+ Error_Attr_P ("prefix of % attribute must be library unit");
end if;
end Check_Library_Unit;
Check_Type;
if not Is_Modular_Integer_Type (P_Type) then
- Error_Attr
- ("prefix of % attribute must be modular integer type", P);
+ Error_Attr_P
+ ("prefix of % attribute must be modular integer type");
end if;
end Check_Modular_Integer_Type;
end loop;
if From_With_Type (Etype (E)) then
- Error_Attr
- ("prefix of % attribute cannot be an incomplete type", P);
+ Error_Attr_P
+ ("prefix of % attribute cannot be an incomplete type");
else
if Is_Access_Type (Etype (E)) then
end if;
if Ekind (Typ) = E_Incomplete_Type
- and then not Present (Full_View (Typ))
+ and then No (Full_View (Typ))
then
- Error_Attr
- ("prefix of % attribute cannot be an incomplete type", P);
+ Error_Attr_P
+ ("prefix of % attribute cannot be an incomplete type");
end if;
end if;
end if;
-- Otherwise we must have an object reference
elsif not Is_Object_Reference (P) then
- Error_Attr ("prefix of % attribute must be object", P);
+ Error_Attr_P ("prefix of % attribute must be object");
end if;
end Check_Object_Reference;
end;
end if;
- Error_Attr ("prefix of % attribute must be program unit", P);
+ Error_Attr_P ("prefix of % attribute must be program unit");
end Check_Program_Unit;
---------------------
Check_Type;
if not Is_Real_Type (P_Type) then
- Error_Attr ("prefix of % attribute must be real type", P);
+ Error_Attr_P ("prefix of % attribute must be real type");
end if;
end Check_Real_Type;
Check_Type;
if not Is_Scalar_Type (P_Type) then
- Error_Attr ("prefix of % attribute must be scalar type", P);
+ Error_Attr_P ("prefix of % attribute must be scalar type");
end if;
end Check_Scalar_Type;
procedure Check_Stream_Attribute (Nam : TSS_Name_Type) is
Etyp : Entity_Id;
Btyp : Entity_Id;
+
begin
Validate_Non_Static_Attribute_Function_Call;
-- Note: the double call to Root_Type here is needed because the
-- root type of a class-wide type is the corresponding type (e.g.
- -- X for X'Class, and we really want to go to the root.
+ -- X for X'Class, and we really want to go to the root.)
if not Is_Access_Type (Etyp)
or else Root_Type (Root_Type (Designated_Type (Etyp))) /=
begin
Analyze (P);
+ -- Ada 2005 (AI-345): Attribute 'Terminated can be applied to
+ -- task interface class-wide types.
+
if Is_Task_Type (Etype (P))
or else (Is_Access_Type (Etype (P))
- and then Is_Task_Type (Designated_Type (Etype (P))))
+ and then Is_Task_Type (Designated_Type (Etype (P))))
+ or else (Ada_Version >= Ada_05
+ and then Ekind (Etype (P)) = E_Class_Wide_Type
+ and then Is_Interface (Etype (P))
+ and then Is_Task_Interface (Etype (P)))
then
Resolve (P);
+
else
- Error_Attr ("prefix of % attribute must be a task", P);
+ if Ada_Version >= Ada_05 then
+ Error_Attr_P
+ ("prefix of % attribute must be a task or a task " &
+ "interface class-wide object");
+
+ else
+ Error_Attr_P ("prefix of % attribute must be a task");
+ end if;
end if;
end Check_Task_Prefix;
if not Is_Entity_Name (P)
or else not Is_Type (Entity (P))
then
- Error_Attr ("prefix of % attribute must be a type", P);
+ Error_Attr_P ("prefix of % attribute must be a type");
elsif Ekind (Entity (P)) = E_Incomplete_Type
and then Present (Full_View (Entity (P)))
Error_Attr;
end Error_Attr;
+ ------------------
+ -- Error_Attr_P --
+ ------------------
+
+ procedure Error_Attr_P (Msg : String) is
+ begin
+ Error_Msg_Name_1 := Aname;
+ Error_Msg_F (Msg, P);
+ Error_Attr;
+ end Error_Attr_P;
+
----------------------------
-- Legal_Formal_Attribute --
----------------------------
if not Is_Entity_Name (P)
or else not Is_Type (Entity (P))
then
- Error_Attr ("prefix of % attribute must be generic type", N);
+ Error_Attr_P ("prefix of % attribute must be generic type");
elsif Is_Generic_Actual_Type (Entity (P))
or else In_Instance
elsif Is_Generic_Type (Entity (P)) then
if not Is_Indefinite_Subtype (Entity (P)) then
- Error_Attr
- ("prefix of % attribute must be indefinite generic type", N);
+ Error_Attr_P
+ ("prefix of % attribute must be indefinite generic type");
end if;
else
- Error_Attr
- ("prefix of % attribute must be indefinite generic type", N);
+ Error_Attr_P
+ ("prefix of % attribute must be indefinite generic type");
end if;
Set_Etype (N, Standard_Boolean);
procedure Standard_Attribute (Val : Int) is
begin
Check_Standard_Prefix;
-
- -- First a special check (more like a kludge really). For GNAT5
- -- on Windows, the alignments in GCC are severely mixed up. In
- -- particular, we have a situation where the maximum alignment
- -- that GCC thinks is possible is greater than the guaranteed
- -- alignment at run-time. That causes many problems. As a partial
- -- cure for this situation, we force a value of 4 for the maximum
- -- alignment attribute on this target. This still does not solve
- -- all problems, but it helps.
-
- -- A further (even more horrible) dimension to this kludge is now
- -- installed. There are two uses for Maximum_Alignment, one is to
- -- determine the maximum guaranteed alignment, that's the one we
- -- want the kludge to yield as 4. The other use is to maximally
- -- align objects, we can't use 4 here, since for example, long
- -- long integer has an alignment of 8, so we will get errors.
-
- -- It is of course impossible to determine which use the programmer
- -- has in mind, but an approximation for now is to disconnect the
- -- kludge if the attribute appears in an alignment clause.
-
- -- To be removed if GCC ever gets its act together here ???
-
- Alignment_Kludge : declare
- P : Node_Id;
-
- function On_X86 return Boolean;
- -- Determine if target is x86 (ia32), return True if so
-
- ------------
- -- On_X86 --
- ------------
-
- function On_X86 return Boolean is
- T : constant String := Sdefault.Target_Name.all;
-
- begin
- -- There is no clean way to check this. That's not surprising,
- -- the front end should not be doing this kind of test ???. The
- -- way we do it is test for either "86" or "pentium" being in
- -- the string for the target name. However, we need to exclude
- -- x86_64 for this check.
-
- for J in T'First .. T'Last - 1 loop
- if (T (J .. J + 1) = "86"
- and then
- (J + 4 > T'Last
- or else T (J + 2 .. J + 4) /= "_64"))
- or else (J <= T'Last - 6
- and then T (J .. J + 6) = "pentium")
- then
- return True;
- end if;
- end loop;
-
- return False;
- end On_X86;
-
- begin
- if Aname = Name_Maximum_Alignment and then On_X86 then
- P := Parent (N);
-
- while Nkind (P) in N_Subexpr loop
- P := Parent (P);
- end loop;
-
- if Nkind (P) /= N_Attribute_Definition_Clause
- or else Chars (P) /= Name_Alignment
- then
- Rewrite (N, Make_Integer_Literal (Loc, 4));
- Analyze (N);
- return;
- end if;
- end if;
- end Alignment_Kludge;
-
- -- Normally we get the value from gcc ???
-
Rewrite (N, Make_Integer_Literal (Loc, Val));
Analyze (N);
end Standard_Attribute;
raise Bad_Attribute;
end if;
- -- Deal with Ada 83 and Features issues
+ -- Deal with Ada 83 issues
if Comes_From_Source (N) then
if not Attribute_83 (Attr_Id) then
end if;
end if;
+ -- Deal with Ada 2005 issues
+
+ if Attribute_05 (Attr_Id) and then Ada_Version <= Ada_95 then
+ Check_Restriction (No_Implementation_Attributes, N);
+ end if;
+
-- Remote access to subprogram type access attribute reference needs
-- unanalyzed copy for tree transformation. The analyzed copy is used
-- for its semantic information (whether prefix is a remote subprogram
end if;
-- Analyze prefix and exit if error in analysis. If the prefix is an
- -- incomplete type, use full view if available. A special case is
- -- that we never analyze the prefix of an Elab_Body or Elab_Spec
- -- or UET_Address attribute.
+ -- incomplete type, use full view if available. Note that there are
+ -- some attributes for which we do not analyze the prefix, since the
+ -- prefix is not a normal name.
if Aname /= Name_Elab_Body
and then
Aname /= Name_Elab_Spec
and then
Aname /= Name_UET_Address
+ and then
+ Aname /= Name_Enabled
then
Analyze (P);
P_Type := Etype (P);
if Is_Entity_Name (P)
and then Present (Entity (P))
and then Is_Type (Entity (P))
- and then Ekind (Entity (P)) = E_Incomplete_Type
then
- P_Type := Get_Full_View (P_Type);
- Set_Entity (P, P_Type);
- Set_Etype (P, P_Type);
+ if Ekind (Entity (P)) = E_Incomplete_Type then
+ P_Type := Get_Full_View (P_Type);
+ Set_Entity (P, P_Type);
+ Set_Etype (P, P_Type);
+
+ elsif Entity (P) = Current_Scope
+ and then Is_Record_Type (Entity (P))
+ then
+ -- Use of current instance within the type. Verify that if the
+ -- attribute appears within a constraint, it yields an access
+ -- type, other uses are illegal.
+
+ declare
+ Par : Node_Id;
+
+ begin
+ Par := Parent (N);
+ while Present (Par)
+ and then Nkind (Parent (Par)) /= N_Component_Definition
+ loop
+ Par := Parent (Par);
+ end loop;
+
+ if Present (Par)
+ and then Nkind (Par) = N_Subtype_Indication
+ then
+ if Attr_Id /= Attribute_Access
+ and then Attr_Id /= Attribute_Unchecked_Access
+ and then Attr_Id /= Attribute_Unrestricted_Access
+ then
+ Error_Msg_N
+ ("in a constraint the current instance can only"
+ & " be used with an access attribute", N);
+ end if;
+ end if;
+ end;
+ end if;
end if;
if P_Type = Any_Type then
E1 := First (Exprs);
Analyze (E1);
- -- Check for missing or bad expression (result of previous error)
+ -- Check for missing/bad expression (result of previous error)
if No (E1) or else Etype (E1) = Any_Type then
raise Bad_Attribute;
end if;
-- Ada 2005 (AI-345): Ensure that the compiler gives exactly the current
- -- output compiling in Ada 95 mode
+ -- output compiling in Ada 95 mode for the case of ambiguous prefixes.
if Ada_Version < Ada_05
and then Is_Overloaded (P)
begin
Get_First_Interp (P, I, It);
-
while Present (It.Nam) loop
if Comes_From_Source (It.Nam) then
Count := Count + 1;
end if;
Set_Address_Taken (Ent);
+ Kill_Current_Values (Ent);
- -- An Address attribute is accepted when generated by
- -- the compiler for dispatching operation, and an error
- -- is issued once the subprogram is frozen (to avoid
- -- confusing errors about implicit uses of Address in
- -- the dispatch table initialization).
+ -- An Address attribute is accepted when generated by the
+ -- compiler for dispatching operation, and an error is
+ -- issued once the subprogram is frozen (to avoid confusing
+ -- errors about implicit uses of Address in the dispatch
+ -- table initialization).
if Is_Always_Inlined (Entity (P))
and then Comes_From_Source (P)
then
- Error_Attr
+ Error_Attr_P
("prefix of % attribute cannot be Inline_Always" &
- " subprogram", P);
+ " subprogram");
end if;
elsif Is_Object (Ent)
procedure Bad_AST_Entry is
begin
- Error_Attr ("prefix for % attribute must be task entry", P);
+ Error_Attr_P ("prefix for % attribute must be task entry");
end Bad_AST_Entry;
function OK_Entry (E : Entity_Id) return Boolean is
if Result then
if not Is_AST_Entry (E) then
Error_Msg_Name_2 := Aname;
- Error_Attr
- ("% attribute requires previous % pragma", P);
+ Error_Attr ("% attribute requires previous % pragma", P);
end if;
end if;
and then not Is_Scalar_Type (Typ)
and then not Is_Generic_Type (Typ)
then
- Error_Msg_N ("prefix of Base attribute must be scalar type", N);
+ Error_Attr_P ("prefix of Base attribute must be scalar type");
elsif Sloc (Typ) = Standard_Location
and then Base_Type (Typ) = Typ
and then Warn_On_Redundant_Constructs
then
- Error_Msg_NE
- ("?redudant attribute, & is its own base type", N, Typ);
+ Error_Msg_NE
+ ("?redudant attribute, & is its own base type", N, Typ);
end if;
Set_Etype (N, Base_Type (Entity (P)));
Check_E0;
if not Is_Object_Reference (P) then
- Error_Attr ("prefix for % attribute must be object", P);
+ Error_Attr_P ("prefix for % attribute must be object");
-- What about the access object cases ???
Check_Type;
if not Is_Record_Type (P_Type) then
- Error_Attr ("prefix of % attribute must be record type", P);
+ Error_Attr_P ("prefix of % attribute must be record type");
end if;
if Bytes_Big_Endian xor Reverse_Bit_Order (P_Type) then
-- immediately and sets an appropriate type.
when Attribute_Bit_Position =>
-
if Comes_From_Source (N) then
Check_Component;
end if;
-----------
when Attribute_Class => Class : declare
+ P : constant Entity_Id := Prefix (N);
+
begin
Check_Restriction (No_Dispatch, N);
Check_Either_E0_Or_E1;
Make_Type_Conversion (Loc,
Subtype_Mark =>
Make_Attribute_Reference (Loc,
- Prefix => Prefix (N),
+ Prefix => P,
Attribute_Name => Name_Class),
Expression => Relocate_Node (E1)));
Save_Interps (E1, Expression (N));
- Analyze (N);
+
+ -- Ada 2005 (AI-251): In case of abstract interfaces we have to
+ -- analyze and resolve the type conversion to generate the code
+ -- that displaces the reference to the base of the object.
+
+ if Is_Interface (Etype (P))
+ or else Is_Interface (Etype (E1))
+ then
+ Analyze_And_Resolve (N, Etype (P));
+
+ -- However, the attribute is a name that occurs in a context
+ -- that imposes its own type. Leave the result unanalyzed,
+ -- so that type checking with the context type take place.
+ -- on the new conversion node, otherwise Resolve is a noop.
+
+ Set_Analyzed (N, False);
+
+ else
+ Analyze (N);
+ end if;
-- Otherwise we just need to find the proper type
else
Find_Type (N);
end if;
-
end Class;
------------------
if Warn_On_Obsolescent_Feature then
Error_Msg_N
("constrained for private type is an " &
- "obsolescent feature ('R'M 'J.4)?", N);
+ "obsolescent feature (RM J.4)?", N);
end if;
-- If we are within an instance, the attribute must be legal
end if;
-- Must have discriminants or be an access type designating
- -- a type with discriminants. If it is a classwide type is
+ -- a type with discriminants. If it is a classwide type is ???
-- has unknown discriminants.
if Has_Discriminants (P_Type)
-- Fall through if bad prefix
- Error_Attr
- ("prefix of % attribute must be object of discriminated type", P);
+ Error_Attr_P
+ ("prefix of % attribute must be object of discriminated type");
---------------
-- Copy_Sign --
if not Is_Floating_Point_Type (P_Type)
and then not Is_Decimal_Fixed_Point_Type (P_Type)
then
- Error_Attr
- ("prefix of % attribute must be float or decimal type", P);
+ Error_Attr_P
+ ("prefix of % attribute must be float or decimal type");
end if;
Set_Etype (N, Universal_Integer);
Check_Floating_Point_Type_0;
Set_Etype (N, Universal_Integer);
+ -------------
+ -- Enabled --
+ -------------
+
+ when Attribute_Enabled =>
+ Check_Either_E0_Or_E1;
+
+ if Present (E1) then
+ if not Is_Entity_Name (E1) or else No (Entity (E1)) then
+ Error_Msg_N ("entity name expected for Enabled attribute", E1);
+ E1 := Empty;
+ end if;
+ end if;
+
+ if Nkind (P) /= N_Identifier then
+ Error_Msg_N ("identifier expected (check name)", P);
+
+ elsif Get_Check_Id (Chars (P)) = No_Check_Id then
+ Error_Msg_N ("& is not a recognized check name", P);
+ end if;
+
+ Set_Etype (N, Standard_Boolean);
+
--------------
-- Enum_Rep --
--------------
and then
Ekind (Entity (P)) /= E_Enumeration_Literal)
then
- Error_Attr
+ Error_Attr_P
("prefix of %attribute must be " &
- "discrete type/object or enum literal", P);
+ "discrete type/object or enum literal");
end if;
end if;
Set_Etype (N, Standard_String);
if not Is_Tagged_Type (P_Type) then
- Error_Attr ("prefix of % attribute must be tagged", P);
+ Error_Attr_P ("prefix of % attribute must be tagged");
end if;
-----------
if Etype (P) = Standard_Exception_Type then
Set_Etype (N, RTE (RE_Exception_Id));
+ -- Ada 2005 (AI-345): Attribute 'Identity may be applied to
+ -- task interface class-wide types.
+
elsif Is_Task_Type (Etype (P))
or else (Is_Access_Type (Etype (P))
- and then Is_Task_Type (Designated_Type (Etype (P))))
+ and then Is_Task_Type (Designated_Type (Etype (P))))
+ or else (Ada_Version >= Ada_05
+ and then Ekind (Etype (P)) = E_Class_Wide_Type
+ and then Is_Interface (Etype (P))
+ and then Is_Task_Interface (Etype (P)))
then
Resolve (P);
Set_Etype (N, RTE (RO_AT_Task_Id));
else
- Error_Attr ("prefix of % attribute must be a task or an "
- & "exception", P);
+ if Ada_Version >= Ada_05 then
+ Error_Attr_P
+ ("prefix of % attribute must be an exception, a " &
+ "task or a task interface class-wide object");
+ else
+ Error_Attr_P
+ ("prefix of % attribute must be a task or an exception");
+ end if;
end if;
-----------
if not Is_Scalar_Type (P_Type)
or else (Is_Entity_Name (P) and then Is_Type (Entity (P)))
then
- Error_Attr
- ("prefix of % attribute must be scalar object name", N);
+ Error_Attr_P
+ ("prefix of % attribute must be scalar object name");
end if;
Check_Enum_Image;
Check_E0;
Set_Etype (N, Universal_Integer);
+ ----------------------
+ -- Machine_Rounding --
+ ----------------------
+
+ when Attribute_Machine_Rounding =>
+ Check_Floating_Point_Type_1;
+ Set_Etype (N, P_Base_Type);
+ Resolve (E1, P_Base_Type);
+
--------------------
-- Machine_Rounds --
--------------------
if not Is_Entity_Name (P)
or else not Is_Subprogram (Entity (P))
then
- Error_Attr ("prefix of % attribute must be subprogram", P);
+ Error_Attr_P ("prefix of % attribute must be subprogram");
end if;
Check_Either_E0_Or_E1;
if P_Type /= Any_Type then
if not Is_Library_Level_Entity (Entity (P)) then
- Error_Attr
- ("prefix of % attribute must be library-level entity", P);
+ Error_Attr_P
+ ("prefix of % attribute must be library-level entity");
-- The defining entity of prefix should not be declared inside
-- a Pure unit. RM E.1(8).
elsif Is_Entity_Name (P)
and then Is_Pure (Entity (P))
then
- Error_Attr
- ("prefix of % attribute must not be declared pure", P);
+ Error_Attr_P
+ ("prefix of % attribute must not be declared pure");
end if;
end if;
end if;
end if;
+ --------------
+ -- Priority --
+ --------------
+
+ -- Ada 2005 (AI-327): Dynamic ceiling priorities
+
+ when Attribute_Priority =>
+ if Ada_Version < Ada_05 then
+ Error_Attr ("% attribute is allowed only in Ada 2005 mode", P);
+ end if;
+
+ Check_E0;
+
+ -- The prefix must be a protected object (AARM D.5.2 (2/2))
+
+ Analyze (P);
+
+ if Is_Protected_Type (Etype (P))
+ or else (Is_Access_Type (Etype (P))
+ and then Is_Protected_Type (Designated_Type (Etype (P))))
+ then
+ Resolve (P, Etype (P));
+ else
+ Error_Attr_P ("prefix of % attribute must be a protected object");
+ end if;
+
+ Set_Etype (N, Standard_Integer);
+
+ -- Must be called from within a protected procedure or entry of the
+ -- protected object.
+
+ declare
+ S : Entity_Id;
+
+ begin
+ S := Current_Scope;
+ while S /= Etype (P)
+ and then S /= Standard_Standard
+ loop
+ S := Scope (S);
+ end loop;
+
+ if S = Standard_Standard then
+ Error_Attr ("the attribute % is only allowed inside protected "
+ & "operations", P);
+ end if;
+ end;
+
+ Validate_Non_Static_Attribute_Function_Call;
+
-----------
-- Range --
-----------
Check_Object_Reference (P);
elsif Is_Entity_Name (P)
- and then Is_Type (Entity (P))
+ and then (Is_Type (Entity (P))
+ or else Ekind (Entity (P)) = E_Enumeration_Literal)
then
null;
null;
else
- Error_Attr ("invalid prefix for % attribute", P);
+ Error_Attr_P ("invalid prefix for % attribute");
end if;
Check_Not_Incomplete_Type;
if Is_Access_Type (P_Type) then
Check_E0;
+ if Ekind (P_Type) = E_Access_Subprogram_Type then
+ Error_Attr_P
+ ("cannot use % attribute for access-to-subprogram type");
+ end if;
+
-- Set appropriate entity
if Present (Associated_Storage_Pool (Root_Type (P_Type))) then
Validate_Remote_Access_To_Class_Wide_Type (N);
else
- Error_Attr ("prefix of % attribute must be access type", P);
+ Error_Attr_P ("prefix of % attribute must be access type");
end if;
------------------
------------------
when Attribute_Storage_Size =>
-
if Is_Task_Type (P_Type) then
Check_E0;
Set_Etype (N, Universal_Integer);
elsif Is_Access_Type (P_Type) then
+ if Ekind (P_Type) = E_Access_Subprogram_Type then
+ Error_Attr_P
+ ("cannot use % attribute for access-to-subprogram type");
+ end if;
+
if Is_Entity_Name (P)
and then Is_Type (Entity (P))
then
end if;
else
- Error_Attr
- ("prefix of % attribute must be access or task type", P);
+ Error_Attr_P ("prefix of % attribute must be access or task type");
end if;
------------------
then
Set_Etype (N, Universal_Integer);
else
- Error_Attr ("invalid prefix for % attribute", P);
+ Error_Attr_P ("invalid prefix for % attribute");
+ end if;
+
+ ---------------
+ -- Stub_Type --
+ ---------------
+
+ when Attribute_Stub_Type =>
+ Check_Type;
+ Check_E0;
+
+ if Is_Remote_Access_To_Class_Wide_Type (P_Type) then
+ Rewrite (N,
+ New_Occurrence_Of (Corresponding_Stub_Type (P_Type), Loc));
+ else
+ Error_Attr_P
+ ("prefix of% attribute must be remote access to classwide");
end if;
----------
Check_Dereference;
if not Is_Tagged_Type (P_Type) then
- Error_Attr ("prefix of % attribute must be tagged", P);
+ Error_Attr_P ("prefix of % attribute must be tagged");
-- Next test does not apply to generated code
-- why not, and what does the illegal reference mean???
and then not Is_Class_Wide_Type (P_Type)
and then Comes_From_Source (N)
then
- Error_Attr
- ("% attribute can only be applied to objects of class-wide type",
- P);
+ Error_Attr_P
+ ("% attribute can only be applied to objects " &
+ "of class - wide type");
end if;
+ -- The prefix cannot be an incomplete type. However, references
+ -- to 'Tag can be generated when expanding interface conversions,
+ -- and this is legal.
+
+ if Comes_From_Source (N) then
+ Check_Not_Incomplete_Type;
+ end if;
Set_Etype (N, RTE (RE_Tag));
-----------------
if Nkind (P) /= N_Identifier
or else Chars (P) /= Name_System
then
- Error_Attr ("prefix of %attribute must be System", P);
+ Error_Attr_P ("prefix of %attribute must be System");
end if;
Generate_Reference (RTE (RE_Address), P);
if not Is_Entity_Name (P)
or else Ekind (Entity (P)) not in Named_Kind
then
- Error_Attr ("prefix for % attribute must be named number", P);
+ Error_Attr_P ("prefix for % attribute must be named number");
else
declare
end if;
if not Is_Scalar_Type (P_Type) then
- Error_Attr ("object for % attribute must be of scalar type", P);
+ Error_Attr_P ("object for % attribute must be of scalar type");
end if;
Set_Etype (N, Standard_Boolean);
Check_E1;
Check_Scalar_Type;
+ -- Case of enumeration type
+
if Is_Enumeration_Type (P_Type) then
Check_Restriction (No_Enumeration_Maps, N);
+
+ -- Mark all enumeration literals as referenced, since the use of
+ -- the Value attribute can implicitly reference any of the
+ -- literals of the enumeration base type.
+
+ declare
+ Ent : Entity_Id := First_Literal (P_Base_Type);
+ begin
+ while Present (Ent) loop
+ Set_Referenced (Ent);
+ Next_Literal (Ent);
+ end loop;
+ end;
end if;
-- Set Etype before resolving expression because expansion of
-- used for First and Last of scalar types. Static is reset to False
-- if the type or index type is not statically constrained.
+ function Statically_Denotes_Entity (N : Node_Id) return Boolean;
+ -- Verify that the prefix of a potentially static array attribute
+ -- satisfies the conditions of 4.9 (14).
+
---------------
-- Aft_Value --
---------------
begin
Result := 1;
Delta_Val := Delta_Value (P_Type);
-
while Delta_Val < Ureal_Tenth loop
Delta_Val := Delta_Val * Ureal_10;
Result := Result + 1;
-----------------------
procedure Check_Expressions is
- E : Node_Id := E1;
-
+ E : Node_Id;
begin
+ E := E1;
while Present (E) loop
Check_Non_Static_Context (E);
Next (E);
end if;
end Set_Bounds;
+ -------------------------------
+ -- Statically_Denotes_Entity --
+ -------------------------------
+
+ function Statically_Denotes_Entity (N : Node_Id) return Boolean is
+ E : Entity_Id;
+
+ begin
+ if not Is_Entity_Name (N) then
+ return False;
+ else
+ E := Entity (N);
+ end if;
+
+ return
+ Nkind (Parent (E)) /= N_Object_Renaming_Declaration
+ or else Statically_Denotes_Entity (Renamed_Object (E));
+ end Statically_Denotes_Entity;
+
-- Start of processing for Eval_Attribute
begin
E2 := Empty;
end if;
+ -- Special processing for Enabled attribute. This attribute has a very
+ -- special prefix, and the easiest way to avoid lots of special checks
+ -- to protect this special prefix from causing trouble is to deal with
+ -- this attribute immediately and be done with it.
+
+ if Id = Attribute_Enabled then
+
+ -- Evaluate the Enabled attribute
+
+ -- We skip evaluation if the expander is not active. This is not just
+ -- an optimization. It is of key importance that we not rewrite the
+ -- attribute in a generic template, since we want to pick up the
+ -- setting of the check in the instance, and testing expander active
+ -- is as easy way of doing this as any.
+
+ if Expander_Active then
+ declare
+ C : constant Check_Id := Get_Check_Id (Chars (P));
+ R : Boolean;
+
+ begin
+ if No (E1) then
+ if C in Predefined_Check_Id then
+ R := Scope_Suppress (C);
+ else
+ R := Is_Check_Suppressed (Empty, C);
+ end if;
+
+ else
+ R := Is_Check_Suppressed (Entity (E1), C);
+ end if;
+
+ if R then
+ Rewrite (N, New_Occurrence_Of (Standard_False, Loc));
+ else
+ Rewrite (N, New_Occurrence_Of (Standard_True, Loc));
+ end if;
+ end;
+ end if;
+
+ return;
+ end if;
+
-- Special processing for cases where the prefix is an object. For
-- this purpose, a string literal counts as an object (attributes
-- of string literals can only appear in generated code).
then
P_Type := Etype (P_Entity);
- -- If the entity is an array constant with an unconstrained
- -- nominal subtype then get the type from the initial value.
- -- If the value has been expanded into assignments, the expression
- -- is not present and the attribute reference remains dynamic.
+ -- If the entity is an array constant with an unconstrained nominal
+ -- subtype then get the type from the initial value. If the value has
+ -- been expanded into assignments, there is no expression and the
+ -- attribute reference remains dynamic.
-- We could do better here and retrieve the type ???
if Ekind (P_Entity) = E_Constant
-- Array case. We enforce the constrained requirement of (RM 4.9(7-8))
-- since we can't do anything with unconstrained arrays. In addition,
-- only the First, Last and Length attributes are possibly static.
- -- In addition Component_Size is possibly foldable, even though it
- -- can never be static.
-- Definite, Has_Access_Values, Has_Discriminants, Type_Class, and
-- Unconstrained_Array are again exceptions, because they apply as
-- well to unconstrained types.
+ -- In addition Component_Size is an exception since it is possibly
+ -- foldable, even though it is never static, and it does apply to
+ -- unconstrained arrays. Furthermore, it is essential to fold this
+ -- in the packed case, since otherwise the value will be incorrect.
+
elsif Id = Attribute_Definite
or else
Id = Attribute_Has_Access_Values
Id = Attribute_Type_Class
or else
Id = Attribute_Unconstrained_Array
+ or else
+ Id = Attribute_Component_Size
then
Static := False;
else
if not Is_Constrained (P_Type)
- or else (Id /= Attribute_Component_Size and then
- Id /= Attribute_First and then
- Id /= Attribute_Last and then
+ or else (Id /= Attribute_First and then
+ Id /= Attribute_Last and then
Id /= Attribute_Length)
then
Check_Expressions;
-- Again we compute the variable Static for easy reference later
-- (note that no array attributes are static in Ada 83).
- Static := Ada_Version >= Ada_95;
+ Static := Ada_Version >= Ada_95
+ and then Statically_Denotes_Entity (P);
declare
N : Node_Id;
-- Image is a scalar attribute, but is never static, because it is
-- not a static function (having a non-scalar argument (RM 4.9(22))
+ -- However, we can constant-fold the image of an enumeration literal
+ -- if names are available.
when Attribute_Image =>
- null;
+ if Is_Entity_Name (E1)
+ and then Ekind (Entity (E1)) = E_Enumeration_Literal
+ and then not Discard_Names (First_Subtype (Etype (E1)))
+ and then not Global_Discard_Names
+ then
+ declare
+ Lit : constant Entity_Id := Entity (E1);
+ Str : String_Id;
+ begin
+ Start_String;
+ Get_Unqualified_Decoded_Name_String (Chars (Lit));
+ Set_Casing (All_Upper_Case);
+ Store_String_Chars (Name_Buffer (1 .. Name_Len));
+ Str := End_String;
+ Rewrite (N, Make_String_Literal (Loc, Strval => Str));
+ Analyze_And_Resolve (N, Standard_String);
+ Set_Is_Static_Expression (N, False);
+ end;
+ end if;
---------
-- Img --
Fold_Uint (N, Uint_2, True);
end if;
+ ----------------------
+ -- Machine_Rounding --
+ ----------------------
+
+ -- Note: for the folding case, it is fine to treat Machine_Rounding
+ -- exactly the same way as Rounding, since this is one of the allowed
+ -- behaviors, and performance is not an issue here. It might be a bit
+ -- better to give the same result as it would give at run-time, even
+ -- though the non-determinism is certainly permitted.
+
+ when Attribute_Machine_Rounding =>
+ Fold_Ureal (N,
+ Eval_Fat.Rounding (P_Root_Type, Expr_Value_R (E1)), Static);
+
--------------------
-- Machine_Rounds --
--------------------
end if;
Rewrite (N, New_Occurrence_Of (RTE (Id), Loc));
-
end Type_Class;
-----------------------
when Attribute_Value_Size => Value_Size : declare
P_TypeA : constant Entity_Id := Underlying_Type (P_Type);
-
begin
if RM_Size (P_TypeA) /= Uint_0 then
Fold_Uint (N, RM_Size (P_TypeA), True);
end if;
-
end Value_Size;
-------------
-- nnn is set to 2 for Short_Float and Float (32 bit
-- floats), and 3 for Long_Float and Long_Long_Float.
- -- This is not quite right, but is good enough.
+ -- For machines where Long_Long_Float is the IEEE
+ -- extended precision type, the exponent takes 4 digits.
declare
Len : Int :=
begin
if Esize (P_Type) <= 32 then
Len := Len + 6;
- else
+ elsif Esize (P_Type) = 64 then
Len := Len + 7;
+ else
+ Len := Len + 8;
end if;
Fold_Uint (N, UI_From_Int (Len), True);
Attribute_Elaborated |
Attribute_Elab_Body |
Attribute_Elab_Spec |
+ Attribute_Enabled |
Attribute_External_Tag |
Attribute_First_Bit |
Attribute_Input |
Attribute_Partition_ID |
Attribute_Pool_Address |
Attribute_Position |
+ Attribute_Priority |
Attribute_Read |
Attribute_Storage_Pool |
Attribute_Storage_Size |
Attribute_Storage_Unit |
+ Attribute_Stub_Type |
Attribute_Tag |
Attribute_Target_Name |
Attribute_Terminated |
else
null;
end if;
-
end Eval_Attribute;
------------------------------
and then Associated_Node_For_Itype (Anon) = Parent (Typ);
end Is_Anonymous_Tagged_Base;
+ --------------------------------
+ -- Name_Implies_Lvalue_Prefix --
+ --------------------------------
+
+ function Name_Implies_Lvalue_Prefix (Nam : Name_Id) return Boolean is
+ pragma Assert (Is_Attribute_Name (Nam));
+ begin
+ return Attribute_Name_Implies_Lvalue_Prefix (Get_Attribute_Id (Nam));
+ end Name_Implies_Lvalue_Prefix;
+
-----------------------
-- Resolve_Attribute --
-----------------------
Aname : constant Name_Id := Attribute_Name (N);
Attr_Id : constant Attribute_Id := Get_Attribute_Id (Aname);
Btyp : constant Entity_Id := Base_Type (Typ);
+ Des_Btyp : Entity_Id;
Index : Interp_Index;
It : Interp;
Nom_Subt : Entity_Id;
-- know will fail, so generate an appropriate warning.
if In_Instance_Body then
- Error_Msg_N
+ Error_Msg_F
("?non-local pointer cannot point to local object", P);
- Error_Msg_N
- ("?Program_Error will be raised at run time", P);
+ Error_Msg_F
+ ("\?Program_Error will be raised at run time", P);
Rewrite (N,
Make_Raise_Program_Error (Loc,
Reason => PE_Accessibility_Check_Failed));
return;
else
- Error_Msg_N
+ Error_Msg_F
("non-local pointer cannot point to local object", P);
-- Check for case where we have a missing access definition
if Present (Indic) then
Error_Msg_NE
("\use an access definition for" &
- " the access discriminant of&", N,
- Entity (Subtype_Mark (Indic)));
+ " the access discriminant of&",
+ N, Entity (Subtype_Mark (Indic)));
end if;
end if;
end if;
| Attribute_Unchecked_Access
| Attribute_Unrestricted_Access =>
+ Access_Attribute : begin
if Is_Variable (P) then
Note_Possible_Modification (P);
end if;
if Is_Entity_Name (P) then
if Is_Overloaded (P) then
Get_First_Interp (P, Index, It);
-
while Present (It.Nam) loop
-
if Type_Conformant (Designated_Type (Typ), It.Nam) then
Set_Entity (P, It.Nam);
- -- The prefix is definitely NOT overloaded anymore
- -- at this point, so we reset the Is_Overloaded
- -- flag to avoid any confusion when reanalyzing
- -- the node.
+ -- The prefix is definitely NOT overloaded anymore at
+ -- this point, so we reset the Is_Overloaded flag to
+ -- avoid any confusion when reanalyzing the node.
Set_Is_Overloaded (P, False);
+ Set_Is_Overloaded (N, False);
Generate_Reference (Entity (P), P);
exit;
end if;
Get_Next_Interp (Index, It);
end loop;
- -- If it is a subprogram name or a type, there is nothing
- -- to resolve.
+ -- If Prefix is a subprogram name, it is frozen by this
+ -- reference:
- elsif not Is_Overloadable (Entity (P))
- and then not Is_Type (Entity (P))
- then
+ -- If it is a type, there is nothing to resolve.
+ -- If it is an object, complete its resolution.
+
+ elsif Is_Overloadable (Entity (P)) then
+ if not In_Default_Expression then
+ Insert_Actions (N, Freeze_Entity (Entity (P), Loc));
+ end if;
+
+ elsif Is_Type (Entity (P)) then
+ null;
+ else
Resolve (P);
end if;
if not Is_Entity_Name (P) then
null;
- elsif Is_Abstract (Entity (P))
- and then Is_Overloadable (Entity (P))
+ elsif Is_Overloadable (Entity (P))
+ and then Is_Abstract_Subprogram (Entity (P))
then
- Error_Msg_N ("prefix of % attribute cannot be abstract", P);
+ Error_Msg_F ("prefix of % attribute cannot be abstract", P);
Set_Etype (N, Any_Type);
elsif Convention (Entity (P)) = Convention_Intrinsic then
if Ekind (Entity (P)) = E_Enumeration_Literal then
- Error_Msg_N
+ Error_Msg_F
("prefix of % attribute cannot be enumeration literal",
- P);
+ P);
else
- Error_Msg_N
+ Error_Msg_F
("prefix of % attribute cannot be intrinsic", P);
end if;
Set_Etype (N, Any_Type);
-
- elsif Is_Thread_Body (Entity (P)) then
- Error_Msg_N
- ("prefix of % attribute cannot be a thread body", P);
end if;
-- Assignments, return statements, components of aggregates,
or else
Ekind (Btyp) = E_Anonymous_Access_Protected_Subprogram_Type
then
+ -- Deal with convention mismatch
+
if Convention (Btyp) /= Convention (Entity (P)) then
- Error_Msg_N
- ("subprogram has invalid convention for context", P);
+ Error_Msg_FE
+ ("subprogram & has wrong convention", P, Entity (P));
+
+ Error_Msg_FE
+ ("\does not match convention of access type &",
+ P, Btyp);
+
+ if not Has_Convention_Pragma (Btyp) then
+ Error_Msg_FE
+ ("\probable missing pragma Convention for &",
+ P, Btyp);
+ end if;
else
Check_Subtype_Conformant
if Attr_Id = Attribute_Unchecked_Access then
Error_Msg_Name_1 := Aname;
- Error_Msg_N
+ Error_Msg_F
("attribute% cannot be applied to a subprogram", P);
elsif Aname = Name_Unrestricted_Access then
null; -- Nothing to check
- -- Check the static accessibility rule of 3.10.2(32)
- -- In an instance body, if subprogram and type are both
- -- local, other rules prevent dangling references, and no
- -- warning is needed.
+ -- Check the static accessibility rule of 3.10.2(32).
+ -- This rule also applies within the private part of an
+ -- instantiation. This rule does not apply to anonymous
+ -- access-to-subprogram types (Ada 2005).
elsif Attr_Id = Attribute_Access
+ and then not In_Instance_Body
and then Subprogram_Access_Level (Entity (P)) >
Type_Access_Level (Btyp)
and then Ekind (Btyp) /=
and then Ekind (Btyp) /=
E_Anonymous_Access_Protected_Subprogram_Type
then
- if not In_Instance_Body then
- Error_Msg_N
- ("subprogram must not be deeper than access type",
- P);
+ Error_Msg_F
+ ("subprogram must not be deeper than access type", P);
+
+ -- Check the restriction of 3.10.2(32) that disallows the
+ -- access attribute within a generic body when the ultimate
+ -- ancestor of the type of the attribute is declared outside
+ -- of the generic unit and the subprogram is declared within
+ -- that generic unit. This includes any such attribute that
+ -- occurs within the body of a generic unit that is a child
+ -- of the generic unit where the subprogram is declared.
+ -- The rule also prohibits applying the attibute when the
+ -- access type is a generic formal access type (since the
+ -- level of the actual type is not known). This restriction
+ -- does not apply when the attribute type is an anonymous
+ -- access-to-subprogram type. Note that this check was
+ -- revised by AI-229, because the originally Ada 95 rule
+ -- was too lax. The original rule only applied when the
+ -- subprogram was declared within the body of the generic,
+ -- which allowed the possibility of dangling references).
+ -- The rule was also too strict in some case, in that it
+ -- didn't permit the access to be declared in the generic
+ -- spec, whereas the revised rule does (as long as it's not
+ -- a formal type).
+
+ -- There are a couple of subtleties of the test for applying
+ -- the check that are worth noting. First, we only apply it
+ -- when the levels of the subprogram and access type are the
+ -- same (the case where the subprogram is statically deeper
+ -- was applied above, and the case where the type is deeper
+ -- is always safe). Second, we want the check to apply
+ -- within nested generic bodies and generic child unit
+ -- bodies, but not to apply to an attribute that appears in
+ -- the generic unit's specification. This is done by testing
+ -- that the attribute's innermost enclosing generic body is
+ -- not the same as the innermost generic body enclosing the
+ -- generic unit where the subprogram is declared (we don't
+ -- want the check to apply when the access attribute is in
+ -- the spec and there's some other generic body enclosing
+ -- generic). Finally, there's no point applying the check
+ -- when within an instance, because any violations will have
+ -- been caught by the compilation of the generic unit.
- elsif Scope (Entity (P)) /= Scope (Btyp) then
- Error_Msg_N
- ("subprogram must not be deeper than access type?",
- P);
+ elsif Attr_Id = Attribute_Access
+ and then not In_Instance
+ and then Present (Enclosing_Generic_Unit (Entity (P)))
+ and then Present (Enclosing_Generic_Body (N))
+ and then Enclosing_Generic_Body (N) /=
+ Enclosing_Generic_Body
+ (Enclosing_Generic_Unit (Entity (P)))
+ and then Subprogram_Access_Level (Entity (P)) =
+ Type_Access_Level (Btyp)
+ and then Ekind (Btyp) /=
+ E_Anonymous_Access_Subprogram_Type
+ and then Ekind (Btyp) /=
+ E_Anonymous_Access_Protected_Subprogram_Type
+ then
+ -- The attribute type's ultimate ancestor must be
+ -- declared within the same generic unit as the
+ -- subprogram is declared. The error message is
+ -- specialized to say "ancestor" for the case where
+ -- the access type is not its own ancestor, since
+ -- saying simply "access type" would be very confusing.
+
+ if Enclosing_Generic_Unit (Entity (P)) /=
+ Enclosing_Generic_Unit (Root_Type (Btyp))
+ then
Error_Msg_N
- ("Constraint_Error will be raised ?", P);
- Set_Raises_Constraint_Error (N);
- end if;
-
- -- Check the restriction of 3.10.2(32) that disallows
- -- the type of the access attribute to be declared
- -- outside a generic body when the subprogram is declared
- -- within that generic body.
-
- -- Ada2005: If the expected type is for an access
- -- parameter, this clause does not apply.
+ ("''Access attribute not allowed in generic body",
+ N);
+
+ if Root_Type (Btyp) = Btyp then
+ Error_Msg_NE
+ ("\because " &
+ "access type & is declared outside " &
+ "generic unit (RM 3.10.2(32))", N, Btyp);
+ else
+ Error_Msg_NE
+ ("\because ancestor of " &
+ "access type & is declared outside " &
+ "generic unit (RM 3.10.2(32))", N, Btyp);
+ end if;
- elsif Present (Enclosing_Generic_Body (Entity (P)))
- and then Enclosing_Generic_Body (Entity (P)) /=
- Enclosing_Generic_Body (Btyp)
- and then
- Ekind (Btyp) /= E_Anonymous_Access_Subprogram_Type
- then
- Error_Msg_N
- ("access type must not be outside generic body", P);
+ Error_Msg_NE
+ ("\move ''Access to private part, or " &
+ "(Ada 2005) use anonymous access type instead of &",
+ N, Btyp);
+
+ -- If the ultimate ancestor of the attribute's type is
+ -- a formal type, then the attribute is illegal because
+ -- the actual type might be declared at a higher level.
+ -- The error message is specialized to say "ancestor"
+ -- for the case where the access type is not its own
+ -- ancestor, since saying simply "access type" would be
+ -- very confusing.
+
+ elsif Is_Generic_Type (Root_Type (Btyp)) then
+ if Root_Type (Btyp) = Btyp then
+ Error_Msg_N
+ ("access type must not be a generic formal type",
+ N);
+ else
+ Error_Msg_N
+ ("ancestor access type must not be a generic " &
+ "formal type", N);
+ end if;
+ end if;
end if;
end if;
-- If this is a renaming, an inherited operation, or a
- -- subprogram instance, use the original entity.
+ -- subprogram instance, use the original entity. This may make
+ -- the node type-inconsistent, so this transformation can only
+ -- be done if the node will not be reanalyzed. In particular,
+ -- if it is within a default expression, the transformation
+ -- must be delayed until the default subprogram is created for
+ -- it, when the enclosing subprogram is frozen.
if Is_Entity_Name (P)
and then Is_Overloadable (Entity (P))
and then Present (Alias (Entity (P)))
+ and then Expander_Active
then
Rewrite (P,
New_Occurrence_Of (Alias (Entity (P)), Sloc (P)));
if Attr_Id = Attribute_Unchecked_Access then
Error_Msg_Name_1 := Aname;
- Error_Msg_N
+ Error_Msg_F
("attribute% cannot be applied to protected operation", P);
end if;
Resolve (P);
end if;
- -- X'Access is illegal if X denotes a constant and the access
- -- type is access-to-variable. Same for 'Unchecked_Access.
- -- The rule does not apply to 'Unrestricted_Access.
+ -- X'Access is illegal if X denotes a constant and the access type
+ -- is access-to-variable. Same for 'Unchecked_Access. The rule
+ -- does not apply to 'Unrestricted_Access. If the reference is a
+ -- default-initialized aggregate component for a self-referential
+ -- type the reference is legal.
if not (Ekind (Btyp) = E_Access_Subprogram_Type
or else Ekind (Btyp) = E_Anonymous_Access_Subprogram_Type
- or else (Is_Record_Type (Btyp) and then
- Present (Corresponding_Remote_Type (Btyp)))
+ or else (Is_Record_Type (Btyp)
+ and then
+ Present (Corresponding_Remote_Type (Btyp)))
or else Ekind (Btyp) = E_Access_Protected_Subprogram_Type
or else Ekind (Btyp)
= E_Anonymous_Access_Protected_Subprogram_Type
or else Is_Variable (P)
or else Attr_Id = Attribute_Unrestricted_Access)
then
- if Comes_From_Source (N) then
- Error_Msg_N ("access-to-variable designates constant", P);
+ if Is_Entity_Name (P)
+ and then Is_Type (Entity (P))
+ then
+ -- Legality of a self-reference through an access
+ -- attribute has been verified in Analyze_Access_Attribute.
+
+ null;
+
+ elsif Comes_From_Source (N) then
+ Error_Msg_F ("access-to-variable designates constant", P);
end if;
end if;
or else Ekind (Btyp) = E_Anonymous_Access_Type)
then
-- Ada 2005 (AI-230): Check the accessibility of anonymous
- -- access types in record and array components. For a
- -- component definition the level is the same of the
- -- enclosing composite type.
+ -- access types for stand-alone objects, record and array
+ -- components, and return objects. For a component definition
+ -- the level is the same of the enclosing composite type.
if Ada_Version >= Ada_05
and then Is_Local_Anonymous_Access (Btyp)
and then Object_Access_Level (P) > Type_Access_Level (Btyp)
+ and then Attr_Id = Attribute_Access
then
-- In an instance, this is a runtime check, but one we
-- know will fail, so generate an appropriate warning.
if In_Instance_Body then
- Error_Msg_N
+ Error_Msg_F
("?non-local pointer cannot point to local object", P);
- Error_Msg_N
- ("?Program_Error will be raised at run time", P);
+ Error_Msg_F
+ ("\?Program_Error will be raised at run time", P);
Rewrite (N,
Make_Raise_Program_Error (Loc,
Reason => PE_Accessibility_Check_Failed));
Set_Etype (N, Typ);
+
else
- Error_Msg_N
+ Error_Msg_F
("non-local pointer cannot point to local object", P);
end if;
end if;
if Is_Dependent_Component_Of_Mutable_Object (P) then
- Error_Msg_N
+ Error_Msg_F
("illegal attribute for discriminant-dependent component",
P);
end if;
- -- Check the static matching rule of 3.10.2(27). The
- -- nominal subtype of the prefix must statically
- -- match the designated type.
+ -- Check static matching rule of 3.10.2(27). Nominal subtype
+ -- of the prefix must statically match the designated type.
Nom_Subt := Etype (P);
if Is_Constr_Subt_For_U_Nominal (Nom_Subt) then
- Nom_Subt := Etype (Nom_Subt);
+ Nom_Subt := Base_Type (Nom_Subt);
+ end if;
+
+ Des_Btyp := Designated_Type (Btyp);
+
+ if Ekind (Des_Btyp) = E_Incomplete_Subtype then
+
+ -- Ada 2005 (AI-412): Subtypes of incomplete types visible
+ -- through a limited with clause or regular incomplete
+ -- subtypes.
+
+ if From_With_Type (Des_Btyp)
+ and then Present (Non_Limited_View (Des_Btyp))
+ then
+ Des_Btyp := Non_Limited_View (Des_Btyp);
+ else
+ Des_Btyp := Etype (Des_Btyp);
+ end if;
end if;
if Is_Tagged_Type (Designated_Type (Typ)) then
-- If the attribute is in the context of an access
- -- parameter, then the prefix is allowed to be of
- -- the class-wide type (by AI-127).
+ -- parameter, then the prefix is allowed to be of the
+ -- class-wide type (by AI-127).
if Ekind (Typ) = E_Anonymous_Access_Type then
if not Covers (Designated_Type (Typ), Nom_Subt)
null;
else
- Error_Msg_NE
+ Error_Msg_FE
("type of prefix: & not compatible",
P, Nom_Subt);
- Error_Msg_NE
+ Error_Msg_FE
("\with &, the expected designated type",
P, Designated_Type (Typ));
end if;
(not Is_Class_Wide_Type (Designated_Type (Typ))
and then Is_Class_Wide_Type (Nom_Subt))
then
- Error_Msg_NE
+ Error_Msg_FE
("type of prefix: & is not covered", P, Nom_Subt);
- Error_Msg_NE
+ Error_Msg_FE
("\by &, the expected designated type" &
- " ('R'M 3.10.2 (27))", P, Designated_Type (Typ));
+ " (RM 3.10.2 (27))", P, Designated_Type (Typ));
end if;
if Is_Class_Wide_Type (Designated_Type (Typ))
(N, Etype (Designated_Type (Typ)));
end if;
- elsif not Subtypes_Statically_Match
- (Designated_Type (Base_Type (Typ)), Nom_Subt)
+ -- Ada 2005 (AI-363): Require static matching when designated
+ -- type has discriminants and a constrained partial view, since
+ -- in general objects of such types are mutable, so we can't
+ -- allow the access value to designate a constrained object
+ -- (because access values must be assumed to designate mutable
+ -- objects when designated type does not impose a constraint).
+
+ elsif not Subtypes_Statically_Match (Des_Btyp, Nom_Subt)
and then
not (Has_Discriminants (Designated_Type (Typ))
+ and then not Is_Constrained (Des_Btyp)
and then
- not Is_Constrained
- (Designated_Type (Base_Type (Typ))))
+ (Ada_Version < Ada_05
+ or else
+ not Has_Constrained_Partial_View
+ (Designated_Type (Base_Type (Typ)))))
then
- Error_Msg_N
+ Error_Msg_F
("object subtype must statically match "
& "designated subtype", P);
if Is_Entity_Name (P)
and then Is_Array_Type (Designated_Type (Typ))
then
-
declare
D : constant Node_Id := Declaration_Node (Entity (P));
if Is_Entity_Name (P)
and then not Is_Protected_Type (Scope (Entity (P)))
then
- Error_Msg_N ("context requires a protected subprogram", P);
+ Error_Msg_F ("context requires a protected subprogram", P);
- -- Check accessibility of protected object against that
- -- of the access type, but only on user code, because
- -- the expander creates access references for handlers.
- -- If the context is an anonymous_access_to_protected,
- -- there are no accessibility checks either.
+ -- Check accessibility of protected object against that of the
+ -- access type, but only on user code, because the expander
+ -- creates access references for handlers. If the context is an
+ -- anonymous_access_to_protected, there are no accessibility
+ -- checks either. Omit check entirely for Unrestricted_Access.
elsif Object_Access_Level (P) > Type_Access_Level (Btyp)
and then Comes_From_Source (N)
and then Ekind (Btyp) = E_Access_Protected_Subprogram_Type
- and then No (Original_Access_Type (Typ))
+ and then Attr_Id /= Attribute_Unrestricted_Access
then
Accessibility_Message;
return;
Ekind (Btyp) = E_Anonymous_Access_Subprogram_Type)
and then Ekind (Etype (N)) = E_Access_Protected_Subprogram_Type
then
- Error_Msg_N ("context requires a non-protected subprogram", P);
+ Error_Msg_F ("context requires a non-protected subprogram", P);
end if;
-- The context cannot be a pool-specific type, but this is a
Wrong_Type (N, Typ);
end if;
- Set_Etype (N, Typ);
+ -- The context may be a constrained access type (however ill-
+ -- advised such subtypes might be) so in order to generate a
+ -- constraint check when needed set the type of the attribute
+ -- reference to the base type of the context.
+
+ Set_Etype (N, Btyp);
-- Check for incorrect atomic/volatile reference (RM C.6(12))
if Is_Atomic_Object (P)
and then not Is_Atomic (Designated_Type (Typ))
then
- Error_Msg_N
+ Error_Msg_F
("access to atomic object cannot yield access-to-" &
"non-atomic type", P);
elsif Is_Volatile_Object (P)
and then not Is_Volatile (Designated_Type (Typ))
then
- Error_Msg_N
+ Error_Msg_F
("access to volatile object cannot yield access-to-" &
"non-volatile type", P);
end if;
end if;
+ if Is_Entity_Name (P) then
+ Set_Address_Taken (Entity (P));
+ end if;
+ end Access_Attribute;
+
-------------
-- Address --
-------------
-- is not permitted here, since there is no context to resolve it.
when Attribute_Address | Attribute_Code_Address =>
+ Address_Attribute : begin
-- To be safe, assume that if the address of a variable is taken,
-- it may be modified via this address, so note modification.
Note_Possible_Modification (P);
end if;
- if Nkind (P) in N_Subexpr
+ if Nkind (P) in N_Subexpr
and then Is_Overloaded (P)
then
Get_First_Interp (P, Index, It);
if Present (It.Nam) then
Error_Msg_Name_1 := Aname;
- Error_Msg_N
- ("prefix of % attribute cannot be overloaded", N);
- return;
+ Error_Msg_F
+ ("prefix of % attribute cannot be overloaded", P);
end if;
end if;
if not Is_Entity_Name (P)
- or else not Is_Overloadable (Entity (P))
+ or else not Is_Overloadable (Entity (P))
then
if not Is_Task_Type (Etype (P))
or else Nkind (P) = N_Explicit_Dereference
New_Occurrence_Of (Alias (Entity (P)), Sloc (P)));
end if;
+ if Is_Entity_Name (P) then
+ Set_Address_Taken (Entity (P));
+ end if;
+ end Address_Attribute;
+
---------------
-- AST_Entry --
---------------
when Attribute_Elaborated =>
null;
+ -------------
+ -- Enabled --
+ -------------
+
+ -- Prefix of Enabled attribute is a check name, which must be treated
+ -- specially and not touched by Resolve.
+
+ when Attribute_Enabled =>
+ null;
+
--------------------
-- Mechanism_Code --
--------------------
when others => null;
end case;
+
+ -- If the prefix of the attribute is a class-wide type then it
+ -- will be expanded into a dispatching call to a predefined
+ -- primitive. Therefore we must check for potential violation
+ -- of such restriction.
+
+ if Is_Class_Wide_Type (Etype (P)) then
+ Check_Restriction (No_Dispatching_Calls, N);
+ end if;
end case;
-- Normally the Freezing is done by Resolve but sometimes the Prefix
is
Etyp : Entity_Id := Typ;
- function Has_Specified_Stream_Attribute
- (Typ : Entity_Id;
- Nam : TSS_Name_Type) return Boolean;
- -- True iff there is a visible attribute definition clause specifying
- -- attribute Nam for Typ.
-
- ------------------------------------
- -- Has_Specified_Stream_Attribute --
- ------------------------------------
-
- function Has_Specified_Stream_Attribute
- (Typ : Entity_Id;
- Nam : TSS_Name_Type) return Boolean
- is
- begin
- return False
- or else
- (Nam = TSS_Stream_Input
- and then Has_Specified_Stream_Input (Typ))
- or else
- (Nam = TSS_Stream_Output
- and then Has_Specified_Stream_Output (Typ))
- or else
- (Nam = TSS_Stream_Read
- and then Has_Specified_Stream_Read (Typ))
- or else
- (Nam = TSS_Stream_Write
- and then Has_Specified_Stream_Write (Typ));
- end Has_Specified_Stream_Attribute;
-
-- Start of processing for Stream_Attribute_Available
begin
-- We need some comments in this body ???
- if Has_Specified_Stream_Attribute (Typ, Nam) then
+ if Has_Stream_Attribute_Definition (Typ, Nam) then
return True;
end if;
end if;
if Nam = TSS_Stream_Input
- and then Is_Abstract (Typ)
+ and then Is_Abstract_Type (Typ)
and then not Is_Class_Wide_Type (Typ)
then
return False;
return True;
end if;
- if Nam = TSS_Stream_Input then
- return Ada_Version >= Ada_05
- and then Stream_Attribute_Available (Etyp, TSS_Stream_Read);
- elsif Nam = TSS_Stream_Output then
- return Ada_Version >= Ada_05
- and then Stream_Attribute_Available (Etyp, TSS_Stream_Write);
+ -- In Ada 2005, Input can invoke Read, and Output can invoke Write
+
+ if Nam = TSS_Stream_Input
+ and then Ada_Version >= Ada_05
+ and then Stream_Attribute_Available (Etyp, TSS_Stream_Read)
+ then
+ return True;
+
+ elsif Nam = TSS_Stream_Output
+ and then Ada_Version >= Ada_05
+ and then Stream_Attribute_Available (Etyp, TSS_Stream_Write)
+ then
+ return True;
end if;
-- Case of Read and Write: check for attribute definition clause that
while Etype (Etyp) /= Etyp loop
Etyp := Etype (Etyp);
- if Has_Specified_Stream_Attribute (Etyp, Nam) then
+ if Has_Stream_Attribute_Definition (Etyp, Nam) then
return True;
end if;
end loop;