]> granicus.if.org Git - clang/commitdiff
Disallow explicit instantiation and explicit specialization for deduction guides.
authorRichard Smith <richard-llvm@metafoo.co.uk>
Thu, 9 Feb 2017 22:47:51 +0000 (22:47 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Thu, 9 Feb 2017 22:47:51 +0000 (22:47 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@294641 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaDecl.cpp
lib/Sema/SemaTemplate.cpp
test/CXX/temp/temp.deduct.guide/p1.cpp
www/cxx_status.html

index 8a36e704c0935cb673b35a00dcb2f19b8c02d595..a27c055a4865a72de6f65d982809aa39b9a14aba 100644 (file)
@@ -1991,6 +1991,8 @@ def err_deduction_guide_name_not_class_template : Error<
   "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_specialized : Error<"deduction guide cannot be "
+  "%select{explicitly instantiated|explicitly specialized}0">;
 
 // C++1y deduced return types
 def err_auto_fn_deduction_failure : Error<
index aa6200c1791d82e4fe1600d0bed9b84cd6f52177..7749bef4e774315e9fd8a98627621fdb0f495fd8 100644 (file)
@@ -7657,8 +7657,9 @@ static FunctionDecl* CreateNewFunctionDecl(Sema &SemaRef, Declarator &D,
   } else if (Name.getNameKind() == DeclarationName::CXXDeductionGuideName) {
     SemaRef.CheckDeductionGuideDeclarator(D, R, SC);
 
-    // We don't need to store any extra information for a deduction guide, so
+    // 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,
@@ -9149,6 +9150,13 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
     } else if (CXXConversionDecl *Conversion
                = dyn_cast<CXXConversionDecl>(NewFD)) {
       ActOnConversionDeclarator(Conversion);
+    } else if (NewFD->isDeductionGuide() &&
+               NewFD->getTemplateSpecializationKind() ==
+                   TSK_ExplicitSpecialization) {
+      // A deduction guide is not on the list of entities that can be
+      // explicitly specialized.
+      Diag(NewFD->getLocStart(), diag::err_deduction_guide_specialized)
+        << /*explicit specialization*/ 1;
     }
 
     // Find any virtual functions that this function overrides.
index 6b11d184c9f124f345f02a3141d902779637ad3e..d0ed17cc494c3f204021b1e3510728bb69e13a25 100644 (file)
@@ -8187,6 +8187,14 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
     return true;
   }
 
+  // A deduction guide is not on the list of entities that can be explicitly
+  // instantiated.
+  if (Name.getNameKind() == DeclarationName::CXXDeductionGuideName) {
+    Diag(D.getDeclSpec().getLocStart(), diag::err_deduction_guide_specialized)
+      << /*explicit instantiation*/ 0;
+    return true;
+  }
+
   // C++0x [temp.explicit]p2:
   //   There are two forms of explicit instantiation: an explicit instantiation
   //   definition and an explicit instantiation declaration. An explicit
index 8dd0720669ae9639fc41ae9daa6a0db2b9548076..c0a2ba1129e20d390ef8d8d293fea5b22c28d1e4 100644 (file)
@@ -86,3 +86,23 @@ A(int(&)[43]) -> A<int> try {} catch (...) {} // expected-error {{deduction guid
 #ifdef CLASS
 };
 #endif
+
+namespace ExplicitInst {
+  // Explicit instantiation / specialization is not permitted.
+  template<typename T> struct B {};
+  template<typename T> B(T) -> B<T>;
+  template<> B(int) -> B<int>; // expected-error {{deduction guide cannot be explicitly specialized}}
+  extern template B(float) -> B<float>; // expected-error {{deduction guide cannot be explicitly instantiated}}
+  template B(char) -> B<char>; // expected-error {{deduction guide cannot be explicitly instantiated}}
+
+  // An attempt at partial specialization doesn't even parse as a deduction-guide.
+  template<typename T> B<T*>(T*) -> B<T*>; // expected-error 1+{{}} expected-note 0+{{}}
+
+  struct X {
+    template<typename T> struct C {};
+    template<typename T> C(T) -> C<T>;
+    template<> C(int) -> C<int>; // expected-error {{explicit specialization of '<deduction guide for C>' in class scope}}
+    extern template C(float) -> C<float>; // expected-error {{expected member name or ';'}}
+    template C(char) -> C<char>; // expected-error {{expected '<' after 'template'}}
+  };
+}
index eb0beeb18552c66343ee21efefba895343243378..6adf7fda8aeecddbac48ba0e4de00746665c0faf 100644 (file)
@@ -682,10 +682,14 @@ as the draft C++1z standard evolves.
       <td class="svn" align="center">Clang 4</td>
     </tr>
     <tr>
-      <td>Template argument deduction for class templates</td>
+      <td rowspan="2">Template argument deduction for class templates</td>
       <td><a href="http://wg21.link/p0091r3">P0091R3</a></td>
-      <td class="none" align="center">No</td>
+      <td class="partial" align="center">Partial</td>
     </tr>
+      <tr> <!-- from Issaquah -->
+        <td><a href="http://wg21.link/p0512r0">P0512R0</a></td>
+        <td class="partial" align="center">Partial</td>
+      </tr>
     <tr>
       <td>Non-type template parameters with <tt>auto</tt> type</td>
       <td><a href="http://wg21.link/p0127r2">P0127R2</a></td>