https://gcc.gnu.org/g:bc2edee538d5a10bbeb0bcaf7017c1816e7331ce

commit r16-2754-gbc2edee538d5a10bbeb0bcaf7017c1816e7331ce
Author: Viljar Indus <in...@adacore.com>
Date:   Thu Jul 24 09:55:45 2025 +0300

    ada: Refactor Validate_Compile_Time_Warning_Or_Error
    
    Simplify the creation of the control characters in
    Validate_Compile_Time_Warning_Or_Error.
    
    gcc/ada/ChangeLog:
    
            * sem_prag.adb (Validate_Compile_Time_Warning_Or_Error):
            simplify the implementation.

Diff:
---
 gcc/ada/sem_prag.adb | 192 +++++++++++++++++++++++++++------------------------
 1 file changed, 102 insertions(+), 90 deletions(-)

diff --git a/gcc/ada/sem_prag.adb b/gcc/ada/sem_prag.adb
index ecb4e22b4f18..c30bf424ae2d 100644
--- a/gcc/ada/sem_prag.adb
+++ b/gcc/ada/sem_prag.adb
@@ -34263,113 +34263,123 @@ package body Sem_Prag is
      (N     : Node_Id;
       Eloc  : Source_Ptr)
    is
-      Arg1  : constant Node_Id := First (Pragma_Argument_Associations (N));
-      Arg1x : constant Node_Id := Get_Pragma_Arg (Arg1);
-      Arg2  : constant Node_Id := Next (Arg1);
+      Arg1    : constant Node_Id := First (Pragma_Argument_Associations (N));
+      Arg1x   : constant Node_Id := Get_Pragma_Arg (Arg1);
+      Prag_Id : constant Pragma_Id := Get_Pragma_Id (N);
 
-      Pname   : constant Name_Id   := Pragma_Name_Unmapped (N);
-      Prag_Id : constant Pragma_Id := Get_Pragma_Id (Pname);
+      procedure Emit_Compile_Time_Message (Msg_Arg : Node_Id);
+      --  Emit the pragma a as diagnostic message. New_Line characters are
+      --  considered separators for those messages where the following lines
+      --  are considered as continuation messages for the same diagnostic.
 
-   begin
-      Analyze_And_Resolve (Arg1x, Standard_Boolean);
+      -------------------------------
+      -- Emit_Compile_Time_Message --
+      -------------------------------
 
-      if Compile_Time_Known_Value (Arg1x) then
-         if Is_True (Expr_Value (Arg1x)) then
+      procedure Emit_Compile_Time_Message (Msg_Arg : Node_Id) is
+         --  We have already verified that the Msg_Arg is a static
+         --  string expression. Its string value must be retrieved
+         --  explicitly if it is a declared constant, otherwise it has
+         --  been constant-folded previously.
+
+         Cent    : constant Entity_Id := Cunit_Entity (Current_Sem_Unit);
+         Str     : constant String_Id :=
+           Strval (Expr_Value_S (Get_Pragma_Arg (Msg_Arg)));
+         Str_Len : constant Nat := String_Length (Str);
+
+         Force : constant Boolean :=
+           Prag_Id = Pragma_Compile_Time_Warning
+           and then Is_Spec_Name (Unit_Name (Current_Sem_Unit))
+           and then (Ekind (Cent) /= E_Package
+                     or else not In_Private_Part (Cent));
+         --  Set True if this is the warning case, and we are in the
+         --  visible part of a package spec, or in a subprogram spec,
+         --  in which case we want to force the client to see the
+         --  warning, even though it is not in the main unit.
+
+         Msg_Ctrl : Bounded_String (6);
+         --  Control characters for the message.
+         --  The longest value contains 6 characters: "\<<~!!"
+
+         C    : Character;
+         CC   : Char_Code;
+         Cont : Boolean;
+         Ptr  : Nat;
 
-            --  We have already verified that the second argument is a static
-            --  string expression. Its string value must be retrieved
-            --  explicitly if it is a declared constant, otherwise it has
-            --  been constant-folded previously.
+      begin
+         --  Loop through segments of message separated by line feeds.
+         --  We output these segments as separate messages with
+         --  continuation marks for all but the first.
 
-            declare
-               Cent    : constant Entity_Id := Cunit_Entity (Current_Sem_Unit);
-               Str     : constant String_Id :=
-                           Strval (Expr_Value_S (Get_Pragma_Arg (Arg2)));
-               Str_Len : constant Nat       := String_Length (Str);
-
-               Force : constant Boolean :=
-                         Prag_Id = Pragma_Compile_Time_Warning
-                           and then Is_Spec_Name (Unit_Name (Current_Sem_Unit))
-                           and then (Ekind (Cent) /= E_Package
-                                      or else not In_Private_Part (Cent));
-               --  Set True if this is the warning case, and we are in the
-               --  visible part of a package spec, or in a subprogram spec,
-               --  in which case we want to force the client to see the
-               --  warning, even though it is not in the main unit.
-
-               C    : Character;
-               CC   : Char_Code;
-               Cont : Boolean;
-               Ptr  : Nat;
+         Cont := False;
+         Ptr := 1;
+         loop
+            Error_Msg_Strlen := 0;
+            Msg_Ctrl.Length := 0;
 
-            begin
-               --  Loop through segments of message separated by line feeds.
-               --  We output these segments as separate messages with
-               --  continuation marks for all but the first.
+            --  Loop to copy characters from argument to error message
+            --  string buffer.
 
-               Cont := False;
-               Ptr  := 1;
-               loop
-                  Error_Msg_Strlen := 0;
+            loop
+               exit when Ptr > Str_Len;
+               CC := Get_String_Char (Str, Ptr);
+               Ptr := Ptr + 1;
 
-                  --  Loop to copy characters from argument to error message
-                  --  string buffer.
+               --  Ignore wide chars ??? else store character
 
-                  loop
-                     exit when Ptr > Str_Len;
-                     CC := Get_String_Char (Str, Ptr);
-                     Ptr := Ptr + 1;
+               if In_Character_Range (CC) then
+                  C := Get_Character (CC);
+                  exit when C = ASCII.LF;
+                  Error_Msg_Strlen := Error_Msg_Strlen + 1;
+                  Error_Msg_String (Error_Msg_Strlen) := C;
+               end if;
+            end loop;
 
-                     --  Ignore wide chars ??? else store character
+            --  Here with one line ready to go
 
-                     if In_Character_Range (CC) then
-                        C := Get_Character (CC);
-                        exit when C = ASCII.LF;
-                        Error_Msg_Strlen := Error_Msg_Strlen + 1;
-                        Error_Msg_String (Error_Msg_Strlen) := C;
-                     end if;
-                  end loop;
+            Error_Msg_Warn := Prag_Id = Pragma_Compile_Time_Warning;
 
-                  --  Here with one line ready to go
+            if Cont then
+               Append (Msg_Ctrl, "\");
+            end if;
 
-                  Error_Msg_Warn := Prag_Id = Pragma_Compile_Time_Warning;
+            Append (Msg_Ctrl, "<<~");
 
-                  --  If this is a warning in a spec, then we want clients
-                  --  to see the warning, so mark the message with the
-                  --  special sequence !! to force the warning. In the case
-                  --  of a package spec, we do not force this if we are in
-                  --  the private part of the spec.
+            --  If this is a warning in a spec, then we want clients
+            --  to see the warning, so mark the message with the
+            --  special sequence !! to force the warning. In the case
+            --  of a package spec, we do not force this if we are in
+            --  the private part of the spec.
 
-                  if Force then
-                     if Cont = False then
-                        Error_Msg
-                           ("<<~!!", Eloc, N, Is_Compile_Time_Pragma => True);
-                        Cont := True;
-                     else
-                        Error_Msg
-                           ("\<<~!!", Eloc, N, Is_Compile_Time_Pragma => True);
-                     end if;
+            if Force then
+               Append (Msg_Ctrl, "!!");
+            end if;
 
-                  --  Error, rather than warning, or in a body, so we do not
-                  --  need to force visibility for client (error will be
-                  --  output in any case, and this is the situation in which
-                  --  we do not want a client to get a warning, since the
-                  --  warning is in the body or the spec private part).
+            --  Error, rather than warning, or in a body, so we do not
+            --  need to force visibility for client (error will be
+            --  output in any case, and this is the situation in which
+            --  we do not want a client to get a warning, since the
+            --  warning is in the body or the spec private part).
 
-                  else
-                     if Cont = False then
-                        Error_Msg
-                           ("<<~", Eloc, N, Is_Compile_Time_Pragma => True);
-                        Cont := True;
-                     else
-                        Error_Msg
-                           ("\<<~", Eloc, N, Is_Compile_Time_Pragma => True);
-                     end if;
-                  end if;
+            Error_Msg
+              (To_String (Msg_Ctrl), Eloc, N, Is_Compile_Time_Pragma => True);
 
-                  exit when Ptr > Str_Len;
-               end loop;
-            end;
+            --  The next lines are considered continuation messages
+
+            Cont := True;
+
+            exit when Ptr > Str_Len;
+         end loop;
+      end Emit_Compile_Time_Message;
+
+   --  Start of processing for Validate_Compile_Time_Warning_Or_Error
+
+   begin
+      Analyze_And_Resolve (Arg1x, Standard_Boolean);
+
+      if Compile_Time_Known_Value (Arg1x) then
+         if Is_True (Expr_Value (Arg1x)) then
+            Emit_Compile_Time_Message (Next (Arg1));
          end if;
 
       --  Arg1x is not known at compile time, so possibly issue an error
@@ -35094,7 +35104,9 @@ package body Sem_Prag is
          begin
             Set_Scope (T.Scope);
             Reset_Analyzed_Flags (T.Prag);
-            Validate_Compile_Time_Warning_Or_Error (T.Prag, T.Eloc);
+            if Nkind (T.Prag) = N_Pragma then
+               Validate_Compile_Time_Warning_Or_Error (T.Prag, T.Eloc);
+            end if;
             Unset_Scope (T.Scope);
          end;
       end loop;

Reply via email to