[clang-tools-extra] [clang-tidy] Exclude well-known conversion bases from readability-magic-numbers (PR #216516)
via cfe-commits
cfe-commits at lists.llvm.org
Sun Aug 16 06:45:02 PDT 2026
https://github.com/Floweynt updated https://github.com/llvm/llvm-project/pull/216516
>From 791aa85d58cabb4c99218596ff76c445ea208e56 Mon Sep 17 00:00:00 2001
From: Floweynt <floweydev at gmail.com>
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;
+}
More information about the cfe-commits
mailing list