OSDN Git Service

PR c++/9634
authorjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 4 Mar 2009 18:42:17 +0000 (18:42 +0000)
committerjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 4 Mar 2009 18:42:17 +0000 (18:42 +0000)
        PR c++/29469
        PR c++/29607
        * decl.c (make_typename_type): Do look inside currently open classes.
        * parser.c (cp_parser_lookup_name): Likewise.
        (cp_parser_template_name): Likewise.
        * pt.c (dependent_scope_p): New function.
        * cp-tree.h: Declare it.
        * class.c (currently_open_class): Return fast if T isn't a class.

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

gcc/cp/ChangeLog
gcc/cp/class.c
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/parser.c
gcc/cp/pt.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/template/dependent-name5.C [new file with mode: 0644]

index 9d1ab5a..30034b1 100644 (file)
@@ -1,3 +1,15 @@
+2009-03-04  Jason Merrill  <jason@redhat.com>
+
+       PR c++/9634
+       PR c++/29469
+       PR c++/29607
+       * decl.c (make_typename_type): Do look inside currently open classes.
+       * parser.c (cp_parser_lookup_name): Likewise.
+       (cp_parser_template_name): Likewise.
+       * pt.c (dependent_scope_p): New function.
+       * cp-tree.h: Declare it.
+       * class.c (currently_open_class): Return fast if T isn't a class.
+
 2009-02-26  H.J. Lu  <hongjiu.lu@intel.com>
 
        PR c++/37789
index 13fa990..ae89218 100644 (file)
@@ -5787,6 +5787,9 @@ currently_open_class (tree t)
 {
   int i;
 
+  if (!CLASS_TYPE_P (t))
+    return false;
+
   /* We start looking from 1 because entry 0 is from global scope,
      and has no type.  */
   for (i = current_class_depth; i > 0; --i)
index 46ff922..b6bf7d4 100644 (file)
@@ -4594,6 +4594,7 @@ extern struct tinst_level *current_instantiation(void);
 extern tree maybe_get_template_decl_from_type_decl (tree);
 extern int processing_template_parmlist;
 extern bool dependent_type_p                   (tree);
+extern bool dependent_scope_p                  (tree);
 extern bool any_dependent_template_arguments_p  (const_tree);
 extern bool dependent_template_p               (tree);
 extern bool dependent_template_id_p            (tree, tree);
index 551764d..ddd133a 100644 (file)
@@ -2977,12 +2977,6 @@ make_typename_type (tree context, tree name, enum tag_types tag_type,
   gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE);
   gcc_assert (TYPE_P (context));
 
-  /* 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 (!MAYBE_CLASS_TYPE_P (context))
     {
       if (complain & tf_error)
@@ -2990,11 +2984,23 @@ make_typename_type (tree context, tree name, enum tag_types tag_type,
       return error_mark_node;
     }
   
+  /* When the CONTEXT is a dependent type,  NAME could refer to a
+     dependent base class of CONTEXT.  But look inside it anyway
+     if CONTEXT is a currently open scope, in case it refers to a
+     member of the current instantiation or a non-dependent base;
+     lookup will stop when we hit a dependent base.  */
+  if (!dependent_scope_p (context))
+    /* 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);
+  else
+    t = NULL_TREE;
+
+  if (!t && dependent_type_p (context)) 
+    return build_typename_type (context, name, fullname, tag_type);
+
   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)
index 80a767e..f07df91 100644 (file)
@@ -10323,7 +10323,7 @@ cp_parser_template_name (cp_parser* parser,
          && !template_keyword_p
          && parser->scope && TYPE_P (parser->scope)
          && check_dependency_p
-         && dependent_type_p (parser->scope)
+         && dependent_scope_p (parser->scope)
          /* Do not do this for dtors (or ctors), since they never
             need the template keyword before their name.  */
          && !constructor_name_p (identifier, parser->scope))
@@ -17023,35 +17023,11 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
         cannot look up the name if the scope is not a class type; it
         might, for example, be a template type parameter.  */
       dependent_p = (TYPE_P (parser->scope)
-                    && !(parser->in_declarator_p
-                         && currently_open_class (parser->scope))
-                    && dependent_type_p (parser->scope));
+                    && dependent_scope_p (parser->scope));
       if ((check_dependency || !CLASS_TYPE_P (parser->scope))
-          && dependent_p)
-       {
-         if (tag_type)
-           {
-             tree type;
-
-             /* The resolution to Core Issue 180 says that `struct
-                A::B' should be considered a type-name, even if `A'
-                is dependent.  */
-             type = make_typename_type (parser->scope, name, tag_type,
-                                        /*complain=*/tf_error);
-             decl = TYPE_NAME (type);
-           }
-         else if (is_template
-                  && (cp_parser_next_token_ends_template_argument_p (parser)
-                      || cp_lexer_next_token_is (parser->lexer,
-                                                 CPP_CLOSE_PAREN)))
-           decl = make_unbound_class_template (parser->scope,
-                                               name, NULL_TREE,
-                                               /*complain=*/tf_error);
-         else
-           decl = build_qualified_name (/*type=*/NULL_TREE,
-                                        parser->scope, name,
-                                        is_template);
-       }
+         && dependent_p)
+       /* Defer lookup.  */
+       decl = error_mark_node;
       else
        {
          tree pushed_scope = NULL_TREE;
@@ -17072,14 +17048,42 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
                                        /*complain=*/true);
 
          /* If we have a single function from a using decl, pull it out.  */
-         if (decl
-             && TREE_CODE (decl) == OVERLOAD
+         if (TREE_CODE (decl) == OVERLOAD
              && !really_overloaded_fn (decl))
            decl = OVL_FUNCTION (decl);
 
          if (pushed_scope)
            pop_scope (pushed_scope);
        }
+
+      /* If the scope is a dependent type and either we deferred lookup or
+        we did lookup but didn't find the name, rememeber the name.  */
+      if (decl == error_mark_node && TYPE_P (parser->scope)
+         && dependent_type_p (parser->scope))
+       {
+         if (tag_type)
+           {
+             tree type;
+
+             /* The resolution to Core Issue 180 says that `struct
+                A::B' should be considered a type-name, even if `A'
+                is dependent.  */
+             type = make_typename_type (parser->scope, name, tag_type,
+                                        /*complain=*/tf_error);
+             decl = TYPE_NAME (type);
+           }
+         else if (is_template
+                  && (cp_parser_next_token_ends_template_argument_p (parser)
+                      || cp_lexer_next_token_is (parser->lexer,
+                                                 CPP_CLOSE_PAREN)))
+           decl = make_unbound_class_template (parser->scope,
+                                               name, NULL_TREE,
+                                               /*complain=*/tf_error);
+         else
+           decl = build_qualified_name (/*type=*/NULL_TREE,
+                                        parser->scope, name,
+                                        is_template);
+       }
       parser->qualifying_scope = parser->scope;
       parser->object_scope = NULL_TREE;
     }
index dacc868..8ae4ed5 100644 (file)
@@ -16067,6 +16067,16 @@ dependent_type_p (tree type)
   return TYPE_DEPENDENT_P (type);
 }
 
+/* Returns TRUE if SCOPE is a dependent scope, in which we can't do any
+   lookup.  In other words, a dependent type that is not the current
+   instantiation.  */
+
+bool
+dependent_scope_p (tree scope)
+{
+  return dependent_type_p (scope) && !currently_open_class (scope);
+}
+
 /* Returns TRUE if EXPRESSION is dependent, according to CRITERION.  */
 
 static bool
@@ -16088,7 +16098,7 @@ dependent_scope_ref_p (tree expression, bool criterion (tree))
      An id-expression is type-dependent if it contains a
      nested-name-specifier that contains a class-name that names a
      dependent type.  */
-  /* The suggested resolution to Core Issue 2 implies that if the
+  /* The suggested resolution to Core Issue 224 implies that if the
      qualifying type is the current class, then we must peek
      inside it.  */
   if (DECL_P (name)
index e1cbbc7..97668fd 100644 (file)
@@ -1,3 +1,11 @@
+2009-03-04  Jason Merrill  <jason@redhat.com>
+           Giovanni Bajo  <giovannibajo@gcc.gnu.org>
+
+       PR c++/9634
+       PR c++/29469
+       PR c++/29607
+       * g++.dg/template/dependent-name5.C: New test.
+
 2009-03-04  Steve Ellcey  <sje@cup.hp.com>
 
        PR testsuite/39357
diff --git a/gcc/testsuite/g++.dg/template/dependent-name5.C b/gcc/testsuite/g++.dg/template/dependent-name5.C
new file mode 100644 (file)
index 0000000..681060c
--- /dev/null
@@ -0,0 +1,45 @@
+// PR c++/9634, c++/29469, c++/29607
+// Contributed by: Giovanni Bajo <giovannibajo at gcc dot gnu dot org>
+// DR224: Make sure that a name is *truly* semantically dependent.
+
+struct D {
+  typedef int K;
+};
+
+template <typename T>
+struct A
+{
+  typedef int Bar;
+
+  template <typename>
+  struct N {};
+
+  typedef Bar          type1;
+  typedef A::Bar       type2;
+  typedef A<T>::Bar    type3;
+  typedef A<T*>::Bar    type4;  // { dg-error "" }
+  typedef typename A<T*>::Bar type5;
+
+  typedef N<int>       type6;
+  typedef A::N<int>    type7;
+  typedef A<T>::N<int> type8;
+  typedef A<T*>::template N<int> type9;  // { dg-error "" }
+  typedef typename A<T*>::template N<int> type10;
+
+  typedef D Bar2;
+  struct N2 { typedef int K; };
+
+  // Check that A::N2 is still considered dependent (because it
+  //  could be specialized), while A::Bar2 (being just ::D) is not.
+  typedef A::Bar2 type11;
+  typedef type11::K k3;
+
+  typedef A::N2 type12;
+  typedef typename type12::K k2;
+  typedef type12::K k1;  // { dg-error "" }
+
+  // Check that A::Bar2 is not considered dependent even if we use
+  // the typename keyword.
+  typedef typename A::Bar2 type13;
+  typedef type13::K k4;
+};