From patchwork Sat Mar 31 16:37:16 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dodji Seketeli X-Patchwork-Id: 149859 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 9A1DBB6F6E for ; Sun, 1 Apr 2012 02:56:39 +1000 (EST) Comment: DKIM? See http://www.dkim.org DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed; d=gcc.gnu.org; s=default; x=1333817800; h=Comment: DomainKey-Signature:Received:Received:Received:Received:Received: Received:From:To:Cc:Subject:Date:Message-ID:User-Agent: MIME-Version:Content-Type:Mailing-List:Precedence:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:Sender: Delivered-To; bh=16K827TPi3AiXTeKhPGfaSFgnW8=; b=p1zDtZwQomKQqKa jT5e84YRBrZGCo7BV5B1tQvozLUHeAy1HHYtOKnQ9+JFXlxKjM5tZnvBv7JhIUVE ls/D6fgY9WMsiHARu42JNFmeaLQiQ0AvBr7X8ZjQ/RoZh4zGMrfGcNmTTxqS8wL5 FY3AZdgxEXW6HzsEprgt2NeQir40= Comment: DomainKeys? See http://antispam.yahoo.com/domainkeys DomainKey-Signature: a=rsa-sha1; q=dns; c=nofws; s=default; d=gcc.gnu.org; h=Received:Received:X-SWARE-Spam-Status:X-Spam-Check-By:Received:Received:Received:Received:From:To:Cc:Subject:X-URL:Date:Message-ID:User-Agent:MIME-Version:Content-Type:Mailing-List:Precedence:List-Id:List-Unsubscribe:List-Archive:List-Post:List-Help:Sender:Delivered-To; b=M1fP+98wNo91vG/MU7oG8sPJr9M85XYZOJkLcGqPVOxMHBPs7r+swbawxIbzPn QA5g0Vs1mpBEsjECJxs50mPXHlBBlPetA03Rg0ZdFVGLfdRyStzk0f7fKLYLuYCE 2CJB/3Tn4W+GMZtUDpbIawGUqpyk6yDa17vJLo7O9zNFg=; Received: (qmail 12099 invoked by alias); 31 Mar 2012 16:56:30 -0000 Received: (qmail 12088 invoked by uid 22791); 31 Mar 2012 16:56:27 -0000 X-SWARE-Spam-Status: No, hits=-5.8 required=5.0 tests=AWL, BAYES_00, KHOP_RCVD_UNTRUST, RCVD_IN_DNSWL_HI, RCVD_IN_HOSTKARMA_W, 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; Sat, 31 Mar 2012 16:56:10 +0000 Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id q2VGu4Di028427 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Sat, 31 Mar 2012 12:56:05 -0400 Received: from localhost (ovpn-116-19.ams2.redhat.com [10.36.116.19]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id q2VGbH1s018460 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Sat, 31 Mar 2012 12:37:18 -0400 Received: by localhost (Postfix, from userid 500) id 7487029C046; Sat, 31 Mar 2012 18:37:16 +0200 (CEST) From: Dodji Seketeli To: GCC Patches Cc: Jason Merrill , Nathan Sidwell Subject: [PATCH] PR c++/40942 - Failure of template specialization partial ordering X-URL: http://www.redhat.com Date: Sat, 31 Mar 2012 18:37:16 +0200 Message-ID: User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.3 (gnu/linux) MIME-Version: 1.0 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 Hello, G++ compiles the example below without error: struct S { template S (T const *) //#0 { } template S (char const (&)[N]) //#1 { } }; int main() { S s1 ("test"); // #3 This should error out because the // call to S constructor is ambiguous. } But the call to the constructor at #3 should be considered ambiguous. G++ considers this call non-ambiguous and chooses #1 because during overload resolution, the partial ordering of the two constructors ends up considering that the second S constructor template is more specialized than the first one. It does so because it wrongly applies an array-to-pointer decay conversion to the "array of const char" parameter type of S in #1 (after the reference-removing conversion that is allowed in that context), converting it into a "pointer to const char". That decay conversion is not allowed in the context of partial ordering of template instantiations ([temp.deduct.partial]/5 lists the conversions allowed in that context and doesn't mention any decay conversion). It is only allowed in the context of a function call. I believe this behaviour dates back from 2001 when the commit r39604 [1] was added, and the commit r97336 [2] that implemented DR 214 worked hard to keep it. Here are the change logs of the two commits in question. [1]: commit a1d01fd0e4b8bf97295885cfbbf8fe6f382efa4c Author: nathan Date: Mon Feb 12 14:38:25 2001 +0000 cp: * pt.c (maybe_adjust_types_for_deduction, DEDUCE_ORDER case): Remove spurious information in comment. Allow further adjustments of REFERENCE_TYPE args. testsuite: * g++.old-deja/g++.pt/spec40.C: New test. [2]: commit 517ee39a43d80fd91cc7c91c244ca0fc6e1d008e Author: nathan Date: Thu Mar 31 17:36:17 2005 +0000 cp: PR c++/19203, implement DR 214 * call.c (joust): Use more_specialized_fn. * cp-tree.h (DEDUCE_ORDER): Remove. (more_specialized): Replace with ... (more_specialized_fn): ... this. * pt.c (maybe_adjust_types_for_deduction): Remove DEDUCE_ORDER case. (type_unification_real): Remove DEDUCE_ORDER case. (more_specialized): Replace with ... (more_specialized_fn): ... this. Implement DR 214. (most_specialized_instantiation): Use get_bindings_real directly. testsuite: PR c++/19203, DR 214 * g++.dg/parse/ambig3.C: Not ambiguous. * g++.dg/template/spec20.C: New. * g++.dg/template/spec21.C: New. Fixed thus by removing the decay conversion in the context of partial ordering of template instantiations. Bootstrapped and tested on x86_64-unknown-linux-gnu against trunk. gcc/cp/ * pt.c (more_specialized_fn): Don't apply decay conversion to types of function parameters. gcc/testsuite/ * g++.old-deja/g++.pt/spec40.C: Adjust to take the resolution of DR 214 in account. --- gcc/cp/pt.c | 40 ---------------------------- gcc/testsuite/g++.old-deja/g++.pt/spec40.C | 27 ++++++++++++++++--- 2 files changed, 23 insertions(+), 44 deletions(-) diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 9b410a7..04ba37d 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -17132,46 +17132,6 @@ more_specialized_fn (tree pat1, tree pat2, int len) quals2 = cp_type_quals (arg2); } - if ((quals1 < 0) != (quals2 < 0)) - { - /* Only of the args is a reference, see if we should apply - array/function pointer decay to it. This is not part of - DR214, but is, IMHO, consistent with the deduction rules - for the function call itself, and with our earlier - implementation of the underspecified partial ordering - rules. (nathan). */ - if (quals1 >= 0) - { - switch (TREE_CODE (arg1)) - { - case ARRAY_TYPE: - arg1 = TREE_TYPE (arg1); - /* FALLTHROUGH. */ - case FUNCTION_TYPE: - arg1 = build_pointer_type (arg1); - break; - - default: - break; - } - } - else - { - switch (TREE_CODE (arg2)) - { - case ARRAY_TYPE: - arg2 = TREE_TYPE (arg2); - /* FALLTHROUGH. */ - case FUNCTION_TYPE: - arg2 = build_pointer_type (arg2); - break; - - default: - break; - } - } - } - arg1 = TYPE_MAIN_VARIANT (arg1); arg2 = TYPE_MAIN_VARIANT (arg2); diff --git a/gcc/testsuite/g++.old-deja/g++.pt/spec40.C b/gcc/testsuite/g++.old-deja/g++.pt/spec40.C index 70abb6f..fc37f41 100644 --- a/gcc/testsuite/g++.old-deja/g++.pt/spec40.C +++ b/gcc/testsuite/g++.old-deja/g++.pt/spec40.C @@ -1,14 +1,33 @@ -// { dg-do run } +// { dg-do compile } // Copyright (C) 2000 Free Software Foundation, Inc. // Contributed by Nathan Sidwell 12 Feb 2001 -// More from bug 1617. We didn't resolve partial ordering properly. The -// std is rather vague about it anyway, DR 214 talks about this. +// More from bug 1617. The resolution of DR 214 implies that the below +// call to Foo is ambiguous. +// +// The type transformation (on the function parameter of Foo) allowed +// in the context of partial ordering of the Foo template overloads is +// the following ([temp.deduct.partial]/5): +// +// Before the partial ordering is done, certain transformations +// are performed on the types used for partial ordering: +// +// - If P is a reference type, P is replaced by the type +// referred to. +// +// - If A is a reference type, A is replaced by the type +// referred to. +// +// It follows that we are not allowed to apply array-to-pointer +// decay conversion to the type of the function parameter +// 'char const (&)[I]'. So the two Foo specializations should +// be considered unrelated. Thus the partial ordering of the two +// Foo specializations should fail. template int Foo (T const *) {return 1;} template int Foo (char const (&)[I]) {return 2;} int main () { - return Foo ("a") != 2; + return Foo ("a") != 2; // { dg-error "call of overloaded \[^\n\r\]* is ambiguous" } }