diff mbox

[C++,Patch/RFC] PR 77752

Message ID 673bd2d5-e060-8f2c-8c69-8139064fde45@oracle.com
State New
Headers show

Commit Message

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

if you like, this ICE is closely related to c++/60848, but occurs when 
we don't have (yet) a broken definition of std::initializer_list, only a 
declaration, which is nonetheless able to cause an ICE at the beginning 
of build_list_conv, as called by implicit_conversion for the testcase at 
issue.

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.

Thanks, Paolo.

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

Comments

Jason Merrill March 10, 2017, 3:57 p.m. UTC | #1
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?

Jason
diff mbox

Patch

Index: cp/decl.c
===================================================================
--- cp/decl.c	(revision 246023)
+++ cp/decl.c	(working copy)
@@ -13645,6 +13645,13 @@  xref_tag_1 (enum tag_types tag_code, tree name,
 	       in push_template_decl.  */
 	    CLASSTYPE_LAMBDA_EXPR (t) = error_mark_node;
 	  t = pushtag (name, t, scope);
+	  if (t != error_mark_node
+	      && CP_TYPE_CONTEXT (t) == std_node
+	      && strcmp (TYPE_NAME_STRING (t), "initializer_list") == 0
+	      && !CLASSTYPE_TEMPLATE_INFO (t))
+	    fatal_error (input_location,
+			 "declaration of std::initializer_list does not match "
+			 "#include <initializer_list>, isn't a template");
 	}
     }
   else
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,9 @@ 
+// PR c++/77752
+// { dg-do compile { target c++11 } }
+
+namespace std {
+  class initializer_list;  // { dg-message "initializer_list" }
+}
+void f(std::initializer_list l) { f({2}); }
+
+// { dg-prune-output "compilation terminated" }