[PATCH] D118370: [clang-tidy] bugprone-signal-handler: Code refactor (NFC)

2022-01-28 Thread Balázs Kéri via Phabricator via cfe-commits
balazske marked 2 inline comments as done.
balazske added inline comments.



Comment at: clang-tools-extra/clang-tidy/bugprone/SignalHandlerCheck.cpp:151
   CallGraphNode *HandlerNode = CG.getNode(HandlerDecl);
-  // Signal handler can be external but not unsafe, no call graph in this case.
-  if (!HandlerNode)
-return;
+  assert(HandlerNode &&
+ "Handler has body, should be present in the call graph.");

balazske wrote:
> There are problems with this approach in C++ code.
The call graph adds nodes for the canonical declaration only. When getting a 
node it works only with the CanonicalDecl unless the `CallGraph` code is 
changed (it seems to be worth to do this change).



Comment at: clang-tools-extra/clang-tidy/bugprone/SignalHandlerCheck.cpp:167
+   const Expr *CallOrRef) {
+  const bool FunctionIsCalled = isa(CallOrRef);
+

njames93 wrote:
> This can probably just be inlined into its only use.
The value is used now multiple times. (But maybe the `diag` call can be put 
into a lambda later.)


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D118370/new/

https://reviews.llvm.org/D118370

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D118370: [clang-tidy] bugprone-signal-handler: Code refactor (NFC)

2022-01-28 Thread Balázs Kéri via Phabricator via cfe-commits
balazske updated this revision to Diff 404040.
balazske added a comment.

Even more simplification, added documentation.
Text of bug reports is more detailed, no NFC now.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D118370/new/

https://reviews.llvm.org/D118370

Files:
  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.c

Index: clang-tools-extra/test/clang-tidy/checkers/bugprone-signal-handler.c
===
--- clang-tools-extra/test/clang-tidy/checkers/bugprone-signal-handler.c
+++ clang-tools-extra/test/clang-tidy/checkers/bugprone-signal-handler.c
@@ -17,7 +17,7 @@
 
 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: system call '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 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: can not verify if 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 f_bad() {
   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: system call '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 f_bad1() {
   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: system call '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_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: system call '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 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: can not verify if 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: system call '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' 

[PATCH] D118370: [clang-tidy] bugprone-signal-handler: Code refactor (NFC)

2022-01-27 Thread Nathan James via Phabricator via cfe-commits
njames93 added inline comments.



Comment at: clang-tools-extra/clang-tidy/bugprone/SignalHandlerCheck.cpp:167
+   const Expr *CallOrRef) {
+  const bool FunctionIsCalled = isa(CallOrRef);
+

This can probably just be inlined into its only use.



Comment at: clang-tools-extra/clang-tidy/bugprone/SignalHandlerCheck.h:36
 private:
+  bool checkFunction(const FunctionDecl *FD, const Expr *CallOrRef);
   bool isFunctionAsyncSafe(const FunctionDecl *FD) const;

This isn't a very descriptive name, and the bool return value conveys no 
meaning. Probably could do with some documentation.



Comment at: clang-tools-extra/clang-tidy/bugprone/SignalHandlerCheck.h:46-49
   llvm::StringSet<> 
 
   static llvm::StringSet<> MinimalConformingFunctions;
   static llvm::StringSet<> POSIXConformingFunctions;

While you're refactoring, those static StringSets really belong in the 
implementation file, and the ConformingFunctions should be a const ref.

However global destructores are kind of a taboo thing, Maybe there is case to 
change them into a sorted array and binary search them to see if a function is 
conforming.
Probably wouldn't advise using TableGens StringMatcher to build this 
functionality as that maybe a little too far.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D118370/new/

https://reviews.llvm.org/D118370

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D118370: [clang-tidy] bugprone-signal-handler: Code refactor (NFC)

2022-01-27 Thread Balázs Kéri via Phabricator via cfe-commits
balazske added inline comments.



Comment at: clang-tools-extra/clang-tidy/bugprone/SignalHandlerCheck.cpp:146
+  if (!HandlerDecl->hasBody()) {
+checkFunction(HandlerDecl, HandlerExpr);
 return;

LegalizeAdulthood wrote:
> Why do we ignore the return value of `checkFunction` here?
> 
> Also, the name doesn't reveal to me why the result is true
> or false, e.g. it acts like a predicate but its name doesn't ask
> a question.
The function returns if a problem (warning) was found. At the next call site it 
is used to display additional notes, but here it is not needed. A better name 
can be `isFunctionValidSignalHandler` but the function checks not only a fact, 
it generates the warnings too.



Comment at: clang-tools-extra/clang-tidy/bugprone/SignalHandlerCheck.cpp:151
   CallGraphNode *HandlerNode = CG.getNode(HandlerDecl);
-  // Signal handler can be external but not unsafe, no call graph in this case.
-  if (!HandlerNode)
-return;
+  assert(HandlerNode &&
+ "Handler has body, should be present in the call graph.");

There are problems with this approach in C++ code.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D118370/new/

https://reviews.llvm.org/D118370

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D118370: [clang-tidy] bugprone-signal-handler: Code refactor (NFC)

2022-01-27 Thread Richard via Phabricator via cfe-commits
LegalizeAdulthood added inline comments.



Comment at: clang-tools-extra/clang-tidy/bugprone/SignalHandlerCheck.cpp:146
+  if (!HandlerDecl->hasBody()) {
+checkFunction(HandlerDecl, HandlerExpr);
 return;

Why do we ignore the return value of `checkFunction` here?

Also, the name doesn't reveal to me why the result is true
or false, e.g. it acts like a predicate but its name doesn't ask
a question.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D118370/new/

https://reviews.llvm.org/D118370

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D118370: [clang-tidy] bugprone-signal-handler: Code refactor (NFC)

2022-01-27 Thread Balázs Kéri via Phabricator via cfe-commits
balazske created this revision.
Herald added subscribers: carlosgalvezp, steakhal, martong, gamesh411, 
Szelethus, dkrupp, xazax.hun.
balazske requested review of this revision.
Herald added a project: clang-tools-extra.
Herald added a subscriber: cfe-commits.

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.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D118370

Files:
  clang-tools-extra/clang-tidy/bugprone/SignalHandlerCheck.cpp
  clang-tools-extra/clang-tidy/bugprone/SignalHandlerCheck.h


Index: clang-tools-extra/clang-tidy/bugprone/SignalHandlerCheck.h
===
--- clang-tools-extra/clang-tidy/bugprone/SignalHandlerCheck.h
+++ clang-tools-extra/clang-tidy/bugprone/SignalHandlerCheck.h
@@ -33,14 +33,12 @@
   void check(const ast_matchers::MatchFinder::MatchResult ) override;
 
 private:
+  bool checkFunction(const FunctionDecl *FD, const Expr *CallOrRef);
   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 Itr,
-   const CallExpr *SignalCall,
-   const FunctionDecl *HandlerDecl,
-   const Expr *HandlerRef);
+  void reportHandlerChain(const llvm::df_iterator ,
+  const FunctionDecl *HandlerDecl,
+  const Expr *HandlerRef);
 
   clang::CallGraph CG;
 
Index: clang-tools-extra/clang-tidy/bugprone/SignalHandlerCheck.cpp
===
--- clang-tools-extra/clang-tidy/bugprone/SignalHandlerCheck.cpp
+++ clang-tools-extra/clang-tidy/bugprone/SignalHandlerCheck.cpp
@@ -142,30 +142,41 @@
"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);
+  if (!HandlerDecl->hasBody()) {
+checkFunction(HandlerDecl, HandlerExpr);
 return;
   }
 
   CallGraphNode *HandlerNode = CG.getNode(HandlerDecl);
-  // Signal handler can be external but not unsafe, no call graph in this case.
-  if (!HandlerNode)
-return;
+  assert(HandlerNode &&
+ "Handler has 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) {
 const auto *CallF = dyn_cast((*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);
+if (CallF && CallF != HandlerDecl) {
+  if (checkFunction(
+  CallF, findCallExpr(Itr.getPath(Itr.getPathLength() - 2), *Itr)))
+reportHandlerChain(Itr, HandlerDecl, HandlerExpr);
 }
   }
 }
 
+bool SignalHandlerCheck::checkFunction(const FunctionDecl *FD,
+   const Expr *CallOrRef) {
+  const bool FunctionIsCalled = isa(CallOrRef);
+
+  if (!isFunctionAsyncSafe(FD)) {
+diag(CallOrRef->getBeginLoc(), "%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;
+}
+
 bool SignalHandlerCheck::isFunctionAsyncSafe(const FunctionDecl *FD) const {
   if (isSystemCall(FD))
 return isSystemCallAsyncSafe(FD);
@@ -186,16 +197,8 @@
   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 Itr, const CallExpr *SignalCall,
+void SignalHandlerCheck::reportHandlerChain(
+const llvm::df_iterator ,
 const FunctionDecl *HandlerDecl, const Expr *HandlerRef) {
   int CallLevel = Itr.getPathLength() - 2;
   assert(CallLevel >= -1 && "Empty iterator?");


Index: clang-tools-extra/clang-tidy/bugprone/SignalHandlerCheck.h
===
---