re PR c++/50852 (ICE: internal compiler error: in tsubst, at cp/pt.c:11030)
authorJason Merrill <jason@redhat.com>
Thu, 5 Jul 2012 19:39:01 +0000 (15:39 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Thu, 5 Jul 2012 19:39:01 +0000 (15:39 -0400)
PR c++/50852
PR c++/53039
* tree.c (strip_typedefs_expr): New.
* cp-tree.h: Declare it.
* pt.c (convert_template_argument, unify): Use it.
* parser.c (cp_parser_template_declaration_after_export): Don't call
fixup_template_parms.

From-SVN: r189298

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/parser.c
gcc/cp/pt.c
gcc/cp/tree.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp0x/variadic133.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/param1.C
gcc/testsuite/g++.dg/template/typedef39.C [new file with mode: 0644]

index e11b240f0e6b6f4983fd2b09e09b6cd28e74c7c2..91df62da41b0353d1b9343c9f6243de108057423 100644 (file)
@@ -1,3 +1,13 @@
+2012-07-05  Jason Merrill  <jason@redhat.com>
+
+       PR c++/50852
+       PR c++/53039
+       * tree.c (strip_typedefs_expr): New.
+       * cp-tree.h: Declare it.
+       * pt.c (convert_template_argument, unify): Use it.
+       * parser.c (cp_parser_template_declaration_after_export): Don't call
+       fixup_template_parms.
+
 2012-07-04  Jason Merrill  <jason@redhat.com>
 
        PR c++/53848
index 41ca83ca8c9bee4e4d20717dca3dbc2e0d70c592..e53f185d428f8d79144fd7bbc50a1a8c1040b804 100644 (file)
@@ -5692,6 +5692,7 @@ 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                     (tree);
+extern tree strip_typedefs_expr                        (tree);
 extern tree copy_binfo                         (tree, tree, tree,
                                                 tree *, int);
 extern int member_p                            (const_tree);
index 027a7b9d07afcdb7de006561d5d3a4a2ef830e9a..4c2167aa7f616c17da02461ace3d28dd96a78436 100644 (file)
@@ -21207,7 +21207,6 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p)
     {
       /* Parse the template parameters.  */
       parameter_list = cp_parser_template_parameter_list (parser);
-      fixup_template_parms ();
     }
 
   /* Get the deferred access checks from the parameter list.  These
index f618fa557d10212a24a55d96946a67f0288b73a7..550a1cb021c7338cf170db922472a8496e363d7b 100644 (file)
@@ -6600,7 +6600,7 @@ convert_template_argument (tree parm,
           argument specification is valid.  */
        val = convert_nontype_argument (t, orig_arg, complain);
       else
-       val = orig_arg;
+       val = strip_typedefs_expr (orig_arg);
 
       if (val == NULL_TREE)
        val = error_mark_node;
@@ -16598,6 +16598,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict,
          && !TEMPLATE_PARM_PARAMETER_PACK (parm))
        return unify_parameter_pack_mismatch (explain_p, parm, arg);
 
+      arg = strip_typedefs_expr (arg);
       TREE_VEC_ELT (INNERMOST_TEMPLATE_ARGS (targs), idx) = arg;
       return unify_success (explain_p);
 
index a03f8459da804d8d37de2b0d870a2d1fe7d86031..15effe41555ba1a1522cb24599bf92a4090ab9d3 100644 (file)
@@ -1094,7 +1094,7 @@ cv_unqualified (tree type)
     * If T is a type that needs structural equality
       its TYPE_CANONICAL (T) will be NULL.
     * TYPE_CANONICAL (T) desn't carry type attributes
-      and looses template parameter names.   */
+      and loses template parameter names.   */
 
 tree
 strip_typedefs (tree t)
@@ -1184,6 +1184,16 @@ strip_typedefs (tree t)
                                   TYPENAME_TYPE_FULLNAME (t),
                                   typename_type, tf_none);
       break;
+    case DECLTYPE_TYPE:
+      result = strip_typedefs_expr (DECLTYPE_TYPE_EXPR (t));
+      if (result == DECLTYPE_TYPE_EXPR (t))
+       return t;
+      else
+       result = (finish_decltype_type
+                 (result,
+                  DECLTYPE_TYPE_ID_EXPR_OR_MEMBER_ACCESS_P (t),
+                  tf_none));
+      break;
     default:
       break;
     }
@@ -1205,6 +1215,186 @@ strip_typedefs (tree t)
   return cp_build_qualified_type (result, cp_type_quals (t));
 }
 
+/* Like strip_typedefs above, but works on expressions, so that in
+
+   template<class T> struct A
+   {
+     typedef T TT;
+     B<sizeof(TT)> b;
+   };
+
+   sizeof(TT) is replaced by sizeof(T).  */
+
+tree
+strip_typedefs_expr (tree t)
+{
+  unsigned i,n;
+  tree r, type, *ops;
+  enum tree_code code;
+
+  if (t == NULL_TREE || t == error_mark_node)
+    return t;
+
+  if (DECL_P (t) || CONSTANT_CLASS_P (t))
+    return t;
+
+  /* Some expressions have type operands, so let's handle types here rather
+     than check TYPE_P in multiple places below.  */
+  if (TYPE_P (t))
+    return strip_typedefs (t);
+
+  code = TREE_CODE (t);
+  switch (code)
+    {
+    case IDENTIFIER_NODE:
+    case TEMPLATE_PARM_INDEX:
+    case OVERLOAD:
+    case BASELINK:
+    case ARGUMENT_PACK_SELECT:
+      return t;
+
+    case TRAIT_EXPR:
+      {
+       tree type1 = strip_typedefs (TRAIT_EXPR_TYPE1 (t));
+       tree type2 = strip_typedefs (TRAIT_EXPR_TYPE2 (t));
+       if (type1 == TRAIT_EXPR_TYPE1 (t)
+           && type2 == TRAIT_EXPR_TYPE2 (t))
+         return t;
+       r = copy_node (t);
+       TRAIT_EXPR_TYPE1 (t) = type1;
+       TRAIT_EXPR_TYPE2 (t) = type2;
+       return r;
+      }
+
+    case TREE_LIST:
+      {
+       VEC(tree,gc) *vec = make_tree_vector ();
+       bool changed = false;
+       tree it;
+       for (it = t; it; it = TREE_CHAIN (it))
+         {
+           tree val = strip_typedefs_expr (TREE_VALUE (t));
+           VEC_safe_push (tree, gc, vec, val);
+           if (val != TREE_VALUE (t))
+             changed = true;
+           gcc_assert (TREE_PURPOSE (it) == NULL_TREE);
+         }
+       if (changed)
+         {
+           r = NULL_TREE;
+           FOR_EACH_VEC_ELT_REVERSE (tree, vec, i, it)
+             r = tree_cons (NULL_TREE, it, r);
+         }
+       else
+         r = t;
+       release_tree_vector (vec);
+       return r;
+      }
+
+    case TREE_VEC:
+      {
+       bool changed = false;
+       VEC(tree,gc)* vec = make_tree_vector ();
+       n = TREE_VEC_LENGTH (t);
+       VEC_reserve (tree, gc, vec, n);
+       for (i = 0; i < n; ++i)
+         {
+           tree op = strip_typedefs_expr (TREE_VEC_ELT (t, i));
+           VEC_quick_push (tree, vec, op);
+           if (op != TREE_VEC_ELT (t, i))
+             changed = true;
+         }
+       if (changed)
+         {
+           r = copy_node (t);
+           for (i = 0; i < n; ++i)
+             TREE_VEC_ELT (r, i) = VEC_index (tree, vec, i);
+         }
+       else
+         r = t;
+       release_tree_vector (vec);
+       return r;
+      }
+
+    case CONSTRUCTOR:
+      {
+       bool changed = false;
+       VEC(constructor_elt,gc) *vec
+         = VEC_copy (constructor_elt, gc, CONSTRUCTOR_ELTS (t));
+       n = CONSTRUCTOR_NELTS (t);
+       type = strip_typedefs (TREE_TYPE (t));
+       for (i = 0; i < n; ++i)
+         {
+           constructor_elt *e = VEC_index (constructor_elt, vec, i);
+           tree op = strip_typedefs_expr (e->value);
+           if (op != e->value)
+             {
+               changed = true;
+               e->value = op;
+             }
+           gcc_checking_assert (e->index == strip_typedefs_expr (e->index));
+         }
+
+       if (!changed && type == TREE_TYPE (t))
+         {
+           VEC_free (constructor_elt, gc, vec);
+           return t;
+         }
+       else
+         {
+           r = copy_node (t);
+           TREE_TYPE (r) = type;
+           CONSTRUCTOR_ELTS (r) = vec;
+           return r;
+         }
+      }
+
+    case LAMBDA_EXPR:
+      gcc_unreachable ();
+
+    default:
+      break;
+    }
+
+  gcc_assert (EXPR_P (t));
+
+  n = TREE_OPERAND_LENGTH (t);
+  ops = XALLOCAVEC (tree, n);
+  type = TREE_TYPE (t);
+
+  switch (code)
+    {
+    CASE_CONVERT:
+    case IMPLICIT_CONV_EXPR:
+    case DYNAMIC_CAST_EXPR:
+    case STATIC_CAST_EXPR:
+    case CONST_CAST_EXPR:
+    case REINTERPRET_CAST_EXPR:
+    case CAST_EXPR:
+    case NEW_EXPR:
+      type = strip_typedefs (type);
+      /* fallthrough */
+
+    default:
+      for (i = 0; i < n; ++i)
+       ops[i] = strip_typedefs_expr (TREE_OPERAND (t, i));
+      break;
+    }
+
+  /* If nothing changed, return t.  */
+  for (i = 0; i < n; ++i)
+    if (ops[i] != TREE_OPERAND (t, i))
+      break;
+  if (i == n && type == TREE_TYPE (t))
+    return t;
+
+  r = copy_node (t);
+  TREE_TYPE (r) = type;
+  for (i = 0; i < n; ++i)
+    TREE_OPERAND (r, i) = ops[i];
+  return r;
+}
+
 /* Makes a copy of BINFO and TYPE, which is to be inherited into a
    graph dominated by T.  If BINFO is NULL, TYPE is a dependent base,
    and we do a shallow copy.  If BINFO is non-NULL, we do a deep copy.
index 74ed2a3d9980add354ad5acafe0d3e3df4602803..a3c9f61fdbd926e9e0631c3071b1bf695ed77fb7 100644 (file)
@@ -1,3 +1,12 @@
+2012-07-05  Jason Merrill  <jason@redhat.com>
+
+       PR c++/50852
+       * g++.dg/template/typedef39.C: New.
+
+       PR c++/53039
+       * g++.dg/cpp0x/variadic133.C: New.
+       * g++.dg/template/param1.C: Adjust.
+
 2012-07-05  Ramana Radhakrishnan  <ramana.radhakrishnan@linaro.org>
 
         PR target/48941
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic133.C b/gcc/testsuite/g++.dg/cpp0x/variadic133.C
new file mode 100644 (file)
index 0000000..0265f09
--- /dev/null
@@ -0,0 +1,46 @@
+// PR c++/53039
+// { dg-do compile { target c++11 } }
+
+template <class, class>
+struct is_convertible
+{
+  static const bool value = true;
+};
+
+template<bool, class T>
+struct enable_if
+{
+  typedef T type;
+};
+
+template <bool...>
+struct Xs
+{
+  static const bool value = true;
+};
+
+template<typename... BTs>
+  class BType
+    {
+      template <typename... BUs,
+        typename enable_if<
+               Xs<is_convertible<BUs, BTs>::value...>::value,
+               bool>::type = false>
+        void fooX(BUs&&...);
+    };
+
+template <typename... ATs>
+  struct AType
+    {
+      template <typename... AUs,
+    typename enable_if<
+               Xs<is_convertible<AUs, ATs>::value...>::value,
+               bool>::type = false>
+        void foo(AUs&&...);
+    };
+
+int main()
+{
+  AType<int, int> t;
+  t.foo(1, 1);
+}
index a8c3791254fd1baa7199693c443f5b395676f211..e3784736fc440fab7780915e292967e978c2db20 100644 (file)
@@ -2,11 +2,11 @@
 // Origin: Volker Reichelt  <reichelt@igpm.rwth-aachen.de>
 // { dg-do compile }
 
-template<int> struct A // { dg-error "declaration" }
+template<int> struct A
 {
   A();
 };
 
-template<int N, char> A<N>::A() {}  // { dg-error "invalid use of incomplete type" }
+template<int N, char> A<N>::A() {}  // { dg-error "got 2 template parameters|1 required" }
 
 A<0> a;
diff --git a/gcc/testsuite/g++.dg/template/typedef39.C b/gcc/testsuite/g++.dg/template/typedef39.C
new file mode 100644 (file)
index 0000000..71d8bdb
--- /dev/null
@@ -0,0 +1,15 @@
+// PR c++/50852
+
+template<int d> class A;
+template<class T> struct B {typedef int K;typedef int L;};
+template<class U,class V> struct C
+{
+    typedef typename U::L X;
+    typedef A<X::a-1> W;       // { dg-error "not a member" }
+};
+template<class U,int d> struct D
+{
+    typedef typename U::L X;
+    typedef A<X::a-1> W;       // the error should really be on this line
+};
+template class D<B<A<1> >,3>;