]> granicus.if.org Git - clang/commitdiff
Fix a constexpr FIXME: When implicitly instantiating the primary template for an
authorRichard Smith <richard-llvm@metafoo.co.uk>
Mon, 20 Feb 2012 23:28:05 +0000 (23:28 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Mon, 20 Feb 2012 23:28:05 +0000 (23:28 +0000)
explicit specialization of a function template, mark the instantiation as
constexpr if the specialization is, rather than requiring them to match.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@151001 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaDeclCXX.cpp
lib/Sema/SemaTemplate.cpp
test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp

index 48dc911b6a30214c7064e4e8bc13939c3ed4fc8d..faf2c41853b9ebbaf8553792ad33bb134c12f8d7 100644 (file)
@@ -516,13 +516,9 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old) {
     }
   }
 
-  // C++0x [dcl.constexpr]p1: If any declaration of a function or function
+  // C++11 [dcl.constexpr]p1: If any declaration of a function or function
   // template has a constexpr specifier then all its declarations shall
-  // contain the constexpr specifier. [Note: An explicit specialization can
-  // differ from the template declaration with respect to the constexpr
-  // specifier. -- end note]
-  //
-  // FIXME: Don't reject changes in constexpr in explicit specializations.
+  // contain the constexpr specifier.
   if (New->isConstexpr() != Old->isConstexpr()) {
     Diag(New->getLocation(), diag::err_constexpr_redecl_mismatch)
       << New << New->isConstexpr();
index 17bdd69ec242a5712939f628f5adc7658a9a5f72..2c98d0ab97ba9495887bf34e330ee760f9f1a9b3 100644 (file)
@@ -5677,8 +5677,13 @@ Sema::CheckFunctionTemplateSpecialization(FunctionDecl *FD,
   // Note: do not overwrite location info if previous template
   // specialization kind was explicit.
   TemplateSpecializationKind TSK = SpecInfo->getTemplateSpecializationKind();
-  if (TSK == TSK_Undeclared || TSK == TSK_ImplicitInstantiation)
+  if (TSK == TSK_Undeclared || TSK == TSK_ImplicitInstantiation) {
     Specialization->setLocation(FD->getLocation());
+    // C++11 [dcl.constexpr]p1: An explicit specialization of a constexpr
+    // function can differ from the template declaration with respect to
+    // the constexpr specifier.
+    Specialization->setConstexpr(FD->isConstexpr());
+  }
 
   // FIXME: Check if the prior specialization has a point of instantiation.
   // If so, we have run afoul of .
index 24e15e3d78805d1a5d68235a56ffd5f04e970269..6820fc6cb8796748007315f242ff4b710c681a68 100644 (file)
@@ -75,15 +75,13 @@ struct S {
 };
 
 // explicit specialization can differ in constepxr
-// FIXME: When checking the explicit specialization, we implicitly instantiate
-// the primary template then claim a constexpr mismatch.
-template <> notlit ft(notlit nl) { return nl; } // unexpected-error {{follows constexpr declaration}} unexpected-note {{here}}
-template <> char ft(char c) { return c; } // desired-note {{previous}} unexpected-error {{follows constexpr declaration}} unexpected-note {{here}}
-template <> constexpr char ft(char nl); // desired-error {{constexpr declaration of 'ft<char>' follows non-constexpr declaration}}
-template <> constexpr int gt(int nl) { return nl; } // unexpected-error {{follows non-constexpr declaration}} unexpected-note {{here}}
-template <> notlit S::f() const { return notlit(); } // unexpected-error {{follows constexpr declaration}} unexpected-note {{here}}
-template <> constexpr int S::g() { return 0; } // desired-note {{previous}} unexpected-error {{follows non-constexpr declaration}} unexpected-note {{here}}
-template <> int S::g() const; // desired-error {{non-constexpr declaration of 'g<int>' follows constexpr declaration}}
+template <> notlit ft(notlit nl) { return nl; }
+template <> char ft(char c) { return c; } // expected-note {{previous}}
+template <> constexpr char ft(char nl); // expected-error {{constexpr declaration of 'ft<char>' follows non-constexpr declaration}}
+template <> constexpr int gt(int nl) { return nl; }
+template <> notlit S::f() const { return notlit(); }
+template <> constexpr int S::g() { return 0; } // expected-note {{previous}}
+template <> int S::g() const; // expected-error {{non-constexpr declaration of 'g<int>' follows constexpr declaration}}
 // specializations can drop the 'constexpr' but not the implied 'const'.
 template <> char S::g() { return 0; } // expected-error {{no function template matches}}
 template <> double S::g() const { return 0; } // ok