diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 96c636011485..197518f99efc 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/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/clang/test/SemaCXX/cxx1y-deduced-return-type.cpp b/clang/test/SemaCXX/cxx1y-deduced-return-type.cpp index d3308b3fd50b..60864165954a 100644 --- a/clang/test/SemaCXX/cxx1y-deduced-return-type.cpp +++ b/clang/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}} }