[PATCH] D72362: [clang-tidy] misc-no-recursion: a new check
Artem Dergachev via Phabricator via cfe-commits
cfe-commits at lists.llvm.org
Wed Feb 5 08:31:14 PST 2020
NoQ added a comment.
`CallGraph` changes look nice, i don't see any immediate problems and it's a nice-to-have thing that other users may benefit from (the static analyzer wouldn't though, it's only interested in topological sorting order on the graph). I guess you could have as well stored a `CallExpr` with the `CallRecord`.
Note that there are certain problems with the call graph itself that are caused by how our very AST is structured. Hopefully they won't cause you too much trouble. I outlined some of them in the inline comments.
================
Comment at: clang-tools-extra/clang-tidy/misc/NoRecursionCheck.cpp:21
+
+inline bool operator==(const CallGraphNode::CallRecord &LHS,
+ const CallGraphNode::CallRecord &RHS) {
----------------
lebedev.ri wrote:
> JonasToth wrote:
> > That should be in the `CallGraph` code, adding a private operator overload does not feel right.
> I didn't want to put this into callgraph, because this
> cements the fact that we do not care about sourceloc,
> which may not be true for other users.
> I can put it there, but if told so by it's code owners (@NoQ ?)
Does this need to be `operator==`? It looks like `DenseMap` uses `DenseMapInfo::isEqual` instead, maybe just call it "isEqual" to avoid confusion?
================
Comment at: clang-tools-extra/clang-tidy/misc/NoRecursionCheck.cpp:31
+
+// Specialize DenseMapInfo for clang::CallGraphNode::CallRecord.
+template <> struct DenseMapInfo<clang::CallGraphNode::CallRecord> {
----------------
lebedev.ri wrote:
> JonasToth wrote:
> > That stuff, too.
> (same reasoning)
So what exactly happens if you link together two different translation units with different specializations of `DenseMapInfo<CallRecord>` and start passing such dense maps from one TU to the other?
(ODR violations are definitely not my specialty)
================
Comment at: clang/lib/Analysis/CallGraph.cpp:96-101
void VisitCXXConstructExpr(CXXConstructExpr *E) {
CXXConstructorDecl *Ctor = E->getConstructor();
if (FunctionDecl *Def = Ctor->getDefinition())
- addCalledDecl(Def);
+ addCalledDecl(Def, Ctor->getBeginLoc());
VisitChildren(E);
}
----------------
Note that you're missing out on destructors. They aren't in the call graph because they aren't in the AST to begin with. Like, declarations are there of course, but expressions are mostly missing. A destructor may call another function that will in turn destroy an object of the same type (maybe even the same object), causing recursion.
(side note: we're missing out on destructors too)
================
Comment at: clang/lib/Analysis/CallGraph.cpp:103-106
// Include the evaluation of the default argument.
void VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E) {
Visit(E->getExpr());
}
----------------
Note that if a function `void foo(int x = boo()) { ... }` is invoked as `void bar() { foo(); foo(); }`, you'd get two different-in-every-way call records from the same function `bar()` to the same function `boo()` with the same source location (the location of call-expression `boo()` within the `ParmVarDecl` for `x`). I'm legit curious if this is a problem for your checker.
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D72362/new/
https://reviews.llvm.org/D72362
More information about the cfe-commits
mailing list