The problem is that the compiler generates 'Valid_Scalars for a formal 
parameter of an Unchecked_Union type, which cannot work because it is not 
possible to find out where the scalars are in it, given that the parameter 
does not contain the discriminants of its Unchecked_Union type.  This also 
changes -gnateV to work without the need for -gnata, as there is no mention of 
this dependence in the documentation.

Tested on x86-64/Linux, applied on the mainline and 15 branch.


2026-01-28  Eric Botcazou  <[email protected]>

        PR ada/123857
        * checks.adb (Apply_Parameter_Validity_Checks.Add_Validity_Check):
        Set Is_Checked on the generated {Pre,Post}_Condition pragma and
        bail out if the parameter is of an Unchecked_Union type.


2026-01-28  Eric Botcazou  <[email protected]>

        * gnat.dg/unchecked_union4.adb: New test.

--
Eric Botcazou
diff --git a/gcc/ada/checks.adb b/gcc/ada/checks.adb
index 4d147d02036..55a81d90045 100644
--- a/gcc/ada/checks.adb
+++ b/gcc/ada/checks.adb
@@ -2584,6 +2584,10 @@ package body Checks is
                     Chars      => Name_Check,
                     Expression => Expr)));
 
+            --  The check is enabled unconditionally
+
+            Set_Is_Checked (Prag);
+
             --  Add a message unless exception messages are suppressed
 
             if not Exception_Locations_Suppressed then
@@ -2641,9 +2645,12 @@ package body Checks is
          if Is_Scalar_Type (Typ) then
             Nam := Name_Valid;
 
-         --  For any non-scalar with scalar parts, generate 'Valid_Scalars test
+         --  For non-scalars with scalar parts, generate 'Valid_Scalars test,
+         --  except for unchecked unions since we cannot know where they are.
 
-         elsif Scalar_Part_Present (Typ) then
+         elsif Scalar_Part_Present (Typ)
+           and then not Is_Unchecked_Union (Typ)
+         then
             Nam := Name_Valid_Scalars;
 
          --  No test needed for other cases (no scalars to test)
@@ -2735,8 +2742,7 @@ package body Checks is
          return;
       end if;
 
-      --  Inspect all the formals applying aliasing and scalar initialization
-      --  checks where applicable.
+      --  Apply scalar initialization checks to formals where applicable
 
       Formal := First_Formal (Subp);
       while Present (Formal) loop
--  { dg-do compile }
--  { dg-options "-gnateV" }

procedure Unchecked_Union4 is

   type R (Bytes_Mode : Boolean := False) is record
      case Bytes_Mode is
         when True =>
            A : Boolean;
         when False =>
            B : Boolean;
      end case;
   end record with Unchecked_Union;

   function F (Message : R) return Integer is (0);

begin
   null;
end;

Reply via email to