From: Richard Smith Date: Mon, 20 Feb 2012 23:28:05 +0000 (+0000) Subject: Fix a constexpr FIXME: When implicitly instantiating the primary template for an X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=ff2348888133dcc64f7363af2093cb608caeb7ce;p=clang Fix a constexpr FIXME: When implicitly instantiating the primary template for an 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 --- diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 48dc911b6a..faf2c41853 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -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(); diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 17bdd69ec2..2c98d0ab97 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -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 . diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp index 24e15e3d78..6820fc6cb8 100644 --- a/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp +++ b/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp @@ -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' 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' 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' 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' 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