[multiple changes]

2016-04-27  Hristian Kirtchev  <kirtchev@adacore.com>

	* aspects.ads Aspects Export and Import do not require delay. They
	were classified as delayed aspects, but treated as non-delayed
	by the analysis of aspects.
	* freeze.adb (Copy_Import_Pragma): New routine.
	(Wrap_Imported_Subprogram): Copy the import pragma by first
	resetting all semantic fields to avoid an infinite loop when
	performing the copy.
	* sem_ch13.adb (Analyze_Aspects_At_Freeze_Point): Add
	comment on the processing of aspects Export and Import
	at the freeze point.
	(Analyze_Aspect_Convention: New routine.
	(Analyze_Aspect_Export_Import): New routine.
	(Analyze_Aspect_External_Link_Name): New routine.
	(Analyze_Aspect_External_Or_Link_Name): Removed.
	(Analyze_Aspect_Specifications): Factor out the analysis of
	aspects Convention, Export, External_Name, Import, and Link_Name
	in their respective routines.  Aspects Export and Import should
	not generate a Boolean pragma because their corresponding pragmas
	have a very different syntax.
	(Build_Export_Import_Pragma): New routine.
	(Get_Interfacing_Aspects): New routine.

2016-04-27  Eric Botcazou  <ebotcazou@adacore.com>

	* inline.adb (Add_Inlined_Body): Overhaul implementation,
	robustify handling of -gnatn1, add special treatment for
	expression functions.

2016-04-27  Doug Rupp  <rupp@adacore.com>

	* g-traceb.ads: Update comment.
	* exp_ch2.adb: minor style fix in object declaration

From-SVN: r235483
This commit is contained in:
Arnaud Charlet 2016-04-27 13:01:35 +02:00
parent 2a253c5bba
commit 2e885a6f7c
7 changed files with 685 additions and 291 deletions

View File

@ -1,3 +1,38 @@
2016-04-27 Hristian Kirtchev <kirtchev@adacore.com>
* aspects.ads Aspects Export and Import do not require delay. They
were classified as delayed aspects, but treated as non-delayed
by the analysis of aspects.
* freeze.adb (Copy_Import_Pragma): New routine.
(Wrap_Imported_Subprogram): Copy the import pragma by first
resetting all semantic fields to avoid an infinite loop when
performing the copy.
* sem_ch13.adb (Analyze_Aspects_At_Freeze_Point): Add
comment on the processing of aspects Export and Import
at the freeze point.
(Analyze_Aspect_Convention: New routine.
(Analyze_Aspect_Export_Import): New routine.
(Analyze_Aspect_External_Link_Name): New routine.
(Analyze_Aspect_External_Or_Link_Name): Removed.
(Analyze_Aspect_Specifications): Factor out the analysis of
aspects Convention, Export, External_Name, Import, and Link_Name
in their respective routines. Aspects Export and Import should
not generate a Boolean pragma because their corresponding pragmas
have a very different syntax.
(Build_Export_Import_Pragma): New routine.
(Get_Interfacing_Aspects): New routine.
2016-04-27 Eric Botcazou <ebotcazou@adacore.com>
* inline.adb (Add_Inlined_Body): Overhaul implementation,
robustify handling of -gnatn1, add special treatment for
expression functions.
2016-04-27 Doug Rupp <rupp@adacore.com>
* g-traceb.ads: Update comment.
* exp_ch2.adb: minor style fix in object declaration
2016-04-27 Hristian Kirtchev <kirtchev@adacore.com>
* sem_elab.adb (Check_Internal_Call): Do not

View File

@ -6,7 +6,7 @@
-- --
-- S p e c --
-- --
-- Copyright (C) 2010-2015, Free Software Foundation, Inc. --
-- Copyright (C) 2010-2016, 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- --
@ -652,12 +652,10 @@ package Aspects is
Aspect_Dispatching_Domain => Always_Delay,
Aspect_Dynamic_Predicate => Always_Delay,
Aspect_Elaborate_Body => Always_Delay,
Aspect_Export => Always_Delay,
Aspect_External_Name => Always_Delay,
Aspect_External_Tag => Always_Delay,
Aspect_Favor_Top_Level => Always_Delay,
Aspect_Implicit_Dereference => Always_Delay,
Aspect_Import => Always_Delay,
Aspect_Independent => Always_Delay,
Aspect_Independent_Components => Always_Delay,
Aspect_Inline => Always_Delay,
@ -726,9 +724,11 @@ package Aspects is
Aspect_Disable_Controlled => Never_Delay,
Aspect_Effective_Reads => Never_Delay,
Aspect_Effective_Writes => Never_Delay,
Aspect_Export => Never_Delay,
Aspect_Extensions_Visible => Never_Delay,
Aspect_Ghost => Never_Delay,
Aspect_Global => Never_Delay,
Aspect_Import => Never_Delay,
Aspect_Initial_Condition => Never_Delay,
Aspect_Initializes => Never_Delay,
Aspect_No_Elaboration_Code_All => Never_Delay,

View File

@ -413,7 +413,7 @@ package body Exp_Ch2 is
and then (Is_Atomic (E) or else Is_Atomic (Etype (E)))
then
declare
Set : Boolean;
Set : Boolean;
begin
-- If variable is atomic, but type is not, setting depends on

View File

@ -4676,14 +4676,65 @@ package body Freeze is
-- for the subprogram body that calls the inner procedure.
procedure Wrap_Imported_Subprogram (E : Entity_Id) is
function Copy_Import_Pragma return Node_Id;
-- Obtain a copy of the Import_Pragma which belongs to subprogram E
------------------------
-- Copy_Import_Pragma --
------------------------
function Copy_Import_Pragma return Node_Id is
-- The subprogram should have an import pragma, otherwise it does
-- need a wrapper.
Prag : constant Node_Id := Import_Pragma (E);
pragma Assert (Present (Prag));
-- Save all semantic fields of the pragma
Save_Asp : constant Node_Id := Corresponding_Aspect (Prag);
Save_From : constant Boolean := From_Aspect_Specification (Prag);
Save_Prag : constant Node_Id := Next_Pragma (Prag);
Save_Rep : constant Node_Id := Next_Rep_Item (Prag);
Result : Node_Id;
begin
-- Reset all semantic fields. This avoids a potential infinite
-- loop when the pragma comes from an aspect as the duplication
-- will copy the aspect, then copy the corresponding pragma and
-- so on.
Set_Corresponding_Aspect (Prag, Empty);
Set_From_Aspect_Specification (Prag, False);
Set_Next_Pragma (Prag, Empty);
Set_Next_Rep_Item (Prag, Empty);
Result := Copy_Separate_Tree (Prag);
-- Restore the original semantic fields
Set_Corresponding_Aspect (Prag, Save_Asp);
Set_From_Aspect_Specification (Prag, Save_From);
Set_Next_Pragma (Prag, Save_Prag);
Set_Next_Rep_Item (Prag, Save_Rep);
return Result;
end Copy_Import_Pragma;
-- Local variables
Loc : constant Source_Ptr := Sloc (E);
CE : constant Name_Id := Chars (E);
Spec : Node_Id;
Parms : List_Id;
Stmt : Node_Id;
Iprag : Node_Id;
Bod : Node_Id;
Forml : Entity_Id;
Parms : List_Id;
Prag : Node_Id;
Spec : Node_Id;
Stmt : Node_Id;
-- Start of processing for Wrap_Imported_Subprogram
begin
-- Nothing to do if not imported
@ -4706,18 +4757,14 @@ package body Freeze is
-- generates the right visibility, and that is exactly what the
-- calls to Copy_Separate_Tree give us.
-- Acquire copy of Inline pragma, and indicate that it does not
-- come from an aspect, as it applies to an internal entity.
Iprag := Copy_Separate_Tree (Import_Pragma (E));
Set_From_Aspect_Specification (Iprag, False);
Prag := Copy_Import_Pragma;
-- Fix up spec to be not imported any more
Set_Is_Imported (E, False);
Set_Interface_Name (E, Empty);
Set_Has_Completion (E, False);
Set_Import_Pragma (E, Empty);
Set_Interface_Name (E, Empty);
Set_Is_Imported (E, False);
-- Grab the subprogram declaration and specification
@ -4757,13 +4804,12 @@ package body Freeze is
Copy_Separate_Tree (Spec),
Declarations => New_List (
Make_Subprogram_Declaration (Loc,
Specification =>
Copy_Separate_Tree (Spec)),
Iprag),
Specification => Copy_Separate_Tree (Spec)),
Prag),
Handled_Statement_Sequence =>
Make_Handled_Sequence_Of_Statements (Loc,
Statements => New_List (Stmt),
End_Label => Make_Identifier (Loc, CE)));
Statements => New_List (Stmt),
End_Label => Make_Identifier (Loc, CE)));
-- Append the body to freeze result

View File

@ -62,6 +62,7 @@
-- GNU/Linux PowerPC
-- LynxOS x86
-- LynxOS 178 xcoff PowerPC
-- LynxOS 178 elf PowerPC
-- Solaris x86
-- Solaris sparc
-- VxWorks PowerPC

View File

@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
-- Copyright (C) 1992-2015, Free Software Foundation, Inc. --
-- Copyright (C) 1992-2016, 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- --
@ -390,6 +390,40 @@ package body Inline is
return;
end if;
-- Find out whether the call must be inlined. Unless the result is
-- Dont_Inline, Must_Inline also creates an edge for the call in the
-- callgraph; however, it will not be activated until after Is_Called
-- is set on the subprogram.
Level := Must_Inline;
if Level = Dont_Inline then
return;
end if;
-- If the call was generated by the compiler and is to a subprogram in
-- a run-time unit, we need to suppress debugging information for it,
-- so that the code that is eventually inlined will not affect the
-- debugging of the program. We do not do it if the call comes from
-- source because, even if the call is inlined, the user may expect it
-- to be present in the debugging information.
if not Comes_From_Source (N)
and then In_Extended_Main_Source_Unit (N)
and then
Is_Predefined_File_Name (Unit_File_Name (Get_Source_Unit (E)))
then
Set_Needs_Debug_Info (E, False);
end if;
-- If the subprogram is an expression function, then there is no need to
-- load any package body since the body of the function is in the spec.
if Is_Expression_Function (E) then
Set_Is_Called (E);
return;
end if;
-- Find unit containing E, and add to list of inlined bodies if needed.
-- If the body is already present, no need to load any other unit. This
-- is the case for an initialization procedure, which appears in the
@ -403,77 +437,48 @@ package body Inline is
-- no enclosing package to retrieve. In this case, it is the body of
-- the function that will have to be loaded.
Level := Must_Inline;
declare
Pack : constant Entity_Id := Get_Code_Unit_Entity (E);
if Level /= Dont_Inline then
declare
Pack : constant Entity_Id := Get_Code_Unit_Entity (E);
begin
if Pack = E then
Set_Is_Called (E);
Inlined_Bodies.Increment_Last;
Inlined_Bodies.Table (Inlined_Bodies.Last) := E;
begin
-- Ensure that Analyze_Inlined_Bodies will be invoked after
-- completing the analysis of the current unit.
elsif Ekind (Pack) = E_Package then
Set_Is_Called (E);
Inline_Processing_Required := True;
if Is_Generic_Instance (Pack) then
null;
if Pack = E then
-- Do not inline the package if the subprogram is an init proc
-- or other internally generated subprogram, because in that
-- case the subprogram body appears in the same unit that
-- declares the type, and that body is visible to the back end.
-- Do not inline it either if it is in the main unit.
-- Extend the -gnatn2 processing to -gnatn1 for Inline_Always
-- calls if the back-end takes care of inlining the call.
-- Library-level inlined function. Add function itself to
-- list of needed units.
Set_Is_Called (E);
Inlined_Bodies.Increment_Last;
Inlined_Bodies.Table (Inlined_Bodies.Last) := E;
elsif Ekind (Pack) = E_Package then
Set_Is_Called (E);
if Is_Generic_Instance (Pack) then
null;
-- Do not inline the package if the subprogram is an init proc
-- or other internally generated subprogram, because in that
-- case the subprogram body appears in the same unit that
-- declares the type, and that body is visible to the back end.
-- Do not inline it either if it is in the main unit.
elsif Level = Inline_Package
and then not Is_Inlined (Pack)
and then not Is_Internal (E)
and then not In_Main_Unit_Or_Subunit (Pack)
then
Set_Is_Inlined (Pack);
Inlined_Bodies.Increment_Last;
Inlined_Bodies.Table (Inlined_Bodies.Last) := Pack;
-- Extend the -gnatn2 processing to -gnatn1 for Inline_Always
-- calls if the back-end takes care of inlining the call.
elsif Level = Inline_Call
and then Has_Pragma_Inline_Always (E)
and then Back_End_Inlining
then
Set_Is_Inlined (Pack);
Inlined_Bodies.Increment_Last;
Inlined_Bodies.Table (Inlined_Bodies.Last) := Pack;
end if;
end if;
-- If the call was generated by the compiler and is to a function
-- in a run-time unit, we need to suppress debugging information
-- for it, so that the code that is eventually inlined will not
-- affect debugging of the program. We do not do it if the call
-- comes from source because, even if the call is inlined, the
-- user may expect it to be present in the debugging information.
if not Comes_From_Source (N)
and then In_Extended_Main_Source_Unit (N)
and then
Is_Predefined_File_Name (Unit_File_Name (Get_Source_Unit (E)))
elsif (Level = Inline_Package
or else (Level = Inline_Call
and then Has_Pragma_Inline_Always (E)
and then Back_End_Inlining))
and then not Is_Inlined (Pack)
and then not Is_Internal (E)
and then not In_Main_Unit_Or_Subunit (Pack)
then
Set_Needs_Debug_Info (E, False);
Set_Is_Inlined (Pack);
Inlined_Bodies.Increment_Last;
Inlined_Bodies.Table (Inlined_Bodies.Last) := Pack;
end if;
end;
end if;
end if;
-- Ensure that Analyze_Inlined_Bodies will be invoked after
-- completing the analysis of the current unit.
Inline_Processing_Required := True;
end;
end Add_Inlined_Body;
----------------------------

View File

@ -101,6 +101,13 @@ package body Sem_Ch13 is
-- list is stored in Static_Discrete_Predicate (Typ), and the Expr is
-- rewritten as a canonicalized membership operation.
function Build_Export_Import_Pragma
(Asp : Node_Id;
Id : Entity_Id) return Node_Id;
-- Create the corresponding pragma for aspect Export or Import denoted by
-- Asp. Id is the related entity subject to the aspect. Return Empty when
-- the expression of aspect Asp evaluates to False or is erroneous.
function Build_Predicate_Function_Declaration
(Typ : Entity_Id) return Node_Id;
-- Build the declaration for a predicate function. The declaration is built
@ -136,6 +143,27 @@ package body Sem_Ch13 is
-- Uint value. If the value is inappropriate, then error messages are
-- posted as required, and a value of No_Uint is returned.
procedure Get_Interfacing_Aspects
(Iface_Asp : Node_Id;
Conv_Asp : out Node_Id;
EN_Asp : out Node_Id;
Expo_Asp : out Node_Id;
Imp_Asp : out Node_Id;
LN_Asp : out Node_Id;
Do_Checks : Boolean := False);
-- Given a single interfacing aspect Iface_Asp, retrieve other interfacing
-- aspects that apply to the same related entity. The aspects considered by
-- this routine are as follows:
--
-- Conv_Asp - aspect Convention
-- EN_Asp - aspect External_Name
-- Expo_Asp - aspect Export
-- Imp_Asp - aspect Import
-- LN_Asp - aspect Link_Name
--
-- When flag Do_Checks is set, this routine will flag duplicate uses of
-- aspects.
function Is_Operational_Item (N : Node_Id) return Boolean;
-- A specification for a stream attribute is allowed before the full type
-- is declared, as explained in AI-00137 and the corrigendum. Attributes
@ -730,10 +758,6 @@ package body Sem_Ch13 is
-------------------------------------
procedure Analyze_Aspects_At_Freeze_Point (E : Entity_Id) is
ASN : Node_Id;
A_Id : Aspect_Id;
Ritem : Node_Id;
procedure Analyze_Aspect_Default_Value (ASN : Node_Id);
-- This routine analyzes an Aspect_Default_[Component_]Value denoted by
-- the aspect specification node ASN.
@ -771,6 +795,7 @@ package body Sem_Ch13 is
----------------------------------
procedure Analyze_Aspect_Default_Value (ASN : Node_Id) is
A_Id : constant Aspect_Id := Get_Aspect_Id (ASN);
Ent : constant Entity_Id := Entity (ASN);
Expr : constant Node_Id := Expression (ASN);
Id : constant Node_Id := Identifier (ASN);
@ -817,7 +842,8 @@ package body Sem_Ch13 is
---------------------------------
procedure Inherit_Delayed_Rep_Aspects (ASN : Node_Id) is
P : constant Entity_Id := Entity (ASN);
A_Id : constant Aspect_Id := Get_Aspect_Id (ASN);
P : constant Entity_Id := Entity (ASN);
-- Entithy for parent type
N : Node_Id;
@ -1013,8 +1039,6 @@ package body Sem_Ch13 is
Expr : constant Node_Id := Expression (ASN);
Loc : constant Source_Ptr := Sloc (ASN);
Prag : Node_Id;
procedure Check_False_Aspect_For_Derived_Type;
-- This procedure checks for the case of a false aspect for a derived
-- type, which improperly tries to cancel an aspect inherited from
@ -1088,6 +1112,10 @@ package body Sem_Ch13 is
("derived type& inherits aspect%, cannot cancel", Expr, E);
end Check_False_Aspect_For_Derived_Type;
-- Local variables
Prag : Node_Id;
-- Start of processing for Make_Pragma_From_Boolean_Aspect
begin
@ -1101,12 +1129,11 @@ package body Sem_Ch13 is
else
Prag :=
Make_Pragma (Loc,
Pragma_Identifier =>
Make_Identifier (Sloc (Ident), Chars (Ident)),
Pragma_Argument_Associations => New_List (
Make_Pragma_Argument_Association (Sloc (Ident),
Expression => New_Occurrence_Of (Ent, Sloc (Ident)))),
Pragma_Identifier =>
Make_Identifier (Sloc (Ident), Chars (Ident)));
Expression => New_Occurrence_Of (Ent, Sloc (Ident)))));
Set_From_Aspect_Specification (Prag, True);
Set_Corresponding_Aspect (Prag, ASN);
@ -1116,6 +1143,12 @@ package body Sem_Ch13 is
end if;
end Make_Pragma_From_Boolean_Aspect;
-- Local variables
A_Id : Aspect_Id;
ASN : Node_Id;
Ritem : Node_Id;
-- Start of processing for Analyze_Aspects_At_Freeze_Point
begin
@ -1142,7 +1175,25 @@ package body Sem_Ch13 is
when Boolean_Aspects |
Library_Unit_Aspects =>
Make_Pragma_From_Boolean_Aspect (ASN);
-- Aspects Export and Import require special handling.
-- Both are by definition Boolean and may benefit from
-- forward references, however their expressions are
-- treated as static. In addition, the syntax of their
-- corresponding pragmas requires extra "pieces" which
-- may also contain forward references. To account for
-- all of this, the corresponding pragma is created by
-- Analyze_Aspect_Export_Import, but is not analyzed as
-- the complete analysis must happen now.
if A_Id = Aspect_Export or else A_Id = Aspect_Import then
null;
-- Otherwise create a corresponding pragma
else
Make_Pragma_From_Boolean_Aspect (ASN);
end if;
-- Special handling for aspects that don't correspond to
-- pragmas/attributes.
@ -1435,8 +1486,9 @@ package body Sem_Ch13 is
-- Insert pragmas/attribute definition clause after this node when no
-- delayed analysis is required.
-- Start of processing for Analyze_Aspect_Specifications
-- Start of processing for Analyze_Aspect_Specifications
begin
-- The general processing involves building an attribute definition
-- clause or a pragma node that corresponds to the aspect. Then in order
-- to delay the evaluation of this aspect to the freeze point, we attach
@ -1456,7 +1508,6 @@ package body Sem_Ch13 is
-- of visibility for the expression analysis. Thus, we just insert
-- the pragma after the node N.
begin
pragma Assert (Present (L));
-- Loop through aspects
@ -1478,8 +1529,14 @@ package body Sem_Ch13 is
-- Source location of expression, modified when we split PPC's. It
-- is set below when Expr is present.
procedure Analyze_Aspect_External_Or_Link_Name;
-- Perform analysis of the External_Name or Link_Name aspects
procedure Analyze_Aspect_Convention;
-- Perform analysis of aspect Convention
procedure Analyze_Aspect_Export_Import;
-- Perform analysis of aspects Export or Import
procedure Analyze_Aspect_External_Link_Name;
-- Perform analysis of aspects External_Name or Link_Name
procedure Analyze_Aspect_Implicit_Dereference;
-- Perform analysis of the Implicit_Dereference aspects
@ -1496,35 +1553,193 @@ package body Sem_Ch13 is
-- True, and sets Corresponding_Aspect to point to the aspect.
-- The resulting pragma is assigned to Aitem.
------------------------------------------
-- Analyze_Aspect_External_Or_Link_Name --
------------------------------------------
-------------------------------
-- Analyze_Aspect_Convention --
-------------------------------
procedure Analyze_Aspect_Convention is
Conv : Node_Id;
Dummy_1 : Node_Id;
Dummy_2 : Node_Id;
Dummy_3 : Node_Id;
Expo : Node_Id;
Imp : Node_Id;
procedure Analyze_Aspect_External_Or_Link_Name is
begin
-- Verify that there is an Import/Export aspect defined for the
-- entity. The processing of that aspect in turn checks that
-- there is a Convention aspect declared. The pragma is
-- constructed when processing the Convention aspect.
-- Obtain all interfacing aspects that apply to the related
-- entity.
declare
A : Node_Id;
Get_Interfacing_Aspects
(Iface_Asp => Aspect,
Conv_Asp => Dummy_1,
EN_Asp => Dummy_2,
Expo_Asp => Expo,
Imp_Asp => Imp,
LN_Asp => Dummy_3,
Do_Checks => True);
begin
A := First (L);
while Present (A) loop
exit when Nam_In (Chars (Identifier (A)), Name_Export,
Name_Import);
Next (A);
end loop;
-- The related entity is subject to aspect Export or Import.
-- Do not process Convention now because it must be analysed
-- as part of Export or Import.
if No (A) then
Error_Msg_N
("missing Import/Export for Link/External name",
Aspect);
if Present (Expo) or else Present (Imp) then
return;
-- Otherwise Convention appears by itself
else
-- The aspect specifies a particular convention
if Present (Expr) then
Conv := New_Copy_Tree (Expr);
-- Otherwise assume convention Ada
else
Conv := Make_Identifier (Loc, Name_Ada);
end if;
end;
end Analyze_Aspect_External_Or_Link_Name;
-- Generate:
-- pragma Convention (<Conv>, <E>);
Make_Aitem_Pragma
(Pragma_Name => Name_Convention,
Pragma_Argument_Associations => New_List (
Make_Pragma_Argument_Association (Loc,
Expression => Conv),
Make_Pragma_Argument_Association (Loc,
Expression => New_Occurrence_Of (E, Loc))));
Decorate (Aspect, Aitem);
Insert_Pragma (Aitem);
end if;
end Analyze_Aspect_Convention;
----------------------------------
-- Analyze_Aspect_Export_Import --
----------------------------------
procedure Analyze_Aspect_Export_Import is
Dummy_1 : Node_Id;
Dummy_2 : Node_Id;
Dummy_3 : Node_Id;
Expo : Node_Id;
Imp : Node_Id;
begin
-- Obtain all interfacing aspects that apply to the related
-- entity.
Get_Interfacing_Aspects
(Iface_Asp => Aspect,
Conv_Asp => Dummy_1,
EN_Asp => Dummy_2,
Expo_Asp => Expo,
Imp_Asp => Imp,
LN_Asp => Dummy_3,
Do_Checks => True);
-- The related entity cannot be subject to both aspects Export
-- and Import.
if Present (Expo) and then Present (Imp) then
Error_Msg_N
("incompatible interfacing aspects given for &", E);
Error_Msg_Sloc := Sloc (Expo);
Error_Msg_N ("\aspect `Export` #", E);
Error_Msg_Sloc := Sloc (Imp);
Error_Msg_N ("\aspect `Import` #", E);
end if;
-- A variable is most likely modified from the outside. Take
-- Take the optimistic approach to avoid spurious errors.
if Ekind (E) = E_Variable then
Set_Never_Set_In_Source (E, False);
end if;
-- Resolve the expression of an Import or Export here, and
-- require it to be of type Boolean and static. This is not
-- quite right, because in general this should be delayed,
-- but that seems tricky for these, because normally Boolean
-- aspects are replaced with pragmas at the freeze point in
-- Make_Pragma_From_Boolean_Aspect.
if not Present (Expr)
or else Is_True (Static_Boolean (Expr))
then
if A_Id = Aspect_Import then
Set_Has_Completion (E);
Set_Is_Imported (E);
-- An imported object cannot be explicitly initialized
if Nkind (N) = N_Object_Declaration
and then Present (Expression (N))
then
Error_Msg_N
("imported entities cannot be initialized "
& "(RM B.1(24))", Expression (N));
end if;
else
pragma Assert (A_Id = Aspect_Export);
Set_Is_Exported (E);
end if;
-- Create the proper form of pragma Export or Import taking
-- into account Conversion, External_Name, and Link_Name.
Aitem := Build_Export_Import_Pragma (Aspect, E);
end if;
end Analyze_Aspect_Export_Import;
---------------------------------------
-- Analyze_Aspect_External_Link_Name --
---------------------------------------
procedure Analyze_Aspect_External_Link_Name is
Dummy_1 : Node_Id;
Dummy_2 : Node_Id;
Dummy_3 : Node_Id;
Expo : Node_Id;
Imp : Node_Id;
begin
-- Obtain all interfacing aspects that apply to the related
-- entity.
Get_Interfacing_Aspects
(Iface_Asp => Aspect,
Conv_Asp => Dummy_1,
EN_Asp => Dummy_2,
Expo_Asp => Expo,
Imp_Asp => Imp,
LN_Asp => Dummy_3,
Do_Checks => True);
-- Ensure that aspect External_Name applies to aspect Export or
-- Import.
if A_Id = Aspect_External_Name then
if No (Expo) and then No (Imp) then
Error_Msg_N
("aspect `External_Name` requires aspect `Import` or "
& "`Export`", Aspect);
end if;
-- Otherwise ensure that aspect Link_Name applies to aspect
-- Export or Import.
else
pragma Assert (A_Id = Aspect_Link_Name);
if No (Expo) and then No (Imp) then
Error_Msg_N
("aspect `Link_Name` requires aspect `Import` or "
& "`Export`", Aspect);
end if;
end if;
end Analyze_Aspect_External_Link_Name;
-----------------------------------------
-- Analyze_Aspect_Implicit_Dereference --
@ -1561,8 +1776,7 @@ package body Sem_Ch13 is
-- Error if no proper access discriminant
if No (Disc) then
Error_Msg_NE
("not an access discriminant of&", Expr, E);
Error_Msg_NE ("not an access discriminant of&", Expr, E);
return;
end if;
end if;
@ -1578,8 +1792,9 @@ package body Sem_Ch13 is
if Present (Parent_Disc)
and then Corresponding_Discriminant (Disc) /= Parent_Disc
then
Error_Msg_N ("reference discriminant does not match " &
"discriminant of parent type", Expr);
Error_Msg_N
("reference discriminant does not match discriminant "
& "of parent type", Expr);
end if;
end if;
end Analyze_Aspect_Implicit_Dereference;
@ -2040,101 +2255,16 @@ package body Sem_Ch13 is
-- Convention
when Aspect_Convention =>
when Aspect_Convention =>
Analyze_Aspect_Convention;
goto Continue;
-- The aspect may be part of the specification of an import
-- or export pragma. Scan the aspect list to gather the
-- other components, if any. The name of the generated
-- pragma is one of Convention/Import/Export.
-- External_Name, Link_Name
declare
Args : constant List_Id := New_List (
Make_Pragma_Argument_Association (Sloc (Expr),
Expression => Relocate_Node (Expr)),
Make_Pragma_Argument_Association (Sloc (Ent),
Expression => Ent));
Imp_Exp_Seen : Boolean := False;
-- Flag set when aspect Import or Export has been seen
Imp_Seen : Boolean := False;
-- Flag set when aspect Import has been seen
Asp : Node_Id;
Asp_Nam : Name_Id;
Extern_Arg : Node_Id;
Link_Arg : Node_Id;
Prag_Nam : Name_Id;
begin
Extern_Arg := Empty;
Link_Arg := Empty;
Prag_Nam := Chars (Id);
Asp := First (L);
while Present (Asp) loop
Asp_Nam := Chars (Identifier (Asp));
-- Aspects Import and Export take precedence over
-- aspect Convention. As a result the generated pragma
-- must carry the proper interfacing aspect's name.
if Nam_In (Asp_Nam, Name_Import, Name_Export) then
if Imp_Exp_Seen then
Error_Msg_N ("conflicting", Asp);
else
Imp_Exp_Seen := True;
if Asp_Nam = Name_Import then
Imp_Seen := True;
end if;
end if;
Prag_Nam := Asp_Nam;
-- Aspect External_Name adds an extra argument to the
-- generated pragma.
elsif Asp_Nam = Name_External_Name then
Extern_Arg :=
Make_Pragma_Argument_Association (Loc,
Chars => Asp_Nam,
Expression => Relocate_Node (Expression (Asp)));
-- Aspect Link_Name adds an extra argument to the
-- generated pragma.
elsif Asp_Nam = Name_Link_Name then
Link_Arg :=
Make_Pragma_Argument_Association (Loc,
Chars => Asp_Nam,
Expression => Relocate_Node (Expression (Asp)));
end if;
Next (Asp);
end loop;
-- Assemble the full argument list
if Present (Extern_Arg) then
Append_To (Args, Extern_Arg);
end if;
if Present (Link_Arg) then
Append_To (Args, Link_Arg);
end if;
Make_Aitem_Pragma
(Pragma_Argument_Associations => Args,
Pragma_Name => Prag_Nam);
-- Store the generated pragma Import in the related
-- subprogram.
if Imp_Seen and then Is_Subprogram (E) then
Set_Import_Pragma (E, Aitem);
end if;
end;
when Aspect_External_Name |
Aspect_Link_Name =>
Analyze_Aspect_External_Link_Name;
goto Continue;
-- CPU, Interrupt_Priority, Priority
@ -2937,8 +3067,9 @@ package body Sem_Ch13 is
if not (Is_Array_Type (E)
and then Is_Scalar_Type (Component_Type (E)))
then
Error_Msg_N ("aspect Default_Component_Value can only "
& "apply to an array of scalar components", N);
Error_Msg_N
("aspect Default_Component_Value can only apply to an "
& "array of scalar components", N);
end if;
Aitem := Empty;
@ -2956,13 +3087,6 @@ package body Sem_Ch13 is
Analyze_Aspect_Implicit_Dereference;
goto Continue;
-- External_Name, Link_Name
when Aspect_External_Name |
Aspect_Link_Name =>
Analyze_Aspect_External_Or_Link_Name;
goto Continue;
-- Dimension
when Aspect_Dimension =>
@ -3187,61 +3311,8 @@ package body Sem_Ch13 is
goto Continue;
elsif A_Id = Aspect_Import or else A_Id = Aspect_Export then
-- For the case of aspects Import and Export, we don't
-- consider that we know the entity is never set in the
-- source, since it is is likely modified outside the
-- program.
-- Note: one might think that the analysis of the
-- resulting pragma would take care of that, but
-- that's not the case since it won't be from source.
if Ekind (E) = E_Variable then
Set_Never_Set_In_Source (E, False);
end if;
-- In older versions of Ada the corresponding pragmas
-- specified a Convention. In Ada 2012 the convention is
-- specified as a separate aspect, and it is optional,
-- given that it defaults to Convention_Ada. The code
-- that verifed that there was a matching convention
-- is now obsolete.
-- Resolve the expression of an Import or Export here,
-- and require it to be of type Boolean and static. This
-- is not quite right, because in general this should be
-- delayed, but that seems tricky for these, because
-- normally Boolean aspects are replaced with pragmas at
-- the freeze point (in Make_Pragma_From_Boolean_Aspect),
-- but in the case of these aspects we can't generate
-- a simple pragma with just the entity name. ???
if not Present (Expr)
or else Is_True (Static_Boolean (Expr))
then
if A_Id = Aspect_Import then
Set_Is_Imported (E);
Set_Has_Completion (E);
-- An imported entity cannot have an explicit
-- initialization.
if Nkind (N) = N_Object_Declaration
and then Present (Expression (N))
then
Error_Msg_N
("imported entities cannot be initialized "
& "(RM B.1(24))", Expression (N));
end if;
elsif A_Id = Aspect_Export then
Set_Is_Exported (E);
end if;
end if;
goto Continue;
elsif A_Id = Aspect_Export or else A_Id = Aspect_Import then
Analyze_Aspect_Export_Import;
-- Disable_Controlled
@ -3302,11 +3373,20 @@ package body Sem_Ch13 is
-- expression is missing other than the above cases.
if not Delay_Required or else No (Expr) then
Make_Aitem_Pragma
(Pragma_Argument_Associations => New_List (
Make_Pragma_Argument_Association (Sloc (Ent),
Expression => Ent)),
Pragma_Name => Chars (Id));
-- Exclude aspects Export and Import because their pragma
-- syntax does not map directly to a Boolean aspect.
if A_Id /= Aspect_Export
and then A_Id /= Aspect_Import
then
Make_Aitem_Pragma
(Pragma_Argument_Associations => New_List (
Make_Pragma_Argument_Association (Sloc (Ent),
Expression => Ent)),
Pragma_Name => Chars (Id));
end if;
Delay_Required := False;
-- In general cases, the corresponding pragma/attribute
@ -3506,7 +3586,7 @@ package body Sem_Ch13 is
-- unit, we simply insert the pragma/attribute definition clause
-- in sequence.
else
elsif Present (Aitem) then
Insert_After (Ins_Node, Aitem);
Ins_Node := Aitem;
end if;
@ -7814,6 +7894,133 @@ package body Sem_Ch13 is
return;
end Build_Discrete_Static_Predicate;
--------------------------------
-- Build_Export_Import_Pragma --
--------------------------------
function Build_Export_Import_Pragma
(Asp : Node_Id;
Id : Entity_Id) return Node_Id
is
Asp_Id : constant Aspect_Id := Get_Aspect_Id (Asp);
Expr : constant Node_Id := Expression (Asp);
Loc : constant Source_Ptr := Sloc (Asp);
Args : List_Id;
Conv : Node_Id;
Conv_Arg : Node_Id;
Dummy_1 : Node_Id;
Dummy_2 : Node_Id;
EN : Node_Id;
LN : Node_Id;
Prag : Node_Id;
Create_Pragma : Boolean := False;
-- This flag is set when the aspect form is such that it warrants the
-- creation of a corresponding pragma.
begin
if Present (Expr) then
if Error_Posted (Expr) then
null;
elsif Is_True (Expr_Value (Expr)) then
Create_Pragma := True;
end if;
-- Otherwise the aspect defaults to True
else
Create_Pragma := True;
end if;
-- Nothing to do when the expression is False or is erroneous
if not Create_Pragma then
return Empty;
end if;
-- Obtain all interfacing aspects that apply to the related entity
Get_Interfacing_Aspects
(Iface_Asp => Asp,
Conv_Asp => Conv,
EN_Asp => EN,
Expo_Asp => Dummy_1,
Imp_Asp => Dummy_2,
LN_Asp => LN);
Args := New_List;
-- Handle the convention argument
if Present (Conv) then
Conv_Arg := New_Copy_Tree (Expression (Conv));
-- Assume convention "Ada' when aspect Convention is missing
else
Conv_Arg := Make_Identifier (Loc, Name_Ada);
end if;
Append_To (Args,
Make_Pragma_Argument_Association (Loc,
Chars => Name_Convention,
Expression => Conv_Arg));
-- Handle the entity argument
Append_To (Args,
Make_Pragma_Argument_Association (Loc,
Chars => Name_Entity,
Expression => New_Occurrence_Of (Id, Loc)));
-- Handle the External_Name argument
if Present (EN) then
Append_To (Args,
Make_Pragma_Argument_Association (Loc,
Chars => Name_External_Name,
Expression => New_Copy_Tree (Expression (EN))));
end if;
-- Handle the Link_Name argument
if Present (LN) then
Append_To (Args,
Make_Pragma_Argument_Association (Loc,
Chars => Name_Link_Name,
Expression => New_Copy_Tree (Expression (LN))));
end if;
-- Generate:
-- pragma Export/Import
-- (Convention => <Conv>/Ada,
-- Entity => <Id>,
-- [External_Name => <EN>,]
-- [Link_Name => <LN>]);
Prag :=
Make_Pragma (Loc,
Pragma_Identifier =>
Make_Identifier (Loc, Chars (Identifier (Asp))),
Pragma_Argument_Associations => Args);
-- Decorate the relevant aspect and the pragma
Set_Aspect_Rep_Item (Asp, Prag);
Set_Corresponding_Aspect (Prag, Asp);
Set_From_Aspect_Specification (Prag);
Set_Parent (Prag, Asp);
if Asp_Id = Aspect_Import and then Is_Subprogram (Id) then
Set_Import_Pragma (Id, Prag);
end if;
return Prag;
end Build_Export_Import_Pragma;
-------------------------------------------
-- Build_Invariant_Procedure_Declaration --
-------------------------------------------
@ -11298,6 +11505,106 @@ package body Sem_Ch13 is
end if;
end Get_Alignment_Value;
-----------------------------
-- Get_Interfacing_Aspects --
-----------------------------
procedure Get_Interfacing_Aspects
(Iface_Asp : Node_Id;
Conv_Asp : out Node_Id;
EN_Asp : out Node_Id;
Expo_Asp : out Node_Id;
Imp_Asp : out Node_Id;
LN_Asp : out Node_Id;
Do_Checks : Boolean := False)
is
procedure Save_Or_Duplication_Error
(Asp : Node_Id;
To : in out Node_Id);
-- Save the value of aspect Asp in node To. If To already has a value,
-- then this is considered a duplicate use of aspect. Emit an error if
-- flag Do_Checks is set.
-------------------------------
-- Save_Or_Duplication_Error --
-------------------------------
procedure Save_Or_Duplication_Error
(Asp : Node_Id;
To : in out Node_Id)
is
begin
-- Detect an extra aspect and issue an error
if Present (To) then
if Do_Checks then
Error_Msg_Name_1 := Chars (Identifier (Asp));
Error_Msg_Sloc := Sloc (To);
Error_Msg_N ("aspect % previously given #", Asp);
end if;
-- Otherwise capture the aspect
else
To := Asp;
end if;
end Save_Or_Duplication_Error;
-- Local variables
Asp : Node_Id;
Asp_Id : Aspect_Id;
-- The following variables capture each individual aspect
Conv : Node_Id := Empty;
EN : Node_Id := Empty;
Expo : Node_Id := Empty;
Imp : Node_Id := Empty;
LN : Node_Id := Empty;
-- Start of processing for Get_Interfacing_Aspects
begin
-- The input interfacing aspect should reside in an aspect specification
-- list.
pragma Assert (Is_List_Member (Iface_Asp));
-- Examine the aspect specifications of the related entity. Find and
-- capture all interfacing aspects. Detect duplicates and emit errors
-- if applicable.
Asp := First (List_Containing (Iface_Asp));
while Present (Asp) loop
Asp_Id := Get_Aspect_Id (Asp);
if Asp_Id = Aspect_Convention then
Save_Or_Duplication_Error (Asp, Conv);
elsif Asp_Id = Aspect_External_Name then
Save_Or_Duplication_Error (Asp, EN);
elsif Asp_Id = Aspect_Export then
Save_Or_Duplication_Error (Asp, Expo);
elsif Asp_Id = Aspect_Import then
Save_Or_Duplication_Error (Asp, Imp);
elsif Asp_Id = Aspect_Link_Name then
Save_Or_Duplication_Error (Asp, LN);
end if;
Next (Asp);
end loop;
Conv_Asp := Conv;
EN_Asp := EN;
Expo_Asp := Expo;
Imp_Asp := Imp;
LN_Asp := LN;
end Get_Interfacing_Aspects;
-------------------------------------
-- Inherit_Aspects_At_Freeze_Point --
-------------------------------------