This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[C++ Patch / RFC] PR 46206


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.

/////////////////////

Attachment: p
Description: Text document


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]