From patchwork Tue Jul 20 18:22:44 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jason Merrill X-Patchwork-Id: 59351 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 1D783B6EEC for ; Wed, 21 Jul 2010 04:22:55 +1000 (EST) Received: (qmail 20670 invoked by alias); 20 Jul 2010 18:22:53 -0000 Received: (qmail 20659 invoked by uid 22791); 20 Jul 2010 18:22:52 -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; Tue, 20 Jul 2010 18:22:46 +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 o6KIMjvI010224 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Tue, 20 Jul 2010 14:22:45 -0400 Received: from [IPv6:::1] (ovpn-113-77.phx2.redhat.com [10.3.113.77]) by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id o6KIMiFb027525 for ; Tue, 20 Jul 2010 14:22:44 -0400 Message-ID: <4C45E974.7090802@redhat.com> Date: Tue, 20 Jul 2010 14:22:44 -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: gcc-patches List Subject: C++ PATCH for c++/44967 (sfinae and variadic templates) 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 This testcase was running into problems because we were effectively assuming that when we tsubst into a CALL_EXPR we're producing a non-dependent result. This is not the case in this testcase, where we do a partial substitution of the explicit template args but can deduce more from the function arguments. Fixed by adding early exit as in cp_parser_postfix_expression. Tested x86_64-pc-linux-gnu, applied to trunk. 2010-07-20 Jason Merrill PR c++/44967 * pt.c (tsubst_copy_and_build): Rework last change. PR c++/44967 * pt.c (tsubst_copy_and_build): Handle partial substitution of CALL_EXPR. diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 0ccd8d9..b618907 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -12531,15 +12531,24 @@ tsubst_copy_and_build (tree t, ret = build_offset_ref_call_from_tree (function, &call_args); else if (TREE_CODE (function) == COMPONENT_REF) { - if (!BASELINK_P (TREE_OPERAND (function, 1))) + tree instance = TREE_OPERAND (function, 0); + tree fn = TREE_OPERAND (function, 1); + + if (processing_template_decl + && (type_dependent_expression_p (instance) + || (!BASELINK_P (fn) + && TREE_CODE (fn) != FIELD_DECL) + || type_dependent_expression_p (fn) + || any_type_dependent_arguments_p (call_args))) + ret = build_nt_call_vec (function, call_args); + else if (!BASELINK_P (fn)) ret = finish_call_expr (function, &call_args, /*disallow_virtual=*/false, /*koenig_p=*/false, complain); else ret = (build_new_method_call - (TREE_OPERAND (function, 0), - TREE_OPERAND (function, 1), + (instance, fn, &call_args, NULL_TREE, qualified_p ? LOOKUP_NONVIRTUAL : LOOKUP_NORMAL, /*fn_p=*/NULL, diff --git a/gcc/testsuite/g++.dg/cpp0x/sfinae2.C b/gcc/testsuite/g++.dg/cpp0x/sfinae2.C new file mode 100644 index 0000000..b9ef70d --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/sfinae2.C @@ -0,0 +1,39 @@ +// PR c++/44967 +// { dg-options -std=c++0x } + +template T&& declval(); + +template +struct has_construct +{ + typedef char one; + typedef struct {char _m[2]; } two; + + template + static decltype(declval().construct(declval(), declval()...), one()) test(int); + template + static two test(...); + + static const bool value = sizeof(test(0)) == 1; +}; + + +struct A0 +{}; + +struct A1 +{ + void construct(int*, int); +}; + +template +struct A2 +{ + template + void construct(_Tp1*, _Args&&...) {} +}; + +#define SA(X) static_assert(X,#X) +SA((!has_construct::value)); // ok +SA((has_construct::value)); // bang +SA((has_construct, int>::value)); // bang