cp/
authornathan <nathan@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 25 Aug 2006 16:56:07 +0000 (16:56 +0000)
committernathan <nathan@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 25 Aug 2006 16:56:07 +0000 (16:56 +0000)
PR c++/27787
* decl.c (make_typename_type): Only try and resolve it when
context is not dependent.  Refactor.
* decl2.c (check_classfn): Push to class scope before looking for
the function.
testsuite/
PR c++/27787
* g++.dg/template/typename10.C: New.
* g++.dg/template/lookup4.C: Remove bogus error marker.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@116409 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/cp/ChangeLog
gcc/cp/decl.c
gcc/cp/decl2.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/template/lookup4.C
gcc/testsuite/g++.dg/template/typename10.C [new file with mode: 0644]

index c3bb4f3..629ba67 100644 (file)
@@ -1,3 +1,11 @@
+2006-08-25  Nathan Sidwell  <nathan@codesourcery.com>
+
+       PR c++/27787
+       * decl.c (make_typename_type): Only try and resolve it when
+       context is not dependent.  Refactor.
+       * decl2.c (check_classfn): Push to class scope before looking for
+       the function.
+
 2006-08-24  Danny Smith   <dannysmith@users.sourceforge.net>
 
        PR driver/28528
index f454596..8ba2a13 100644 (file)
@@ -2779,6 +2779,8 @@ make_typename_type (tree context, tree name, enum tag_types tag_type,
                    tsubst_flags_t complain)
 {
   tree fullname;
+  tree t;
+  bool want_template;
 
   if (name == error_mark_node
       || context == NULL_TREE
@@ -2816,73 +2818,60 @@ make_typename_type (tree context, tree name, enum tag_types tag_type,
   gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE);
   gcc_assert (TYPE_P (context));
 
-  if (!dependent_type_p (context)
-      || currently_open_class (context))
-    {
-      if (TREE_CODE (fullname) == TEMPLATE_ID_EXPR)
-       {
-         tree tmpl = NULL_TREE;
-         if (IS_AGGR_TYPE (context))
-           tmpl = lookup_field (context, name, 0, false);
-         if (!tmpl || !DECL_CLASS_TEMPLATE_P (tmpl))
-           {
-             if (complain & tf_error)
-               error ("no class template named %q#T in %q#T",
-                      name, context);
-             return error_mark_node;
-           }
-
-         if (complain & tf_error)
-           perform_or_defer_access_check (TYPE_BINFO (context), tmpl);
-
-         return lookup_template_class (tmpl,
-                                       TREE_OPERAND (fullname, 1),
-                                       NULL_TREE, context,
-                                       /*entering_scope=*/0,
-                                       tf_warning_or_error | tf_user);
-       }
-      else
-       {
-         tree t;
+  /* When the CONTEXT is a dependent type,  NAME could refer to a
+     dependent base class of CONTEXT.  So we cannot peek inside it,
+     even if CONTEXT is a currently open scope.  */
+  if (dependent_type_p (context))
+    return build_typename_type (context, name, fullname, tag_type);
 
-         if (!IS_AGGR_TYPE (context))
-           {
-             if (complain & tf_error)
-               error ("no type named %q#T in %q#T", name, context);
-             return error_mark_node;
-           }
-
-         t = lookup_field (context, name, 0, true);
-         if (t)
-           {
-             if (TREE_CODE (t) != TYPE_DECL)
-               {
-                 if (complain & tf_error)
-                   error ("no type named %q#T in %q#T", name, context);
-                 return error_mark_node;
-               }
-
-             if (complain & tf_error)
-               perform_or_defer_access_check (TYPE_BINFO (context), t);
-
-             if (DECL_ARTIFICIAL (t) || !(complain & tf_keep_type_decl))
-               t = TREE_TYPE (t);
-
-             return t;
-           }
-       }
+  if (!IS_AGGR_TYPE (context))
+    {
+      if (complain & tf_error)
+       error ("%q#T is not a class", context);
+      return error_mark_node;
     }
-
-  /* If the CONTEXT is not a template type, then either the field is
-     there now or its never going to be.  */
-  if (!dependent_type_p (context))
+  
+  want_template = TREE_CODE (fullname) == TEMPLATE_ID_EXPR;
+  
+  /* We should only set WANT_TYPE when we're a nested typename type.
+     Then we can give better diagnostics if we find a non-type.  */
+  t = lookup_field (context, name, 0, /*want_type=*/true);
+  if (!t)
     {
       if (complain & tf_error)
-       error ("no type named %q#T in %q#T", name, context);
+       error (want_template ? "no class template named %q#T in %q#T"
+              : "no type named %q#T in %q#T", name, context);
       return error_mark_node;
     }
-
-  return build_typename_type (context, name, fullname, tag_type);
+  
+  if (want_template && !DECL_CLASS_TEMPLATE_P (t))
+    {
+      if (complain & tf_error)
+       error ("%<typename %T::%D%> names %q#T, which is not a class template",
+              context, name, t);
+      return error_mark_node;
+    }
+  if (!want_template && TREE_CODE (t) != TYPE_DECL)
+    {
+      if (complain & tf_error)
+       error ("%<typename %T::%D%> names %q#T, which is not a type",
+              context, name, t);
+      return error_mark_node;
+    }
+  
+  if (complain & tf_error)
+    perform_or_defer_access_check (TYPE_BINFO (context), t);
+
+  if (want_template)
+    return lookup_template_class (t, TREE_OPERAND (fullname, 1),
+                                 NULL_TREE, context,
+                                 /*entering_scope=*/0,
+                                 tf_warning_or_error | tf_user);
+  
+  if (DECL_ARTIFICIAL (t) || !(complain & tf_keep_type_decl))
+    t = TREE_TYPE (t);
+  
+  return t;
 }
 
 /* Resolve `CONTEXT::template NAME'.  Returns a TEMPLATE_DECL if the name
index 0de2756..db1e917 100644 (file)
@@ -553,7 +553,8 @@ check_classfn (tree ctype, tree function, tree template_parms)
 {
   int ix;
   bool is_template;
-
+  tree pushed_scope;
+  
   if (DECL_USE_TEMPLATE (function)
       && !(TREE_CODE (function) == TEMPLATE_DECL
           && DECL_TEMPLATE_SPECIALIZATION (function))
@@ -583,16 +584,18 @@ check_classfn (tree ctype, tree function, tree template_parms)
   /* OK, is this a definition of a member template?  */
   is_template = (template_parms != NULL_TREE);
 
+  /* We must enter the scope here, because conversion operators are
+     named by target type, and type equivalence relies on typenames
+     resolving within the scope of CTYPE.  */
+  pushed_scope = push_scope (ctype);
   ix = class_method_index_for_fn (complete_type (ctype), function);
   if (ix >= 0)
     {
       VEC(tree,gc) *methods = CLASSTYPE_METHOD_VEC (ctype);
       tree fndecls, fndecl = 0;
       bool is_conv_op;
-      tree pushed_scope;
       const char *format = NULL;
 
-      pushed_scope = push_scope (ctype);
       for (fndecls = VEC_index (tree, methods, ix);
           fndecls; fndecls = OVL_NEXT (fndecls))
        {
@@ -631,10 +634,13 @@ check_classfn (tree ctype, tree function, tree template_parms)
                      == DECL_TI_TEMPLATE (fndecl))))
            break;
        }
-      if (pushed_scope)
-       pop_scope (pushed_scope);
       if (fndecls)
-       return OVL_CURRENT (fndecls);
+       {
+         if (pushed_scope)
+           pop_scope (pushed_scope);
+         return OVL_CURRENT (fndecls);
+       }
+      
       error ("prototype for %q#D does not match any in class %qT",
             function, ctype);
       is_conv_op = DECL_CONV_FN_P (fndecl);
@@ -682,6 +688,9 @@ check_classfn (tree ctype, tree function, tree template_parms)
      properly within the class.  */
   if (COMPLETE_TYPE_P (ctype))
     add_method (ctype, function, NULL_TREE);
+  
+  if (pushed_scope)
+    pop_scope (pushed_scope);
   return NULL_TREE;
 }
 
index 2a1485c..8e9e60a 100644 (file)
@@ -1,3 +1,9 @@
+2006-08-25  Nathan Sidwell  <nathan@codesourcery.com>
+
+       PR c++/27787
+       * g++.dg/template/typename10.C: New.
+       * g++.dg/template/lookup4.C: Remove bogus error marker.
+
 2006-08-25  Richard Guenther  <rguenther@suse.de>
 
        PR testsuite/28829
index d640061..3bd73a3 100644 (file)
@@ -2,5 +2,5 @@
 
 template <class T> struct Base {};
 template <class T> struct Derived: public Base<T> {
-  typename Derived::template Base<double>* p1; // { dg-error "" }
+  typename Derived::template Base<double>* p1;
 };
diff --git a/gcc/testsuite/g++.dg/template/typename10.C b/gcc/testsuite/g++.dg/template/typename10.C
new file mode 100644 (file)
index 0000000..f6f9931
--- /dev/null
@@ -0,0 +1,24 @@
+// { dg-do compile }
+
+// Copyright (C) 2006 Free Software Foundation, Inc.
+// Contributed by Nathan Sidwell 25 Aug 2006 <nathan@codesourcery.com>
+
+// Origin: Tobias Schwinger <tschwinger@neoscientists.org>
+// PR 27787. Too eager to resolve a typename
+
+template<typename X>
+struct x
+{
+  template<typename Y>
+  struct y
+  {
+    typedef Y type;
+  };
+};
+
+template<typename A>
+struct a : x<A>
+{
+  template<typename B>
+  typename a::template y<B>::type f(B);
+};