aboutsummaryrefslogtreecommitdiff
path: root/gcc/ada/exp_ch6.adb
diff options
context:
space:
mode:
authorJustin Squirek <squirek@adacore.com>2019-09-18 08:33:07 +0000
committerPierre-Marie de Rodat <pmderodat@gcc.gnu.org>2019-09-18 08:33:07 +0000
commit43b264110f5581af0cc93308f9433fe8053f01cc (patch)
treebf5040d78121224b3f819b3ec3708201aabd818a /gcc/ada/exp_ch6.adb
parentc8324fe7b12851c16c867f16ce248c95d2dbae7d (diff)
downloadgcc-43b264110f5581af0cc93308f9433fe8053f01cc.zip
gcc-43b264110f5581af0cc93308f9433fe8053f01cc.tar.gz
gcc-43b264110f5581af0cc93308f9433fe8053f01cc.tar.bz2
[Ada] Spurious run time error on anonymous access formals
This patch fixes an issue whereby subprograms with anonymous access formals may trigger spurious runtime accessibility errors when such formals are used as actuals in calls to nested subprograms. Running these commands: gnatmake -q pass.adb gnatmake -q fail.adb gnatmake -q test_main.adb gnatmake -q indirect_call_test.adb pass fail test_main indirect_call_test On the following sources: -- pass.adb procedure Pass is function A (Param : access Integer) return Boolean is type Typ is access all Integer; function A_Inner (Param : access Integer) return Typ is begin return Typ (Param); -- OK end; begin return A_Inner (Param) = Typ (Param); end; function B (Param : access Integer) return Boolean; function B (Param : access Integer) return Boolean is type Typ is access all Integer; function B_Inner (Param : access Integer) return Typ is begin return Typ (Param); -- OK end; begin return B_Inner (Param) = Typ (Param); end; procedure C (Param : access Integer) is type Typ is access all Integer; Var : Typ; procedure C_Inner (Param : access Integer) is begin Var := Typ (Param); -- OK end; begin C_Inner (Param); end; procedure D (Param : access Integer); procedure D (Param : access Integer) is type Typ is access all Integer; Var : Typ; procedure D_Inner (Param : access Integer) is begin Var := Typ (Param); -- OK end; begin D_Inner (Param); end; protected type E is function G (Param : access Integer) return Boolean; procedure I (Param : access Integer); end; protected body E is function F (Param : access Integer) return Boolean is type Typ is access all Integer; function F_Inner (Param : access Integer) return Typ is begin return Typ (Param); -- OK end; begin return F_Inner (Param) = Typ (Param); end; function G (Param : access Integer) return Boolean is type Typ is access all Integer; function G_Inner (Param : access Integer) return Typ is begin return Typ (Param); -- OK end; B : Boolean := F (Param); -- OK begin return G_Inner (Param) = Typ (Param); end; procedure H (Param : access Integer) is type Typ is access all Integer; Var : Typ; procedure H_Inner (Param : access Integer) is begin Var := Typ (Param); -- OK end; begin H_Inner (Param); end; procedure I (Param : access Integer) is type Typ is access all Integer; Var : Typ; procedure I_Inner (Param : access Integer) is begin Var := Typ (Param); -- OK end; begin H (Param); -- OK I_Inner (Param); end; end; task type J is end; task body J is function K (Param : access Integer) return Boolean is type Typ is access all Integer; function K_Inner (Param : access Integer) return Typ is begin return Typ (Param); -- OK end; begin return K_Inner (Param) = Typ (Param); end; function L (Param : access Integer) return Boolean; function L (Param : access Integer) return Boolean is type Typ is access all Integer; function L_Inner (Param : access Integer) return Typ is begin return Typ (Param); -- OK end; begin return L_Inner (Param) = Typ (Param); end; procedure M (Param : access Integer) is type Typ is access all Integer; Var : Typ; procedure M_Inner (Param : access Integer) is begin Var := Typ (Param); -- OK end; begin M_Inner (Param); end; procedure N (Param : access Integer); procedure N (Param : access Integer) is type Typ is access all Integer; Var : Typ; procedure N_Inner (Param : access Integer) is begin Var := Typ (Param); -- OK end; begin N_Inner (Param); end; Var : aliased Integer := 666; begin if K (Var'Access) then null; end if; -- OK if L (Var'Access) then null; end if; -- OK M (Var'Access); -- OK N (Var'Access); -- OK end; begin begin begin declare Var : aliased Integer := 666; T : J; Prot : E; begin if A (Var'Access) then null; end if; -- OK if B (Var'Access) then null; end if; -- OK C (Var'Access); -- OK D (Var'Access); -- OK if Prot.G (Var'Access) then null; end if; -- OK Prot.I (Var'Access); -- OK end; end; end; end; -- fail.adb procedure Fail is Failures : Integer := 0; type Base_Typ is access all Integer; function A (Param : access Integer) return Boolean is subtype Typ is Base_Typ; function A_Inner (Param : access Integer) return Typ is begin return Typ (Param); -- ERROR end; begin return A_Inner (Param) = Typ (Param); exception when others => Failures := Failures + 1; return False; end; function B (Param : access Integer) return Boolean; function B (Param : access Integer) return Boolean is subtype Typ is Base_Typ; function B_Inner (Param : access Integer) return Typ is begin return Typ (Param); -- ERROR end; begin return B_Inner (Param) = Typ (Param); exception when others => Failures := Failures + 1; return False; end; procedure C (Param : access Integer) is subtype Typ is Base_Typ; Var : Typ; procedure C_Inner (Param : access Integer) is begin Var := Typ (Param); -- ERROR end; begin C_Inner (Param); exception when others => Failures := Failures + 1; end; procedure D (Param : access Integer); procedure D (Param : access Integer) is subtype Typ is Base_Typ; Var : Typ; procedure D_Inner (Param : access Integer) is begin Var := Typ (Param); -- ERROR end; begin D_Inner (Param); exception when others => Failures := Failures + 1; end; protected type E is function G (Param : access Integer) return Boolean; procedure I (Param : access Integer); end; protected body E is function F (Param : access Integer) return Boolean is subtype Typ is Base_Typ; function F_Inner (Param : access Integer) return Typ is begin return Typ (Param); -- ERROR end; begin return F_Inner (Param) = Typ (Param); exception when others => Failures := Failures + 1; return False; end; function G (Param : access Integer) return Boolean is subtype Typ is Base_Typ; function G_Inner (Param : access Integer) return Typ is begin return Typ (Param); -- ERROR end; B : Boolean := F (Param); -- ERROR begin return G_Inner (Param) = Typ (Param); exception when others => Failures := Failures + 1; return False; end; procedure H (Param : access Integer) is subtype Typ is Base_Typ; Var : Typ; procedure H_Inner (Param : access Integer) is begin Var := Typ (Param); -- ERROR end; begin H_Inner (Param); exception when others => Failures := Failures + 1; end; procedure I (Param : access Integer) is subtype Typ is Base_Typ; Var : Typ; procedure I_Inner (Param : access Integer) is begin Var := Typ (Param); -- ERROR end; begin H (Param); -- ERROR I_Inner (Param); exception when others => Failures := Failures + 1; end; end; task type J is end; task body J is function K (Param : access Integer) return Boolean is subtype Typ is Base_Typ; function K_Inner (Param : access Integer) return Typ is begin return Typ (Param); -- ERROR end; begin return K_Inner (Param) = Typ (Param); exception when others => Failures := Failures + 1; return False; end; function L (Param : access Integer) return Boolean; function L (Param : access Integer) return Boolean is subtype Typ is Base_Typ; function L_Inner (Param : access Integer) return Typ is begin return Typ (Param); -- ERROR end; begin return L_Inner (Param) = Typ (Param); exception when others => Failures := Failures + 1; return False; end; procedure M (Param : access Integer) is subtype Typ is Base_Typ; Var : Typ; procedure M_Inner (Param : access Integer) is begin Var := Typ (Param); -- ERROR end; begin M_Inner (Param); exception when others => Failures := Failures + 1; end; procedure N (Param : access Integer); procedure N (Param : access Integer) is subtype Typ is Base_Typ; Var : Typ; procedure N_Inner (Param : access Integer) is begin Var := Typ (Param); -- ERROR end; begin N_Inner (Param); exception when others => Failures := Failures + 1; end; Var : aliased Integer := 666; begin if K (Var'Access) then null; end if; -- ERROR if L (Var'Access) then null; end if; -- ERROR M (Var'Access); -- ERROR N (Var'Access); -- ERROR end; begin begin begin declare Var : aliased Integer := 666; T : J; Prot : E; begin if A (Var'Access) then null; end if; -- ERROR if B (Var'Access) then null; end if; -- ERROR C (Var'Access); -- ERROR D (Var'Access); -- ERROR if Prot.G (Var'Access) then null; end if; -- ERROR Prot.I (Var'Access); -- ERROR if Failures /= 12 then raise Program_Error; end if; end; end; end; end; -- indirect_call_test.adb with Text_IO; procedure Indirect_Call_Test is Tracing_Enabled : constant Boolean := False; procedure Trace (S : String) is begin if Tracing_Enabled then Text_IO.Put_Line (S); end if; end; package Pkg is type Root is abstract tagged null record; function F (X : Root; Param : access Integer) return Boolean is abstract; end Pkg; function F_Wrapper (X : Pkg.Root; Param : access Integer) return Boolean is (Pkg.F (Pkg.Root'Class (X), Param)); -- dispatching call function A (Param : access Integer) return Boolean is type Typ is access all Integer; package Nested is type Ext is new Pkg.Root with null record; overriding function F (X : Ext; Param : access Integer) return Boolean; end Nested; function A_Inner (Param : access Integer) return Typ is begin return Typ (Param); -- OK end A_Inner; package body Nested is function F (X : Ext; Param : access Integer) return Boolean is begin return A_Inner (Param) = null; end; end; Ext_Obj : Nested.Ext; begin Trace ("In subtest A"); return F_Wrapper (Pkg.Root (Ext_Obj), Param); exception when Program_Error => Trace ("Failed"); return True; end A; function B (Param : access Integer) return Boolean is type Typ is access all Integer; function B_Inner (Param : access Integer) return Typ is begin return Typ (Param); -- OK end B_Inner; type Ref is access function (Param : access Integer) return Typ; Ptr : Ref := B_Inner'Access; function Ptr_Caller return Typ is (Ptr.all (Param)); -- access-to-subp value begin Trace ("In subtest B"); return Ptr_Caller = null; exception when Program_Error => Trace ("*** failed"); return True; end B; begin begin begin declare Var : aliased Integer := 666; begin if A (Var'Access) then null; end if; Trace ("Subtest A done"); if B (Var'Access) then null; end if; Trace ("Subtest B done"); end; end; end; end Indirect_Call_Test; Should produce the following output: Failure Failure Failure Failure Failure Failure Failure Failure Failure Failure Failure Failure Failure Failure Failure Failure Failure Failure Failure Failure Failure Failure Failure Failure 2019-09-18 Justin Squirek <squirek@adacore.com> gcc/ada/ * einfo.adb, einfo.ads (Minimum_Accessibility): Added new field. (Set_Minimum_Accessibility): Added to set new field. (Minimum_Accessibility): Added to fetch new field. * exp_ch6.adb (Expand_Subprogram_Call): Modify calls to fetch accessibility levels to the new subprogram Get_Accessibility which handles cases where minimum accessibility might be needed. * sem_ch6.adb (Analyze_Subprogram_Body_Helper): Add section to generate a Minimum_Accessibility object within relevant subprograms. * sem_util.adb, sem_util.ads (Dynamic_Accessibility_Level): Additional documentation added and modify section to use new function Get_Accessibility. (Get_Accessibility): Added to centralize processing of accessibility levels. From-SVN: r275858
Diffstat (limited to 'gcc/ada/exp_ch6.adb')
-rw-r--r--gcc/ada/exp_ch6.adb34
1 files changed, 17 insertions, 17 deletions
diff --git a/gcc/ada/exp_ch6.adb b/gcc/ada/exp_ch6.adb
index 3277b46..78a1496 100644
--- a/gcc/ada/exp_ch6.adb
+++ b/gcc/ada/exp_ch6.adb
@@ -3221,7 +3221,7 @@ package body Exp_Ch6 is
-- Create possible extra actual for accessibility level
- if Present (Extra_Accessibility (Formal)) then
+ if Present (Get_Accessibility (Formal)) then
-- Ada 2005 (AI-252): If the actual was rewritten as an Access
-- attribute, then the original actual may be an aliased object
@@ -3297,8 +3297,8 @@ package body Exp_Ch6 is
Add_Extra_Actual
(Expr =>
- New_Occurrence_Of (Extra_Accessibility (Parm_Ent), Loc),
- EF => Extra_Accessibility (Formal));
+ New_Occurrence_Of (Get_Accessibility (Parm_Ent), Loc),
+ EF => Get_Accessibility (Formal));
end;
elsif Is_Entity_Name (Prev_Orig) then
@@ -3327,12 +3327,12 @@ package body Exp_Ch6 is
begin
pragma Assert (Present (Parm_Ent));
- if Present (Extra_Accessibility (Parm_Ent)) then
+ if Present (Get_Accessibility (Parm_Ent)) then
Add_Extra_Actual
(Expr =>
New_Occurrence_Of
- (Extra_Accessibility (Parm_Ent), Loc),
- EF => Extra_Accessibility (Formal));
+ (Get_Accessibility (Parm_Ent), Loc),
+ EF => Get_Accessibility (Formal));
-- If the actual access parameter does not have an
-- associated extra formal providing its scope level,
@@ -3344,7 +3344,7 @@ package body Exp_Ch6 is
(Expr =>
Make_Integer_Literal (Loc,
Intval => Scope_Depth (Standard_Standard)),
- EF => Extra_Accessibility (Formal));
+ EF => Get_Accessibility (Formal));
end if;
end;
@@ -3354,7 +3354,7 @@ package body Exp_Ch6 is
else
Add_Extra_Actual
(Expr => Dynamic_Accessibility_Level (Prev_Orig),
- EF => Extra_Accessibility (Formal));
+ EF => Get_Accessibility (Formal));
end if;
-- If the actual is an access discriminant, then pass the level
@@ -3370,7 +3370,7 @@ package body Exp_Ch6 is
(Expr =>
Make_Integer_Literal (Loc,
Intval => Object_Access_Level (Prefix (Prev_Orig))),
- EF => Extra_Accessibility (Formal));
+ EF => Get_Accessibility (Formal));
-- All other cases
@@ -3440,19 +3440,19 @@ package body Exp_Ch6 is
Make_Integer_Literal (Loc,
Intval =>
Type_Access_Level (Pref_Entity)),
- EF => Extra_Accessibility (Formal));
+ EF => Get_Accessibility (Formal));
elsif Nkind (Prev_Orig) = N_Explicit_Dereference
and then Present (Pref_Entity)
and then Is_Formal (Pref_Entity)
and then Present
- (Extra_Accessibility (Pref_Entity))
+ (Get_Accessibility (Pref_Entity))
then
Add_Extra_Actual
(Expr =>
New_Occurrence_Of
- (Extra_Accessibility (Pref_Entity), Loc),
- EF => Extra_Accessibility (Formal));
+ (Get_Accessibility (Pref_Entity), Loc),
+ EF => Get_Accessibility (Formal));
else
Add_Extra_Actual
@@ -3460,7 +3460,7 @@ package body Exp_Ch6 is
Make_Integer_Literal (Loc,
Intval =>
Object_Access_Level (Prev_Orig)),
- EF => Extra_Accessibility (Formal));
+ EF => Get_Accessibility (Formal));
end if;
-- Treat the unchecked attributes as library-level
@@ -3472,7 +3472,7 @@ package body Exp_Ch6 is
(Expr =>
Make_Integer_Literal (Loc,
Intval => Scope_Depth (Standard_Standard)),
- EF => Extra_Accessibility (Formal));
+ EF => Get_Accessibility (Formal));
-- No other cases of attributes returning access
-- values that can be passed to access parameters.
@@ -3494,7 +3494,7 @@ package body Exp_Ch6 is
(Expr =>
Make_Integer_Literal (Loc,
Intval => Scope_Depth (Current_Scope) + 1),
- EF => Extra_Accessibility (Formal));
+ EF => Get_Accessibility (Formal));
-- For most other cases we simply pass the level of the
-- actual's access type. The type is retrieved from
@@ -3505,7 +3505,7 @@ package body Exp_Ch6 is
when others =>
Add_Extra_Actual
(Expr => Dynamic_Accessibility_Level (Prev),
- EF => Extra_Accessibility (Formal));
+ EF => Get_Accessibility (Formal));
end case;
end if;
end if;