summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2017-06-07 02:42:27 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2017-06-07 02:42:27 +0000
commite6d4b773dea2b1944e544511d957b17b78fa05a9 (patch)
tree9633f887aa7c552ae55100ae309144059c1ea67e /clang/lib
parentd57c58d75d22a9c7b5922f5d4f7e57d153d67c6a (diff)
downloadbcm5719-llvm-e6d4b773dea2b1944e544511d957b17b78fa05a9.tar.gz
bcm5719-llvm-e6d4b773dea2b1944e544511d957b17b78fa05a9.zip
Fix a couple of class template argument deduction crashes with libc++'s tuple.
RecursiveASTVisitor was not properly recursing through a SubstTemplateTypeParmTypes, resulting in crashes in pack expansion where we couldn't always find an unexpanded pack within a pack expansion. We also have an issue where substitution of deduced template arguments for an implicit deduction guide creates the "impossible" case of naming a non-dependent member of the current instantiation, but within a specialization that is actually instantiated from a different (partial/explicit) specialization of the template. We resolve this by declaring that constructors that do so can only be used to deduce specializations of the primary template. I'm running this past CWG to see if people agree this is the right thing to do. llvm-svn: 304862
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/Sema/SemaTemplateInstantiate.cpp19
-rw-r--r--clang/lib/Sema/SemaTemplateInstantiateDecl.cpp16
2 files changed, 34 insertions, 1 deletions
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index a654ca800b0..2279c9ca550 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -2350,6 +2350,25 @@ namespace {
};
}
+bool Sema::usesPartialOrExplicitSpecialization(
+ SourceLocation Loc, ClassTemplateSpecializationDecl *ClassTemplateSpec) {
+ if (ClassTemplateSpec->getTemplateSpecializationKind() ==
+ TSK_ExplicitSpecialization)
+ return true;
+
+ SmallVector<ClassTemplatePartialSpecializationDecl *, 4> PartialSpecs;
+ ClassTemplateSpec->getSpecializedTemplate()
+ ->getPartialSpecializations(PartialSpecs);
+ for (unsigned I = 0, N = PartialSpecs.size(); I != N; ++I) {
+ TemplateDeductionInfo Info(Loc);
+ if (!DeduceTemplateArguments(PartialSpecs[I],
+ ClassTemplateSpec->getTemplateArgs(), Info))
+ return true;
+ }
+
+ return false;
+}
+
/// Get the instantiation pattern to use to instantiate the definition of a
/// given ClassTemplateSpecializationDecl (either the pattern of the primary
/// template or of a partial specialization).
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index e7523ce2836..9e8b4d55d63 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -5000,7 +5000,21 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D,
QualType T = CheckTemplateIdType(TemplateName(TD), Loc, Args);
if (T.isNull())
return nullptr;
- DC = T->getAsCXXRecordDecl();
+ auto *SubstRecord = T->getAsCXXRecordDecl();
+ assert(SubstRecord && "class template id not a class type?");
+ // Check that this template-id names the primary template and not a
+ // partial or explicit specialization. (In the latter cases, it's
+ // meaningless to attempt to find an instantiation of D within the
+ // specialization.)
+ // FIXME: The standard doesn't say what should happen here.
+ if (usesPartialOrExplicitSpecialization(Loc,
+ cast<ClassTemplateSpecializationDecl>(SubstRecord))) {
+ Diag(Loc, diag::err_specialization_not_primary_template)
+ << T << (SubstRecord->getTemplateSpecializationKind() ==
+ TSK_ExplicitSpecialization);
+ return nullptr;
+ }
+ DC = SubstRecord;
continue;
}
}
OpenPOWER on IntegriCloud