https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92009

Jakub Jelinek <jakub at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|ASSIGNED                    |NEW
                 CC|                            |jason at gcc dot gnu.org
           Assignee|jakub at gcc dot gnu.org           |unassigned at gcc dot 
gnu.org

--- Comment #2 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
So, cxx_fold_indirect_ref is called with void * as type and &_ZTIi as op0 (with
some casts that are skipped).  Previously, before r276563, it would fail,
because for FIELD_DECLs we would check if the FIELD_DECL's type is similar to
type (it is not) and punt.
_ZTIi has type __fundamental_type_info_pseudo_2, which is a struct containing
(an anonymous) FIELD_DECL with __type_info_pseudo_0 type, which is again a
struct containing some FIELD_DECLs, an anynymous FIELD_DECL with void * type as
the first element.  So, the r276563 code in this case will recurse and find the
void * type in there.  The ICE later on is that constexpr.c code when
evaluating
_ZTIi VAR_DECL with that __fundamental_type_info_pseudo_2 calls
4758          if (COMPLETE_TYPE_P (TREE_TYPE (t))
4759              && is_really_empty_class (TREE_TYPE (t),
/*ignore_vptr*/false))
on it, and is_really_empty_class has:
8449          for (binfo = TYPE_BINFO (type), i = 0;
8450               BINFO_BASE_ITERATE (binfo, i, base_binfo); ++i)
8451            if (!is_really_empty_class (BINFO_TYPE (base_binfo),
ignore_vptr))
8452              return false;
While __fundamental_type_info_pseudo_2 has CLASS_TYPE_P flag set (created
through
get_tinfo_desc
1461      /* Create the pseudo type.  */
1462      tree pseudo_type = make_class_type (RECORD_TYPE);
1463      /* Pass the fields chained in reverse.  */
1464      finish_builtin_struct (pseudo_type, pseudo_name, fields, NULL_TREE);
1465      CLASSTYPE_AS_BASE (pseudo_type) = pseudo_type;
it has NULL TYPE_BINFO.

So, shall is_really_empty_class not go through TYPE_BINFO if it is NULL, or
shall get_tinfo_desc fill in TYPE_BINFO, something else?
E.g. following (without needed reindentation) fixes the ICE:

--- gcc/cp/class.c.jj   2019-10-05 09:36:39.244674589 +0200
+++ gcc/cp/class.c      2019-10-07 12:04:04.555012116 +0200
@@ -8446,6 +8446,7 @@ is_really_empty_class (tree type, bool i
       if (!ignore_vptr && TYPE_CONTAINS_VPTR_P (type))
        return false;

+      if (TYPE_BINFO (type))
       for (binfo = TYPE_BINFO (type), i = 0;
           BINFO_BASE_ITERATE (binfo, i, base_binfo); ++i)
        if (!is_really_empty_class (BINFO_TYPE (base_binfo), ignore_vptr))


Another thing I'm worried about,
namespace std { class type_info {}; }

constexpr bool
foo ()
{
  return ((void **) &typeid (int))[0];
}

constexpr bool x = foo ();
used to be rejected due to the reinterpret_cast in there, but assuming this ICE
is fixed, it is rejected with another reason:
pr92009.C:9:24:   in ‘constexpr’ expansion of ‘foo()’
pr92009.C:9:25: error: the value of ‘_ZTIi’ is not usable in a constant
expression
    9 | constexpr bool x = foo ();
      |                         ^
pr92009.C:6:33: note: ‘_ZTIi’ was not declared ‘constexpr’
    6 |   return ((void **) &typeid (int))[0];
      |                                 ^

Now, consider
struct S { void *p; };
struct T { S s; };
constexpr S s = { nullptr };
constexpr T t = { { nullptr } };

constexpr void *
foo ()
{
  return ((void **) &t)[0];
}

constexpr void *
bar ()
{
  return ((void **) &s)[0];
}

constexpr auto x = foo ();
constexpr auto y = bar ();
clang++ rejects here both the foo and bar calls as non-constexpr, as
reinterpret_cast is encountered.  GCC 9 will succeed with cxx_fold_indirect_ref
in the bar case and fail the foo case, so rejects foo, but (incorrectly?)
accepts bar call.  And GCC 10 with the change I've made will accept both. 
Makes me wonder if cxx_eval_indirect_ref shouldn't evaluate the argument as
constant expression no matter if cxx_fold_indirect_ref actually folds it into
something or not, so that what is non-constexpr is really diagnosed as such. 
But am also afraid of what all it will break.

Jason, thoughts on this?

Reply via email to