From patchwork Sat Sep 2 00:00:01 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marek Polacek X-Patchwork-Id: 137414 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:c792:0:b0:3f2:4152:657d with SMTP id b18csp1210167vqu; Fri, 1 Sep 2023 17:01:56 -0700 (PDT) X-Google-Smtp-Source: AGHT+IGwM+D/LxxRKoGqgLUO4TD80jEiB9dhSW35zA3yrIRyvCODxDa01fP5HApmHGFfFt4W8AnJ X-Received: by 2002:a17:907:7886:b0:9a1:d915:d8dd with SMTP id ku6-20020a170907788600b009a1d915d8ddmr2839085ejc.10.1693612915878; Fri, 01 Sep 2023 17:01:55 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1693612915; cv=none; d=google.com; s=arc-20160816; b=jPVoBDO849GZZBb9Oi6eVZuHuu5XiR+WF/ydlV0j2L7my+bzFAWLxZeD6kDo/7zQid wDB5j1bB0kb3+pgR66iwUDUp0PMTJg/RnUOnMY4Z4Inzx7wvc4hxKI5KI3D+XrTRydhJ DowhCHR3OBiRHxcXm0M3qOoApExdSInbV7orvQ5XfdfwD0EMXFGPWLZYkU/IpOwwySq2 1C1I+vqRPYSz92yhcot92aFE747PJxhZRXqH0xTk6qAFWO+jPnE/MOcCEj0IsgLr7YEO XsDw7DKfBdn8Bk/aHozbkWOW6OvirbJea9TDNR1S9ipaXrbHuENoQ3FgEaSmGx0PGIem ZnLA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:reply-to:from:list-subscribe:list-help:list-post :list-archive:list-unsubscribe:list-id:precedence :content-transfer-encoding:mime-version:message-id:date:subject:to :dmarc-filter:delivered-to:dkim-signature:dkim-filter; bh=Guz7Fk4mXpGbLpWUbi5arOzENQaWqfy1jQp0FzoKAgQ=; fh=fpCc4VkYXmQrurtjjuGMl3oKQaOAjGwXgTAjHxumZ4s=; b=zxqruwC67WVgJ1ljZl8+n4/1kPdu3lkcMJHw9PJWkeU4ZapVWb/BuvglhMmcbLBZr4 BETJwbvOdK1iqrVVtzWoVe1CrpzNYzaVNTl6lqU72wI9gZTiCE1isQNl65MIP9sLggcq YHv3L993fHNY3X42X5T2tL1kuz8npvXCdWwLWUi4GwENcgSUnqDJK+Im0Piu1DcFyFmh k8vqFDZNeGmk679If7Hf8yq6jW5A2qu4zA4Tg/e7lTMD70eXrYxWVY/TO+mvNyMIl21k LSi0nDFqSPT2rYwqHEt7kRf6NkkGjdTGjeWCdrzidWuc/1BmQmvsvbDs8iWrRknkJbkr 2vSg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gcc.gnu.org header.s=default header.b=BA2SzFNc; spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 8.43.85.97 as permitted sender) smtp.mailfrom="gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=gnu.org Received: from server2.sourceware.org (ip-8-43-85-97.sourceware.org. [8.43.85.97]) by mx.google.com with ESMTPS id re1-20020a170906d8c100b009a19f88af95si3244718ejb.1042.2023.09.01.17.01.55 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 01 Sep 2023 17:01:55 -0700 (PDT) Received-SPF: pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 8.43.85.97 as permitted sender) client-ip=8.43.85.97; Authentication-Results: mx.google.com; dkim=pass header.i=@gcc.gnu.org header.s=default header.b=BA2SzFNc; spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 8.43.85.97 as permitted sender) smtp.mailfrom="gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=gnu.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id C25FA3858408 for ; Sat, 2 Sep 2023 00:01:54 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org C25FA3858408 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1693612914; bh=Guz7Fk4mXpGbLpWUbi5arOzENQaWqfy1jQp0FzoKAgQ=; h=To:Subject:Date:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:From; b=BA2SzFNcCpWB7+PrFeycgngqxsD2TH8QGq74gvZFa28euN0upoZ5OtHebak7lTclG CzfMQBh1ZfXau2jT2/OtVw93PKB+6BWQWAhMCAtdOaae73mYK1/e1zloY/xZK2egFc z1n8x35lRWdrbuEFLejoM3VLD5wIvTwA0lY+ECxk= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by sourceware.org (Postfix) with ESMTPS id 2A1363858D1E for ; Sat, 2 Sep 2023 00:00:17 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 2A1363858D1E Received: from mimecast-mx02.redhat.com (mx-ext.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-318-wE8g9SuZMoCyzpmV_mWRPg-1; Fri, 01 Sep 2023 20:00:06 -0400 X-MC-Unique: wE8g9SuZMoCyzpmV_mWRPg-1 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.rdu2.redhat.com [10.11.54.7]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id CF4C61C05152 for ; Sat, 2 Sep 2023 00:00:05 +0000 (UTC) Received: from pdp-11.redhat.com (unknown [10.22.17.86]) by smtp.corp.redhat.com (Postfix) with ESMTP id B02BD1402C0A; Sat, 2 Sep 2023 00:00:05 +0000 (UTC) To: Jason Merrill , GCC Patches Subject: [PATCH] c++: improve verify_constant diagnostic [PR91483] Date: Fri, 1 Sep 2023 20:00:01 -0400 Message-ID: <20230902000001.873118-1-polacek@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.7 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-12.4 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H4, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_NONE, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Marek Polacek via Gcc-patches From: Marek Polacek Reply-To: Marek Polacek Errors-To: gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org Sender: "Gcc-patches" X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1775881857007427175 X-GMAIL-MSGID: 1775881857007427175 Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk? -- >8 -- When verify_constant complains, it's pretty terse. Consider void test () { constexpr int i = 42; constexpr const int *p = &i; } where it says "'& i' is not a constant expression". OK, but why? With this patch, we say: b.C:5:28: error: '& i' is not a constant expression 5 | constexpr const int *p = &i; | ^~ b.C:5:28: note: pointer to 'i' is not a constant expression b.C:4:17: note: address of non-static constexpr variable 'i' may differ on each invocation of the enclosing function; add 'static' to give it a constant address 4 | constexpr int i = 42; | ^ | static which brings g++ on par with clang++. gcc/cp/ChangeLog: * constexpr.cc (verify_constant_explain_r): New. (verify_constant): Call it. gcc/testsuite/ChangeLog: * g++.dg/diagnostic/constexpr3.C: New test. --- gcc/cp/constexpr.cc | 56 +++++++++++++++++++- gcc/testsuite/g++.dg/diagnostic/constexpr3.C | 32 +++++++++++ 2 files changed, 87 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/g++.dg/diagnostic/constexpr3.C base-commit: 6f06152541d62ae7c8579b7d7bf552be19e15b05 diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc index 8bd5c4a47f8..6d5aed82377 100644 --- a/gcc/cp/constexpr.cc +++ b/gcc/cp/constexpr.cc @@ -3381,6 +3381,54 @@ ok: } } +/* *TP was not deemed constant by reduced_constant_expression_p. Explain + why and suggest what could be done about it. */ + +static tree +verify_constant_explain_r (tree *tp, int *, void *) +{ + bool ref_p = false; + + switch (TREE_CODE (*tp)) + { + CASE_CONVERT: + if (TREE_CODE (TREE_OPERAND (*tp, 0)) != ADDR_EXPR) + break; + ref_p = TYPE_REF_P (TREE_TYPE (*tp)); + *tp = TREE_OPERAND (*tp, 0); + gcc_fallthrough (); + case ADDR_EXPR: + { + tree op = TREE_OPERAND (*tp, 0); + if (VAR_P (op) + && DECL_DECLARED_CONSTEXPR_P (op) + && !TREE_STATIC (op) + /* ??? We should also say something about temporaries. */ + && !DECL_ARTIFICIAL (op)) + { + if (ref_p) + inform (location_of (*tp), "reference to %qD is not a constant " + "expression", op); + else + inform (location_of (*tp), "pointer to %qD is not a constant " + "expression", op); + const location_t op_loc = DECL_SOURCE_LOCATION (op); + rich_location richloc (line_table, op_loc); + richloc.add_fixit_insert_before (op_loc, "static "); + inform (&richloc, + "address of non-static constexpr variable %qD may differ on " + "each invocation of the enclosing function; add % " + "to give it a constant address", op); + } + break; + } + default: + break; + } + + return NULL_TREE; +} + /* Some expressions may have constant operands but are not constant themselves, such as 1/0. Call this function to check for that condition. @@ -3398,7 +3446,13 @@ verify_constant (tree t, bool allow_non_constant, bool *non_constant_p, && t != void_node) { if (!allow_non_constant) - error ("%q+E is not a constant expression", t); + { + auto_diagnostic_group d; + error_at (cp_expr_loc_or_input_loc (t), + "%q+E is not a constant expression", t); + cp_walk_tree_without_duplicates (&t, verify_constant_explain_r, + nullptr); + } *non_constant_p = true; } if (TREE_OVERFLOW_P (t)) diff --git a/gcc/testsuite/g++.dg/diagnostic/constexpr3.C b/gcc/testsuite/g++.dg/diagnostic/constexpr3.C new file mode 100644 index 00000000000..b6e43a93664 --- /dev/null +++ b/gcc/testsuite/g++.dg/diagnostic/constexpr3.C @@ -0,0 +1,32 @@ +// { dg-do compile { target c++14 } } + +struct X { + int const& var; +}; + +struct A { + A *ap = this; +}; + +constexpr A +foo () +{ + return {}; +} + +void +test () +{ + constexpr int i = 42; // { dg-message "may differ on each invocation" } + + constexpr X x{i}; // { dg-error "not a constant expression" } + // { dg-message "reference to .i. is not a constant expression" "" { target *-*-* } .-1 } + constexpr const int *p = &i; // { dg-error "not a constant expression" } + // { dg-message "pointer to .i. is not a constant expression" "" { target *-*-* } .-1 } + + constexpr A a = foo (); // { dg-error "not a constant expression" } + // { dg-message "pointer to .a. is not a constant expression|may differ" "" { target *-*-* } .-1 } + + constexpr const int *q = __builtin_launder (&i); // { dg-error "not a constant expression" } + // { dg-message "pointer to .i. is not a constant expression" "" { target *-*-* } .-1 } +}