NoQ added inline comments.

================
Comment at: lib/StaticAnalyzer/Checkers/EnumCastOutOfRangeChecker.cpp:96
+  // Get the value of the expression to cast.
+  const auto ValueToCastOptional =
+      C.getSVal(CE->getSubExpr()).getAs<DefinedOrUnknownSVal>();
----------------
aaron.ballman wrote:
> NoQ wrote:
> > aaron.ballman wrote:
> > > Szelethus wrote:
> > > > Szelethus wrote:
> > > > > ZaMaZaN4iK wrote:
> > > > > > lebedev.ri wrote:
> > > > > > > ZaMaZaN4iK wrote:
> > > > > > > > lebedev.ri wrote:
> > > > > > > > > ZaMaZaN4iK wrote:
> > > > > > > > > > lebedev.ri wrote:
> > > > > > > > > > > ZaMaZaN4iK wrote:
> > > > > > > > > > > > aaron.ballman wrote:
> > > > > > > > > > > > > `const auto *`
> > > > > > > > > > > > Why do we need this change here? If I understand 
> > > > > > > > > > > > correctly, with `const auto*` we also need change 
> > > > > > > > > > > > initializer to 
> > > > > > > > > > > > `C.getSVal(CE->getSubExpr()).getAs<DefinedOrUnknownSVal>().getPointer()`.
> > > > > > > > > > > >  But I don't understand why we need this.
> > > > > > > > > > > Is `ValueToCastOptional` a pointer, a reference, or just 
> > > > > > > > > > > an actual `DefinedOrUnknownSVal`? I can't tell.
> > > > > > > > > > > (sidenote: would be great to have a clang-tidy check for 
> > > > > > > > > > > this.)
> > > > > > > > > > `ValueToCastOptional` is 
> > > > > > > > > > `llvm::Optional<DefinedOrUnknownSVal>`
> > > > > > > > > See, all my guesses were wrong. That is why it should not be 
> > > > > > > > > `auto` at all.
> > > > > > > > I don't agree with you for this case. Honestly it's like a yet 
> > > > > > > > another holywar question. If we are talking only about this 
> > > > > > > > case - here you can see `getAs<DefinedOrUnknownSVal>` part of 
> > > > > > > > the expression. this means clearly (at least for me) that we 
> > > > > > > > get something like `DefinedOrUnknownSVal`. What we get? I just 
> > > > > > > > press hotkey in my favourite IDE/text editor and see that 
> > > > > > > > `getAs` returns `llvm::Optional<DefinedOrUnknownSVal>`. From my 
> > > > > > > > point of view it's clear enough here.
> > > > > > > > 
> > > > > > > > If we are talking more generally about question "When should we 
> > > > > > > > use `auto` at all? " - we can talk, but not here, I think :)
> > > > > > > https://llvm.org/docs/CodingStandards.html#use-auto-type-deduction-to-make-code-more-readable
> > > > > > >  comes to mind.
> > > > > > > > What we get? I just press hotkey in my favourite IDE/text 
> > > > > > > > editor and see that getAs returns 
> > > > > > > > llvm::Optional<DefinedOrUnknownSVal>
> > > > > > > Which hotkey do i need to press to see this here, in the 
> > > > > > > phabricator?
> > > > > > > 
> > > > > > > This really shouldn't be `auto`, if you have to explain that in 
> > > > > > > the variable's name, justify it in review comments.
> > > > > > Ok, didn't know about such LLVM coding standard. Of course, with 
> > > > > > this information I will fix using `auto` here. Thank you.
> > > > > Actually, I disagree. In the Static Analyzer we use `auto` if the 
> > > > > return type is in the name of the expression, and `getAs` may fail, 
> > > > > so it returns an `Optional`. In the case where a nullptr may be 
> > > > > returned to signal failure, `auto *` is used, so I believe that 
> > > > > `auto` is appropriate here.
> > > > But don't change it back now, it doesn't matter a whole lot :D
> > > > Actually, I disagree. In the Static Analyzer we use auto if the return 
> > > > type is in the name of the expression, and getAs may fail, so it 
> > > > returns an Optional. 
> > > 
> > > The static analyzer should be following the same coding standard as the 
> > > rest of the project. This is new code, so it's not matching inappropriate 
> > > styles from older code, so there's really no reason to not match the 
> > > coding standard.
> > > 
> > > > In the case where a nullptr may be returned to signal failure, auto * 
> > > > is used, so I believe that auto is appropriate here.
> > > 
> > > I disagree that `auto` is appropriate here. The amount of confusion about 
> > > the type demonstrates why.
> > I confirm the strong local tradition of preferring `auto` for optional 
> > `SVal`s in new code, and i believe it's well-justified from the overall 
> > coding guideline's point of view. Even if you guys didn't get it right from 
> > the start, the amount of Analyzer-specific experience required to 
> > understand that it's an optional is very minimal and people get used to it 
> > very quickly when they start actively working on the codebase.
> > 
> > On one hand, being a class that combines LLVM custom RTTI with 
> > pass-by-value semantics (i.e., it's like `QualType` when it comes to 
> > passing it around and like `Type` when it comes to casting), optionals are 
> > inevitable for representing `SVal` dynamic cast results.
> > 
> > On the other hand, `SVal` is one of the most common classes of objects in 
> > the Static Analyzer (like, maybe, `Stmt` in Clang; i think a lot of people 
> > who are interested in Static Analyzer more than in the rest of Clang learn 
> > about `SVal`s earlier than about `Stmt`s), and in particular `SVal` casts 
> > are extremely common (around 3-4 `SVal::getAs<T>()` casts per a 
> > path-sensitive checker, not counting `castAs`, ~2x more common than 
> > arithmetic operations over `SVal`s, only ~3x less common than all sorts of 
> > `dyn_cast` in all checkers, including path-insensitive checkers), so it's 
> > something you get used to really quickly.
> > 
> > Writing `Optional<DefinedOrUnknownSVal> DV = 
> > V.getAs<DefinedOrUnknownSVal>();` in a lot of checker callbacks is annoying 
> > for pretty much all checker developers from day 1. This clutters the most 
> > important parts of the checker's logic: transfer functions and the 
> > definition of the error state. Most bugs are in *that* part of the code, 
> > and those bugs are *not* due to using `auto` for casts. Not using `auto` 
> > almost doubles the amount of code you need to write to perform a simple 
> > run-time type check. With a more verbose variable name or a bit more code 
> > around it, it also causes a line break.
> > 
> > And it only provides information that most of the readers either already 
> > know ("`SVal` is a value-type, so it uses optionals"), or memorize 
> > immediately after encountering this pattern once on their first day, or 
> > barely even care (optionals are used like pointers anyway). Being finally 
> > allowed to replace it with just `auto` after migration to C++11 was divine.
> > 
> > So i'm still strongly in favor of keeping this pattern included in the list 
> > of //"places where the type is already obvious from the context"//. This is 
> > the top-1 source of annoying boilerplate in Static Analyzer, and it's as 
> > easy to remember as it is to learn that `dyn_cast<T>(S)` returns a pointer 
> > (or a reference? - you need to look up the definition of `S` to figure this 
> > out, unlike `V.getAs<T>()` that is always an optional for `SVal`s).
> > 
> > P.S. Though i admit that coming up with a less annoying API is also a good 
> > idea :)
> > P.P.S. I guess some sort of `Optional<auto>` would have made everybody 
> > happy. But it's not a thing unfortunately :(
> Thank you for the explanation. However, I'm still not convinced this is 
> supported by the coding style guideline. The point to "places where the type 
> is already obvious from the context" has (in my estimation) only covered 
> places where the type truly is obvious. i.e., it's either spelled out 
> explicitly (`dyn_cast<>`, `getAs<>`, etc) or it's entirely immaterial for 
> understanding (iterators). Whether a value is optional strikes me as highly 
> pertinent information for code reviewers or maintainers to understand because 
> it conveys information about the validity of a value. To me, this is just as 
> important as the distinction between `auto`, `auto *`, and `auto &`, which we 
> make the user spell out in the case of pointers and references. From what I 
> can tell, we also spell out `Optional` pretty consistently elsewhere in the 
> product.
> 
> The rationale that this is a common idiom makes the push-back understandable, 
> but at the same time, use of `auto` where the type is not immediately obvious 
> makes the static analyzer more hostile to get into, especially for people who 
> only stray into this part of the code base periodically (which is one major 
> motivation for having a style guide in the first place).
> 
> I also don't do a ton of work in the static analyzer, so take this feedback 
> with a grain of salt. I certainly don't expect to change the static 
> analyzer's decision here. However, this is also the second time this week 
> I've run into "we don't do that in the static analyzer" and both times have 
> been in response to common review feedback that applies elsewhere in the 
> product and both times have consumed review time from multiple people in 
> order to resolve.
> 
> Ultimately, a style guide is just that -- a guide, not a mandate. It may also 
> be that deviation from the guide here is reasonable, but it does come at a 
> cost. That said, this ship may have already sailed; churning the code to 
> remove use of `auto` comes with its own costs that may not be worth paying.
Like, i mean, until now i always thought of using `auto` for casts, including 
casts of value-types, as of something that the coding guideline explicitly asks 
for, and didn't even consider that it might be a deviation, and that's the 
first time i hear this concern raised. Though now that you point this out, the 
problem with highlighting that it's //the// `llvm::Optional` is indeed an 
unclear situation.

For me as a maintainer, pure `auto` is definitely much easier to read and 
review when used with `getAs`. For a casual reader - i don't know, i accept 
that it might be harder than i imagine.

As usual, i'm happy to be proven wrong and/or accept any decision on that 
matter. To me coding guidelines are definitely above personal preferences.

> conveys information about the validity of a value

This is conveyed via the choice between `getAs` and `castAs`.


https://reviews.llvm.org/D33672



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

Reply via email to