[C++] PR 85227 ("[7/8/ Regression] ICE with structured binding of a forward declared variable")

Message ID 015b4c9b-5405-7391-42d2-941106b41931@oracle.com
State New
Headers show
Series
  • [C++] PR 85227 ("[7/8/ Regression] ICE with structured binding of a forward declared variable")
Related show

Commit Message

Paolo Carlini April 6, 2018, 9:01 a.m.
Hi,

here, for an incomplete type we ICE pretty soon in 
find_decomp_class_base. Comparing to other cases too, I convinced myself 
that trying to complete the type is Ok. Also, it seems that in these 
functions we want to talk about structured binding and use an 
appropriate location, thus no complete_type_or_maybe_complain. Tested 
x86_64-linux.

Thanks, Paolo.

/////////////////////
/cp
2018-04-06  Paolo Carlini  <paolo.carlini@oracle.com>

	PR c++/85227
	* decl.c (find_decomp_class_base): Try to complete the type
	and give an error if that fails.

/testsuite
2018-04-06  Paolo Carlini  <paolo.carlini@oracle.com>

	PR c++/85227
	* g++.dg/cpp1z/decomp42.C: New.

Comments

Jason Merrill April 6, 2018, 5:04 p.m. | #1
On Fri, Apr 6, 2018 at 5:01 AM, Paolo Carlini <paolo.carlini@oracle.com> wrote:
> here, for an incomplete type we ICE pretty soon in find_decomp_class_base.

> Comparing to other cases too, I convinced myself that trying to complete the

> type is Ok. Also, it seems that in these functions we want to talk about

> structured binding and use an appropriate location, thus no

> complete_type_or_maybe_complain. Tested x86_64-linux.


What if, in a template, we defer trying to do bindings to an incomplete type, so

extern struct A a;

template<int>
void f()
{
  auto [x] = a;
}

struct A { int i; };

int main()
{
  f<0>();
}

works?  Probably with a pedwarn, as in xref_basetypes or
cp_parser_dot_deref_incomplete.

Jason
Paolo Carlini April 6, 2018, 7:05 p.m. | #2
Hi,

On 06/04/2018 19:04, Jason Merrill wrote:
> On Fri, Apr 6, 2018 at 5:01 AM, Paolo Carlini <paolo.carlini@oracle.com> wrote:

>> here, for an incomplete type we ICE pretty soon in find_decomp_class_base.

>> Comparing to other cases too, I convinced myself that trying to complete the

>> type is Ok. Also, it seems that in these functions we want to talk about

>> structured binding and use an appropriate location, thus no

>> complete_type_or_maybe_complain. Tested x86_64-linux.

> What if, in a template, we defer trying to do bindings to an incomplete type, so

>

> extern struct A a;

>

> template<int>

> void f()

> {

>    auto [x] = a;

> }

>

> struct A { int i; };

>

> int main()

> {

>    f<0>();

> }

>

> works?  Probably with a pedwarn, as in xref_basetypes or

> cp_parser_dot_deref_incomplete.

Ok... I tested the very simple patch below, wasnt sure between pedwarn 
(loc, 0, ...) and pedwarn (loc, OPT_Wpedantic, ...) but probably we want 
to former in order not to be too permissive (for comparison, clang 
rejects with an hard error both tests). What do you think?

Thanks!
Paolo.

/////////////////////
Index: cp/decl.c
===================================================================
--- cp/decl.c	(revision 259184)
+++ cp/decl.c	(working copy)
@@ -7756,6 +7756,9 @@ cp_finish_decomp (tree decl, tree first, unsigned
       error_at (loc, "cannot decompose lambda closure type %qT", type);
       goto error_out;
     }
+  else if (processing_template_decl && !COMPLETE_TYPE_P (type))
+    pedwarn (loc, 0, "structured binding refers to incomplete class type %qT",
+	     type);
   else
     {
       tree btype = find_decomp_class_base (loc, type, NULL_TREE);
Index: testsuite/g++.dg/cpp1z/decomp43.C
===================================================================
--- testsuite/g++.dg/cpp1z/decomp43.C	(nonexistent)
+++ testsuite/g++.dg/cpp1z/decomp43.C	(working copy)
@@ -0,0 +1,10 @@
+// PR c++/85227
+// { dg-do compile { target c++11 } }
+// { dg-options "" }
+
+extern struct A a;
+
+template<int> void foo()
+{
+  auto[i] = a;  // { dg-warning "incomplete" }
+}  // { dg-warning "structured bindings only available with -std=c..17 or -std=gnu..17" "" { target c++14_down } .-1 }
Index: testsuite/g++.dg/cpp1z/decomp44.C
===================================================================
--- testsuite/g++.dg/cpp1z/decomp44.C	(nonexistent)
+++ testsuite/g++.dg/cpp1z/decomp44.C	(working copy)
@@ -0,0 +1,18 @@
+// PR c++/85227
+// { dg-do compile { target c++11 } }
+// { dg-options "" }
+
+extern struct A a;
+
+template<int>
+void f()
+{
+  auto [x] = a;  // { dg-warning "incomplete" }
+}  // { dg-warning "structured bindings only available with -std=c..17 or -std=gnu..17" "" { target c++14_down } .-1 }
+
+struct A { int i; };
+
+int main()
+{
+  f<0>();
+}
Jason Merrill April 9, 2018, 7:03 p.m. | #3
OK.

On Fri, Apr 6, 2018 at 3:05 PM, Paolo Carlini <paolo.carlini@oracle.com> wrote:
> Hi,

>

> On 06/04/2018 19:04, Jason Merrill wrote:

>>

>> On Fri, Apr 6, 2018 at 5:01 AM, Paolo Carlini <paolo.carlini@oracle.com>

>> wrote:

>>>

>>> here, for an incomplete type we ICE pretty soon in

>>> find_decomp_class_base.

>>> Comparing to other cases too, I convinced myself that trying to complete

>>> the

>>> type is Ok. Also, it seems that in these functions we want to talk about

>>> structured binding and use an appropriate location, thus no

>>> complete_type_or_maybe_complain. Tested x86_64-linux.

>>

>> What if, in a template, we defer trying to do bindings to an incomplete

>> type, so

>>

>> extern struct A a;

>>

>> template<int>

>> void f()

>> {

>>    auto [x] = a;

>> }

>>

>> struct A { int i; };

>>

>> int main()

>> {

>>    f<0>();

>> }

>>

>> works?  Probably with a pedwarn, as in xref_basetypes or

>> cp_parser_dot_deref_incomplete.

>

> Ok... I tested the very simple patch below, wasnt sure between pedwarn (loc,

> 0, ...) and pedwarn (loc, OPT_Wpedantic, ...) but probably we want to former

> in order not to be too permissive (for comparison, clang rejects with an

> hard error both tests). What do you think?

>

> Thanks!

> Paolo.

>

> /////////////////////

Patch

Index: cp/decl.c
===================================================================
--- cp/decl.c	(revision 259156)
+++ cp/decl.c	(working copy)
@@ -7310,6 +7310,13 @@  cp_finish_decl (tree decl, tree init, bool init_co
 static tree
 find_decomp_class_base (location_t loc, tree type, tree ret)
 {
+  if (!COMPLETE_TYPE_P (complete_type (type)))
+    {
+      error_at (loc, "structured binding refers to incomplete class type %qT",
+		type);
+      return error_mark_node;
+    }
+
   bool member_seen = false;
   for (tree field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
     if (TREE_CODE (field) != FIELD_DECL
Index: testsuite/g++.dg/cpp1z/decomp42.C
===================================================================
--- testsuite/g++.dg/cpp1z/decomp42.C	(nonexistent)
+++ testsuite/g++.dg/cpp1z/decomp42.C	(working copy)
@@ -0,0 +1,10 @@ 
+// PR c++/85227
+// { dg-do compile { target c++11 } }
+// { dg-options "" }
+
+extern struct A a;
+
+template<int> void foo()
+{
+  auto[i] = a;  // { dg-error "incomplete" }
+}  // { dg-warning "structured bindings only available with -std=c..17 or -std=gnu..17" "" { target c++14_down } .-1 }