"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">;
// 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.
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
// 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;
// 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);
// 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;
if (D->isInlined())
Function->setImplicitlyInline();
+ // A deduction-guide could be explicit.
+ if (D->isExplicitSpecified())
+ Function->setExplicitSpecified();
+
if (QualifierLoc)
Function->setQualifierInfo(QualifierLoc);
--- /dev/null
+// 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);
+}
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}}
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...>;
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.