AST dumper: if we have multiple implicit instantiations of the same class

template specialization (from different modules), dump them all, so that every
declaration is dumped somewhere.

llvm-svn: 204100
This commit is contained in:
Richard Smith 2014-03-18 02:07:28 +00:00
parent 4a2f95f60e
commit cbdf733dba
2 changed files with 59 additions and 16 deletions

View File

@ -254,6 +254,11 @@ namespace {
void VisitTypeAliasTemplateDecl(const TypeAliasTemplateDecl *D);
void VisitCXXRecordDecl(const CXXRecordDecl *D);
void VisitStaticAssertDecl(const StaticAssertDecl *D);
template<typename SpecializationDecl>
void VisitTemplateDeclSpecialization(ChildDumper &Children,
const SpecializationDecl *D,
bool DumpExplicitInst,
bool DumpRefOnly);
template<typename TemplateDecl>
void VisitTemplateDecl(const TemplateDecl *D, bool DumpExplicitInst);
void VisitFunctionTemplateDecl(const FunctionTemplateDecl *D);
@ -1075,6 +1080,46 @@ void ASTDumper::VisitStaticAssertDecl(const StaticAssertDecl *D) {
dumpStmt(D->getMessage());
}
template<typename SpecializationDecl>
void ASTDumper::VisitTemplateDeclSpecialization(ChildDumper &Children,
const SpecializationDecl *D,
bool DumpExplicitInst,
bool DumpRefOnly) {
bool DumpedAny = false;
for (auto *RedeclWithBadType : D->redecls()) {
// FIXME: The redecls() range sometimes has elements of a less-specific
// type. (In particular, ClassTemplateSpecializationDecl::redecls() gives
// us TagDecls, and should give CXXRecordDecls).
auto *Redecl = dyn_cast<SpecializationDecl>(RedeclWithBadType);
if (!Redecl) {
// Found the injected-class-name for a class template. This will be dumped
// as part of its surrounding class so we don't need to dump it here.
assert(isa<CXXRecordDecl>(RedeclWithBadType) &&
"expected an injected-class-name");
continue;
}
switch (Redecl->getTemplateSpecializationKind()) {
case TSK_ExplicitInstantiationDeclaration:
case TSK_ExplicitInstantiationDefinition:
if (!DumpExplicitInst)
break;
// Fall through.
case TSK_Undeclared:
case TSK_ImplicitInstantiation:
Children.dump(Redecl, DumpRefOnly);
DumpedAny = true;
break;
case TSK_ExplicitSpecialization:
break;
}
}
// Ensure we dump at least one decl for each specialization.
if (!DumpedAny)
Children.dumpRef(D);
}
template<typename TemplateDecl>
void ASTDumper::VisitTemplateDecl(const TemplateDecl *D,
bool DumpExplicitInst) {
@ -1084,22 +1129,9 @@ void ASTDumper::VisitTemplateDecl(const TemplateDecl *D,
ChildDumper Children(*this);
Children.dump(D->getTemplatedDecl());
for (auto *Child : D->specializations()) {
switch (Child->getTemplateSpecializationKind()) {
case TSK_Undeclared:
case TSK_ImplicitInstantiation:
Children.dump(Child, /*Ref*/D != D->getCanonicalDecl());
break;
case TSK_ExplicitInstantiationDeclaration:
case TSK_ExplicitInstantiationDefinition:
Children.dump(Child, /*Ref*/D != D->getCanonicalDecl() ||
!DumpExplicitInst);
break;
case TSK_ExplicitSpecialization:
Children.dumpRef(Child);
break;
}
}
for (auto *Child : D->specializations())
VisitTemplateDeclSpecialization(Children, Child, DumpExplicitInst,
!D->isCanonicalDecl());
}
void ASTDumper::VisitFunctionTemplateDecl(const FunctionTemplateDecl *D) {

View File

@ -1,6 +1,7 @@
// RUN: rm -rf %t
// RUN: not %clang_cc1 -x objective-c++ -fmodules -fmodules-cache-path=%t -I %S/Inputs %s -std=c++11 -ast-dump -ast-dump-lookups | FileCheck %s --check-prefix=CHECK-GLOBAL
// RUN: not %clang_cc1 -x objective-c++ -fmodules -fmodules-cache-path=%t -I %S/Inputs %s -std=c++11 -ast-dump -ast-dump-lookups -ast-dump-filter N | FileCheck %s --check-prefix=CHECK-NAMESPACE-N
// RUN: not %clang_cc1 -x objective-c++ -fmodules -fmodules-cache-path=%t -I %S/Inputs %s -std=c++11 -ast-dump | FileCheck %s --check-prefix=CHECK-DUMP
// RUN: %clang_cc1 -x objective-c++ -fmodules -fmodules-cache-path=%t -I %S/Inputs %s -verify -std=c++11
@import cxx_templates_a;
@ -123,3 +124,13 @@ void testImplicitSpecialMembers(SomeTemplate<char[1]> &a,
// CHECK-NAMESPACE-N: DeclarationName 'f'
// CHECK-NAMESPACE-N-NEXT: |-FunctionTemplate {{.*}} 'f'
// CHECK-NAMESPACE-N-NEXT: `-FunctionTemplate {{.*}} 'f'
// CHECK-DUMP: ClassTemplateDecl {{.*}} <{{.*}}/cxx-templates-common.h:1:1, {{.*}}> in cxx_templates_common SomeTemplate
// CHECK-DUMP: ClassTemplateSpecializationDecl {{.*}} prev [[CHAR2:[^ ]*]] {{.*}} SomeTemplate
// CHECK-DUMP-NEXT: TemplateArgument type 'char [2]'
// CHECK-DUMP: ClassTemplateSpecializationDecl [[CHAR2]] {{.*}} SomeTemplate definition
// CHECK-DUMP-NEXT: TemplateArgument type 'char [2]'
// CHECK-DUMP: ClassTemplateSpecializationDecl {{.*}} prev [[CHAR1:[^ ]*]] {{.*}} SomeTemplate
// CHECK-DUMP-NEXT: TemplateArgument type 'char [1]'
// CHECK-DUMP: ClassTemplateSpecializationDecl [[CHAR1]] {{.*}} SomeTemplate definition
// CHECK-DUMP-NEXT: TemplateArgument type 'char [1]'