[C++ PATCH] [PR9634] A little bit of DR224 (regression on mainline)

Giovanni Bajo giovannibajo@libero.it
Fri Dec 19 18:34:00 GMT 2003


Hello,

This patch makes parser.c follow more strictly DR224: when the name of the
current instantiation of a template (like the injected class name) is used as
qualifier in a nested-name, it is treated as non-dependent. From an user
standpoint, the situation without this patch is a regression because the
well-formed code like in the testcase used to be accepted thanks to the
implicit typename extension in previous GCC versions. More information can be
found in the comments.

The testcase tweak is necessary only if this patch goes in before
http://gcc.gnu.org/ml/gcc-patches/2003-12/msg01698.html, becuase otherwise it
would trigger an ICE. The hunk in cp_parser_class_head is necessary to fix that
situation, the following code really can't handle error_mark_node so it seems
feasable to just go out.

Tested on i686-pc-linux-gnu (rebuild v3 & libjava, check-c++), no new
regressions. OK for mainline?

Giovanni Bajo




2003-12-19  Giovanni Bajo  <giovannibajo@gcc.gnu.org>

        PR c++/9634
        * parser.c (cp_parser_lookup_name): When looking up a qualified id,
        if the scope is the currently open class, try to look inside it
        immediatly.
        (cp_parser_class_head): Exit early if the typename type can't be
        resolved.


2003-12-19  Giovanni Bajo  <giovannibajo@gcc.gnu.org>

        PR c++/9634
        * g++.dg/template/qualttp10.C: Keyword 'template' is not needed
        anymore, and removing it workarounds another problem.
        * g++.dg/template/dependent-name3.C: New test.


Index: parser.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/parser.c,v
retrieving revision 1.137
diff -c -3 -p -r1.137 parser.c
*** parser.c    18 Dec 2003 11:50:58 -0000      1.137
--- parser.c    19 Dec 2003 16:59:44 -0000
*************** cp_parser_class_head (cp_parser* parser,
*** 11861,11866 ****
--- 11861,11867 ----
            {
              cp_parser_error (parser, "could not resolve typename type");
              type = error_mark_node;
+             goto done;
            }
        }

*************** cp_parser_lookup_name (cp_parser *parser
*** 13317,13326 ****
         the template is instantiated -- unless we are explicitly
         looking up names in uninstantiated templates.  Even then, we
         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));
        if ((check_dependency || !CLASS_TYPE_P (parser->scope))
           && dependent_p)
--- 13318,13331 ----
         the template is instantiated -- unless we are explicitly
         looking up names in uninstantiated templates.  Even then, we
         cannot look up the name if the scope is not a class type; it
!        might, for example, be a template type parameter.
!
!        DR224 says that the name of the current instantiation of a
!        class template, when forming the scope of a qualified id,
!        does not make teh ID dependent. Thus, if the current scope is
!        the currently open class, we just treat it as non-dependent.  */
        dependent_p = (TYPE_P (parser->scope)
!                    && !currently_open_class (parser->scope)
                     && dependent_type_p (parser->scope));
        if ((check_dependency || !CLASS_TYPE_P (parser->scope))
           && dependent_p)
*************** cp_parser_lookup_name (cp_parser *parser
*** 13352,13357 ****
--- 13357,13380 ----
                                        /*complain=*/true);
          if (dependent_p)
            pop_scope (parser->scope);
+         /* If the scope is the current class, and it is a template, and
+            the lookup failed, defer it until instantiation time to take
+            care of dependent bases.  Consider:
+
+            template <class> struct A {
+               typedef int K;
+            };
+            template <class T> struct B : A<T> {
+               B::K t;
+            };
+
+            At parsing time, the lookup for K inside B will fail, but
+            at instantiation time it will succeed.  */
+         if (decl == error_mark_node && is_type
+             && currently_open_class (parser->scope)
+             && dependent_type_p (parser->scope))
+           decl = TYPE_NAME (make_typename_type (parser->scope, name,
+                                                 /*complain=*/1));
        }
        parser->qualifying_scope = parser->scope;
        parser->object_scope = NULL_TREE;
Index: g++.dg/template/qualttp10.C
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/g++.dg/template/qualttp10.C,v
retrieving revision 1.1
diff -c -3 -p -r1.1 qualttp10.C
*** g++.dg/template/qualttp10.C 23 Oct 2001 09:14:15 -0000      1.1
--- g++.dg/template/qualttp10.C 19 Dec 2003 15:29:51 -0000
*************** template <template <class> class TT> cla
*** 7,13 ****

  template <class T> struct D {
        template <class U> class B {};
!       C<D<T>::template B> c;
  };

  D<int> d;
--- 7,13 ----

  template <class T> struct D {
        template <class U> class B {};
!       C<D<T>::B> c;
  };

  D<int> d;



// { dg-do compile }
// 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 "" }
};




More information about the Gcc-patches mailing list