Patchwork [C++,committed] PR 44969 (first half)

login
register
mail settings
Submitter Jason Merrill
Date July 19, 2010, 2:49 p.m.
Message ID <4C4465F7.3060209@redhat.com>
Download mbox | patch
Permalink /patch/59203/
State New
Headers show

Comments

Jason Merrill - July 19, 2010, 2:49 p.m.
And here's the second half: we were failing to consider the type of a 
functional cast when comparing arguments, so we thought the partial 
instantiation of test(int) was the same as the primary template.

Applying to trunk.

Patch

commit b22dd1b1bbe2ae953493af824eb42320df241be6
Author: Jason Merrill <jason@redhat.com>
Date:   Mon Jul 19 09:35:58 2010 -0400

    	PR c++/44969
    	* tree.c (cp_tree_equal): Compare type of *CAST_EXPR.
    	* pt.c (iterative_hash_template_arg): Hash type of *CAST_EXPR.

diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 3259043..0ccd8d9 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -1566,31 +1566,43 @@  iterative_hash_template_arg (tree arg, hashval_t val)
       gcc_assert (seen_error ());
       return val;
 
+    case CAST_EXPR:
+    case STATIC_CAST_EXPR:
+    case REINTERPRET_CAST_EXPR:
+    case CONST_CAST_EXPR:
+    case DYNAMIC_CAST_EXPR:
+    case NEW_EXPR:
+      val = iterative_hash_template_arg (TREE_TYPE (arg), val);
+      /* Now hash operands as usual.  */
+      break;
+
     default:
-      switch (tclass)
-	{
-	case tcc_type:
-	  if (TYPE_CANONICAL (arg))
-	    return iterative_hash_object (TYPE_HASH (TYPE_CANONICAL (arg)),
-					  val);
-	  else if (TREE_CODE (arg) == DECLTYPE_TYPE)
-	    return iterative_hash_template_arg (DECLTYPE_TYPE_EXPR (arg), val);
-	  /* Otherwise just compare the types during lookup.  */
-	  return val;
+      break;
+    }
 
-	case tcc_declaration:
-	case tcc_constant:
-	  return iterative_hash_expr (arg, val);
+  switch (tclass)
+    {
+    case tcc_type:
+      if (TYPE_CANONICAL (arg))
+	return iterative_hash_object (TYPE_HASH (TYPE_CANONICAL (arg)),
+				      val);
+      else if (TREE_CODE (arg) == DECLTYPE_TYPE)
+	return iterative_hash_template_arg (DECLTYPE_TYPE_EXPR (arg), val);
+      /* Otherwise just compare the types during lookup.  */
+      return val;
 
-	default:
-	  gcc_assert (IS_EXPR_CODE_CLASS (tclass));
-	  {
-	    unsigned n = TREE_OPERAND_LENGTH (arg);
-	    for (i = 0; i < n; ++i)
-	      val = iterative_hash_template_arg (TREE_OPERAND (arg, i), val);
-	    return val;
-	  }
-	}
+    case tcc_declaration:
+    case tcc_constant:
+      return iterative_hash_expr (arg, val);
+
+    default:
+      gcc_assert (IS_EXPR_CODE_CLASS (tclass));
+      {
+	unsigned n = TREE_OPERAND_LENGTH (arg);
+	for (i = 0; i < n; ++i)
+	  val = iterative_hash_template_arg (TREE_OPERAND (arg, i), val);
+	return val;
+      }
     }
   gcc_unreachable ();
   return 0;
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index d62f9d7..2abd8dd 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -2191,6 +2191,17 @@  cp_tree_equal (tree t1, tree t2)
       return same_type_p (TRAIT_EXPR_TYPE1 (t1), TRAIT_EXPR_TYPE1 (t2))
 	&& same_type_p (TRAIT_EXPR_TYPE2 (t1), TRAIT_EXPR_TYPE2 (t2));
 
+    case CAST_EXPR:
+    case STATIC_CAST_EXPR:
+    case REINTERPRET_CAST_EXPR:
+    case CONST_CAST_EXPR:
+    case DYNAMIC_CAST_EXPR:
+    case NEW_EXPR:
+      if (!same_type_p (TREE_TYPE (t1), TREE_TYPE (t2)))
+	return false;
+      /* Now compare operands as usual.  */
+      break;
+
     default:
       break;
     }
diff --git a/gcc/testsuite/g++.dg/template/sfinae24.C b/gcc/testsuite/g++.dg/template/sfinae24.C
new file mode 100644
index 0000000..8a50c8e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/sfinae24.C
@@ -0,0 +1,27 @@ 
+// PR c++/44969
+
+template<bool, typename T = void> struct enable_if { typedef T type; };
+template<typename T> struct enable_if<false, T> { };
+
+template<typename Tp, typename Arg1, typename Arg2>
+  class mini_is_constructible
+  {
+    typedef char one;
+    typedef struct { char arr[2]; } two;
+
+    template<typename Tp1, typename Arg1_, typename Arg2_>
+      static typename
+      enable_if<(sizeof(Tp1(Arg1_(), Arg2_()), 1) > 0), one>::type
+      test(int);
+
+    template<typename, typename, typename>
+      static two test(...);
+
+  public:
+    static const bool value = sizeof(test<Tp, Arg1, Arg2>(0)) == 1;
+  };
+
+class A { };
+
+int Test[mini_is_constructible<int, A, A>::value ? -1 : 1];
+