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;