diff options
author | Jakub Jelinek <jakub@redhat.com> | 2019-03-01 15:20:03 +0100 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2019-03-01 15:20:03 +0100 |
commit | 1259cb6d0034f36cce26ca8fd3d22d40bafce04a (patch) | |
tree | f0b32a4e2a747b9f23167114d3bd16b4a456e95d /gcc | |
parent | c5effe9673bd266887b5c4cb968cce61ce137ca1 (diff) | |
download | gcc-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/ChangeLog | 12 | ||||
-rw-r--r-- | gcc/cp/constexpr.c | 12 | ||||
-rw-r--r-- | gcc/cp/parser.c | 27 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 11 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/constexpr-ctor10.C | 2 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp2a/constexpr-try1.C | 44 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp2a/constexpr-try2.C | 45 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp2a/constexpr-try3.C | 44 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp2a/constexpr-try4.C | 61 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp2a/constexpr-try5.C | 40 |
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; + } +} |