From 80de0002429c74626198cefa168c3081c9d90566 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Tue, 14 Jan 2020 00:05:47 -0500 Subject: [PATCH] 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. --- gcc/cp/ChangeLog | 7 +++++++ gcc/cp/constexpr.c | 11 +++++++++- gcc/cp/rtti.c | 1 + .../g++.dg/cpp0x/constexpr-reinterpret2.C | 21 +++++++++++++++++++ gcc/testsuite/g++.dg/rtti/typeid13.C | 11 ++++++++++ 5 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/constexpr-reinterpret2.C create mode 100644 gcc/testsuite/g++.dg/rtti/typeid13.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 4729e3d331d..f7e5e74d281 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,10 @@ +2020-01-14 Jason Merrill + + 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 PR c++/92746 - ICE with noexcept of function concept check. diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index 3a9fb566a52..bb126a9c006 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 2fc52f07980..36c1b4ed7bc 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 00000000000..1bc2a8f3012 --- /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 00000000000..d42005ed0d6 --- /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]; +} -- 2.30.2