diff options
author | Mark Mitchell <mark@codesourcery.com> | 1999-04-16 00:15:26 +0000 |
---|---|---|
committer | Mark Mitchell <mmitchel@gcc.gnu.org> | 1999-04-16 00:15:26 +0000 |
commit | 235f734d821eb0b079d551de729b56cb97800676 (patch) | |
tree | 36e9d12d45904be2c30de0bc4854d6d8427051d9 /gcc | |
parent | a9ba8a885857f6b7a14722dbd741bc07121ee72c (diff) | |
download | gcc-235f734d821eb0b079d551de729b56cb97800676.zip gcc-235f734d821eb0b079d551de729b56cb97800676.tar.gz gcc-235f734d821eb0b079d551de729b56cb97800676.tar.bz2 |
decl.c (warn_about_implicit_typename_lookup): New function.
* decl.c (warn_about_implicit_typename_lookup): New function.
(lookup_name_real): Use it. Rework handling of implicit typename
extension.
From-SVN: r26487
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/cp/decl.c | 109 | ||||
-rw-r--r-- | gcc/testsuite/g++.old-deja/g++.pt/typename18.C | 21 | ||||
-rw-r--r-- | gcc/testsuite/g++.old-deja/g++.pt/typename19.C | 26 |
4 files changed, 113 insertions, 49 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index cdcb7b5..8f61598 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,9 @@ +1999-04-16 Mark Mitchell <mark@codesourcery.com> + + * decl.c (warn_about_implicit_typename_lookup): New function. + (lookup_name_real): Use it. Rework handling of implicit typename + extension. + 1999-04-15 Mark Mitchell <mark@codesourcery.com> * cp-tree.h (lookup_nested_field): Remove. diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 163c3d7..fe30586 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -192,6 +192,7 @@ static const char *tag_name PROTO((enum tag_types code)); static void find_class_binding_level PROTO((void)); static struct binding_level *innermost_nonclass_level PROTO((void)); static tree poplevel_class PROTO((void)); +static void warn_about_implicit_typename_lookup PROTO((tree, tree)); #if defined (DEBUG_CP_BINDING_LEVELS) static void indent PROTO((void)); @@ -5526,6 +5527,32 @@ qualify_lookup (val, flags) return val; } +/* Any other BINDING overrides an implicit TYPENAME. Warn about + that. */ + +static void +warn_about_implicit_typename_lookup (typename, binding) + tree typename; + tree binding; +{ + tree subtype = TREE_TYPE (TREE_TYPE (typename)); + tree name = DECL_NAME (typename); + + if (! (TREE_CODE (binding) == TEMPLATE_DECL + && CLASSTYPE_TEMPLATE_INFO (subtype) + && CLASSTYPE_TI_TEMPLATE (subtype) == binding) + && ! (TREE_CODE (binding) == TYPE_DECL + && same_type_p (TREE_TYPE (binding), subtype))) + { + cp_warning ("lookup of `%D' finds `%#D'", + name, binding); + cp_warning (" instead of `%D' from dependent base class", + typename); + cp_warning (" (use `typename %T::%D' if that's what you meant)", + constructor_name (current_class_type), name); + } +} + /* Look up NAME in the current binding level and its superiors in the namespace of variables, functions and typedefs. Return a ..._DECL node of some kind representing its definition if there is only one @@ -5545,10 +5572,12 @@ lookup_name_real (name, prefer_type, nonclass, namespaces_only) tree name; int prefer_type, nonclass, namespaces_only; { - register tree val; + tree t; + tree val = NULL_TREE; int yylex = 0; tree from_obj = NULL_TREE; int flags; + int val_is_implicit_typename = 0; /* Hack: copy flag set by parser, if set. */ if (only_namespace_names) @@ -5623,67 +5652,49 @@ lookup_name_real (name, prefer_type, nonclass, namespaces_only) } /* First, look in non-namespace scopes. */ - for (val = IDENTIFIER_BINDING (name); val; val = TREE_CHAIN (val)) + for (t = IDENTIFIER_BINDING (name); t; t = TREE_CHAIN (t)) { - if (!LOCAL_BINDING_P (val) && nonclass) + tree binding; + + if (!LOCAL_BINDING_P (t) && nonclass) /* We're not looking for class-scoped bindings, so keep going. */ continue; /* If this is the kind of thing we're looking for, we're done. */ - if (qualify_lookup (BINDING_VALUE (val), flags)) - { - val = BINDING_VALUE (val); - break; - } + if (qualify_lookup (BINDING_VALUE (t), flags)) + binding = BINDING_VALUE (t); else if ((flags & LOOKUP_PREFER_TYPES) - && qualify_lookup (BINDING_TYPE (val), flags)) - { - val = BINDING_TYPE (val); - break; + && qualify_lookup (BINDING_TYPE (t), flags)) + binding = BINDING_TYPE (t); + else + binding = NULL_TREE; + + if (binding + && (!val || !(TREE_CODE (binding) == TYPE_DECL + && IMPLICIT_TYPENAME_P (TREE_TYPE (binding))))) + { + if (val_is_implicit_typename && !yylex) + warn_about_implicit_typename_lookup (val, binding); + val = binding; + val_is_implicit_typename + = (TREE_CODE (val) == TYPE_DECL + && IMPLICIT_TYPENAME_P (TREE_TYPE (val))); + if (!val_is_implicit_typename) + break; } } - /* If we found a type from a dependent base class (using the - implicit typename extension) make sure that there's not some - global name which should be chosen instead. */ - if (val && TREE_CODE (val) == TYPE_DECL - && IMPLICIT_TYPENAME_P (TREE_TYPE (val))) + /* Now lookup in namespace scopes. */ + if (!val || val_is_implicit_typename) { - tree global_val; - - /* Any other name takes precedence over an implicit typename. Warn the - user about this potentially confusing lookup. */ - global_val = unqualified_namespace_lookup (name, flags); - - if (global_val) + t = unqualified_namespace_lookup (name, flags); + if (t) { - tree subtype; - - /* Only warn when not lexing; we don't want to warn if they - use this name as a declarator. */ - subtype = TREE_TYPE (TREE_TYPE (val)); - if (! yylex - && ! (TREE_CODE (global_val) == TEMPLATE_DECL - && CLASSTYPE_TEMPLATE_INFO (subtype) - && CLASSTYPE_TI_TEMPLATE (subtype) == global_val) - && ! (TREE_CODE (global_val) == TYPE_DECL - && same_type_p (TREE_TYPE (global_val), subtype))) - { - cp_warning ("lookup of `%D' finds `%#D'", name, global_val); - cp_warning (" instead of `%D' from dependent base class", - val); - cp_warning (" (use `typename %T::%D' if that's what you meant)", - constructor_name (current_class_type), name); - } - - /* Use the global value instead of the implicit typename. */ - val = global_val; + if (val_is_implicit_typename && !yylex) + warn_about_implicit_typename_lookup (val, t); + val = t; } } - else if (!val) - /* No local, or class-scoped binding. Look for a namespace-scope - declaration. */ - val = unqualified_namespace_lookup (name, flags); done: if (val) diff --git a/gcc/testsuite/g++.old-deja/g++.pt/typename18.C b/gcc/testsuite/g++.old-deja/g++.pt/typename18.C new file mode 100644 index 0000000..ed423e7 --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.pt/typename18.C @@ -0,0 +1,21 @@ +// Build don't link: +// Special g++ Options: +// Origin: Mark Mitchell <mark@codesourcery.com> + +void X(); + +template <class T> +struct J { + typedef T X; +}; + +template <class T> +struct S { + typedef T X; + + struct I : public J<X> { + static X* f(); + }; +}; + +S<int> si; diff --git a/gcc/testsuite/g++.old-deja/g++.pt/typename19.C b/gcc/testsuite/g++.old-deja/g++.pt/typename19.C new file mode 100644 index 0000000..be93a98 --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.pt/typename19.C @@ -0,0 +1,26 @@ +// Special g++ Options: +// Origin: Mark Mitchell <mark@codesourcery.com> + +template <class T> +struct O { + typedef char X; +}; + +template <class T> +struct S { + typedef double X; + + template <class U> + struct I : public O<U> { + static X x; // WARNING - lookup finds S<T>::X + }; +}; + +template <class T> +template <class U> +typename S<T>::X S<T>::I<U>::x; + +int main() +{ + return sizeof (S<int>::I<double>::x) == 1; +} |