diff --git a/clang-tools-extra/clang-tidy/readability/MagicNumbersCheck.h b/clang-tools-extra/clang-tidy/readability/MagicNumbersCheck.h --- a/clang-tools-extra/clang-tidy/readability/MagicNumbersCheck.h +++ b/clang-tools-extra/clang-tidy/readability/MagicNumbersCheck.h @@ -40,10 +40,17 @@ const FloatingLiteral *) const { return false; } - bool isSyntheticValue(const clang::SourceManager *SourceManager, const IntegerLiteral *Literal) const; + bool isBitFieldWidth(const clang::ast_matchers::MatchFinder::MatchResult &, + const FloatingLiteral &) const { + return false; + } + + bool isBitFieldWidth(const clang::ast_matchers::MatchFinder::MatchResult &Result, + const IntegerLiteral &Literal) const; + template void checkBoundMatch(const ast_matchers::MatchFinder::MatchResult &Result, const char *BoundName) { @@ -64,6 +71,9 @@ if (isSyntheticValue(Result.SourceManager, MatchedLiteral)) return; + if (isBitFieldWidth(Result, *MatchedLiteral)) + return; + const StringRef LiteralSourceText = Lexer::getSourceText( CharSourceRange::getTokenRange(MatchedLiteral->getSourceRange()), *Result.SourceManager, getLangOpts()); @@ -74,6 +84,7 @@ } const bool IgnoreAllFloatingPointValues; + const bool IgnoreBitFieldsWidths; const bool IgnorePowersOf2IntegerValues; constexpr static unsigned SensibleNumberOfMagicValueExceptions = 16; diff --git a/clang-tools-extra/clang-tidy/readability/MagicNumbersCheck.cpp b/clang-tools-extra/clang-tidy/readability/MagicNumbersCheck.cpp --- a/clang-tools-extra/clang-tidy/readability/MagicNumbersCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/MagicNumbersCheck.cpp @@ -43,6 +43,19 @@ }); } +bool isUsedToDefineABitField(const MatchFinder::MatchResult &Result, + const DynTypedNode &Node) { + + const auto *AsFieldDecl = Node.get(); + if (AsFieldDecl && AsFieldDecl->isBitField()) + return true; + + return llvm::any_of(Result.Context->getParents(Node), + [&Result](const DynTypedNode &Parent) { + return isUsedToDefineABitField(Result, Parent); + }); +} + } // namespace namespace clang { @@ -56,6 +69,7 @@ : ClangTidyCheck(Name, Context), IgnoreAllFloatingPointValues( Options.get("IgnoreAllFloatingPointValues", false)), + IgnoreBitFieldsWidths(Options.get("IgnoreBitFieldsWidths", false)), IgnorePowersOf2IntegerValues( Options.get("IgnorePowersOf2IntegerValues", false)) { // Process the set of ignored integer values. @@ -165,6 +179,17 @@ return BufferIdentifier.empty(); } +bool MagicNumbersCheck::isBitFieldWidth( + const clang::ast_matchers::MatchFinder::MatchResult &Result, + const IntegerLiteral &Literal) const { + + return IgnoreBitFieldsWidths && + llvm::any_of(Result.Context->getParents(Literal), + [&Result](const DynTypedNode &Parent) { + return isUsedToDefineABitField(Result, Parent); + }); +} + } // namespace readability } // namespace tidy } // namespace clang diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability-magic-numbers-bitfields.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability-magic-numbers-bitfields.cpp new file mode 100644 --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/checkers/readability-magic-numbers-bitfields.cpp @@ -0,0 +1,23 @@ +// RUN: %check_clang_tidy %s readability-magic-numbers %t \ +// RUN: -config='{CheckOptions: \ +// RUN: [{key: readability-magic-numbers.IgnoredIntegerValues, value: "0;1;2;10;100;"}, \ +// RUN: {key: readability-magic-numbers.IgnoreBitFieldsWidths, value: 1}]}' \ +// RUN: -- + +struct HardwareGateway { + unsigned int Some: 5; + unsigned int Bits: 7; + unsigned int: 7; + unsigned int Rest: 13; +}; + +unsigned int TestBitFields() { + HardwareGateway SomeRegister{}; + + SomeRegister.Some = 1; + SomeRegister.Rest = 22; + // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: 22 is a magic number; consider replacing it with a named constant [readability-magic-numbers] + + return SomeRegister.Bits; +} + diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability-magic-numbers.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability-magic-numbers.cpp --- a/clang-tools-extra/test/clang-tidy/checkers/readability-magic-numbers.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/readability-magic-numbers.cpp @@ -79,6 +79,26 @@ // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: 3 is a magic number; consider replacing it with a named constant [readability-magic-numbers] } +struct HardwareGateway { + unsigned int Some: 5; + // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: 5 is a magic number; consider replacing it with a named constant [readability-magic-numbers] + unsigned int Bits: 7; + // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: 7 is a magic number; consider replacing it with a named constant [readability-magic-numbers] + unsigned int: 7; + // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: 7 is a magic number; consider replacing it with a named constant [readability-magic-numbers] + unsigned int Rest: 13; + // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: 13 is a magic number; consider replacing it with a named constant [readability-magic-numbers] +}; + +unsigned int TestBitFields() { + HardwareGateway SomeRegister{}; + + SomeRegister.Some = 1; + SomeRegister.Rest = 2; + + return SomeRegister.Bits; +} + /* * Clean code */