diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index c3582fcc2b6..1c66708438e 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,10 @@ +2000-10-21 Jason Merrill + + * parse.y (operator): Set got_object from got_scope. + Set looking_for_typename. + * decl.c (lookup_name_real): Clear val after setting from_obj. + Reorganize diagnostic. + 2000-10-20 Jason Merrill * tree.c (walk_tree): Don't walk into default args. @@ -419,7 +426,7 @@ Thu Sep 14 12:10:45 2000 Richard Kenner (cp_parse_init): Adjust. (do_id): If lastiddecl is NULL, do do_identifier. (operator): Save scope information. - (unoperator): new reduction. Restore scope information. + (unoperator): New reduction. Restore scope information. (operator_name): Append unoperator. Call frob_opname. * spew.c (frob_opname): Define. diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 7963a52f41a..8040137c710 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -5946,7 +5946,10 @@ lookup_name_real (name, prefer_type, nonclass, namespaces_only) if (got_scope) goto done; else if (got_object && val) - from_obj = val; + { + from_obj = val; + val = NULL_TREE; + } } else { @@ -6015,13 +6018,12 @@ lookup_name_real (name, prefer_type, nonclass, namespaces_only) { if (looking_for_typename && TREE_CODE (from_obj) == TYPE_DECL && TREE_CODE (val) == TYPE_DECL - && TREE_TYPE (from_obj) != TREE_TYPE (val)) - { - cp_pedwarn ("lookup of `%D' in the scope of `%#T' (`%#T')", - name, got_object, TREE_TYPE (from_obj)); - cp_pedwarn (" does not match lookup in the current scope (`%#T')", - TREE_TYPE (val)); - } + && ! same_type_p (TREE_TYPE (from_obj), TREE_TYPE (val))) + cp_pedwarn ("\ +lookup of `%D' in the scope of `%#T' (`%#T') \ +does not match lookup in the current scope (`%#T')", + name, got_object, TREE_TYPE (from_obj), + TREE_TYPE (val)); /* We don't change val to from_obj if got_object depends on template parms because that breaks implicit typename for diff --git a/gcc/cp/parse.y b/gcc/cp/parse.y index 27075e84df2..5e998620a67 100644 --- a/gcc/cp/parse.y +++ b/gcc/cp/parse.y @@ -3745,9 +3745,15 @@ conversion_declarator: operator: OPERATOR - { saved_scopes = tree_cons (got_scope, got_object, saved_scopes); - got_scope = NULL_TREE; got_object = NULL_TREE; } + { + saved_scopes = tree_cons (got_scope, got_object, saved_scopes); + /* We look for conversion-type-id's in both the class and current + scopes, just as for ID in 'ptr->ID::'. */ + looking_for_typename = 1; got_object = got_scope; + got_scope = NULL_TREE; + } ; + unoperator: { got_scope = TREE_PURPOSE (saved_scopes); got_object = TREE_VALUE (saved_scopes); @@ -3821,7 +3827,6 @@ operator_name: { $$ = frob_opname (ansi_opname (VEC_NEW_EXPR)); } | operator DELETE '[' ']' unoperator { $$ = frob_opname (ansi_opname (VEC_DELETE_EXPR)); } - /* Names here should be looked up in class scope ALSO. */ | operator type_specifier_seq conversion_declarator unoperator { $$ = frob_opname (grokoptypename ($2.t, $3)); } | operator error unoperator diff --git a/gcc/testsuite/g++.old-deja/g++.other/lookup19.C b/gcc/testsuite/g++.old-deja/g++.other/lookup19.C new file mode 100644 index 00000000000..e355f2d392a --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.other/lookup19.C @@ -0,0 +1,54 @@ +// Test for proper handling of type lookup for conversion operator names. +// Build don't link: + +// Test 1: Only at file scope +typedef int B; +struct A +{ + int B; + operator B *(); +}; + +A::operator B * () +{ + return 0; +} + +// Test 2: Only at class scope +struct C +{ + typedef int D; + operator D *(); +}; + +int D; +C::operator D * () +{ + return 0; +} + +// Test 3: Matching +struct E +{ + typedef int F; + operator F *(); +}; + +typedef int F; +E::operator F * () +{ + return 0; +} + +// Test 4: Conflicting +struct G +{ + typedef int H; + operator H *(); +}; + +typedef double H; +G::operator H * () // ERROR - mismatch +{ + return 0; +}