This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
C++ PATCH for implicit typename extension
- To: egcs-patches at egcs dot cygnus dot com
- Subject: C++ PATCH for implicit typename extension
- From: Mark Mitchell <mark at codesourcery dot com>
- Date: Fri, 16 Apr 1999 00:16:01 -0700
- Reply-to: mark at codesourcery dot com
Believe it or not, the implicit typename extension still has a few
kinks. Here are two test cases where the extension caused us to fail
to compile perfectly good code.
--
Mark Mitchell mark@codesourcery.com
CodeSourcery, LLC http://www.codesourcery.com
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.
Index: testsuite/g++.old-deja/g++.pt/typename18.C
===================================================================
RCS file: typename18.C
diff -N typename18.C
--- /dev/null Sat Dec 5 20:30:03 1998
+++ typename18.C Fri Apr 16 00:10:30 1999
@@ -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;
Index: testsuite/g++.old-deja/g++.pt/typename19.C
===================================================================
RCS file: typename19.C
diff -N typename19.C
--- /dev/null Sat Dec 5 20:30:03 1998
+++ typename19.C Fri Apr 16 00:10:30 1999
@@ -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;
+}
Index: cp/decl.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/decl.c,v
retrieving revision 1.344
diff -u -p -r1.344 decl.c
--- decl.c 1999/04/15 19:21:18 1.344
+++ decl.c 1999/04/16 07:10:40
@@ -192,6 +192,7 @@ static const char *tag_name PROTO((enum
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, non
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, non
}
/* 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)))
- {
- 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)
- {
- 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;
- }
- }
- else if (!val)
- /* No local, or class-scoped binding. Look for a namespace-scope
- declaration. */
- val = unqualified_namespace_lookup (name, flags);
+ /* Now lookup in namespace scopes. */
+ if (!val || val_is_implicit_typename)
+ {
+ t = unqualified_namespace_lookup (name, flags);
+ if (t)
+ {
+ if (val_is_implicit_typename && !yylex)
+ warn_about_implicit_typename_lookup (val, t);
+ val = t;
+ }
+ }
done:
if (val)