Closed balazske closed 5 years ago
This fixes the "isValidBaseClass" assert at LLVM analysis.
Richard said:
It's intentional. The friend in the template does not constitute a declaration of ::Class until the template Base is instantiated. For example, the template parameters of the friend are at different depths than those of the class.
Can we have a test case where we instantiate Base
? We should see a redecl chain then (?).
Richard said:
It's intentional. The friend in the template does not constitute a declaration of ::Class until the template Base is instantiated. For example, the template parameters of the friend are at different depths than those of the class.
Can we have a test case where we instantiate
Base
? We should see a redecl chain then (?).
Well, I tried it, we will have a redecl chain, but between the Definition of Base
and the proto of Base
under the Specialization:
|-ClassTemplateDecl 0x217b288 <input.cc:2:9, line:6:9> line:3:16 Base
| |-TemplateTypeParmDecl 0x217b090 <line:2:19, col:25> col:25 class depth 0 index 0 T1
| |-TemplateTypeParmDecl 0x217b138 <col:29, col:35> col:35 class depth 0 index 1 T2
| |-CXXRecordDecl 0x217b1f8 <line:3:9, line:6:9> line:3:16 struct Base 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 0x217b520 <col:9, col:16> col:16 implicit struct Base
| | `-FriendDecl 0x217b9f8 <line:4:11, line:5:25> col:25
| | `-ClassTemplateDecl 0x217b7a8 parent 0x2109f08 <line:4:11, line:5:25> col:25 Class
| | |-TemplateTypeParmDecl 0x217b5b0 <line:4:21, col:27> col:27 class depth 1 index 0 U1
| | |-TemplateTypeParmDecl 0x217b658 <col:31, col:37> col:37 class depth 1 index 1 U2
| | `-CXXRecordDecl 0x217b718 parent 0x2109f08 <line:5:18, col:25> col:25 struct Class
| `-ClassTemplateSpecialization 0x21a6450 'Base'
|-ClassTemplateDecl 0x217bbf8 <line:7:9, line:8:24> col:16 Class
| |-TemplateTypeParmDecl 0x217ba68 <line:7:19, col:25> col:25 class depth 0 index 0 T1
| |-TemplateTypeParmDecl 0x217bad8 <col:29, col:35> col:35 class depth 0 index 1 T2
| `-CXXRecordDecl 0x217bb68 <line:8:9, col:24> col:16 struct Class 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 0x217be90 <col:9, col:16> col:16 implicit struct Class
`-ClassTemplateSpecializationDecl 0x21a6450 <line:9:9, col:37> col:24 struct Base 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'
|-TemplateArgument type 'int'
|-CXXRecordDecl 0x21a6688 prev 0x21a6450 <line:3:9, col:16> col:16 implicit struct Base
`-FriendDecl 0x21a6920 <line:4:11, line:5:25> col:25
`-ClassTemplateDecl 0x21a68a8 parent 0x2109f08 prev 0x217bbf8 <line:4:11, line:5:25> col:25 Class
|-TemplateTypeParmDecl 0x21a6718 <line:4:21, col:27> col:27 class depth 0 index 0 U1
|-TemplateTypeParmDecl 0x21a6788 <col:31, col:37> col:37 class depth 0 index 1 U2
`-CXXRecordDecl 0x21a6818 parent 0x2109f08 prev 0x217bb68 <line:5:18, col:25> col:25 struct Class
So, we don't need another test case, because the relation between the first two ClassTemplateDecl's of Base
does not change.
If there is a friend class template "prototype" (forward declaration) and later a definition for it in the existing code, this existing definition may be not found by ASTImporter because it is not linked to the prototype (under the friend AST node). The problem is fixed by looping over all found matching decls instead of break after the first found one.