NoQ accepted this revision.
NoQ added a comment.
This revision is now accepted and ready to land.

Thanks!



================
Comment at: 
clang/lib/StaticAnalyzer/Checkers/EnumCastOutOfRangeChecker.cpp:94-98
+  // If cast is implicit LValueToRValue, no conversion is taking place,
+  // and therefore no range check is needed.  Don't analyze further.
+  if (CE->getCastKind() == CK_LValueToRValue)
+    return;
+
----------------
chrish_ericsson_atx wrote:
> NoQ wrote:
> > chrish_ericsson_atx wrote:
> > > NoQ wrote:
> > > > chrish_ericsson_atx wrote:
> > > > > NoQ wrote:
> > > > > > If you look at the list of cast kinds, you'll be shocked to see 
> > > > > > ridiculously weird cornercases. Even though lvalue-to-rvalue cast 
> > > > > > definitely stands out (because it's the only one that has very 
> > > > > > little to do with actual casting), i'd still be much more 
> > > > > > comfortable if we *whitelist* the casts that we check, rather than 
> > > > > > blacklist them.
> > > > > > 
> > > > > > Can you take a look at the list and find which casts are we 
> > > > > > actually talking about and hardcode them here?
> > > > > I'm happy to cross-check a list; however, I'm not aware of the list 
> > > > > you are referring to.  Would you mind providing a bit more detail?
> > > > See **[[ 
> > > > https://github.com/llvm-mirror/clang/blob/release_90/include/clang/AST/OperationKinds.def
> > > >  | include/clang/AST/OperationKinds.def ]]**.
> > > Ah.   Okay -- That is a list I've seen before, of course...  :)   
> > > 
> > > Hmm...  regarding whitelisting versus blacklisting...  In this case, it 
> > > seems to me that switching to whitelisting casts that we know we should 
> > > be checking increases the risk that we would introduce a new bug -- 
> > > specifically that we'd accidentally leave out cast type that should have 
> > > been included, which would disable a legitimate check (that some users 
> > > might already be relying on).  By contrast, blacklisting the one cast 
> > > type we know should *not* be checked adds zero new risk and still fixes 
> > > this bug.
> > > 
> > > The sense of risk for me comes partly from being fairly new to working on 
> > > clang AST code -- this is my first change.   It strikes me that if I were 
> > > to feel confident about having the "correct" whitelist, I would have to 
> > > understand every cast type fairly deeply.  Given that I see several cast 
> > > kinds in that list that I know nothing about, I'm concerned with the 
> > > level of effort required, and that I still won't be able to fully 
> > > mitigate the risk.
> > > 
> > > Can you help me understand your rationale for preferring a whitelist in 
> > > this case?  Or, do you feel I've overstated the risk here?  I'm not 
> > > emotionally invested in being proven correct-- just want to learn!  :)
> > > 
> > Generally, if you're not sure, try to not to warn. False positives are 
> > worse than false negatives. It is natural to start with a small set of 
> > cases in which you're sure, and then slowly cover more and more cases as 
> > you investigate further. Leave a comment if you're unsure if you covered 
> > all cases, so that people knew that the code is potentially incomplete and 
> > it's a good place to look for potential improvements.
> > 
> > When you're actively developing the checker, you should rely on your own 
> > experiments with the real-world code that you plan to analyze. When the 
> > checker is still in alpha, it's fine for it to be more aggressive than 
> > necessary, because "you're still experimenting with it", but this will need 
> > to be addressed when the checker is moved out of alpha.
> > 
> > In particular, you have the following tricks at your disposal:
> > - Take a large codebase, run your checker on it (you'll need to do this 
> > regularly anyway) and include the cast kind in the warning text. This will 
> > give you a nice list of casts that you want to support (and probably also a 
> > list of casts that you //don't// want to support).
> > - If you want to be notified of false negatives by your power-users, 
> > instead of a whitelist put an assertion (immediately before emitting the 
> > report) that the cast kind is one of the known cast kinds. This is a bit 
> > evil, of course, but it only affects the users that run analysis with 
> > assertions on, which means custom-built clang, which means power-users that 
> > actively want to report these bugs.
> > - If you don't know what code does a specific AST node kind represent, as a 
> > last resort you can always assert that this kind of node never gets 
> > constructed and see which clang tests fail.
> > - If you want to have some protection against newly introduced cast kinds, 
> > make a `switch (getCastKind())` and don't add a `default:` case into it. 
> > This way anybody who introduces a new cast kind would get a compiler 
> > warning ("unhandled case in switch") and will be forced to take a look at 
> > how this code should handle the new cast kind.
> Okay.  Very fair points.  I've been focused too much on released production 
> code lately-- the mantra there is to be a surgical as possible, and minimize 
> risk of any changes other than the one we are specifically trying to correct. 
>  Of course, that doesn't preclude wider-scope change, but it requires a great 
> deal more time and effort to validate.  In this case, where the code is 
> alpha, and where missing a valid warning is better than issuing a spurious 
> one, it makes sense to do as you've described.  I'll work on that.   Thanks 
> for taking the time to explain in more detail.
> 
> Logistical question now (since this is my first change and review for 
> LLVM/clang code) -- does this review stall until I have updated code (which 
> may not happen quickly due to other work on my plate)?  Or do we greenlight 
> this change, and I just follow it up later with the whitelist version in a 
> separate review?
This change is already is improvement, so feel free to add a `// FIXME: Turn 
this into a whitelist.` and commit :)

Generally, patches don't need to be perfect, but they should be going in the 
right direction and shouldn't cause glaring regressions. A lot of review 
feedback is not in order to block the patch, but instead to help you make it 
even better and share common values and such.


================
Comment at: clang/test/Analysis/enum-cast-out-of-range.c:27-34
+enum unscoped_unspecified_t unused;
+void unusedExpr() {
+    // following line is not something that EnumCastOutOfRangeChecker should 
evaluate.  checker should either ignore this line
+    // or process it without producing any warnings.  However, compilation 
will (and should) still generate a warning having 
+    // nothing to do with this checker.
+    unused; // expected-warning {{expression result unused}}
+}
----------------
chrish_ericsson_atx wrote:
> NoQ wrote:
> > I guess this covers D33672#1537287!
> > 
> > That said, there's one thing about this test that i don't understand. Why 
> > does this AST contain an implicit lvalue-to-rvalue cast at all? This looks 
> > like a (most likely otherwise harmless) bug in the AST; if i understand 
> > correctly, this should be a freestanding `DeclRefExpr`.
> It sure looks like D33672 is the same bug, so yes, I bet it will fix that 
> one.   This fix also addresses https://bugs.llvm.org/show_bug.cgi?id=41388.  
> (Forgive me if there's a way to directly link to bugs.llvm.org with this 
> markup.)
> 
> Not sure about whether the AST should have represented this node as a 
> DeclRefExpr-- that certainly makes some sense, but the LValueToRValue cast 
> isn't really wrong either.   At the end of the day, this statement is 
> useless, so I'm not sure it matters (much) how the AST represents it.  
> Representing it as LValueToRValue cast wouldn't cause side effects, would it? 
> (E.g.,  cause IR to contain explicit dereferencing code?)
Aha, i think i made some sense out of it. That's different in C and C++. In 
particular, if you have a freestanding `*x` where `x` is a null pointer, it's 
UB in C but not in C++ (though `&*x` is explicitly defined to be the same as 
`x` in C, so it's not a UB anymore if you proceed to turn it back into a 
pointer rvalue). I figure, Clang models these different rules by automatically 
wrapping any freestanding lvalue into an implicit lvalue-to-rvalue cast in C 
but not in C++.


Repository:
  rC Clang

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

https://reviews.llvm.org/D66014



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

Reply via email to