From: Richard Smith Date: Tue, 22 Apr 2014 23:14:23 +0000 (+0000) Subject: PR18746: If a constexpr function has a dependent return type and no return X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=e75dc3bcc44a28cc42706c516b614ee5c0406196;p=clang PR18746: If a constexpr function has a dependent return type and no return statements, don't diagnose; the return type might end up being 'void'. Patch by Rahul Jain! Tiny tweaks by me. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@206929 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 96c6360114..197518f99e 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -1175,10 +1175,12 @@ bool Sema::CheckConstexprFunctionBody(const FunctionDecl *Dcl, Stmt *Body) { } else { if (ReturnStmts.empty()) { // C++1y doesn't require constexpr functions to contain a 'return' - // statement. We still do, unless the return type is void, because + // statement. We still do, unless the return type might be void, because // otherwise if there's no return statement, the function cannot // be used in a core constant expression. - bool OK = getLangOpts().CPlusPlus1y && Dcl->getReturnType()->isVoidType(); + bool OK = getLangOpts().CPlusPlus1y && + (Dcl->getReturnType()->isVoidType() || + Dcl->getReturnType()->isDependentType()); Diag(Dcl->getLocation(), OK ? diag::warn_cxx11_compat_constexpr_body_no_return : diag::err_constexpr_body_no_return); diff --git a/test/SemaCXX/cxx1y-deduced-return-type.cpp b/test/SemaCXX/cxx1y-deduced-return-type.cpp index d3308b3fd5..6086416595 100644 --- a/test/SemaCXX/cxx1y-deduced-return-type.cpp +++ b/test/SemaCXX/cxx1y-deduced-return-type.cpp @@ -261,6 +261,13 @@ namespace DefaultedMethods { namespace Constexpr { constexpr auto f1(int n) { return n; } + template struct X { constexpr auto f() {} }; // PR18746 + template struct Y { constexpr T f() {} }; // expected-note {{control reached end of constexpr function}} + void f() { + X().f(); + Y().f(); + constexpr int q = Y().f(); // expected-error {{must be initialized by a constant expression}} expected-note {{in call to '&Y()->f()'}} + } struct NonLiteral { ~NonLiteral(); } nl; // expected-note {{user-provided destructor}} constexpr auto f2(int n) { return nl; } // expected-error {{return type 'Constexpr::NonLiteral' is not a literal type}} }