aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoman Lebedev <lebedev.ri@gmail.com>2020-02-20 14:06:40 +0300
committerRoman Lebedev <lebedev.ri@gmail.com>2020-02-20 14:17:30 +0300
commitc8f9e526bc5319f2d0beed4012fbf17b11e15161 (patch)
tree834c0d0101798aa6c5230fc427f478d6aee7af23
parentf4fd7dbf85e278eff303514760bff4773a87e601 (diff)
downloadllvm-c8f9e526bc5319f2d0beed4012fbf17b11e15161.zip
llvm-c8f9e526bc5319f2d0beed4012fbf17b11e15161.tar.gz
llvm-c8f9e526bc5319f2d0beed4012fbf17b11e15161.tar.bz2
[clang-tidy] misc-no-recursion: point to the function defs, not decls
Results in slightly better UX. This actually was the initial intent, but it kinda got lost along the way.
-rw-r--r--clang-tools-extra/clang-tidy/misc/NoRecursionCheck.cpp9
-rw-r--r--clang-tools-extra/test/clang-tidy/checkers/misc-no-recursion.cpp52
-rw-r--r--clang/include/clang/Analysis/CallGraph.h4
3 files changed, 34 insertions, 31 deletions
diff --git a/clang-tools-extra/clang-tidy/misc/NoRecursionCheck.cpp b/clang-tools-extra/clang-tidy/misc/NoRecursionCheck.cpp
index cfbd654..d382501d 100644
--- a/clang-tools-extra/clang-tidy/misc/NoRecursionCheck.cpp
+++ b/clang-tools-extra/clang-tidy/misc/NoRecursionCheck.cpp
@@ -204,9 +204,8 @@ void NoRecursionCheck::handleSCC(ArrayRef<CallGraphNode *> SCC) {
// First of all, call out every stongly connected function.
for (CallGraphNode *N : SCC) {
- Decl *D = N->getDecl();
- diag(D->getLocation(), "function %0 is within a recursive call chain")
- << cast<NamedDecl>(D);
+ FunctionDecl *D = N->getDefinition();
+ diag(D->getLocation(), "function %0 is within a recursive call chain") << D;
}
// Now, SCC only tells us about strongly connected function declarations in
@@ -228,13 +227,13 @@ void NoRecursionCheck::handleSCC(ArrayRef<CallGraphNode *> SCC) {
assert(CyclicCallStack.size() >= 2 && "Cycle requires at least 2 frames");
// Which function we decided to be the entry point that lead to the recursion?
- Decl *CycleEntryFn = CyclicCallStack.front().Callee->getDecl();
+ FunctionDecl *CycleEntryFn = CyclicCallStack.front().Callee->getDefinition();
// And now, for ease of understanding, let's print the call sequence that
// forms the cycle in question.
diag(CycleEntryFn->getLocation(),
"example recursive call chain, starting from function %0",
DiagnosticIDs::Note)
- << cast<NamedDecl>(CycleEntryFn);
+ << CycleEntryFn;
for (int CurFrame = 1, NumFrames = CyclicCallStack.size();
CurFrame != NumFrames; ++CurFrame) {
CallGraphNode::CallRecord PrevNode = CyclicCallStack[CurFrame - 1];
diff --git a/clang-tools-extra/test/clang-tidy/checkers/misc-no-recursion.cpp b/clang-tools-extra/test/clang-tidy/checkers/misc-no-recursion.cpp
index 0cfacfe..e323c8a 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/misc-no-recursion.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/misc-no-recursion.cpp
@@ -60,12 +60,12 @@ void indirect_recursion() {
conditionally_executed();
}
+// CHECK-NOTES: :[[@LINE-9]]:6: warning: function 'conditionally_executed' is within a recursive call chain [misc-no-recursion]
+// CHECK-NOTES: :[[@LINE-6]]:6: note: example recursive call chain, starting from function 'indirect_recursion'
+// CHECK-NOTES: :[[@LINE-5]]:5: note: Frame #1: function 'indirect_recursion' calls function 'conditionally_executed' here:
+// CHECK-NOTES: :[[@LINE-10]]:5: note: Frame #2: function 'conditionally_executed' calls function 'indirect_recursion' here:
+// CHECK-NOTES: :[[@LINE-11]]:5: note: ... which was the starting point of the recursive call chain; there may be other cycles
// CHECK-NOTES: :[[@LINE-10]]:6: warning: function 'indirect_recursion' is within a recursive call chain [misc-no-recursion]
-// CHECK-NOTES: :[[@LINE-10]]:6: warning: function 'conditionally_executed' is within a recursive call chain [misc-no-recursion]
-// CHECK-NOTES: :[[@LINE-12]]:6: note: example recursive call chain, starting from function 'indirect_recursion'
-// CHECK-NOTES: :[[@LINE-6]]:5: note: Frame #1: function 'indirect_recursion' calls function 'conditionally_executed' here:
-// CHECK-NOTES: :[[@LINE-11]]:5: note: Frame #2: function 'conditionally_executed' calls function 'indirect_recursion' here:
-// CHECK-NOTES: :[[@LINE-12]]:5: note: ... which was the starting point of the recursive call chain; there may be other cycles
void taint();
void maybe_selfrecursion_with_two_backedges() {
@@ -97,13 +97,13 @@ void indirect_recursion_with_alternatives() {
conditionally_executed_choice_1();
}
-// CHECK-NOTES: :[[@LINE-16]]:6: warning: function 'indirect_recursion_with_alternatives' is within a recursive call chain [misc-no-recursion]
-// CHECK-NOTES: :[[@LINE-16]]:6: warning: function 'conditionally_executed_choice_0' is within a recursive call chain [misc-no-recursion]
-// CHECK-NOTES: :[[@LINE-18]]:6: note: example recursive call chain, starting from function 'indirect_recursion_with_alternatives'
-// CHECK-NOTES: :[[@LINE-8]]:5: note: Frame #1: function 'indirect_recursion_with_alternatives' calls function 'conditionally_executed_choice_0' here:
-// CHECK-NOTES: :[[@LINE-17]]:5: note: Frame #2: function 'conditionally_executed_choice_0' calls function 'indirect_recursion_with_alternatives' here:
-// CHECK-NOTES: :[[@LINE-18]]:5: note: ... which was the starting point of the recursive call chain; there may be other cycles
-// CHECK-NOTES: :[[@LINE-17]]:6: warning: function 'conditionally_executed_choice_1' is within a recursive call chain [misc-no-recursion]
+// CHECK-NOTES: :[[@LINE-15]]:6: warning: function 'conditionally_executed_choice_0' is within a recursive call chain [misc-no-recursion]
+// CHECK-NOTES: :[[@LINE-8]]:6: note: example recursive call chain, starting from function 'indirect_recursion_with_alternatives'
+// CHECK-NOTES: :[[@LINE-7]]:5: note: Frame #1: function 'indirect_recursion_with_alternatives' calls function 'conditionally_executed_choice_0' here:
+// CHECK-NOTES: :[[@LINE-16]]:5: note: Frame #2: function 'conditionally_executed_choice_0' calls function 'indirect_recursion_with_alternatives' here:
+// CHECK-NOTES: :[[@LINE-17]]:5: note: ... which was the starting point of the recursive call chain; there may be other cycles
+// CHECK-NOTES: :[[@LINE-16]]:6: warning: function 'conditionally_executed_choice_1' is within a recursive call chain [misc-no-recursion]
+// CHECK-NOTES: :[[@LINE-13]]:6: warning: function 'indirect_recursion_with_alternatives' is within a recursive call chain [misc-no-recursion]
static void indirect_recursion_with_depth2();
static void conditionally_executed_depth1() {
@@ -119,14 +119,14 @@ void indirect_recursion_with_depth2() {
conditionally_executed_depth0();
}
-// CHECK-NOTES: :[[@LINE-14]]:13: warning: function 'indirect_recursion_with_depth2' is within a recursive call chain [misc-no-recursion]
-// CHECK-NOTES: :[[@LINE-14]]:13: warning: function 'conditionally_executed_depth1' is within a recursive call chain [misc-no-recursion]
-// CHECK-NOTES: :[[@LINE-11]]:13: note: example recursive call chain, starting from function 'conditionally_executed_depth0'
-// CHECK-NOTES: :[[@LINE-10]]:5: note: Frame #1: function 'conditionally_executed_depth0' calls function 'conditionally_executed_depth1' here:
-// CHECK-NOTES: :[[@LINE-15]]:5: note: Frame #2: function 'conditionally_executed_depth1' calls function 'indirect_recursion_with_depth2' here:
-// CHECK-NOTES: :[[@LINE-8]]:5: note: Frame #3: function 'indirect_recursion_with_depth2' calls function 'conditionally_executed_depth0' here:
-// CHECK-NOTES: :[[@LINE-9]]:5: note: ... which was the starting point of the recursive call chain; there may be other cycles
-// CHECK-NOTES: :[[@LINE-16]]:13: warning: function 'conditionally_executed_depth0' is within a recursive call chain [misc-no-recursion]
+// CHECK-NOTES: :[[@LINE-13]]:13: warning: function 'conditionally_executed_depth1' is within a recursive call chain [misc-no-recursion]
+// CHECK-NOTES: :[[@LINE-10]]:13: note: example recursive call chain, starting from function 'conditionally_executed_depth0'
+// CHECK-NOTES: :[[@LINE-9]]:5: note: Frame #1: function 'conditionally_executed_depth0' calls function 'conditionally_executed_depth1' here:
+// CHECK-NOTES: :[[@LINE-14]]:5: note: Frame #2: function 'conditionally_executed_depth1' calls function 'indirect_recursion_with_depth2' here:
+// CHECK-NOTES: :[[@LINE-7]]:5: note: Frame #3: function 'indirect_recursion_with_depth2' calls function 'conditionally_executed_depth0' here:
+// CHECK-NOTES: :[[@LINE-8]]:5: note: ... which was the starting point of the recursive call chain; there may be other cycles
+// CHECK-NOTES: :[[@LINE-15]]:13: warning: function 'conditionally_executed_depth0' is within a recursive call chain [misc-no-recursion]
+// CHECK-NOTES: :[[@LINE-12]]:6: warning: function 'indirect_recursion_with_depth2' is within a recursive call chain [misc-no-recursion]
int boo();
void foo(int x = boo()) {}
@@ -139,12 +139,12 @@ int boo() {
return 0;
}
-// CHECK-NOTES: :[[@LINE-11]]:5: warning: function 'boo' is within a recursive call chain [misc-no-recursion]
-// CHECK-NOTES: :[[@LINE-10]]:6: warning: function 'bar' is within a recursive call chain [misc-no-recursion]
-// CHECK-NOTES: :[[@LINE-13]]:5: note: example recursive call chain, starting from function 'boo'
-// CHECK-NOTES: :[[@LINE-7]]:3: note: Frame #1: function 'boo' calls function 'bar' here:
-// CHECK-NOTES: :[[@LINE-14]]:18: note: Frame #2: function 'bar' calls function 'boo' here:
-// CHECK-NOTES: :[[@LINE-15]]:18: note: ... which was the starting point of the recursive call chain; there may be other cycles
+// CHECK-NOTES: :[[@LINE-9]]:6: warning: function 'bar' is within a recursive call chain [misc-no-recursion]
+// CHECK-NOTES: :[[@LINE-6]]:5: note: example recursive call chain, starting from function 'boo'
+// CHECK-NOTES: :[[@LINE-6]]:3: note: Frame #1: function 'boo' calls function 'bar' here:
+// CHECK-NOTES: :[[@LINE-13]]:18: note: Frame #2: function 'bar' calls function 'boo' here:
+// CHECK-NOTES: :[[@LINE-14]]:18: note: ... which was the starting point of the recursive call chain; there may be other cycles
+// CHECK-NOTES: :[[@LINE-10]]:5: warning: function 'boo' is within a recursive call chain [misc-no-recursion]
int recursion_through_function_ptr() {
auto *ptr = &recursion_through_function_ptr;
diff --git a/clang/include/clang/Analysis/CallGraph.h b/clang/include/clang/Analysis/CallGraph.h
index 0e56d1c..0410503 100644
--- a/clang/include/clang/Analysis/CallGraph.h
+++ b/clang/include/clang/Analysis/CallGraph.h
@@ -189,6 +189,10 @@ public:
Decl *getDecl() const { return FD; }
+ FunctionDecl *getDefinition() const {
+ return getDecl()->getAsFunction()->getDefinition();
+ }
+
void print(raw_ostream &os) const;
void dump() const;
};