aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorMark Mitchell <mark@codesourcery.com>1999-04-16 00:15:26 +0000
committerMark Mitchell <mmitchel@gcc.gnu.org>1999-04-16 00:15:26 +0000
commit235f734d821eb0b079d551de729b56cb97800676 (patch)
tree36e9d12d45904be2c30de0bc4854d6d8427051d9 /gcc
parenta9ba8a885857f6b7a14722dbd741bc07121ee72c (diff)
downloadgcc-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/ChangeLog6
-rw-r--r--gcc/cp/decl.c109
-rw-r--r--gcc/testsuite/g++.old-deja/g++.pt/typename18.C21
-rw-r--r--gcc/testsuite/g++.old-deja/g++.pt/typename19.C26
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;
+}