]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR c++/9634 ([DR224] Injected class name as qualifier should not make the name...
authorJason Merrill <jason@redhat.com>
Wed, 4 Mar 2009 18:42:17 +0000 (13:42 -0500)
committerJason Merrill <jason@gcc.gnu.org>
Wed, 4 Mar 2009 18:42:17 +0000 (13:42 -0500)
        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.

Co-Authored-By: Giovanni Bajo <giovannibajo@gcc.gnu.org>
From-SVN: r144618

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 9d1ab5a6211c6c9c5f1c78101bc1f75c6ce4cfc6..30034b1e575d2e8155a5712b04efe98106c752d7 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 13fa99027aaead017db1af74b144f2183c7a8dcc..ae89218a700d0a5001c9de2a2f0df3bace65241a 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 46ff9222b976162ad320e026c017de2c86a8e235..b6bf7d40da0939c5ff87ddc4b4afdd0d4fe5ed37 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 551764dc29cc077a7a40f05338a39b5034daf42a..ddd133ae2ea68085f630edb2ede2c74f40945d86 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 80a767ebe2d45c87bec46903fd81e7859d2a8e08..f07df913447f82fa66fa1bc03012fb55f3e2ae85 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 dacc8689f38a8cdf7e2f509f0b6b1505932b4e3d..8ae4ed511cc4260d6e8bc54aed69a39eead12cc5 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 e1cbbc73365a35c05a4640b01d53cbbae148e329..97668fd82dfdfd798028983b942f4947c10e9beb 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;
+};