aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2019-03-01 15:20:03 +0100
committerJakub Jelinek <jakub@gcc.gnu.org>2019-03-01 15:20:03 +0100
commit1259cb6d0034f36cce26ca8fd3d22d40bafce04a (patch)
treef0b32a4e2a747b9f23167114d3bd16b4a456e95d /gcc
parentc5effe9673bd266887b5c4cb968cce61ce137ca1 (diff)
downloadgcc-1259cb6d0034f36cce26ca8fd3d22d40bafce04a.zip
gcc-1259cb6d0034f36cce26ca8fd3d22d40bafce04a.tar.gz
gcc-1259cb6d0034f36cce26ca8fd3d22d40bafce04a.tar.bz2
Implement P1002R1, Try-catch blocks in constexpr functions PR c++/89513
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. * 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. From-SVN: r269314
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog12
-rw-r--r--gcc/cp/constexpr.c12
-rw-r--r--gcc/cp/parser.c27
-rw-r--r--gcc/testsuite/ChangeLog11
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-ctor10.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/constexpr-try1.C44
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/constexpr-try2.C45
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/constexpr-try3.C44
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/constexpr-try4.C61
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/constexpr-try5.C40
10 files changed, 286 insertions, 12 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index a86ffa3..11b9bb2 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,15 @@
+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.
diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index 5bc5efe..65888b6 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -601,6 +601,12 @@ build_constexpr_constructor_member_initializers (tree type, tree body)
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);
@@ -626,12 +632,6 @@ build_constexpr_constructor_member_initializers (tree type, tree body)
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
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 5f69403..2edd685 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -22590,11 +22590,25 @@ cp_parser_ctor_initializer_opt_and_function_body (cp_parser *parser,
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. */
@@ -25329,8 +25343,11 @@ cp_parser_try_block (cp_parser* parser)
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);
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 2ad0d80..7734ac6 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,14 @@
+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
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor10.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor10.C
index 1dbc335..194cc7c 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor10.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor10.C
@@ -2,5 +2,5 @@
// { 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 } }
};
diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-try1.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-try1.C
new file mode 100644
index 0000000..977eb86
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-try1.C
@@ -0,0 +1,44 @@
+// 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 } }
+ }
+};
diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-try2.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-try2.C
new file mode 100644
index 0000000..7ca7261
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-try2.C
@@ -0,0 +1,45 @@
+// 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 } }
+ }
+};
diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-try3.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-try3.C
new file mode 100644
index 0000000..ab7e8f6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-try3.C
@@ -0,0 +1,44 @@
+// 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 (...) {
+ }
+};
diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-try4.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-try4.C
new file mode 100644
index 0000000..8c2baef
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-try4.C
@@ -0,0 +1,61 @@
+// 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;
diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-try5.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-try5.C
new file mode 100644
index 0000000..47cdce8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-try5.C
@@ -0,0 +1,40 @@
+// 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;
+ }
+}