aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2020-01-14 00:05:47 -0500
committerJason Merrill <jason@redhat.com>2020-01-14 11:57:34 -0500
commit80de0002429c74626198cefa168c3081c9d90566 (patch)
tree75dab2481c042655ada32a010a12ab43732fc35d
parent336da03cc3a1795942938c6187277b666ce9b86c (diff)
downloadgcc-80de0002429c74626198cefa168c3081c9d90566.zip
gcc-80de0002429c74626198cefa168c3081c9d90566.tar.gz
gcc-80de0002429c74626198cefa168c3081c9d90566.tar.bz2
PR c++/92009 - ICE with punning of typeid.
There were two issues in this PR: 1) We were crashing in is_really_empty_class because we say that the internal RTTI types are classes, but never gave them TYPE_BINFO. 2) We were allowing the cast to a different pointer type because STRIP_NOPS in cxx_fold_indirect_ref ignored REINTERPRET_CAST_P. * rtti.c (get_tinfo_desc): Call xref_basetypes. * constexpr.c (cxx_fold_indirect_ref): Don't strip REINTERPRET_CAST_P.
-rw-r--r--gcc/cp/ChangeLog7
-rw-r--r--gcc/cp/constexpr.c11
-rw-r--r--gcc/cp/rtti.c1
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-reinterpret2.C21
-rw-r--r--gcc/testsuite/g++.dg/rtti/typeid13.C11
5 files changed, 50 insertions, 1 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 4729e3d..f7e5e74 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,10 @@
+2020-01-14 Jason Merrill <jason@redhat.com>
+
+ PR c++/92009 - ICE with punning of typeid.
+ * rtti.c (get_tinfo_desc): Call xref_basetypes.
+ * constexpr.c (cxx_fold_indirect_ref): Don't strip
+ REINTERPRET_CAST_P.
+
2020-01-13 Jason Merrill <jason@redhat.com>
PR c++/92746 - ICE with noexcept of function concept check.
diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index 3a9fb56..bb126a9 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -4023,7 +4023,16 @@ cxx_fold_indirect_ref (location_t loc, tree type, tree op0, bool *empty_base)
tree subtype;
poly_uint64 const_op01;
- STRIP_NOPS (sub);
+ /* STRIP_NOPS, but stop if REINTERPRET_CAST_P. */
+ while (CONVERT_EXPR_P (sub) || TREE_CODE (sub) == NON_LVALUE_EXPR
+ || TREE_CODE (sub) == VIEW_CONVERT_EXPR)
+ {
+ if (TREE_CODE (sub) == NOP_EXPR
+ && REINTERPRET_CAST_P (sub))
+ return NULL_TREE;
+ sub = TREE_OPERAND (sub, 0);
+ }
+
subtype = TREE_TYPE (sub);
if (!INDIRECT_TYPE_P (subtype))
return NULL_TREE;
diff --git a/gcc/cp/rtti.c b/gcc/cp/rtti.c
index 2fc52f0..36c1b4e 100644
--- a/gcc/cp/rtti.c
+++ b/gcc/cp/rtti.c
@@ -1472,6 +1472,7 @@ get_tinfo_desc (unsigned ix)
/* Pass the fields chained in reverse. */
finish_builtin_struct (pseudo_type, pseudo_name, fields, NULL_TREE);
CLASSTYPE_AS_BASE (pseudo_type) = pseudo_type;
+ xref_basetypes (pseudo_type, /*bases=*/NULL_TREE);
res->type = cp_build_qualified_type (pseudo_type, TYPE_QUAL_CONST);
res->name = get_identifier (real_name);
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-reinterpret2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-reinterpret2.C
new file mode 100644
index 0000000..1bc2a8f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-reinterpret2.C
@@ -0,0 +1,21 @@
+// { dg-do compile { target c++11 } }
+
+struct S { void *p; };
+struct T { S s; };
+constexpr S s = { nullptr };
+constexpr T t = { { nullptr } };
+
+constexpr void *
+foo ()
+{
+ return ((void **) &t)[0]; // { dg-error "reinterpret_cast" }
+}
+
+constexpr void *
+bar ()
+{
+ return ((void **) &s)[0]; // { dg-error "reinterpret_cast" }
+}
+
+constexpr auto x = foo ();
+constexpr auto y = bar ();
diff --git a/gcc/testsuite/g++.dg/rtti/typeid13.C b/gcc/testsuite/g++.dg/rtti/typeid13.C
new file mode 100644
index 0000000..d42005e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/rtti/typeid13.C
@@ -0,0 +1,11 @@
+// PR c++/92009
+
+namespace std {
+ class type_info {};
+}
+
+bool
+a2 ()
+{
+ return ((void **) &typeid (int))[0];
+}