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

            Bug ID: 128044
           Summary: Fully qualified name resolved to the current package
                    when instantiating a generic child
           Product: gcc
           Version: 16.1.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: ada
          Assignee: unassigned at gcc dot gnu.org
          Reporter: lionel.draghi at free dot fr
                CC: dkm at gcc dot gnu.org
  Target Milestone: ---

Since GNAT 16.1, a legal Ada program is rejected when instantiating, through
the parent's instance, a generic child package whose simple name is the same
as one of its ancestors. A fully qualified reference to the ancestor inside
the generic child is resolved to the current instance of the child itself,
producing a premature-use error.

Distilled from OpenToken 6.0c; the generic formal parameters are removed,
they are not needed to trigger the error:

-- opentoken.ads
package OpenToken is end OpenToken;

-- opentoken-production.ads
generic
package OpenToken.Production is
end OpenToken.Production;

-- opentoken-production-parser.ads
generic
package OpenToken.Production.Parser is
   type Instance is abstract tagged null record;
   procedure Parse (Parser : in out Instance) is abstract;
end OpenToken.Production.Parser;

-- opentoken-production-parser-lalr.ads
generic
package OpenToken.Production.Parser.LALR is
end OpenToken.Production.Parser.LALR;

-- opentoken-production-parser-lalr-parser.ads
generic
package OpenToken.Production.Parser.LALR.Parser is
   type Instance is new OpenToken.Production.Parser.Instance
     with null record;
   overriding
   procedure Parse (Parser : in out Instance) is null;
end OpenToken.Production.Parser.LALR.Parser;

-- main.adb
with OpenToken.Production;
with OpenToken.Production.Parser;
with OpenToken.Production.Parser.LALR;
with OpenToken.Production.Parser.LALR.Parser;

procedure Main is
   package Production  is new OpenToken.Production;
   package Parser      is new Production.Parser;
   package LALRs       is new Parser.LALR;
   package LALR_Parser is new LALRs.Parser;
begin
   null;
end Main;

Observed (GNAT 16.1.0 and 16.2.0, default switches, Linux and Windows):

main.adb:10:04: error: instantiation error at
opentoken-production-parser-lalr-parser.ads:3
main.adb:10:04: error: type "Parser.Instance" cannot be used before end of its
declaration
main.adb:10:04: error: instantiation error at
opentoken-production-parser-lalr-parser.ads:6
main.adb:10:04: error: subprogram "Parse" is not overriding

Note that the type name quoted in the message, "Parser.Instance", does not
appear in the source, which uses the fully qualified
OpenToken.Production.Parser.Instance; the message itself betrays the
misresolution.

Expected: the program is legal and compiles (accepted by GNAT 14.2.1 and
15.2.1).

Version matrix (minimal repro, gcc -c main.adb, default switches, Linux
x86_64):

- GNAT 14.2.1 (GNAT-FSF-builds via Alire): OK
- GNAT 15.2.1 (GNAT-FSF-builds via Alire): OK
- GNAT 16.1.0 (GNAT-FSF-builds via Alire): FAIL
- GNAT 16.2.0 (Debian gcc-16): FAIL

The failure is not dependent on the language mode: on 16.1, -gnat2005 and
-gnat2012 produce the identical error, so this is not a default-standard
change effect.

Observations:

1. The generic template compiles on its own
   (gcc -c opentoken-production-parser-lalr-parser.ads). The error appears
   only at the last instantiation, of a generic child through the parent's
   instance.
2. Renaming the grandchild to OpenToken.Production.Parser.LALR.Lalr_Parser -
   so it no longer shares its simple name with its grandparent
   OpenToken.Production.Parser - makes everything compile, with the reference
   OpenToken.Production.Parser.Instance left unchanged. This points to a
   name resolution issue in the instance context, not to a legality rule.
3. Adding "package Grandparent renames OpenToken.Production.Parser;" in the
   grandchild and deriving from Grandparent.Instance does not work around
   it: the error becomes
   type "Grandparent.Instance" cannot be used before end of its declaration.

So, in the instance context, the ancestor subtype mark
OpenToken.Production.Parser is (incorrectly) taken to denote the current
instance of the child generic, hence the premature use.

Real-world impact: OpenToken 6.0.3 (current release in the Alire index) no
longer builds on GNAT 16 for any user instantiating
OpenToken.Production.Parser.LALR.Parser (e.g. ArchiCheck). The same sources
have been built fine with earlier GNAT releases for years.

Discussed at
https://forum.ada-lang.io/t/gnat-16-1-fully-qualified-name-resolved-to-the-current-package-when-instantiating-a-generic-child-bug/4826

Reply via email to