From: Richard Smith Date: Sun, 5 Feb 2012 02:30:54 +0000 (+0000) Subject: constexpr: Implement DR1358: An instantiation of a constexpr function which X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=d79093af384ac0ea78f4237a001eae7467e06a61;p=clang constexpr: Implement DR1358: An instantiation of a constexpr function which can't produce a constant expression is not ill-formed (so long as some instantiation of that function can produce a constant expression). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@149802 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index d2d61abc7a..8aca77f51a 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -1016,7 +1016,8 @@ public: }; bool CheckConstexprFunctionDecl(const FunctionDecl *FD, CheckConstexprKind CCK); - bool CheckConstexprFunctionBody(const FunctionDecl *FD, Stmt *Body); + bool CheckConstexprFunctionBody(const FunctionDecl *FD, Stmt *Body, + bool IsInstantiation); void DiagnoseHiddenVirtualMethods(CXXRecordDecl *DC, CXXMethodDecl *MD); // Returns true if the function declaration is a redeclaration diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 6b92b0ad67..172e931153 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -7302,7 +7302,7 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, } if (FD && FD->isConstexpr() && !FD->isInvalidDecl() && - !CheckConstexprFunctionBody(FD, Body)) + !CheckConstexprFunctionBody(FD, Body, IsInstantiation)) FD->setInvalidDecl(); assert(ExprCleanupObjects.empty() && "Leftover temporaries in function"); diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index a52d44c4f2..10883af4b4 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -837,7 +837,8 @@ static void CheckConstexprCtorInitializer(Sema &SemaRef, /// the permitted types of statement. C++11 [dcl.constexpr]p3,p4. /// /// \return true if the body is OK, false if we have diagnosed a problem. -bool Sema::CheckConstexprFunctionBody(const FunctionDecl *Dcl, Stmt *Body) { +bool Sema::CheckConstexprFunctionBody(const FunctionDecl *Dcl, Stmt *Body, + bool IsInstantiation) { if (isa(Body)) { // C++11 [dcl.constexpr]p3: // The definition of a constexpr function shall satisfy the following @@ -989,7 +990,7 @@ bool Sema::CheckConstexprFunctionBody(const FunctionDecl *Dcl, Stmt *Body) { // can't produce constant expressions. llvm::SmallVector Diags; if (!Context.getSourceManager().isInSystemHeader(Dcl->getLocation()) && - !Expr::isPotentialConstantExpr(Dcl, Diags)) { + !IsInstantiation && !Expr::isPotentialConstantExpr(Dcl, Diags)) { Diag(Dcl->getLocation(), diag::err_constexpr_function_never_constant_expr) << isa(Dcl); for (size_t I = 0, N = Diags.size(); I != N; ++I) diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p5.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p5.cpp index 43fc887b00..4e7608ec62 100644 --- a/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p5.cpp +++ b/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p5.cpp @@ -78,4 +78,29 @@ constexpr bool BcpCall(int n) { } static_assert(BcpCall(0), ""); +// DR1311: A function template which can produce a constant expression, but +// for which a particular specialization cannot, is ok. +template constexpr T cmin(T a, T b) { + return a < b ? a : b; +} +int n = cmin(3, 5); // ok + +struct X { + constexpr X() {} + bool operator<(X); // not constexpr +}; + +X x = cmin(X(), X()); // ok, not constexpr + +// Same with other temploids. +template +struct Y { + constexpr Y() {} + constexpr int get() { return T(); } +}; +struct Z { operator int(); }; + +int y1 = Y().get(); // ok +int y2 = Y().get(); // ok + }