Skip to content

Commit ba1a73e

Browse files
committed
[clang-tidy] fix cppcoreguidelines-narrowing-conversions false positives when narrowing integer to signed integer in C++20
1 parent 3f9d02a commit ba1a73e

12 files changed

+96
-21
lines changed

clang-tools-extra/clang-tidy/cppcoreguidelines/NarrowingConversionsCheck.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -393,8 +393,14 @@ void NarrowingConversionsCheck::handleIntegralCast(const ASTContext &Context,
393393
const Expr &Lhs,
394394
const Expr &Rhs) {
395395
if (WarnOnIntegerNarrowingConversion) {
396+
// From [conv.integral] since C++20
397+
// The result is the unique value of the destination type that is congruent
398+
// to the source integer modulo 2^N, where N is the width of the destination
399+
// type.
400+
if (getLangOpts().CPlusPlus20)
401+
return;
396402
const BuiltinType *ToType = getBuiltinType(Lhs);
397-
// From [conv.integral]p7.3.8:
403+
// From [conv.integral] before C++20:
398404
// Conversions to unsigned integer is well defined so no warning is issued.
399405
// "The resulting value is the smallest unsigned value equal to the source
400406
// value modulo 2^n where n is the number of bits used to represent the

clang-tools-extra/docs/ReleaseNotes.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,10 @@ Changes in existing checks
207207
<clang-tidy/checks/cppcoreguidelines/init-variables>` check by fixing the
208208
insertion location for function pointers.
209209

210+
- Fixed :doc:`cppcoreguidelines-narrowing-conversions
211+
<clang-tidy/checks/cppcoreguidelines/narrowing-conversions>` check to avoid
212+
false positives when narrowing integer to signed integer in C++20.
213+
210214
- Improved :doc:`cppcoreguidelines-prefer-member-initializer
211215
<clang-tidy/checks/cppcoreguidelines/prefer-member-initializer>` check to
212216
avoid false positive when member initialization depends on a structured

clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/narrowing-conversions.rst

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ This check implements `ES.46
1212
from the C++ Core Guidelines.
1313

1414
We enforce only part of the guideline, more specifically, we flag narrowing conversions from:
15-
- an integer to a narrower integer (e.g. ``char`` to ``unsigned char``)
15+
- an integer to a narrower integer before C++20 (e.g. ``char`` to ``unsigned char``)
1616
if WarnOnIntegerNarrowingConversion Option is set,
1717
- an integer to a narrower floating-point (e.g. ``uint64_t`` to ``float``)
1818
if WarnOnIntegerToFloatingPointNarrowingConversion Option is set,
@@ -89,7 +89,9 @@ the range [-2^31, 2^31-1].
8989

9090
You may have encountered messages like "narrowing conversion from 'unsigned int'
9191
to signed type 'int' is implementation-defined".
92-
The C/C++ standard does not mandate two's complement for signed integers, and so
93-
the compiler is free to define what the semantics are for converting an unsigned
94-
integer to signed integer. Clang's implementation uses the two's complement
95-
format.
92+
Before C++20, the C/C++ standard does not mandate two's complement for signed
93+
integers, and so the compiler is free to define what the semantics are for
94+
converting an unsigned integer to signed integer. Clang's implementation uses
95+
the two's complement format.
96+
Since C++20, the C++ standard defines the conversion between all kinds of
97+
integers.

clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/narrowing-conversions-bitfields.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
// RUN: %check_clang_tidy %s cppcoreguidelines-narrowing-conversions %t \
2-
// RUN: -std=c++17 -- -target x86_64-unknown-linux
1+
// RUN: %check_clang_tidy %s cppcoreguidelines-narrowing-conversions %t -std=c++17 \
2+
// RUN: -- -target x86_64-unknown-linux
33

44
#define CHAR_BITS 8
55
static_assert(sizeof(unsigned int) == 32 / CHAR_BITS);
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
// RUN: %check_clang_tidy %s cppcoreguidelines-narrowing-conversions %t -std=c++20 -- -Wno-everything
2+
3+
void narrow_integer_to_signed_integer_is_ok_since_cxx20() {
4+
char c;
5+
short s;
6+
int i;
7+
long l;
8+
long long ll;
9+
10+
unsigned char uc;
11+
unsigned short us;
12+
unsigned int ui;
13+
unsigned long ul;
14+
unsigned long long ull;
15+
16+
c = c;
17+
c = s;
18+
c = i;
19+
c = l;
20+
c = ll;
21+
22+
c = uc;
23+
c = us;
24+
c = ui;
25+
c = ul;
26+
c = ull;
27+
28+
i = c;
29+
i = s;
30+
i = i;
31+
i = l;
32+
i = ll;
33+
34+
i = uc;
35+
i = us;
36+
i = ui;
37+
i = ul;
38+
i = ull;
39+
40+
ll = c;
41+
ll = s;
42+
ll = i;
43+
ll = l;
44+
ll = ll;
45+
46+
ll = uc;
47+
ll = us;
48+
ll = ui;
49+
ll = ul;
50+
ll = ull;
51+
}
52+
53+
void narrow_constant_to_signed_integer_is_ok_since_cxx20() {
54+
char c1 = -128;
55+
char c2 = 127;
56+
char c3 = -129;
57+
char c4 = 128;
58+
59+
short s1 = -32768;
60+
short s2 = 32767;
61+
short s3 = -32769;
62+
short s4 = 32768;
63+
}

clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/narrowing-conversions-equivalentbitwidth-option.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
// RUN: %check_clang_tidy -check-suffix=DEFAULT %s \
1+
// RUN: %check_clang_tidy -check-suffix=DEFAULT %s -std=c++17 \
22
// RUN: cppcoreguidelines-narrowing-conversions %t --
33

4-
// RUN: %check_clang_tidy -check-suffix=DISABLED %s \
4+
// RUN: %check_clang_tidy -check-suffix=DISABLED %s -std=c++17 \
55
// RUN: cppcoreguidelines-narrowing-conversions %t -- \
66
// RUN: -config='{CheckOptions: { \
77
// RUN: cppcoreguidelines-narrowing-conversions.WarnOnEquivalentBitWidth: 0}}'

clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/narrowing-conversions-ignoreconversionfromtypes-option.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
// RUN: %check_clang_tidy -check-suffix=DEFAULT %s \
1+
// RUN: %check_clang_tidy -check-suffix=DEFAULT %s -std=c++17 \
22
// RUN: cppcoreguidelines-narrowing-conversions %t --
33

4-
// RUN: %check_clang_tidy -check-suffix=IGNORED %s \
4+
// RUN: %check_clang_tidy -check-suffix=IGNORED %s -std=c++17 \
55
// RUN: cppcoreguidelines-narrowing-conversions %t -- \
66
// RUN: -config='{CheckOptions: { \
77
// RUN: cppcoreguidelines-narrowing-conversions.IgnoreConversionFromTypes: "global_size_t;nested_size_type;long" \

clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/narrowing-conversions-intemplates-option.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
// RUN: %check_clang_tidy -check-suffix=DEFAULT %s \
1+
// RUN: %check_clang_tidy -check-suffix=DEFAULT %s -std=c++17 \
22
// RUN: cppcoreguidelines-narrowing-conversions %t --
33

4-
// RUN: %check_clang_tidy -check-suffix=WARN %s \
4+
// RUN: %check_clang_tidy -check-suffix=WARN %s -std=c++17 \
55
// RUN: cppcoreguidelines-narrowing-conversions %t -- \
66
// RUN: -config='{CheckOptions: { \
77
// RUN: cppcoreguidelines-narrowing-conversions.WarnWithinTemplateInstantiation: 1 \

clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/narrowing-conversions-long-is-32bits.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
// RUN: %check_clang_tidy %s cppcoreguidelines-narrowing-conversions %t \
2-
// RUN: -- -- -target x86_64-unknown-linux -m32
1+
// RUN: %check_clang_tidy %s cppcoreguidelines-narrowing-conversions %t -std=c++17 \
2+
// RUN: -- -target x86_64-unknown-linux -m32
33

44
static_assert(sizeof(int) * 8 == 32, "int is 32-bits");
55
static_assert(sizeof(long) * 8 == 32, "long is 32-bits");

clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/narrowing-conversions-narrowinginteger-option.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
// RUN: %check_clang_tidy -check-suffix=DEFAULT %s \
1+
// RUN: %check_clang_tidy -check-suffix=DEFAULT %s -std=c++17 \
22
// RUN: cppcoreguidelines-narrowing-conversions %t -- \
33
// RUN: -config='{CheckOptions: {cppcoreguidelines-narrowing-conversions.WarnOnIntegerNarrowingConversion: true}}'
44

5-
// RUN: %check_clang_tidy -check-suffix=DISABLED %s \
5+
// RUN: %check_clang_tidy -check-suffix=DISABLED %s -std=c++17 \
66
// RUN: cppcoreguidelines-narrowing-conversions %t -- \
77
// RUN: -config='{CheckOptions: {cppcoreguidelines-narrowing-conversions.WarnOnIntegerNarrowingConversion: false}}'
88

0 commit comments

Comments
 (0)