Hi,
in this error recovery regression, we ICE only when optimizing, while
building the cgraph. Avoiding the reported problem seems easy, just
check the return value of duplicate_decls in start_decl and immediately
return back error_mark_node. However, while working on the issue, I
noticed something slightly more interesting, IMO: we have, after the
relevant duplicate_decls call:
- if (decl_spec_seq_has_spec_p (declspecs, ds_constexpr)
- && !DECL_DECLARED_CONSTEXPR_P (field))
- error ("%qD declared %<constexpr%> outside its class",
field);
which I propose to remove. In fact - something I didn't really know -
for well formed user code, duplicate_decls, near the end, does some
memcpys which mean that its second argument (would be 'field' in the
start_decl section we are looking at) is adjusted to have a
DECL_DECLARED_CONSTEXPR_P consistent with its first argument. That's of
course because we want to accept snippets like:
struct A
{
static const int x;
};
constexpr int A::x = 0;
In turn that means the error above is issued only when something went
wrong in duplicate_decls in the first place. Thus the above error seems
at least verbose. However, here in start_decl we are only handling VAR_P
(decl), thus I don't think the message above even makes sense and could
be misleading, given snippets like the above. Therefore, I propose to
remove the diagnostic entirely, which overall also simplifies a patch
dealing with c++/70621. The below passes testing as-is on x86_64-linux.
Thanks, Paolo.
////////////////////////
/cp
2017-29-08 Paolo Carlini <paolo.carl...@oracle.com>
PR c++/70621
* decl.c (start_decl): Early return error_mark_node if duplicate_decls
returns it; avoid misleading error message.
/testsuite
2017-29-08 Paolo Carlini <paolo.carl...@oracle.com>
PR c++/70621
* g++.dg/torture/pr70621.C: New.
Index: cp/decl.c
===================================================================
--- cp/decl.c (revision 251375)
+++ cp/decl.c (working copy)
@@ -5023,11 +5023,12 @@ start_decl (const cp_declarator *declarator,
about this situation, and so we check here. */
if (initialized && DECL_INITIALIZED_IN_CLASS_P (field))
error ("duplicate initialization of %qD", decl);
- if (duplicate_decls (decl, field, /*newdecl_is_friend=*/false))
+ field = duplicate_decls (decl, field,
+ /*newdecl_is_friend=*/false);
+ if (field == error_mark_node)
+ return error_mark_node;
+ else if (field)
decl = field;
- if (decl_spec_seq_has_spec_p (declspecs, ds_constexpr)
- && !DECL_DECLARED_CONSTEXPR_P (field))
- error ("%qD declared %<constexpr%> outside its class", field);
}
}
else
Index: testsuite/g++.dg/torture/pr70621.C
===================================================================
--- testsuite/g++.dg/torture/pr70621.C (revision 0)
+++ testsuite/g++.dg/torture/pr70621.C (working copy)
@@ -0,0 +1,13 @@
+float foo();
+
+struct A
+{
+ static float x; // { dg-message "previous declaration" }
+};
+
+double A::x = foo(); // { dg-error "conflicting declaration" }
+
+void bar()
+{
+ A::x = 0;
+}