forked from OSchip/llvm-project
Fix the breakage by handling indirect instantiations. This would be much
improved if there were a consistent name for getInstantiatedFromMemberX() across all classes. Cheap refactor if someone wants to do it, but let's get the buildbots happy first. llvm-svn: 80425
This commit is contained in:
parent
57b946c94b
commit
5966088621
|
@ -1379,6 +1379,10 @@ class EnumDecl : public TagDecl {
|
||||||
IntegerType = QualType();
|
IntegerType = QualType();
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
|
EnumDecl *getCanonicalDecl() {
|
||||||
|
return cast<EnumDecl>(TagDecl::getCanonicalDecl());
|
||||||
|
}
|
||||||
|
|
||||||
static EnumDecl *Create(ASTContext &C, DeclContext *DC,
|
static EnumDecl *Create(ASTContext &C, DeclContext *DC,
|
||||||
SourceLocation L, IdentifierInfo *Id,
|
SourceLocation L, IdentifierInfo *Id,
|
||||||
SourceLocation TKL, EnumDecl *PrevDecl);
|
SourceLocation TKL, EnumDecl *PrevDecl);
|
||||||
|
|
|
@ -408,6 +408,10 @@ public:
|
||||||
typedef std::reverse_iterator<base_class_const_iterator>
|
typedef std::reverse_iterator<base_class_const_iterator>
|
||||||
reverse_base_class_const_iterator;
|
reverse_base_class_const_iterator;
|
||||||
|
|
||||||
|
virtual CXXRecordDecl *getCanonicalDecl() {
|
||||||
|
return cast<CXXRecordDecl>(RecordDecl::getCanonicalDecl());
|
||||||
|
}
|
||||||
|
|
||||||
static CXXRecordDecl *Create(ASTContext &C, TagKind TK, DeclContext *DC,
|
static CXXRecordDecl *Create(ASTContext &C, TagKind TK, DeclContext *DC,
|
||||||
SourceLocation L, IdentifierInfo *Id,
|
SourceLocation L, IdentifierInfo *Id,
|
||||||
SourceLocation TKL = SourceLocation(),
|
SourceLocation TKL = SourceLocation(),
|
||||||
|
|
|
@ -1166,38 +1166,94 @@ Sema::InstantiateMemInitializers(CXXConstructorDecl *New,
|
||||||
NewInits.data(), NewInits.size());
|
NewInits.data(), NewInits.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: this could be templated if the various decl types used the
|
||||||
|
// same method name.
|
||||||
|
static bool isInstantiationOf(ClassTemplateDecl *Pattern,
|
||||||
|
ClassTemplateDecl *Instance) {
|
||||||
|
Pattern = Pattern->getCanonicalDecl();
|
||||||
|
|
||||||
|
do {
|
||||||
|
Instance = Instance->getCanonicalDecl();
|
||||||
|
if (Pattern == Instance) return true;
|
||||||
|
Instance = Instance->getInstantiatedFromMemberTemplate();
|
||||||
|
} while (Instance);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool isInstantiationOf(CXXRecordDecl *Pattern,
|
||||||
|
CXXRecordDecl *Instance) {
|
||||||
|
Pattern = Pattern->getCanonicalDecl();
|
||||||
|
|
||||||
|
do {
|
||||||
|
Instance = Instance->getCanonicalDecl();
|
||||||
|
if (Pattern == Instance) return true;
|
||||||
|
Instance = Instance->getInstantiatedFromMemberClass();
|
||||||
|
} while (Instance);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool isInstantiationOf(FunctionDecl *Pattern,
|
||||||
|
FunctionDecl *Instance) {
|
||||||
|
Pattern = Pattern->getCanonicalDecl();
|
||||||
|
|
||||||
|
do {
|
||||||
|
Instance = Instance->getCanonicalDecl();
|
||||||
|
if (Pattern == Instance) return true;
|
||||||
|
Instance = Instance->getInstantiatedFromMemberFunction();
|
||||||
|
} while (Instance);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool isInstantiationOf(EnumDecl *Pattern,
|
||||||
|
EnumDecl *Instance) {
|
||||||
|
Pattern = Pattern->getCanonicalDecl();
|
||||||
|
|
||||||
|
do {
|
||||||
|
Instance = Instance->getCanonicalDecl();
|
||||||
|
if (Pattern == Instance) return true;
|
||||||
|
Instance = Instance->getInstantiatedFromMemberEnum();
|
||||||
|
} while (Instance);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool isInstantiationOfStaticDataMember(VarDecl *Pattern,
|
||||||
|
VarDecl *Instance) {
|
||||||
|
assert(Instance->isStaticDataMember());
|
||||||
|
|
||||||
|
Pattern = Pattern->getCanonicalDecl();
|
||||||
|
|
||||||
|
do {
|
||||||
|
Instance = Instance->getCanonicalDecl();
|
||||||
|
if (Pattern == Instance) return true;
|
||||||
|
Instance = Instance->getInstantiatedFromStaticDataMember();
|
||||||
|
} while (Instance);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static bool isInstantiationOf(ASTContext &Ctx, NamedDecl *D, Decl *Other) {
|
static bool isInstantiationOf(ASTContext &Ctx, NamedDecl *D, Decl *Other) {
|
||||||
if (D->getKind() != Other->getKind())
|
if (D->getKind() != Other->getKind())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(Other)) {
|
if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(Other))
|
||||||
if (CXXRecordDecl *Pattern = Record->getInstantiatedFromMemberClass())
|
return isInstantiationOf(cast<CXXRecordDecl>(D), Record);
|
||||||
return Pattern->getCanonicalDecl() == D->getCanonicalDecl();
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (FunctionDecl *Function = dyn_cast<FunctionDecl>(Other)) {
|
if (FunctionDecl *Function = dyn_cast<FunctionDecl>(Other))
|
||||||
if (FunctionDecl *Pattern = Function->getInstantiatedFromMemberFunction())
|
return isInstantiationOf(cast<FunctionDecl>(D), Function);
|
||||||
return Pattern->getCanonicalDecl() == D->getCanonicalDecl();
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (EnumDecl *Enum = dyn_cast<EnumDecl>(Other)) {
|
if (EnumDecl *Enum = dyn_cast<EnumDecl>(Other))
|
||||||
if (EnumDecl *Pattern = Enum->getInstantiatedFromMemberEnum())
|
return isInstantiationOf(cast<EnumDecl>(D), Enum);
|
||||||
return Pattern->getCanonicalDecl() == D->getCanonicalDecl();
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (VarDecl *Var = dyn_cast<VarDecl>(Other))
|
if (VarDecl *Var = dyn_cast<VarDecl>(Other))
|
||||||
if (Var->isStaticDataMember()) {
|
if (Var->isStaticDataMember())
|
||||||
if (VarDecl *Pattern = Var->getInstantiatedFromStaticDataMember())
|
return isInstantiationOfStaticDataMember(cast<VarDecl>(D), Var);
|
||||||
return Pattern->getCanonicalDecl() == D->getCanonicalDecl();
|
|
||||||
else
|
if (ClassTemplateDecl *Temp = dyn_cast<ClassTemplateDecl>(Other))
|
||||||
return false;
|
return isInstantiationOf(cast<ClassTemplateDecl>(D), Temp);
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME: How can we find instantiations of anonymous unions?
|
// FIXME: How can we find instantiations of anonymous unions?
|
||||||
|
|
||||||
|
@ -1262,6 +1318,28 @@ NamedDecl * Sema::FindInstantiatedDecl(NamedDecl *D) {
|
||||||
return cast<NamedDecl>(CurrentInstantiationScope->getInstantiationOf(D));
|
return cast<NamedDecl>(CurrentInstantiationScope->getInstantiationOf(D));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(D))
|
||||||
|
if (ClassTemplateDecl *ClassTemplate
|
||||||
|
= Record->getDescribedClassTemplate()) {
|
||||||
|
// When the declaration D was parsed, it referred to the current
|
||||||
|
// instantiation. Therefore, look through the current context,
|
||||||
|
// which contains actual instantiations, to find the
|
||||||
|
// instantiation of the "current instantiation" that D refers
|
||||||
|
// to. Alternatively, we could just instantiate the
|
||||||
|
// injected-class-name with the current template arguments, but
|
||||||
|
// such an instantiation is far more expensive.
|
||||||
|
for (DeclContext *DC = CurContext; !DC->isFileContext();
|
||||||
|
DC = DC->getParent()) {
|
||||||
|
if (ClassTemplateSpecializationDecl *Spec
|
||||||
|
= dyn_cast<ClassTemplateSpecializationDecl>(DC))
|
||||||
|
if (isInstantiationOf(ClassTemplate, Spec->getSpecializedTemplate()))
|
||||||
|
return Spec;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(false &&
|
||||||
|
"Unable to find declaration for the current instantiation");
|
||||||
|
}
|
||||||
|
|
||||||
ParentDC = FindInstantiatedContext(ParentDC);
|
ParentDC = FindInstantiatedContext(ParentDC);
|
||||||
if (!ParentDC) return 0;
|
if (!ParentDC) return 0;
|
||||||
|
|
||||||
|
@ -1286,33 +1364,11 @@ NamedDecl * Sema::FindInstantiatedDecl(NamedDecl *D) {
|
||||||
ParentDC->decls_begin(),
|
ParentDC->decls_begin(),
|
||||||
ParentDC->decls_end());
|
ParentDC->decls_end());
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(Result && "Unable to find instantiation of declaration!");
|
assert(Result && "Unable to find instantiation of declaration!");
|
||||||
D = Result;
|
D = Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(D))
|
|
||||||
if (ClassTemplateDecl *ClassTemplate
|
|
||||||
= Record->getDescribedClassTemplate()) {
|
|
||||||
// When the declaration D was parsed, it referred to the current
|
|
||||||
// instantiation. Therefore, look through the current context,
|
|
||||||
// which contains actual instantiations, to find the
|
|
||||||
// instantiation of the "current instantiation" that D refers
|
|
||||||
// to. Alternatively, we could just instantiate the
|
|
||||||
// injected-class-name with the current template arguments, but
|
|
||||||
// such an instantiation is far more expensive.
|
|
||||||
for (DeclContext *DC = CurContext; !DC->isFileContext();
|
|
||||||
DC = DC->getParent()) {
|
|
||||||
if (ClassTemplateSpecializationDecl *Spec
|
|
||||||
= dyn_cast<ClassTemplateSpecializationDecl>(DC))
|
|
||||||
if (Spec->getSpecializedTemplate()->getCanonicalDecl()
|
|
||||||
== ClassTemplate->getCanonicalDecl())
|
|
||||||
return Spec;
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(false &&
|
|
||||||
"Unable to find declaration for the current instantiation");
|
|
||||||
}
|
|
||||||
|
|
||||||
return D;
|
return D;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue