NoQ added a comment. A few random comments here and there as i slowly wrap my head around the overall analysis algorithm.
================ Comment at: clang/lib/Analysis/CalledOnceCheck.cpp:47 +using CFGSizedVector = llvm::SmallVector<T, EXPECTED_NUMBER_OF_BASIC_BLOCKS>; +constexpr llvm::StringLiteral CONVENTIONAL_NAME = "completionHandler"; +constexpr llvm::StringLiteral CONVENTIONAL_CONDITIONS[] = { ---------------- Around this point I would have given up and declared `using namespace llvm;`. ================ Comment at: clang/lib/Analysis/CalledOnceCheck.cpp:76 + + // Defined elements should maintain the following properties: + // 1. for any Kind K: NoReturn | K == K ---------------- Maybe `static_assert` at least some of those? ================ Comment at: clang/lib/Analysis/CalledOnceCheck.cpp:135 + +class State { +public: ---------------- Let's say this out loud: The state is defined as a vector of parameter status values. ================ Comment at: clang/lib/Analysis/CalledOnceCheck.cpp:252 + // procedure for a nested expression instead. + const Expr *DeclutteredExpr = E->IgnoreParenCasts(); + return E != DeclutteredExpr ? Visit(DeclutteredExpr) : nullptr; ---------------- Every time I see such code, I want the behavior with respect to implicit lvalue-to-rvalue casts considered or at least explained explicitly. Because they're the ones that make the expression suddenly represent a completely unrelated value and in this regard they're very different from all other kinds of casts. Like, they're not some immaterial bureaucratic clutter to satisfy the type system, they're a huge transformation, basically one of the most important operations in the entire language, an entire freakin' memory access! So i'm curious how exactly do you want your code to behave in this specific case and i want you to comment loudly about that. This is also at least the 3rd implementation of this functionality i've seen in Clang (and there are probably a lot more that i haven't seen) but it sounds like nobody's willing to define what they actually want when they do this precisely enough to figure out if they're all doing the same thing or a different thing. Everybody's like "Oh I just want some `DeclRefExpr` to point to, I don't care what role does it play in the expression" but it occasionally turns out that they do in fact care a lot. So, like, i don't insist on doing this right now but it'd be great to finally figure out what causes people to write such code and whether they have something in common. ================ Comment at: clang/lib/Analysis/CalledOnceCheck.cpp:421 + llvm::Optional<Clarification> VisitBinaryOperator(const BinaryOperator *) { + // We don't want to report on short-curcuit logical operations. + return llvm::None; ---------------- Why not? What if the programmer was a big fan of shell scripts? ================ Comment at: clang/lib/Analysis/CalledOnceCheck.cpp:426 + llvm::Optional<Clarification> VisitStmt(const Stmt *Terminator) { + // If we got here, we didn't have a visit function for more dirived + // classes of statement that this terminator actually belongs to. ---------------- Also there's no test for this, right? Otherwise you would have come up with a better message and this case would have been unnecessary. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D92039/new/ https://reviews.llvm.org/D92039 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits