balazske added a comment.

I think the name of this checker should be changed. It could in future not only 
check for the SIG30-C rule. (Plan is to include C++ checks too, and SIG31-C 
could be checked in this checker too.) It can be called 
"bugprone-signal-handler" instead?



================
Comment at: clang-tools-extra/clang-tidy/cert/SignalHandlerCheck.cpp:33
+
+  for (const FunctionDecl *D : Node.redecls())
+    if (D->getASTContext().getSourceManager().isInSystemHeader(
----------------
balazske wrote:
> aaron.ballman wrote:
> > balazske wrote:
> > > aaron.ballman wrote:
> > > > balazske wrote:
> > > > > aaron.ballman wrote:
> > > > > > balazske wrote:
> > > > > > > aaron.ballman wrote:
> > > > > > > > I'm not certain I understand why we're looking through the 
> > > > > > > > entire redeclaration chain to see if the function is ever 
> > > > > > > > mentioned in a system header. I was expecting we'd look at the 
> > > > > > > > expansion location of the declaration and see if that's in a 
> > > > > > > > system header, which is already handled by the 
> > > > > > > > `isExpansionInSystemHeader()` matcher. Similar below.
> > > > > > > This function is called from ` SignalHandlerCheck::check` when 
> > > > > > > any function call is found. So the check for system header is 
> > > > > > > needed. It was unclear to me what the "expansion location" means 
> > > > > > > but it seems to work if using that expansion location and 
> > > > > > > checking for system header, instead of this loop. I will update 
> > > > > > > the code.
> > > > > > > This function is called from  SignalHandlerCheck::check when any 
> > > > > > > function call is found. So the check for system header is needed. 
> > > > > > 
> > > > > > The check for the system header isn't what I was concerned by, it 
> > > > > > was the fact that we're walking the entire redeclaration chain to 
> > > > > > see if *any* declaration is in a system header that I don't 
> > > > > > understand the purpose of.
> > > > > > 
> > > > > > > It was unclear to me what the "expansion location" means but it 
> > > > > > > seems to work if using that expansion location and checking for 
> > > > > > > system header, instead of this loop. I will update the code.
> > > > > > 
> > > > > > The spelling location is where the user wrote the code and the 
> > > > > > expansion location is where the macro name is written, but thinking 
> > > > > > on it harder, that shouldn't matter for this situation as either 
> > > > > > location would be in the system header anyway.
> > > > > The function declaration is not often a macro name so there is no 
> > > > > "expansion location" or the same as the original location. My concern 
> > > > > was that if there is a declaration of system call function in a 
> > > > > source file (like `void abort(void);` in .c file) for any reason, we 
> > > > > may find this declaration instead of the one in the header file, if 
> > > > > not looping over the declaration chain.
> > > > > The function declaration is not often a macro name so there is no 
> > > > > "expansion location" or the same as the original location.
> > > > 
> > > > Agreed.
> > > > 
> > > > > My concern was that if there is a declaration of system call function 
> > > > > in a source file (like `void abort(void);` in .c file) for any 
> > > > > reason, we may find this declaration instead of the one in the header 
> > > > > file, if not looping over the declaration chain.
> > > > 
> > > > Typically, when a C user does something like that, it's because they're 
> > > > explicitly *not* including the header file at all (they're just forward 
> > > > declaring the function so they can use it) and so we'd get the logic 
> > > > wrong for them anyway because we'd never find the declaration in the 
> > > > system header.
> > > > 
> > > > Using the canonical declaration is more typical and would realistically 
> > > > fail only in circumstances like forward declaring a system header 
> > > > function and then later including the system header itself. That said, 
> > > > I suppose your approach is defensible enough. Redeclaration chains are 
> > > > hopefully short enough that it isn't a performance hit.
> > > I changed back to the original code to search the entire redeclaration 
> > > chain. Otherwise it can be fooled with declarations before or after 
> > > inclusion of the system header. Such declarations were added to the test 
> > > file (it did not pass if `isExpansionInSystemHeader` was used).
> > I don't think that's necessary (we aren't consistent about whether we check 
> > the entire redecl chain, so I worry about inconsistent behavior between 
> > checks). If you are looking at the canonical declaration (instead of just 
> > any declaration), you'll always be looking at the *first* declaration 
> > encountered, which is generally sufficient.
> > ```
> > // a.c
> > #include <sysheader.h> // Most common case will be inclusion directly from 
> > a header, this works fine
> > 
> > // b.c
> > extern void sysfunc(void); // Next most common case will be extern 
> > declaration, can't catch this with either approach.
> > 
> > // c.c
> > #include <sysheader.h> // Canonical declaration, so this works
> > extern void sysfunc(void); // redecl won't matter
> > 
> > // d.c
> > extern void sysfunc(void); // Canonical declaration, so this fails
> > #include <sysheader.h> // But at the same time, who does this?
> > ```
> > I don't insist on a change, but as a mental note to myself and other 
> > authors, we should probably try to have a more consistent policy here.
> If I understand correctly, the problem is that other checkers already test 
> for "system calls" by checking only the canonical declaration (or 
> "isExpansionInSystemHeader"). It would be better to have a common function or 
> AST matcher for this purpose and update all checkers to use that (even in 
> clang static analyzer). 
My decision would be to use the current code, it is more safe. There is not a 
documented guarantee (?) that canonical declaration is always the first one, 
and the last "d.c" case may happen:

```
// d.h
extern void sysfunc(void); // used by some construct in this file or just 
forgotten here

// d.c
#include "d.h"
#include <sysheader.h>
```


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D87449

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

Reply via email to