llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
26.82k stars 11k forks source link

`-ast-dump` provides incomplete content of template type alias declaration #67248

Open jonathanpoelen opened 9 months ago

jonathanpoelen commented 9 months ago

Consider this simple example:

template<class C> struct A { using type = C; };
template<class C> using t = typename A<C>::type;

With -ast-dump or -ast-dump=json, the type TypeAliasDecl does not contain information of each part of the alias value:

$ clang -fsyntax-only -Xclang -ast-dump test.cpp
TranslationUnitDecl 0x557305bbed48 <<invalid sloc>> <invalid sloc>
|-TypedefDecl 0x557305bbf5b0 <<invalid sloc>> <invalid sloc> implicit __int128_t '__int128'
| `-BuiltinType 0x557305bbf310 '__int128'
|-TypedefDecl 0x557305bbf620 <<invalid sloc>> <invalid sloc> implicit __uint128_t 'unsigned __int128'
| `-BuiltinType 0x557305bbf330 'unsigned __int128'
|-TypedefDecl 0x557305bbf998 <<invalid sloc>> <invalid sloc> implicit __NSConstantString '__NSConstantString_tag'
| `-RecordType 0x557305bbf710 '__NSConstantString_tag'
|   `-CXXRecord 0x557305bbf678 '__NSConstantString_tag'
|-TypedefDecl 0x557305bbfa30 <<invalid sloc>> <invalid sloc> implicit __builtin_ms_va_list 'char *'
| `-PointerType 0x557305bbf9f0 'char *'
|   `-BuiltinType 0x557305bbedf0 'char'
|-TypedefDecl 0x557305c06128 <<invalid sloc>> <invalid sloc> implicit __builtin_va_list '__va_list_tag[1]'
| `-ConstantArrayType 0x557305c060d0 '__va_list_tag[1]' 1 
|   `-RecordType 0x557305bbfb20 '__va_list_tag'
|     `-CXXRecord 0x557305bbfa88 '__va_list_tag'
|-ClassTemplateDecl 0x557305c062d0 <test.cpp:1:1, col:46> col:26 A
| |-TemplateTypeParmDecl 0x557305c06180 <col:10, col:16> col:16 referenced class depth 0 index 0 C
| `-CXXRecordDecl 0x557305c06240 <col:19, col:46> col:26 struct A definition
|   |-DefinitionData empty aggregate standard_layout trivially_copyable pod trivial literal has_constexpr_non_copy_move_ctor can_const_default_init
|   | |-DefaultConstructor exists trivial constexpr needs_implicit defaulted_is_constexpr
|   | |-CopyConstructor simple trivial has_const_param needs_implicit implicit_has_const_param
|   | |-MoveConstructor exists simple trivial needs_implicit
|   | |-CopyAssignment simple trivial has_const_param needs_implicit implicit_has_const_param
|   | |-MoveAssignment exists simple trivial needs_implicit
|   | `-Destructor simple irrelevant trivial needs_implicit
|   |-CXXRecordDecl 0x557305c06520 <col:19, col:26> col:26 implicit struct A
|   `-TypeAliasDecl 0x557305c065c0 <col:30, col:43> col:36 type 'C'
|     `-TemplateTypeParmType 0x557305c06200 'C' dependent depth 0 index 0
|       `-TemplateTypeParm 0x557305c06180 'C'
`-TypeAliasTemplateDecl 0x557305c06880 <line:2:1, col:44> col:19 t
  |-TemplateTypeParmDecl 0x557305c06638 <col:10, col:16> col:16 referenced class depth 0 index 0 C
  `-TypeAliasDecl 0x557305c06820 <col:19, col:44> col:25 t 'typename A<C>::type'
    `-DependentNameType 0x557305c067b0 'typename A<C>::type' dependent
{
          ....
          "name": "t",
          "type": {
            "qualType": "typename A<C>::type"
          },
          "inner": [
            {
              "id": "0x55a7efb20170",
              "kind": "DependentNameType",
              "type": {
                "qualType": "typename A<C>::type"
              },
              "isDependent": true,
              "isInstantiationDependent": true
            }
          ]
        }

The inner part, which should refer to A, C and type, is missing.

(clang 16.0.6, and 15, 16 and 18.0.0 (https://github.com/llvm/llvm-project.git 8a7f4eeb605324c8cb1996dba55ae3e24109d3d8) in compiler explorer)

mizvekov commented 9 months ago

Right, the AST Node Traverser is missing an implementation for DependentNameType, among other things:

https://github.com/llvm/llvm-project/blob/3f0bddb56ac33389e0a02444c6f67c7a42855582/clang/include/clang/AST/ASTNodeTraverser.h#L418

Another missing element not mentioned in that FIXME, but that would also be of interest to you, is traversal for NestedNameSpecifier, which is what would ultimately contain A and C (which would have been embedded in a TemplateSpecializationType inside of that, which we do implement already).

llvmbot commented 9 months ago

@llvm/issue-subscribers-clang-frontend

Consider this simple example: ```cpp template<class C> struct A { using type = C; }; template<class C> using t = typename A<C>::type; ``` With `-ast-dump` or `-ast-dump=json`, the type `TypeAliasDecl` does not contain information of each part of the alias value: ```console $ clang -fsyntax-only -Xclang -ast-dump test.cpp TranslationUnitDecl 0x557305bbed48 <<invalid sloc>> <invalid sloc> |-TypedefDecl 0x557305bbf5b0 <<invalid sloc>> <invalid sloc> implicit __int128_t '__int128' | `-BuiltinType 0x557305bbf310 '__int128' |-TypedefDecl 0x557305bbf620 <<invalid sloc>> <invalid sloc> implicit __uint128_t 'unsigned __int128' | `-BuiltinType 0x557305bbf330 'unsigned __int128' |-TypedefDecl 0x557305bbf998 <<invalid sloc>> <invalid sloc> implicit __NSConstantString '__NSConstantString_tag' | `-RecordType 0x557305bbf710 '__NSConstantString_tag' | `-CXXRecord 0x557305bbf678 '__NSConstantString_tag' |-TypedefDecl 0x557305bbfa30 <<invalid sloc>> <invalid sloc> implicit __builtin_ms_va_list 'char *' | `-PointerType 0x557305bbf9f0 'char *' | `-BuiltinType 0x557305bbedf0 'char' |-TypedefDecl 0x557305c06128 <<invalid sloc>> <invalid sloc> implicit __builtin_va_list '__va_list_tag[1]' | `-ConstantArrayType 0x557305c060d0 '__va_list_tag[1]' 1 | `-RecordType 0x557305bbfb20 '__va_list_tag' | `-CXXRecord 0x557305bbfa88 '__va_list_tag' |-ClassTemplateDecl 0x557305c062d0 <test.cpp:1:1, col:46> col:26 A | |-TemplateTypeParmDecl 0x557305c06180 <col:10, col:16> col:16 referenced class depth 0 index 0 C | `-CXXRecordDecl 0x557305c06240 <col:19, col:46> col:26 struct A definition | |-DefinitionData empty aggregate standard_layout trivially_copyable pod trivial literal has_constexpr_non_copy_move_ctor can_const_default_init | | |-DefaultConstructor exists trivial constexpr needs_implicit defaulted_is_constexpr | | |-CopyConstructor simple trivial has_const_param needs_implicit implicit_has_const_param | | |-MoveConstructor exists simple trivial needs_implicit | | |-CopyAssignment simple trivial has_const_param needs_implicit implicit_has_const_param | | |-MoveAssignment exists simple trivial needs_implicit | | `-Destructor simple irrelevant trivial needs_implicit | |-CXXRecordDecl 0x557305c06520 <col:19, col:26> col:26 implicit struct A | `-TypeAliasDecl 0x557305c065c0 <col:30, col:43> col:36 type 'C' | `-TemplateTypeParmType 0x557305c06200 'C' dependent depth 0 index 0 | `-TemplateTypeParm 0x557305c06180 'C' `-TypeAliasTemplateDecl 0x557305c06880 <line:2:1, col:44> col:19 t |-TemplateTypeParmDecl 0x557305c06638 <col:10, col:16> col:16 referenced class depth 0 index 0 C `-TypeAliasDecl 0x557305c06820 <col:19, col:44> col:25 t 'typename A<C>::type' `-DependentNameType 0x557305c067b0 'typename A<C>::type' dependent ``` ```json { .... "name": "t", "type": { "qualType": "typename A<C>::type" }, "inner": [ { "id": "0x55a7efb20170", "kind": "DependentNameType", "type": { "qualType": "typename A<C>::type" }, "isDependent": true, "isInstantiationDependent": true } ] } ``` The `inner` part, which should refer to `A`, `C` and `type`, is missing. (clang 16.0.6, and 15, 16 and 18.0.0 (https://github.com/llvm/llvm-project.git 8a7f4eeb605324c8cb1996dba55ae3e24109d3d8) in compiler explorer)