This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] PR c++/42225


Hello,

In this PR we omit to strip typedefs from TYPENAME_TYPEs. I noticed we also omit
it for DECLTYPE_TYPE expression that involve types, like in the typedef25.C
example in the patch below.

The change in convert_template_argument is just to factorize typedef stripping
from SCOPE_REFs.

Tested against trunk on x86_64-unknown-linux-gnu.

        Dodji

commit eb317c85b6f8e2443b27977b24d0bad12e5aed7d
Author: Dodji Seketeli <dodji@redhat.com>
Date:   Tue Dec 1 15:22:26 2009 +0100

    Fix PR c++/42225
    
    gcc/cp/ChangeLog:
    	PR c++/42225
    	* tree.c (strip_typedefs_from_expr): New function.
    	(strip_typedefs): Handle TYPENAME_TYPE and DECLTYPE_TYPE.
    	* pt.c (convert_template_argument): Use strip_typedefs_from_expr to
    	handle SCOPE_REFs.
    
    gcc/testsuite/ChangeLog:
    	PR c++/42225
    	* g++.dg/template/typedef24.C: New test.
    	* g++.dg/template/typedef25.C: New test.

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 2d8f409..aac2f52 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -5170,6 +5170,7 @@ extern bool type_has_nontrivial_default_init	(const_tree);
 extern bool type_has_nontrivial_copy_init	(const_tree);
 extern bool class_tmpl_impl_spec_p		(const_tree);
 extern int zero_init_p				(const_tree);
+extern tree strip_typedefs_from_expr		(tree);
 extern tree strip_typedefs			(tree);
 extern bool typedef_variant_p			(tree);
 extern tree copy_binfo				(tree, tree, tree,
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 9fd06b3..1068001 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -5527,12 +5527,8 @@ convert_template_argument (tree parm,
 	val = strip_typedefs (val);
     }
   else if (TREE_CODE (orig_arg) == SCOPE_REF)
-    {
-      /* Strip typedefs from the SCOPE_REF.  */
-      tree type = strip_typedefs (TREE_TYPE (orig_arg));
-      tree scope = strip_typedefs (TREE_OPERAND (orig_arg, 0));
-      val = build2 (SCOPE_REF, type, scope, TREE_OPERAND (orig_arg, 1));
-    }
+    /* Strip typedefs from the SCOPE_REF.  */
+    val = strip_typedefs_from_expr (orig_arg);
   else
     {
       tree t = tsubst (TREE_TYPE (parm), args, complain, in_decl);
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 17fc495..be6464c 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -957,6 +957,48 @@ cv_unqualified (tree type)
   return cp_build_qualified_type (type, quals);
 }
 
+/* If EXPR is an expression or reference involving a type, strip typedefs
+   from its type part.  E.g, if EXPR is a construct like: foo::bar, *foo::bar,
+   &foo::bar where foo is a type, strip typedefs from foo.
+   Otherwise, return EXPR unmodified.
+   This is a subroutine of strip_typedefs.  */
+
+tree
+strip_typedefs_from_expr (tree expr)
+{
+  tree type, op0;
+  enum tree_code code;
+  char tclass;
+
+  if (expr)
+    code = TREE_CODE (expr);
+  else
+    return NULL_TREE;
+
+  tclass = TREE_CODE_CLASS (code);
+  if (tclass != tcc_expression && tclass != tcc_reference)
+    return expr;
+
+  switch (code)
+    {
+    case SCOPE_REF:
+      type = strip_typedefs (TREE_TYPE (expr));
+      op0 = strip_typedefs (TREE_OPERAND (expr, 0));
+      expr = build2 (code, type, op0, TREE_OPERAND (expr, 1));
+      break;
+    case INDIRECT_REF:
+    case ADDR_EXPR:
+      type = strip_typedefs (TREE_TYPE (expr));
+      op0 = strip_typedefs_from_expr (TREE_OPERAND (expr, 0));
+      expr = build1 (code, type, op0);
+      break;
+    default:
+      break;
+    }
+
+  return expr;
+}
+
 /* Builds a qualified variant of T that is not a typedef variant.
    E.g. consider the following declarations:
      typedef const int ConstInt;
@@ -1009,6 +1051,19 @@ strip_typedefs (tree t)
 	  result = build_ptrmemfunc_type (t0);
 	}
       break;
+    case TYPENAME_TYPE:
+      t0 = strip_typedefs (TYPE_CONTEXT (t));
+      result = make_typename_type (t0, TYPENAME_TYPE_FULLNAME (t),
+				   typename_type, tf_none);
+      break;
+    case DECLTYPE_TYPE:
+      t0 = strip_typedefs_from_expr (DECLTYPE_TYPE_EXPR (t));
+      result = cxx_make_type (DECLTYPE_TYPE);
+      DECLTYPE_TYPE_EXPR (result) = t0;
+      DECLTYPE_TYPE_ID_EXPR_OR_MEMBER_ACCESS_P (result)
+	= DECLTYPE_TYPE_ID_EXPR_OR_MEMBER_ACCESS_P (t);
+      SET_TYPE_STRUCTURAL_EQUALITY (result);
+      break;
     case ARRAY_TYPE:
       type = strip_typedefs (TREE_TYPE (t));
       t0  = strip_typedefs (TYPE_DOMAIN (t));;
diff --git a/gcc/testsuite/g++.dg/template/typedef24.C b/gcc/testsuite/g++.dg/template/typedef24.C
new file mode 100644
index 0000000..ad05846
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/typedef24.C
@@ -0,0 +1,32 @@
+// Contributed by Dodji Seketeli <dodji@redhat.com>
+// Origin PR c++/42225
+// { dg-do compile }
+
+template<class T>
+struct A
+{
+    typedef T I;
+};
+
+template<class T, int>
+struct B
+{
+    typedef T TT;
+    typedef typename TT::I TT_I;
+    typedef A<TT_I> TA;
+};
+
+template<class T>
+void
+foo()
+{
+    typedef T TT;
+    typedef typename TT::I TT_I;
+    typedef A<TT_I> TA;
+}
+
+int
+main()
+{
+    foo<A<int> >();
+}
diff --git a/gcc/testsuite/g++.dg/template/typedef25.C b/gcc/testsuite/g++.dg/template/typedef25.C
new file mode 100644
index 0000000..098a022
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/typedef25.C
@@ -0,0 +1,42 @@
+// Contributed by Dodji Seketeli <dodji@redhat.com>
+// Origin PR c++/42225
+// { dg-options "-std=c++0x" }
+// { dg-do compile }
+
+template<class T>
+struct A
+{
+    typedef T I;
+    static const char *i;
+};
+
+template<class T, int>
+struct B
+{
+    typedef T TT;
+    typedef decltype(TT::i)  TT_I0;
+    typedef decltype(&TT::i) TT_I1;
+    typedef decltype(*TT::i) TT_I2;
+    typedef A<TT_I0> TA0;
+    typedef A<TT_I1> TA1;
+    typedef A<TT_I2> TA2;
+};
+
+template<class T>
+void
+foo()
+{
+    typedef T TT;
+    typedef decltype(TT::i)  TT_I0;
+    typedef decltype(&TT::i) TT_I1;
+    typedef decltype(*TT::i) TT_I2;
+    typedef A<TT_I0> TA0;
+    typedef A<TT_I1> TA1;
+    typedef A<TT_I2> TA2;
+}
+
+int
+main()
+{
+    foo<A<int> >();
+}


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]