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/SemaInit.cpp | |
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/SemaInit.cpp')
-rw-r--r-- | clang/lib/Sema/SemaInit.cpp | 21 |
1 files changed, 21 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) |