+2019-03-01 Jakub Jelinek <jakub@redhat.com>
+
+ Implement P1002R1, Try-catch blocks in constexpr functions
+ PR c++/89513
+ * parser.c (cp_parser_ctor_initializer_opt_and_function_body):
+ Diagnose constexpr ctor or function with function-try-block with
+ pedwarn for c++17 and earlier. Formatting fix.
+ (cp_parser_try_block): Use pedwarn instead of error and only for
+ c++17 and earlier when try block appears in constexpr function.
+ * constexpr.c (build_constexpr_constructor_member_initializers):
+ Handle TRY_BLOCK here instead of erroring on it.
+
2019-02-28 Jason Merrill <jason@redhat.com>
PR c++/88183 - ICE with .* fold-expression.
gcc_unreachable ();
}
found:
+ if (TREE_CODE (body) == TRY_BLOCK)
+ {
+ body = TREE_OPERAND (body, 0);
+ if (TREE_CODE (body) == BIND_EXPR)
+ body = BIND_EXPR_BODY (body);
+ }
if (TREE_CODE (body) == CLEANUP_POINT_EXPR)
{
body = TREE_OPERAND (body, 0);
break;
}
}
- else if (TREE_CODE (body) == TRY_BLOCK)
- {
- error ("body of %<constexpr%> constructor cannot be "
- "a function-try-block");
- return error_mark_node;
- }
else if (EXPR_P (body))
ok = build_data_member_initialization (body, &vec);
else
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)
+ && cxx_dialect < cxx2a)
+ {
+ if (DECL_CONSTRUCTOR_P (current_function_decl))
+ pedwarn (input_location, 0,
+ "function-try-block body of %<constexpr%> constructor only "
+ "available with -std=c++2a or -std=gnu++2a");
+ else
+ pedwarn (input_location, 0,
+ "function-try-block body of %<constexpr%> function only "
+ "available with -std=c++2a or -std=gnu++2a");
+ }
+
/* Begin the function body. */
body = begin_function_body ();
/* Parse the optional ctor-initializer. */
cp_parser_require_keyword (parser, RID_TRY, RT_TRY);
if (parser->in_function_body
- && DECL_DECLARED_CONSTEXPR_P (current_function_decl))
- error ("%<try%> in %<constexpr%> function");
+ && DECL_DECLARED_CONSTEXPR_P (current_function_decl)
+ && cxx_dialect < cxx2a)
+ pedwarn (input_location, 0,
+ "%<try%> in %<constexpr%> function only "
+ "available with -std=c++2a or -std=gnu++2a");
try_block = begin_try_block ();
cp_parser_compound_statement (parser, NULL, BCS_TRY_BLOCK, false);
+2019-03-01 Jakub Jelinek <jakub@redhat.com>
+
+ Implement P1002R1, Try-catch blocks in constexpr functions
+ PR c++/89513
+ * g++.dg/cpp2a/constexpr-try1.C: New test.
+ * g++.dg/cpp2a/constexpr-try2.C: New test.
+ * g++.dg/cpp2a/constexpr-try3.C: New test.
+ * g++.dg/cpp2a/constexpr-try4.C: New test.
+ * g++.dg/cpp2a/constexpr-try5.C: New test.
+ * g++.dg/cpp0x/constexpr-ctor10.C: Don't expect error for C++2a.
+
2019-03-01 Richard Sandiford <richard.sandiford@arm.com>
PR tree-optimization/89535
// { dg-do compile { target c++11 } }
struct foo {
- constexpr foo() try { } catch(...) { }; // { dg-error "constexpr" }
+ constexpr foo() try { } catch(...) { }; // { dg-error "constexpr" "" { target c++17_down } }
};
--- /dev/null
+// PR c++/89513
+// { dg-do compile { target c++11 } }
+
+constexpr bool foo ()
+try { // { dg-error "function-try-block body of 'constexpr' function only available with" "" { target c++17_down } }
+ return true;
+} catch (...) { // { dg-error "compound-statement in 'constexpr' function" "" { target c++11_only } }
+ return false;
+} // { dg-error "body of 'constexpr' function" "" { target c++11_only } }
+
+constexpr bool bar ()
+try { // { dg-error "function-try-block body of 'constexpr' function only available with" "" { target c++17_down } }
+ try { // { dg-error "'try' in 'constexpr' function only available with" "" { target c++17_down } }
+ return true; // { dg-error "compound-statement in 'constexpr' function" "" { target c++11_only } .-1 }
+ } catch (int) { // { dg-error "compound-statement in 'constexpr' function" "" { target c++11_only } }
+ return false;
+ }
+} catch (...) { // { dg-error "compound-statement in 'constexpr' function" "" { target c++11_only } }
+ return false;
+} // { dg-error "not a return-statement" "" { target c++11_only } }
+
+constexpr bool baz ()
+{
+ try { return true; } catch (...) { return false; } // { dg-error "'try' in 'constexpr' function only available with" "" { target c++17_down } }
+} // { dg-error "not a return-statement" "" { target c++11_only } }
+ // { dg-error "compound-statement in 'constexpr' function" "" { target c++11_only } .-2 }
+
+struct S {
+ constexpr S () try : m (1) // { dg-error "function-try-block body of 'constexpr' constructor only available with" "" { target c++17_down } }
+ {
+ try { // { dg-error "'try' in 'constexpr' function only available with" "" { target c++17_down } }
+ } catch (int) { // { dg-error "compound-statement in 'constexpr' function" "" { target c++11_only } }
+ } // { dg-error "compound-statement in 'constexpr' function" "" { target c++11_only } .-2 }
+ } catch (...) { // { dg-error "'constexpr' constructor does not have empty body" "" { target c++11_only } }
+ }
+ int m;
+};
+
+struct T {
+ constexpr T ()
+ try { // { dg-error "function-try-block body of 'constexpr' constructor only available with" "" { target c++17_down } }
+ } catch (...) { // { dg-error "compound-statement in 'constexpr' function" "" { target c++11_only } }
+ }
+};
--- /dev/null
+// PR c++/89513
+// { dg-do compile { target c++11 } }
+// { dg-options "-pedantic" }
+
+constexpr bool foo ()
+try { // { dg-warning "function-try-block body of 'constexpr' function only available with" "" { target c++17_down } }
+ return true;
+} catch (...) { // { dg-warning "compound-statement in 'constexpr' function" "" { target c++11_only } }
+ return false;
+} // { dg-error "body of 'constexpr' function" "" { target c++11_only } }
+
+constexpr bool bar ()
+try { // { dg-warning "function-try-block body of 'constexpr' function only available with" "" { target c++17_down } }
+ try { // { dg-warning "'try' in 'constexpr' function only available with" "" { target c++17_down } }
+ return true; // { dg-warning "compound-statement in 'constexpr' function" "" { target c++11_only } .-1 }
+ } catch (int) { // { dg-warning "compound-statement in 'constexpr' function" "" { target c++11_only } }
+ return false;
+ }
+} catch (...) { // { dg-warning "compound-statement in 'constexpr' function" "" { target c++11_only } }
+ return false;
+} // { dg-error "not a return-statement" "" { target c++11_only } }
+
+constexpr bool baz ()
+{
+ try { return true; } catch (...) { return false; } // { dg-warning "'try' in 'constexpr' function only available with" "" { target c++17_down } }
+} // { dg-error "not a return-statement" "" { target c++11_only } }
+ // { dg-warning "compound-statement in 'constexpr' function" "" { target c++11_only } .-2 }
+
+struct S {
+ constexpr S () try : m (1) // { dg-warning "function-try-block body of 'constexpr' constructor only available with" "" { target c++17_down } }
+ {
+ try { // { dg-warning "'try' in 'constexpr' function only available with" "" { target c++17_down } }
+ } catch (int) { // { dg-warning "compound-statement in 'constexpr' function" "" { target c++11_only } }
+ } // { dg-warning "compound-statement in 'constexpr' function" "" { target c++11_only } .-2 }
+ } catch (...) { // { dg-error "'constexpr' constructor does not have empty body" "" { target c++11_only } }
+ }
+ int m;
+};
+
+struct T {
+ constexpr T ()
+ try { // { dg-warning "function-try-block body of 'constexpr' constructor only available with" "" { target c++17_down } }
+ } catch (...) { // { dg-warning "compound-statement in 'constexpr' function" "" { target c++11_only } }
+ }
+};
--- /dev/null
+// PR c++/89513
+// { dg-do compile { target c++11 } }
+// { dg-options "" }
+
+constexpr bool foo ()
+try { // { dg-warning "function-try-block body of 'constexpr' function only available with" "" { target c++17_down } }
+ return true;
+} catch (...) {
+ return false;
+} // { dg-error "body of 'constexpr' function" "" { target c++11_only } }
+
+constexpr bool bar ()
+try { // { dg-warning "function-try-block body of 'constexpr' function only available with" "" { target c++17_down } }
+ try { // { dg-warning "'try' in 'constexpr' function only available with" "" { target c++17_down } }
+ return true;
+ } catch (int) {
+ return false;
+ }
+} catch (...) {
+ return false;
+} // { dg-error "not a return-statement" "" { target c++11_only } }
+
+constexpr bool baz ()
+{
+ try { return true; } catch (...) { return false; } // { dg-warning "'try' in 'constexpr' function only available with" "" { target c++17_down } }
+} // { dg-error "not a return-statement" "" { target c++11_only } }
+
+struct S {
+ constexpr S () try : m (1) // { dg-warning "function-try-block body of 'constexpr' constructor only available with" "" { target c++17_down } }
+ {
+ try { // { dg-warning "'try' in 'constexpr' function only available with" "" { target c++17_down } }
+ } catch (int) {
+ }
+ } catch (...) { // { dg-error "'constexpr' constructor does not have empty body" "" { target c++11_only } }
+ }
+ int m;
+};
+
+struct T {
+ constexpr T ()
+ try { // { dg-warning "function-try-block body of 'constexpr' constructor only available with" "" { target c++17_down } }
+ } catch (...) {
+ }
+};
--- /dev/null
+// PR c++/89513
+// { dg-do compile { target c++14 } }
+// { dg-options "" }
+
+constexpr int foo ()
+try { // { dg-warning "function-try-block body of 'constexpr' function only available with" "" { target c++17_down } }
+ int a = 1;
+ for (int i = 0; i < 10; i++)
+ a += i;
+ return a;
+} catch (...) {
+ return -1;
+}
+
+constexpr int bar ()
+try { // { dg-warning "function-try-block body of 'constexpr' function only available with" "" { target c++17_down } }
+ int a = 0;
+ for (int i = 0; i < 9; i++)
+ try { // { dg-warning "'try' in 'constexpr' function only available with" "" { target c++17_down } }
+ a += i;
+ } catch (int) {
+ return -1;
+ }
+ return a;
+} catch (...) {
+ return -2;
+}
+
+constexpr bool baz ()
+{
+ try { return true; } catch (...) { return false; } // { dg-warning "'try' in 'constexpr' function only available with" "" { target c++17_down } }
+}
+
+struct S {
+ constexpr S () try : m (1) // { dg-warning "function-try-block body of 'constexpr' constructor only available with" "" { target c++17_down } }
+ {
+ try { // { dg-warning "'try' in 'constexpr' function only available with" "" { target c++17_down } }
+ m += 2;
+ } catch (int) {
+ m = -1;
+ }
+ } catch (...) {
+ m = -2;
+ }
+ int m;
+ constexpr int get () const { return m; }
+};
+
+struct T {
+ constexpr T ()
+ try { // { dg-warning "function-try-block body of 'constexpr' constructor only available with" "" { target c++17_down } }
+ } catch (...) {
+ }
+};
+
+static_assert (foo () == 46, "");
+static_assert (bar () == 36, "");
+static_assert (baz (), "");
+constexpr S s;
+static_assert (s.get () == 3, "");
+constexpr T t;
--- /dev/null
+// PR c++/89513
+// { dg-do compile { target c++14 } }
+// { dg-options "" }
+
+constexpr int foo ()
+try { // { dg-warning "function-try-block body of 'constexpr' function only available with" "" { target c++17_down } }
+ int a; // { dg-error "uninitialized variable 'a' in 'constexpr' function" }
+ static double b = 1.0;// { dg-error "'b' declared 'static' in 'constexpr' function" }
+ goto l; // { dg-error "'goto' in 'constexpr' function" }
+ l:;
+ return 0;
+} catch (...) {
+ long int c; // { dg-error "uninitialized variable 'c' in 'constexpr' function" }
+ static float d = 2.0f;// { dg-error "'d' declared 'static' in 'constexpr' function" }
+ goto l2; // { dg-error "'goto' in 'constexpr' function" }
+ l2:;
+ return -1;
+}
+
+constexpr int bar ()
+{
+ int a; // { dg-error "uninitialized variable 'a' in 'constexpr' function" }
+ static long double b = 3.0;// { dg-error "'b' declared 'static' in 'constexpr' function" }
+ goto l; // { dg-error "'goto' in 'constexpr' function" }
+ l:;
+ try { // { dg-warning "'try' in 'constexpr' function only available with" "" { target c++17_down } }
+ short c; // { dg-error "uninitialized variable 'c' in 'constexpr' function" }
+ static float d; // { dg-error "'d' declared 'static' in 'constexpr' function" }
+ // { dg-error "uninitialized variable 'd' in 'constexpr' function" "" { target *-*-* } .-1 }
+ goto l2; // { dg-error "'goto' in 'constexpr' function" }
+ l2:;
+ return 0;
+ } catch (int) {
+ char e; // { dg-error "uninitialized variable 'e' in 'constexpr' function" }
+ static int f = 5; // { dg-error "'f' declared 'static' in 'constexpr' function" }
+ goto l3; // { dg-error "'goto' in 'constexpr' function" }
+ l3:;
+ return 1;
+ }
+}