aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarek Polacek <polacek@redhat.com>2023-07-19 08:47:29 -0400
committerMarek Polacek <polacek@redhat.com>2023-07-20 10:32:48 -0400
commit2cb0dc866e8f95151df5d759157708108e850dd9 (patch)
treef433d597f619f63a4e71a9e21cfc305680d76faf
parentb6b72562d116bd0a589dce39437f9d2b3c34491f (diff)
downloadgcc-2cb0dc866e8f95151df5d759157708108e850dd9.zip
gcc-2cb0dc866e8f95151df5d759157708108e850dd9.tar.gz
gcc-2cb0dc866e8f95151df5d759157708108e850dd9.tar.bz2
c++: fix ICE with designated initializer [PR110114]
r13-1227 added an assert checking that the index in a CONSTRUCTOR is a FIELD_DECL. That's a reasonable assumption but in this case we never called reshape_init due to the type being incomplete, and so the index remained an identifier node: get_class_binding never got around to looking up the FIELD_DECL. We can avoid the crash by returning early in implicit_conversion_1; we'd return NULL anyway due to: if (i < CONSTRUCTOR_NELTS (ctor)) return NULL; in build_aggr_conv. PR c++/110114 gcc/cp/ChangeLog: * call.cc (implicit_conversion_1): Return early if the type isn't complete. gcc/testsuite/ChangeLog: * g++.dg/cpp0x/initlist100.C: Adjust expected diagnostic. * g++.dg/cpp2a/desig28.C: New test. * g++.dg/cpp2a/desig29.C: New test.
-rw-r--r--gcc/cp/call.cc19
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist100.C4
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/desig28.C17
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/desig29.C10
4 files changed, 40 insertions, 10 deletions
diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
index b55230d..673ec91 100644
--- a/gcc/cp/call.cc
+++ b/gcc/cp/call.cc
@@ -2059,15 +2059,18 @@ implicit_conversion_1 (tree to, tree from, tree expr, bool c_cast_p,
complain &= ~tf_error;
/* Call reshape_init early to remove redundant braces. */
- if (expr && BRACE_ENCLOSED_INITIALIZER_P (expr)
- && CLASS_TYPE_P (to)
- && COMPLETE_TYPE_P (complete_type (to))
- && !CLASSTYPE_NON_AGGREGATE (to))
+ if (expr && BRACE_ENCLOSED_INITIALIZER_P (expr) && CLASS_TYPE_P (to))
{
- expr = reshape_init (to, expr, complain);
- if (expr == error_mark_node)
- return NULL;
- from = TREE_TYPE (expr);
+ to = complete_type (to);
+ if (!COMPLETE_TYPE_P (to))
+ return nullptr;
+ if (!CLASSTYPE_NON_AGGREGATE (to))
+ {
+ expr = reshape_init (to, expr, complain);
+ if (expr == error_mark_node)
+ return nullptr;
+ from = TREE_TYPE (expr);
+ }
}
if (TYPE_REF_P (to))
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist100.C b/gcc/testsuite/g++.dg/cpp0x/initlist100.C
index 9d80a00..6865d34 100644
--- a/gcc/testsuite/g++.dg/cpp0x/initlist100.C
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist100.C
@@ -2,9 +2,9 @@
// { dg-do compile { target c++11 } }
namespace std {
-template <class> class initializer_list; // { dg-message "declaration" }
+template <class> class initializer_list;
}
template <typename T> struct B { B (std::initializer_list<T>); };
struct C { virtual int foo (); };
-struct D : C {} d { B<C> { D {} } }; // { dg-error "incomplete|no matching" }
+struct D : C {} d { B<C> { D {} } }; // { dg-error "no matching" }
diff --git a/gcc/testsuite/g++.dg/cpp2a/desig28.C b/gcc/testsuite/g++.dg/cpp2a/desig28.C
new file mode 100644
index 0000000..b63265f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/desig28.C
@@ -0,0 +1,17 @@
+// PR c++/110114
+// { dg-do compile { target c++20 } }
+
+struct A {
+ int a,b;
+};
+
+struct B;
+
+void foo(const A &) {}
+void foo(const B &) {}
+
+int
+main ()
+{
+ foo({.a=0});
+}
diff --git a/gcc/testsuite/g++.dg/cpp2a/desig29.C b/gcc/testsuite/g++.dg/cpp2a/desig29.C
new file mode 100644
index 0000000..bd1a82b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/desig29.C
@@ -0,0 +1,10 @@
+// PR c++/110114
+// { dg-do compile { target c++20 } }
+
+struct B;
+
+void foo(const B &) {}
+
+int main() {
+ foo({.a=0}); // { dg-error "invalid" }
+}