]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
ada: Add error message for a declared-too-late abstract state constituent
authorSteve Baird <baird@adacore.com>
Tue, 14 Jan 2025 23:53:57 +0000 (15:53 -0800)
committerMarc Poulhiès <dkm@gcc.gnu.org>
Thu, 5 Jun 2025 08:18:35 +0000 (10:18 +0200)
In the error case of an undefined abstract state constituent, we want to
help users distinguish between the case where the constituent is
"really" undefined versus being defined "too late" (i.e., after a body).
So in the latter case we generate an additional message.

gcc/ada/ChangeLog:

* sem_prag.adb
(Analyze_Constituent): In the specific case case of a defined-too-late
abstract state constituent, generate an additional error message.

gcc/ada/sem_prag.adb

index dcee8600d7c392e9292bd3194d155231bfdacf47..83aae7c89a624908c2490bfbfb4a2b6239615fe2 100644 (file)
@@ -30940,34 +30940,67 @@ package body Sem_Prag is
                   --    end Pack;
 
                   if Constit_Id = Any_Id then
-                     SPARK_Msg_NE ("& is undefined", Constit, Constit_Id);
+                     --  A "Foo is undefined" message has already been
+                     --  generated for this constituent. Emit an additional
+                     --  message in the special case where the named
+                     --  would-be constituent was declared too late in the
+                     --  declaration list (as opposed to, for example, not
+                     --  being declared at all).
+
+                     --  Look for named constituent after freezing point
+                     if Present (Freeze_Id) then
+                        declare
+                           Decl : Node_Id;
+                        begin
+                           Decl := Enclosing_Declaration (Freeze_Id);
 
-                     --  Emit a specialized info message when the contract of
-                     --  the related package body was "frozen" by another body.
-                     --  Note that it is not possible to precisely identify why
-                     --  the constituent is undefined because it is not visible
-                     --  when pragma Refined_State is analyzed. This message is
-                     --  a reasonable approximation.
+                           while Present (Decl) loop
+                              if Nkind (Decl) = N_Object_Declaration
+                                and then Same_Name (Defining_Identifier (Decl),
+                                                    Constit)
+                                and then not Constant_Present (Decl)
+                              then
+                                 Error_Msg_Node_1 := Constit;
+                                 Error_Msg_Sloc :=
+                                   Sloc (Defining_Identifier (Decl));
 
-                     if Present (Freeze_Id) and then not Freeze_Posted then
-                        Freeze_Posted := True;
+                                 SPARK_Msg_NE
+                                  ("abstract state constituent & declared"
+                                   & " too late #!", Constit, Constit);
 
-                        Error_Msg_Name_1 := Chars (Body_Id);
-                        Error_Msg_Sloc   := Sloc (Freeze_Id);
-                        SPARK_Msg_NE
-                          ("body & declared # freezes the contract of %",
-                           N, Freeze_Id);
-                        SPARK_Msg_N
-                          ("\all constituents must be declared before body #",
-                           N);
+                                 exit;
+                              end if;
+                              Next (Decl);
+                           end loop;
+                        end;
+
+                        --  Emit a specialized info message when the contract
+                        --  of the related package body was "frozen" by
+                        --  another body. If a "declared too late" message
+                        --  is generated, this will clarify what is meant by
+                        --  "too late".
+
+                        if not Freeze_Posted then
+                           Freeze_Posted := True;
 
-                        --  A misplaced constituent is a critical error because
-                        --  pragma Refined_Depends or Refined_Global depends on
-                        --  the proper link between a state and a constituent.
-                        --  Stop the compilation, as this leads to a multitude
-                        --  of misleading cascaded errors.
+                           Error_Msg_Name_1 := Chars (Body_Id);
+                           Error_Msg_Sloc   := Sloc (Freeze_Id);
+                           SPARK_Msg_NE
+                             ("body & declared # freezes the contract of %",
+                              N, Freeze_Id);
+                           SPARK_Msg_N
+                             ("\all constituents must be declared" &
+                              " before body #", N);
 
-                        raise Unrecoverable_Error;
+                           --  A misplaced constituent is a critical error
+                           --  because pragma Refined_Depends or
+                           --  Refined_Global depends on the proper link
+                           --  between a state and a constituent. Stop the
+                           --  compilation, as this leads to a multitude of
+                           --  misleading cascaded errors.
+
+                           raise Unrecoverable_Error;
+                        end if;
                      end if;
 
                   --  The constituent is a valid state or object