Skip to content

Commit e45e091

Browse files
authored
[clang-tidy] swap cppcoreguidelines-narrowing-conversions and bugprone-narrowing-conversions (#120245)
According to #116591. > Coding guidelines should "cherry-pick" (and posddsibly configure/harden/make more strict) base checks. We should move narrowing conversion to bugprone and keep alias in cppcoreguidelines
1 parent ff29f38 commit e45e091

22 files changed

+289
-281
lines changed

clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
#include "../ClangTidy.h"
1010
#include "../ClangTidyModule.h"
1111
#include "../ClangTidyModuleRegistry.h"
12-
#include "../cppcoreguidelines/NarrowingConversionsCheck.h"
1312
#include "ArgumentCommentCheck.h"
1413
#include "AssertSideEffectCheck.h"
1514
#include "AssignmentInIfConditionCheck.h"
@@ -47,6 +46,7 @@
4746
#include "MultiLevelImplicitPointerConversionCheck.h"
4847
#include "MultipleNewInOneExpressionCheck.h"
4948
#include "MultipleStatementMacroCheck.h"
49+
#include "NarrowingConversionsCheck.h"
5050
#include "NoEscapeCheck.h"
5151
#include "NonZeroEnumToBoolConversionCheck.h"
5252
#include "NondeterministicPointerIterationOrderCheck.h"
@@ -183,7 +183,7 @@ class BugproneModule : public ClangTidyModule {
183183
"bugprone-pointer-arithmetic-on-polymorphic-object");
184184
CheckFactories.registerCheck<RedundantBranchConditionCheck>(
185185
"bugprone-redundant-branch-condition");
186-
CheckFactories.registerCheck<cppcoreguidelines::NarrowingConversionsCheck>(
186+
CheckFactories.registerCheck<NarrowingConversionsCheck>(
187187
"bugprone-narrowing-conversions");
188188
CheckFactories.registerCheck<NoEscapeCheck>("bugprone-no-escape");
189189
CheckFactories.registerCheck<NonZeroEnumToBoolConversionCheck>(

clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ add_clang_library(clangTidyBugproneModule STATIC
4242
MultiLevelImplicitPointerConversionCheck.cpp
4343
MultipleNewInOneExpressionCheck.cpp
4444
MultipleStatementMacroCheck.cpp
45+
NarrowingConversionsCheck.cpp
4546
NoEscapeCheck.cpp
4647
NonZeroEnumToBoolConversionCheck.cpp
4748
NondeterministicPointerIterationOrderCheck.cpp

clang-tools-extra/clang-tidy/cppcoreguidelines/NarrowingConversionsCheck.cpp renamed to clang-tools-extra/clang-tidy/bugprone/NarrowingConversionsCheck.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222

2323
using namespace clang::ast_matchers;
2424

25-
namespace clang::tidy::cppcoreguidelines {
25+
namespace clang::tidy::bugprone {
2626

2727
namespace {
2828

@@ -614,4 +614,4 @@ void NarrowingConversionsCheck::check(const MatchFinder::MatchResult &Result) {
614614
return handleImplicitCast(*Result.Context, *Cast);
615615
llvm_unreachable("must be binary operator or cast expression");
616616
}
617-
} // namespace clang::tidy::cppcoreguidelines
617+
} // namespace clang::tidy::bugprone

clang-tools-extra/clang-tidy/cppcoreguidelines/NarrowingConversionsCheck.h renamed to clang-tools-extra/clang-tidy/bugprone/NarrowingConversionsCheck.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,19 @@
66
//
77
//===----------------------------------------------------------------------===//
88

9-
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_NARROWING_CONVERSIONS_H
10-
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_NARROWING_CONVERSIONS_H
9+
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_NARROWING_CONVERSIONS_H
10+
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_NARROWING_CONVERSIONS_H
1111

1212
#include "../ClangTidyCheck.h"
1313

14-
namespace clang::tidy::cppcoreguidelines {
14+
namespace clang::tidy::bugprone {
1515

1616
/// Checks for narrowing conversions, e.g:
1717
/// int i = 0;
1818
/// i += 0.1;
1919
///
2020
/// For the user-facing documentation see:
21-
/// http://clang.llvm.org/extra/clang-tidy/checks/cppcoreguidelines/narrowing-conversions.html
21+
/// http://clang.llvm.org/extra/clang-tidy/checks/bugprone/narrowing-conversions.html
2222
class NarrowingConversionsCheck : public ClangTidyCheck {
2323
public:
2424
NarrowingConversionsCheck(StringRef Name, ClangTidyContext *Context);
@@ -104,6 +104,6 @@ class NarrowingConversionsCheck : public ClangTidyCheck {
104104
const bool PedanticMode;
105105
};
106106

107-
} // namespace clang::tidy::cppcoreguidelines
107+
} // namespace clang::tidy::bugprone
108108

109-
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_NARROWING_CONVERSIONS_H
109+
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_NARROWING_CONVERSIONS_H

clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ add_clang_library(clangTidyCppCoreGuidelinesModule STATIC
1616
MacroUsageCheck.cpp
1717
MisleadingCaptureDefaultByValueCheck.cpp
1818
MissingStdForwardCheck.cpp
19-
NarrowingConversionsCheck.cpp
2019
NoMallocCheck.cpp
2120
NoSuspendWithLockCheck.cpp
2221
OwningMemoryCheck.cpp

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "../ClangTidy.h"
1010
#include "../ClangTidyModule.h"
1111
#include "../ClangTidyModuleRegistry.h"
12+
#include "../bugprone/NarrowingConversionsCheck.h"
1213
#include "../misc/NonPrivateMemberVariablesInClassesCheck.h"
1314
#include "../misc/UnconventionalAssignOperatorCheck.h"
1415
#include "../modernize/AvoidCArraysCheck.h"
@@ -30,7 +31,6 @@
3031
#include "MacroUsageCheck.h"
3132
#include "MisleadingCaptureDefaultByValueCheck.h"
3233
#include "MissingStdForwardCheck.h"
33-
#include "NarrowingConversionsCheck.h"
3434
#include "NoMallocCheck.h"
3535
#include "NoSuspendWithLockCheck.h"
3636
#include "OwningMemoryCheck.h"
@@ -87,7 +87,7 @@ class CppCoreGuidelinesModule : public ClangTidyModule {
8787
"cppcoreguidelines-misleading-capture-default-by-value");
8888
CheckFactories.registerCheck<MissingStdForwardCheck>(
8989
"cppcoreguidelines-missing-std-forward");
90-
CheckFactories.registerCheck<NarrowingConversionsCheck>(
90+
CheckFactories.registerCheck<bugprone::NarrowingConversionsCheck>(
9191
"cppcoreguidelines-narrowing-conversions");
9292
CheckFactories.registerCheck<NoMallocCheck>("cppcoreguidelines-no-malloc");
9393
CheckFactories.registerCheck<NoSuspendWithLockCheck>(

clang-tools-extra/docs/ReleaseNotes.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -361,6 +361,13 @@ Removed checks
361361
Miscellaneous
362362
^^^^^^^^^^^^^
363363

364+
- The :doc:`bugprone-narrowing-conversions <clang-tidy/checks/bugprone/narrowing-conversions>`
365+
check is no longer an alias of :doc:`cppcoreguidelines-narrowing-conversions
366+
<clang-tidy/checks/cppcoreguidelines/narrowing-conversions>`. Instead,
367+
:doc:`cppcoreguidelines-narrowing-conversions
368+
<clang-tidy/checks/cppcoreguidelines/narrowing-conversions>` is now an alias
369+
of :doc:`bugprone-narrowing-conversions <clang-tidy/checks/bugprone/narrowing-conversions>`.
370+
364371
Improvements to include-fixer
365372
-----------------------------
366373

Lines changed: 121 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,126 @@
11
.. title:: clang-tidy - bugprone-narrowing-conversions
2-
.. meta::
3-
:http-equiv=refresh: 5;URL=../cppcoreguidelines/narrowing-conversions.html
42

53
bugprone-narrowing-conversions
64
==============================
75

8-
The bugprone-narrowing-conversions check is an alias, please see
9-
:doc:`cppcoreguidelines-narrowing-conversions <../cppcoreguidelines/narrowing-conversions>`
10-
for more information.
6+
`cppcoreguidelines-narrowing-conversions` redirects here as an alias for this check.
7+
8+
Checks for silent narrowing conversions, e.g: ``int i = 0; i += 0.1;``. While
9+
the issue is obvious in this former example, it might not be so in the
10+
following: ``void MyClass::f(double d) { int_member_ += d; }``.
11+
12+
We flag narrowing conversions from:
13+
- an integer to a narrower integer (e.g. ``char`` to ``unsigned char``)
14+
if WarnOnIntegerNarrowingConversion Option is set,
15+
- an integer to a narrower floating-point (e.g. ``uint64_t`` to ``float``)
16+
if WarnOnIntegerToFloatingPointNarrowingConversion Option is set,
17+
- a floating-point to an integer (e.g. ``double`` to ``int``),
18+
- a floating-point to a narrower floating-point (e.g. ``double`` to ``float``)
19+
if WarnOnFloatingPointNarrowingConversion Option is set.
20+
21+
This check will flag:
22+
- All narrowing conversions that are not marked by an explicit cast (c-style or
23+
``static_cast``). For example: ``int i = 0; i += 0.1;``,
24+
``void f(int); f(0.1);``,
25+
- All applications of binary operators with a narrowing conversions.
26+
For example: ``int i; i+= 0.1;``.
27+
28+
Arithmetic with smaller integer types than ``int`` trigger implicit conversions,
29+
as explained under `"Integral Promotion" on cppreference.com
30+
<https://en.cppreference.com/w/cpp/language/implicit_conversion>`_.
31+
This check diagnoses more instances of narrowing than the compiler warning
32+
`-Wconversion` does. The example below demonstrates this behavior.
33+
34+
.. code-block:: c++
35+
36+
// The following function definition demonstrates usage of arithmetic with
37+
// integer types smaller than `int` and how the narrowing conversion happens
38+
// implicitly.
39+
void computation(short argument1, short argument2) {
40+
// Arithmetic written by humans:
41+
short result = argument1 + argument2;
42+
// Arithmetic actually performed by C++:
43+
short result = static_cast<short>(static_cast<int>(argument1) + static_cast<int>(argument2));
44+
}
45+
46+
void recommended_resolution(short argument1, short argument2) {
47+
short result = argument1 + argument2;
48+
// ^ warning: narrowing conversion from 'int' to signed type 'short' is implementation-defined
49+
50+
// The cppcoreguidelines recommend to resolve this issue by using the GSL
51+
// in one of two ways. Either by a cast that throws if a loss of precision
52+
// would occur.
53+
short result = gsl::narrow<short>(argument1 + argument2);
54+
// Or it can be resolved without checking the result risking invalid results.
55+
short result = gsl::narrow_cast<short>(argument1 + argument2);
56+
57+
// A classical `static_cast` will silence the warning as well if the GSL
58+
// is not available.
59+
short result = static_cast<short>(argument1 + argument2);
60+
}
61+
62+
Options
63+
-------
64+
65+
.. option:: WarnOnIntegerNarrowingConversion
66+
67+
When `true`, the check will warn on narrowing integer conversion
68+
(e.g. ``int`` to ``size_t``). `true` by default.
69+
70+
.. option:: WarnOnIntegerToFloatingPointNarrowingConversion
71+
72+
When `true`, the check will warn on narrowing integer to floating-point
73+
conversion (e.g. ``size_t`` to ``double``). `true` by default.
74+
75+
.. option:: WarnOnFloatingPointNarrowingConversion
76+
77+
When `true`, the check will warn on narrowing floating point conversion
78+
(e.g. ``double`` to ``float``). `true` by default.
79+
80+
.. option:: WarnWithinTemplateInstantiation
81+
82+
When `true`, the check will warn on narrowing conversions within template
83+
instantiations. `false` by default.
84+
85+
.. option:: WarnOnEquivalentBitWidth
86+
87+
When `true`, the check will warn on narrowing conversions that arise from
88+
casting between types of equivalent bit width. (e.g.
89+
`int n = uint(0);` or `long long n = double(0);`) `true` by default.
90+
91+
.. option:: IgnoreConversionFromTypes
92+
93+
Narrowing conversions from any type in this semicolon-separated list will be
94+
ignored. This may be useful to weed out commonly occurring, but less commonly
95+
problematic assignments such as `int n = std::vector<char>().size();` or
96+
`int n = std::difference(it1, it2);`. The default list is empty, but one
97+
suggested list for a legacy codebase would be
98+
`size_t;ptrdiff_t;size_type;difference_type`.
99+
100+
.. option:: PedanticMode
101+
102+
When `true`, the check will warn on assigning a floating point constant
103+
to an integer value even if the floating point value is exactly
104+
representable in the destination type (e.g. ``int i = 1.0;``).
105+
`false` by default.
106+
107+
FAQ
108+
---
109+
110+
- What does "narrowing conversion from 'int' to 'float'" mean?
111+
112+
An IEEE754 Floating Point number can represent all integer values in the range
113+
[-2^PrecisionBits, 2^PrecisionBits] where PrecisionBits is the number of bits in
114+
the mantissa.
115+
116+
For ``float`` this would be [-2^23, 2^23], where ``int`` can represent values in
117+
the range [-2^31, 2^31-1].
118+
119+
- What does "implementation-defined" mean?
120+
121+
You may have encountered messages like "narrowing conversion from 'unsigned int'
122+
to signed type 'int' is implementation-defined".
123+
The C/C++ standard does not mandate two's complement for signed integers, and so
124+
the compiler is free to define what the semantics are for converting an unsigned
125+
integer to signed integer. Clang's implementation uses the two's complement
126+
format.
Lines changed: 6 additions & 121 deletions
Original file line numberDiff line numberDiff line change
@@ -1,129 +1,14 @@
11
.. title:: clang-tidy - cppcoreguidelines-narrowing-conversions
2+
.. meta::
3+
:http-equiv=refresh: 5;URL=../bugprone/narrowing-conversions.html
24

35
cppcoreguidelines-narrowing-conversions
46
=======================================
57

6-
Checks for silent narrowing conversions, e.g: ``int i = 0; i += 0.1;``. While
7-
the issue is obvious in this former example, it might not be so in the
8-
following: ``void MyClass::f(double d) { int_member_ += d; }``.
9-
10-
This check implements `ES.46
8+
This check implements part of `ES.46
119
<https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#es46-avoid-lossy-narrowing-truncating-arithmetic-conversions>`_
1210
from the C++ Core Guidelines.
1311

14-
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``)
16-
if WarnOnIntegerNarrowingConversion Option is set,
17-
- an integer to a narrower floating-point (e.g. ``uint64_t`` to ``float``)
18-
if WarnOnIntegerToFloatingPointNarrowingConversion Option is set,
19-
- a floating-point to an integer (e.g. ``double`` to ``int``),
20-
- a floating-point to a narrower floating-point (e.g. ``double`` to ``float``)
21-
if WarnOnFloatingPointNarrowingConversion Option is set.
22-
23-
This check will flag:
24-
- All narrowing conversions that are not marked by an explicit cast (c-style or
25-
``static_cast``). For example: ``int i = 0; i += 0.1;``,
26-
``void f(int); f(0.1);``,
27-
- All applications of binary operators with a narrowing conversions.
28-
For example: ``int i; i+= 0.1;``.
29-
30-
Arithmetic with smaller integer types than ``int`` trigger implicit conversions,
31-
as explained under `"Integral Promotion" on cppreference.com
32-
<https://en.cppreference.com/w/cpp/language/implicit_conversion>`_.
33-
This check diagnoses more instances of narrowing than the compiler warning
34-
`-Wconversion` does. The example below demonstrates this behavior.
35-
36-
.. code-block:: c++
37-
38-
// The following function definition demonstrates usage of arithmetic with
39-
// integer types smaller than `int` and how the narrowing conversion happens
40-
// implicitly.
41-
void computation(short argument1, short argument2) {
42-
// Arithmetic written by humans:
43-
short result = argument1 + argument2;
44-
// Arithmetic actually performed by C++:
45-
short result = static_cast<short>(static_cast<int>(argument1) + static_cast<int>(argument2));
46-
}
47-
48-
void recommended_resolution(short argument1, short argument2) {
49-
short result = argument1 + argument2;
50-
// ^ warning: narrowing conversion from 'int' to signed type 'short' is implementation-defined
51-
52-
// The cppcoreguidelines recommend to resolve this issue by using the GSL
53-
// in one of two ways. Either by a cast that throws if a loss of precision
54-
// would occur.
55-
short result = gsl::narrow<short>(argument1 + argument2);
56-
// Or it can be resolved without checking the result risking invalid results.
57-
short result = gsl::narrow_cast<short>(argument1 + argument2);
58-
59-
// A classical `static_cast` will silence the warning as well if the GSL
60-
// is not available.
61-
short result = static_cast<short>(argument1 + argument2);
62-
}
63-
64-
65-
Options
66-
-------
67-
68-
.. option:: WarnOnIntegerNarrowingConversion
69-
70-
When `true`, the check will warn on narrowing integer conversion
71-
(e.g. ``int`` to ``size_t``). `true` by default.
72-
73-
.. option:: WarnOnIntegerToFloatingPointNarrowingConversion
74-
75-
When `true`, the check will warn on narrowing integer to floating-point
76-
conversion (e.g. ``size_t`` to ``double``). `true` by default.
77-
78-
.. option:: WarnOnFloatingPointNarrowingConversion
79-
80-
When `true`, the check will warn on narrowing floating point conversion
81-
(e.g. ``double`` to ``float``). `true` by default.
82-
83-
.. option:: WarnWithinTemplateInstantiation
84-
85-
When `true`, the check will warn on narrowing conversions within template
86-
instantiations. `false` by default.
87-
88-
.. option:: WarnOnEquivalentBitWidth
89-
90-
When `true`, the check will warn on narrowing conversions that arise from
91-
casting between types of equivalent bit width. (e.g.
92-
`int n = uint(0);` or `long long n = double(0);`) `true` by default.
93-
94-
.. option:: IgnoreConversionFromTypes
95-
96-
Narrowing conversions from any type in this semicolon-separated list will be
97-
ignored. This may be useful to weed out commonly occurring, but less commonly
98-
problematic assignments such as `int n = std::vector<char>().size();` or
99-
`int n = std::difference(it1, it2);`. The default list is empty, but one
100-
suggested list for a legacy codebase would be
101-
`size_t;ptrdiff_t;size_type;difference_type`.
102-
103-
.. option:: PedanticMode
104-
105-
When `true`, the check will warn on assigning a floating point constant
106-
to an integer value even if the floating point value is exactly
107-
representable in the destination type (e.g. ``int i = 1.0;``).
108-
`false` by default.
109-
110-
FAQ
111-
---
112-
113-
- What does "narrowing conversion from 'int' to 'float'" mean?
114-
115-
An IEEE754 Floating Point number can represent all integer values in the range
116-
[-2^PrecisionBits, 2^PrecisionBits] where PrecisionBits is the number of bits in
117-
the mantissa.
118-
119-
For ``float`` this would be [-2^23, 2^23], where ``int`` can represent values in
120-
the range [-2^31, 2^31-1].
121-
122-
- What does "implementation-defined" mean?
123-
124-
You may have encountered messages like "narrowing conversion from 'unsigned int'
125-
to signed type 'int' is implementation-defined".
126-
The C/C++ standard does not mandate two's complement for signed integers, and so
127-
the compiler is free to define what the semantics are for converting an unsigned
128-
integer to signed integer. Clang's implementation uses the two's complement
129-
format.
12+
The cppcoreguidelines-narrowing-conversions check is an alias, please see
13+
:doc:`bugprone-narrowing-conversions <../bugprone/narrowing-conversions>`
14+
for more information.

0 commit comments

Comments
 (0)