OSDN Git Service

cp/
authornathan <nathan@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 22 Jul 2007 16:25:54 +0000 (16:25 +0000)
committernathan <nathan@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 22 Jul 2007 16:25:54 +0000 (16:25 +0000)
PR c++/30818
* typeck.c (structural_comptypes): No need to check
resolve_typename_type return value here.
* cp-tree.h (TYPENAME_IS_RESOLVING_P): New.
* pt.c (resolve_typename_type): Follow typename typedefs.  Return
original type rather than error_mark_node in case of failure.
* parser.c (cp_parser_nested_name_specifier_opt): Adjust
resolve_typename_type result check.
(cp_parser_direct_declarator, cp_parser_head,
cp_parser_constructor_declarator_p): Likewise.

testsuite/
PR c++/30818
* g++.dg/template/crash47.C: Adjust errors.
* g++.dg/template/crash48.C: Adjust errors.
* g++.dg/template/typename12.C: New.
* g++.dg/template/typename13.C: New.
* g++.dg/template/typename14.C: New.
* g++.dg/template/typedef6.C: Adjust errors.

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

12 files changed:
gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/parser.c
gcc/cp/pt.c
gcc/cp/typeck.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/template/crash47.C
gcc/testsuite/g++.dg/template/crash48.C
gcc/testsuite/g++.dg/template/typedef6.C
gcc/testsuite/g++.dg/template/typename12.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/typename13.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/typename14.C [new file with mode: 0644]

index 192c8f4..6faa01f 100644 (file)
@@ -1,3 +1,16 @@
+2007-07-22  Nathan Sidwell  <nathan@codesourcery.com>
+
+       PR c++/30818
+       * typeck.c (structural_comptypes): No need to check
+       resolve_typename_type return value here.
+       * cp-tree.h (TYPENAME_IS_RESOLVING_P): New.
+       * pt.c (resolve_typename_type): Follow typename typedefs.  Return
+       original type rather than error_mark_node in case of failure.
+       * parser.c (cp_parser_nested_name_specifier_opt): Adjust
+       resolve_typename_type result check.
+       (cp_parser_direct_declarator, cp_parser_head,
+       cp_parser_constructor_declarator_p): Likewise.
+
 2007-07-12  Kazu Hirata  <kazu@codesourcery.com>
 
        * pt.c (template_parms_variadic_p): Remove.
index 8604447..e440171 100644 (file)
@@ -71,6 +71,7 @@ struct diagnostic_context;
       ICS_THIS_FLAG (in _CONV)
       DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (in VAR_DECL)
       STATEMENT_LIST_TRY_BLOCK (in STATEMENT_LIST)
+      TYPENAME_IS_RESOLVING_P (in TYPE_NAME_TYPE)
    3: (TREE_REFERENCE_EXPR) (in NON_LVALUE_EXPR) (commented-out).
       ICS_BAD_FLAG (in _CONV)
       FN_TRY_BLOCK_P (in TRY_BLOCK)
@@ -2589,6 +2590,10 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter)
 #define TYPENAME_IS_CLASS_P(NODE) \
   (TREE_LANG_FLAG_1 (TYPENAME_TYPE_CHECK (NODE)))
 
+/* True if a TYPENAME_TYPE is in the process of being resolved.  */
+#define TYPENAME_IS_RESOLVING_P(NODE) \
+  (TREE_LANG_FLAG_2 (TYPENAME_TYPE_CHECK (NODE)))
+
 /* Nonzero in INTEGER_CST means that this int is negative by dint of
    using a twos-complement negated operand.  */
 #define TREE_NEGATED_INT(NODE) TREE_LANG_FLAG_0 (INTEGER_CST_CHECK (NODE))
index b49b9f8..458d300 100644 (file)
@@ -3922,7 +3922,7 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
            {
              new_scope = resolve_typename_type (parser->scope,
                                                 /*only_current_p=*/false);
-             if (new_scope != error_mark_node)
+             if (TREE_CODE (new_scope) != TYPENAME_TYPE)
                parser->scope = new_scope;
            }
          success = true;
@@ -12464,7 +12464,7 @@ cp_parser_direct_declarator (cp_parser* parser,
              type = resolve_typename_type (qualifying_scope,
                                            /*only_current_p=*/false);
              /* If that failed, the declarator is invalid.  */
-             if (type == error_mark_node)
+             if (TREE_CODE (type) == TYPENAME_TYPE)
                error ("%<%T::%E%> is not a type",
                       TYPE_CONTEXT (qualifying_scope),
                       TYPE_IDENTIFIER (qualifying_scope));
@@ -14282,7 +14282,7 @@ cp_parser_class_head (cp_parser* parser,
        {
          class_type = resolve_typename_type (TREE_TYPE (type),
                                              /*only_current_p=*/false);
-         if (class_type != error_mark_node)
+         if (TREE_CODE (class_type) != TYPENAME_TYPE)
            type = TYPE_NAME (class_type);
          else
            {
@@ -16291,7 +16291,7 @@ cp_parser_constructor_declarator_p (cp_parser *parser, bool friend_p)
                {
                  type = resolve_typename_type (type,
                                                /*only_current_p=*/false);
-                 if (type == error_mark_node)
+                 if (TREE_CODE (type) == TYPENAME_TYPE)
                    {
                      cp_parser_abort_tentative_parse (parser);
                      return false;
index 3ff4706..86b8eee 100644 (file)
@@ -15457,11 +15457,12 @@ dependent_template_id_p (tree tmpl, tree args)
 }
 
 /* TYPE is a TYPENAME_TYPE.  Returns the ordinary TYPE to which the
-   TYPENAME_TYPE corresponds.  Returns ERROR_MARK_NODE if no such TYPE
-   can be found.  Note that this function peers inside uninstantiated
-   templates and therefore should be used only in extremely limited
-   situations.  ONLY_CURRENT_P restricts this peering to the currently
-   open classes hierarchy (which is required when comparing types).  */
+   TYPENAME_TYPE corresponds.  Returns the original TYPENAME_TYPE if
+   no such TYPE can be found.  Note that this function peers inside
+   uninstantiated templates and therefore should be used only in
+   extremely limited situations.  ONLY_CURRENT_P restricts this
+   peering to the currently open classes hierarchy (which is required
+   when comparing types).  */
 
 tree
 resolve_typename_type (tree type, bool only_current_p)
@@ -15471,6 +15472,7 @@ resolve_typename_type (tree type, bool only_current_p)
   tree decl;
   int quals;
   tree pushed_scope;
+  tree result;
 
   gcc_assert (TREE_CODE (type) == TYPENAME_TYPE);
 
@@ -15483,8 +15485,8 @@ resolve_typename_type (tree type, bool only_current_p)
     scope = resolve_typename_type (scope, only_current_p);
   /* If we don't know what SCOPE refers to, then we cannot resolve the
      TYPENAME_TYPE.  */
-  if (scope == error_mark_node || TREE_CODE (scope) == TYPENAME_TYPE)
-    return error_mark_node;
+  if (TREE_CODE (scope) == TYPENAME_TYPE)
+    return type;
   /* If the SCOPE is a template type parameter, we have no way of
      resolving the name.  */
   if (TREE_CODE (scope) == TEMPLATE_TYPE_PARM)
@@ -15492,7 +15494,7 @@ resolve_typename_type (tree type, bool only_current_p)
   /* If the SCOPE is not the current instantiation, there's no reason
      to look inside it.  */
   if (only_current_p && !currently_open_class (scope))
-    return error_mark_node;
+    return type;
   /* If SCOPE is a partial instantiation, it will not have a valid
      TYPE_FIELDS list, so use the original template.  */
   scope = CLASSTYPE_PRIMARY_TEMPLATE_TYPE (scope);
@@ -15502,15 +15504,20 @@ resolve_typename_type (tree type, bool only_current_p)
   pushed_scope = push_scope (scope);
   /* Look up the declaration.  */
   decl = lookup_member (scope, name, /*protect=*/0, /*want_type=*/true);
-  /* Obtain the set of qualifiers applied to the TYPE.  */
-  quals = cp_type_quals (type);
+
+  result = NULL_TREE;
+  
   /* For a TYPENAME_TYPE like "typename X::template Y<T>", we want to
      find a TEMPLATE_DECL.  Otherwise, we want to find a TYPE_DECL.  */
   if (!decl)
-    type = error_mark_node;
+    /*nop*/;
   else if (TREE_CODE (TYPENAME_TYPE_FULLNAME (type)) == IDENTIFIER_NODE
           && TREE_CODE (decl) == TYPE_DECL)
-    type = TREE_TYPE (decl);
+    {
+      result = TREE_TYPE (decl);
+      if (result == error_mark_node)
+       result = NULL_TREE;
+    }
   else if (TREE_CODE (TYPENAME_TYPE_FULLNAME (type)) == TEMPLATE_ID_EXPR
           && DECL_CLASS_TEMPLATE_P (decl))
     {
@@ -15520,19 +15527,37 @@ resolve_typename_type (tree type, bool only_current_p)
       tmpl = TREE_OPERAND (TYPENAME_TYPE_FULLNAME (type), 0);
       args = TREE_OPERAND (TYPENAME_TYPE_FULLNAME (type), 1);
       /* Instantiate the template.  */
-      type = lookup_template_class (tmpl, args, NULL_TREE, NULL_TREE,
-                                   /*entering_scope=*/0, tf_error | tf_user);
+      result = lookup_template_class (tmpl, args, NULL_TREE, NULL_TREE,
+                                     /*entering_scope=*/0,
+                                     tf_error | tf_user);
+      if (result == error_mark_node)
+       result = NULL_TREE;
     }
-  else
-    type = error_mark_node;
-  /* Qualify the resulting type.  */
-  if (type != error_mark_node && quals)
-    type = cp_build_qualified_type (type, quals);
+  
   /* Leave the SCOPE.  */
   if (pushed_scope)
     pop_scope (pushed_scope);
 
-  return type;
+  /* If we failed to resolve it, return the original typename.  */
+  if (!result)
+    return type;
+  
+  /* If lookup found a typename type, resolve that too.  */
+  if (TREE_CODE (result) == TYPENAME_TYPE && !TYPENAME_IS_RESOLVING_P (result))
+    {
+      /* Ill-formed programs can cause infinite recursion here, so we
+        must catch that.  */
+      TYPENAME_IS_RESOLVING_P (type) = 1;
+      result = resolve_typename_type (result, only_current_p);
+      TYPENAME_IS_RESOLVING_P (type) = 0;
+    }
+  
+  /* Qualify the resulting type.  */
+  quals = cp_type_quals (type);
+  if (quals)
+    result = cp_build_qualified_type (result, cp_type_quals (result) | quals);
+
+  return result;
 }
 
 /* EXPR is an expression which is not type-dependent.  Return a proxy
index 4f08c8e..7e59ec3 100644 (file)
@@ -943,20 +943,10 @@ structural_comptypes (tree t1, tree t2, int strict)
   /* TYPENAME_TYPEs should be resolved if the qualifying scope is the
      current instantiation.  */
   if (TREE_CODE (t1) == TYPENAME_TYPE)
-    {
-      tree resolved = resolve_typename_type (t1, /*only_current_p=*/true);
-
-      if (resolved != error_mark_node)
-       t1 = resolved;
-    }
+    t1 = resolve_typename_type (t1, /*only_current_p=*/true);
 
   if (TREE_CODE (t2) == TYPENAME_TYPE)
-    {
-      tree resolved = resolve_typename_type (t2, /*only_current_p=*/true);
-
-      if (resolved != error_mark_node)
-       t2 = resolved;
-    }
+    t2 = resolve_typename_type (t2, /*only_current_p=*/true);
 
   if (TYPE_PTRMEMFUNC_P (t1))
     t1 = TYPE_PTRMEMFUNC_FN_TYPE (t1);
index f091d14..1b5a410 100644 (file)
@@ -1,3 +1,13 @@
+2007-07-22  Nathan Sidwell  <nathan@codesourcery.com>
+
+       PR c++/30818
+       * g++.dg/template/crash47.C: Adjust errors.
+       * g++.dg/template/crash48.C: Adjust errors.
+       * g++.dg/template/typename12.C: New.
+       * g++.dg/template/typename13.C: New.
+       * g++.dg/template/typename14.C: New.
+       * g++.dg/template/typedef6.C: Adjust errors.
+
 2007-07-21  Christopher D. Rickett  <crickett@lanl.gov>
 
        PR fortran/32627
index ad4aaa2..9c21632 100644 (file)
@@ -1,3 +1,3 @@
 // PR c++/27102
 
-template<typename T> void T::X::foo() {} // { dg-error "invalid" }
+template<typename T> void T::X::foo() {} // { dg-error "invalid|not a type" }
index 9fd1a4f..deb9446 100644 (file)
@@ -7,4 +7,4 @@ template<typename T> struct A
   typedef typename T::X X;
 };
 
-template<typename T> A<T>::X::X() {} // { dg-error "no type|invalid use" }
+template<typename T> A<T>::X::X() {} // { dg-error "no type|invalid use|not a type" }
index cd2db63..c959459 100644 (file)
@@ -5,4 +5,4 @@ template<typename T> struct A
   typedef struct typename T::X X;       // { dg-error "expected identifier|two or more" }
 };
 
-template<typename T> A<T>::X::X() {}    // { dg-error "not a type|forbids declaration" }
+template<typename T> A<T>::X::X() {}    // { dg-error "not a type|forbids declaration|invalid use of" }
diff --git a/gcc/testsuite/g++.dg/template/typename12.C b/gcc/testsuite/g++.dg/template/typename12.C
new file mode 100644 (file)
index 0000000..0bb78c7
--- /dev/null
@@ -0,0 +1,25 @@
+// { dg-do compile }
+
+// Copyright (C) 2007 Free Software Foundation, Inc.
+// Contributed by Nathan Sidwell 21 Jul 2007 <nathan@codesourcery.com>
+
+// Origin: sschunck@pdf.de
+// PR 30818, failure to resolve typename typedef
+
+template < typename T > 
+class A 
+{
+  typedef int type;
+  class B;
+};
+
+template < typename T >
+class A<T>::B
+{
+  typedef typename A<T>::type type;
+  type f();
+};
+
+template < typename T >
+typename A<T>::B::type 
+A<T>::B::f() { return 0; }
diff --git a/gcc/testsuite/g++.dg/template/typename13.C b/gcc/testsuite/g++.dg/template/typename13.C
new file mode 100644 (file)
index 0000000..527b0d1
--- /dev/null
@@ -0,0 +1,24 @@
+// { dg-do compile }
+
+// Copyright (C) 2007 Free Software Foundation, Inc.
+// Contributed by Nathan Sidwell 21 Jul 2007 <nathan@codesourcery.com>
+
+template <typename T> struct A
+{
+  struct B;
+  typedef typename B::type type;
+};
+
+template <typename T> struct A<T>::B
+{
+  typedef typename A<T>::type type;
+
+  type Foo ();
+};
+
+template <typename T>
+typename A<T>::B::type
+A<T>::B::Foo () 
+{
+  return 0;
+}
diff --git a/gcc/testsuite/g++.dg/template/typename14.C b/gcc/testsuite/g++.dg/template/typename14.C
new file mode 100644 (file)
index 0000000..7e73cb0
--- /dev/null
@@ -0,0 +1,24 @@
+// { dg-do compile }
+
+// Copyright (C) 2007 Free Software Foundation, Inc.
+// Contributed by Nathan Sidwell 21 Jul 2007 <nathan@codesourcery.com>
+
+template <typename T> struct A  
+{
+  typedef const T X;
+  
+  struct B;
+};
+
+template <typename T> struct A<T>::B
+{
+  typedef volatile typename A<T>::X Y;
+
+  T const volatile *Foo ();
+};
+
+template<typename T>
+typename A<T>::B::Y *A<T>::B::Foo ()
+{
+  return 0;
+}