Index: lib/AST/ExprConstant.cpp =================================================================== --- lib/AST/ExprConstant.cpp +++ lib/AST/ExprConstant.cpp @@ -4274,6 +4274,23 @@ case Stmt::CaseStmtClass: case Stmt::DefaultStmtClass: return EvaluateStmt(Result, Info, cast(S)->getSubStmt(), Case); + case Stmt::CXXTryStmtClass: { + // Evaluate try blocks by evaluating all sub statements and keep track + // whether there's a return. + EvalStmtResult ESR = ESR_Succeeded; + for (const Stmt *SubStmt : S->children()) { + EvalStmtResult SubStmtESR = EvaluateStmt(Result, Info, SubStmt, Case); + if (SubStmtESR != ESR_Succeeded && SubStmtESR != ESR_Returned) + return ESR_Failed; + if (SubStmtESR == ESR_Returned) + ESR = SubStmtESR; + } + return ESR; + } + case Stmt::CXXCatchStmtClass: + // No need to evaluate catch since it will be ignored in case the try block + // is successfully evaluated. + return ESR_Succeeded; } } Index: lib/Sema/SemaDeclCXX.cpp =================================================================== --- lib/Sema/SemaDeclCXX.cpp +++ lib/Sema/SemaDeclCXX.cpp @@ -1900,6 +1900,27 @@ return false; return true; + case Stmt::CXXTryStmtClass: + if (!SemaRef.getLangOpts().CPlusPlus2a) + break; + if (!Cxx1yLoc.isValid()) + Cxx1yLoc = S->getBeginLoc(); + for (Stmt *SubStmt : S->children()) + if (SubStmt && + !CheckConstexprFunctionStmt(SemaRef, Dcl, SubStmt, ReturnStmts, + Cxx1yLoc)) + return false; + return true; + + case Stmt::CXXCatchStmtClass: + if (!SemaRef.getLangOpts().CPlusPlus2a) + break; + if (!Cxx1yLoc.isValid()) + Cxx1yLoc = S->getBeginLoc(); + // In case we got a valid constexpr try block, the catch block can be + // ignored since it will never be evaluated in a constexpr context. + return true; + default: if (!isa(S)) break; @@ -1920,6 +1941,8 @@ /// /// \return true if the body is OK, false if we have diagnosed a problem. bool Sema::CheckConstexprFunctionBody(const FunctionDecl *Dcl, Stmt *Body) { + SmallVector ReturnStmts; + if (isa(Body)) { // C++11 [dcl.constexpr]p3: // The definition of a constexpr function shall satisfy the following @@ -1930,12 +1953,25 @@ // C++11 [dcl.constexpr]p4: // In the definition of a constexpr constructor, [...] // - its function-body shall not be a function-try-block; - Diag(Body->getBeginLoc(), diag::err_constexpr_function_try_block) - << isa(Dcl); - return false; - } + if (!getLangOpts().CPlusPlus2a) { + Diag(Body->getBeginLoc(), diag::err_constexpr_function_try_block) + << isa(Dcl); + return false; + } - SmallVector ReturnStmts; + // constexpr function try blocks are allowed in c++2a, assuming that the + // inner statements do also apply to general constexpr rules. + SourceLocation Cxx1yLoc; + for (Stmt *SubStmt : Body->children()) + if (SubStmt && + !CheckConstexprFunctionStmt(*this, Dcl, SubStmt, ReturnStmts, + Cxx1yLoc)) + return false; + if (Cxx1yLoc.isValid()) + Diag(Cxx1yLoc, diag::warn_cxx11_compat_constexpr_body_invalid_stmt) + << isa(Dcl); + return true; + } // - its function-body shall be [...] a compound-statement that contains only // [... list of cases ...] Index: test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp =================================================================== --- test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp +++ test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp @@ -1,5 +1,6 @@ // RUN: %clang_cc1 -verify -fcxx-exceptions -triple=x86_64-linux-gnu -std=c++11 -Werror=c++1y-extensions %s // RUN: %clang_cc1 -verify -fcxx-exceptions -triple=x86_64-linux-gnu -std=c++1y -DCXX1Y %s +// RUN: %clang_cc1 -verify -fcxx-exceptions -triple=x86_64-linux-gnu -std=c++2a -DCXX1Y -DCXX2A %s namespace N { typedef char C; @@ -78,7 +79,12 @@ }; struct T3 { constexpr T3 &operator=(const T3&) const = default; - // expected-error@-1 {{an explicitly-defaulted copy assignment operator may not have 'const' or 'volatile' qualifiers}} +#ifndef CXX2A + // expected-error@-2 {{an explicitly-defaulted copy assignment operator may not have 'const' or 'volatile' qualifiers}} +#else + // expected-warning@-4 {{explicitly defaulted copy assignment operator is implicitly deleted}} + // expected-note@-5 {{function is implicitly deleted because its declared type does not match the type of an implicit copy assignment operator}} +#endif }; #endif struct U { @@ -131,7 +137,10 @@ } constexpr int DisallowedStmtsCXX1Y_3() { // - a try-block, - try {} catch (...) {} // expected-error {{statement not allowed in constexpr function}} + try {} catch (...) {} +#ifndef CXX2A + // expected-error@-2 {{statement not allowed in constexpr function}} +#endif return 0; } constexpr int DisallowedStmtsCXX1Y_4() { Index: test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p4.cpp =================================================================== --- test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p4.cpp +++ test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p4.cpp @@ -1,5 +1,6 @@ // RUN: %clang_cc1 -verify -std=c++11 -fcxx-exceptions -Werror=c++1y-extensions %s // RUN: %clang_cc1 -verify -std=c++1y -fcxx-exceptions -DCXX1Y %s +// RUN: %clang_cc1 -verify -std=c++2a -fcxx-exceptions -DCXX1Y -DCXX2A %s namespace N { typedef char C; @@ -49,7 +50,10 @@ // - its function-body shall not be a function-try-block; struct U { constexpr U() - try // expected-error {{function try block not allowed in constexpr constructor}} + try +#ifndef CXX2A + // expected-error@-2 {{function try block not allowed in constexpr constructor}} +#endif : u() { } catch (...) { throw; Index: test/CXX/drs/dr6xx.cpp =================================================================== --- test/CXX/drs/dr6xx.cpp +++ test/CXX/drs/dr6xx.cpp @@ -492,7 +492,10 @@ struct C { constexpr C(NonLiteral); constexpr C(NonLiteral, int) {} // expected-error {{not a literal type}} - constexpr C() try {} catch (...) {} // expected-error {{function try block}} + constexpr C() try {} catch (...) {} +#if __cplusplus <= 201703L + // expected-error@-2 {{function try block}} +#endif }; struct D { Index: www/cxx_status.html =================================================================== --- www/cxx_status.html +++ www/cxx_status.html @@ -953,13 +953,15 @@ Relaxations of constexpr restrictions P1064R0 - No + No P1002R1 + Clang 8 P1327R1 + No P1330R0