aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2010-06-16 11:45:36 -0400
committerJason Merrill <jason@gcc.gnu.org>2010-06-16 11:45:36 -0400
commit59f9c2ed530507a5dcaaf4c6d3789b908dc3dfa6 (patch)
treed0cfe8570eb95b543a4e2033811af7af2bda6204 /gcc
parent7c69566f11b2361bcfac2c53e385a271792d09f2 (diff)
downloadgcc-59f9c2ed530507a5dcaaf4c6d3789b908dc3dfa6.zip
gcc-59f9c2ed530507a5dcaaf4c6d3789b908dc3dfa6.tar.gz
gcc-59f9c2ed530507a5dcaaf4c6d3789b908dc3dfa6.tar.bz2
c.opt: Add -Wnoexcept.
* c.opt: Add -Wnoexcept. * except.c (check_noexcept_r): Return the problematic function. (finish_noexcept_expr): Give -Wnoexcept warning. Add complain parm. * pt.c (tsubst_copy_and_build): Pass it. * parser.c (cp_parser_unary_expression): Likewise. * cp-tree.h: Adjust prototype. From-SVN: r160842
Diffstat (limited to 'gcc')
-rw-r--r--gcc/c-family/ChangeLog4
-rw-r--r--gcc/c-family/c.opt4
-rw-r--r--gcc/cp/ChangeLog6
-rw-r--r--gcc/cp/cp-tree.h2
-rw-r--r--gcc/cp/except.c39
-rw-r--r--gcc/cp/parser.c2
-rw-r--r--gcc/cp/pt.c2
-rw-r--r--gcc/doc/invoke.texi10
-rw-r--r--gcc/testsuite/ChangeLog2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/noexcept03.C6
10 files changed, 58 insertions, 19 deletions
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog
index 433d699..8c7eed1 100644
--- a/gcc/c-family/ChangeLog
+++ b/gcc/c-family/ChangeLog
@@ -1,3 +1,7 @@
+2010-06-16 Jason Merrill <jason@redhat.com>
+
+ * c.opt: Add -Wnoexcept.
+
2010-06-16 Richard Guenther <rguenther@suse.de>
PR c/44555
diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index 5122e1a..0517d35 100644
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -341,6 +341,10 @@ Wnested-externs
C ObjC Var(warn_nested_externs) Warning
Warn about \"extern\" declarations not at file scope
+Wnoexcept
+C++ ObjC++ Var(warn_noexcept) Warning
+Warn when a noexcept expression evaluates to true even though the expression can't actually throw
+
Wnon-template-friend
C++ ObjC++ Var(warn_nontemplate_friend) Init(1) Warning
Warn when non-templatized friend functions are declared within a template
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 37a3544..8402afd 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,11 @@
2010-06-16 Jason Merrill <jason@redhat.com>
+ * except.c (check_noexcept_r): Return the problematic function.
+ (finish_noexcept_expr): Give -Wnoexcept warning. Add complain parm.
+ * pt.c (tsubst_copy_and_build): Pass it.
+ * parser.c (cp_parser_unary_expression): Likewise.
+ * cp-tree.h: Adjust prototype.
+
* method.c (defaulted_late_check): Give the defaulted method
the same exception specification as the implicit declaration.
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index b71f8af..f63ec2e 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -4845,7 +4845,7 @@ extern tree build_exc_ptr (void);
extern tree build_throw (tree);
extern int nothrow_libfn_p (const_tree);
extern void check_handlers (tree);
-extern tree finish_noexcept_expr (tree);
+extern tree finish_noexcept_expr (tree, tsubst_flags_t);
extern bool nothrow_spec_p (const_tree);
extern bool type_noexcept_p (const_tree);
extern bool type_throw_all_p (const_tree);
diff --git a/gcc/cp/except.c b/gcc/cp/except.c
index c682c8d..64f4171 100644
--- a/gcc/cp/except.c
+++ b/gcc/cp/except.c
@@ -1028,20 +1028,22 @@ check_noexcept_r (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED,
We could use TREE_NOTHROW (t) for !TREE_PUBLIC fns, though... */
tree fn = (code == AGGR_INIT_EXPR
? AGGR_INIT_EXPR_FN (t) : CALL_EXPR_FN (t));
+ tree type = TREE_TYPE (TREE_TYPE (fn));
+
+ STRIP_NOPS (fn);
if (TREE_CODE (fn) == ADDR_EXPR)
{
/* We do use TREE_NOTHROW for ABI internals like __dynamic_cast,
and for C library functions known not to throw. */
- tree fn2 = TREE_OPERAND (fn, 0);
- if (TREE_CODE (fn2) == FUNCTION_DECL
- && DECL_EXTERN_C_P (fn2)
- && (DECL_ARTIFICIAL (fn2)
- || nothrow_libfn_p (fn2)))
- return TREE_NOTHROW (fn2) ? NULL_TREE : t;
+ fn = TREE_OPERAND (fn, 0);
+ if (TREE_CODE (fn) == FUNCTION_DECL
+ && DECL_EXTERN_C_P (fn)
+ && (DECL_ARTIFICIAL (fn)
+ || nothrow_libfn_p (fn)))
+ return TREE_NOTHROW (fn) ? NULL_TREE : fn;
}
- fn = TREE_TYPE (TREE_TYPE (fn));
- if (!TYPE_NOTHROW_P (fn))
- return t;
+ if (!TYPE_NOTHROW_P (type))
+ return fn;
}
return NULL_TREE;
@@ -1050,13 +1052,26 @@ check_noexcept_r (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED,
/* Evaluate noexcept ( EXPR ). */
tree
-finish_noexcept_expr (tree expr)
+finish_noexcept_expr (tree expr, tsubst_flags_t complain)
{
+ tree fn;
+
if (processing_template_decl)
return build_min (NOEXCEPT_EXPR, boolean_type_node, expr);
- if (cp_walk_tree_without_duplicates (&expr, check_noexcept_r, 0))
- return boolean_false_node;
+ fn = cp_walk_tree_without_duplicates (&expr, check_noexcept_r, 0);
+ if (fn)
+ {
+ if ((complain & tf_warning) && TREE_CODE (fn) == FUNCTION_DECL
+ && TREE_NOTHROW (fn) && !DECL_ARTIFICIAL (fn))
+ {
+ warning (OPT_Wnoexcept, "noexcept-expression evaluates to %<false%> "
+ "because of a call to %qD", fn);
+ warning (OPT_Wnoexcept, "but %q+D does not throw; perhaps "
+ "it should be declared %<noexcept%>", fn);
+ }
+ return boolean_false_node;
+ }
else
return boolean_true_node;
}
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 0a7006a..c6f8d7e 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -5883,7 +5883,7 @@ cp_parser_unary_expression (cp_parser *parser, bool address_p, bool cast_p,
parser->type_definition_forbidden_message = saved_message;
cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
- return finish_noexcept_expr (expr);
+ return finish_noexcept_expr (expr, tf_warning_or_error);
}
default:
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 55ea539..b97d3f5 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -12259,7 +12259,7 @@ tsubst_copy_and_build (tree t,
/*integral_constant_expression_p=*/false);
--cp_unevaluated_operand;
--c_inhibit_evaluation_warnings;
- return finish_noexcept_expr (op1);
+ return finish_noexcept_expr (op1, complain);
case MODOP_EXPR:
{
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 9e517e9..34acfbc 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -196,7 +196,7 @@ in the following sections.
-fno-default-inline -fvisibility-inlines-hidden @gol
-fvisibility-ms-compat @gol
-Wabi -Wconversion-null -Wctor-dtor-privacy @gol
--Wnon-virtual-dtor -Wreorder @gol
+-Wnoexcept -Wnon-virtual-dtor -Wreorder @gol
-Weffc++ -Wstrict-null-sentinel @gol
-Wno-non-template-friend -Wold-style-cast @gol
-Woverloaded-virtual -Wno-pmf-conversions @gol
@@ -2282,6 +2282,14 @@ Warn when a class seems unusable because all the constructors or
destructors in that class are private, and it has neither friends nor
public static member functions.
+@item -Wnoexcept @r{(C++ and Objective-C++ only)}
+@opindex Wnoexcept
+@opindex Wno-noexcept
+Warn when a noexcept-expression evaluates to false because of a call
+to a function that does not have a non-throwing exception
+specification (i.e. @samp{throw()} or @samp{noexcept}) but is known by
+the compiler to never throw an exception.
+
@item -Wnon-virtual-dtor @r{(C++ and Objective-C++ only)}
@opindex Wnon-virtual-dtor
@opindex Wno-non-virtual-dtor
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index b06e381..d9ddc0b 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,5 +1,7 @@
2010-06-16 Jason Merrill <jason@redhat.com>
+ * g++.dg/cpp0x/noexcept03.C: Test -Wnoexcept.
+
* g++.dg/cpp0x/noexcept01.C: Test defaulted fns.
2010-06-16 Richard Guenther <rguenther@suse.de>
diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept03.C b/gcc/testsuite/g++.dg/cpp0x/noexcept03.C
index d992245..c759f6f 100644
--- a/gcc/testsuite/g++.dg/cpp0x/noexcept03.C
+++ b/gcc/testsuite/g++.dg/cpp0x/noexcept03.C
@@ -1,5 +1,5 @@
// Runtime test for noexcept-specification.
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++0x -Wnoexcept" }
// { dg-do run }
#include <exception>
@@ -23,7 +23,7 @@ void f () noexcept (false)
}
template <class T>
-void f(T) noexcept (noexcept (T()))
+void f(T) noexcept (noexcept (T())) // { dg-warning "false" }
{
p();
}
@@ -34,7 +34,7 @@ void f2(T a) noexcept (noexcept (f (a)))
f(a);
}
-struct A { A() { } };
+struct A { A() { } }; // { dg-warning "does not throw" }
// throw(int) overrides noexcept(false) in either order.
void h() throw (int, std::bad_exception);