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

Richard Biener <rguenth at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |jsm28 at gcc dot gnu.org,
                   |                            |mpolacek at gcc dot gnu.org
          Component|middle-end                  |c

--- Comment #2 from Richard Biener <rguenth at gcc dot gnu.org> ---
So we are building the VEC_PERM_EXPR at a point where 'a' has vector type but
then later via

(gdb) bt
#0  pop_scope () at ../../src/trunk/gcc/c/c-decl.c:1375
#1  0x0000000000976572 in pop_file_scope ()
    at ../../src/trunk/gcc/c/c-decl.c:1456
#2  0x0000000000ac6667 in c_common_parse_file ()
    at ../../src/trunk/gcc/c-family/c-opts.c:1191
#3  0x000000000132b2e0 in compile_file () at ../../src/trunk/gcc/toplev.c:458
#4  0x000000000132e469 in do_compile () at ../../src/trunk/gcc/toplev.c:2273

we are patching up its type to an ARRAY_TYPE, resulting in invalid GENERIC
for the formerly built tree.

We should do no such thing here.  Iff the FE wants to continue then it
should simply remove the shadowed decl from the bindings and continue
with the shadowing one.  But here it seems to patch something up
what wasn't "merged" during duplicate_decls so clearly something is "off".

Oddly enough both b and b->shadowed refer to the same decl(?) and with
vector type(!).  I guess I don't really understand the purpose of
the type "restore(?)" below:

tree
pop_scope (void)
{
...
          /* It is possible for a decl not to have a name.  We get
             here with b->id NULL in this case.  */
          if (b->id)
            {
              gcc_assert (I_SYMBOL_BINDING (b->id) == b);
              I_SYMBOL_BINDING (b->id) = b->shadowed;
              if (b->shadowed && b->shadowed->u.type)
                TREE_TYPE (b->shadowed->decl) = b->shadowed->u.type;


Martin, while we certainly can paper over this in the middle-end the
issue clearly lies in the FE so I suggest to leave this to FE maintainers
to sort out.

I suppose similar issues might arise with

double a;
double foo () { return a / 3.0; };

int a = 0;

where we should get a RDIV_EXPR with integer typed a. Hum, no, for some
unknown reason _this_ testcase has 'a' still have double type and we
do not run into the above code?!  Ah, so in _this_ case we have
two different decls in b->decl vs. b->shadowed->decl and
b->shadowed->u.type is NULL.

Err, for the vector case we get everything correct up to popping
the vector a which somehow has itself registered as shadowed
but with array type?!

OK, so for the vector case we register two bindings for the same decl:

#0  0x000000000097496f in bind (name=<identifier_node 0x7ffff6d7d960 a>, 
    decl=<var_decl 0x7ffff7fedb40 a>, scope=0x7ffff6c3b300, invisible=true, 
    nested=false, locus=266848) at ../../src/trunk/gcc/c/c-decl.c:729
#1  0x000000000097e409 in pushdecl (x=<var_decl 0x7ffff7fedb40 a>)
    at ../../src/trunk/gcc/c/c-decl.c:3274
#2  0x0000000000982c4f in start_decl (declarator=0x3764510, 
    declspecs=0x3764450, initialized=false, attributes=<tree 0x0>)
    at ../../src/trunk/gcc/c/c-decl.c:5177

and then

#0  0x000000000097496f in bind (name=<identifier_node 0x7ffff6d7d960 a>, 
    decl=<var_decl 0x7ffff7fedb40 a>, scope=0x7ffff6d7e1e0, invisible=false, 
    nested=true, locus=266848) at ../../src/trunk/gcc/c/c-decl.c:729
#1  0x000000000097e485 in pushdecl (x=<var_decl 0x7ffff7fedb40 a>)
    at ../../src/trunk/gcc/c/c-decl.c:3295
#2  0x0000000000982c4f in start_decl (declarator=0x3764510, 
    declspecs=0x3764450, initialized=false, attributes=<tree 0x0>)
    at ../../src/trunk/gcc/c/c-decl.c:5177

and then update u.type of the shadowed here:

  /* Deduce size of array from initialization, if not already known.
     This is only needed for an initialization in the current scope;
     it must not be done for a file-scope initialization of a
     declaration with external linkage, redeclared in an inner scope
     with the outer declaration shadowed in an intermediate scope.  */
  if (TREE_CODE (type) == ARRAY_TYPE
      && TYPE_DOMAIN (type) == NULL_TREE
      && TREE_CODE (decl) != TYPE_DECL
      && !(TREE_PUBLIC (decl) && current_scope != file_scope))
    {
...
        case 0:
          /* For global variables, update the copy of the type that
             exists in the binding.  */
          if (TREE_PUBLIC (decl))
            {
              struct c_binding *b_ext = I_SYMBOL_BINDING (DECL_NAME (decl));
              while (b_ext && !B_IN_EXTERNAL_SCOPE (b_ext))
                b_ext = b_ext->shadowed;
              if (b_ext && TREE_CODE (decl) == TREE_CODE (b_ext->decl))
                {
                  if (b_ext->u.type && comptypes (b_ext->u.type, type))
                    b_ext->u.type = composite_type (b_ext->u.type, type);
                  else
                    b_ext->u.type = type;

so the special case here is an array initializer.  Indeed the following
testcase exposes the bogus RDIV_EXPR:

double a;
double foo () { return a / 3.0; };

int a[] = { 0 };

but we're not consuming the bogus IL anywhere it would ICE.

Reply via email to