summaryrefslogtreecommitdiff
path: root/gcc/ada/exp_ch13.adb
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/ada/exp_ch13.adb')
-rw-r--r--gcc/ada/exp_ch13.adb157
1 files changed, 92 insertions, 65 deletions
diff --git a/gcc/ada/exp_ch13.adb b/gcc/ada/exp_ch13.adb
index bbc8458eff5..b1e24128c0b 100644
--- a/gcc/ada/exp_ch13.adb
+++ b/gcc/ada/exp_ch13.adb
@@ -8,7 +8,7 @@
-- --
-- $Revision$
-- --
--- Copyright (C) 1992-2001, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2002, 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- --
@@ -50,6 +50,11 @@ with Uintp; use Uintp;
package body Exp_Ch13 is
+ procedure Expand_External_Tag_Definition (N : Node_Id);
+ -- The code to assign and register an external tag must be elaborated
+ -- after the dispatch table has been created, so the expansion of the
+ -- attribute definition node is delayed until after the type is frozen.
+
------------------------------------------
-- Expand_N_Attribute_Definition_Clause --
------------------------------------------
@@ -115,70 +120,6 @@ package body Exp_Ch13 is
end if;
------------------
- -- External_Tag --
- ------------------
-
- -- For the rep clause "for x'external_tag use y" generate:
-
- -- xV : constant string := y;
- -- Set_External_Tag (x'tag, xV'Address);
- -- Register_Tag (x'tag);
-
- -- note that register_tag has been delayed up to now because
- -- the external_tag must be set before resistering.
-
- when Attribute_External_Tag => External_Tag : declare
- E : Entity_Id;
- Old_Val : String_Id := Strval (Expr_Value_S (Exp));
- New_Val : String_Id;
-
- begin
- -- Create a new nul terminated string if it is not already
-
- if String_Length (Old_Val) > 0
- and then Get_String_Char (Old_Val, String_Length (Old_Val)) = 0
- then
- New_Val := Old_Val;
- else
- Start_String (Old_Val);
- Store_String_Char (Get_Char_Code (ASCII.NUL));
- New_Val := End_String;
- end if;
-
- E :=
- Make_Defining_Identifier (Loc,
- New_External_Name (Chars (Ent), 'A'));
-
- Insert_Action (N,
- Make_Object_Declaration (Loc,
- Defining_Identifier => E,
- Constant_Present => True,
- Object_Definition =>
- New_Reference_To (Standard_String, Loc),
- Expression =>
- Make_String_Literal (Loc, Strval => New_Val)));
-
- Insert_Actions (N, New_List (
- Make_Procedure_Call_Statement (Loc,
- Name => New_Reference_To (RTE (RE_Set_External_Tag), Loc),
- Parameter_Associations => New_List (
- Make_Attribute_Reference (Loc,
- Attribute_Name => Name_Tag,
- Prefix => New_Occurrence_Of (Ent, Loc)),
-
- Make_Attribute_Reference (Loc,
- Attribute_Name => Name_Address,
- Prefix => New_Occurrence_Of (E, Loc)))),
-
- Make_Procedure_Call_Statement (Loc,
- Name => New_Reference_To (RTE (RE_Register_Tag), Loc),
- Parameter_Associations => New_List (
- Make_Attribute_Reference (Loc,
- Attribute_Name => Name_Tag,
- Prefix => New_Occurrence_Of (Ent, Loc))))));
- end External_Tag;
-
- ------------------
-- Storage_Size --
------------------
@@ -224,6 +165,76 @@ package body Exp_Ch13 is
end Expand_N_Attribute_Definition_Clause;
+ -------------------------------------
+ -- Expand_External_Tag_Definition --
+ -------------------------------------
+
+ procedure Expand_External_Tag_Definition (N : Node_Id) is
+ Loc : constant Source_Ptr := Sloc (N);
+ Ent : constant Entity_Id := Entity (Name (N));
+ E : Entity_Id;
+ Old_Val : String_Id := Strval (Expr_Value_S (Expression (N)));
+ New_Val : String_Id;
+
+ begin
+
+ -- For the rep clause "for x'external_tag use y" generate:
+
+ -- xV : constant string := y;
+ -- Set_External_Tag (x'tag, xV'Address);
+ -- Register_Tag (x'tag);
+
+ -- note that register_tag has been delayed up to now because
+ -- the external_tag must be set before registering.
+
+ -- Create a new nul terminated string if it is not already
+
+ if String_Length (Old_Val) > 0
+ and then Get_String_Char (Old_Val, String_Length (Old_Val)) = 0
+ then
+ New_Val := Old_Val;
+ else
+ Start_String (Old_Val);
+ Store_String_Char (Get_Char_Code (ASCII.NUL));
+ New_Val := End_String;
+ end if;
+
+ E :=
+ Make_Defining_Identifier (Loc,
+ New_External_Name (Chars (Ent), 'A'));
+
+ -- The generated actions must be elaborated at the subsequent
+ -- freeze point, not at the point of the attribute definition.
+
+ Append_Freeze_Action (Ent,
+ Make_Object_Declaration (Loc,
+ Defining_Identifier => E,
+ Constant_Present => True,
+ Object_Definition =>
+ New_Reference_To (Standard_String, Loc),
+ Expression =>
+ Make_String_Literal (Loc, Strval => New_Val)));
+
+ Append_Freeze_Actions (Ent, New_List (
+ Make_Procedure_Call_Statement (Loc,
+ Name => New_Reference_To (RTE (RE_Set_External_Tag), Loc),
+ Parameter_Associations => New_List (
+ Make_Attribute_Reference (Loc,
+ Attribute_Name => Name_Tag,
+ Prefix => New_Occurrence_Of (Ent, Loc)),
+
+ Make_Attribute_Reference (Loc,
+ Attribute_Name => Name_Address,
+ Prefix => New_Occurrence_Of (E, Loc)))),
+
+ Make_Procedure_Call_Statement (Loc,
+ Name => New_Reference_To (RTE (RE_Register_Tag), Loc),
+ Parameter_Associations => New_List (
+ Make_Attribute_Reference (Loc,
+ Attribute_Name => Name_Tag,
+ Prefix => New_Occurrence_Of (Ent, Loc))))));
+ end Expand_External_Tag_Definition;
+
----------------------------
-- Expand_N_Freeze_Entity --
----------------------------
@@ -309,6 +320,22 @@ package body Exp_Ch13 is
if Is_Enumeration_Type (E) then
Build_Enumeration_Image_Tables (E, N);
+
+ elsif Is_Tagged_Type (E)
+ and then Is_First_Subtype (E)
+ then
+
+ -- Check for a definition of External_Tag, whose expansion must
+ -- be delayed until the dispatch table is built.
+
+ declare
+ Def : Node_Id :=
+ Get_Attribute_Definition_Clause (E, Attribute_External_Tag);
+ begin
+ if Present (Def) then
+ Expand_External_Tag_Definition (Def);
+ end if;
+ end;
end if;
-- If subprogram, freeze the subprogram