aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorBob Duff <duff@adacore.com>2024-01-12 08:12:27 -0500
committerMarc Poulhiès <poulhies@adacore.com>2024-05-07 09:55:55 +0200
commite29c2dabc362c47e02374e4f793ffd48a0cfb4cb (patch)
tree8c0f09532b6d25994c36fe746b3832879d1709d0 /gcc
parent1955a35a46e4667cccf8d22116edc29b88e3e729 (diff)
downloadgcc-e29c2dabc362c47e02374e4f793ffd48a0cfb4cb.zip
gcc-e29c2dabc362c47e02374e4f793ffd48a0cfb4cb.tar.gz
gcc-e29c2dabc362c47e02374e4f793ffd48a0cfb4cb.tar.bz2
ada: Fix crash on body postcondition
This patch fixes a bug where the compiler could crash on a postcondition on a subprogram body (i.e. a body that "acts as spec"), if the postcondition contains 'Old attributes that use the Ada 2022 feature that allows certain conditionals (see RM-6.1.1). The main bug fix here is in exp_attr.adb to set Ins_Node properly in the Acts_As_Spec case. Otherwise, the initialization of the 'Old temp would occur before the declaration, which gigi does not like. gcc/ada/ * exp_attr.adb (Attribute_Old): The 'Old attribute we are processing here is in a postcondition, which cannot be inside the "Wrapped_Statements" of the subprogram with that postcondition. So remove the loop labeled "Climb the parent chain looking for subprogram _Wrapped_Statements". The only way this loop could find a Subp is if we are nested inside a subprogram that also has a postcondition, and in that case we would find the wrong (outer) one. In any case, Subp is set to Empty after the loop, so all subsequent tests for Present (Subp) are necessarily False; remove them and the corresponding code. Set Ins_Node unconditionally (to the right thing). Remove obsolete comments. * sem_util.adb (Determining_Expressions): Fix assertion; Pragma_Test_Case was missing. (Eligible_For_Conditional_Evaluation): Fix assert that could fail in case of errors. * libgnat/s-valspe.ads: Remove pragma Unevaluated_Use_Of_Old; there are no uses of 'Old in this package.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ada/exp_attr.adb72
-rw-r--r--gcc/ada/libgnat/s-valspe.ads2
-rw-r--r--gcc/ada/sem_util.adb6
3 files changed, 13 insertions, 67 deletions
diff --git a/gcc/ada/exp_attr.adb b/gcc/ada/exp_attr.adb
index a8e06f0..63b311c 100644
--- a/gcc/ada/exp_attr.adb
+++ b/gcc/ada/exp_attr.adb
@@ -4988,7 +4988,6 @@ package body Exp_Attr is
CW_Typ : Entity_Id;
Decl : Node_Id;
Ins_Nod : Node_Id;
- Subp : Node_Id;
Temp : Entity_Id;
use Old_Attr_Util.Conditional_Evaluation;
@@ -5007,27 +5006,6 @@ package body Exp_Attr is
return;
end if;
- -- Climb the parent chain looking for subprogram _Wrapped_Statements
-
- Subp := N;
- while Present (Subp) loop
- exit when Nkind (Subp) = N_Subprogram_Body
- and then Chars (Defining_Entity (Subp))
- = Name_uWrapped_Statements;
-
- -- If assertions are disabled, no need to create the declaration
- -- that preserves the value. The postcondition pragma in which
- -- 'Old appears will be checked or disabled according to the
- -- current policy in effect.
-
- if Nkind (Subp) = N_Pragma and then not Is_Checked (Subp) then
- return;
- end if;
-
- Subp := Parent (Subp);
- end loop;
- Subp := Empty;
-
-- 'Old can only appear in the case where local contract-related
-- wrapper has been generated with the purpose of wrapping the
-- original declarations and statements.
@@ -5040,44 +5018,20 @@ package body Exp_Attr is
Mutate_Ekind (Temp, E_Constant);
Set_Stores_Attribute_Old_Prefix (Temp);
- -- Push the scope of the related subprogram where _Postcondition
- -- resides as this ensures that the object will be analyzed in the
- -- proper context.
-
- if Present (Subp) then
- Push_Scope (Scope (Defining_Entity (Subp)));
-
- -- No need to push the scope when generating C code since the
- -- _Postcondition procedure has been inlined.
-
- else
- null;
- end if;
-
-- Locate the insertion place of the internal temporary that saves
-- the 'Old value.
- if Present (Subp) then
- Ins_Nod := Subp;
+ Ins_Nod := N;
+ while Nkind (Ins_Nod) /= N_Subprogram_Body loop
+ Ins_Nod := Parent (Ins_Nod);
+ end loop;
- -- General case where the postcondition checks occur after the call
- -- to _Wrapped_Statements.
+ pragma Assert (Present (Wrapped_Statements
+ (if Acts_As_Spec (Ins_Nod)
+ then Defining_Unit_Name (Specification (Ins_Nod))
+ else Corresponding_Spec (Ins_Nod))));
- else
- Ins_Nod := N;
- while Nkind (Ins_Nod) /= N_Subprogram_Body loop
- Ins_Nod := Parent (Ins_Nod);
- end loop;
-
- if Present (Corresponding_Spec (Ins_Nod))
- and then Present
- (Wrapped_Statements (Corresponding_Spec (Ins_Nod)))
- then
- Ins_Nod := Last (Declarations (Ins_Nod));
- else
- Ins_Nod := First (Declarations (Ins_Nod));
- end if;
- end if;
+ Ins_Nod := Last (Declarations (Ins_Nod));
if Eligible_For_Conditional_Evaluation (N) then
declare
@@ -5122,10 +5076,6 @@ package body Exp_Attr is
(Temp => Temp,
Typ => Etype (Pref),
Loc => Loc));
-
- if Present (Subp) then
- Pop_Scope;
- end if;
return;
end;
@@ -5179,10 +5129,6 @@ package body Exp_Attr is
end if;
- if Present (Subp) then
- Pop_Scope;
- end if;
-
-- Ensure that the prefix of attribute 'Old is valid. The check must
-- be inserted after the expansion of the attribute has taken place
-- to reflect the new placement of the prefix.
diff --git a/gcc/ada/libgnat/s-valspe.ads b/gcc/ada/libgnat/s-valspe.ads
index 016e1df..d51f680 100644
--- a/gcc/ada/libgnat/s-valspe.ads
+++ b/gcc/ada/libgnat/s-valspe.ads
@@ -48,8 +48,6 @@ package System.Val_Spec with
Pure,
Ghost
is
- pragma Unevaluated_Use_Of_Old (Allow);
-
function Only_Space_Ghost (S : String; From, To : Integer) return Boolean is
(for all J in From .. To => S (J) = ' ')
with
diff --git a/gcc/ada/sem_util.adb b/gcc/ada/sem_util.adb
index d629c76..ebfe27a 100644
--- a/gcc/ada/sem_util.adb
+++ b/gcc/ada/sem_util.adb
@@ -30562,7 +30562,8 @@ package body Sem_Util is
| Pragma_Post
| Pragma_Postcondition
| Pragma_Post_Class
- | Pragma_Refined_Post);
+ | Pragma_Refined_Post
+ | Pragma_Test_Case);
return (1 .. 0 => <>); -- recursion terminates here
end if;
@@ -30619,7 +30620,8 @@ package body Sem_Util is
Determiners : constant Determining_Expression_List :=
Determining_Expressions (Expr);
begin
- pragma Assert (Determiners'Length > 0);
+ pragma Assert (if Serious_Errors_Detected = 0 then
+ Determiners'Length > 0);
for Idx in Determiners'Range loop
if not Is_Known_On_Entry (Determiners (Idx).Expr) then