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
This commit is contained in:
Jason Merrill 2010-06-16 11:45:36 -04:00 committed by Jason Merrill
parent 7c69566f11
commit 59f9c2ed53
10 changed files with 58 additions and 19 deletions

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -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);

View File

@ -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;
}

View File

@ -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:

View File

@ -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:
{

View File

@ -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

View File

@ -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>

View File

@ -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);