Hi! C++ before 2a says that constexpr constructors may not have function-try-block body, for other constexpr functions it instead says that the function body can be (=delete, =default or compound-statement), but that rules out function-try-block as well.
For ctors we were diagnostic this in build_constexpr_constructor_member_initializers, but with worse locus, so this patch diagnoses it for both ctors and other constexpr functions in the same place. Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? Or would you prefer to have P1002R1 implemented and thus make this perhaps a pedwarn before cxx2a, similarly for the error on try block in the body and tweak build_constexpr_constructor_member_initializers? I think constexpr evaluation handles TRY_BLOCK already. 2019-02-27 Jakub Jelinek <ja...@redhat.com> PR c++/89513 * parser.c (cp_parser_ctor_initializer_opt_and_function_body): Diagnose constexpr ctor or function with function-try-block. Formatting fix. * constexpr.c (build_constexpr_constructor_member_initializers): Don't diagnose constexpr ctor with function-try-block here. * g++.dg/cpp0x/constexpr-89513.C: New test. --- gcc/cp/parser.c.jj 2019-02-23 11:32:45.705614155 +0100 +++ gcc/cp/parser.c 2019-02-27 14:18:26.211248671 +0100 @@ -22589,11 +22589,22 @@ cp_parser_ctor_initializer_opt_and_funct bool in_function_try_block) { tree body, list; - const bool check_body_p = - DECL_CONSTRUCTOR_P (current_function_decl) - && DECL_DECLARED_CONSTEXPR_P (current_function_decl); + const bool check_body_p + = (DECL_CONSTRUCTOR_P (current_function_decl) + && DECL_DECLARED_CONSTEXPR_P (current_function_decl)); tree last = NULL; + if (in_function_try_block + && DECL_DECLARED_CONSTEXPR_P (current_function_decl)) + { + if (DECL_CONSTRUCTOR_P (current_function_decl)) + error ("body of %<constexpr%> constructor cannot be " + "a function-try-block"); + else + error ("body of %<constexpr%> function cannot be " + "a function-try-block"); + } + /* Begin the function body. */ body = begin_function_body (); /* Parse the optional ctor-initializer. */ --- gcc/cp/constexpr.c.jj 2019-02-26 15:37:06.475371073 +0100 +++ gcc/cp/constexpr.c 2019-02-27 14:17:34.434096156 +0100 @@ -627,11 +627,8 @@ build_constexpr_constructor_member_initi } } else if (TREE_CODE (body) == TRY_BLOCK) - { - error ("body of %<constexpr%> constructor cannot be " - "a function-try-block"); - return error_mark_node; - } + /* This should have been diagnosed earlier. */ + return error_mark_node; else if (EXPR_P (body)) ok = build_data_member_initialization (body, &vec); else --- gcc/testsuite/g++.dg/cpp0x/constexpr-89513.C.jj 2019-02-27 14:28:50.280033938 +0100 +++ gcc/testsuite/g++.dg/cpp0x/constexpr-89513.C 2019-02-27 14:34:51.585120108 +0100 @@ -0,0 +1,48 @@ +// PR c++/89513 +// { dg-do compile { target c++11 } } +// { dg-options "" } + +constexpr bool foo () +try { // { dg-error "body of 'constexpr' function cannot be a function-try-block" } + return true; +} catch (...) { + return false; +} // { dg-error "body of 'constexpr' function" "" { target c++11_only } } + +#if __cplusplus > 201103L +constexpr bool bar () +try { // { dg-error "body of 'constexpr' function cannot be a function-try-block" "" { target c++14 } } + try { // { dg-error "'try' in 'constexpr' function" "" { target c++14 } } + return true; + } catch (int) { + return false; + } +} catch (...) { + return false; +} + +constexpr bool baz () +{ + try { return true; } catch (...) { return false; } // { dg-error "'try' in 'constexpr' function" "" { target c++14 } } +} +#endif + +struct S { + constexpr S () try : m (1) // { dg-error "body of 'constexpr' constructor cannot be a function-try-block" } + { +#if __cplusplus > 201103L + try { // { dg-error "'try' in 'constexpr' function" "" { target c++14 } } + } catch (int) { + } +#endif + } catch (...) { + } + int m; +}; + +struct T { + constexpr T () + try { // { dg-error "body of 'constexpr' constructor cannot be a function-try-block" } + } catch (...) { + } +}; Jakub