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. _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits