This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 116a. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.

2024-12-19


2968. Name lookup result for typedef-name vs. class-name

Section: 6.5.1  [basic.lookup.general]     Status: open     Submitter: CWG     Date: 2024-11-21

Consider:

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

According to 6.5.1 [basic.lookup.general] paragraph 4:

In certain contexts, only certain kinds of declarations are included. After any such restriction, any declarations of classes or enumerations are discarded if any other declarations are found. [Note 4: A type (but not a typedef-name or template) is therefore hidden by any other entity in its scope. -- end note] However, if a lookup is type-only, only declarations of types and templates whose specializations are types are considered; furthermore, if declarations of a typedef-name and of the type to which it refers are found, the declaration of the typedef-name is discarded instead of the type declaration.

Thus, the declaration of s is ill-formed, because the public class-name S is discarded. Clang and EDG concur; GCC and MSVC prefer the public class-name.

Possible resolution:

Change in 6.5.1 [basic.lookup.general] paragraph 4 as follows:

...

However, if a lookup is type-only, only declarations of types and templates whose specializations are types are considered; furthermore, if declarations of a typedef-name and of the type to which it refers are found, the declaration of the typedef-name is discarded instead of the type declaration.

[ Example:

  class C {
  public:
    struct S { };          // #1
  private:
    typedef struct S S;    // #2
  };
  struct C::S s;           // OK, type-only lookup, C::S denotes #1, because #2 is discarded
  C::S s;                  // error: C::S denotes #2, because #1 is discarded

-- end example ]