r294693 - [c++1z] P0512R0: support for 'explicit' specifier on deduction-guides.
Richard Smith via cfe-commits
cfe-commits at lists.llvm.org
Thu Feb 9 18:19:06 PST 2017
Author: rsmith
Date: Thu Feb 9 20:19:05 2017
New Revision: 294693
URL: http://llvm.org/viewvc/llvm-project?rev=294693&view=rev
Log:
[c++1z] P0512R0: support for 'explicit' specifier on deduction-guides.
Added:
cfe/trunk/test/CXX/over/over.match/over.match.funcs/over.match.class.deduct/p2.cpp
Modified:
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
cfe/trunk/lib/Sema/SemaDecl.cpp
cfe/trunk/lib/Sema/SemaDeclCXX.cpp
cfe/trunk/lib/Sema/SemaInit.cpp
cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
cfe/trunk/test/CXX/over/over.match/over.match.funcs/over.match.class.deduct/p3.cpp
cfe/trunk/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=294693&r1=294692&r2=294693&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Thu Feb 9 20:19:05 2017
@@ -1991,6 +1991,9 @@ def err_deduction_guide_name_not_class_t
"template template parameter|dependent template name}0 %1">;
def err_deduction_guide_defines_function : Error<
"deduction guide cannot have a function definition">;
+def err_deduction_guide_explicit_mismatch : Error<
+ "deduction guide is %select{not |}0declared 'explicit' but "
+ "previous declaration was%select{ not|}0">;
def err_deduction_guide_specialized : Error<"deduction guide cannot be "
"%select{explicitly instantiated|explicitly specialized}0">;
Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=294693&r1=294692&r2=294693&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Thu Feb 9 20:19:05 2017
@@ -7659,11 +7659,12 @@ static FunctionDecl* CreateNewFunctionDe
// We don't need to store much extra information for a deduction guide, so
// just model it as a plain FunctionDecl.
- // FIXME: Store IsExplicit!
- return FunctionDecl::Create(SemaRef.Context, DC,
- D.getLocStart(),
- NameInfo, R, TInfo, SC, isInline,
- true/*HasPrototype*/, isConstexpr);
+ auto *FD = FunctionDecl::Create(SemaRef.Context, DC, D.getLocStart(),
+ NameInfo, R, TInfo, SC, isInline,
+ true /*HasPrototype*/, isConstexpr);
+ if (isExplicit)
+ FD->setExplicitSpecified();
+ return FD;
} else if (DC->isRecord()) {
// If the name of the function is the same as the name of the record,
// then this must be an invalid constructor that has a return type.
Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=294693&r1=294692&r2=294693&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Thu Feb 9 20:19:05 2017
@@ -647,6 +647,16 @@ bool Sema::MergeCXXFunctionDecl(Function
Invalid = true;
}
+ // FIXME: It's not clear what should happen if multiple declarations of a
+ // deduction guide have different explicitness. For now at least we simply
+ // reject any case where the explicitness changes.
+ if (New->isDeductionGuide() &&
+ New->isExplicitSpecified() != Old->isExplicitSpecified()) {
+ Diag(New->getLocation(), diag::err_deduction_guide_explicit_mismatch)
+ << New->isExplicitSpecified();
+ Diag(Old->getLocation(), diag::note_previous_declaration);
+ }
+
// C++11 [dcl.fct.default]p4: If a friend declaration specifies a default
// argument expression, that declaration shall be a definition and shall be
// the only declaration of the function or function template in the
Modified: cfe/trunk/lib/Sema/SemaInit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=294693&r1=294692&r2=294693&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaInit.cpp (original)
+++ cfe/trunk/lib/Sema/SemaInit.cpp Thu Feb 9 20:19:05 2017
@@ -8324,10 +8324,13 @@ QualType Sema::DeduceTemplateSpecializat
// C++ [over.match.copy]p1: (non-list copy-initialization from class)
// The converting constructors of T are candidate functions.
if (Kind.isCopyInit() && !ListInit) {
- // FIXME: if (FD->isExplicit()) continue;
+ // Only consider converting constructors.
+ if (FD->isExplicit())
+ continue;
// When looking for a converting constructor, deduction guides that
- // could never be called with one argument are not interesting.
+ // could never be called with one argument are not interesting to
+ // check or note.
if (FD->getMinRequiredArguments() > 1 ||
(FD->getNumParams() == 0 && !FD->isVariadic()))
continue;
@@ -8353,7 +8356,6 @@ QualType Sema::DeduceTemplateSpecializat
// ever have a parameter of the right type.
bool SuppressUserConversions = Kind.isCopyInit();
- // FIXME: These are definitely wrong in the non-deduction-guide case.
if (TD)
AddTemplateOverloadCandidate(TD, Pair, /*ExplicitArgs*/ nullptr, Inits,
Candidates, SuppressUserConversions);
@@ -8410,8 +8412,7 @@ QualType Sema::DeduceTemplateSpecializat
// C++ [over.match.list]p1:
// In copy-list-initialization, if an explicit constructor is chosen, the
// initialization is ill-formed.
- if (Kind.isCopyInit() && ListInit &&
- false /*FIXME: Best->Function->isExplicit()*/) {
+ if (Kind.isCopyInit() && ListInit && Best->Function->isExplicit()) {
bool IsDeductionGuide = !Best->Function->isImplicit();
Diag(Kind.getLocation(), diag::err_deduced_class_template_explicit)
<< TemplateName << IsDeductionGuide;
Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=294693&r1=294692&r2=294693&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Thu Feb 9 20:19:05 2017
@@ -1610,6 +1610,10 @@ Decl *TemplateDeclInstantiator::VisitFun
if (D->isInlined())
Function->setImplicitlyInline();
+ // A deduction-guide could be explicit.
+ if (D->isExplicitSpecified())
+ Function->setExplicitSpecified();
+
if (QualifierLoc)
Function->setQualifierInfo(QualifierLoc);
Added: 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=294693&view=auto
==============================================================================
--- cfe/trunk/test/CXX/over/over.match/over.match.funcs/over.match.class.deduct/p2.cpp (added)
+++ cfe/trunk/test/CXX/over/over.match/over.match.funcs/over.match.class.deduct/p2.cpp Thu Feb 9 20:19:05 2017
@@ -0,0 +1,25 @@
+// RUN: %clang_cc1 -verify -std=c++1z %s
+
+namespace Explicit {
+ // Each notional constructor is explicit if the function or function template
+ // was generated from a constructor or deduction-guide that was declared explicit.
+ template<typename T> struct A {
+ A(T);
+ A(T*);
+ };
+ template<typename T> A(T) -> A<T>;
+ template<typename T> explicit A(T*) -> A<T>; // expected-note {{explicit}}
+
+ int *p;
+ A a(p);
+ A b = p;
+ A c{p};
+ A d = {p}; // expected-error {{selected an explicit deduction guide}}
+
+ using X = A<int>;
+ using Y = A<int*>;
+
+ using X = decltype(a);
+ using Y = decltype(b);
+ using X = decltype(c);
+}
Modified: cfe/trunk/test/CXX/over/over.match/over.match.funcs/over.match.class.deduct/p3.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/over/over.match/over.match.funcs/over.match.class.deduct/p3.cpp?rev=294693&r1=294692&r2=294693&view=diff
==============================================================================
--- cfe/trunk/test/CXX/over/over.match/over.match.funcs/over.match.class.deduct/p3.cpp (original)
+++ cfe/trunk/test/CXX/over/over.match/over.match.funcs/over.match.class.deduct/p3.cpp Thu Feb 9 20:19:05 2017
@@ -15,9 +15,9 @@ namespace std_example {
A a4 = {0, i}; // expected-error {{no viable constructor or deduction guide}}
template <class T> A(const T &, const T &) -> A<T &>;
- template <class T> explicit A(T &&, T &&) -> A<T>;
+ template <class T> explicit A(T &&, T &&) -> A<T>; // expected-note {{explicit deduction guide declared here}}
- A a5 = {0, 1}; // FIXME: Should be invalid, explicit deduction guide selected in copy-list-init
+ A a5 = {0, 1}; // expected-error {{class template argument deduction for 'A' selected an explicit deduction guide}}
A a6{0, 1};
A a7 = {0, i}; // expected-note {{in instantiation of}}
A a8{0, i}; // expected-error {{no matching constructor}}
Modified: cfe/trunk/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp?rev=294693&r1=294692&r2=294693&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp (original)
+++ cfe/trunk/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp Thu Feb 9 20:19:05 2017
@@ -35,9 +35,14 @@ static_assert(has_type<vector<char>>(v2)
vector v3(5, 5);
static_assert(has_type<vector<int>>(v3));
+vector v4 = {it, end};
+static_assert(has_type<vector<iter>>(v4));
+
+vector v5{it, end};
+static_assert(has_type<vector<iter>>(v5));
template<typename ...T> struct tuple { tuple(T...); };
-template<typename ...T> explicit tuple(T ...t) -> tuple<T...>;
+template<typename ...T> explicit tuple(T ...t) -> tuple<T...>; // expected-note {{declared}}
// FIXME: Remove
template<typename ...T> tuple(tuple<T...>) -> tuple<T...>;
@@ -46,14 +51,14 @@ tuple ta = tuple{1, 'a', "foo", n};
static_assert(has_type<tuple<int, char, const char*, int>>(ta));
tuple tb{ta};
-static_assert(has_type<tuple<int, char, const char*, int>>(ta));
+static_assert(has_type<tuple<int, char, const char*, int>>(tb));
-// FIXME: This should be tuple<tuple<...>>;
+// FIXME: This should be tuple<tuple<...>>; when the above guide is removed.
tuple tc = {ta};
-static_assert(has_type<tuple<int, char, const char*, int>>(ta));
+static_assert(has_type<tuple<int, char, const char*, int>>(tc));
-tuple td = {1, 2, 3};
-static_assert(has_type<tuple<int, char, const char*, int>>(ta));
+tuple td = {1, 2, 3}; // expected-error {{selected an explicit deduction guide}}
+static_assert(has_type<tuple<int, char, const char*, int>>(td));
// FIXME: This is a GCC extension for now; if CWG don't allow this, at least
// add a warning for it.
More information about the cfe-commits
mailing list