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

            Bug ID: 93969
           Summary: Static data member cannot be initialized in place, if
                    it is of a nested class type with a default argument
                    in its constructor.
           Product: gcc
           Version: 9.2.1
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: igusarov at mail dot ru
  Target Milestone: ---

Dear gcc developers,

x86_64-gcc-9.2 available online at godbolt.org, refuses to compile a sample
program which I believe is well-formed:

    struct Outer
    {
        struct Inner
        {
            Inner(int arg = 23);
        };
        static inline Inner  x{};    // (1)
    };

If invoked with a sole "-std=c++17" command-line option, the compilation fails
at line marked (1) and the following error is reported:

        error: call to 'Outer::Inner::Inner(int)'
        uses the default argument for parameter 1,
        which is not yet defined

The sample program looks well-formed to me because of the following reasoning:
(clause numbers are per N4659 C++17 draft at
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/n4659.pdf )

1) Class Outer::Inner is fully defined at its closing brace (12.2/p6) and
therefore is already a complete-type before Outer::x data member is declared;

2) The declaration of static inline data member Outer::x comes with a
brace-initializer (12.2/p8) which means that it is also the definition
(12.2.3.2/p3), also initializing-declaration and defining declaration
(11.6/p21);

3) Outer::x is direct-list-initialized (11.6/p16, 11.6/p17); the initializer
list is empty;

4) Class Outer::Inner has a user-defined constructor Outer::Inner::Inner(int).
That constructor is the default constructor because every formal parameter has
a corresponding default argument (15.1/p4);

5) Combination of points 3) and 4) means that Outer::x should be
default-initialized (11.6.4/p3.4, 11.6/p8.1);

6) Default initialization of Outer::x should be performed by calling its
matching constructor with an empty argument list (11.6/p7.1);

7) Each time the constructor is called with no arguments, default argument
should be evaluated for the corresponding parameter (11.3.6/p9);

8) Default argument to that constructor is an integral constant expression
which is already defined. So it seems that evaluation of the said default
argument should cause no problem.

----
P.S. clang-9.0.0 also reports a similar error.

Reply via email to