[clang-tools-extra] cc7ed0c - [clang-tidy] bugprone-signal-handler: Message improvement and code refactoring.
Balázs Kéri via cfe-commits
cfe-commits at lists.llvm.org
Thu Apr 7 00:39:55 PDT 2022
Author: Balázs Kéri
Date: 2022-04-07T09:38:58+02:00
New Revision: cc7ed0caaca58bb38c789dcf2e0aade5f68f1e02
URL: https://github.com/llvm/llvm-project/commit/cc7ed0caaca58bb38c789dcf2e0aade5f68f1e02
DIFF: https://github.com/llvm/llvm-project/commit/cc7ed0caaca58bb38c789dcf2e0aade5f68f1e02.diff
LOG: [clang-tidy] bugprone-signal-handler: Message improvement and code refactoring.
Another change of the code design.
Code simplified again, now there is a single place to check
a handler function and less functions for bug report emitting.
More details are added to the bug report messages.
Reviewed By: whisperity
Differential Revision: https://reviews.llvm.org/D118370
Added:
Modified:
clang-tools-extra/clang-tidy/bugprone/SignalHandlerCheck.cpp
clang-tools-extra/clang-tidy/bugprone/SignalHandlerCheck.h
clang-tools-extra/test/clang-tidy/checkers/bugprone-signal-handler-minimal.c
clang-tools-extra/test/clang-tidy/checkers/bugprone-signal-handler-posix.c
clang-tools-extra/test/clang-tidy/checkers/bugprone-signal-handler.c
Removed:
################################################################################
diff --git a/clang-tools-extra/clang-tidy/bugprone/SignalHandlerCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/SignalHandlerCheck.cpp
index 983a7c0610d71..37d373905b693 100644
--- a/clang-tools-extra/clang-tidy/bugprone/SignalHandlerCheck.cpp
+++ b/clang-tools-extra/clang-tidy/bugprone/SignalHandlerCheck.cpp
@@ -11,215 +11,9 @@
#include "llvm/ADT/DepthFirstIterator.h"
#include "llvm/ADT/STLExtras.h"
-using namespace clang::ast_matchers;
-
-namespace clang {
-namespace tidy {
-
-template <>
-struct OptionEnumMapping<
- bugprone::SignalHandlerCheck::AsyncSafeFunctionSetType> {
- static llvm::ArrayRef<std::pair<
- bugprone::SignalHandlerCheck::AsyncSafeFunctionSetType, StringRef>>
- getEnumMapping() {
- static constexpr std::pair<
- bugprone::SignalHandlerCheck::AsyncSafeFunctionSetType, StringRef>
- Mapping[] = {
- {bugprone::SignalHandlerCheck::AsyncSafeFunctionSetType::Minimal,
- "minimal"},
- {bugprone::SignalHandlerCheck::AsyncSafeFunctionSetType::POSIX,
- "POSIX"},
- };
- return makeArrayRef(Mapping);
- }
-};
-
-namespace bugprone {
-
-namespace {
-
-bool isSystemCall(const FunctionDecl *FD) {
- // Find a possible redeclaration in system header.
- // FIXME: Looking at the canonical declaration is not the most exact way
- // to do this.
-
- // Most common case will be inclusion directly from a header.
- // This works fine by using canonical declaration.
- // a.c
- // #include <sysheader.h>
-
- // Next most common case will be extern declaration.
- // Can't catch this with either approach.
- // b.c
- // extern void sysfunc(void);
-
- // Canonical declaration is the first found declaration, so this works.
- // c.c
- // #include <sysheader.h>
- // extern void sysfunc(void); // redecl won't matter
-
- // This does not work with canonical declaration.
- // Probably this is not a frequently used case but may happen (the first
- // declaration can be in a non-system header for example).
- // d.c
- // extern void sysfunc(void); // Canonical declaration, not in system header.
- // #include <sysheader.h>
-
- return FD->getASTContext().getSourceManager().isInSystemHeader(
- FD->getCanonicalDecl()->getLocation());
-}
-
-/// Given a call graph node of a function and another one that is called from
-/// this function, get a CallExpr of the corresponding function call.
-/// It is unspecified which call is found if multiple calls exist, but the order
-/// should be deterministic (depend only on the AST).
-Expr *findCallExpr(const CallGraphNode *Caller, const CallGraphNode *Callee) {
- auto FoundCallee = llvm::find_if(
- Caller->callees(), [Callee](const CallGraphNode::CallRecord &Call) {
- return Call.Callee == Callee;
- });
- assert(FoundCallee != Caller->end() &&
- "Callee should be called from the caller function here.");
- return FoundCallee->CallExpr;
-}
-
-} // namespace
-
-AST_MATCHER(FunctionDecl, isSystemCall) { return isSystemCall(&Node); }
-
-SignalHandlerCheck::SignalHandlerCheck(StringRef Name,
- ClangTidyContext *Context)
- : ClangTidyCheck(Name, Context),
- AsyncSafeFunctionSet(
- Options.get("AsyncSafeFunctionSet", AsyncSafeFunctionSetType::POSIX)),
- ConformingFunctions(AsyncSafeFunctionSet ==
- AsyncSafeFunctionSetType::Minimal
- ? MinimalConformingFunctions
- : POSIXConformingFunctions) {}
-
-void SignalHandlerCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
- Options.store(Opts, "AsyncSafeFunctionSet", AsyncSafeFunctionSet);
-}
-
-bool SignalHandlerCheck::isLanguageVersionSupported(
- const LangOptions &LangOpts) const {
- // FIXME: Make the checker useful on C++ code.
- if (LangOpts.CPlusPlus)
- return false;
-
- return true;
-}
-
-void SignalHandlerCheck::registerMatchers(MatchFinder *Finder) {
- auto SignalFunction = functionDecl(hasAnyName("::signal", "::std::signal"),
- parameterCountIs(2), isSystemCall());
- auto HandlerExpr =
- declRefExpr(hasDeclaration(functionDecl().bind("handler_decl")),
- unless(isExpandedFromMacro("SIG_IGN")),
- unless(isExpandedFromMacro("SIG_DFL")))
- .bind("handler_expr");
- Finder->addMatcher(
- callExpr(callee(SignalFunction), hasArgument(1, HandlerExpr))
- .bind("register_call"),
- this);
-}
-
-void SignalHandlerCheck::check(const MatchFinder::MatchResult &Result) {
- const auto *SignalCall = Result.Nodes.getNodeAs<CallExpr>("register_call");
- const auto *HandlerDecl =
- Result.Nodes.getNodeAs<FunctionDecl>("handler_decl");
- const auto *HandlerExpr = Result.Nodes.getNodeAs<DeclRefExpr>("handler_expr");
- assert(SignalCall && HandlerDecl && HandlerExpr &&
- "All of these should exist in a match here.");
-
- if (CG.size() <= 1) {
- // Call graph must be populated with the entire TU at the beginning.
- // (It is possible to add a single function but the functions called from it
- // are not analysed in this case.)
- CG.addToCallGraph(const_cast<TranslationUnitDecl *>(
- HandlerDecl->getTranslationUnitDecl()));
- assert(CG.size() > 1 &&
- "There should be at least one function added to call graph.");
- }
-
- // Check for special case when the signal handler itself is an unsafe external
- // function.
- if (!isFunctionAsyncSafe(HandlerDecl)) {
- reportBug(HandlerDecl, HandlerExpr, /*DirectHandler=*/true);
- return;
- }
-
- CallGraphNode *HandlerNode = CG.getNode(HandlerDecl);
- // Signal handler can be external but not unsafe, no call graph in this case.
- if (!HandlerNode)
- return;
- // Start from signal handler and visit every function call.
- for (auto Itr = llvm::df_begin(HandlerNode), ItrE = llvm::df_end(HandlerNode);
- Itr != ItrE; ++Itr) {
- const auto *CallF = dyn_cast<FunctionDecl>((*Itr)->getDecl());
- if (CallF && !isFunctionAsyncSafe(CallF)) {
- assert(Itr.getPathLength() >= 2);
- reportBug(CallF, findCallExpr(Itr.getPath(Itr.getPathLength() - 2), *Itr),
- /*DirectHandler=*/false);
- reportHandlerCommon(Itr, SignalCall, HandlerDecl, HandlerExpr);
- }
- }
-}
-
-bool SignalHandlerCheck::isFunctionAsyncSafe(const FunctionDecl *FD) const {
- if (isSystemCall(FD))
- return isSystemCallAsyncSafe(FD);
- // For external (not checkable) functions assume that these are unsafe.
- return FD->hasBody();
-}
-
-bool SignalHandlerCheck::isSystemCallAsyncSafe(const FunctionDecl *FD) const {
- const IdentifierInfo *II = FD->getIdentifier();
- // Unnamed functions are not explicitly allowed.
- if (!II)
- return false;
-
- // FIXME: Improve for C++ (check for namespace).
- if (ConformingFunctions.count(II->getName()))
- return true;
-
- return false;
-}
-
-void SignalHandlerCheck::reportBug(const FunctionDecl *CalledFunction,
- const Expr *CallOrRef, bool DirectHandler) {
- diag(CallOrRef->getBeginLoc(),
- "%0 may not be asynchronous-safe; %select{calling it from|using it as}1 "
- "a signal handler may be dangerous")
- << CalledFunction << DirectHandler;
-}
-
-void SignalHandlerCheck::reportHandlerCommon(
- llvm::df_iterator<clang::CallGraphNode *> Itr, const CallExpr *SignalCall,
- const FunctionDecl *HandlerDecl, const Expr *HandlerRef) {
- int CallLevel = Itr.getPathLength() - 2;
- assert(CallLevel >= -1 && "Empty iterator?");
-
- const CallGraphNode *Caller = Itr.getPath(CallLevel + 1), *Callee = nullptr;
- while (CallLevel >= 0) {
- Callee = Caller;
- Caller = Itr.getPath(CallLevel);
- const Expr *CE = findCallExpr(Caller, Callee);
- diag(CE->getBeginLoc(), "function %0 called here from %1",
- DiagnosticIDs::Note)
- << cast<FunctionDecl>(Callee->getDecl())
- << cast<FunctionDecl>(Caller->getDecl());
- --CallLevel;
- }
-
- diag(HandlerRef->getBeginLoc(),
- "function %0 registered here as signal handler", DiagnosticIDs::Note)
- << HandlerDecl;
-}
-
// This is the minimal set of safe functions.
// https://wiki.sei.cmu.edu/confluence/display/c/SIG30-C.+Call+only+asynchronous-safe+functions+within+signal+handlers
-llvm::StringSet<> SignalHandlerCheck::MinimalConformingFunctions{
+constexpr std::initializer_list<llvm::StringRef> MinimalConformingFunctions = {
"signal", "abort", "_Exit", "quick_exit"};
// The POSIX-defined set of safe functions.
@@ -228,7 +22,7 @@ llvm::StringSet<> SignalHandlerCheck::MinimalConformingFunctions{
// mentioned POSIX specification was not updated after 'quick_exit' appeared
// in the C11 standard.
// Also, we want to keep the "minimal set" a subset of the "POSIX set".
-llvm::StringSet<> SignalHandlerCheck::POSIXConformingFunctions{
+constexpr std::initializer_list<llvm::StringRef> POSIXConformingFunctions = {
"_Exit",
"_exit",
"abort",
@@ -422,6 +216,234 @@ llvm::StringSet<> SignalHandlerCheck::POSIXConformingFunctions{
"wmemset",
"write"};
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+
+template <>
+struct OptionEnumMapping<
+ bugprone::SignalHandlerCheck::AsyncSafeFunctionSetKind> {
+ static llvm::ArrayRef<std::pair<
+ bugprone::SignalHandlerCheck::AsyncSafeFunctionSetKind, StringRef>>
+ getEnumMapping() {
+ static constexpr std::pair<
+ bugprone::SignalHandlerCheck::AsyncSafeFunctionSetKind, StringRef>
+ Mapping[] = {
+ {bugprone::SignalHandlerCheck::AsyncSafeFunctionSetKind::Minimal,
+ "minimal"},
+ {bugprone::SignalHandlerCheck::AsyncSafeFunctionSetKind::POSIX,
+ "POSIX"},
+ };
+ return makeArrayRef(Mapping);
+ }
+};
+
+namespace bugprone {
+
+namespace {
+
+/// Returns if a function is declared inside a system header.
+/// These functions are considered to be "standard" (system-provided) library
+/// functions.
+bool isStandardFunction(const FunctionDecl *FD) {
+ // Find a possible redeclaration in system header.
+ // FIXME: Looking at the canonical declaration is not the most exact way
+ // to do this.
+
+ // Most common case will be inclusion directly from a header.
+ // This works fine by using canonical declaration.
+ // a.c
+ // #include <sysheader.h>
+
+ // Next most common case will be extern declaration.
+ // Can't catch this with either approach.
+ // b.c
+ // extern void sysfunc(void);
+
+ // Canonical declaration is the first found declaration, so this works.
+ // c.c
+ // #include <sysheader.h>
+ // extern void sysfunc(void); // redecl won't matter
+
+ // This does not work with canonical declaration.
+ // Probably this is not a frequently used case but may happen (the first
+ // declaration can be in a non-system header for example).
+ // d.c
+ // extern void sysfunc(void); // Canonical declaration, not in system header.
+ // #include <sysheader.h>
+
+ return FD->getASTContext().getSourceManager().isInSystemHeader(
+ FD->getCanonicalDecl()->getLocation());
+}
+
+/// Given a call graph node of a \p Caller function and a \p Callee that is
+/// called from \p Caller, get a \c CallExpr of the corresponding function call.
+/// It is unspecified which call is found if multiple calls exist, but the order
+/// should be deterministic (depend only on the AST).
+Expr *findCallExpr(const CallGraphNode *Caller, const CallGraphNode *Callee) {
+ auto FoundCallee = llvm::find_if(
+ Caller->callees(), [Callee](const CallGraphNode::CallRecord &Call) {
+ return Call.Callee == Callee;
+ });
+ assert(FoundCallee != Caller->end() &&
+ "Callee should be called from the caller function here.");
+ return FoundCallee->CallExpr;
+}
+
+} // namespace
+
+AST_MATCHER(FunctionDecl, isStandardFunction) {
+ return isStandardFunction(&Node);
+}
+
+SignalHandlerCheck::SignalHandlerCheck(StringRef Name,
+ ClangTidyContext *Context)
+ : ClangTidyCheck(Name, Context),
+ AsyncSafeFunctionSet(
+ Options.get("AsyncSafeFunctionSet", AsyncSafeFunctionSetKind::POSIX)),
+ ConformingFunctions(AsyncSafeFunctionSet ==
+ AsyncSafeFunctionSetKind::Minimal
+ ? MinimalConformingFunctions
+ : POSIXConformingFunctions) {}
+
+void SignalHandlerCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
+ Options.store(Opts, "AsyncSafeFunctionSet", AsyncSafeFunctionSet);
+}
+
+bool SignalHandlerCheck::isLanguageVersionSupported(
+ const LangOptions &LangOpts) const {
+ // FIXME: Make the checker useful on C++ code.
+ if (LangOpts.CPlusPlus)
+ return false;
+
+ return true;
+}
+
+void SignalHandlerCheck::registerMatchers(MatchFinder *Finder) {
+ auto SignalFunction = functionDecl(hasAnyName("::signal", "::std::signal"),
+ parameterCountIs(2), isStandardFunction());
+ auto HandlerExpr =
+ declRefExpr(hasDeclaration(functionDecl().bind("handler_decl")),
+ unless(isExpandedFromMacro("SIG_IGN")),
+ unless(isExpandedFromMacro("SIG_DFL")))
+ .bind("handler_expr");
+ Finder->addMatcher(
+ callExpr(callee(SignalFunction), hasArgument(1, HandlerExpr))
+ .bind("register_call"),
+ this);
+}
+
+void SignalHandlerCheck::check(const MatchFinder::MatchResult &Result) {
+ const auto *SignalCall = Result.Nodes.getNodeAs<CallExpr>("register_call");
+ const auto *HandlerDecl =
+ Result.Nodes.getNodeAs<FunctionDecl>("handler_decl");
+ const auto *HandlerExpr = Result.Nodes.getNodeAs<DeclRefExpr>("handler_expr");
+ assert(SignalCall && HandlerDecl && HandlerExpr &&
+ "All of these should exist in a match here.");
+
+ if (CG.size() <= 1) {
+ // Call graph must be populated with the entire TU at the beginning.
+ // (It is possible to add a single function but the functions called from it
+ // are not analysed in this case.)
+ CG.addToCallGraph(const_cast<TranslationUnitDecl *>(
+ HandlerDecl->getTranslationUnitDecl()));
+ assert(CG.size() > 1 &&
+ "There should be at least one function added to call graph.");
+ }
+
+ if (!HandlerDecl->hasBody()) {
+ (void)checkFunction(HandlerDecl, HandlerExpr);
+ // Here checkFunction will put the messages to HandlerExpr.
+ // No need to show a call chain.
+ // Without code body there is nothing more to check.
+ return;
+ }
+
+ CallGraphNode *HandlerNode = CG.getNode(HandlerDecl->getCanonicalDecl());
+ assert(HandlerNode &&
+ "Handler with body should be present in the call graph.");
+ // Start from signal handler and visit every function call.
+ for (auto Itr = llvm::df_begin(HandlerNode), ItrE = llvm::df_end(HandlerNode);
+ Itr != ItrE; ++Itr) {
+ if (const auto *CallF = dyn_cast<FunctionDecl>((*Itr)->getDecl())) {
+ unsigned int PathL = Itr.getPathLength();
+ const Expr *CallOrRef = (PathL == 1)
+ ? HandlerExpr
+ : findCallExpr(Itr.getPath(PathL - 2), *Itr);
+ if (checkFunction(CallF, CallOrRef))
+ reportHandlerChain(Itr, HandlerExpr);
+ }
+ }
+}
+
+bool SignalHandlerCheck::checkFunction(const FunctionDecl *FD,
+ const Expr *CallOrRef) {
+ bool FunctionIsCalled = isa<CallExpr>(CallOrRef);
+
+ if (isStandardFunction(FD)) {
+ if (!isStandardFunctionAsyncSafe(FD)) {
+ diag(CallOrRef->getBeginLoc(), "standard function %0 may not be "
+ "asynchronous-safe; "
+ "%select{using it as|calling it from}1 "
+ "a signal handler may be dangerous")
+ << FD << FunctionIsCalled;
+ return true;
+ }
+ return false;
+ }
+
+ if (!FD->hasBody()) {
+ diag(CallOrRef->getBeginLoc(), "cannot verify that external function %0 is "
+ "asynchronous-safe; "
+ "%select{using it as|calling it from}1 "
+ "a signal handler may be dangerous")
+ << FD << FunctionIsCalled;
+ return true;
+ }
+
+ return false;
+}
+
+bool SignalHandlerCheck::isStandardFunctionAsyncSafe(
+ const FunctionDecl *FD) const {
+ assert(isStandardFunction(FD));
+
+ const IdentifierInfo *II = FD->getIdentifier();
+ // Unnamed functions are not explicitly allowed.
+ if (!II)
+ return false;
+
+ // FIXME: Improve for C++ (check for namespace).
+ if (ConformingFunctions.count(II->getName()))
+ return true;
+
+ return false;
+}
+
+void SignalHandlerCheck::reportHandlerChain(
+ const llvm::df_iterator<clang::CallGraphNode *> &Itr,
+ const DeclRefExpr *HandlerRef) {
+ int CallLevel = Itr.getPathLength() - 2;
+ assert(CallLevel >= -1 && "Empty iterator?");
+
+ const CallGraphNode *Caller = Itr.getPath(CallLevel + 1), *Callee = nullptr;
+ while (CallLevel >= 0) {
+ Callee = Caller;
+ Caller = Itr.getPath(CallLevel);
+ const Expr *CE = findCallExpr(Caller, Callee);
+ diag(CE->getBeginLoc(), "function %0 called here from %1",
+ DiagnosticIDs::Note)
+ << cast<FunctionDecl>(Callee->getDecl())
+ << cast<FunctionDecl>(Caller->getDecl());
+ --CallLevel;
+ }
+
+ diag(HandlerRef->getBeginLoc(),
+ "function %0 registered here as signal handler", DiagnosticIDs::Note)
+ << cast<FunctionDecl>(Caller->getDecl()) << HandlerRef->getSourceRange();
+}
+
} // namespace bugprone
} // namespace tidy
} // namespace clang
diff --git a/clang-tools-extra/clang-tidy/bugprone/SignalHandlerCheck.h b/clang-tools-extra/clang-tidy/bugprone/SignalHandlerCheck.h
index dbc7ac85f2c50..f3457d9de3334 100644
--- a/clang-tools-extra/clang-tidy/bugprone/SignalHandlerCheck.h
+++ b/clang-tools-extra/clang-tidy/bugprone/SignalHandlerCheck.h
@@ -24,7 +24,7 @@ namespace bugprone {
/// http://clang.llvm.org/extra/clang-tidy/checks/bugprone-signal-handler-check.html
class SignalHandlerCheck : public ClangTidyCheck {
public:
- enum class AsyncSafeFunctionSetType { Minimal, POSIX };
+ enum class AsyncSafeFunctionSetKind { Minimal, POSIX };
SignalHandlerCheck(StringRef Name, ClangTidyContext *Context);
void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
@@ -33,22 +33,34 @@ class SignalHandlerCheck : public ClangTidyCheck {
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
private:
- bool isFunctionAsyncSafe(const FunctionDecl *FD) const;
- bool isSystemCallAsyncSafe(const FunctionDecl *FD) const;
- void reportBug(const FunctionDecl *CalledFunction, const Expr *CallOrRef,
- bool DirectHandler);
- void reportHandlerCommon(llvm::df_iterator<clang::CallGraphNode *> Itr,
- const CallExpr *SignalCall,
- const FunctionDecl *HandlerDecl,
- const Expr *HandlerRef);
+ /// Check if a function is allowed as a signal handler.
+ /// Should test the properties of the function, and check in the code body.
+ /// Should not check function calls in the code (this part is done by the call
+ /// graph scan).
+ /// @param FD The function to check. It may or may not have a definition.
+ /// @param CallOrRef Location of the call to this function (in another
+ /// function) or the reference to the function (if it is used as a registered
+ /// signal handler). This is the location where diagnostics are to be placed.
+ /// @return Returns true if a diagnostic was emitted for this function.
+ bool checkFunction(const FunctionDecl *FD, const Expr *CallOrRef);
+ /// Returns true if a standard library function is considered as
+ /// asynchronous-safe.
+ bool isStandardFunctionAsyncSafe(const FunctionDecl *FD) const;
+ /// Add diagnostic notes to show the call chain of functions from a signal
+ /// handler to a function that is called (directly or indirectly) from it.
+ /// Also add a note to the place where the signal handler is registered.
+ /// @param Itr Position during a call graph depth-first iteration. It contains
+ /// the "path" (call chain) from the signal handler to the actual found
+ /// function call.
+ /// @param HandlerRef Reference to the signal handler function where it is
+ /// registered as signal handler.
+ void reportHandlerChain(const llvm::df_iterator<clang::CallGraphNode *> &Itr,
+ const DeclRefExpr *HandlerRef);
clang::CallGraph CG;
- AsyncSafeFunctionSetType AsyncSafeFunctionSet;
- llvm::StringSet<> &ConformingFunctions;
-
- static llvm::StringSet<> MinimalConformingFunctions;
- static llvm::StringSet<> POSIXConformingFunctions;
+ AsyncSafeFunctionSetKind AsyncSafeFunctionSet;
+ const llvm::StringSet<> ConformingFunctions;
};
} // namespace bugprone
diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone-signal-handler-minimal.c b/clang-tools-extra/test/clang-tidy/checkers/bugprone-signal-handler-minimal.c
index 846079a388dfe..7e88534aeb4b8 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/bugprone-signal-handler-minimal.c
+++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone-signal-handler-minimal.c
@@ -10,12 +10,12 @@
void handler_bad1(int) {
_exit(0);
- // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: '_exit' may not be asynchronous-safe; calling it from a signal handler may be dangerous [bugprone-signal-handler]
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: standard function '_exit' may not be asynchronous-safe; calling it from a signal handler may be dangerous [bugprone-signal-handler]
}
void handler_bad2(void *dst, const void *src) {
memcpy(dst, src, 10);
- // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'memcpy' may not be asynchronous-safe; calling it from a signal handler may be dangerous [bugprone-signal-handler]
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: standard function 'memcpy' may not be asynchronous-safe; calling it from a signal handler may be dangerous [bugprone-signal-handler]
}
void handler_good(int) {
diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone-signal-handler-posix.c b/clang-tools-extra/test/clang-tidy/checkers/bugprone-signal-handler-posix.c
index 28a69259bd8d0..4fd8e863fd1af 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/bugprone-signal-handler-posix.c
+++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone-signal-handler-posix.c
@@ -11,7 +11,7 @@
void handler_bad(int) {
printf("1234");
- // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'printf' may not be asynchronous-safe; calling it from a signal handler may be dangerous [bugprone-signal-handler]
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: standard function 'printf' may not be asynchronous-safe; calling it from a signal handler may be dangerous [bugprone-signal-handler]
}
void handler_good(int) {
diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone-signal-handler.c b/clang-tools-extra/test/clang-tidy/checkers/bugprone-signal-handler.c
index 10ee3e815adc7..27f431d432a88 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/bugprone-signal-handler.c
+++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone-signal-handler.c
@@ -5,7 +5,7 @@
#include "stdio.h"
#include "system-other.h"
-// The function should be classified as system call even if there is
+// The function should be classified as standard function even if there is
// declaration the in source file.
// FIXME: The detection works only if the first declaration is in system
// header.
@@ -17,7 +17,7 @@ void f_extern(void);
void handler_printf(int) {
printf("1234");
- // CHECK-NOTES: :[[@LINE-1]]:3: warning: 'printf' may not be asynchronous-safe; calling it from a signal handler may be dangerous [bugprone-signal-handler]
+ // CHECK-NOTES: :[[@LINE-1]]:3: warning: standard function 'printf' may not be asynchronous-safe; calling it from a signal handler may be dangerous [bugprone-signal-handler]
// CHECK-NOTES: :[[@LINE-2]]:3: note: function 'printf' called here from 'handler_printf'
// CHECK-NOTES: :[[@LINE+4]]:18: note: function 'handler_printf' registered here as signal handler
}
@@ -28,7 +28,7 @@ void test_printf(void) {
void handler_extern(int) {
f_extern();
- // CHECK-NOTES: :[[@LINE-1]]:3: warning: 'f_extern' may not be asynchronous-safe; calling it from a signal handler may be dangerous [bugprone-signal-handler]
+ // CHECK-NOTES: :[[@LINE-1]]:3: warning: cannot verify that external function 'f_extern' is asynchronous-safe; calling it from a signal handler may be dangerous [bugprone-signal-handler]
// CHECK-NOTES: :[[@LINE-2]]:3: note: function 'f_extern' called here from 'handler_extern'
// CHECK-NOTES: :[[@LINE+4]]:18: note: function 'handler_extern' registered here as signal handler
}
@@ -51,7 +51,7 @@ void test_ok(void) {
void f_bad(void) {
printf("1234");
- // CHECK-NOTES: :[[@LINE-1]]:3: warning: 'printf' may not be asynchronous-safe; calling it from a signal handler may be dangerous [bugprone-signal-handler]
+ // CHECK-NOTES: :[[@LINE-1]]:3: warning: standard function 'printf' may not be asynchronous-safe; calling it from a signal handler may be dangerous [bugprone-signal-handler]
// CHECK-NOTES: :[[@LINE-2]]:3: note: function 'printf' called here from 'f_bad'
// CHECK-NOTES: :[[@LINE+5]]:3: note: function 'f_bad' called here from 'handler_bad'
// CHECK-NOTES: :[[@LINE+8]]:18: note: function 'handler_bad' registered here as signal handler
@@ -67,7 +67,7 @@ void test_bad(void) {
void f_bad1(void) {
printf("1234");
- // CHECK-NOTES: :[[@LINE-1]]:3: warning: 'printf' may not be asynchronous-safe; calling it from a signal handler may be dangerous [bugprone-signal-handler]
+ // CHECK-NOTES: :[[@LINE-1]]:3: warning: standard function 'printf' may not be asynchronous-safe; calling it from a signal handler may be dangerous [bugprone-signal-handler]
// CHECK-NOTES: :[[@LINE-2]]:3: note: function 'printf' called here from 'f_bad1'
// CHECK-NOTES: :[[@LINE+6]]:3: note: function 'f_bad1' called here from 'f_bad2'
// CHECK-NOTES: :[[@LINE+9]]:3: note: function 'f_bad2' called here from 'handler_bad1'
@@ -99,7 +99,7 @@ void handler_signal(int) {
void handler_false_condition(int) {
if (0)
printf("1234");
- // CHECK-NOTES: :[[@LINE-1]]:5: warning: 'printf' may not be asynchronous-safe; calling it from a signal handler may be dangerous [bugprone-signal-handler]
+ // CHECK-NOTES: :[[@LINE-1]]:5: warning: standard function 'printf' may not be asynchronous-safe; calling it from a signal handler may be dangerous [bugprone-signal-handler]
// CHECK-NOTES: :[[@LINE-2]]:5: note: function 'printf' called here from 'handler_false_condition'
// CHECK-NOTES: :[[@LINE+4]]:18: note: function 'handler_false_condition' registered here as signal handler
}
@@ -110,11 +110,11 @@ void test_false_condition(void) {
void handler_multiple_calls(int) {
f_extern();
- // CHECK-NOTES: :[[@LINE-1]]:3: warning: 'f_extern' may not be asynchronous-safe; calling it from a signal handler may be dangerous [bugprone-signal-handler]
+ // CHECK-NOTES: :[[@LINE-1]]:3: warning: cannot verify that external function 'f_extern' is asynchronous-safe; calling it from a signal handler may be dangerous [bugprone-signal-handler]
// CHECK-NOTES: :[[@LINE-2]]:3: note: function 'f_extern' called here from 'handler_multiple_calls'
// CHECK-NOTES: :[[@LINE+10]]:18: note: function 'handler_multiple_calls' registered here as signal handler
printf("1234");
- // CHECK-NOTES: :[[@LINE-1]]:3: warning: 'printf' may not be asynchronous-safe; calling it from a signal handler may be dangerous [bugprone-signal-handler]
+ // CHECK-NOTES: :[[@LINE-1]]:3: warning: standard function 'printf' may not be asynchronous-safe; calling it from a signal handler may be dangerous [bugprone-signal-handler]
// CHECK-NOTES: :[[@LINE-2]]:3: note: function 'printf' called here from 'handler_multiple_calls'
// CHECK-NOTES: :[[@LINE+6]]:18: note: function 'handler_multiple_calls' registered here as signal handler
f_extern();
@@ -130,17 +130,17 @@ void f_recursive(void);
void handler_recursive(int) {
f_recursive();
printf("");
- // first 'printf' call (in other function) found only
+ // first 'printf' call (in f_recursive) found only
}
void f_recursive(void) {
f_extern();
- // CHECK-NOTES: :[[@LINE-1]]:3: warning: 'f_extern' may not be asynchronous-safe; calling it from a signal handler may be dangerous [bugprone-signal-handler]
+ // CHECK-NOTES: :[[@LINE-1]]:3: warning: cannot verify that external function 'f_extern' is asynchronous-safe; calling it from a signal handler may be dangerous [bugprone-signal-handler]
// CHECK-NOTES: :[[@LINE-2]]:3: note: function 'f_extern' called here from 'f_recursive'
// CHECK-NOTES: :[[@LINE-9]]:3: note: function 'f_recursive' called here from 'handler_recursive'
// CHECK-NOTES: :[[@LINE+10]]:18: note: function 'handler_recursive' registered here as signal handler
printf("");
- // CHECK-NOTES: :[[@LINE-1]]:3: warning: 'printf' may not be asynchronous-safe; calling it from a signal handler may be dangerous [bugprone-signal-handler]
+ // CHECK-NOTES: :[[@LINE-1]]:3: warning: standard function 'printf' may not be asynchronous-safe; calling it from a signal handler may be dangerous [bugprone-signal-handler]
// CHECK-NOTES: :[[@LINE-2]]:3: note: function 'printf' called here from 'f_recursive'
// CHECK-NOTES: :[[@LINE-14]]:3: note: function 'f_recursive' called here from 'handler_recursive'
// CHECK-NOTES: :[[@LINE+5]]:18: note: function 'handler_recursive' registered here as signal handler
@@ -153,7 +153,7 @@ void test_recursive(void) {
void f_multiple_paths(void) {
printf("");
- // CHECK-NOTES: :[[@LINE-1]]:3: warning: 'printf' may not be asynchronous-safe; calling it from a signal handler may be dangerous [bugprone-signal-handler]
+ // CHECK-NOTES: :[[@LINE-1]]:3: warning: standard function 'printf' may not be asynchronous-safe; calling it from a signal handler may be dangerous [bugprone-signal-handler]
// CHECK-NOTES: :[[@LINE-2]]:3: note: function 'printf' called here from 'f_multiple_paths'
// CHECK-NOTES: :[[@LINE+5]]:3: note: function 'f_multiple_paths' called here from 'handler_multiple_paths'
// CHECK-NOTES: :[[@LINE+9]]:18: note: function 'handler_multiple_paths' registered here as signal handler
@@ -184,9 +184,9 @@ void test_other(void) {
signal(SIGINT, _Exit);
signal(SIGINT, other_call);
- // CHECK-NOTES: :[[@LINE-1]]:18: warning: 'other_call' may not be asynchronous-safe; using it as a signal handler may be dangerous [bugprone-signal-handler]
+ // CHECK-NOTES: :[[@LINE-1]]:18: warning: standard function 'other_call' may not be asynchronous-safe; using it as a signal handler may be dangerous [bugprone-signal-handler]
signal(SIGINT, f_extern);
- // CHECK-NOTES: :[[@LINE-1]]:18: warning: 'f_extern' may not be asynchronous-safe; using it as a signal handler may be dangerous [bugprone-signal-handler]
+ // CHECK-NOTES: :[[@LINE-1]]:18: warning: cannot verify that external function 'f_extern' is asynchronous-safe; using it as a signal handler may be dangerous [bugprone-signal-handler]
signal(SIGINT, SIG_IGN);
signal(SIGINT, SIG_DFL);
More information about the cfe-commits
mailing list