From patchwork Fri Feb 9 02:09:26 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexandre Oliva X-Patchwork-Id: 871184 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-472910-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="KMzV2ahu"; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3zcz624RL9z9ryQ for ; Fri, 9 Feb 2018 13:09:46 +1100 (AEDT) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:subject:date:message-id:mime-version:content-type; q=dns; s= default; b=ZhMgF8qcidrZHSo/Dvf3kAKUb+/ZZPXz73da4J7YL4c4AqqqEeF/R NqdCNa/0QChT1F7WUWntj67UOX5E/09to6gJNQCw3tK6b5d+6vUe3Kg2dRSxW6Yh MR1Ls5yU4eNeSWxsPIRqRPJGLENpbKTuwHrCITm+JlD1UFajUdHYwA= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:subject:date:message-id:mime-version:content-type; s= default; bh=UBOMKqeAlIorjx4RFf1PWYy/rUI=; b=KMzV2ahuSDYzGGVHyGwu yK04+LLoKQfN7ix1uxGZ8fWlLW3GeWPtG4XOUAfjwqLhT1Kv1W0zoaucCry4de54 WPPJfEd7ZAs1+r6gLWuNoFEMlL2y0MsInjxM5UyoWuouSyeo3L+TWlrvXeZdBW/x +V82zshai+rJevTI4E4xlFo= Received: (qmail 112389 invoked by alias); 9 Feb 2018 02:09:38 -0000 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 Received: (qmail 112373 invoked by uid 89); 9 Feb 2018 02:09:37 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-26.9 required=5.0 tests=BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, T_RP_MATCHES_RCVD autolearn=ham version=3.3.2 spammy= X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Fri, 09 Feb 2018 02:09:36 +0000 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 14548C04AC5C for ; Fri, 9 Feb 2018 02:09:35 +0000 (UTC) Received: from freie.home (ovpn04.gateway.prod.ext.phx2.redhat.com [10.5.9.4]) by smtp.corp.redhat.com (Postfix) with ESMTPS id C56DE5D70B for ; Fri, 9 Feb 2018 02:09:34 +0000 (UTC) Received: from livre (livre.home [172.31.160.2]) by freie.home (8.15.2/8.15.2) with ESMTP id w1929QYn028197; Fri, 9 Feb 2018 00:09:26 -0200 From: Alexandre Oliva To: gcc-patches@gcc.gnu.org Subject: [C++] [PR84231] overload on cond_expr in template Date: Fri, 09 Feb 2018 00:09:26 -0200 Message-ID: User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/25.3 (gnu/linux) MIME-Version: 1.0 A non-type-dependent COND_EXPR within a template is reconstructed with the original operands, after one with non-dependent proxies is built to determine its result type. This is problematic because the operands of a COND_EXPR determined to be an rvalue may have been converted to denote their rvalue nature. The reconstructed one, however, won't have such conversions, so lvalue_kind may not recognize it as an rvalue, which may lead to e.g. incorrect overload resolution decisions. If we mistake such a COND_EXPR for an lvalue, overload resolution might regard a conversion sequence that binds it to a non-const reference as viable, and then select that over one that binds it to a const reference. Only after template substitution would we rebuild the COND_EXPR, realize it is an rvalue, and conclude the reference binding is ill-formed, but at that point we'd have long discarded any alternate candidates we could have used. This patch verifies that, if a non-type-dependent COND_EXPRs is recognized as an rvalues, so is the to-be-template-substituted one created in its stead, so that overload resolution selects the correct alternative. Regstrapped on x86_64- and i686-linux-gnu. Ok to install? for gcc/cp/ChangeLog PR c++/84231 * typeck.c (build_x_conditional_expr): Make sure the to-be-tsubsted expr is an rvalue when it should. for gcc/testsuite/g++.dg/ChangeLog PR c++/84231 * pr84231.C: New. --- gcc/cp/typeck.c | 16 +++++++++++++++- gcc/testsuite/g++.dg/pr84231.C | 29 +++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/g++.dg/pr84231.C diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 83e767829986..25ac44e57772 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -6560,12 +6560,26 @@ build_x_conditional_expr (location_t loc, tree ifexp, tree op1, tree op2, expr = build_conditional_expr (loc, ifexp, op1, op2, complain); if (processing_template_decl && expr != error_mark_node) { + bool rval = !glvalue_p (expr); tree min = build_min_non_dep (COND_EXPR, expr, orig_ifexp, orig_op1, orig_op2); + bool mrval = !glvalue_p (min); /* Remember that the result is an lvalue or xvalue. */ - if (glvalue_p (expr) && !glvalue_p (min)) + if (!rval && mrval) TREE_TYPE (min) = cp_build_reference_type (TREE_TYPE (min), !lvalue_p (expr)); + else if (rval && !mrval) + { + /* If it was supposed to be an rvalue but it's not, adjust + one of the operands so that any overload resolution + taking this COND_EXPR as an operand makes the correct + decisions. See c++/84231. */ + TREE_OPERAND (min, 2) = build1_loc (loc, NON_LVALUE_EXPR, + TREE_TYPE (min), + TREE_OPERAND (min, 2)); + EXPR_LOCATION_WRAPPER_P (TREE_OPERAND (min, 2)) = 1; + gcc_checking_assert (!glvalue_p (min)); + } expr = convert_from_reference (min); } return expr; diff --git a/gcc/testsuite/g++.dg/pr84231.C b/gcc/testsuite/g++.dg/pr84231.C new file mode 100644 index 000000000000..de7c89a2ab69 --- /dev/null +++ b/gcc/testsuite/g++.dg/pr84231.C @@ -0,0 +1,29 @@ +// PR c++/84231 - overload resolution with cond_expr in a template + +// { dg-do compile } + +struct format { + template format& operator%(const T&) { return *this; } + template format& operator%(T&) { return *this; } +}; + +format f; + +template +void function_template(bool b) +{ + // Compiles OK with array lvalue: + f % (b ? "x" : "x"); + + // Used to fails with pointer rvalue: + f % (b ? "" : "x"); +} + +void normal_function(bool b) +{ + // Both cases compile OK in non-template function: + f % (b ? "x" : "x"); + f % (b ? "" : "x"); + + function_template(b); +}