Skip to content

Commit 6dcb100

Browse files
0x8000-0000AaronBallman
authored andcommitted
Optionally exclude bitfield definitions from magic numbers check
Adds the IgnoreBitFieldsWidths option to readability-magic-numbers.
1 parent c25de56 commit 6dcb100

File tree

6 files changed

+90
-8
lines changed

6 files changed

+90
-8
lines changed

clang-tools-extra/clang-tidy/readability/MagicNumbersCheck.cpp

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,20 +21,20 @@
2121
using namespace clang::ast_matchers;
2222
using namespace clang::ast_type_traits;
2323

24-
namespace {
24+
namespace clang {
2525

26-
bool isUsedToInitializeAConstant(const MatchFinder::MatchResult &Result,
27-
const DynTypedNode &Node) {
26+
static bool isUsedToInitializeAConstant(const MatchFinder::MatchResult &Result,
27+
const DynTypedNode &Node) {
2828

29-
const auto *AsDecl = Node.get<clang::DeclaratorDecl>();
29+
const auto *AsDecl = Node.get<DeclaratorDecl>();
3030
if (AsDecl) {
3131
if (AsDecl->getType().isConstQualified())
3232
return true;
3333

3434
return AsDecl->isImplicit();
3535
}
3636

37-
if (Node.get<clang::EnumConstantDecl>() != nullptr)
37+
if (Node.get<EnumConstantDecl>() != nullptr)
3838
return true;
3939

4040
return llvm::any_of(Result.Context->getParents(Node),
@@ -43,9 +43,18 @@ bool isUsedToInitializeAConstant(const MatchFinder::MatchResult &Result,
4343
});
4444
}
4545

46-
} // namespace
46+
static bool isUsedToDefineABitField(const MatchFinder::MatchResult &Result,
47+
const DynTypedNode &Node) {
48+
const auto *AsFieldDecl = Node.get<FieldDecl>();
49+
if (AsFieldDecl && AsFieldDecl->isBitField())
50+
return true;
51+
52+
return llvm::any_of(Result.Context->getParents(Node),
53+
[&Result](const DynTypedNode &Parent) {
54+
return isUsedToDefineABitField(Result, Parent);
55+
});
56+
}
4757

48-
namespace clang {
4958
namespace tidy {
5059
namespace readability {
5160

@@ -56,6 +65,7 @@ MagicNumbersCheck::MagicNumbersCheck(StringRef Name, ClangTidyContext *Context)
5665
: ClangTidyCheck(Name, Context),
5766
IgnoreAllFloatingPointValues(
5867
Options.get("IgnoreAllFloatingPointValues", false)),
68+
IgnoreBitFieldsWidths(Options.get("IgnoreBitFieldsWidths", true)),
5969
IgnorePowersOf2IntegerValues(
6070
Options.get("IgnorePowersOf2IntegerValues", false)) {
6171
// Process the set of ignored integer values.
@@ -165,6 +175,16 @@ bool MagicNumbersCheck::isSyntheticValue(const SourceManager *SourceManager,
165175
return BufferIdentifier.empty();
166176
}
167177

178+
bool MagicNumbersCheck::isBitFieldWidth(
179+
const clang::ast_matchers::MatchFinder::MatchResult &Result,
180+
const IntegerLiteral &Literal) const {
181+
return IgnoreBitFieldsWidths &&
182+
llvm::any_of(Result.Context->getParents(Literal),
183+
[&Result](const DynTypedNode &Parent) {
184+
return isUsedToDefineABitField(Result, Parent);
185+
});
186+
}
187+
168188
} // namespace readability
169189
} // namespace tidy
170190
} // namespace clang

clang-tools-extra/clang-tidy/readability/MagicNumbersCheck.h

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,17 @@ class MagicNumbersCheck : public ClangTidyCheck {
4040
const FloatingLiteral *) const {
4141
return false;
4242
}
43-
4443
bool isSyntheticValue(const clang::SourceManager *SourceManager,
4544
const IntegerLiteral *Literal) const;
4645

46+
bool isBitFieldWidth(const clang::ast_matchers::MatchFinder::MatchResult &,
47+
const FloatingLiteral &) const {
48+
return false;
49+
}
50+
51+
bool isBitFieldWidth(const clang::ast_matchers::MatchFinder::MatchResult &Result,
52+
const IntegerLiteral &Literal) const;
53+
4754
template <typename L>
4855
void checkBoundMatch(const ast_matchers::MatchFinder::MatchResult &Result,
4956
const char *BoundName) {
@@ -64,6 +71,9 @@ class MagicNumbersCheck : public ClangTidyCheck {
6471
if (isSyntheticValue(Result.SourceManager, MatchedLiteral))
6572
return;
6673

74+
if (isBitFieldWidth(Result, *MatchedLiteral))
75+
return;
76+
6777
const StringRef LiteralSourceText = Lexer::getSourceText(
6878
CharSourceRange::getTokenRange(MatchedLiteral->getSourceRange()),
6979
*Result.SourceManager, getLangOpts());
@@ -74,6 +84,7 @@ class MagicNumbersCheck : public ClangTidyCheck {
7484
}
7585

7686
const bool IgnoreAllFloatingPointValues;
87+
const bool IgnoreBitFieldsWidths;
7788
const bool IgnorePowersOf2IntegerValues;
7889

7990
constexpr static unsigned SensibleNumberOfMagicValueExceptions = 16;

clang-tools-extra/docs/ReleaseNotes.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,12 @@ Improvements to clang-tidy
173173
Finds classes, structs, and unions that contain redundant member
174174
access specifiers.
175175

176+
- Improved :doc:`readability-magic-numbers
177+
<clang-tidy/checks/readability-magic-numbers>` check.
178+
179+
The check now supports the ``IgnoreBitFieldsWidths`` option to suppress
180+
the warning for numbers used to specify bit field widths.
181+
176182
- New :doc:`readability-make-member-function-const
177183
<clang-tidy/checks/readability-make-member-function-const>` check.
178184

clang-tools-extra/docs/clang-tidy/checks/readability-magic-numbers.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,3 +111,8 @@ Options
111111
Boolean value indicating whether to accept all floating point values without
112112
warning. Default value is `false`.
113113

114+
.. option:: IgnoreBitFieldsWidths
115+
116+
Boolean value indicating whether to accept magic numbers as bit field widths
117+
without warning. This is useful for example for register definitions which
118+
are generated from hardware specifications. Default value is `true`.
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// RUN: %check_clang_tidy %s readability-magic-numbers %t \
2+
// RUN: -config='{CheckOptions: \
3+
// RUN: [{key: readability-magic-numbers.IgnoredIntegerValues, value: "1;2;10;100;"}]}' \
4+
// RUN: --
5+
6+
struct HardwareGateway {
7+
/*
8+
* The configuration suppresses the warnings for the bitfields...
9+
*/
10+
unsigned int Some: 5;
11+
unsigned int Bits: 7;
12+
unsigned int: 7;
13+
unsigned int: 0;
14+
unsigned int Rest: 13;
15+
16+
/*
17+
* ... but other fields trigger the warning.
18+
*/
19+
unsigned int Another[3];
20+
// CHECK-MESSAGES: :[[@LINE-1]]:25: warning: 3 is a magic number; consider replacing it with a named constant [readability-magic-numbers]
21+
};
22+

clang-tools-extra/test/clang-tidy/checkers/readability-magic-numbers.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// RUN: -config='{CheckOptions: \
33
// RUN: [{key: readability-magic-numbers.IgnoredIntegerValues, value: "0;1;2;10;100;"}, \
44
// RUN: {key: readability-magic-numbers.IgnoredFloatingPointValues, value: "3.14;2.71828;9.81;10000.0;101.0;0x1.2p3"}, \
5+
// RUN: {key: readability-magic-numbers.IgnoreBitFieldsWidths, value: 0}, \
56
// RUN: {key: readability-magic-numbers.IgnorePowersOf2IntegerValues, value: 1}]}' \
67
// RUN: --
78

@@ -79,6 +80,23 @@ int getAnswer() {
7980
// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: 3 is a magic number; consider replacing it with a named constant [readability-magic-numbers]
8081
}
8182

83+
struct HardwareGateway {
84+
unsigned int Some: 5;
85+
// CHECK-MESSAGES: :[[@LINE-1]]:23: warning: 5 is a magic number; consider replacing it with a named constant [readability-magic-numbers]
86+
unsigned int Bits: 7;
87+
// CHECK-MESSAGES: :[[@LINE-1]]:23: warning: 7 is a magic number; consider replacing it with a named constant [readability-magic-numbers]
88+
unsigned int: 6;
89+
// CHECK-MESSAGES: :[[@LINE-1]]:18: warning: 6 is a magic number; consider replacing it with a named constant [readability-magic-numbers]
90+
unsigned int Flag: 1; // no warning since this is suppressed by IgnoredIntegerValues rule
91+
unsigned int: 0; // no warning since this is suppressed by IgnoredIntegerValues rule
92+
unsigned int Rest: 13;
93+
// CHECK-MESSAGES: :[[@LINE-1]]:23: warning: 13 is a magic number; consider replacing it with a named constant [readability-magic-numbers]
94+
//
95+
unsigned int Another[3];
96+
// CHECK-MESSAGES: :[[@LINE-1]]:25: warning: 3 is a magic number; consider replacing it with a named constant [readability-magic-numbers]
97+
};
98+
99+
82100
/*
83101
* Clean code
84102
*/

0 commit comments

Comments
 (0)