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
This commit is contained in:
Mark Mitchell 1999-04-16 00:15:26 +00:00 committed by Mark Mitchell
parent a9ba8a8858
commit 235f734d82
4 changed files with 112 additions and 48 deletions

View File

@ -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.

View File

@ -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))
&& 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)))))
{
val = BINDING_TYPE (val);
break;
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)

View File

@ -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;

View File

@ -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;
}