commit d5a95e55cff9bc03308ec27f05988146d9aadb43
Author: Jason Merrill <jason@redhat.com>
Date: Tue Jun 15 21:42:03 2010 -0400
* method.c (defaulted_late_check): Give the defaulted method
the same exception specification as the implicit declaration.
@@ -1022,6 +1022,15 @@ defaulted_late_check (tree fn)
error_at (DECL_SOURCE_LOCATION (fn),
"does not match expected signature %qD", implicit_fn);
}
+
+ /* 8.4.2/2: If it is explicitly defaulted on its first declaration, it is
+ implicitly considered to have the same exception-specification as if
+ it had been implicitly declared. */
+ if (DECL_DEFAULTED_IN_CLASS_P (fn))
+ {
+ tree eh_spec = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (implicit_fn));
+ TREE_TYPE (fn) = build_exception_variant (TREE_TYPE (fn), eh_spec);
+ }
}
/* Returns true iff FN can be explicitly defaulted, and gives any
@@ -59,6 +59,14 @@ struct F
SA (noexcept (F()));
+struct G
+{
+ G() = default;
+ ~G() = default;
+};
+
+SA (noexcept (G()));
+
template <class T, bool b>
void tf()
{
commit 6ccf227626b3ac9a09f5061daf2cece776c0be7c
Author: Jason Merrill <jason@redhat.com>
Date: Wed Jun 16 11:30:02 2010 -0400
* 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.
@@ -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
@@ -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);
@@ -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;
}
@@ -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:
@@ -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:
{
@@ -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
@@ -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);