[clang-tools-extra] [clang-tidy] fix cppcoreguidelines-narrowing-conversions false positives when narrowing integer to signed integer in C++20 (PR #116591)
Congcong Cai via cfe-commits
cfe-commits at lists.llvm.org
Mon Nov 18 01:14:15 PST 2024
https://github.com/HerrCai0907 created https://github.com/llvm/llvm-project/pull/116591
None
>From ba1a73e0220937e26618ce0417a7aeadd0ed3792 Mon Sep 17 00:00:00 2001
From: Congcong Cai <congcongcai0907 at 163.com>
Date: Mon, 18 Nov 2024 15:09:34 +0800
Subject: [PATCH] [clang-tidy] fix cppcoreguidelines-narrowing-conversions
false positives when narrowing integer to signed integer in C++20
---
.../NarrowingConversionsCheck.cpp | 8 ++-
clang-tools-extra/docs/ReleaseNotes.rst | 4 ++
.../narrowing-conversions.rst | 12 ++--
.../narrowing-conversions-bitfields.cpp | 4 +-
.../narrowing-conversions-cxx20.cpp | 63 +++++++++++++++++++
...-conversions-equivalentbitwidth-option.cpp | 4 +-
...sions-ignoreconversionfromtypes-option.cpp | 4 +-
...rrowing-conversions-intemplates-option.cpp | 4 +-
.../narrowing-conversions-long-is-32bits.cpp | 4 +-
...ng-conversions-narrowinginteger-option.cpp | 4 +-
.../narrowing-conversions-unsigned-char.cpp | 4 +-
.../narrowing-conversions.cpp | 2 +-
12 files changed, 96 insertions(+), 21 deletions(-)
create mode 100644 clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/narrowing-conversions-cxx20.cpp
diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/NarrowingConversionsCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/NarrowingConversionsCheck.cpp
index 45fef9471d5211..a053aa1544e8e1 100644
--- a/clang-tools-extra/clang-tidy/cppcoreguidelines/NarrowingConversionsCheck.cpp
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/NarrowingConversionsCheck.cpp
@@ -393,8 +393,14 @@ void NarrowingConversionsCheck::handleIntegralCast(const ASTContext &Context,
const Expr &Lhs,
const Expr &Rhs) {
if (WarnOnIntegerNarrowingConversion) {
+ // From [conv.integral] since C++20
+ // The result is the unique value of the destination type that is congruent
+ // to the source integer modulo 2^N, where N is the width of the destination
+ // type.
+ if (getLangOpts().CPlusPlus20)
+ return;
const BuiltinType *ToType = getBuiltinType(Lhs);
- // From [conv.integral]p7.3.8:
+ // From [conv.integral] before C++20:
// Conversions to unsigned integer is well defined so no warning is issued.
// "The resulting value is the smallest unsigned value equal to the source
// value modulo 2^n where n is the number of bits used to represent the
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index f967dfabd1c940..50dd594d177631 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -207,6 +207,10 @@ Changes in existing checks
<clang-tidy/checks/cppcoreguidelines/init-variables>` check by fixing the
insertion location for function pointers.
+- Fixed :doc:`cppcoreguidelines-narrowing-conversions
+ <clang-tidy/checks/cppcoreguidelines/narrowing-conversions>` check to avoid
+ false positives when narrowing integer to signed integer in C++20.
+
- Improved :doc:`cppcoreguidelines-prefer-member-initializer
<clang-tidy/checks/cppcoreguidelines/prefer-member-initializer>` check to
avoid false positive when member initialization depends on a structured
diff --git a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/narrowing-conversions.rst b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/narrowing-conversions.rst
index 04260e75aa558f..eb9539a6c25b1c 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/narrowing-conversions.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/narrowing-conversions.rst
@@ -12,7 +12,7 @@ This check implements `ES.46
from the C++ Core Guidelines.
We enforce only part of the guideline, more specifically, we flag narrowing conversions from:
- - an integer to a narrower integer (e.g. ``char`` to ``unsigned char``)
+ - an integer to a narrower integer before C++20 (e.g. ``char`` to ``unsigned char``)
if WarnOnIntegerNarrowingConversion Option is set,
- an integer to a narrower floating-point (e.g. ``uint64_t`` to ``float``)
if WarnOnIntegerToFloatingPointNarrowingConversion Option is set,
@@ -89,7 +89,9 @@ the range [-2^31, 2^31-1].
You may have encountered messages like "narrowing conversion from 'unsigned int'
to signed type 'int' is implementation-defined".
-The C/C++ standard does not mandate two's complement for signed integers, and so
-the compiler is free to define what the semantics are for converting an unsigned
-integer to signed integer. Clang's implementation uses the two's complement
-format.
+Before C++20, the C/C++ standard does not mandate two's complement for signed
+integers, and so the compiler is free to define what the semantics are for
+converting an unsigned integer to signed integer. Clang's implementation uses
+the two's complement format.
+Since C++20, the C++ standard defines the conversion between all kinds of
+integers.
diff --git a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/narrowing-conversions-bitfields.cpp b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/narrowing-conversions-bitfields.cpp
index 36fde38202efcd..7c5c38321ae94b 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/narrowing-conversions-bitfields.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/narrowing-conversions-bitfields.cpp
@@ -1,5 +1,5 @@
-// RUN: %check_clang_tidy %s cppcoreguidelines-narrowing-conversions %t \
-// RUN: -std=c++17 -- -target x86_64-unknown-linux
+// RUN: %check_clang_tidy %s cppcoreguidelines-narrowing-conversions %t -std=c++17 \
+// RUN: -- -target x86_64-unknown-linux
#define CHAR_BITS 8
static_assert(sizeof(unsigned int) == 32 / CHAR_BITS);
diff --git a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/narrowing-conversions-cxx20.cpp b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/narrowing-conversions-cxx20.cpp
new file mode 100644
index 00000000000000..32cf53aa24615b
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/narrowing-conversions-cxx20.cpp
@@ -0,0 +1,63 @@
+// RUN: %check_clang_tidy %s cppcoreguidelines-narrowing-conversions %t -std=c++20 -- -Wno-everything
+
+void narrow_integer_to_signed_integer_is_ok_since_cxx20() {
+ char c;
+ short s;
+ int i;
+ long l;
+ long long ll;
+
+ unsigned char uc;
+ unsigned short us;
+ unsigned int ui;
+ unsigned long ul;
+ unsigned long long ull;
+
+ c = c;
+ c = s;
+ c = i;
+ c = l;
+ c = ll;
+
+ c = uc;
+ c = us;
+ c = ui;
+ c = ul;
+ c = ull;
+
+ i = c;
+ i = s;
+ i = i;
+ i = l;
+ i = ll;
+
+ i = uc;
+ i = us;
+ i = ui;
+ i = ul;
+ i = ull;
+
+ ll = c;
+ ll = s;
+ ll = i;
+ ll = l;
+ ll = ll;
+
+ ll = uc;
+ ll = us;
+ ll = ui;
+ ll = ul;
+ ll = ull;
+}
+
+void narrow_constant_to_signed_integer_is_ok_since_cxx20() {
+ char c1 = -128;
+ char c2 = 127;
+ char c3 = -129;
+ char c4 = 128;
+
+ short s1 = -32768;
+ short s2 = 32767;
+ short s3 = -32769;
+ short s4 = 32768;
+}
diff --git a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/narrowing-conversions-equivalentbitwidth-option.cpp b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/narrowing-conversions-equivalentbitwidth-option.cpp
index fb5c7e36eeb0df..36f0f2a94c5ab1 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/narrowing-conversions-equivalentbitwidth-option.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/narrowing-conversions-equivalentbitwidth-option.cpp
@@ -1,7 +1,7 @@
-// RUN: %check_clang_tidy -check-suffix=DEFAULT %s \
+// RUN: %check_clang_tidy -check-suffix=DEFAULT %s -std=c++17 \
// RUN: cppcoreguidelines-narrowing-conversions %t --
-// RUN: %check_clang_tidy -check-suffix=DISABLED %s \
+// RUN: %check_clang_tidy -check-suffix=DISABLED %s -std=c++17 \
// RUN: cppcoreguidelines-narrowing-conversions %t -- \
// RUN: -config='{CheckOptions: { \
// RUN: cppcoreguidelines-narrowing-conversions.WarnOnEquivalentBitWidth: 0}}'
diff --git a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/narrowing-conversions-ignoreconversionfromtypes-option.cpp b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/narrowing-conversions-ignoreconversionfromtypes-option.cpp
index 91e908f535a0d4..3a7e045068c1fd 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/narrowing-conversions-ignoreconversionfromtypes-option.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/narrowing-conversions-ignoreconversionfromtypes-option.cpp
@@ -1,7 +1,7 @@
-// RUN: %check_clang_tidy -check-suffix=DEFAULT %s \
+// RUN: %check_clang_tidy -check-suffix=DEFAULT %s -std=c++17 \
// RUN: cppcoreguidelines-narrowing-conversions %t --
-// RUN: %check_clang_tidy -check-suffix=IGNORED %s \
+// RUN: %check_clang_tidy -check-suffix=IGNORED %s -std=c++17 \
// RUN: cppcoreguidelines-narrowing-conversions %t -- \
// RUN: -config='{CheckOptions: { \
// RUN: cppcoreguidelines-narrowing-conversions.IgnoreConversionFromTypes: "global_size_t;nested_size_type;long" \
diff --git a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/narrowing-conversions-intemplates-option.cpp b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/narrowing-conversions-intemplates-option.cpp
index cb19ed78cce8a7..f5967c8a5e7ade 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/narrowing-conversions-intemplates-option.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/narrowing-conversions-intemplates-option.cpp
@@ -1,7 +1,7 @@
-// RUN: %check_clang_tidy -check-suffix=DEFAULT %s \
+// RUN: %check_clang_tidy -check-suffix=DEFAULT %s -std=c++17 \
// RUN: cppcoreguidelines-narrowing-conversions %t --
-// RUN: %check_clang_tidy -check-suffix=WARN %s \
+// RUN: %check_clang_tidy -check-suffix=WARN %s -std=c++17 \
// RUN: cppcoreguidelines-narrowing-conversions %t -- \
// RUN: -config='{CheckOptions: { \
// RUN: cppcoreguidelines-narrowing-conversions.WarnWithinTemplateInstantiation: 1 \
diff --git a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/narrowing-conversions-long-is-32bits.cpp b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/narrowing-conversions-long-is-32bits.cpp
index dcf1848a30f664..f63a758373a62c 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/narrowing-conversions-long-is-32bits.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/narrowing-conversions-long-is-32bits.cpp
@@ -1,5 +1,5 @@
-// RUN: %check_clang_tidy %s cppcoreguidelines-narrowing-conversions %t \
-// RUN: -- -- -target x86_64-unknown-linux -m32
+// RUN: %check_clang_tidy %s cppcoreguidelines-narrowing-conversions %t -std=c++17 \
+// RUN: -- -target x86_64-unknown-linux -m32
static_assert(sizeof(int) * 8 == 32, "int is 32-bits");
static_assert(sizeof(long) * 8 == 32, "long is 32-bits");
diff --git a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/narrowing-conversions-narrowinginteger-option.cpp b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/narrowing-conversions-narrowinginteger-option.cpp
index f58de65f042328..435f333ad180d6 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/narrowing-conversions-narrowinginteger-option.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/narrowing-conversions-narrowinginteger-option.cpp
@@ -1,8 +1,8 @@
-// RUN: %check_clang_tidy -check-suffix=DEFAULT %s \
+// RUN: %check_clang_tidy -check-suffix=DEFAULT %s -std=c++17 \
// RUN: cppcoreguidelines-narrowing-conversions %t -- \
// RUN: -config='{CheckOptions: {cppcoreguidelines-narrowing-conversions.WarnOnIntegerNarrowingConversion: true}}'
-// RUN: %check_clang_tidy -check-suffix=DISABLED %s \
+// RUN: %check_clang_tidy -check-suffix=DISABLED %s -std=c++17 \
// RUN: cppcoreguidelines-narrowing-conversions %t -- \
// RUN: -config='{CheckOptions: {cppcoreguidelines-narrowing-conversions.WarnOnIntegerNarrowingConversion: false}}'
diff --git a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/narrowing-conversions-unsigned-char.cpp b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/narrowing-conversions-unsigned-char.cpp
index 6bd437f98d44c5..dcce3864feedf3 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/narrowing-conversions-unsigned-char.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/narrowing-conversions-unsigned-char.cpp
@@ -1,5 +1,5 @@
-// RUN: %check_clang_tidy %s cppcoreguidelines-narrowing-conversions %t \
-// RUN: -- -- -target x86_64-unknown-linux -funsigned-char
+// RUN: %check_clang_tidy %s cppcoreguidelines-narrowing-conversions %t -std=c++17 \
+// RUN: -- -target x86_64-unknown-linux -funsigned-char
void narrow_integer_to_unsigned_integer_is_ok() {
signed char sc;
diff --git a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/narrowing-conversions.cpp b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/narrowing-conversions.cpp
index 29b38e74e1a22d..6c7993cb51b941 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/narrowing-conversions.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/narrowing-conversions.cpp
@@ -1,4 +1,4 @@
-// RUN: %check_clang_tidy %s cppcoreguidelines-narrowing-conversions %t \
+// RUN: %check_clang_tidy %s cppcoreguidelines-narrowing-conversions %t -std=c++17 \
// RUN: -config="{CheckOptions: { \
// RUN: cppcoreguidelines-narrowing-conversions.WarnOnFloatingPointNarrowingConversion: false}}" \
// RUN: -- -target x86_64-unknown-linux -fsigned-char
More information about the cfe-commits
mailing list