Hi,

I have been investigating this very old and very weird issue where we wrongly reject:

class Foo
{
int u, v, w, x;
typedef struct Bar { } Bar;
virtual void foo(void) {
struct Bar bar;
}
};

46206.C: In member function ‘virtual void Foo::foo()’:
46206.C:6:12: error: using typedef-name ‘Foo::Bar’ after ‘struct’
46206.C:4:26: note: ‘Foo::Bar’ has a previous declaration here

whereas we don't reject variants with one less data member, say x, or non-virtual foo, all sorts of variants corresponding to a smaller Foo!!

I figured out that when we parse "typedef struct Bar { } Bar;" we create two TYPE_DECL: first, one marked as DECL_IMPLICIT_TYPEDEF_P in pushtag_1 (via create_implicit_typedef); then a second, non-implicit, one in grokdeclarator, via build_lang_decl (TYPE_DECL... ). When we do lookup for "struct Bar bar", it happens that the *second* one is found, thus the check in check_elaborated_type_specifier triggers.

The latter function is called by lookup_and_check_tag, with the decl returned by lookup_name_prefer_type (name, 2). The latter, in turn, ends up calling lookup_name_real_1 which has:

/* If this is the kind of thing we're looking for, we're done. */
if (qualify_lookup (iter->value, flags))
binding = iter->value;
else if ((flags & LOOKUP_PREFER_TYPES)
&& qualify_lookup (iter->type, flags))
binding = iter->type;
else
binding = NULL_TREE;

and it happens that the first qualify_lookup succeeds but with iter->value which is the variant of the Bar TYPE_DECL with DECL_IMPLICIT_TYPEDEF_P not set. On the other hand, iter->type is the Ok variant, that which would not trigger the error.

Then I noticed the following comment in name_lookup.c, around line 4890, in lookup_type_scope_1:

We check ITER->TYPE before ITER->VALUE in order to handle
typedef struct C {} C;
correctly. */

and after this comment, both pairs of qualify_lookup are called in that order. Thus I started seriously suspecting that something may be wrong in the if-else above, that is, that we really want something with iter->type *before* iter->value there too: the attached patchlet p works for the testcase and passes bootstrap & test. Does it make sense to you?

Final observation: in many cases, like for example, variants of the testcase with one less data member, what happens is that iter->type and iter->value are *both* the same variant of the TYPE_DECL Bar, the one which is fine, has DECL_IMPLICIT_TYPEDEF_P set. Thus the ordering doesn't matter. Frankly, at the moment I'm not sure to understand how exactly when the class becomes bigger the iter->type and iter->value become different and becomes important to handle the former first.

Fiuuuu ;)

Thanks!
Paolo.

/////////////////////
Index: name-lookup.c
===================================================================
--- name-lookup.c       (revision 201511)
+++ name-lookup.c       (working copy)
@@ -4740,11 +4740,11 @@ lookup_name_real_1 (tree name, int prefer_type, in
          continue;
 
        /* If this is the kind of thing we're looking for, we're done.  */
-       if (qualify_lookup (iter->value, flags))
+       if ((flags & LOOKUP_PREFER_TYPES)
+           && qualify_lookup (iter->type, flags))
+         binding = iter->type;
+       else if (qualify_lookup (iter->value, flags))
          binding = iter->value;
-       else if ((flags & LOOKUP_PREFER_TYPES)
-                && qualify_lookup (iter->type, flags))
-         binding = iter->type;
        else
          binding = NULL_TREE;
 

Reply via email to