Skip to content

No TypeLoc node for outer nested-name-specifier in pointer-to-member type #118198

@HighCommander4

Description

@HighCommander4

In the following code:

struct Outer {
  struct Inner {};
};

using Alias = void (Outer::Inner:: *)();

the token Outer on the last line does not get a TypeLoc node in the AST.

Here's what TypeLoc::dump() prints for the MemberPointerTypeLoc representing void (Outer::Inner:: *)():

MemberPointerTypeLoc 'void (struct Outer::Inner::*)(void)'
|-RecordTypeLoc 'struct Outer::Inner'
| `-CXXRecord 0x5583b9d05430 'Inner'
`-ParenTypeLoc 'void (void)'
  `-FunctionProtoTypeLoc 'void (void)' cdecl
    `-BuiltinTypeLoc 'void'

The TypeLoc for the "class" part of the member pointer is a RecordTypeLoc for Outer::Inner, with no distinct TypeLoc for Outer.

In other contexts where a nested class type like Outer::Inner appears, it's represented as an ElaboratedTypeLoc wrapping the RecordTypeLoc. The ElaboratedTypeLoc exposes a NestedNameSpecifierLoc which allows getting at TypeLocs for other elements of the nested-name-specifier.

A consequence of this missing TypeLoc is that many clangd features, including go-to-definition and semantic highlighting, do not work on the affected Outer token (clangd/clangd#2235).

Metadata

Metadata

Assignees

No one assigned

    Labels

    c++clang:frontendLanguage frontend issues, e.g. anything involving "Sema"

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions