https://github.com/Floweynt created https://github.com/llvm/llvm-project/pull/216516
Some functions (e.g. `strtoul`) take a base argument, for which common choices of base (10, 16, 8) should not flag as a magic value. The option for exclusion is enabled by default, since it seems sensible to not generate noise when calling string-to-int conversions with very commonly used bases. >From c1019e996d44fa9b3af40d4449998134fa0bf13f Mon Sep 17 00:00:00 2001 From: Floweynt <[email protected]> Date: Sat, 15 Aug 2026 10:08:14 -0500 Subject: [PATCH] [clang-tidy] Exclude well-known conversion bases from readability-magic-numbers Some functions (e.g. `strtoul`) take a base argument, for which common choices of base (10, 16, 8) should not flag as a magic value. --- .../readability/MagicNumbersCheck.cpp | 100 +++++++++++++ .../readability/MagicNumbersCheck.h | 8 + clang-tools-extra/docs/ReleaseNotes.md | 5 + .../checks/readability/magic-numbers.rst | 7 + .../checkers/Inputs/Headers/std/charconv | 51 +++++++ .../checkers/Inputs/Headers/std/cstdlib | 36 +++++ .../checkers/Inputs/Headers/std/iomanip | 21 +++ .../checkers/Inputs/Headers/std/stdlib.h | 12 ++ .../checkers/Inputs/Headers/std/string | 14 ++ .../magic-numbers-well-known-args.cpp | 137 ++++++++++++++++++ 10 files changed, 391 insertions(+) create mode 100644 clang-tools-extra/test/clang-tidy/checkers/Inputs/Headers/std/charconv create mode 100644 clang-tools-extra/test/clang-tidy/checkers/Inputs/Headers/std/cstdlib create mode 100644 clang-tools-extra/test/clang-tidy/checkers/Inputs/Headers/std/iomanip create mode 100644 clang-tools-extra/test/clang-tidy/checkers/readability/magic-numbers-well-known-args.cpp diff --git a/clang-tools-extra/clang-tidy/readability/MagicNumbersCheck.cpp b/clang-tools-extra/clang-tidy/readability/MagicNumbersCheck.cpp index c0b11b7fc1afb..ac759db58340c 100644 --- a/clang-tools-extra/clang-tidy/readability/MagicNumbersCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/MagicNumbersCheck.cpp @@ -23,6 +23,41 @@ using namespace clang::ast_matchers; namespace clang { +namespace { + +struct WellKnownArg { + ArrayRef<uint64_t> AcceptedValues; + ArrayRef<StringRef> FunctionNames; + unsigned ArgIndex; +}; + +constexpr uint64_t CommonBases[] = {8, 10, 16}; + +constexpr StringRef BaseAtArg2[] = { + "strtol", "strtoll", "strtoul", "strtoull", "strtoimax", + "strtoumax", "wcstol", "wcstoll", "wcstoul", "wcstoull", + "wcstoimax", "wcstoumax", "strtol_l", "strtoll_l", "strtoul_l", + "strtoull_l", "wcstol_l", "wcstoll_l", "wcstoul_l", "wcstoull_l", + "stoi", "stol", "stoul", "stoll", "stoull", +}; + +constexpr StringRef BaseAtArg3[] = { + "from_chars", + "to_chars", +}; + +constexpr StringRef BaseAtArg0[] = { + "setbase", +}; + +constexpr WellKnownArg WellKnownArgs[] = { + {CommonBases, BaseAtArg2, 2}, + {CommonBases, BaseAtArg3, 3}, + {CommonBases, BaseAtArg0, 0}, +}; + +} // namespace + static bool isUsedToInitializeAConstant(const MatchFinder::MatchResult &Result, const DynTypedNode &Node) { const auto *AsDecl = Node.get<DeclaratorDecl>(); @@ -65,6 +100,47 @@ static bool isUsedToDefineABitField(const MatchFinder::MatchResult &Result, }); } +static bool isUsedAsAConversionBase(const MatchFinder::MatchResult &Result, + const DynTypedNode &Node, + const Expr &Literal, uint64_t Base) { + const auto *Call = Node.get<CallExpr>(); + if (!Call) { + if (!isa_and_nonnull<ImplicitCastExpr, ParenExpr, FullExpr>( + Node.get<Expr>())) + return false; + + return llvm::any_of(Result.Context->getParents(Node), + [&Result, &Literal, Base](const DynTypedNode &Parent) { + return isUsedAsAConversionBase(Result, Parent, + Literal, Base); + }); + } + + unsigned ArgIndex = 0; + for (; ArgIndex < Call->getNumArgs(); ++ArgIndex) + if (Call->getArg(ArgIndex)->IgnoreParenImpCasts() == &Literal) + break; + + if (ArgIndex == Call->getNumArgs()) + return false; + + const FunctionDecl *Callee = Call->getDirectCallee(); + if (!Callee || !Callee->getIdentifier()) + return false; + + if (!Callee->getDeclContext()->getRedeclContext()->isTranslationUnit() && + !Callee->isInStdNamespace()) + return false; + + const StringRef Name = Callee->getName(); + for (const WellKnownArg &Entry : WellKnownArgs) + if (Entry.ArgIndex == ArgIndex && + llvm::is_contained(Entry.FunctionNames, Name)) + return llvm::is_contained(Entry.AcceptedValues, Base); + + return false; +} + namespace tidy::readability { const char DefaultIgnoredIntegerValues[] = "1;2;3;4;"; @@ -80,6 +156,8 @@ MagicNumbersCheck::MagicNumbersCheck(StringRef Name, ClangTidyContext *Context) IgnoreTypeAliases(Options.get("IgnoreTypeAliases", false)), IgnoreUserDefinedLiterals( Options.get("IgnoreUserDefinedLiterals", false)), + IgnoreWellKnownFunctionArgs( + Options.get("IgnoreWellKnownFunctionArgs", true)), RawIgnoredIntegerValues( Options.get("IgnoredIntegerValues", DefaultIgnoredIntegerValues)), RawIgnoredFloatingPointValues(Options.get( @@ -130,6 +208,8 @@ void MagicNumbersCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { IgnorePowersOf2IntegerValues); Options.store(Opts, "IgnoreTypeAliases", IgnoreTypeAliases); Options.store(Opts, "IgnoreUserDefinedLiterals", IgnoreUserDefinedLiterals); + Options.store(Opts, "IgnoreWellKnownFunctionArgs", + IgnoreWellKnownFunctionArgs); Options.store(Opts, "IgnoredIntegerValues", RawIgnoredIntegerValues); Options.store(Opts, "IgnoredFloatingPointValues", RawIgnoredFloatingPointValues); @@ -251,5 +331,25 @@ bool MagicNumbersCheck::isUserDefinedLiteral( return Parents[0].get<UserDefinedLiteral>() != nullptr; } +bool MagicNumbersCheck::isWellKnownFunctionArg( + const ast_matchers::MatchFinder::MatchResult &Result, + const Expr &Literal) const { + if (!IgnoreWellKnownFunctionArgs) + return false; + + const std::optional<llvm::APSInt> Value = + Literal.getIntegerConstantExpr(*Result.Context); + if (!Value || Value->isNegative()) + return false; + + const uint64_t Base = Value->getZExtValue(); + + return llvm::any_of(Result.Context->getParents(Literal), + [&Result, &Literal, Base](const DynTypedNode &Parent) { + return isUsedAsAConversionBase(Result, Parent, Literal, + Base); + }); +} + } // namespace tidy::readability } // namespace clang diff --git a/clang-tools-extra/clang-tidy/readability/MagicNumbersCheck.h b/clang-tools-extra/clang-tidy/readability/MagicNumbersCheck.h index ca64880c030cf..53270d7d9ac51 100644 --- a/clang-tools-extra/clang-tidy/readability/MagicNumbersCheck.h +++ b/clang-tools-extra/clang-tidy/readability/MagicNumbersCheck.h @@ -52,6 +52,10 @@ class MagicNumbersCheck : public ClangTidyCheck { isUserDefinedLiteral(const ast_matchers::MatchFinder::MatchResult &Result, const Expr &Literal) const; + bool + isWellKnownFunctionArg(const ast_matchers::MatchFinder::MatchResult &Result, + const Expr &Literal) const; + template <typename L> void checkBoundMatch(const ast_matchers::MatchFinder::MatchResult &Result, const char *BoundName) { @@ -79,6 +83,9 @@ class MagicNumbersCheck : public ClangTidyCheck { isUserDefinedLiteral(Result, *MatchedLiteral)) return; + if (isWellKnownFunctionArg(Result, *MatchedLiteral)) + return; + const StringRef LiteralSourceText = Lexer::getSourceText( CharSourceRange::getTokenRange(MatchedLiteral->getSourceRange()), *Result.SourceManager, getLangOpts()); @@ -93,6 +100,7 @@ class MagicNumbersCheck : public ClangTidyCheck { const bool IgnorePowersOf2IntegerValues; const bool IgnoreTypeAliases; const bool IgnoreUserDefinedLiterals; + const bool IgnoreWellKnownFunctionArgs; const StringRef RawIgnoredIntegerValues; const StringRef RawIgnoredFloatingPointValues; diff --git a/clang-tools-extra/docs/ReleaseNotes.md b/clang-tools-extra/docs/ReleaseNotes.md index e81a4b7139106..13a180522dcc3 100644 --- a/clang-tools-extra/docs/ReleaseNotes.md +++ b/clang-tools-extra/docs/ReleaseNotes.md @@ -163,6 +163,11 @@ infrastructure are described first, followed by tool-specific sections. - Fixed {option}`DefaultHungarianPrefix` being incorrectly diagnosed as an invalid option. +- Improved {doc}`readability-magic-numbers + <clang-tidy/checks/readability/magic-numbers>` check by adding + {option}`IgnoreWellKnownFunctionArgs` to ignore common base arguments passed + into well-known base conversion functions. This option is enabled by default. + - Improved {doc}`readability-named-parameter <clang-tidy/checks/readability/named-parameter>` check by ignoring standard tag types (e.g. `std::in_place_t`, `std::allocator_arg_t`, 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 index 5e4af5dabc5f2..838364baff12c 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/readability/magic-numbers.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/readability/magic-numbers.rst @@ -148,3 +148,10 @@ Options Boolean value indicating whether to accept magic numbers in user-defined literals. Default value is `false`. + +.. option:: IgnoreWellKnownFunctionArgs + + Boolean value indicating whether to accept common conversion bases (``8``, + ``10``, ``16``) passed to well-known conversion functions such as + ``strtol``, ``std::stoi``, ``std::from_chars`` and ``std::setbase``. + Default value is `true`. diff --git a/clang-tools-extra/test/clang-tidy/checkers/Inputs/Headers/std/charconv b/clang-tools-extra/test/clang-tidy/checkers/Inputs/Headers/std/charconv new file mode 100644 index 0000000000000..8608b76b6f6f6 --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/checkers/Inputs/Headers/std/charconv @@ -0,0 +1,51 @@ +//===--- charconv - Stub header for tests -----------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _CHARCONV_ +#define _CHARCONV_ + +namespace std { + +enum class chars_format { + scientific = 1, + fixed = 2, + hex = 4, + general = fixed | scientific +}; + +enum class errc { }; + +struct from_chars_result { + const char *ptr; + errc ec; +}; + +from_chars_result from_chars(const char *First, const char *Last, int &Value, + int Base = 10); +from_chars_result from_chars(const char *First, const char *Last, long &Value, + int Base = 10); +from_chars_result from_chars(const char *First, const char *Last, + unsigned &Value, int Base = 10); +from_chars_result from_chars(const char *First, const char *Last, double &Value, + chars_format Fmt = chars_format::general); + +struct to_chars_result { + char *ptr; + errc ec; +}; + +to_chars_result to_chars(char *First, char *Last, int Value, int Base = 10); +to_chars_result to_chars(char *First, char *Last, long Value, int Base = 10); +to_chars_result to_chars(char *First, char *Last, unsigned Value, + int Base = 10); +to_chars_result to_chars(char *First, char *Last, double Value, + chars_format Fmt); + +} // namespace std + +#endif diff --git a/clang-tools-extra/test/clang-tidy/checkers/Inputs/Headers/std/cstdlib b/clang-tools-extra/test/clang-tidy/checkers/Inputs/Headers/std/cstdlib new file mode 100644 index 0000000000000..3e60635852433 --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/checkers/Inputs/Headers/std/cstdlib @@ -0,0 +1,36 @@ +//===--- cstdlib - Stub header for tests ------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _CSTDLIB_ +#define _CSTDLIB_ + +#include <stdlib.h> + +long wcstol(const wchar_t *Str, wchar_t **End, int Base); +long long wcstoll(const wchar_t *Str, wchar_t **End, int Base); +unsigned long wcstoul(const wchar_t *Str, wchar_t **End, int Base); +unsigned long long wcstoull(const wchar_t *Str, wchar_t **End, int Base); + +namespace std { + +using ::strtod; +using ::strtof; +using ::strtol; +using ::strtold; +using ::strtoll; +using ::strtoul; +using ::strtoull; + +using ::wcstol; +using ::wcstoll; +using ::wcstoul; +using ::wcstoull; + +} // namespace std + +#endif diff --git a/clang-tools-extra/test/clang-tidy/checkers/Inputs/Headers/std/iomanip b/clang-tools-extra/test/clang-tidy/checkers/Inputs/Headers/std/iomanip new file mode 100644 index 0000000000000..36bd311f97186 --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/checkers/Inputs/Headers/std/iomanip @@ -0,0 +1,21 @@ +//===--- iomanip - Stub header for tests ------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _IOMANIP_ +#define _IOMANIP_ + +namespace std { + +struct BaseManipulator { +}; + +BaseManipulator setbase(int Base); + +} // namespace std + +#endif diff --git a/clang-tools-extra/test/clang-tidy/checkers/Inputs/Headers/std/stdlib.h b/clang-tools-extra/test/clang-tidy/checkers/Inputs/Headers/std/stdlib.h index 6c9ddad82dcec..766062bc5efc4 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/Inputs/Headers/std/stdlib.h +++ b/clang-tools-extra/test/clang-tidy/checkers/Inputs/Headers/std/stdlib.h @@ -13,4 +13,16 @@ void abort(void); void _Exit(int); void quick_exit(int); +long strtol(const char *Str, char **End, int Base); +long long strtoll(const char *Str, char **End, int Base); +unsigned long strtoul(const char *Str, char **End, int Base); +unsigned long long strtoull(const char *Str, char **End, int Base); + +double strtod(const char *Str, char **End); +float strtof(const char *Str, char **End); +long double strtold(const char *Str, char **End); + +int atoi(const char *Str); +long atol(const char *Str); + #endif // _STDLIB_H_ diff --git a/clang-tools-extra/test/clang-tidy/checkers/Inputs/Headers/std/string b/clang-tools-extra/test/clang-tidy/checkers/Inputs/Headers/std/string index 766f240c655fb..aca370069a68f 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/Inputs/Headers/std/string +++ b/clang-tools-extra/test/clang-tidy/checkers/Inputs/Headers/std/string @@ -212,6 +212,20 @@ inline namespace string_view_literals { string_view operator""sv(const char *, size_t); } } + +int stoi(const string &Str, size_t *Pos = nullptr, int Base = 10); +long stol(const string &Str, size_t *Pos = nullptr, int Base = 10); +long long stoll(const string &Str, size_t *Pos = nullptr, int Base = 10); +unsigned long stoul(const string &Str, size_t *Pos = nullptr, int Base = 10); +unsigned long long stoull(const string &Str, size_t *Pos = nullptr, + int Base = 10); + +float stof(const string &Str, size_t *Pos = nullptr); +double stod(const string &Str, size_t *Pos = nullptr); +long double stold(const string &Str, size_t *Pos = nullptr); + +int stoi(const wstring &Str, size_t *Pos = nullptr, int Base = 10); +long stol(const wstring &Str, size_t *Pos = nullptr, int Base = 10); } #endif // _STRING_ diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/magic-numbers-well-known-args.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/magic-numbers-well-known-args.cpp new file mode 100644 index 0000000000000..e2ea6bfb3ad5c --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/checkers/readability/magic-numbers-well-known-args.cpp @@ -0,0 +1,137 @@ +// RUN: %check_clang_tidy -std=c++17-or-later %s readability-magic-numbers %t \ +// RUN: -config='{CheckOptions: \ +// RUN: {readability-magic-numbers.IgnoredIntegerValues: "1;2;3;4;", \ +// RUN: readability-magic-numbers.IgnorePowersOf2IntegerValues: false}}' \ +// RUN: -- +// +// RUN: %check_clang_tidy -std=c++17-or-later -check-suffixes=,ALL %s \ +// RUN: readability-magic-numbers %t \ +// RUN: -config='{CheckOptions: \ +// RUN: {readability-magic-numbers.IgnoredIntegerValues: "1;2;3;4;", \ +// RUN: readability-magic-numbers.IgnorePowersOf2IntegerValues: false, \ +// RUN: readability-magic-numbers.IgnoreWellKnownFunctionArgs: false}}' \ +// RUN: -- + +#include <charconv> +#include <cstdlib> +#include <iomanip> +#include <string> + +void CFamily(const char *Str, const wchar_t *WStr) { + (void)strtol(Str, nullptr, 0); + (void)strtol(Str, nullptr, 8); + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:30: warning: 8 is a magic number; consider replacing it with a named constant [readability-magic-numbers] + (void)strtol(Str, nullptr, 10); + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:30: warning: 10 is a magic number; consider replacing it with a named constant [readability-magic-numbers] + (void)strtol(Str, nullptr, 16); + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:30: warning: 16 is a magic number; consider replacing it with a named constant [readability-magic-numbers] + (void)strtoll(Str, nullptr, 16); + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:31: warning: 16 is a magic number; consider replacing it with a named constant [readability-magic-numbers] + (void)strtoul(Str, nullptr, 8); + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:31: warning: 8 is a magic number; consider replacing it with a named constant [readability-magic-numbers] + (void)strtoull(Str, nullptr, 16); + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:32: warning: 16 is a magic number; consider replacing it with a named constant [readability-magic-numbers] + (void)wcstol(WStr, nullptr, 8); + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:31: warning: 8 is a magic number; consider replacing it with a named constant [readability-magic-numbers] + (void)wcstoul(WStr, nullptr, 16); + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:32: warning: 16 is a magic number; consider replacing it with a named constant [readability-magic-numbers] +} + +void Qualified(const char *Str) { + (void)std::strtol(Str, nullptr, 16); + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:35: warning: 16 is a magic number; consider replacing it with a named constant [readability-magic-numbers] + (void)std::strtoull(Str, nullptr, 8); + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:37: warning: 8 is a magic number; consider replacing it with a named constant [readability-magic-numbers] +} + +void Cxx(const std::string &S, char *Begin, char *End, int &Value) { + (void)std::stoi(S, nullptr, 16); + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:31: warning: 16 is a magic number; consider replacing it with a named constant [readability-magic-numbers] + (void)std::stol(S, nullptr, 8); + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:31: warning: 8 is a magic number; consider replacing it with a named constant [readability-magic-numbers] + (void)std::stoul(S, nullptr, 16); + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:32: warning: 16 is a magic number; consider replacing it with a named constant [readability-magic-numbers] + + // The base is the fourth argument for the charconv functions. + (void)std::from_chars(Begin, End, Value, 16); + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:44: warning: 16 is a magic number; consider replacing it with a named constant [readability-magic-numbers] + (void)std::to_chars(Begin, End, Value, 16); + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:42: warning: 16 is a magic number; consider replacing it with a named constant [readability-magic-numbers] + + // And the only argument here. + (void)std::setbase(16); + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:22: warning: 16 is a magic number; consider replacing it with a named constant [readability-magic-numbers] +} + +void Wrappers(const char *Str) { + // Parentheses and the implicit conversion to int do not hide the argument. + (void)strtol(Str, nullptr, (16)); + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:31: warning: 16 is a magic number; consider replacing it with a named constant [readability-magic-numbers] + (void)strtol(Str, nullptr, ((8))); + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:32: warning: 8 is a magic number; consider replacing it with a named constant [readability-magic-numbers] +} + +template <typename T> +long ParseAs(const char *Str) { + return strtol(Str, nullptr, 16); + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:31: warning: 16 is a magic number; consider replacing it with a named constant [readability-magic-numbers] +} + +long InstantiatedParse(const char *Str) { return ParseAs<int>(Str); } + +namespace mylib { +long strtol(const char *Str, char **End, int Base); +} + +void configure(const char *Str, char **End, int Flags); + +void UnacceptedBase(const char *Str) { + (void)strtol(Str, nullptr, 12); + // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: 12 is a magic number; consider replacing it with a named constant [readability-magic-numbers] +} + +void ComputedBase(const char *Str, bool Cond) { + (void)strtol(Str, nullptr, 16 * 2); + // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: 16 is a magic number; consider replacing it with a named constant [readability-magic-numbers] + (void)strtol(Str, nullptr, Cond ? 8 : 16); + // CHECK-MESSAGES: :[[@LINE-1]]:37: warning: 8 is a magic number; consider replacing it with a named constant [readability-magic-numbers] + // CHECK-MESSAGES: :[[@LINE-2]]:41: warning: 16 is a magic number; consider replacing it with a named constant [readability-magic-numbers] +} + +void WrongArgumentIndex(char *Begin, char *End) { + (void)std::to_chars(Begin, End, 16, 10); + // CHECK-MESSAGES: :[[@LINE-1]]:35: warning: 16 is a magic number; consider replacing it with a named constant [readability-magic-numbers] + // CHECK-MESSAGES-ALL: :[[@LINE-2]]:39: warning: 10 is a magic number; consider replacing it with a named constant [readability-magic-numbers] +} + +void UnrelatedFunction(const char *Str) { + configure(Str, nullptr, 16); + // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: 16 is a magic number; consider replacing it with a named constant [readability-magic-numbers] +} + +void UserNamespaceLookalike(const char *Str) { + (void)mylib::strtol(Str, nullptr, 16); + // CHECK-MESSAGES: :[[@LINE-1]]:37: warning: 16 is a magic number; consider replacing it with a named constant [readability-magic-numbers] +} + +struct Parser { + long strtol(const char *Str, char **End, int Base); + + void parse(const char *Str) { + (void)strtol(Str, nullptr, 16); + // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: 16 is a magic number; consider replacing it with a named constant [readability-magic-numbers] + } +}; + +void IndirectCall(const char *Str) { + long (*Fn)(const char *, char **, int) = strtol; + + (void)Fn(Str, nullptr, 16); + // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: 16 is a magic number; consider replacing it with a named constant [readability-magic-numbers] +} + +void NotAnArgument() { + int Base = 16; + // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: 16 is a magic number; consider replacing it with a named constant [readability-magic-numbers] + (void)Base; +} _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
