https://gcc.gnu.org/g:85d7cf8cf72816e439252d5a9be9a0cbe1deac21

commit r17-5246-g85d7cf8cf72816e439252d5a9be9a0cbe1deac21
Author: Eric Botcazou <[email protected]>
Date:   Fri Oct 16 11:45:20 2026 +0200

    Ada: Fix inconsistent resolution of operator for nonlocal subtype of Integer
    
    The problem is that the predefined operators for the type of the subtype are
    correctly invisible when they are the only candidate interpretations in the
    overload resolution of an operation involving only integer literals, but are
    incorrectly visible when there are several candidate interpretations, thus
    leading to spurious ambiguities.
    
    gcc/ada/
            PR ada/126321
            * sem_type.adb (Has_Compatible_Type): Remove code redundant with
            the Covers routine, and deal specially with operations whose result
            is of an universal numeric type when they are overloaded.
    
    gcc/testsuite/
            * gnat.dg/test_rational_arithmetic2.adb: New test.
            * gnat.dg/rational_arithmetic2.ads: New helper package.
            * gnat.dg/invisible.ads: Likewise.

Diff:
---
 gcc/ada/sem_type.adb                               | 46 +++++-----------------
 gcc/testsuite/gnat.dg/invisible.ads                |  5 +++
 gcc/testsuite/gnat.dg/rational_arithmetic2.ads     | 22 +++++++++++
 .../gnat.dg/test_rational_arithmetic2.adb          | 13 ++++++
 4 files changed, 50 insertions(+), 36 deletions(-)

diff --git a/gcc/ada/sem_type.adb b/gcc/ada/sem_type.adb
index 8f7cdbcd266d..64581a43919d 100644
--- a/gcc/ada/sem_type.adb
+++ b/gcc/ada/sem_type.adb
@@ -2473,54 +2473,28 @@ package body Sem_Type is
          return False;
       end if;
 
+      --  Non-overloaded case. Note that we do not special case the operations
+      --  whose result is of an universal type like below, because we want to
+      --  give a specific error message for them in Check_For_Visible_Operator.
+
       if Nkind (N) = N_Subtype_Indication or else not Is_Overloaded (N) then
          if Covers (Typ, Etype (N))
-
-            --  Ada 2005 (AI-345): The context may be a synchronized interface.
-            --  If the type is already frozen, use the corresponding_record to
-            --  check whether it is a proper descendant.
-
-           or else
-             (Is_Record_Type (Typ)
-               and then Is_Concurrent_Type (Etype (N))
-               and then Present (Corresponding_Record_Type (Etype (N)))
-               and then Covers (Typ, Corresponding_Record_Type (Etype (N))))
-
-           or else
-             (Is_Concurrent_Type (Typ)
-               and then Is_Record_Type (Etype (N))
-               and then Present (Corresponding_Record_Type (Typ))
-               and then Covers (Corresponding_Record_Type (Typ), Etype (N)))
-
            or else Is_User_Defined_Literal (N, Typ)
-
          then
             return True;
          end if;
 
-      --  Overloaded case
+      --  Overloaded case. For an operation whose result is of an universal
+      --  numeric type, we need to check that the interpretation would be
+      --  a visible operator, because this cannot be done without context.
 
       else
          Get_First_Interp (N, I, It);
          while Present (It.Typ) loop
             if Covers (Typ, It.Typ)
-
-               --  Ada 2005 (AI-345)
-
-              or else
-                (Is_Record_Type (Typ)
-                  and then Is_Concurrent_Type (It.Typ)
-                  and then Present (Corresponding_Record_Type (Etype (It.Typ)))
-                  and then
-                    Covers (Typ, Corresponding_Record_Type (Etype (It.Typ))))
-
-              or else
-                (Is_Concurrent_Type (Typ)
-                  and then Is_Record_Type (It.Typ)
-                  and then Present (Corresponding_Record_Type (Typ))
-                  and then
-                    Covers (Corresponding_Record_Type (Typ), Etype (It.Typ)))
-
+              and then (Nkind (N) not in N_Op
+                         or else not Is_Universal_Numeric_Type (It.Typ)
+                         or else Is_Visible_Operator (N, Base_Type (Typ)))
             then
                return True;
             end if;
diff --git a/gcc/testsuite/gnat.dg/invisible.ads 
b/gcc/testsuite/gnat.dg/invisible.ads
new file mode 100644
index 000000000000..f027b5705937
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/invisible.ads
@@ -0,0 +1,5 @@
+package Invisible is
+
+  type Whole is new Integer;
+
+end Invisible;
diff --git a/gcc/testsuite/gnat.dg/rational_arithmetic2.ads 
b/gcc/testsuite/gnat.dg/rational_arithmetic2.ads
new file mode 100644
index 000000000000..f0e6250384eb
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/rational_arithmetic2.ads
@@ -0,0 +1,22 @@
+with Invisible;
+
+package Rational_Arithmetic2 is
+
+  subtype Whole is Invisible.Whole;
+
+  type Rational is private;
+
+  function "+" (Right: Whole) return Rational;
+
+  function "/" (Left, Right: Whole) return Rational;
+
+  function "=" (Left: Rational; Right: Whole) return Boolean;
+
+private
+
+  type Rational is record
+    Numerator  : Whole;
+    Denominator: Whole;
+  end record;
+
+end Rational_Arithmetic2;
diff --git a/gcc/testsuite/gnat.dg/test_rational_arithmetic2.adb 
b/gcc/testsuite/gnat.dg/test_rational_arithmetic2.adb
new file mode 100644
index 000000000000..c93430c4ad2a
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/test_rational_arithmetic2.adb
@@ -0,0 +1,13 @@
+-- { dg-do compile }
+
+with Rational_Arithmetic2; use Rational_Arithmetic2;
+
+procedure Test_Rational_Arithmetic2 is
+  R: Rational;
+  B: Boolean;
+  W: Whole;
+begin
+  R := +5;
+  B := R = 5/1; -- { dg-bogus "ambiguous expression" }
+  W := 5/1;     -- { dg-error "not directly visible|use clause" }
+end Test_Rational_Arithmetic2;

Reply via email to