[PATCH] D92039: [-Wcalled-once-parameter] Introduce 'called_once' attribute

Valeriy Savchenko via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Wed Dec 23 05:29:08 PST 2020


vsavchenko added inline comments.


================
Comment at: clang/include/clang/Analysis/Analyses/CalledOnceCheck.h:32
+/// \enum SwitchSkipped -- there is no call if none of the cases appies.
+/// \enum LoopEntered -- no call when the loop is entered.
+/// \enum LoopSkipped -- no call when the loop is not entered.
----------------
NoQ wrote:
> Hold up, how can this happen at all without path sensitivity? If the loop is not entered then literally nothing happens, so there can't be a call. If there's no call in either case then probably it's just "there's simply no call at all"?
You can see examples in tests 😉 


================
Comment at: clang/lib/Analysis/CalledOnceCheck.cpp:541-542
+private:
+  NotCalledClarifier(const CFGBlock *Parent, const CFGBlock *SuccInQuestion)
+      : Parent(Parent), SuccInQuestion(SuccInQuestion) {}
+
----------------
NoQ wrote:
> This is one of the more subtle facilities, i really want a comment here a lot more than on the `NamesCollector`. Like, which blocks do you feed into this class? Do i understand correctly that `Parent` is the block at which we decided to emit the warning? And `SuccInQuestion` is its successor on which there was no call? Or on which there was a call? I can probably ultimately figure this out if i read all the code but i would be much happier if there was a comment.
These are correct questions and I will add a comment, but I want to point out that these questions should be asked not about a private constructor (I always consider those as "don't go there girlfriend!").  The only "entry point" to this class,`clarify`, has more reasonable parameter names.


================
Comment at: clang/lib/Analysis/CalledOnceCheck.cpp:560
+                    bool CheckConventionalParameters)
+      : FunctionCFG(FunctionCFG), AC(AC), Handler(Handler),
+        CheckConventionalParameters(CheckConventionalParameters),
----------------
NoQ wrote:
> Why not `FunctionCFG(AC->getCFG())` and omit the CFG parameter? That's the same function, right?
Right, I thought about it!  It is simply how it was done in some other analysis-based warning


================
Comment at: clang/lib/Analysis/CalledOnceCheck.cpp:780
+    //
+    // The following algorithm has the worst case complexity of O(N + E),
+    // where N is the number of basic blocks in FunctionCFG,
----------------
NoQ wrote:
> I'm super used to `V` and `E` for Vertices and Edges in the big-O-notation for graph algorithms, is it just me?
Yep, it is a rudiment of the previous version of this comment.  I'll change it!


================
Comment at: clang/lib/Analysis/CalledOnceCheck.cpp:822
+  /// calling the parameter itself, but rather uses it as the argument.
+  template <class CallLikeExpr>
+  void checkIndirectCall(const CallLikeExpr *CallOrMessage) {
----------------
NoQ wrote:
> Did you consider `AnyCall`? That's a universal wrapper for all kinds of AST calls for exactly these cases. It's not super compile-time but it adds a lot of convenience. (Also uh-oh, its doxygen page seems to be broken). It's ok if you find it unsuitable but i kind of still want to popularize it.
It doesn't seem to have iteration over arguments.


================
Comment at: clang/lib/Analysis/CalledOnceCheck.cpp:1124
+                     (ReturnChildren &&
+                      ReturnChildren->getParent(SuspiciousStmt));
+            }
----------------
NoQ wrote:
> 
Oh, didn't notice that one!


================
Comment at: clang/lib/Analysis/CalledOnceCheck.cpp:1132
+  /// Check if parameter with the given index was ever used.
+  /// NOTE: This function checks only for escapes.
+  bool wasEverUsed(unsigned Index) const {
----------------
NoQ wrote:
> So the contract of this function is "We haven't seen any actual calls, which is why we're wondering", otherwise it's not expected to do what it says it does?
Right!


================
Comment at: clang/lib/Analysis/CalledOnceCheck.cpp:1247
+                               State &ToAlter) const {
+    // Even when the analyzer is technically correct, it is a widespread pattern
+    // not to call completion handlers in some scenarios.  These usually have
----------------
NoQ wrote:
> (:
So true 😄 


================
Comment at: clang/lib/Analysis/CalledOnceCheck.cpp:1310
+  /// a specified status for the given parameter.
+  bool isAnyOfSuccessorsHasStatus(const CFGBlock *Parent,
+                                  unsigned ParameterIndex,
----------------
NoQ wrote:
> "Successor is has status" doesn't sound right, maybe `anySuccessorHasStatus`?
Dern it! I noticed that before, but forgot to change it, thanks!


================
Comment at: clang/lib/Analysis/CalledOnceCheck.cpp:1442
+    // is intentionally not called on this path.
+    if (Cast->getType() == AC.getASTContext().VoidTy) {
+      checkEscapee(Cast->getSubExpr());
----------------
NoQ wrote:
> I feel really bad bringing this up in this context but i guess it kind of makes sense to canonicalize the type first?
Will do


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D92039



More information about the cfe-commits mailing list