From patchwork Mon Jul 19 14:49:27 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jason Merrill X-Patchwork-Id: 59203 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id 68788B6EED for ; Tue, 20 Jul 2010 00:49:39 +1000 (EST) Received: (qmail 15853 invoked by alias); 19 Jul 2010 14:49:38 -0000 Received: (qmail 15843 invoked by uid 22791); 19 Jul 2010 14:49:37 -0000 X-SWARE-Spam-Status: No, hits=-6.0 required=5.0 tests=AWL, BAYES_00, RCVD_IN_DNSWL_HI, SPF_HELO_PASS, T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Mon, 19 Jul 2010 14:49:29 +0000 Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) by mx1.redhat.com (8.13.8/8.13.8) with ESMTP id o6JEnSSn032068 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Mon, 19 Jul 2010 10:49:28 -0400 Received: from [IPv6:::1] ([10.3.113.14]) by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id o6JEnRgH017810; Mon, 19 Jul 2010 10:49:27 -0400 Message-ID: <4C4465F7.3060209@redhat.com> Date: Mon, 19 Jul 2010 10:49:27 -0400 From: Jason Merrill User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.10) Gecko/20100714 Lightning/1.0b1 Shredder/3.0.7pre MIME-Version: 1.0 To: Paolo Carlini CC: "gcc-patches@gcc.gnu.org" Subject: Re: [C++, committed] PR 44969 (first half) References: <4C442904.2040806@oracle.com> In-Reply-To: <4C442904.2040806@oracle.com> Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org 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. commit b22dd1b1bbe2ae953493af824eb42320df241be6 Author: Jason Merrill 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 struct enable_if { typedef T type; }; +template struct enable_if { }; + +template + class mini_is_constructible + { + typedef char one; + typedef struct { char arr[2]; } two; + + template + static typename + enable_if<(sizeof(Tp1(Arg1_(), Arg2_()), 1) > 0), one>::type + test(int); + + template + static two test(...); + + public: + static const bool value = sizeof(test(0)) == 1; + }; + +class A { }; + +int Test[mini_is_constructible::value ? -1 : 1]; +