From 8d34d18307ef5731f0fe27f7bcd30060efa80822 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Thu, 7 Sep 2017 07:22:36 +0000 Subject: [PATCH] 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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@312703 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaInit.cpp | 21 +++++++++++++ lib/Sema/SemaTemplateDeduction.cpp | 11 +++++++ .../over.match.class.deduct/p2.cpp | 31 +++++++++++++++++++ www/cxx_status.html | 8 ++++- 4 files changed, 70 insertions(+), 1 deletion(-) diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index 32024cb335..8aa60bcef0 100644 --- a/lib/Sema/SemaInit.cpp +++ b/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(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(E) && RD && + isOrIsDerivedFromSpecializationOf(RD, Template)) + TryListConstructors = false; } if (TryListConstructors) diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp index 5ed802d004..0dcf52aec5 100644 --- a/lib/Sema/SemaTemplateDeduction.cpp +++ b/lib/Sema/SemaTemplateDeduction.cpp @@ -2695,6 +2695,17 @@ static bool isSimpleTemplateIdType(QualType T) { = T->getAs()) 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()) + return true; + return false; } diff --git a/test/CXX/over/over.match/over.match.funcs/over.match.class.deduct/p2.cpp b/test/CXX/over/over.match/over.match.funcs/over.match.class.deduct/p2.cpp index fe1b6a63d7..cf925455ac 100644 --- a/test/CXX/over/over.match/over.match.funcs/over.match.class.deduct/p2.cpp +++ b/test/CXX/over/over.match/over.match.funcs/over.match.class.deduct/p2.cpp @@ -23,3 +23,34 @@ namespace Explicit { using Y = decltype(b); using X = decltype(c); } + +namespace std { + template struct initializer_list { + const T *ptr; + __SIZE_TYPE__ size; + initializer_list(); + }; +} + +namespace p0702r1 { + template struct X { // expected-note {{candidate}} + X(std::initializer_list); // expected-note {{candidate}} + }; + + X xi = {0}; + X xxi = {xi}; + extern X xi; + // Prior to P0702R1, this is X>. + extern X xxi; + + struct Y : X {}; + Y y {{0}}; + X xy {y}; + extern X xy; + + struct Z : X, X {}; + Z z = {{0}, {0.0f}}; + // This is not X even though that would work. Instead, it's ambiguous + // between X and X. + X xz = {z}; // expected-error {{no viable constructor or deduction guide}} +} diff --git a/www/cxx_status.html b/www/cxx_status.html index d90d08f0c2..0a904765cf 100644 --- a/www/cxx_status.html +++ b/www/cxx_status.html @@ -828,7 +828,7 @@ as the draft C++2a standard evolves. Initializer list constructors in class template argument deduction P0702R1 - No + SVN (13) Concepts @@ -838,6 +838,12 @@ as the draft C++2a standard evolves. +

+(13): This is the resolution to a Defect Report, so is applied +to all language versions supporting class template argument deduction. + +

+

Technical specifications and standing documents

ISO C++ also publishes a number of documents describing additional language -- 2.40.0