-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[clang-tidy] Add user-defined functions to bugprone-unsafe-functions
check
#106350
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@llvm/pr-subscribers-clang-tidy @llvm/pr-subscribers-clang-tools-extra Author: Discookie (Discookie) ChangesAdds the check options The functions names are matched using the same mechanism as the Patch is 26.16 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/106350.diff 7 Files Affected:
diff --git a/clang-tools-extra/clang-tidy/bugprone/UnsafeFunctionsCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/UnsafeFunctionsCheck.cpp
index ea7eaa0b0ff811..8d9ffda04a847a 100644
--- a/clang-tools-extra/clang-tidy/bugprone/UnsafeFunctionsCheck.cpp
+++ b/clang-tools-extra/clang-tidy/bugprone/UnsafeFunctionsCheck.cpp
@@ -7,6 +7,8 @@
//===----------------------------------------------------------------------===//
#include "UnsafeFunctionsCheck.h"
+#include "../utils/Matchers.h"
+#include "../utils/OptionsUtils.h"
#include "clang/AST/ASTContext.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/Lex/PPCallbacks.h"
@@ -18,6 +20,12 @@ using namespace llvm;
namespace clang::tidy::bugprone {
+static constexpr llvm::StringLiteral OptionNameCustomNormalFunctions =
+ "CustomNormalFunctions";
+static constexpr llvm::StringLiteral OptionNameCustomAnnexKFunctions =
+ "CustomAnnexKFunctions";
+static constexpr llvm::StringLiteral OptionNameReportDefaultFunctions =
+ "ReportDefaultFunctions";
static constexpr llvm::StringLiteral OptionNameReportMoreUnsafeFunctions =
"ReportMoreUnsafeFunctions";
@@ -26,6 +34,8 @@ static constexpr llvm::StringLiteral FunctionNamesWithAnnexKReplacementId =
static constexpr llvm::StringLiteral FunctionNamesId = "FunctionsNames";
static constexpr llvm::StringLiteral AdditionalFunctionNamesId =
"AdditionalFunctionsNames";
+static constexpr llvm::StringLiteral CustomFunctionNamesId = "CustomFunctionNames";
+static constexpr llvm::StringLiteral CustomAnnexKFunctionNamesId = "CustomAnnexKFunctionNames";
static constexpr llvm::StringLiteral DeclRefId = "DRE";
static std::optional<std::string>
@@ -127,55 +137,151 @@ static bool isAnnexKAvailable(std::optional<bool> &CacheVar, Preprocessor *PP,
return CacheVar.value();
}
+static std::vector<UnsafeFunctionsCheck::CheckedFunction>
+ParseCheckedFunctions(StringRef Option, StringRef OptionName,
+ ClangTidyContext *Context) {
+ std::vector<StringRef> Functions = utils::options::parseStringList(Option);
+ std::vector<UnsafeFunctionsCheck::CheckedFunction> Result;
+ Result.reserve(Functions.size());
+
+ for (StringRef Function : Functions) {
+ if (Function.empty()) {
+ continue;
+ }
+
+ auto [Name, Rest] = Function.split(',');
+ auto [Replacement, Reason] = Rest.split(',');
+
+ if (Name.trim().empty()) {
+ Context->configurationDiag(
+ "invalid configuration value for option '%0'; "
+ "expected the name of an unsafe function") << OptionName;
+ }
+
+ if (Replacement.trim().empty()) {
+ Context->configurationDiag(
+ "invalid configuration value '%0' for option '%1'; "
+ "expected a replacement function name") << Name.trim() << OptionName;
+ }
+
+ Result.push_back({ Name.trim().str(), matchers::MatchesAnyListedNameMatcher::NameMatcher(Name.trim()),
+ Replacement.trim().str(), Reason.trim().str() });
+ }
+
+ return Result;
+}
+
+static std::string SerializeCheckedFunctions(
+ const std::vector<UnsafeFunctionsCheck::CheckedFunction> &Functions) {
+ std::vector<std::string> Result;
+ Result.reserve(Functions.size());
+
+ for (const auto &Entry : Functions) {
+ if (Entry.Reason.empty())
+ Result.push_back(Entry.Name + "," + Entry.Replacement);
+ else
+ Result.push_back(Entry.Name + "," + Entry.Replacement + "," +
+ Entry.Reason);
+ }
+
+ return llvm::join(Result, ";");
+}
+
UnsafeFunctionsCheck::UnsafeFunctionsCheck(StringRef Name,
ClangTidyContext *Context)
: ClangTidyCheck(Name, Context),
+ CustomNormalFunctions(ParseCheckedFunctions(
+ Options.get(OptionNameCustomNormalFunctions, ""),
+ OptionNameCustomNormalFunctions, Context)),
+ CustomAnnexKFunctions(ParseCheckedFunctions(
+ Options.get(OptionNameCustomAnnexKFunctions, ""),
+ OptionNameCustomAnnexKFunctions, Context)),
+ ReportDefaultFunctions(Options.get(OptionNameReportDefaultFunctions, true)),
ReportMoreUnsafeFunctions(
Options.get(OptionNameReportMoreUnsafeFunctions, true)) {}
void UnsafeFunctionsCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
+ Options.store(Opts, OptionNameCustomNormalFunctions,
+ SerializeCheckedFunctions(CustomNormalFunctions));
+ Options.store(Opts, OptionNameCustomAnnexKFunctions,
+ SerializeCheckedFunctions(CustomAnnexKFunctions));
+ Options.store(Opts, OptionNameReportDefaultFunctions, ReportDefaultFunctions);
Options.store(Opts, OptionNameReportMoreUnsafeFunctions,
ReportMoreUnsafeFunctions);
}
void UnsafeFunctionsCheck::registerMatchers(MatchFinder *Finder) {
- if (getLangOpts().C11) {
- // Matching functions with safe replacements only in Annex K.
- auto FunctionNamesWithAnnexKReplacementMatcher = hasAnyName(
- "::bsearch", "::ctime", "::fopen", "::fprintf", "::freopen", "::fscanf",
- "::fwprintf", "::fwscanf", "::getenv", "::gmtime", "::localtime",
- "::mbsrtowcs", "::mbstowcs", "::memcpy", "::memmove", "::memset",
- "::printf", "::qsort", "::scanf", "::snprintf", "::sprintf", "::sscanf",
- "::strcat", "::strcpy", "::strerror", "::strlen", "::strncat",
- "::strncpy", "::strtok", "::swprintf", "::swscanf", "::vfprintf",
- "::vfscanf", "::vfwprintf", "::vfwscanf", "::vprintf", "::vscanf",
- "::vsnprintf", "::vsprintf", "::vsscanf", "::vswprintf", "::vswscanf",
- "::vwprintf", "::vwscanf", "::wcrtomb", "::wcscat", "::wcscpy",
- "::wcslen", "::wcsncat", "::wcsncpy", "::wcsrtombs", "::wcstok",
- "::wcstombs", "::wctomb", "::wmemcpy", "::wmemmove", "::wprintf",
- "::wscanf");
+ if (ReportDefaultFunctions) {
+ if (getLangOpts().C11) {
+ // Matching functions with safe replacements only in Annex K.
+ auto FunctionNamesWithAnnexKReplacementMatcher = hasAnyName(
+ "::bsearch", "::ctime", "::fopen", "::fprintf", "::freopen", "::fscanf",
+ "::fwprintf", "::fwscanf", "::getenv", "::gmtime", "::localtime",
+ "::mbsrtowcs", "::mbstowcs", "::memcpy", "::memmove", "::memset",
+ "::printf", "::qsort", "::scanf", "::snprintf", "::sprintf", "::sscanf",
+ "::strcat", "::strcpy", "::strerror", "::strlen", "::strncat",
+ "::strncpy", "::strtok", "::swprintf", "::swscanf", "::vfprintf",
+ "::vfscanf", "::vfwprintf", "::vfwscanf", "::vprintf", "::vscanf",
+ "::vsnprintf", "::vsprintf", "::vsscanf", "::vswprintf", "::vswscanf",
+ "::vwprintf", "::vwscanf", "::wcrtomb", "::wcscat", "::wcscpy",
+ "::wcslen", "::wcsncat", "::wcsncpy", "::wcsrtombs", "::wcstok",
+ "::wcstombs", "::wctomb", "::wmemcpy", "::wmemmove", "::wprintf",
+ "::wscanf");
+ Finder->addMatcher(
+ declRefExpr(to(functionDecl(FunctionNamesWithAnnexKReplacementMatcher)
+ .bind(FunctionNamesWithAnnexKReplacementId)))
+ .bind(DeclRefId),
+ this);
+ }
+
+ // Matching functions with replacements without Annex K.
+ auto FunctionNamesMatcher =
+ hasAnyName("::asctime", "asctime_r", "::gets", "::rewind", "::setbuf");
Finder->addMatcher(
- declRefExpr(to(functionDecl(FunctionNamesWithAnnexKReplacementMatcher)
- .bind(FunctionNamesWithAnnexKReplacementId)))
+ declRefExpr(to(functionDecl(FunctionNamesMatcher).bind(FunctionNamesId)))
.bind(DeclRefId),
this);
+
+ if (ReportMoreUnsafeFunctions) {
+ // Matching functions with replacements without Annex K, at user request.
+ auto AdditionalFunctionNamesMatcher =
+ hasAnyName("::bcmp", "::bcopy", "::bzero", "::getpw", "::vfork");
+ Finder->addMatcher(
+ declRefExpr(to(functionDecl(AdditionalFunctionNamesMatcher)
+ .bind(AdditionalFunctionNamesId)))
+ .bind(DeclRefId),
+ this);
+ }
}
- // Matching functions with replacements without Annex K.
- auto FunctionNamesMatcher =
- hasAnyName("::asctime", "asctime_r", "::gets", "::rewind", "::setbuf");
- Finder->addMatcher(
- declRefExpr(to(functionDecl(FunctionNamesMatcher).bind(FunctionNamesId)))
- .bind(DeclRefId),
- this);
-
- if (ReportMoreUnsafeFunctions) {
- // Matching functions with replacements without Annex K, at user request.
- auto AdditionalFunctionNamesMatcher =
- hasAnyName("::bcmp", "::bcopy", "::bzero", "::getpw", "::vfork");
+ if (!CustomAnnexKFunctions.empty()) {
+ std::vector<llvm::StringRef> FunctionNames;
+ FunctionNames.reserve(CustomAnnexKFunctions.size());
+
+ for (const auto &Entry : CustomAnnexKFunctions)
+ FunctionNames.push_back(Entry.Name);
+
+ auto CustomAnnexKFunctionsMatcher =
+ matchers::matchesAnyListedName(FunctionNames);
+
Finder->addMatcher(
- declRefExpr(to(functionDecl(AdditionalFunctionNamesMatcher)
- .bind(AdditionalFunctionNamesId)))
+ declRefExpr(to(functionDecl(CustomAnnexKFunctionsMatcher).bind(CustomAnnexKFunctionNamesId)))
+ .bind(DeclRefId),
+ this);
+ }
+
+ if (!CustomNormalFunctions.empty()) {
+ std::vector<llvm::StringRef> FunctionNames;
+ FunctionNames.reserve(CustomNormalFunctions.size());
+
+ for (const auto &Entry : CustomNormalFunctions)
+ FunctionNames.push_back(Entry.Name);
+
+ auto CustomFunctionsMatcher =
+ matchers::matchesAnyListedName(FunctionNames);
+
+ Finder->addMatcher(
+ declRefExpr(to(functionDecl(CustomFunctionsMatcher).bind(CustomFunctionNamesId)))
.bind(DeclRefId),
this);
}
@@ -186,16 +292,62 @@ void UnsafeFunctionsCheck::check(const MatchFinder::MatchResult &Result) {
const auto *FuncDecl = cast<FunctionDecl>(DeclRef->getDecl());
assert(DeclRef && FuncDecl && "No valid matched node in check()");
+ // Only one of these are matched at a time.
const auto *AnnexK = Result.Nodes.getNodeAs<FunctionDecl>(
FunctionNamesWithAnnexKReplacementId);
const auto *Normal = Result.Nodes.getNodeAs<FunctionDecl>(FunctionNamesId);
const auto *Additional =
Result.Nodes.getNodeAs<FunctionDecl>(AdditionalFunctionNamesId);
- assert((AnnexK || Normal || Additional) && "No valid match category.");
+ const auto *CustomAnnexK = Result.Nodes.getNodeAs<FunctionDecl>(
+ CustomAnnexKFunctionNamesId);
+ const auto *CustomNormal = Result.Nodes.getNodeAs<FunctionDecl>(
+ CustomFunctionNamesId);
+ assert((AnnexK || Normal || Additional || CustomAnnexK || CustomNormal) &&
+ "No valid match category.");
bool AnnexKIsAvailable =
isAnnexKAvailable(IsAnnexKAvailable, PP, getLangOpts());
StringRef FunctionName = FuncDecl->getName();
+
+ if (CustomAnnexK || CustomNormal) {
+ const auto ShowCheckedFunctionWarning = [&](const CheckedFunction &Entry) {
+ StringRef Reason = Entry.Reason.empty() ? "is marked as unsafe"
+ : Entry.Reason.c_str();
+ diag(DeclRef->getExprLoc(), "function %0 %1; '%2' should be used instead")
+ << FuncDecl << Reason
+ << Entry.Replacement << DeclRef->getSourceRange();
+ };
+
+ if (AnnexKIsAvailable) {
+ for (const auto &Entry : CustomAnnexKFunctions) {
+ if (Entry.Pattern.match(*FuncDecl)) {
+ // If both Annex K and Normal are matched, show Annex K warning only.
+ if (CustomAnnexK)
+ ShowCheckedFunctionWarning(Entry);
+
+ return;
+ }
+ }
+
+ assert(!CustomAnnexK && "No custom Annex K function was matched.");
+ }
+
+ // Annex K was not available, or the assertion failed.
+ if (CustomAnnexK)
+ return;
+
+ for (const auto &Entry : CustomNormalFunctions) {
+
+ if (Entry.Pattern.match(*FuncDecl)) {
+ ShowCheckedFunctionWarning(Entry);
+ return;
+ }
+ }
+
+ assert(false && "No custom function was matched.");
+ return;
+ }
+
const std::optional<std::string> ReplacementFunctionName =
[&]() -> std::optional<std::string> {
if (AnnexK) {
diff --git a/clang-tools-extra/clang-tidy/bugprone/UnsafeFunctionsCheck.h b/clang-tools-extra/clang-tidy/bugprone/UnsafeFunctionsCheck.h
index 5adfee60d1a7de..ad23a807666e79 100644
--- a/clang-tools-extra/clang-tidy/bugprone/UnsafeFunctionsCheck.h
+++ b/clang-tools-extra/clang-tidy/bugprone/UnsafeFunctionsCheck.h
@@ -10,6 +10,7 @@
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_UNSAFEFUNCTIONSCHECK_H
#include "../ClangTidyCheck.h"
+#include "../utils/Matchers.h"
#include <optional>
namespace clang::tidy::bugprone {
@@ -32,7 +33,19 @@ class UnsafeFunctionsCheck : public ClangTidyCheck {
Preprocessor *ModuleExpanderPP) override;
void onEndOfTranslationUnit() override;
+ struct CheckedFunction {
+ std::string Name;
+ matchers::MatchesAnyListedNameMatcher::NameMatcher Pattern;
+ std::string Replacement;
+ std::string Reason;
+ };
+
private:
+ const std::vector<CheckedFunction> CustomNormalFunctions;
+ const std::vector<CheckedFunction> CustomAnnexKFunctions;
+
+ // If true, the default set of functions are reported.
+ const bool ReportDefaultFunctions;
/// If true, additional functions from widely used API-s (such as POSIX) are
/// added to the list of reported functions.
const bool ReportMoreUnsafeFunctions;
diff --git a/clang-tools-extra/clang-tidy/utils/Matchers.h b/clang-tools-extra/clang-tidy/utils/Matchers.h
index 5fd98db9678708..f79d872300320b 100644
--- a/clang-tools-extra/clang-tidy/utils/Matchers.h
+++ b/clang-tools-extra/clang-tidy/utils/Matchers.h
@@ -85,15 +85,7 @@ class MatchesAnyListedNameMatcher
NameList.begin(), NameList.end(), std::back_inserter(NameMatchers),
[](const llvm::StringRef Name) { return NameMatcher(Name); });
}
- bool matches(
- const NamedDecl &Node, ast_matchers::internal::ASTMatchFinder *Finder,
- ast_matchers::internal::BoundNodesTreeBuilder *Builder) const override {
- return llvm::any_of(NameMatchers, [&Node](const NameMatcher &NM) {
- return NM.match(Node);
- });
- }
-private:
class NameMatcher {
llvm::Regex Regex;
enum class MatchMode {
@@ -136,6 +128,16 @@ class MatchesAnyListedNameMatcher
}
};
+ bool matches(
+ const NamedDecl &Node, ast_matchers::internal::ASTMatchFinder *Finder,
+ ast_matchers::internal::BoundNodesTreeBuilder *Builder) const override {
+ return llvm::any_of(NameMatchers, [&Node](const NameMatcher &NM) {
+ return NM.match(Node);
+ });
+ }
+
+private:
+
std::vector<NameMatcher> NameMatchers;
};
diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/unsafe-functions.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/unsafe-functions.rst
index a0a267883b6fe9..e97794cd8f30b0 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/unsafe-functions.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/unsafe-functions.rst
@@ -19,6 +19,9 @@ The check implements the following rules from the CERT C Coding Standard:
Unsafe functions
----------------
+The following functions are reported if `ReportDefaultFunctions
+<unsafe-functions.html#cmdoption-arg-ReportDefaultFunctions>`_ is enabled.
+
If *Annex K.* is available, a replacement from *Annex K.* is suggested for the
following functions:
@@ -74,6 +77,40 @@ Both macros have to be defined to suggest replacement functions from *Annex K.*
``__STDC_WANT_LIB_EXT1__`` must be defined to ``1`` by the user **before**
including any system headers.
+Custom functions
+----------------
+
+The options `CustomNormalFunctions` and `CustomAnnexKFunctions` allow the user
+to define custom functions to be checked. The format is the following, without
+newlines:
+
+.. code::
+
+ bugprone-unsafe-functions.CustomNormalFunctions="
+ functionRegex1, replacement1[, reason1];
+ functionRegex2, replacement2[, reason2];
+ ...
+ "
+
+The functions are matched using POSIX extended regular expressions.
+*(Note: The regular expressions do not support negative* ``(?!)`` *matches)*
+
+The `reason` is optional and is used to provide additional information about the
+reasoning behind the replacement. The default reason is ``is marked as unsafe``.
+
+As an example, the configuration ``^original$, replacement, is deprecated;``
+will produce the following diagnostic message.
+
+.. code:: c
+
+ original(); // warning: function 'original' is deprecated; 'replacement' should be used instead.
+ ::std::original(); // no-warning
+ original_function(); // no-warning
+
+If the regular expression contains the character ``:``, it is matched against the
+qualified name (i.e. ``std::original``), otherwise the regex is matched against the unqualified name (``original``).
+If the regular expression starts with ``::`` (or ``^::``), it is matched against the
+fully qualified name (``::std::original``).
Options
-------
@@ -86,6 +123,22 @@ Options
this option enables.
Default is `true`.
+.. option:: ReportDefaultFunctions
+
+ When `true`, the check reports the default set of functions.
+ Default is `true`.
+
+.. option:: CustomNormalFunctions
+
+ A comma-separated list of regular expressions, their replacements, and an
+ optional reason. For more information, see `Custom functions
+ <unsafe-functions.html#custom-functions>`_.
+
+.. option:: CustomAnnexKFunctions
+
+ A comma-separated list of regular expressions, their replacements, and an
+ optional reason. For more information, see `Custom functions
+ <unsafe-functions.html#custom-functions>`_.
Examples
--------
diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/unsafe-functions-custom-regex.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone/unsafe-functions-custom-regex.cpp
new file mode 100644
index 00000000000000..4554c43fb700d5
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/unsafe-functions-custom-regex.cpp
@@ -0,0 +1,63 @@
+// This test fails on "x86_64-sie" buildbot and "x86_64-scei-ps4" target.
+// According to @dyung, something related to the kind of standard library
+// availability is causing the failure. Even though we explicitly define
+// the relevant macros the check is hunting for in the invocation, the real
+// parsing and preprocessor state will not have that case.
+// UNSUPPORTED: target={{.*-(ps4|ps5)}}
+//
+// RUN: %check_clang_tidy -check-suffix=NON-STRICT-REGEX %s bugprone-unsafe-functions %t --\
+// RUN: -config="{CheckOptions: {bugprone-unsafe-functions.CustomNormalFunctions: '::non_annex_k_only,replacement;::both,replacement,is a normal function'}}"\
+// RUN: -- -U__STDC_LIB_EXT1__ -U__STDC_WANT_LIB_EXT1__
+// RUN: %check_clang_tidy -check-suffix=STRICT-REGEX %s bugprone-unsafe-functions %t --\
+// RUN: -config="{CheckOptions: {bugprone-unsafe-functions.CustomNormalFunctions: '^non_annex_k_only$,replacement,is matched on function name only;^::both,replacement,is matched on qualname prefix'}}"\
+// RUN: -- -U__STDC_LIB_EXT1__ -U__STDC_WANT_LIB_EXT1__
+// RUN: %check_clang_tidy -check-suffix=WITH-ANNEX-K %s bugprone-unsafe-functions %t --\
+// RUN: -config="{CheckOptions: {bugprone-unsafe-functions.CustomAnnexKFunctions: '::annex_k_only,replacement;::both,replacement,is an Annex K function'}}"\
+// RUN: -- -D__STDC_LIB_EXT1__=1 -D__STDC_WANT_LIB_EXT1__=1
+
+// TODO: How is "Annex K" available in C++ mode?
+// no-warning WITH-ANNEX-K
+
+void non_annex_k_only();
+void annex_k_only();
+void both();
+
+namespace regex_test {
+void non_annex_k_only();
+void both();
+}
+
+void non_annex_k_only_regex();
+void both_regex();
+
+void f1() {
+ non_annex_k_only();
+ // CHECK-MESSAGES-NON-STRICT-REGEX: :[[@LINE-1]]:3: warning: function 'non_annex_k_only' is marked as unsafe; 'replacement' should be used instead
+ // CHECK-MESSAGES-STRICT-REGEX: :[[@LINE-2]]:3: warning: function 'non_annex_k_only' is matched on function name only; 'replacement' should be used instead
+ annex_k_only();
+ // no-warning NON-STRICT-REGEX
+ // no-warning STRICT-REGEX
+ both();
+ // CHECK-MESSAGES-NON-STRICT-REGEX: :[[@LINE-1]]:3: warning: function 'both' is a normal function; 'replacement' should be...
[truncated]
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
The same matching mechanism should be used both there and within bugprone-unsafe-functions check.
…r bugprone-unsafe-functions check
80694ad
to
476d571
Compare
Note: I copied over the header from the test |
The following functions are reported if `ReportDefaultFunctions | ||
<unsafe-functions.html#cmdoption-arg-ReportDefaultFunctions>`_ is enabled. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of the automatically generated label which might break apart if the template is changed, try to use a reference label in the RST with a proper identifier and refer that instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I hope I did it correctly, I'm not that familiar with RST syntax.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Referring to the .html
directly is definitely not good because rst can be lowered to different markup syntaxes.
You need to create (or check if opt::
automatically does?) a referable entity, and then :ref:
can be used to make the link clickable. So you will use the ID or "label" you allocated in the document instead of relying on the automatically generated, HTML-specific anchor.
High-level design question: Why is |
I could rename CustomNormalFunctions to CustomFunctions or something to make it clearer that it's always available. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please mention changes in Release Notes.
clang-tools-extra/docs/clang-tidy/checks/bugprone/unsafe-functions.rst
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just some small things
clang-tools-extra/docs/clang-tidy/checks/bugprone/unsafe-functions.rst
Outdated
Show resolved
Hide resolved
Do not add invalid options to the functions list Rewrite description for options Minor formatting fixes
I'm still not sure why we need both |
Internal was the wrong word there, the distinction is only about whether AnnexK is available or not, in the context of the checked code. We certainly could eliminate |
Ultimately it would not get much use outside of being able to reproduce the default check logic.
Removed the normal/AnnexK distinction as I think it would get little use as it's a rare edge case, and it made everything more confusing. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alright, I think this patch is good from a design standpoint! I'll get into the nitty-gritty in a bit.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks good from my side.
@@ -19,6 +19,8 @@ The check implements the following rules from the CERT C Coding Standard: | |||
Unsafe functions | |||
---------------- | |||
|
|||
The following functions are reported if :ref:`ReportDefaultFunctions<option-ReportDefaultFunctions>` is enabled. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The following functions are reported if :ref:`ReportDefaultFunctions<option-ReportDefaultFunctions>` is enabled. | |
The following functions are reported if :option:`ReportDefaultFunctions` is enabled. |
I knew there were examples for this, and now I was able to find some:
clang-tools-extra/docs/clang-tidy/checks/bugprone/unsafe-functions.rst
Outdated
Show resolved
Hide resolved
clang-tools-extra/docs/clang-tidy/checks/bugprone/unsafe-functions.rst
Outdated
Show resolved
Hide resolved
clang-tools-extra/docs/clang-tidy/checks/bugprone/unsafe-functions.rst
Outdated
Show resolved
Hide resolved
.. _option-ReportMoreUnsafeFunctions: | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
.. _option-ReportMoreUnsafeFunctions: |
With using :option:...
maybe these are not needed, but please double check!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Checked, they aren't needed. Thanks for finding usages for the doc syntax!
clang-tools-extra/docs/clang-tidy/checks/bugprone/unsafe-functions.rst
Outdated
Show resolved
Hide resolved
clang-tools-extra/docs/clang-tidy/checks/bugprone/unsafe-functions.rst
Outdated
Show resolved
Hide resolved
Fixed the outstanding minor issues. |
…s` check (llvm#106350) Adds the check option `bugprone-unsafe-functions.CustomFunctions` to be able to match user-defined functions as part of the checker. Adds the option `bugprone-unsafe-functions.ReportDefaultFunctions` to disable reporting the default set of functions as well. The functions names are matched using the same mechanism as the `matchesAnyListedName` tidy matcher, documented in `unsafe-functions.rst`.
Adds the check option
bugprone-unsafe-functions.CustomFunctions
to be able to match user-defined functions as part of the checker.Adds the option
bugprone-unsafe-functions.ReportDefaultFunctions
to disable reporting the default set of functions as well.The functions names are matched using the same mechanism as the
matchesAnyListedName
tidy matcher, documented inunsafe-functions.rst
.