diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2017-09-07 07:22:36 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2017-09-07 07:22:36 +0000 |
commit | 1363e8f6eddf0e050b2f4a0dc87b44eb4ee201dd (patch) | |
tree | 54c2692c838da62db3d38efcf7c1efe1e8c436ae /clang/lib/Sema | |
parent | 7bc65e220c31066575e88a36f08463e1ccdfbd52 (diff) | |
download | bcm5719-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.cpp | 21 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplateDeduction.cpp | 11 |
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; } |