Hi,

On 10/03/2017 16:57, Jason Merrill wrote:
On Fri, Mar 10, 2017 at 9:58 AM, Paolo Carlini <paolo.carl...@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.

////////////////////
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" }

Reply via email to