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