From patchwork Wed Mar 20 20:12:13 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marek Polacek X-Patchwork-Id: 1059523 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-498195-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="BLMVzNYZ"; 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 44Ph0x6f2rz9sQw for ; Thu, 21 Mar 2019 07:12:28 +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:date :from:to:subject:message-id:mime-version:content-type; q=dns; s= default; b=VIYT9gs/YMmQj02DNGDohG0nLQ0bdsYExwI6mUBYh7dxKSFODYjdN qlc4nUfyK8uohgQY7edKU1yvFT8UhZmVPeoP9DnbR+/afW3ckwZVinWUMnrqAOKV v97iAisNSGnYP/f6HNveQqLTa+H9pCSaQ8bs7UPBCqJyVgArIA9h6k= 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:date :from:to:subject:message-id:mime-version:content-type; s= default; bh=n88Pjyasr9Zx5rrYif/dwInIe24=; b=BLMVzNYZ5boaKGY6ualf j5hvJBA228s0tFjsIp5S9sOtzYNR1i2pXO+ct8VrA411K+kE7q+3ROR18m0g4M3Y 4USwegYdBZ0y45ETNaQSSfjRMQ5TC7tdlFvfOWFE82PpC0heVhkamxan3EnBLtZH 67lULOoY0a+pV4FuVS2OGfQ= Received: (qmail 25830 invoked by alias); 20 Mar 2019 20:12:20 -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 25790 invoked by uid 89); 20 Mar 2019 20:12:18 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-23.8 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_SHORT, SPF_HELO_PASS autolearn=ham version=3.3.1 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; Wed, 20 Mar 2019 20:12:17 +0000 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 025FD8553A for ; Wed, 20 Mar 2019 20:12:16 +0000 (UTC) Received: from redhat.com (unknown [10.20.4.51]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 9EB0719C66; Wed, 20 Mar 2019 20:12:15 +0000 (UTC) Date: Wed, 20 Mar 2019 16:12:13 -0400 From: Marek Polacek To: GCC Patches , Jason Merrill Subject: C++ PATCH for c++/87145 - bogus error converting class type in template argument list Message-ID: <20190320201213.GA26967@redhat.com> MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.11.3 (2019-02-01) The fix for 77656 caused us to call convert_nontype_argument even for value-dependent arguments, to perform the conversion in order to avoid a bogus warning. In this case, the argument is Pod{N}. The call to build_converted_constant_expr in convert_nontype_argument produces Pod::operator Enum(&{N}). It doesn't crash because we're in a template and build_address no longer crashes on CONSTRUCTORs in a template. Then when instantiating the function foo we substitute its argument: &{N}. So we're in tsubst_copy_and_build/ADDR_EXPR. The call to tsubst_non_call_postfix_expression turns {N} into TARGET_EXPR . Then build_x_unary_op is supposed to put the ADDR_EXPR back. It calls cp_build_addr_expr_strict. But it's *strict*, so the prvalue of class type TARGET_EXPR isn't allowed -> error. It's _strict since , that seem like a desirable change, and we had a warning for taking the address of a TARGET_EXPR in build_x_unary_op even before that. So rather than messing with _strict, let's avoid this scenario altogether. I checked whether we have a case in the testsuite that results in convert_like getting a value-dependent CONSTRUCTOR, but found none. With this patch, we avoid it, and only call convert_nontype_argument after substitution, at which point maybe_constant_value will be able to evaluate the conversion to a constant. This problem doesn't occur when passing Pod{N} as an argument to a function, or using it as an array dimension; seems we avoid converting the argument if it's value-dependent. Bootstrapped/regtested on x86_64-linux, ok for trunk? 2019-03-20 Marek Polacek PR c++/87145 - bogus error converting class type in template arg list. * pt.c (convert_template_argument): Don't call convert_nontype_argument if it could involve calling a conversion function with a value-dependent constructor as its argument. * g++.dg/cpp0x/constexpr-conv3.C: New test. * g++.dg/cpp0x/constexpr-conv4.C: New test. diff --git gcc/cp/pt.c gcc/cp/pt.c index 0acc16d1b92..6878583d99b 100644 --- gcc/cp/pt.c +++ gcc/cp/pt.c @@ -8056,7 +8056,16 @@ convert_template_argument (tree parm, t = canonicalize_type_argument (t, complain); if (!type_dependent_expression_p (orig_arg) - && !uses_template_parms (t)) + && !uses_template_parms (t) + /* This might trigger calling a conversion function with + a value-dependent argument, which could invoke taking + the address of a temporary representing the result of + the conversion. */ + && !(COMPOUND_LITERAL_P (orig_arg) + && MAYBE_CLASS_TYPE_P (TREE_TYPE (orig_arg)) + && TYPE_HAS_CONVERSION (TREE_TYPE (orig_arg)) + && INTEGRAL_OR_ENUMERATION_TYPE_P (t) + && value_dependent_expression_p (orig_arg))) /* We used to call digest_init here. However, digest_init will report errors, which we don't want when complain is zero. More importantly, digest_init will try too @@ -8092,7 +8101,7 @@ convert_template_argument (tree parm, && TREE_CODE (TREE_TYPE (innertype)) == FUNCTION_TYPE && TREE_OPERAND_LENGTH (inner) > 0 && reject_gcc_builtin (TREE_OPERAND (inner, 0))) - return error_mark_node; + return error_mark_node; } if (TREE_CODE (val) == SCOPE_REF) diff --git gcc/testsuite/g++.dg/cpp0x/constexpr-conv3.C gcc/testsuite/g++.dg/cpp0x/constexpr-conv3.C new file mode 100644 index 00000000000..3f47c58cd2a --- /dev/null +++ gcc/testsuite/g++.dg/cpp0x/constexpr-conv3.C @@ -0,0 +1,25 @@ +// PR c++/87145 +// { dg-do compile { target c++11 } } + +template struct integral_constant { + static constexpr T value = t; +}; + +enum class Enum : unsigned {}; + +struct Pod { + unsigned val; + + constexpr operator Enum() const { + return static_cast(val); + } +}; + +template +constexpr void foo() { + using Foo = integral_constant; +} + +int main() { + foo<2>(); +} diff --git gcc/testsuite/g++.dg/cpp0x/constexpr-conv4.C gcc/testsuite/g++.dg/cpp0x/constexpr-conv4.C new file mode 100644 index 00000000000..f4e3f00a585 --- /dev/null +++ gcc/testsuite/g++.dg/cpp0x/constexpr-conv4.C @@ -0,0 +1,25 @@ +// PR c++/87145 +// { dg-do compile { target c++11 } } + +struct S { + int val; + + constexpr operator int() const { + return static_cast(val); + } +}; + +template +struct F { }; + +template +constexpr void foo() { + F f; + F f2; +} + +int +main() +{ + foo<2>(); +}