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;
