LWG 2165, submitted by Jonathan, argues that declaring a defaulted
constructor noexcept should not be ill-formed if the implicitly-
declared constructor would not be noexcept. At the Chicago meeting, CWG
agreed. This patch makes it deleted instead.
The second hunk adds %X for printing an exception-specification in
diagnostics.
Tested x86_64-pc-linux-gnu, applying to trunk.
commit 785cdfa527c1481af08a31fb0f3c2489119b539c
Author: Jason Merrill <ja...@redhat.com>
Date: Tue Oct 22 16:17:31 2013 -0400
LWG 2165
* method.c (defaulted_late_check): Delete on eh-spec mismatch.
(maybe_explain_implicit_delete): Explain it.
diff --git a/gcc/cp/method.c b/gcc/cp/method.c
index 593a4a6..594a004 100644
--- a/gcc/cp/method.c
+++ b/gcc/cp/method.c
@@ -1466,13 +1466,34 @@ maybe_explain_implicit_delete (tree decl)
tree parms = FUNCTION_FIRST_USER_PARMTYPE (decl);
tree parm_type = TREE_VALUE (parms);
bool const_p = CP_TYPE_CONST_P (non_reference (parm_type));
+ tree raises = NULL_TREE;
+ bool deleted_p = false;
tree scope = push_scope (ctype);
- inform (0, "%q+#D is implicitly deleted because the default "
- "definition would be ill-formed:", decl);
- pop_scope (scope);
+
synthesized_method_walk (ctype, sfk, const_p,
- NULL, NULL, NULL, NULL, true,
+ &raises, NULL, &deleted_p, NULL, false,
DECL_INHERITED_CTOR_BASE (decl), parms);
+ if (deleted_p)
+ {
+ inform (0, "%q+#D is implicitly deleted because the default "
+ "definition would be ill-formed:", decl);
+ synthesized_method_walk (ctype, sfk, const_p,
+ NULL, NULL, NULL, NULL, true,
+ DECL_INHERITED_CTOR_BASE (decl), parms);
+ }
+ else if (!comp_except_specs
+ (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (decl)),
+ raises, ce_normal))
+ inform (DECL_SOURCE_LOCATION (decl), "%q#F is implicitly "
+ "deleted because its exception-specification does not "
+ "match the implicit exception-specification %qX",
+ decl, raises);
+#ifdef ENABLE_CHECKING
+ else
+ gcc_unreachable ();
+#endif
+
+ pop_scope (scope);
}
input_location = loc;
@@ -1782,9 +1803,10 @@ defaulted_late_check (tree fn)
eh_spec, ce_normal))
{
if (DECL_DEFAULTED_IN_CLASS_P (fn))
- error ("function %q+D defaulted on its first declaration "
- "with an exception-specification that differs from "
- "the implicit declaration %q#D", fn, implicit_fn);
+ {
+ DECL_DELETED_FN (fn) = true;
+ eh_spec = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn));
+ }
else
error ("function %q+D defaulted on its redeclaration "
"with an exception-specification that differs from "
diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted23.C b/gcc/testsuite/g++.dg/cpp0x/defaulted23.C
index 319cb39..be2fd2f 100644
--- a/gcc/testsuite/g++.dg/cpp0x/defaulted23.C
+++ b/gcc/testsuite/g++.dg/cpp0x/defaulted23.C
@@ -6,22 +6,32 @@ struct A
A() noexcept = default;
};
+A a;
+
struct B
{
- B() throw (int) = default; // { dg-error "exception-specification that differs from the implicit declaration" }
+ B() throw (int) = default; // { dg-message "exception-specification" }
};
+B b; // { dg-error "deleted" }
+
struct C
{
C() throw (int) { }
};
+C c;
+
struct D: C
{
D() throw (int) = default;
};
+D d;
+
struct E
{
E() = default;
};
+
+E e;
diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted43.C b/gcc/testsuite/g++.dg/cpp0x/defaulted43.C
index e1c2b72..f2846fe 100644
--- a/gcc/testsuite/g++.dg/cpp0x/defaulted43.C
+++ b/gcc/testsuite/g++.dg/cpp0x/defaulted43.C
@@ -7,6 +7,8 @@ struct T
~T() noexcept(false) { }
};
+T t;
+
struct A
{
A() noexcept;
@@ -24,6 +26,8 @@ struct U
~U() noexcept(false) { }
};
+U u;
+
struct B
{
B() noexcept(false);
@@ -35,16 +39,22 @@ struct B
B::B() noexcept(false) = default;
B::~B() noexcept(false) = default;
+B b;
+
struct V
{
V() noexcept(false) { }
~V() noexcept(false) { }
};
+V v;
+
struct C
{
- C() noexcept = default; // { dg-error "defaulted" }
- ~C() noexcept = default; // { dg-error "defaulted" }
+ C() noexcept = default; // { dg-message "exception-specification" }
+ ~C() noexcept = default; // { dg-message "exception-specification" }
V v;
};
+
+C c; // { dg-error "deleted" }
commit cc95ba6f007d4b15a40b2da5d9e7ee65a276b738
Author: Jason Merrill <ja...@redhat.com>
Date: Tue Oct 22 16:15:32 2013 -0400
c-family/
* c-format.c (gcc_cxxdiag_char_table): Add %X.
cp/
* error.c (eh_spec_to_string): New.
(cp_printer): Use it for %X.
diff --git a/gcc/c-family/c-format.c b/gcc/c-family/c-format.c
index c11d93a..f0371d3 100644
--- a/gcc/c-family/c-format.c
+++ b/gcc/c-family/c-format.c
@@ -721,7 +721,7 @@ static const format_char_info gcc_cxxdiag_char_table[] =
/* Custom conversion specifiers. */
/* These will require a "tree" at runtime. */
- { "ADEFKSTV",0,STD_C89,{ T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q+#", "", NULL },
+ { "ADEFKSTVX",0,STD_C89,{ T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q+#", "", NULL },
{ "v", 0,STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q#", "", NULL },
diff --git a/gcc/cp/error.c b/gcc/cp/error.c
index 3f6f594..5f997c3 100644
--- a/gcc/cp/error.c
+++ b/gcc/cp/error.c
@@ -2998,6 +2998,15 @@ cv_to_string (tree p, int v)
return pp_ggc_formatted_text (cxx_pp);
}
+static const char *
+eh_spec_to_string (tree p, int /*v*/)
+{
+ int flags = 0;
+ reinit_cxx_pp ();
+ dump_exception_spec (cxx_pp, p, flags);
+ return pp_ggc_formatted_text (cxx_pp);
+}
+
/* Langhook for print_error_function. */
void
cxx_print_error_function (diagnostic_context *context, const char *file,
@@ -3379,8 +3388,10 @@ maybe_print_constexpr_context (diagnostic_context *context)
%O binary operator.
%P function parameter whose position is indicated by an integer.
%Q assignment operator.
+ %S substitution (template + args)
%T type.
- %V cv-qualifier. */
+ %V cv-qualifier.
+ %X exception-specification. */
static bool
cp_printer (pretty_printer *pp, text_info *text, const char *spec,
int precision, bool wide, bool set_locus, bool verbose)
@@ -3427,6 +3438,7 @@ cp_printer (pretty_printer *pp, text_info *text, const char *spec,
case 'S': result = subst_to_string (next_tree); break;
case 'T': result = type_to_string (next_tree, verbose); break;
case 'V': result = cv_to_string (next_tree, verbose); break;
+ case 'X': result = eh_spec_to_string (next_tree, verbose); break;
case 'K':
percent_K_format (text);