aaron.ballman 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>(); ---------------- 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. https://reviews.llvm.org/D33672 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits