summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2017-09-07 07:22:36 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2017-09-07 07:22:36 +0000
commit1363e8f6eddf0e050b2f4a0dc87b44eb4ee201dd (patch)
tree54c2692c838da62db3d38efcf7c1efe1e8c436ae /clang/lib/Sema
parent7bc65e220c31066575e88a36f08463e1ccdfbd52 (diff)
downloadbcm5719-llvm-1363e8f6eddf0e050b2f4a0dc87b44eb4ee201dd.tar.gz
bcm5719-llvm-1363e8f6eddf0e050b2f4a0dc87b44eb4ee201dd.zip
P0702R1: in class template argument deduction from a list of one element, if
that element's type is (or is derived from) a specialization of the deduced template, skip the std::initializer_list special case. llvm-svn: 312703
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r--clang/lib/Sema/SemaInit.cpp21
-rw-r--r--clang/lib/Sema/SemaTemplateDeduction.cpp11
2 files changed, 32 insertions, 0 deletions
diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index 32024cb335d..8aa60bcef07 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -8339,6 +8339,16 @@ Sema::PerformCopyInitialization(const InitializedEntity &Entity,
return Result;
}
+/// Determine whether RD is, or is derived from, a specialization of CTD.
+static bool isOrIsDerivedFromSpecializationOf(CXXRecordDecl *RD,
+ ClassTemplateDecl *CTD) {
+ auto NotSpecialization = [&] (const CXXRecordDecl *Candidate) {
+ auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(Candidate);
+ return !CTSD || !declaresSameEntity(CTSD->getSpecializedTemplate(), CTD);
+ };
+ return !(NotSpecialization(RD) && RD->forallBases(NotSpecialization));
+}
+
QualType Sema::DeduceTemplateSpecializationFromInitializer(
TypeSourceInfo *TSInfo, const InitializedEntity &Entity,
const InitializationKind &Kind, MultiExprArg Inits) {
@@ -8483,6 +8493,17 @@ QualType Sema::DeduceTemplateSpecializationFromInitializer(
break;
}
}
+ } else if (ListInit->getNumInits() == 1) {
+ // C++ [over.match.class.deduct]:
+ // As an exception, the first phase in [over.match.list] (considering
+ // initializer-list constructors) is omitted if the initializer list
+ // consists of a single expression of type cv U, where U is a
+ // specialization of C or a class derived from a specialization of C.
+ Expr *E = ListInit->getInit(0);
+ auto *RD = E->getType()->getAsCXXRecordDecl();
+ if (!isa<InitListExpr>(E) && RD &&
+ isOrIsDerivedFromSpecializationOf(RD, Template))
+ TryListConstructors = false;
}
if (TryListConstructors)
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp
index 5ed802d004f..0dcf52aec59 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -2695,6 +2695,17 @@ static bool isSimpleTemplateIdType(QualType T) {
= T->getAs<TemplateSpecializationType>())
return Spec->getTemplateName().getAsTemplateDecl() != nullptr;
+ // C++17 [temp.local]p2:
+ // the injected-class-name [...] is equivalent to the template-name followed
+ // by the template-arguments of the class template specialization or partial
+ // specialization enclosed in <>
+ // ... which means it's equivalent to a simple-template-id.
+ //
+ // This only arises during class template argument deduction for a copy
+ // deduction candidate, where it permits slicing.
+ if (T->getAs<InjectedClassNameType>())
+ return true;
+
return false;
}
OpenPOWER on IntegriCloud