summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChandler Carruth <chandlerc@gmail.com>2017-04-19 05:25:13 +0000
committerChandler Carruth <chandlerc@gmail.com>2017-04-19 05:25:13 +0000
commitbd186c0787844f4d9111e5a918c457ad9e830e8c (patch)
treee905edadea2e5376a0d8537d72f8f62762319ef4
parent73daaa8fb25385d4b664a3e174985b08b4b3db59 (diff)
downloadbcm5719-llvm-bd186c0787844f4d9111e5a918c457ad9e830e8c.tar.gz
bcm5719-llvm-bd186c0787844f4d9111e5a918c457ad9e830e8c.zip
Revert r300653 and r300650. The underlying commit fixes one issue with
modules but exposes much more widespread issues. Example and more information is on the review thread for r300650. Original commit summary: [modules] Properly look up the owning module for an instantiation of a merged template. llvm-svn: 300659
-rw-r--r--clang/lib/AST/Decl.cpp55
-rw-r--r--clang/lib/AST/DeclCXX.cpp13
-rw-r--r--clang/lib/Sema/SemaLookup.cpp22
-rw-r--r--clang/test/Modules/Inputs/template-default-args/a.h8
-rw-r--r--clang/test/Modules/template-default-args.cpp15
5 files changed, 46 insertions, 67 deletions
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index 5fe07065212..2b22e5bb50a 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -2251,14 +2251,6 @@ bool VarDecl::checkInitIsICE() const {
return Eval->IsICE;
}
-template<typename DeclT>
-static DeclT *getDefinitionOrSelf(DeclT *D) {
- assert(D);
- if (auto *Def = D->getDefinition())
- return Def;
- return D;
-}
-
VarDecl *VarDecl::getTemplateInstantiationPattern() const {
// If it's a variable template specialization, find the template or partial
// specialization from which it was instantiated.
@@ -2270,7 +2262,7 @@ VarDecl *VarDecl::getTemplateInstantiationPattern() const {
break;
VTD = NewVTD;
}
- return getDefinitionOrSelf(VTD->getTemplatedDecl());
+ return VTD->getTemplatedDecl()->getDefinition();
}
if (auto *VTPSD =
From.dyn_cast<VarTemplatePartialSpecializationDecl *>()) {
@@ -2279,7 +2271,7 @@ VarDecl *VarDecl::getTemplateInstantiationPattern() const {
break;
VTPSD = NewVTPSD;
}
- return getDefinitionOrSelf<VarDecl>(VTPSD);
+ return VTPSD->getDefinition();
}
}
@@ -2288,18 +2280,23 @@ VarDecl *VarDecl::getTemplateInstantiationPattern() const {
VarDecl *VD = getInstantiatedFromStaticDataMember();
while (auto *NewVD = VD->getInstantiatedFromStaticDataMember())
VD = NewVD;
- return getDefinitionOrSelf(VD);
+ return VD->getDefinition();
}
}
if (VarTemplateDecl *VarTemplate = getDescribedVarTemplate()) {
+
while (VarTemplate->getInstantiatedFromMemberTemplate()) {
if (VarTemplate->isMemberSpecialization())
break;
VarTemplate = VarTemplate->getInstantiatedFromMemberTemplate();
}
- return getDefinitionOrSelf(VarTemplate->getTemplatedDecl());
+ assert((!VarTemplate->getTemplatedDecl() ||
+ !isTemplateInstantiation(getTemplateSpecializationKind())) &&
+ "couldn't find pattern for variable instantiation");
+
+ return VarTemplate->getTemplatedDecl();
}
return nullptr;
}
@@ -3203,12 +3200,9 @@ bool FunctionDecl::isTemplateInstantiation() const {
FunctionDecl *FunctionDecl::getTemplateInstantiationPattern() const {
// Handle class scope explicit specialization special case.
- if (getTemplateSpecializationKind() == TSK_ExplicitSpecialization) {
- if (auto *Spec = getClassScopeSpecializationPattern())
- return getDefinitionOrSelf(Spec);
- return nullptr;
- }
-
+ if (getTemplateSpecializationKind() == TSK_ExplicitSpecialization)
+ return getClassScopeSpecializationPattern();
+
// If this is a generic lambda call operator specialization, its
// instantiation pattern is always its primary template's pattern
// even if its primary template was instantiated from another
@@ -3220,10 +3214,16 @@ FunctionDecl *FunctionDecl::getTemplateInstantiationPattern() const {
if (isGenericLambdaCallOperatorSpecialization(
dyn_cast<CXXMethodDecl>(this))) {
- assert(getPrimaryTemplate() && "not a generic lambda call operator?");
- return getDefinitionOrSelf(getPrimaryTemplate()->getTemplatedDecl());
+ assert(getPrimaryTemplate() && "A generic lambda specialization must be "
+ "generated from a primary call operator "
+ "template");
+ assert(getPrimaryTemplate()->getTemplatedDecl()->getBody() &&
+ "A generic lambda call operator template must always have a body - "
+ "even if instantiated from a prototype (i.e. as written) member "
+ "template");
+ return getPrimaryTemplate()->getTemplatedDecl();
}
-
+
if (FunctionTemplateDecl *Primary = getPrimaryTemplate()) {
while (Primary->getInstantiatedFromMemberTemplate()) {
// If we have hit a point where the user provided a specialization of
@@ -3232,14 +3232,11 @@ FunctionDecl *FunctionDecl::getTemplateInstantiationPattern() const {
break;
Primary = Primary->getInstantiatedFromMemberTemplate();
}
-
- return getDefinitionOrSelf(Primary->getTemplatedDecl());
+
+ return Primary->getTemplatedDecl();
}
-
- if (auto *MFD = getInstantiatedFromMemberFunction())
- return getDefinitionOrSelf(MFD);
-
- return nullptr;
+
+ return getInstantiatedFromMemberFunction();
}
FunctionTemplateDecl *FunctionDecl::getPrimaryTemplate() const {
@@ -3783,7 +3780,7 @@ EnumDecl *EnumDecl::getTemplateInstantiationPattern() const {
EnumDecl *ED = getInstantiatedFromMemberEnum();
while (auto *NewED = ED->getInstantiatedFromMemberEnum())
ED = NewED;
- return getDefinitionOrSelf(ED);
+ return ED;
}
}
diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp
index dd8f768c571..2e5cec9c108 100644
--- a/clang/lib/AST/DeclCXX.cpp
+++ b/clang/lib/AST/DeclCXX.cpp
@@ -1364,13 +1364,6 @@ CXXRecordDecl::setTemplateSpecializationKind(TemplateSpecializationKind TSK) {
}
const CXXRecordDecl *CXXRecordDecl::getTemplateInstantiationPattern() const {
- auto GetDefinitionOrSelf =
- [](const CXXRecordDecl *D) -> const CXXRecordDecl * {
- if (auto *Def = D->getDefinition())
- return Def;
- return D;
- };
-
// If it's a class template specialization, find the template or partial
// specialization from which it was instantiated.
if (auto *TD = dyn_cast<ClassTemplateSpecializationDecl>(this)) {
@@ -1381,7 +1374,7 @@ const CXXRecordDecl *CXXRecordDecl::getTemplateInstantiationPattern() const {
break;
CTD = NewCTD;
}
- return GetDefinitionOrSelf(CTD->getTemplatedDecl());
+ return CTD->getTemplatedDecl()->getDefinition();
}
if (auto *CTPSD =
From.dyn_cast<ClassTemplatePartialSpecializationDecl *>()) {
@@ -1390,7 +1383,7 @@ const CXXRecordDecl *CXXRecordDecl::getTemplateInstantiationPattern() const {
break;
CTPSD = NewCTPSD;
}
- return GetDefinitionOrSelf(CTPSD);
+ return CTPSD->getDefinition();
}
}
@@ -1399,7 +1392,7 @@ const CXXRecordDecl *CXXRecordDecl::getTemplateInstantiationPattern() const {
const CXXRecordDecl *RD = this;
while (auto *NewRD = RD->getInstantiatedFromMemberClass())
RD = NewRD;
- return GetDefinitionOrSelf(RD);
+ return RD->getDefinition();
}
}
diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp
index 0ac3eebcf29..e4d420f3683 100644
--- a/clang/lib/Sema/SemaLookup.cpp
+++ b/clang/lib/Sema/SemaLookup.cpp
@@ -1326,6 +1326,12 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) {
return !R.empty();
}
+/// \brief Find the declaration that a class temploid member specialization was
+/// instantiated from, or the member itself if it is an explicit specialization.
+static Decl *getInstantiatedFrom(Decl *D, MemberSpecializationInfo *MSInfo) {
+ return MSInfo->isExplicitSpecialization() ? D : MSInfo->getInstantiatedFrom();
+}
+
Module *Sema::getOwningModule(Decl *Entity) {
// If it's imported, grab its owning module.
Module *M = Entity->getImportedOwningModule();
@@ -1407,14 +1413,20 @@ static Module *getDefiningModule(Sema &S, Decl *Entity) {
if (CXXRecordDecl *Pattern = RD->getTemplateInstantiationPattern())
Entity = Pattern;
} else if (EnumDecl *ED = dyn_cast<EnumDecl>(Entity)) {
- if (auto *Pattern = ED->getTemplateInstantiationPattern())
- Entity = Pattern;
+ if (MemberSpecializationInfo *MSInfo = ED->getMemberSpecializationInfo())
+ Entity = getInstantiatedFrom(ED, MSInfo);
} else if (VarDecl *VD = dyn_cast<VarDecl>(Entity)) {
- if (VarDecl *Pattern = VD->getTemplateInstantiationPattern())
- Entity = Pattern;
+ // FIXME: Map from variable template specializations back to the template.
+ if (MemberSpecializationInfo *MSInfo = VD->getMemberSpecializationInfo())
+ Entity = getInstantiatedFrom(VD, MSInfo);
}
- return S.getOwningModule(Entity);
+ // Walk up to the containing context. That might also have been instantiated
+ // from a template.
+ DeclContext *Context = Entity->getDeclContext();
+ if (Context->isFileContext())
+ return S.getOwningModule(Entity);
+ return getDefiningModule(S, cast<Decl>(Context));
}
llvm::DenseSet<Module*> &Sema::getLookupModules() {
diff --git a/clang/test/Modules/Inputs/template-default-args/a.h b/clang/test/Modules/Inputs/template-default-args/a.h
index 0f4a39a1892..532cbc8be03 100644
--- a/clang/test/Modules/Inputs/template-default-args/a.h
+++ b/clang/test/Modules/Inputs/template-default-args/a.h
@@ -14,11 +14,3 @@ struct FriendL {
template<typename T> friend struct L;
};
END
-
-namespace DeferredLookup {
- template<typename T, typename U = T> using X = U;
- template<typename T> void f() { (void) X<T>(); }
- template<typename T> int n = X<T>();
- template<typename T> struct S { X<T> xt; enum E : int; };
- template<typename T> enum S<T>::E : int { a = X<T>() };
-}
diff --git a/clang/test/Modules/template-default-args.cpp b/clang/test/Modules/template-default-args.cpp
index 1d31592fd1f..9d16cbf4342 100644
--- a/clang/test/Modules/template-default-args.cpp
+++ b/clang/test/Modules/template-default-args.cpp
@@ -44,18 +44,3 @@ H<> h; // expected-error {{default argument of 'H' must be imported from module
I<> i;
L<> *l;
END
-
-namespace DeferredLookup {
- template<typename T, typename U = T> using X = U;
- template<typename T> void f() { (void) X<T>(); }
- template<typename T> int n = X<T>(); // expected-warning {{extension}}
- template<typename T> struct S { X<T> xt; enum E : int; };
- template<typename T> enum S<T>::E : int { a = X<T>() };
-
- void test() {
- f<int>();
- n<int> = 1;
- S<int> s;
- S<int>::E e = S<int>::E::a;
- }
-}
OpenPOWER on IntegriCloud