This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

C++ PATCH for implicit typename extension



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)


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]