OSDN Git Service

PR c++/56395
authorjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 22 Feb 2013 22:26:08 +0000 (22:26 +0000)
committerjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 22 Feb 2013 22:26:08 +0000 (22:26 +0000)
* tree.c (strip_typedefs): Strip typedefs from TYPENAME_TYPE template
args.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/gcc-4_7-branch@196232 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/cp/ChangeLog
gcc/cp/tree.c
gcc/testsuite/g++.dg/template/typename19.C [new file with mode: 0644]

index 6086d2b..7145496 100644 (file)
@@ -1,3 +1,9 @@
+2013-02-22  Jason Merrill  <jason@redhat.com>
+
+       PR c++/56395
+       * tree.c (strip_typedefs): Strip typedefs from TYPENAME_TYPE template
+       args.
+
 2013-02-19  Jakub Jelinek  <jakub@redhat.com>
 
        Backported from mainline
index c95a360..8909c72 100644 (file)
@@ -1207,9 +1207,35 @@ strip_typedefs (tree t)
       }
       break;
     case TYPENAME_TYPE:
-      result = make_typename_type (strip_typedefs (TYPE_CONTEXT (t)),
-                                  TYPENAME_TYPE_FULLNAME (t),
-                                  typename_type, tf_none);
+      {
+       tree fullname = TYPENAME_TYPE_FULLNAME (t);
+       if (TREE_CODE (fullname) == TEMPLATE_ID_EXPR)
+         {
+           tree args = TREE_OPERAND (fullname, 1);
+           tree new_args = copy_node (args);
+           bool changed = false;
+           int i;
+           for (i = 0; i < TREE_VEC_LENGTH (args); ++i)
+             {
+               tree arg = TREE_VEC_ELT (args, i);
+               tree strip_arg;
+               if (TYPE_P (arg))
+                 strip_arg = strip_typedefs (arg);
+               else
+                 strip_arg = strip_typedefs_expr (arg);
+               TREE_VEC_ELT (new_args, i) = strip_arg;
+               if (strip_arg != arg)
+                 changed = true;
+             }
+           if (changed)
+             fullname = lookup_template_function (TREE_OPERAND (fullname, 0),
+                                                  new_args);
+           else
+             ggc_free (new_args);
+         }
+       result = make_typename_type (strip_typedefs (TYPE_CONTEXT (t)),
+                                    fullname, typename_type, tf_none);
+      }
       break;
     case DECLTYPE_TYPE:
       result = strip_typedefs_expr (DECLTYPE_TYPE_EXPR (t));
diff --git a/gcc/testsuite/g++.dg/template/typename19.C b/gcc/testsuite/g++.dg/template/typename19.C
new file mode 100644 (file)
index 0000000..735deb2
--- /dev/null
@@ -0,0 +1,24 @@
+// PR c++/56395
+
+struct A
+{
+  template <class T> struct B { };
+};
+
+template <class T> struct D { };
+
+template <class T, class U> struct C
+{
+  typedef T _Type;
+  typedef typename T::template B<_Type> _BType;
+  D<_BType> d;
+};
+
+template <class T> struct C<T,T>
+{
+  typedef T _Type;
+  typedef typename T::template B<_Type> _BType;
+  D<_BType> d;
+};
+
+C<A,A> c;