From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mengyan1223.wang (mengyan1223.wang [89.208.246.23]) by sourceware.org (Postfix) with ESMTPS id D9A173857C40 for ; Sat, 10 Jul 2021 17:48:58 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org D9A173857C40 Received: from [IPv6:240e:35a:1024:d400:dc73:854d:832e:3] (unknown [IPv6:240e:35a:1024:d400:dc73:854d:832e:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange ECDHE (P-256) server-signature ECDSA (P-384) server-digest SHA384) (Client did not present a certificate) (Authenticated sender: xry111@mengyan1223.wang) by mengyan1223.wang (Postfix) with ESMTPSA id 8C76366664; Sat, 10 Jul 2021 13:48:54 -0400 (EDT) Message-ID: <97e5dcd67f293955d90123c910b9d81b2b1269dd.camel@mengyan1223.wang> Subject: [PATCH] ipa-devirt: check precision mismatch of enum values [PR101396] From: Xi Ruoyao Reply-To: xry111@mengyan1223.wang To: gcc-patches@gcc.gnu.org Cc: xry111@mengyan1223.wang Date: Sun, 11 Jul 2021 01:48:47 +0800 Content-Type: text/plain; charset="UTF-8" User-Agent: Evolution 3.40.2 MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Spam-Status: No, score=-3039.5 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, JMQ_SPF_NEUTRAL, SPF_HELO_PASS, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 10 Jul 2021 17:49:01 -0000 We are comparing enum values (in wide_int) to check ODR violation. However, if we compare two wide_int values with different precision, we'll trigger an assert, leading to ICE. With enum-base introduced in C++11, it's easy to sink into this situation. To fix the issue, we need to explicitly check this kind of mismatch, and emit a proper warning message if there is such one. Bootstrapped & regtested on x86_64-linux-gnu. Ok for trunk? gcc/ PR ipa/101396 * ipa-devirt.c (ipa_odr_read_section): Compare the precision of enum values, and emit a warning if they mismatch. gcc/testsuite/ PR ipa/101396 * g++.dg/lto/pr101396_0.C: New test. * g++.dg/lto/pr101396_1.C: New test. --- gcc/ipa-devirt.c | 9 +++++++++ gcc/testsuite/g++.dg/lto/pr101396_0.C | 12 ++++++++++++ gcc/testsuite/g++.dg/lto/pr101396_1.C | 10 ++++++++++ 3 files changed, 31 insertions(+) create mode 100644 gcc/testsuite/g++.dg/lto/pr101396_0.C create mode 100644 gcc/testsuite/g++.dg/lto/pr101396_1.C diff --git a/gcc/ipa-devirt.c b/gcc/ipa-devirt.c index 8cd1100aba9..8deec75b2df 100644 --- a/gcc/ipa-devirt.c +++ b/gcc/ipa-devirt.c @@ -4193,6 +4193,8 @@ ipa_odr_read_section (struct lto_file_decl_data *file_data, const char *data, if (do_warning != -1 || j >= this_enum.vals.length ()) continue; if (strcmp (id, this_enum.vals[j].name) + || (val.get_precision() != + this_enum.vals[j].val.get_precision()) || val != this_enum.vals[j].val) { warn_name = xstrdup (id); @@ -4260,6 +4262,13 @@ ipa_odr_read_section (struct lto_file_decl_data *file_data, const char *data, "name %qs differs from name %qs defined" " in another translation unit", this_enum.vals[j].name, warn_name); + else if (this_enum.vals[j].val.get_precision() != + warn_value.get_precision()) + inform (this_enum.vals[j].locus, + "name %qs is defined as %u-bit while another " + "translation unit defines it as %u-bit", + warn_name, this_enum.vals[j].val.get_precision(), + warn_value.get_precision()); /* FIXME: In case there is easy way to print wide_ints, perhaps we could do it here instead of overflow check. */ else if (wi::fits_shwi_p (this_enum.vals[j].val) diff --git a/gcc/testsuite/g++.dg/lto/pr101396_0.C b/gcc/testsuite/g++.dg/lto/pr101396_0.C new file mode 100644 index 00000000000..b7a2947a880 --- /dev/null +++ b/gcc/testsuite/g++.dg/lto/pr101396_0.C @@ -0,0 +1,12 @@ +/* { dg-lto-do link } */ + +enum A : __UINT32_TYPE__ { // { dg-lto-warning "6: type 'A' violates the C\\+\\+ One Definition Rule" } + a, // { dg-lto-note "3: name 'a' is defined as 32-bit while another translation unit defines it as 64-bit" } + b, + c +}; + +int main() +{ + return (int) A::a; +} diff --git a/gcc/testsuite/g++.dg/lto/pr101396_1.C b/gcc/testsuite/g++.dg/lto/pr101396_1.C new file mode 100644 index 00000000000..a6d032d694d --- /dev/null +++ b/gcc/testsuite/g++.dg/lto/pr101396_1.C @@ -0,0 +1,10 @@ +enum A : __UINT64_TYPE__ { // { dg-lto-note "6: an enum with different value name is defined in another translation unit" } + a, // { dg-lto-note "3: mismatching definition" } + b, + c +}; + +int f(enum A x) +{ + return (int) x; +} -- 2.32.0