[PATCH] D51997: [clang] Make sure attributes on member classes are applied properly
Louis Dionne via Phabricator via cfe-commits
cfe-commits at lists.llvm.org
Wed Sep 12 11:14:45 PDT 2018
ldionne added a comment.
This patch is missing support for partial specializations and explicit specializations. The part I don't understand is how to get the `CXXRecordDecl`s to have the right attribute below. Here's the AST dump for the test file with the current patch:
TranslationUnitDecl 0x7f8a2a00a8e8 <<invalid sloc>> <invalid sloc>
|-TypedefDecl 0x7f8a2a00b1c0 <<invalid sloc>> <invalid sloc> implicit __int128_t '__int128'
| `-BuiltinType 0x7f8a2a00ae80 '__int128'
|-TypedefDecl 0x7f8a2a00b228 <<invalid sloc>> <invalid sloc> implicit __uint128_t 'unsigned __int128'
| `-BuiltinType 0x7f8a2a00aea0 'unsigned __int128'
|-TypedefDecl 0x7f8a2a00b558 <<invalid sloc>> <invalid sloc> implicit __NSConstantString '__NSConstantString_tag'
| `-RecordType 0x7f8a2a00b300 '__NSConstantString_tag'
| `-CXXRecord 0x7f8a2a00b278 '__NSConstantString_tag'
|-TypedefDecl 0x7f8a28827600 <<invalid sloc>> <invalid sloc> implicit __builtin_ms_va_list 'char *'
| `-PointerType 0x7f8a2a00b5b0 'char *'
| `-BuiltinType 0x7f8a2a00a980 'char'
|-TypedefDecl 0x7f8a28827928 <<invalid sloc>> <invalid sloc> implicit __builtin_va_list '__va_list_tag [1]'
| `-ConstantArrayType 0x7f8a288278d0 '__va_list_tag [1]' 1
| `-RecordType 0x7f8a288276e0 '__va_list_tag'
| `-CXXRecord 0x7f8a28827650 '__va_list_tag'
|-ClassTemplateDecl 0x7f8a28827ab8 </Users/ldionne/work/clang-attribute/clang/test/SemaCXX/PR38913.cpp:7:1, col:77> col:26 A
| |-TemplateTypeParmDecl 0x7f8a28827978 <col:10, col:16> col:16 class depth 0 index 0 T
| |-CXXRecordDecl 0x7f8a28827a30 <col:19, col:77> 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 trivial has_const_param needs_implicit implicit_has_const_param
| | | |-MoveAssignment exists simple trivial needs_implicit
| | | `-Destructor simple irrelevant trivial needs_implicit
| | |-CXXRecordDecl 0x7f8a28827d00 <col:19, col:26> col:26 implicit struct A
| | `-CXXRecordDecl 0x7f8a28827e38 <col:30, col:74> col:70 struct X 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 trivial has_const_param needs_implicit implicit_has_const_param
| | | |-MoveAssignment exists simple trivial needs_implicit
| | | `-Destructor simple irrelevant trivial needs_implicit
| | |-AbiTagAttr 0x7f8a28827f48 <col:52, col:66> ATAG
| | `-CXXRecordDecl 0x7f8a28827fa8 <col:30, col:70> col:70 implicit struct X
| `-ClassTemplateSpecializationDecl 0x7f8a28828088 <col:1, col:77> col:26 struct A definition
| |-DefinitionData pass_in_registers 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 trivial has_const_param needs_implicit implicit_has_const_param
| | |-MoveAssignment exists simple trivial needs_implicit
| | `-Destructor simple irrelevant trivial needs_implicit
| |-TemplateArgument type 'int'
| |-CXXRecordDecl 0x7f8a28828280 prev 0x7f8a28828088 <col:19, col:26> col:26 implicit struct A
| `-CXXRecordDecl 0x7f8a28828308 <col:30, col:70> col:70 referenced struct X
| `-AbiTagAttr 0x7f8a288283b0 <col:52> ATAG
|-FunctionDecl 0x7f8a2885a200 <line:8:1, col:28> col:12 a 'A<int>::X *()'
| `-CompoundStmt 0x7f8a2885a328 <col:16, col:28>
| `-ReturnStmt 0x7f8a2885a310 <col:18, col:25>
| `-ImplicitCastExpr 0x7f8a2885a2f8 <col:25> 'A<int>::X *' <NullToPointer>
| `-IntegerLiteral 0x7f8a2885a2d8 <col:25> 'int' 0
|-ClassTemplateDecl 0x7f8a2885a448 <line:11:1, col:95> col:26 B
| |-TemplateTypeParmDecl 0x7f8a2885a340 <col:10, col:16> col:16 class depth 0 index 0 T
| |-CXXRecordDecl 0x7f8a2885a3c0 <col:19, col:95> col:26 struct B 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 trivial has_const_param needs_implicit implicit_has_const_param
| | | |-MoveAssignment exists simple trivial needs_implicit
| | | `-Destructor simple irrelevant trivial needs_implicit
| | |-CXXRecordDecl 0x7f8a2885a690 <col:19, col:26> col:26 implicit struct B
| | `-ClassTemplateDecl 0x7f8a2885a888 <col:30, col:92> col:88 X
| | |-TemplateTypeParmDecl 0x7f8a2885a718 <col:39, col:45> col:45 class depth 1 index 0 U
| | `-CXXRecordDecl 0x7f8a2885a800 <col:48, col:92> col:88 struct X 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 trivial has_const_param needs_implicit implicit_has_const_param
| | | |-MoveAssignment exists simple trivial needs_implicit
| | | `-Destructor simple irrelevant trivial needs_implicit
| | |-AbiTagAttr 0x7f8a2885aad0 <col:70, col:84> BTAG
| | `-CXXRecordDecl 0x7f8a2885ab38 <col:48, col:88> col:88 implicit struct X
| `-ClassTemplateSpecializationDecl 0x7f8a2885ac18 <col:1, col:95> col:26 struct B definition
| |-DefinitionData pass_in_registers 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 trivial has_const_param needs_implicit implicit_has_const_param
| | |-MoveAssignment exists simple trivial needs_implicit
| | `-Destructor simple irrelevant trivial needs_implicit
| |-TemplateArgument type 'int'
| |-CXXRecordDecl 0x7f8a2885adf8 prev 0x7f8a2885ac18 <col:19, col:26> col:26 implicit struct B
| `-ClassTemplateDecl 0x7f8a2885af88 <col:30, col:88> col:88 X
| |-TemplateTypeParmDecl 0x7f8a2885ae80 <col:39, col:45> col:45 class depth 0 index 0 U
| |-CXXRecordDecl 0x7f8a2885af00 <col:48, col:88> col:88 struct X
| | `-AbiTagAttr 0x7f8a2885b038 <col:70> BTAG
| |-ClassTemplateSpecializationDecl 0x7f8a2885b290 <col:30, col:88> col:88 struct X
| | |-TemplateArgument type 'int'
| | `-AbiTagAttr 0x7f8a2885b390 <col:70> BTAG
| `-AbiTagAttr 0x7f8a2885afd8 <col:70> BTAG
|-FunctionDecl 0x7f8a2885b5d8 <line:12:1, col:33> col:17 b 'B<int>::X<int> *()'
| `-CompoundStmt 0x7f8a2885b6c0 <col:21, col:33>
| `-ReturnStmt 0x7f8a2885b6a8 <col:23, col:30>
| `-ImplicitCastExpr 0x7f8a2885b690 <col:30> 'B<int>::X<int> *' <NullToPointer>
| `-IntegerLiteral 0x7f8a2885b670 <col:30> 'int' 0
|-ClassTemplateDecl 0x7f8a2885b7e8 <line:15:1, line:18:1> line:15:26 C
| |-TemplateTypeParmDecl 0x7f8a2885b6d8 <col:10, col:16> col:16 class depth 0 index 0 T
| |-CXXRecordDecl 0x7f8a2885b760 <col:19, line:18:1> line:15:26 struct C 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 trivial has_const_param needs_implicit implicit_has_const_param
| | | |-MoveAssignment exists simple trivial needs_implicit
| | | `-Destructor simple irrelevant trivial needs_implicit
| | |-CXXRecordDecl 0x7f8a2885ba30 <col:19, col:26> col:26 implicit struct C
| | |-ClassTemplateDecl 0x7f8a2885bc70 <line:16:3, col:41> col:37 X
| | | |-TemplateTypeParmDecl 0x7f8a2885bab8 <col:12, col:18> col:18 class depth 1 index 0 U
| | | |-TemplateTypeParmDecl 0x7f8a2885bb28 <col:21, col:27> col:27 class depth 1 index 1 V
| | | `-CXXRecordDecl 0x7f8a2885bbe8 <col:30, col:41> col:37 struct X 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 trivial has_const_param needs_implicit implicit_has_const_param
| | | | |-MoveAssignment exists simple trivial needs_implicit
| | | | `-Destructor simple irrelevant trivial needs_implicit
| | | `-CXXRecordDecl 0x7f8a2885bf00 <col:30, col:37> col:37 implicit struct X
| | `-ClassTemplatePartialSpecializationDecl 0x7f8a29803000 <line:17:3, col:73> col:61 struct X 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 trivial has_const_param needs_implicit implicit_has_const_param
| | | |-MoveAssignment exists simple trivial needs_implicit
| | | `-Destructor simple irrelevant trivial needs_implicit
| | |-TemplateArgument type 'int'
| | |-TemplateArgument type 'type-parameter-1-0'
| | |-TemplateTypeParmDecl 0x7f8a2885bfa8 <col:12, col:18> col:18 referenced class depth 1 index 0 V
| | |-AbiTagAttr 0x7f8a29803138 <col:43, col:57> CTAG
| | `-CXXRecordDecl 0x7f8a298032b8 <col:21, col:61> col:61 implicit struct X
| `-ClassTemplateSpecializationDecl 0x7f8a29803398 <line:15:1, line:18:1> line:15:26 struct C definition
| |-DefinitionData pass_in_registers 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 trivial has_const_param needs_implicit implicit_has_const_param
| | |-MoveAssignment exists simple trivial needs_implicit
| | `-Destructor simple irrelevant trivial needs_implicit
| |-TemplateArgument type 'int'
| |-CXXRecordDecl 0x7f8a29803578 prev 0x7f8a29803398 <col:19, col:26> col:26 implicit struct C
| `-ClassTemplateDecl 0x7f8a298037b0 <line:16:3, col:37> col:37 X
| |-TemplateTypeParmDecl 0x7f8a29803600 <col:12, col:18> col:18 class depth 0 index 0 U
| |-TemplateTypeParmDecl 0x7f8a29803668 <col:21, col:27> col:27 class depth 0 index 1 V
| |-CXXRecordDecl 0x7f8a29803728 <col:30, col:37> col:37 struct X
| `-ClassTemplateSpecializationDecl 0x7f8a29803e30 <col:3, col:37> col:37 struct X
| |-TemplateArgument type 'int'
| `-TemplateArgument type 'long'
|-FunctionDecl 0x7f8a29804990 <line:19:1, col:39> col:23 c 'C<int>::X<int, long> *()'
| `-CompoundStmt 0x7f8a29804a78 <col:27, col:39>
| `-ReturnStmt 0x7f8a29804a60 <col:29, col:36>
| `-ImplicitCastExpr 0x7f8a29804a48 <col:36> 'C<int>::X<int, long> *' <NullToPointer>
| `-IntegerLiteral 0x7f8a29804a28 <col:36> 'int' 0
|-ClassTemplateDecl 0x7f8a29804b98 <line:22:1, line:25:1> line:22:26 D
| |-TemplateTypeParmDecl 0x7f8a29804a90 <col:10, col:16> col:16 class depth 0 index 0 T
| |-CXXRecordDecl 0x7f8a29804b10 <col:19, line:25:1> line:22:26 struct D 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 trivial has_const_param needs_implicit implicit_has_const_param
| | | |-MoveAssignment exists simple trivial needs_implicit
| | | `-Destructor simple irrelevant trivial needs_implicit
| | |-CXXRecordDecl 0x7f8a29804de0 <col:19, col:26> col:26 implicit struct D
| | |-ClassTemplateDecl 0x7f8a29804f78 <line:23:3, col:32> col:28 X
| | | |-TemplateTypeParmDecl 0x7f8a29804e68 <col:12, col:18> col:18 class depth 1 index 0 U
| | | |-CXXRecordDecl 0x7f8a29804ef0 <col:21, col:32> col:28 struct X 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 trivial has_const_param needs_implicit implicit_has_const_param
| | | | | |-MoveAssignment exists simple trivial needs_implicit
| | | | | `-Destructor simple irrelevant trivial needs_implicit
| | | | `-CXXRecordDecl 0x7f8a298051c0 <col:21, col:28> col:28 implicit struct X
| | | `-ClassTemplateSpecialization 0x7f8a298052c0 'X'
| | `-ClassTemplateSpecializationDecl 0x7f8a298052c0 <line:24:3, col:63> col:54 struct X 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 trivial has_const_param needs_implicit implicit_has_const_param
| | | |-MoveAssignment exists simple trivial needs_implicit
| | | `-Destructor simple irrelevant trivial needs_implicit
| | |-TemplateArgument type 'int'
| | |-AbiTagAttr 0x7f8a29805470 <col:36, col:50> DTAG
| | `-CXXRecordDecl 0x7f8a298055c8 <col:14, col:54> col:54 implicit struct X
| `-ClassTemplateSpecializationDecl 0x7f8a298056a8 <line:22:1, line:25:1> line:22:26 struct D definition
| |-DefinitionData pass_in_registers 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 trivial has_const_param needs_implicit implicit_has_const_param
| | |-MoveAssignment exists simple trivial needs_implicit
| | `-Destructor simple irrelevant trivial needs_implicit
| |-TemplateArgument type 'int'
| |-CXXRecordDecl 0x7f8a2a03b6a8 prev 0x7f8a298056a8 <col:19, col:26> col:26 implicit struct D
| |-ClassTemplateDecl 0x7f8a2a03b838 <line:23:3, col:28> col:28 X
| | |-TemplateTypeParmDecl 0x7f8a2a03b730 <col:12, col:18> col:18 class depth 0 index 0 U
| | |-CXXRecordDecl 0x7f8a2a03b7b0 <col:21, col:28> col:28 struct X
| | `-ClassTemplateSpecialization 0x7f8a2a03ba18 'X'
| `-ClassTemplateSpecializationDecl 0x7f8a2a03ba18 <line:24:3, col:63> col:54 struct X definition
| |-DefinitionData pass_in_registers 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 trivial has_const_param needs_implicit implicit_has_const_param
| | |-MoveAssignment exists simple trivial needs_implicit
| | `-Destructor simple irrelevant trivial needs_implicit
| |-TemplateArgument type 'int'
| |-AbiTagAttr 0x7f8a2a03bbe0 <col:36> DTAG
| `-CXXRecordDecl 0x7f8a2a03bcb0 prev 0x7f8a2a03ba18 <col:14, col:54> col:54 implicit struct X
`-FunctionDecl 0x7f8a2a03bf98 <line:26:1, col:33> col:17 d 'D<int>::X<int> *()'
`-CompoundStmt 0x7f8a2a03c080 <col:21, col:33>
`-ReturnStmt 0x7f8a2a03c068 <col:23, col:30>
`-ImplicitCastExpr 0x7f8a2a03c050 <col:30> 'D<int>::X<int> *' <NullToPointer>
`-IntegerLiteral 0x7f8a2a03c030 <col:30> 'int' 0
As you can see, the `CXXRecordDecl`s have the right attributes for the member class and member class template cases, but not for the partial and explicit specializations.
================
Comment at: clang/lib/Sema/SemaTemplateInstantiateDecl.cpp:2971
InstD->setExternLoc(D->getExternLoc());
InstD->setTemplateKeywordLoc(D->getTemplateKeywordLoc());
----------------
I tried a couple variations of things like:
```
SemaRef.InstantiateAttrsForDecl(TemplateArgs, D, InstD, LateAttrs, StartingScope);
```
and
```
SemaRef.InstantiateAttrsForDecl(TemplateArgs, D, ClassTemplate->getTemplatedDecl(), LateAttrs, StartingScope);
```
For some reason, none of them end up instantiating the attribute on the `CXXRecordDecl` that is used to determine the mangling.
================
Comment at: clang/lib/Sema/SemaTemplateInstantiateDecl.cpp:3247
InstPartialSpec->setTypeAsWritten(WrittenTy);
// Check the completed partial specialization.
----------------
I tried adding
```
SemaRef.InstantiateAttrsForDecl(TemplateArgs, ClassTemplate->getTemplatedDecl(), InstPartialSpec, LateAttrs, StartingScope);
```
here, but just like for explicit specializations, that doesn't instantiate the attributes on the `CXXRecordDecl` used to determine mangling.
================
Comment at: clang/test/SemaCXX/PR38913.cpp:19
+};
+C<int>::X<int, long>* c() { return 0; } // CHECK-DAG: @_Z1cB4CTAGv
+
----------------
This test is failing in the current iteration of the patch.
================
Comment at: clang/test/SemaCXX/PR38913.cpp:26
+};
+D<int>::X<int>* d() { return 0; } // CHECK-DAG: @_Z1dB4DTAGv
----------------
This test is failing in the current iteration of the patch.
Repository:
rC Clang
https://reviews.llvm.org/D51997
More information about the cfe-commits
mailing list