diff mbox

[C++,Patch/RFC] PR 77752

Message ID 82a3fdf8-74ac-a15e-d1ef-b85782b6055f@oracle.com
State New
Headers show

Commit Message

Paolo Carlini March 10, 2017, 10:38 p.m. UTC
Hi,

On 10/03/2017 16:57, Jason Merrill wrote:
> On Fri, Mar 10, 2017 at 9:58 AM, Paolo Carlini <paolo.carlini@oracle.com> wrote:
>> As such, the broken declaration cannot be rejected by the code we have in
>> finish_struct, something must happen earlier than that. It seems to me that
>> xref_tag_1 can be a good place, per the below patchlet, which passes testing
>> on x86_64-linux. I briefly wondered if making is_std_init_list stricter
>> would make sense instead, but I don't think so (consistently with the trail
>> of c++/60848 too): I believe that by the time we use is_std_init_list in the
>> internals we want something as simple as possible, we are assuming that
>> broken, fake, std::initializer_list aren't around in the translation unit.
>> In terms of details, I also wondered if CLASSTYPE_IS_TEMPLATE would make for
>> a better check, but seems unnecessarily more complex. Also, in principle, we
>> may want to have an even stricter check at declaration time (how many
>> template parameters, etc) but that seems overkilling and I don't think we
>> are risking ICEs because of that.
> I agree with all of this.  How about in pushtag_1 instead, where we
> can return error_mark_node instead of aborting?
Sure. In that case the testcase for that older issue also requires 
adjusting. The below passes testing, anyway.

Thanks,
Paolo.

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

Comments

Jason Merrill March 20, 2017, 9:10 p.m. UTC | #1
OK.

On Fri, Mar 10, 2017 at 5:38 PM, Paolo Carlini <paolo.carlini@oracle.com> wrote:
> Hi,
>
> On 10/03/2017 16:57, Jason Merrill wrote:
>>
>> On Fri, Mar 10, 2017 at 9:58 AM, Paolo Carlini <paolo.carlini@oracle.com>
>> wrote:
>>>
>>> As such, the broken declaration cannot be rejected by the code we have in
>>> finish_struct, something must happen earlier than that. It seems to me
>>> that
>>> xref_tag_1 can be a good place, per the below patchlet, which passes
>>> testing
>>> on x86_64-linux. I briefly wondered if making is_std_init_list stricter
>>> would make sense instead, but I don't think so (consistently with the
>>> trail
>>> of c++/60848 too): I believe that by the time we use is_std_init_list in
>>> the
>>> internals we want something as simple as possible, we are assuming that
>>> broken, fake, std::initializer_list aren't around in the translation
>>> unit.
>>> In terms of details, I also wondered if CLASSTYPE_IS_TEMPLATE would make
>>> for
>>> a better check, but seems unnecessarily more complex. Also, in principle,
>>> we
>>> may want to have an even stricter check at declaration time (how many
>>> template parameters, etc) but that seems overkilling and I don't think we
>>> are risking ICEs because of that.
>>
>> I agree with all of this.  How about in pushtag_1 instead, where we
>> can return error_mark_node instead of aborting?
>
> Sure. In that case the testcase for that older issue also requires
> adjusting. The below passes testing, anyway.
>
> Thanks,
> Paolo.
>
> ////////////////////
diff mbox

Patch

Index: cp/name-lookup.c
===================================================================
--- cp/name-lookup.c	(revision 246023)
+++ cp/name-lookup.c	(working copy)
@@ -6207,6 +6207,15 @@  pushtag_1 (tree name, tree type, tag_scope scope)
 	  decl = pushdecl_with_scope_1 (decl, b, /*is_friend=*/false);
 	  if (decl == error_mark_node)
 	    return decl;
+
+	  if (DECL_CONTEXT (decl) == std_node
+	      && strcmp (TYPE_NAME_STRING (type), "initializer_list") == 0
+	      && !CLASSTYPE_TEMPLATE_INFO (type))
+	    {
+	      error ("declaration of std::initializer_list does not match "
+		     "#include <initializer_list>, isn't a template");
+	      return error_mark_node;
+	    }
 	}
 
       if (! in_class)
Index: testsuite/g++.dg/cpp0x/initlist85.C
===================================================================
--- testsuite/g++.dg/cpp0x/initlist85.C	(revision 246023)
+++ testsuite/g++.dg/cpp0x/initlist85.C	(working copy)
@@ -3,7 +3,7 @@ 
 
 namespace std
 {
-  struct initializer_list {};	// { dg-message "initializer_list" }
+  struct initializer_list {};  // { dg-error "declaration" }
 }
 
 void foo(std::initializer_list &);
@@ -10,7 +10,5 @@  void foo(std::initializer_list &);
 
 void f()
 {
-  foo({1, 2});
+  foo({1, 2});  // { dg-error "invalid initialization" }
 }
-
-// { dg-prune-output "compilation terminated" }
Index: testsuite/g++.dg/cpp0x/initlist97.C
===================================================================
--- testsuite/g++.dg/cpp0x/initlist97.C	(revision 0)
+++ testsuite/g++.dg/cpp0x/initlist97.C	(working copy)
@@ -0,0 +1,7 @@ 
+// PR c++/77752
+// { dg-do compile { target c++11 } }
+
+namespace std {
+  class initializer_list;  // { dg-error "declaration" }
+}
+void f(std::initializer_list l) { f({2}); }  // { dg-error "incomplete type" }