https://gcc.gnu.org/bugzilla/show_bug.cgi?id=123138

            Bug ID: 123138
           Summary: [GNAT 15/16 Regression] ICE when comparing
                    Universal_Integer reduction expression with integer
                    constant
           Product: gcc
           Version: 16.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: ada
          Assignee: unassigned at gcc dot gnu.org
          Reporter: lisa at felidae dot bam.moe
                CC: dkm at gcc dot gnu.org
  Target Milestone: ---

Consider the following code (main.adb):

```
procedure Main is
        X : array(1..2) of Integer := (1,2);
begin
        if [for E of X => 1]'Reduce("+",0) = 3 then
                null;
        end if;
end Main;
```

When compiled on GNAT 15.2.0 (tested on Debian 14 x86_64 and Windows x86_64) or
GNAT 16 (tested on Debian 14 x86_64 with commit
897cba5b334294bc5c9f184764f9395f0c628fcf, configured with `../configure
--disable-multilib --disable-bootstrap --enable-checking=yes,rtl
--enable-languages=c,ada CFLAGS='-O0 -g3' CXXFLAGS='-O0 -g3'`) with `gcc -c
-gnat2022 main.adb`, the following appears:

```
+===========================GNAT BUG DETECTED==============================+
| 16.0.0 20251215 (experimental) (x86_64-pc-linux-gnu) GCC error:          |
| in build_binary_op, at ada/gcc-interface/utils2.cc:1341                  |
| Error detected at main.adb:4:46                                          |
| Compiling main.adb                                                       |
| Please submit a bug report; see https://gcc.gnu.org/bugs/ .              |
| Use a subject line meaningful to you and us to track the bug.            |
| Include the entire contents of this bug box in the report.               |
| Include the exact command that you entered.                              |
| Also include sources listed below.                                       |
+==========================================================================+

Please include these source files with error report
Note that list may not be accurate in some cases,
so please double check that the problem can still
be reproduced with the set of files listed.
Consider also -gnatd.n switch (see debug.adb).

main.adb
```

It appears to compile fine on GNAT 13.3.0 (Debian 13 arm64) and 14.2.0 (Debian
13 arm64).

You can work around the bug by wrapping either the reduce expression, the
integer constant, or both in an Integer(), like so:

```
if Integer([for E of X => 1]'Reduce("+",0)) = 3 then

-- or 

if [for E of X => 1]'Reduce("+",0) = Integer(3) then

-- or

if Integer([for E of X => 1]'Reduce("+",0)) = Integer(3) then

```

After some debugging, I believe the issue comes from the reduce expression's
type not being resolved early enough when GNAT does semantic analysis. The
issue manifests in gcc/ada/gcc-interface/utils2.cc's build_binary_op, which
receives a left operand with base type Integer, and a right operand with base
type Universal_Integer. The function is only built to handle differing base
types in the case of pointer or record types, so it hits a gcc_unreachable().
The reason behind the differing base types seems to be that the analyzer for
the Reduce attribute assigns it a type of Universal_Integer, but this type gets
converted to Standard.Integer by Resolve_Attribute, called from
Resolve_Equality_Op. By that time, the type of the right operand in
Resolve_Equality_Op has already been set to Universal_Integer (as
Find_Unique_Type on 2 Universal_Integers returns Universal_Integer), so they're
mismatched.

I implemented a hacky workaround by checking if the analyzer set the type to
Universal_Integer or Universal_Real, and overriding it with Standard_Integer or
Standard_Float, respectively. This way, when Resolve_Equality_Op calls
Find_Unique_Type it returns Standard.Integer, and the integer constant gets
converted to that as well. It seems to work -- it prevents the crash -- but I'm
not very familiar with GNAT or GCC in general, so I don't know if it's the
correct solution. I hope my little investigation proves helpful at least. I've
never worked on GCC before, so take it with a grain of salt; it's entirely
possible I missed some things.

Reply via email to