[Ada] Spurious error with pragma Thread_Local_Storage
The following patch modifies the checks related to pragma Thread_Local_Storage to correct a confusion in semantics which led to spurious errors. ------------ -- Source -- ------------ -- pack.ads package Pack is type Arr is array (1 .. 5) of Boolean; type Arr_With_Default is array (1 .. 5) of Boolean with Default_Component_Value => False; type Int is new Integer range 1 .. 5; type Int_With_Default is new Integer range 1 .. 5 with Default_Value => 1; protected type Prot_Typ is entry E; end Prot_Typ; type Rec_1 is record Comp : Integer; end record; type Rec_2 is record Comp : Int; end record; type Rec_3 is record Comp : Int_With_Default; end record; task type Task_Typ is entry E; end Task_Typ; end Pack; -- pack.adb package body Pack is function F (Val : Int) return Int is begin if Val <= 1 then return 1; else return F (Val - 1) * Val; end if; end F; function F (Val : Int_With_Default) return Int_With_Default is begin if Val <= 1 then return 1; else return F (Val - 1) * Val; end if; end F; function F (Val : Integer) return Integer is begin if Val <= 1 then return 1; else return F (Val - 1) * Val; end if; end F; protected body Prot_Typ is entry E when True is begin null; end E; end Prot_Typ; task body Task_Typ is begin accept E; end Task_Typ; Obj_1 : Arr; -- OK pragma Thread_Local_Storage (Obj_1); Obj_2 : Arr := (others => True); -- OK pragma Thread_Local_Storage (Obj_2); Obj_3 : Arr := (others => F (2) = Integer (3)); -- ERROR pragma Thread_Local_Storage (Obj_3); Obj_4 : Arr_With_Default; -- ERROR pragma Thread_Local_Storage (Obj_4); Obj_5 : Arr_With_Default := (others => True); -- OK pragma Thread_Local_Storage (Obj_5); Obj_6 : Arr_With_Default := (others => F (2) = Integer (3)); -- ERROR pragma Thread_Local_Storage (Obj_6); Obj_7 : Integer; -- OK pragma Thread_Local_Storage (Obj_7); Obj_8 : Integer := 1; -- OK pragma Thread_Local_Storage (Obj_8); Obj_9 : Integer := F (2); -- ERROR pragma Thread_Local_Storage (Obj_9); Obj_10 : Int; -- OK pragma Thread_Local_Storage (Obj_10); Obj_11 : Int := 1; -- OK pragma Thread_Local_Storage (Obj_11); Obj_12 : Int := F (2); -- ERROR pragma Thread_Local_Storage (Obj_12); Obj_13 : Int_With_Default; -- ERROR pragma Thread_Local_Storage (Obj_13); Obj_14 : Int_With_Default := 1; -- OK pragma Thread_Local_Storage (Obj_14); Obj_15 : Int_With_Default := F (2); -- ERROR pragma Thread_Local_Storage (Obj_15); Obj_16 : Prot_Typ; -- ERROR pragma Thread_Local_Storage (Obj_16); Obj_17 : Rec_1; -- OK pragma Thread_Local_Storage (Obj_17); Obj_18 : Rec_1 := (others => 1); -- OK pragma Thread_Local_Storage (Obj_18); Obj_19 : Rec_1 := (others => F (2)); -- ERROR pragma Thread_Local_Storage (Obj_19); Obj_20 : Rec_2; -- OK pragma Thread_Local_Storage (Obj_20); Obj_21 : Rec_2 := (others => 1); -- OK pragma Thread_Local_Storage (Obj_21); Obj_22 : Rec_2 := (others => F (2)); -- ERROR pragma Thread_Local_Storage (Obj_22); Obj_23 : Rec_3; -- ERROR pragma Thread_Local_Storage (Obj_23); Obj_24 : Rec_3 := (others => 1); -- OK pragma Thread_Local_Storage (Obj_24); Obj_25 : Rec_3 := (others => F (2)); -- ERROR pragma Thread_Local_Storage (Obj_25); Obj_26 : Task_Typ; -- ERROR pragma Thread_Local_Storage (Obj_26); end Pack; ---------------------------- -- Compilation and output -- ---------------------------- $ gcc -c pack.adb pack.adb:47:04: Thread_Local_Storage variable "Obj_4" is improperly initialized pack.adb:47:04: only allowed initialization is explicit "null", static expression or static aggregate pack.adb:62:04: Thread_Local_Storage variable "Obj_9" is improperly initialized pack.adb:62:04: only allowed initialization is explicit "null", static expression or static aggregate pack.adb:71:04: Thread_Local_Storage variable "Obj_12" is improperly initialized pack.adb:71:04: only allowed initialization is explicit "null", static expression or static aggregate pack.adb:74:04: Thread_Local_Storage variable "Obj_13" is improperly initialized pack.adb:74:04: only allowed initialization is explicit "null", static expression or static aggregate pack.adb:80:04: Thread_Local_Storage variable "Obj_15" is improperly initialized pack.adb:80:04: only allowed initialization is explicit "null", static expression or static aggregate pack.adb:83:04: Thread_Local_Storage variable "Obj_16" is improperly initialized pack.adb:83:04: only allowed initialization is explicit "null", static expression or static aggregate pack.adb:92:04: Thread_Local_Storage variable "Obj_19" is improperly initialized pack.adb:92:04: only allowed initialization is explicit "null", static expression or static aggregate pack.adb:101:04: Thread_Local_Storage variable "Obj_22" is improperly initialized pack.adb:101:04: only allowed initialization is explicit "null", static expression or static aggregate pack.adb:104:04: Thread_Local_Storage variable "Obj_23" is improperly initialized pack.adb:104:04: only allowed initialization is explicit "null", static expression or static aggregate pack.adb:110:04: Thread_Local_Storage variable "Obj_25" is improperly initialized pack.adb:110:04: only allowed initialization is explicit "null", static expression or static aggregate pack.adb:113:04: Thread_Local_Storage variable "Obj_26" is improperly initialized pack.adb:113:04: only allowed initialization is explicit "null", static expression or static aggregate 2018-12-11 Hristian Kirtchev <kirtchev@adacore.com> gcc/ada/ * freeze.adb (Check_Pragma_Thread_Local_Storage): Use the violating set to diagnose detect an illegal initialization, rather than the complement of the OK set. (Freeze_Object_Declaration): Factorize code in Has_Default_Initialization. (Has_Default_Initialization, Has_Incompatible_Initialization): New routines. From-SVN: r267017
This commit is contained in:
parent
759f164802
commit
921186579c
2 changed files with 114 additions and 45 deletions
|
@ -1,3 +1,13 @@
|
|||
2018-12-11 Hristian Kirtchev <kirtchev@adacore.com>
|
||||
|
||||
* freeze.adb (Check_Pragma_Thread_Local_Storage): Use the
|
||||
violating set to diagnose detect an illegal initialization,
|
||||
rather than the complement of the OK set.
|
||||
(Freeze_Object_Declaration): Factorize code in
|
||||
Has_Default_Initialization.
|
||||
(Has_Default_Initialization, Has_Incompatible_Initialization):
|
||||
New routines.
|
||||
|
||||
2018-12-11 Dmitriy Anisimkov <anisimko@adacore.com>
|
||||
|
||||
* libgnat/g-socket.ads (Family_Type): Add new enumerated value
|
||||
|
|
|
@ -3187,8 +3187,13 @@ package body Freeze is
|
|||
-- length of the array, or its corresponding attribute.
|
||||
|
||||
procedure Check_Pragma_Thread_Local_Storage (Var_Id : Entity_Id);
|
||||
-- Ensure that the initialization state of variable Var_Id subject to
|
||||
-- pragma Thread_Local_Storage satisfies the semantics of the pragma.
|
||||
-- Ensure that the initialization state of variable Var_Id subject
|
||||
-- to pragma Thread_Local_Storage agrees with the semantics of the
|
||||
-- pragma.
|
||||
|
||||
function Has_Default_Initialization
|
||||
(Obj_Id : Entity_Id) return Boolean;
|
||||
-- Determine whether object Obj_Id default initialized
|
||||
|
||||
-------------------------------
|
||||
-- Check_Large_Modular_Array --
|
||||
|
@ -3274,53 +3279,117 @@ package body Freeze is
|
|||
---------------------------------------
|
||||
|
||||
procedure Check_Pragma_Thread_Local_Storage (Var_Id : Entity_Id) is
|
||||
Decl : constant Node_Id := Declaration_Node (Var_Id);
|
||||
Expr : constant Node_Id := Expression (Decl);
|
||||
function Has_Incompatible_Initialization
|
||||
(Var_Decl : Node_Id) return Boolean;
|
||||
-- Determine whether variable Var_Id with declaration Var_Decl is
|
||||
-- initialized with a value that violates the semantics of pragma
|
||||
-- Thread_Local_Storage.
|
||||
|
||||
-------------------------------------
|
||||
-- Has_Incompatible_Initialization --
|
||||
-------------------------------------
|
||||
|
||||
function Has_Incompatible_Initialization
|
||||
(Var_Decl : Node_Id) return Boolean
|
||||
is
|
||||
Init_Expr : constant Node_Id := Expression (Var_Decl);
|
||||
|
||||
begin
|
||||
-- The variable is default-initialized. This directly violates
|
||||
-- the semantics of the pragma.
|
||||
|
||||
if Has_Default_Initialization (Var_Id) then
|
||||
return True;
|
||||
|
||||
-- The variable has explicit initialization. In this case only
|
||||
-- a handful of values satisfy the semantics of the pragma.
|
||||
|
||||
elsif Has_Init_Expression (Var_Decl)
|
||||
and then Present (Init_Expr)
|
||||
then
|
||||
-- "null" is a legal form of initialization
|
||||
|
||||
if Nkind (Init_Expr) = N_Null then
|
||||
return False;
|
||||
|
||||
-- A static expression is a legal form of initialization
|
||||
|
||||
elsif Is_Static_Expression (Init_Expr) then
|
||||
return False;
|
||||
|
||||
-- A static aggregate is a legal form of initialization
|
||||
|
||||
elsif Nkind (Init_Expr) = N_Aggregate
|
||||
and then Compile_Time_Known_Aggregate (Init_Expr)
|
||||
then
|
||||
return False;
|
||||
|
||||
-- All other initialization expressions violate the semantic
|
||||
-- of the pragma.
|
||||
|
||||
else
|
||||
return True;
|
||||
end if;
|
||||
|
||||
-- The variable lacks any kind of initialization, which agrees
|
||||
-- with the semantics of the pragma.
|
||||
|
||||
else
|
||||
return False;
|
||||
end if;
|
||||
end Has_Incompatible_Initialization;
|
||||
|
||||
-- Local declarations
|
||||
|
||||
Var_Decl : constant Node_Id := Declaration_Node (Var_Id);
|
||||
|
||||
-- Start of processing for Check_Pragma_Thread_Local_Storage
|
||||
|
||||
begin
|
||||
-- A variable whose initialization is suppressed lacks default
|
||||
-- A variable whose initialization is suppressed lacks any kind of
|
||||
-- initialization.
|
||||
|
||||
if Suppress_Initialization (Var_Id) then
|
||||
null;
|
||||
|
||||
-- The variable has some form of initialization. Check whether it
|
||||
-- is compatible with the semantics of the pragma.
|
||||
-- The variable has default initialization, or is explicitly
|
||||
-- initialized to a value other than null, static expression,
|
||||
-- or a static aggregate.
|
||||
|
||||
elsif Has_Init_Expression (Decl)
|
||||
and then Present (Expr)
|
||||
and then
|
||||
|
||||
-- The variable is initialized with "null"
|
||||
|
||||
(Nkind (Expr) = N_Null
|
||||
or else
|
||||
|
||||
-- The variable is initialized with a static constant
|
||||
|
||||
Is_OK_Static_Expression (Expr)
|
||||
or else
|
||||
|
||||
-- The variable is initialized with a static aggregate
|
||||
|
||||
(Nkind (Expr) = N_Aggregate
|
||||
and then Compile_Time_Known_Aggregate (Expr)))
|
||||
then
|
||||
null;
|
||||
|
||||
-- Otherwise the initialization of the variable violates the
|
||||
-- semantics of pragma Thread_Local_Storage.
|
||||
|
||||
else
|
||||
elsif Has_Incompatible_Initialization (Var_Decl) then
|
||||
Error_Msg_NE
|
||||
("Thread_Local_Storage variable& is improperly initialized",
|
||||
Decl, Var_Id);
|
||||
Var_Decl, Var_Id);
|
||||
Error_Msg_NE
|
||||
("\only allowed initialization is explicit NULL, static "
|
||||
& "expression or static aggregate", Decl, Var_Id);
|
||||
& "expression or static aggregate", Var_Decl, Var_Id);
|
||||
end if;
|
||||
end Check_Pragma_Thread_Local_Storage;
|
||||
|
||||
--------------------------------
|
||||
-- Has_Default_Initialization --
|
||||
--------------------------------
|
||||
|
||||
function Has_Default_Initialization
|
||||
(Obj_Id : Entity_Id) return Boolean
|
||||
is
|
||||
Obj_Decl : constant Node_Id := Declaration_Node (Obj_Id);
|
||||
Obj_Typ : constant Entity_Id := Etype (Obj_Id);
|
||||
|
||||
begin
|
||||
return
|
||||
Comes_From_Source (Obj_Id)
|
||||
and then not Is_Imported (Obj_Id)
|
||||
and then not Has_Init_Expression (Obj_Decl)
|
||||
and then
|
||||
((Has_Non_Null_Base_Init_Proc (Obj_Typ)
|
||||
and then not No_Initialization (Obj_Decl)
|
||||
and then not Initialization_Suppressed (Obj_Typ))
|
||||
or else
|
||||
(Needs_Simple_Initialization (Obj_Typ)
|
||||
and then not Is_Internal (Obj_Id)));
|
||||
end Has_Default_Initialization;
|
||||
|
||||
-- Local variables
|
||||
|
||||
Typ : constant Entity_Id := Etype (E);
|
||||
|
@ -3438,17 +3507,7 @@ package body Freeze is
|
|||
if Ekind (E) = E_Constant and then Present (Full_View (E)) then
|
||||
null;
|
||||
|
||||
elsif Comes_From_Source (E)
|
||||
and then not Is_Imported (E)
|
||||
and then not Has_Init_Expression (Declaration_Node (E))
|
||||
and then
|
||||
((Has_Non_Null_Base_Init_Proc (Typ)
|
||||
and then not No_Initialization (Declaration_Node (E))
|
||||
and then not Initialization_Suppressed (Typ))
|
||||
or else
|
||||
(Needs_Simple_Initialization (Typ)
|
||||
and then not Is_Internal (E)))
|
||||
then
|
||||
elsif Has_Default_Initialization (E) then
|
||||
Check_Restriction
|
||||
(No_Default_Initialization, Declaration_Node (E));
|
||||
end if;
|
||||
|
|
Loading…
Add table
Reference in a new issue