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

--- Comment #5 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
Note C++ ICEs as well on the same testcase.
The problem (I guess for both FEs) is from where to emit the DECL_EXPRs, e.g.
in the C FE groktypename is called from many spots and I believe the middle-end
wants to see DECL_EXPRs not just for the toplevel variably_modified_type_p
(e.g. from c_cast_expr), but also any VLA types it refers to, if they don't
have DECL_EXPRs emitted yet.
I don't think either FE tracks that right now.

Or shall we try to emit those later (e.g. from C genericization), if we see a
variably modified type that doesn't have a TYPE_DECL yet add somewhere (before
the stmt containing it? What about conditional contexts etc.?) a DECL_EXPR for
the TYPE_DECL we create for it.

E.g. for:
int
foo (int n, void *x, void *y)
{
  struct S { int (***p)[n][n][n]; } s;
  int (***q)[n][n][n];
  s.p = x;
  q = y;
  return (***s.p)[1][2][3] + (***q)[1][2][3];
}
we emit all the needed DECL_EXPRs, apparently from:
            /* When the pointed-to type involves components of variable size,
               care must be taken to ensure that the size evaluation code is
               emitted early enough to dominate all the possible later uses
               and late enough for the variables on which it depends to have
               been assigned.

               This is expected to happen automatically when the pointed-to
               type has a name/declaration of it's own, but special attention
               is required if the type is anonymous.

               We handle the NORMAL and FIELD contexts here by attaching an
               artificial TYPE_DECL to such pointed-to type.  This forces the
               sizes evaluation at a safe point and ensures it is not deferred
               until e.g. within a deeper conditional context.

               We expect nothing to be needed here for PARM or TYPENAME.
               Pushing a TYPE_DECL at this point for TYPENAME would actually
               be incorrect, as we might be in the middle of an expression
               with side effects on the pointed-to type size "arguments" prior
               to the pointer declaration point and the fake TYPE_DECL in the
               enclosing context would force the size evaluation prior to the
               side effects.  */

            if (!TYPE_NAME (type)
                && (decl_context == NORMAL || decl_context == FIELD)
                && variably_modified_type_p (type, NULL_TREE))
              {
                tree decl = build_decl (loc, TYPE_DECL, NULL_TREE, type);
                DECL_ARTIFICIAL (decl) = 1;
                pushdecl (decl);
                finish_decl (decl, loc, NULL_TREE, NULL_TREE, NULL_TREE);
                TYPE_NAME (type) = decl;
              }
in grokdeclarator.  The reason why this doesn't trigger in the cast case is
that it uses groktypename which sets decl_context to TYPENAME.  Now, I can
understand in some cases we don't want any DECL_EXPRs, e.g. in sizeof, alignof,
_Alignas.  But in C case we as this testcase shows need it.
What about _Atomic ( type-name ), typeof, generic, va_arg, offsetof,
types_compatible_p, ObjC at encode, compound literals?  There is also OpenMP
UDR (though, perhaps that doesn't want them, for them to be used one needs a
compatible type to be somewhere else for it to match).

So, shall groktypename have a boolean or similar arg whether it wants them or
not and shall we use separate decl_context for TYPENAME which would add the
DECL_EXPRs and e.g. SIZEOF which wouldn't?

Reply via email to