Author: rsmith Date: Thu Sep 7 00:22:36 2017 New Revision: 312703 URL: http://llvm.org/viewvc/llvm-project?rev=312703&view=rev Log: 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.
Modified: cfe/trunk/lib/Sema/SemaInit.cpp cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp cfe/trunk/test/CXX/over/over.match/over.match.funcs/over.match.class.deduct/p2.cpp cfe/trunk/www/cxx_status.html Modified: cfe/trunk/lib/Sema/SemaInit.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=312703&r1=312702&r2=312703&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaInit.cpp (original) +++ cfe/trunk/lib/Sema/SemaInit.cpp Thu Sep 7 00:22:36 2017 @@ -8339,6 +8339,16 @@ Sema::PerformCopyInitialization(const In 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::DeduceTemplateSpecializat 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) Modified: cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp?rev=312703&r1=312702&r2=312703&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp (original) +++ cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp Thu Sep 7 00:22:36 2017 @@ -2695,6 +2695,17 @@ static bool isSimpleTemplateIdType(QualT = 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; } Modified: cfe/trunk/test/CXX/over/over.match/over.match.funcs/over.match.class.deduct/p2.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/over/over.match/over.match.funcs/over.match.class.deduct/p2.cpp?rev=312703&r1=312702&r2=312703&view=diff ============================================================================== --- cfe/trunk/test/CXX/over/over.match/over.match.funcs/over.match.class.deduct/p2.cpp (original) +++ cfe/trunk/test/CXX/over/over.match/over.match.funcs/over.match.class.deduct/p2.cpp Thu Sep 7 00:22:36 2017 @@ -23,3 +23,34 @@ namespace Explicit { using Y = decltype(b); using X = decltype(c); } + +namespace std { + template<typename T> struct initializer_list { + const T *ptr; + __SIZE_TYPE__ size; + initializer_list(); + }; +} + +namespace p0702r1 { + template<typename T> struct X { // expected-note {{candidate}} + X(std::initializer_list<T>); // expected-note {{candidate}} + }; + + X xi = {0}; + X xxi = {xi}; + extern X<int> xi; + // Prior to P0702R1, this is X<X<int>>. + extern X<int> xxi; + + struct Y : X<int> {}; + Y y {{0}}; + X xy {y}; + extern X<int> xy; + + struct Z : X<int>, X<float> {}; + Z z = {{0}, {0.0f}}; + // This is not X<Z> even though that would work. Instead, it's ambiguous + // between X<int> and X<float>. + X xz = {z}; // expected-error {{no viable constructor or deduction guide}} +} Modified: cfe/trunk/www/cxx_status.html URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/www/cxx_status.html?rev=312703&r1=312702&r2=312703&view=diff ============================================================================== --- cfe/trunk/www/cxx_status.html (original) +++ cfe/trunk/www/cxx_status.html Thu Sep 7 00:22:36 2017 @@ -828,7 +828,7 @@ as the draft C++2a standard evolves. <tr> <td>Initializer list constructors in class template argument deduction</td> <td><a href="http://wg21.link/p0702r1">P0702R1</a></td> - <td class="none" align="center">No</td> + <td class="svn" align="center">SVN <a href="#p0702">(13)</a></td> </tr> <tr id="p0374"> <td>Concepts</td> @@ -838,6 +838,12 @@ as the draft C++2a standard evolves. </table> </details> +<p> +<span id="p0702">(13): This is the resolution to a Defect Report, so is applied +to all language versions supporting class template argument deduction. +</span> +</p> + <h2 id="ts">Technical specifications and standing documents</h2> <p>ISO C++ also publishes a number of documents describing additional language _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits