Hi again,
On 07/14/2015 05:43 PM, Paolo Carlini wrote:
Hi,
On 07/14/2015 05:07 PM, Jason Merrill wrote:
On 07/13/2015 09:41 AM, Paolo Carlini wrote:
+++ testsuite/g++.dg/template/crash81.C (working copy)
@@ -3,6 +3,6 @@
struct A
{
template<T::X> struct X; // { dg-error "'T' has not been
declared" "T" }
- // { dg-error "declaration of 'template<int X> struct A::X'"
"A::X" { target *-*-* } 5 }
- // { dg-error "shadows template parm 'int X'" "shadow" { target
*-*-* } 5 }
+ // { dg-error "declaration of 'template<int X> struct A::X'
shadows" "A::X" { target *-*-* } 5 }
+ // { dg-message "template parameter 'X'" "" { target *-*-* } 5 }
I don't see any reason to check for specific diagnostics here; the
latter two messages are poor error-recovery, not something to test for.
Indeed, I noticed the error recovery issue, which I didn't know, and
considered looking into it, when I'm done with some other things. In
the meanwhile I'm shortening the expected error/inform.
I had a look and tried various things... Ultimately the issue is due to
the type_was_error_mark_node becomes integer_type_node trick in
grokdeclarator (which I don't like that much ;) Thus for this testcase
the latter simply returns a PARM_DECL of that type and no trace remains
of the error, then the following bad error recovery. Now,
cp_parser_template_parameter knows how to handle error_mark_node thus in
principle we should be able to just return it and be done. The only
problem with that, testsuite-wise, is the very broken cpp/pr64127.C
which ends up regressing, since we emit a spurious additional error
about "default argument for template parameter for class enclosing" from
check_default_tmpl_args. Note that for this specific testcase
grokdeclarator gets also a null declarator thus for it isn't the same if
grokdeclarator returns error_mark_node immediately or just sets type =
error_mark_node at the beginning (which results in grokdeclarator not
returning an error_mark_node, instead a PARM_DECL with error_mark_node
as type).
Thus I have two different proposals: 1- More conservative, just set type
= error_mark_node instead of integer_type_node when we have a template
parameter; 2- Return error_mark_node immediately and adjust
check_default_tmpl_args to cope correctly with pr64127.C.
Thanks!
Paolo.
Index: cp/decl.c
===================================================================
--- cp/decl.c (revision 226028)
+++ cp/decl.c (working copy)
@@ -9315,7 +9315,10 @@ grokdeclarator (const cp_declarator *declarator,
warning (OPT_Wreturn_type,
"ISO C++ forbids declaration of %qs with no type", name);
- type = integer_type_node;
+ if (type_was_error_mark_node && template_parm_flag)
+ type = error_mark_node;
+ else
+ type = integer_type_node;
}
ctype = NULL_TREE;
Index: testsuite/g++.dg/template/crash81.C
===================================================================
--- testsuite/g++.dg/template/crash81.C (revision 226028)
+++ testsuite/g++.dg/template/crash81.C (working copy)
@@ -2,6 +2,5 @@
struct A
{
- template<T::X> struct X; // { dg-error "'T' has not been declared" "T" }
- // { dg-bogus "declaration" "" { xfail *-*-* } 5 }
+ template<T::X> struct X; // { dg-error "'T' has not been declared" }
};
Index: cp/decl.c
===================================================================
--- cp/decl.c (revision 226028)
+++ cp/decl.c (working copy)
@@ -9303,7 +9303,13 @@ grokdeclarator (const cp_declarator *declarator,
&& current_namespace == global_namespace);
if (type_was_error_mark_node)
- /* We've already issued an error, don't complain more. */;
+ {
+ /* We've already issued an error, don't complain more. */
+ if (template_parm_flag)
+ /* Just return the error_mark_node, cp_parser_template_parameter
+ knows how to handle it. */
+ return error_mark_node;
+ }
else if (in_system_header_at (input_location) || flag_ms_extensions)
/* Allow it, sigh. */;
else if (! is_main)
Index: cp/pt.c
===================================================================
--- cp/pt.c (revision 226028)
+++ cp/pt.c (working copy)
@@ -4704,9 +4704,14 @@ check_default_tmpl_args (tree decl, tree parms, bo
ntparms = TREE_VEC_LENGTH (inner_parms);
for (i = 0; i < ntparms; ++i)
{
- if (TREE_VEC_ELT (inner_parms, i) == error_mark_node)
+ tree parm = TREE_VEC_ELT (inner_parms, i);
+
+ if (parm == error_mark_node)
continue;
+ if (TREE_PURPOSE (parm) == error_mark_node)
+ continue;
+
if (TREE_PURPOSE (TREE_VEC_ELT (inner_parms, i)))
{
if (msg)
Index: testsuite/g++.dg/template/crash81.C
===================================================================
--- testsuite/g++.dg/template/crash81.C (revision 226028)
+++ testsuite/g++.dg/template/crash81.C (working copy)
@@ -2,6 +2,5 @@
struct A
{
- template<T::X> struct X; // { dg-error "'T' has not been declared" "T" }
- // { dg-bogus "declaration" "" { xfail *-*-* } 5 }
+ template<T::X> struct X; // { dg-error "'T' has not been declared" }
};