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

            Bug ID: 124590
           Summary: Public typedef of private nested class rejected when
                    typedef has same name as class
           Product: gcc
           Version: 16.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: abhinavagarwal1996 at gmail dot com
  Target Milestone: ---

GCC rejects the following valid program:

class C {
    struct S { };
public:
    typedef struct S S;
};

void f() {
    C::S s;
    (void)s;
}

int main() { f(); }

Compile with: g++ -std=c++17 -Wall -Wextra test.cpp
(Reproduces under -std=c++98 through -std=c++26.)

GCC output:

test.cpp: In function 'void f()':
test.cpp:9:8: error: 'struct C::S' is private within this context
    9 |     C::S s;
      |        ^
test.cpp:2:12: note: declared private here
    2 |     struct S { };
      |            ^

https://godbolt.org/z/c1eGPr43b

Expected: the program is well-formed. Lookup of C::S finds both the class-name
and the typedef-name. This is not a type-only lookup context
([basic.lookup.general]/4), so the class declaration is discarded when the
typedef declaration exists. Only the public typedef survives, and access
control passes.

[class.access.general]/4 has an example showing this pattern:

class A {
  class B { };
public:
  typedef B BB;
};

void f() {
  A::BB x;    // OK, typedef A::BB is public
  A::B y;     // access error, A::B is private
}

The note says: "if access control is applied to a type alias, only the
accessibility of the typedef or alias declaration itself is considered."

The only difference here is that the typedef uses the same name as the class
(typedef struct S S). The discard rule in [basic.lookup.general]/4 applies
identically — both cases have a class declaration and a typedef declaration for
the same name.

Clang trunk accepts this. MSVC also rejects (separate bug).

Related to CWG 2968 (which covers the opposite access pattern: public class +
private typedef).

Reply via email to