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 @@ -49,6 +49,10 @@ bool isBitFieldWidth(const clang::ast_matchers::MatchFinder::MatchResult &Result, const IntegerLiteral &Literal) const; + bool isUserDefinedLiteral( + const clang::ast_matchers::MatchFinder::MatchResult &Result, + const clang::Expr &Literal) const; + template void checkBoundMatch(const ast_matchers::MatchFinder::MatchResult &Result, const char *BoundName) { @@ -72,6 +76,10 @@ if (isBitFieldWidth(Result, *MatchedLiteral)) return; + if (IgnoreUserDefinedLiterals && + isUserDefinedLiteral(Result, *MatchedLiteral)) + return; + const StringRef LiteralSourceText = Lexer::getSourceText( CharSourceRange::getTokenRange(MatchedLiteral->getSourceRange()), *Result.SourceManager, getLangOpts()); @@ -85,6 +93,7 @@ const bool IgnoreBitFieldsWidths; const bool IgnorePowersOf2IntegerValues; const bool IgnoreTypeAliases; + const bool IgnoreUserDefinedLiterals; const StringRef RawIgnoredIntegerValues; const StringRef RawIgnoredFloatingPointValues; 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 @@ -81,6 +81,8 @@ IgnorePowersOf2IntegerValues( Options.get("IgnorePowersOf2IntegerValues", false)), IgnoreTypeAliases(Options.get("IgnoreTypeAliases", false)), + IgnoreUserDefinedLiterals( + Options.get("IgnoreUserDefinedLiterals", false)), RawIgnoredIntegerValues( Options.get("IgnoredIntegerValues", DefaultIgnoredIntegerValues)), RawIgnoredFloatingPointValues(Options.get( @@ -130,6 +132,7 @@ Options.store(Opts, "IgnorePowersOf2IntegerValues", IgnorePowersOf2IntegerValues); Options.store(Opts, "IgnoreTypeAliases", IgnoreTypeAliases); + Options.store(Opts, "IgnoreUserDefinedLiterals", IgnoreUserDefinedLiterals); Options.store(Opts, "IgnoredIntegerValues", RawIgnoredIntegerValues); Options.store(Opts, "IgnoredFloatingPointValues", RawIgnoredFloatingPointValues); @@ -243,5 +246,14 @@ }); } +bool MagicNumbersCheck::isUserDefinedLiteral( + const clang::ast_matchers::MatchFinder::MatchResult &Result, + const clang::Expr &Literal) const { + DynTypedNodeList Parents = Result.Context->getParents(Literal); + if (Parents.empty()) + return false; + return Parents[0].get() != nullptr; +} + } // namespace tidy::readability } // namespace clang diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -211,6 +211,9 @@ behavior of using `i` as the prefix for enum tags, set the `EnumConstantPrefix` option to `i` instead of using `EnumConstantHungarianPrefix`. +- Added support to optionally ignore user-defined literals in + :doc:`readability-magic-numbers`. + - Fixed a false positive in :doc:`readability-container-size-empty ` check when comparing ``std::array`` objects to default constructed ones. The behavior for this and diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability/magic-numbers.rst b/clang-tools-extra/docs/clang-tidy/checks/readability/magic-numbers.rst --- a/clang-tools-extra/docs/clang-tidy/checks/readability/magic-numbers.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/readability/magic-numbers.rst @@ -57,7 +57,7 @@ const size_t NUMBER_OF_ELEMENTS = 30; using containerType = CustomType; - + struct OtherType { containerType container; } @@ -144,3 +144,8 @@ Boolean value indicating whether to accept magic numbers in ``typedef`` or ``using`` declarations. Default value is `false`. + +.. option:: IgnoreUserDefinedLiterals + + Boolean value indicating whether to accept magic numbers in user-defined + literals. Default value is `false`. diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/magic-numbers-userliteral.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/magic-numbers-userliteral.cpp --- a/clang-tools-extra/test/clang-tidy/checkers/readability/magic-numbers-userliteral.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/readability/magic-numbers-userliteral.cpp @@ -1,10 +1,18 @@ -// RUN: %check_clang_tidy -std=c++14-or-later %s readability-magic-numbers %t -- +// RUN: %check_clang_tidy -check-suffixes=UDL-ALLOWED -std=c++14-or-later %s readability-magic-numbers %t \ +// RUN: -config='{CheckOptions: \ +// RUN: [{key: readability-magic-numbers.IgnoreUserDefinedLiterals, value: false}]}' \ +// RUN: -- +// RUN: %check_clang_tidy -check-suffixes=UDL-IGNORED -std=c++14-or-later %s readability-magic-numbers %t \ +// RUN: -config='{CheckOptions: \ +// RUN: [{key: readability-magic-numbers.IgnoreUserDefinedLiterals, value: true}]}' \ +// RUN: -- namespace std { class string {}; using size_t = decltype(sizeof(int)); string operator ""s(const char *, std::size_t); int operator "" s(unsigned long long); + float operator "" s(long double); } void UserDefinedLiteral() { @@ -12,5 +20,9 @@ "Hello World"s; const int i = 3600s; int j = 3600s; - // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: 3600s is a magic number; consider replacing it with a named constant [readability-magic-numbers] + // CHECK-MESSAGES-UDL-ALLOWED: :[[@LINE-1]]:11: warning: 3600s is a magic number; consider replacing it with a named constant [readability-magic-numbers] + // CHECK-MESSAGES-UDL-IGNORED-NOT: :[[@LINE-2]]:11: warning: 3600s is a magic number; consider replacing it with a named constant [readability-magic-numbers] + float k = 3600.0s; + // CHECK-MESSAGES-UDL-ALLOWED: :[[@LINE-1]]:13: warning: 3600.0s is a magic number; consider replacing it with a named constant [readability-magic-numbers] + // CHECK-MESSAGES-UDL-IGNORED-NOT: :[[@LINE-1]]:13: warning: 3600.0s is a magic number; consider replacing it with a named constant [readability-magic-numbers] }