r312703 - P0702R1: in class template argument deduction from a list of one element, if
Richard Smith via cfe-commits
cfe-commits at lists.llvm.org
Thu Sep 7 00:22:36 PDT 2017
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
More information about the cfe-commits
mailing list