diff options
author | Jason Merrill <jason@redhat.com> | 2015-05-05 22:25:01 -0400 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2015-05-05 22:25:01 -0400 |
commit | 8243e2a9d0a466a907459d1b04d2d20027e5ef9b (patch) | |
tree | 9ad11d8e374ad72b911037b02842a64b8871323b | |
parent | 81b6a6c55bd5b2549dbaa16a87e736c4c8ac1bf5 (diff) | |
download | gcc-8243e2a9d0a466a907459d1b04d2d20027e5ef9b.zip gcc-8243e2a9d0a466a907459d1b04d2d20027e5ef9b.tar.gz gcc-8243e2a9d0a466a907459d1b04d2d20027e5ef9b.tar.bz2 |
c.opt (Wterminate): New.
gcc/c-family/
* c.opt (Wterminate): New.
gcc/cp/
* cp-gimplify.c (cp_genericize_r): Track TRY_BLOCK and
MUST_NOT_THROW_EXPR, warn about a THROW_EXPR directly within a
MUST_NOT_THROW_EXPR.
(cp_genericize_data): Add try_block field.
(cp_genericize_tree): Initialize it.
* except.c (expand_end_catch_block): Set TREE_NO_WARNING on
implicit rethrow.
From-SVN: r222842
-rw-r--r-- | gcc/c-family/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/c-family/c.opt | 4 | ||||
-rw-r--r-- | gcc/cp/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/cp/cp-gimplify.c | 50 | ||||
-rw-r--r-- | gcc/cp/except.c | 6 | ||||
-rw-r--r-- | gcc/doc/invoke.texi | 6 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/compat/eh/ctor1.h | 2 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/compat/eh/ctor1_y.C | 2 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/noexcept06.C | 1 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/noexcept17.C | 1 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/eh/cond4.C | 2 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/eh/ehopt1.C | 4 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/eh/init-temp2.C | 6 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/tm/noexcept-5.C | 2 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/torture/pr49394.C | 2 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/warn/Wterminate1.C | 20 | ||||
-rw-r--r-- | gcc/testsuite/g++.old-deja/g++.mike/eh25.C | 2 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/30_threads/lock_guard/cons/1.cc | 2 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/util/replacement_memory_operators.h | 2 |
19 files changed, 112 insertions, 14 deletions
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index 8c2e933..9d16d43 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,7 @@ +2015-05-05 Jason Merrill <jason@redhat.com> + + * c.opt (Wterminate): New. + 2015-04-30 Marek Polacek <polacek@redhat.com> * c-common.c (maybe_warn_bool_compare): When comparing with 0/1, diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt index 983f4a8..8ef0cea 100644 --- a/gcc/c-family/c.opt +++ b/gcc/c-family/c.opt @@ -829,6 +829,10 @@ Wsystem-headers C ObjC C++ ObjC++ Warning ; Documented in common.opt +Wterminate +C++ ObjC++ Warning Var(warn_terminate) Init(1) +Warn if a throw expression will always result in a call to terminate() + Wtraditional C ObjC CPP(cpp_warn_traditional) CppReason(CPP_W_TRADITIONAL) Var(warn_traditional) Init(0) Warning Warn about features not present in traditional C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index fc543e6..b1da4fe 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,13 @@ 2015-05-05 Jason Merrill <jason@redhat.com> + * cp-gimplify.c (cp_genericize_r): Track TRY_BLOCK and + MUST_NOT_THROW_EXPR, warn about a THROW_EXPR directly within a + MUST_NOT_THROW_EXPR. + (cp_genericize_data): Add try_block field. + (cp_genericize_tree): Initialize it. + * except.c (expand_end_catch_block): Set TREE_NO_WARNING on + implicit rethrow. + * constexpr.c (potential_constant_expression_1) [AT_ENCODE_EXPR]: Return false. diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c index 70645b5..35749ef 100644 --- a/gcc/cp/cp-gimplify.c +++ b/gcc/cp/cp-gimplify.c @@ -905,6 +905,7 @@ struct cp_genericize_data hash_set<tree> *p_set; vec<tree> bind_expr_stack; struct cp_genericize_omp_taskreg *omp_ctx; + tree try_block; }; /* Perform any pre-gimplification lowering of C++ front end trees to @@ -1193,6 +1194,54 @@ cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data) wtd->omp_ctx = omp_ctx.outer; splay_tree_delete (omp_ctx.variables); } + else if (TREE_CODE (stmt) == TRY_BLOCK) + { + *walk_subtrees = 0; + tree try_block = wtd->try_block; + wtd->try_block = stmt; + cp_walk_tree (&TRY_STMTS (stmt), cp_genericize_r, data, NULL); + wtd->try_block = try_block; + cp_walk_tree (&TRY_HANDLERS (stmt), cp_genericize_r, data, NULL); + } + else if (TREE_CODE (stmt) == MUST_NOT_THROW_EXPR) + { + /* MUST_NOT_THROW_COND might be something else with TM. */ + if (MUST_NOT_THROW_COND (stmt) == NULL_TREE) + { + *walk_subtrees = 0; + tree try_block = wtd->try_block; + wtd->try_block = stmt; + cp_walk_tree (&TREE_OPERAND (stmt, 0), cp_genericize_r, data, NULL); + wtd->try_block = try_block; + } + } + else if (TREE_CODE (stmt) == THROW_EXPR) + { + location_t loc = location_of (stmt); + if (TREE_NO_WARNING (stmt)) + /* Never mind. */; + else if (wtd->try_block) + { + if (TREE_CODE (wtd->try_block) == MUST_NOT_THROW_EXPR + && warning_at (loc, OPT_Wterminate, + "throw will always call terminate()") + && cxx_dialect >= cxx11 + && DECL_DESTRUCTOR_P (current_function_decl)) + inform (loc, "in C++11 destructors default to noexcept"); + } + else + { + if (warn_cxx0x_compat && cxx_dialect < cxx11 + && DECL_DESTRUCTOR_P (current_function_decl) + && (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (current_function_decl)) + == NULL_TREE) + && (get_defaulted_eh_spec (current_function_decl) + == empty_except_spec)) + warning_at (loc, OPT_Wc__0x_compat, + "in C++11 this throw will terminate because " + "destructors default to noexcept"); + } + } else if (TREE_CODE (stmt) == CONVERT_EXPR) gcc_assert (!CONVERT_EXPR_VBASE_PATH (stmt)); else if (TREE_CODE (stmt) == FOR_STMT) @@ -1269,6 +1318,7 @@ cp_genericize_tree (tree* t_p) wtd.p_set = new hash_set<tree>; wtd.bind_expr_stack.create (0); wtd.omp_ctx = NULL; + wtd.try_block = NULL_TREE; cp_walk_tree (t_p, cp_genericize_r, &wtd, NULL); delete wtd.p_set; wtd.bind_expr_stack.release (); diff --git a/gcc/cp/except.c b/gcc/cp/except.c index 3ff1ce6..614f2e9 100644 --- a/gcc/cp/except.c +++ b/gcc/cp/except.c @@ -579,7 +579,11 @@ expand_end_catch_block (void) if (in_function_try_handler && (DECL_CONSTRUCTOR_P (current_function_decl) || DECL_DESTRUCTOR_P (current_function_decl))) - finish_expr_stmt (build_throw (NULL_TREE)); + { + tree rethrow = build_throw (NULL_TREE); + TREE_NO_WARNING (rethrow) = true; + finish_expr_stmt (rethrow); + } } tree diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index debd8ed..9c8aa99 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -2882,6 +2882,12 @@ Warn when overload resolution chooses a promotion from unsigned or enumerated type to a signed type, over a conversion to an unsigned type of the same size. Previous versions of G++ tried to preserve unsignedness, but the standard mandates the current behavior. + +@item -Wno-terminate @r{(C++ and Objective-C++ only)} +@opindex Wterminate +@opindex Wno-terminate +Disable the warning about a throw-expression that will immediately +result in a call to @code{terminate}. @end table @node Objective-C and Objective-C++ Dialect Options diff --git a/gcc/testsuite/g++.dg/compat/eh/ctor1.h b/gcc/testsuite/g++.dg/compat/eh/ctor1.h index e83476f..9ad1860 100644 --- a/gcc/testsuite/g++.dg/compat/eh/ctor1.h +++ b/gcc/testsuite/g++.dg/compat/eh/ctor1.h @@ -5,6 +5,6 @@ struct Foo struct Bar { - ~Bar (); + ~Bar () throw(int); Foo f; }; diff --git a/gcc/testsuite/g++.dg/compat/eh/ctor1_y.C b/gcc/testsuite/g++.dg/compat/eh/ctor1_y.C index 260ab1c..ca1cf38 100644 --- a/gcc/testsuite/g++.dg/compat/eh/ctor1_y.C +++ b/gcc/testsuite/g++.dg/compat/eh/ctor1_y.C @@ -7,7 +7,7 @@ Foo::~Foo() was_f_in_Bar_destroyed=true; } -Bar::~Bar() +Bar::~Bar() throw(int) { throw 1; } diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept06.C b/gcc/testsuite/g++.dg/cpp0x/noexcept06.C index 7e1db66..ad9edec 100644 --- a/gcc/testsuite/g++.dg/cpp0x/noexcept06.C +++ b/gcc/testsuite/g++.dg/cpp0x/noexcept06.C @@ -1,6 +1,7 @@ // Test that checking of a nothrow specification uses the one on the // definition. // { dg-do run { target c++11 } } +// { dg-options "-Wno-terminate" } #include <exception> #include <cstdlib> diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept17.C b/gcc/testsuite/g++.dg/cpp0x/noexcept17.C index b27acef..9ea1623 100644 --- a/gcc/testsuite/g++.dg/cpp0x/noexcept17.C +++ b/gcc/testsuite/g++.dg/cpp0x/noexcept17.C @@ -1,5 +1,6 @@ // PR c++/50043 // { dg-do compile { target c++11 } } +// { dg-options "-Wno-terminate" } struct True1 {}; struct True2 { ~True2(); }; diff --git a/gcc/testsuite/g++.dg/eh/cond4.C b/gcc/testsuite/g++.dg/eh/cond4.C index a8d1cfb..4d312e4 100644 --- a/gcc/testsuite/g++.dg/eh/cond4.C +++ b/gcc/testsuite/g++.dg/eh/cond4.C @@ -12,7 +12,7 @@ void my_terminate () struct A { A(int) { } - ~A() { throw 1; }; + ~A() throw(int) { throw 1; }; }; struct B { B(A) { } diff --git a/gcc/testsuite/g++.dg/eh/ehopt1.C b/gcc/testsuite/g++.dg/eh/ehopt1.C index 163d76e..b2fb412 100644 --- a/gcc/testsuite/g++.dg/eh/ehopt1.C +++ b/gcc/testsuite/g++.dg/eh/ehopt1.C @@ -15,7 +15,7 @@ class A<int, int> public: A(int) { ++count; if (b) throw 1; } A(const A&) { ++count; if (b) throw 1; } - ~A() { --count; if (b) throw 1; } + ~A() throw(int) { --count; if (b) throw 1; } }; typedef A<int, int> B; @@ -26,7 +26,7 @@ class A<void *, void *> public: A() { if (b) throw 1; } A(const B&) { if (b) throw 1; } - ~A() { if (b) throw 1; } + ~A() throw(int) { if (b) throw 1; } }; typedef A<void *, void *> C; diff --git a/gcc/testsuite/g++.dg/eh/init-temp2.C b/gcc/testsuite/g++.dg/eh/init-temp2.C index 6a58dda..9cf8797 100644 --- a/gcc/testsuite/g++.dg/eh/init-temp2.C +++ b/gcc/testsuite/g++.dg/eh/init-temp2.C @@ -8,18 +8,18 @@ template <class _Tp> class AutoPtr public: explicit AutoPtr(_Tp* __p = 0) : _M_ptr(__p) {} - ~AutoPtr() { delete _M_ptr; } + ~AutoPtr() throw(int) { delete _M_ptr; } }; struct A { A() { } - ~A() { throw 1.0; } + ~A() throw(int) { throw 1; } }; struct B { - virtual ~B(); + virtual ~B() throw(int); }; B* f (const A &s) { throw 1; } diff --git a/gcc/testsuite/g++.dg/tm/noexcept-5.C b/gcc/testsuite/g++.dg/tm/noexcept-5.C index 4267432..e4d3f53 100644 --- a/gcc/testsuite/g++.dg/tm/noexcept-5.C +++ b/gcc/testsuite/g++.dg/tm/noexcept-5.C @@ -1,5 +1,5 @@ // { dg-do compile { target c++11 } } -// { dg-options "-fgnu-tm -O -fdump-tree-tmmark -fdump-tree-tmlower" } +// { dg-options "-fgnu-tm -O -fdump-tree-tmmark -fdump-tree-tmlower -Wno-terminate" } int global; diff --git a/gcc/testsuite/g++.dg/torture/pr49394.C b/gcc/testsuite/g++.dg/torture/pr49394.C index 67d521f..e471885 100644 --- a/gcc/testsuite/g++.dg/torture/pr49394.C +++ b/gcc/testsuite/g++.dg/torture/pr49394.C @@ -4,7 +4,7 @@ struct Mutex { bool locked; - ~Mutex () + ~Mutex () throw(int) { if (locked) throw 0; diff --git a/gcc/testsuite/g++.dg/warn/Wterminate1.C b/gcc/testsuite/g++.dg/warn/Wterminate1.C new file mode 100644 index 0000000..affb48d --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/Wterminate1.C @@ -0,0 +1,20 @@ +// In C++98 mode this gets a -Wc++11-compat warning, in C++11 mode a +// -Wterminate warning. + +// { dg-options "-Wall" } + +struct A +{ + ~A() + { + throw 1; // { dg-warning "terminate" } + } +}; + +int main() +{ + try { A a; } + catch (...) {} +} + + diff --git a/gcc/testsuite/g++.old-deja/g++.mike/eh25.C b/gcc/testsuite/g++.old-deja/g++.mike/eh25.C index fb492f7..f3728cf 100644 --- a/gcc/testsuite/g++.old-deja/g++.mike/eh25.C +++ b/gcc/testsuite/g++.old-deja/g++.mike/eh25.C @@ -10,7 +10,7 @@ void my_terminate() { struct A { A() { } - ~A() { + ~A() throw(int) { std::set_terminate (my_terminate); throw 1; // This throws from EH dtor, should call my_terminate } diff --git a/libstdc++-v3/testsuite/30_threads/lock_guard/cons/1.cc b/libstdc++-v3/testsuite/30_threads/lock_guard/cons/1.cc index 4219782a..6d99c27 100644 --- a/libstdc++-v3/testsuite/30_threads/lock_guard/cons/1.cc +++ b/libstdc++-v3/testsuite/30_threads/lock_guard/cons/1.cc @@ -27,7 +27,7 @@ struct Mutex { Mutex() : locked(false) { } - ~Mutex() + ~Mutex() throw(int) { if (locked) throw 0; diff --git a/libstdc++-v3/testsuite/util/replacement_memory_operators.h b/libstdc++-v3/testsuite/util/replacement_memory_operators.h index 0bfa3fc..06d955a 100644 --- a/libstdc++-v3/testsuite/util/replacement_memory_operators.h +++ b/libstdc++-v3/testsuite/util/replacement_memory_operators.h @@ -32,7 +32,7 @@ namespace __gnu_test counter() : _M_count(0), _M_throw(true) { } - ~counter() + ~counter() throw (counter_error) { if (_M_throw && _M_count != 0) throw counter_error(); |