Patchwork C++/24314

login
register
mail settings
Submitter Paolo Carlini
Date Sept. 7, 2012, 10:02 p.m.
Message ID <504A6EF5.5010909@oracle.com>
Download mbox | patch
Permalink /patch/182468/
State New
Headers show

Comments

Paolo Carlini - Sept. 7, 2012, 10:02 p.m.
Hi,

On 09/07/2012 11:36 PM, Jason Merrill wrote:
> On 09/07/2012 05:07 PM, Paolo Carlini wrote:
>> the regression of template/crash83.C because of excess errors. The 
>> latter happens because we have code in cp_parser_class_head which 
>> tries to improve error recovery for cases of missing 'template <>' in 
>> explicit specializations, and, for that rather broken testcase, it 
>> confuses the code I'm tentatively adding, resulting in the additional 
>> error message below:
>>
>> crash83.C:5:27: error: an explicit specialization must be preceded by 
>> ‘template <>’
>>  template<typename = class A<0>: > struct B {}; // { dg-error 
>> "explicit specialization|expected" }
>>                            ^
>> crash83.C:5:27: error: too many template-parameter-lists for A<0> 
>> (should be 1)
>
> So we're adding a second irrelevant diagnostic to go with the first 
> one.  The error in this testcase is a simple stray ':' causing a 
> syntax error, it has nothing to do with explicit specialization.  It 
> would be nice to improve this, but given that we're already not giving 
> the right error, adding a second wrong error doesn't seem like a big 
> problem.
Yeah. I wasn't particularly worried by that regression.
>
>> More importantly, I'm having troubles removing the early
>> cp_parser_check_template_parameters check in cp_parser_class_head: one
>> issue is that it also checks for too few template-parameter-lists not
>> just too many, and thus catches rather broken testcases like, eg,
>> template/error7.C or template/class2.C:
>>
>> template <class T>
>> struct A {
>>    struct B;
>>    struct A::B { }; // { dg-error "" }
>> };
>
> This testcase is indeed ill-formed, but its ill-formedness has nothing 
> to do with too few template-parameter-lists.  The problem is that 
> clause 9 says
>
> If a class-head-name contains a nested-name-specifier, the 
> class-specifier shall refer to a class that was previously declared 
> directly in the class or namespace to which the nested-name-specifier 
> refers, ... and the class-specifier shall appear in a namespace 
> enclosing the previous declaration.
>
> The definition of A::B does not appear at namespace scope, so it is 
> ill-formed.  Removing the incorrect error is an improvement, but then 
> we need to add the correct error rather than accept the testcase.
>
>> but there are definitely more problems with just checking
>> template_header_count < wanted too in
>> maybe_process_partial_specialization and removing the early check, I'm
>> seeing many, many fails if I just try to extend "p4" like that...
>
> Like what?
Like a nightmare ;) If I run the testsuite with the attached "p5" a lot 
is broken, with template templates, variadic templates, we have all sort 
of problems. The below is just the beginning, template/pr39425.C times 
out. I think we need something radically different / radically more complex.

Paolo.

////////////////////////

FAIL: g++.dg/abi/mangle34.C -std=c++98 (test for excess errors)
FAIL: g++.dg/abi/mangle34.C -std=c++11 (test for excess errors)
FAIL: g++.dg/cpp0x/initlist48.C (test for excess errors)
FAIL: g++.dg/cpp0x/lambda/lambda-pass.C (test for excess errors)
WARNING: g++.dg/cpp0x/lambda/lambda-pass.C compilation failed to produce 
executable
FAIL: g++.dg/cpp0x/lambda/lambda-recursive.C (test for excess errors)
WARNING: g++.dg/cpp0x/lambda/lambda-recursive.C compilation failed to 
produce executable
FAIL: g++.dg/cpp0x/lambda/lambda-std-function.C (test for excess errors)
WARNING: g++.dg/cpp0x/lambda/lambda-std-function.C compilation failed to 
produce executable
FAIL: g++.dg/cpp0x/pr31993.C (test for excess errors)
FAIL: g++.dg/cpp0x/pr38646.C (test for excess errors)
FAIL: g++.dg/cpp0x/pr47416.C (test for excess errors)
FAIL: g++.dg/cpp0x/variadic-104.C (test for excess errors)
FAIL: g++.dg/cpp0x/variadic-crash1.C (test for excess errors)
FAIL: g++.dg/cpp0x/variadic-lambda.C (test for excess errors)
FAIL: g++.dg/cpp0x/variadic129.C -std=c++11 (test for excess errors)
FAIL: g++.dg/cpp0x/variadic132.C -std=c++11 (test for excess errors)
FAIL: g++.dg/cpp0x/variadic19.C (test for excess errors)
FAIL: g++.dg/cpp0x/variadic20.C  (test for errors, line 16)
FAIL: g++.dg/cpp0x/variadic20.C  (test for errors, line 27)
FAIL: g++.dg/cpp0x/variadic20.C  (test for errors, line 34)
FAIL: g++.dg/cpp0x/variadic20.C bound (test for errors, line 40)
FAIL: g++.dg/cpp0x/variadic20.C bound (test for errors, line 42)
FAIL: g++.dg/cpp0x/variadic20.C incomplete (test for errors, line 40)
FAIL: g++.dg/cpp0x/variadic20.C incomplete (test for errors, line 42)
FAIL: g++.dg/cpp0x/variadic20.C (test for excess errors)
FAIL: g++.dg/cpp0x/variadic26.C (test for excess errors)
FAIL: g++.dg/cpp0x/variadic84.C (test for excess errors)
FAIL: g++.dg/cpp0x/variadic85.C (test for excess errors)
FAIL: g++.dg/cpp0x/variadic86.C (test for excess errors)
FAIL: g++.dg/cpp0x/variadic87.C (test for excess errors)
FAIL: g++.dg/cpp0x/variadic89.C (test for excess errors)
FAIL: g++.dg/ext/attrib9.C -std=c++98 (test for excess errors)
FAIL: g++.dg/ext/attrib9.C -std=c++11 (test for excess errors)
FAIL: g++.dg/ext/complex4.C -std=c++11 (test for excess errors)
FAIL: g++.dg/init/new18.C -std=gnu++11 (test for excess errors)
FAIL: g++.dg/opt/pr30965.C -std=gnu++98 (test for excess errors)
FAIL: g++.dg/opt/pr30965.C -std=gnu++11 (test for excess errors)
FAIL: g++.dg/opt/pr47615.C -std=gnu++98 (test for excess errors)
FAIL: g++.dg/opt/pr47615.C -std=gnu++11 (test for excess errors)
FAIL: g++.dg/other/crash-10.C -std=c++98 (test for excess errors)
FAIL: g++.dg/other/crash-10.C -std=c++11 (test for excess errors)
FAIL: g++.dg/other/crash-11.C -std=c++98 (test for excess errors)
FAIL: g++.dg/other/crash-11.C -std=c++11 (test for excess errors)
FAIL: g++.dg/template/class2.C -std=c++98  (test for errors, line 6)
FAIL: g++.dg/template/class2.C -std=c++11  (test for errors, line 6)
FAIL: g++.dg/template/crash104.C -std=c++98  (test for errors, line 25)
FAIL: g++.dg/template/crash104.C -std=c++98 (test for excess errors)
FAIL: g++.dg/template/crash104.C -std=c++11  (test for errors, line 25)
FAIL: g++.dg/template/crash104.C -std=c++11 (test for excess errors)
FAIL: g++.dg/template/crash83.C -std=c++98 (test for excess errors)
FAIL: g++.dg/template/crash83.C -std=c++11 (test for excess errors)
FAIL: g++.dg/template/crash95.C -std=c++98  (test for errors, line 11)
FAIL: g++.dg/template/crash95.C -std=c++98 (test for excess errors)
FAIL: g++.dg/template/crash95.C -std=c++11  (test for errors, line 11)
FAIL: g++.dg/template/crash95.C -std=c++11 (test for excess errors)
FAIL: g++.dg/template/ctor4.C -std=c++98 (test for excess errors)
FAIL: g++.dg/template/ctor4.C -std=c++11 (test for excess errors)
FAIL: g++.dg/template/defarg11.C -std=c++98 (test for excess errors)
FAIL: g++.dg/template/defarg11.C -std=c++11 (test for excess errors)
FAIL: g++.dg/template/error7.C -std=gnu++98 (internal compiler error)
FAIL: g++.dg/template/error7.C -std=gnu++98  (test for errors, line 5)
FAIL: g++.dg/template/error7.C -std=gnu++98  (test for errors, line 6)
FAIL: g++.dg/template/error7.C -std=gnu++98 (test for excess errors)
FAIL: g++.dg/template/error7.C -std=gnu++11 (internal compiler error)
FAIL: g++.dg/template/error7.C -std=gnu++11  (test for errors, line 5)
FAIL: g++.dg/template/error7.C -std=gnu++11  (test for errors, line 6)
FAIL: g++.dg/template/error7.C -std=gnu++11 (test for excess errors)
FAIL: g++.dg/template/mem-partial1.C -std=c++98 (test for excess errors)
FAIL: g++.dg/template/mem-partial1.C -std=c++11 (test for excess errors)
FAIL: g++.dg/template/mem-partial2.C -std=c++98 (test for excess errors)
WARNING: g++.dg/template/mem-partial2.C -std=c++98 compilation failed to 
produce executable
FAIL: g++.dg/template/mem-partial2.C -std=c++11 (test for excess errors)
WARNING: g++.dg/template/mem-partial2.C -std=c++11 compilation failed to 
produce executable
FAIL: g++.dg/template/mem-partial3.C -std=c++98 (test for excess errors)
FAIL: g++.dg/template/mem-partial3.C -std=c++11 (test for excess errors)
FAIL: g++.dg/template/partial13.C -std=c++98 (test for excess errors)
FAIL: g++.dg/template/partial13.C -std=c++11 (test for excess errors)
FAIL: g++.dg/template/partial2.C -std=c++98 (test for excess errors)
FAIL: g++.dg/template/partial2.C -std=c++11 (test for excess errors)
FAIL: g++.dg/template/partial4.C -std=c++98 (test for excess errors)
FAIL: g++.dg/template/partial4.C -std=c++11 (test for excess errors)
WARNING: program timed out.
FAIL: g++.dg/template/pr39425.C -std=c++98  (test for errors, line 18)
FAIL: g++.dg/template/pr39425.C -std=c++98 (test for excess errors)

Patch

Index: pt.c
===================================================================
--- pt.c	(revision 191082)
+++ pt.c	(working copy)
@@ -835,6 +835,19 @@  maybe_process_partial_specialization (tree type)
 	  && !COMPLETE_TYPE_P (type))
 	{
 	  check_specialization_namespace (CLASSTYPE_TI_TEMPLATE (type));
+
+	  int wanted = num_template_headers_for_class (type);
+	  if (template_header_count != wanted)
+	    {
+	      if (template_header_count > wanted)
+		error ("too many template-parameter-lists for %E "
+		       "(should be %d)", type, wanted);
+	      else
+		error ("too few template-parameter-lists for %E "
+		       "(should be %d)", type, wanted);
+	      return error_mark_node;
+	    }
+
 	  SET_CLASSTYPE_TEMPLATE_SPECIALIZATION (type);
 	  if (processing_template_decl)
 	    {
@@ -882,6 +895,18 @@  maybe_process_partial_specialization (tree type)
 	  tree t;
 	  tree tmpl = CLASSTYPE_TI_TEMPLATE (type);
 
+	  int wanted = num_template_headers_for_class (type);
+	  if (template_header_count != wanted)
+	    {
+	      if (template_header_count > wanted)
+		error ("too many template-parameter-lists for %E "
+		       "(should be %d)", type, wanted);
+	      else
+		error ("too few template-parameter-lists for %E "
+		       "(should be %d)", type, wanted);
+	      return error_mark_node;
+	    }
+
 	  if (current_namespace
 	      != decl_namespace_context (tmpl))
 	    {
Index: parser.c
===================================================================
--- parser.c	(revision 191082)
+++ parser.c	(working copy)
@@ -18528,7 +18528,7 @@  cp_parser_class_head (cp_parser* parser,
      use "goto done;" to return.  */
   /* Make sure that the right number of template parameters were
      present.  */
-  if (!cp_parser_check_template_parameters (parser, num_templates,
+  if (0 && !cp_parser_check_template_parameters (parser, num_templates,
 					    type_start_token->location,
 					    /*declarator=*/NULL))
     {