From: Piotr Trojanek <[email protected]>

The copies of class-wide pre- and postconditions are now attached to the
original pragma, so that legality checks, like the one for 'Old, can find the
original context of where those expressions appeared.

gcc/ada/ChangeLog:

        * sem_attr.adb (Uneval_Old_Msg): Attribute Old never occurs outside of
        a pragma.
        * sem_ch13.adb (Analyze_One_Aspect): Attach expression copy of a
        class-wide aspect to the corresponding pragma.
        * sem_prag.adb (Analyze_Pre_Post_Condition): Likewise for a class-wide
        pragma.

Tested on x86_64-pc-linux-gnu, committed on master.

---
 gcc/ada/sem_attr.adb |  1 +
 gcc/ada/sem_ch13.adb | 22 ++++++++++++++++------
 gcc/ada/sem_prag.adb | 16 ++++++++++++----
 3 files changed, 29 insertions(+), 10 deletions(-)

diff --git a/gcc/ada/sem_attr.adb b/gcc/ada/sem_attr.adb
index 77a61fff801..e038774849d 100644
--- a/gcc/ada/sem_attr.adb
+++ b/gcc/ada/sem_attr.adb
@@ -3143,6 +3143,7 @@ package body Sem_Attr is
          --  from Opt.Uneval_Old. Perhaps this is due to a previous error?
 
          else
+            Check_Error_Detected;
             Uneval_Old_Setting := Opt.Uneval_Old;
          end if;
 
diff --git a/gcc/ada/sem_ch13.adb b/gcc/ada/sem_ch13.adb
index eda8f58a64b..397285d3df1 100644
--- a/gcc/ada/sem_ch13.adb
+++ b/gcc/ada/sem_ch13.adb
@@ -5431,6 +5431,8 @@ package body Sem_Ch13 is
          when Pre_Post_Aspects => Pre_Post : declare
             Pname : Name_Id;
 
+            Class_Wide_Expr : Node_Id := Empty;
+
          begin
             if A_Id in Aspect_Pre | Aspect_Precondition then
                Pname := Name_Precondition;
@@ -5467,11 +5469,11 @@ package body Sem_Ch13 is
               and then not Is_Ignored_Ghost_Entity_In_Codegen (E)
             then
                if A_Id = Aspect_Pre then
+                  Class_Wide_Expr := New_Copy_Tree (Expr);
                   if Is_Ignored_In_Codegen (Aspect) then
-                     Set_Ignored_Class_Preconditions (E,
-                       New_Copy_Tree (Expr));
+                     Set_Ignored_Class_Preconditions (E, Class_Wide_Expr);
                   else
-                     Set_Class_Preconditions (E, New_Copy_Tree (Expr));
+                     Set_Class_Preconditions (E, Class_Wide_Expr);
                   end if;
 
                --  Postconditions may split into separate aspects, and we
@@ -5481,11 +5483,11 @@ package body Sem_Ch13 is
                elsif No (Class_Postconditions (E))
                  and then No (Ignored_Class_Postconditions (E))
                then
+                  Class_Wide_Expr := New_Copy_Tree (Expr);
                   if Is_Ignored_In_Codegen (Aspect) then
-                     Set_Ignored_Class_Postconditions (E,
-                       New_Copy_Tree (Expr));
+                     Set_Ignored_Class_Postconditions (E, Class_Wide_Expr);
                   else
-                     Set_Class_Postconditions (E, New_Copy_Tree (Expr));
+                     Set_Class_Postconditions (E, Class_Wide_Expr);
                   end if;
                end if;
             end if;
@@ -5503,6 +5505,14 @@ package body Sem_Ch13 is
                     Pragma_Name                => Pname);
             end;
 
+            --  If class-wide expression was copied, then attach it to the AST,
+            --  so that its original context can be retrieved by climbing the
+            --  chain of parents.
+
+            if Present (Class_Wide_Expr) then
+               Set_Parent (Class_Wide_Expr, Aitem);
+            end if;
+
             --  For Pre/Post cases, insert immediately after the entity
             --  declaration, since that is the required pragma placement.
             --  Note that for these aspects, we do not have to worry
diff --git a/gcc/ada/sem_prag.adb b/gcc/ada/sem_prag.adb
index fb78b800590..60c05a62be9 100644
--- a/gcc/ada/sem_prag.adb
+++ b/gcc/ada/sem_prag.adb
@@ -5933,23 +5933,31 @@ package body Sem_Prag is
             declare
                Expr : constant Node_Id := Expression (Get_Argument (N));
 
+               Class_Wide_Expr : constant Node_Id := New_Copy_Tree (Expr);
+
             begin
                if Pname = Name_Pre_Class then
                   if Is_Ignored_In_Codegen (N) then
                      Set_Ignored_Class_Preconditions (Subp_Id,
-                       New_Copy_Tree (Expr));
+                       Class_Wide_Expr);
                   else
-                     Set_Class_Preconditions (Subp_Id, New_Copy_Tree (Expr));
+                     Set_Class_Preconditions (Subp_Id, Class_Wide_Expr);
                   end if;
 
                else
                   if Is_Ignored_In_Codegen (N) then
                      Set_Ignored_Class_Postconditions (Subp_Id,
-                       New_Copy_Tree (Expr));
+                       Class_Wide_Expr);
                   else
-                     Set_Class_Postconditions (Subp_Id, New_Copy_Tree (Expr));
+                     Set_Class_Postconditions (Subp_Id, Class_Wide_Expr);
                   end if;
                end if;
+
+               --  Attach the copied class-wide expression to the AST, so that
+               --  its original context can be retrieved by climbing the chain
+               --  of parents.
+
+               Set_Parent (Class_Wide_Expr, N);
             end;
          end if;
       end Analyze_Pre_Post_Condition;
-- 
2.53.0

Reply via email to