[clang] [analyzer] Allow recursive functions to be trivial. (PR #91876)

2024-05-24 Thread Ryosuke Niwa via cfe-commits

https://github.com/rniwa closed https://github.com/llvm/llvm-project/pull/91876
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [analyzer] Allow recursive functions to be trivial. (PR #91876)

2024-05-24 Thread Ryosuke Niwa via cfe-commits

rniwa wrote:

Thanks for the review!

https://github.com/llvm/llvm-project/pull/91876
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [analyzer] Allow recursive functions to be trivial. (PR #91876)

2024-05-24 Thread Artem Dergachev via cfe-commits

https://github.com/haoNoQ approved this pull request.

Ok LGTM then!

https://github.com/llvm/llvm-project/pull/91876
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [analyzer] Allow recursive functions to be trivial. (PR #91876)

2024-05-23 Thread Ryosuke Niwa via cfe-commits

https://github.com/rniwa updated https://github.com/llvm/llvm-project/pull/91876

>From e40017a2750ee39bfd1a87b5ddea620076bc4419 Mon Sep 17 00:00:00 2001
From: Ryosuke Niwa 
Date: Sat, 11 May 2024 20:18:52 -0700
Subject: [PATCH 1/6] [analyzer] Allow recursive functions to be trivial.

---
 .../Checkers/WebKit/PtrTypesSemantics.cpp  | 18 +-
 .../Checkers/WebKit/uncounted-obj-arg.cpp  |  6 ++
 2 files changed, 15 insertions(+), 9 deletions(-)

diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp 
b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
index 5c797d5233089..2a4da9eeaee6d 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
@@ -517,11 +517,9 @@ class TrivialFunctionAnalysisVisitor
 
 bool TrivialFunctionAnalysis::isTrivialImpl(
 const Decl *D, TrivialFunctionAnalysis::CacheTy ) {
-  // If the function isn't in the cache, conservatively assume that
-  // it's not trivial until analysis completes. This makes every recursive
-  // function non-trivial. This also guarantees that each function
-  // will be scanned at most once.
-  auto [It, IsNew] = Cache.insert(std::make_pair(D, false));
+  // Treat every recursive function as trivial until otherwise proven.
+  // This guarantees each function is evaluated at most once.
+  auto [It, IsNew] = Cache.insert(std::make_pair(D, true));
   if (!IsNew)
 return It->second;
 
@@ -535,12 +533,14 @@ bool TrivialFunctionAnalysis::isTrivialImpl(
   }
 
   const Stmt *Body = D->getBody();
-  if (!Body)
-return false;
+  if (!Body) {
+Cache[D] = false;
+return false;
+  }
 
   bool Result = V.Visit(Body);
-  if (Result)
-Cache[D] = true;
+  if (!Result)
+Cache[D] = false;
 
   return Result;
 }
diff --git a/clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp 
b/clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp
index 96986631726fe..18af9e17f78b0 100644
--- a/clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp
+++ b/clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp
@@ -231,6 +231,8 @@ class RefCounted {
   void method();
   void someFunction();
   int otherFunction();
+  unsigned recursiveFunction(int n) { return !n ? 1 : recursiveFunction(n - 
1);  }
+  unsigned recursiveComplexFunction(int n) { return !n ? otherFunction() : 
recursiveComplexFunction(n - 1);  }
 
   int trivial1() { return 123; }
   float trivial2() { return 0.3; }
@@ -498,6 +500,10 @@ class UnrelatedClass {
 RefCounted::singleton().trivial18(); // no-warning
 RefCounted::singleton().someFunction(); // no-warning
 
+getFieldTrivial().recursiveFunction(7); // no-warning
+getFieldTrivial().recursiveComplexFunction(9);
+// expected-warning@-1{{Call argument for 'this' parameter is uncounted 
and unsafe}}
+
 getFieldTrivial().someFunction();
 // expected-warning@-1{{Call argument for 'this' parameter is uncounted 
and unsafe}}
 getFieldTrivial().nonTrivial1();

>From 5d7a259c0209a8cbb70c2718518905669db2a885 Mon Sep 17 00:00:00 2001
From: Ryosuke Niwa 
Date: Sat, 11 May 2024 20:24:10 -0700
Subject: [PATCH 2/6] Fix formatting.

---
 clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp 
b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
index 2a4da9eeaee6d..449e56be9984d 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
@@ -535,7 +535,7 @@ bool TrivialFunctionAnalysis::isTrivialImpl(
   const Stmt *Body = D->getBody();
   if (!Body) {
 Cache[D] = false;
-return false;
+return false;
   }
 
   bool Result = V.Visit(Body);

>From 9971dcdebc160acb708b548bf67ef5efa76d4fe0 Mon Sep 17 00:00:00 2001
From: Ryosuke Niwa 
Date: Sun, 12 May 2024 15:15:33 -0700
Subject: [PATCH 3/6] Fix the TrivialFunctionAnalysis::isTrivialImpl for
 mutually recursive functions.

Instead of assuming every function to be initially trivial, we explicitly track
the set of functions that we're currently visting. When one of the currently 
visited
function is determined to be not trivial, we clear this set to signal that all
mutually recursive functions are non-trivial. We conclude that a function is 
trivial
when Visit() call on the function body returned true **AND** the set still 
contains
the function.

To implement this new algorithm, a new public function, IsFunctionTrivial,
is introduced to TrivialFunctionAnalysisVisitor, and various Visit functions in
TrivialFunctionAnalysisVisitor has been updated to use this function instead of
TrivialFunctionAnalysis::isTrivialImpl, which is now a wrapper for the function.
---
 .../Checkers/WebKit/PtrTypesSemantics.cpp | 69 +++
 .../Checkers/WebKit/uncounted-obj-arg.cpp   

[clang] [analyzer] Allow recursive functions to be trivial. (PR #91876)

2024-05-23 Thread Ryosuke Niwa via cfe-commits


@@ -231,6 +231,15 @@ class RefCounted {
   void method();
   void someFunction();
   int otherFunction();
+  unsigned recursiveTrivialFunction(int n) { return !n ? 1 : 
recursiveTrivialFunction(n - 1);  }
+  unsigned recursiveComplexFunction(int n) { return !n ? otherFunction() : 
recursiveComplexFunction(n - 1);  }
+  unsigned mutuallyRecursiveFunction1(int n) { return n < 0 ? 1 : (n % 2 ? 
mutuallyRecursiveFunction2(n - 2) : mutuallyRecursiveFunction1(n - 1)); }
+  unsigned mutuallyRecursiveFunction2(int n) { return n < 0 ? 1 : (n % 3 ? 
mutuallyRecursiveFunction2(n - 3) : mutuallyRecursiveFunction1(n - 2)); }
+  unsigned mutuallyRecursiveFunction3(int n) { return n < 0 ? 1 : (n % 5 ? 
mutuallyRecursiveFunction3(n - 5) : mutuallyRecursiveFunction4(n - 3)); }
+  unsigned mutuallyRecursiveFunction4(int n) { return n < 0 ? 1 : (n % 7 ? 
otherFunction() : mutuallyRecursiveFunction3(n - 3)); }
+  unsigned mutuallyRecursiveFunction5(unsigned n) { return n > 100 ? 2 : (n % 
2 ? mutuallyRecursiveFunction5(n + 1) : mutuallyRecursiveFunction6(n + 2)); }

rniwa wrote:

Sure, added.

https://github.com/llvm/llvm-project/pull/91876
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [analyzer] Allow recursive functions to be trivial. (PR #91876)

2024-05-23 Thread Artem Dergachev via cfe-commits

https://github.com/haoNoQ commented:

> If that is an issue, one way to do this "properly" would be to create a graph

Note that we do have a 
[`CallGraph`](https://clang.llvm.org/doxygen/classclang_1_1CallGraph.html) 
class. The static analyzer uses it to identify top-level entry points. It 
doesn't look like it has a readily available solution for identifying recursive 
functions. But it may be a good idea to simply use the class and implement it 
there.

https://github.com/llvm/llvm-project/pull/91876
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [analyzer] Allow recursive functions to be trivial. (PR #91876)

2024-05-23 Thread Artem Dergachev via cfe-commits


@@ -231,6 +231,15 @@ class RefCounted {
   void method();
   void someFunction();
   int otherFunction();
+  unsigned recursiveTrivialFunction(int n) { return !n ? 1 : 
recursiveTrivialFunction(n - 1);  }
+  unsigned recursiveComplexFunction(int n) { return !n ? otherFunction() : 
recursiveComplexFunction(n - 1);  }
+  unsigned mutuallyRecursiveFunction1(int n) { return n < 0 ? 1 : (n % 2 ? 
mutuallyRecursiveFunction2(n - 2) : mutuallyRecursiveFunction1(n - 1)); }
+  unsigned mutuallyRecursiveFunction2(int n) { return n < 0 ? 1 : (n % 3 ? 
mutuallyRecursiveFunction2(n - 3) : mutuallyRecursiveFunction1(n - 2)); }
+  unsigned mutuallyRecursiveFunction3(int n) { return n < 0 ? 1 : (n % 5 ? 
mutuallyRecursiveFunction3(n - 5) : mutuallyRecursiveFunction4(n - 3)); }
+  unsigned mutuallyRecursiveFunction4(int n) { return n < 0 ? 1 : (n % 7 ? 
otherFunction() : mutuallyRecursiveFunction3(n - 3)); }
+  unsigned mutuallyRecursiveFunction5(unsigned n) { return n > 100 ? 2 : (n % 
2 ? mutuallyRecursiveFunction5(n + 1) : mutuallyRecursiveFunction6(n + 2)); }

haoNoQ wrote:

I think it may be a good idea to add a direct test for @MitalAshok's example.
```c++
void foo() { bar(); something_non_trivial(); }
void bar() { foo(); }

void test() {
  foo();
  bar();
}
```
where none of the functions call themselves directly. I'm still not quite sure 
whether we're correctly confirming that `bar()` is non-trivial here, when we 
start the analysis from `foo()`.

https://github.com/llvm/llvm-project/pull/91876
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [analyzer] Allow recursive functions to be trivial. (PR #91876)

2024-05-23 Thread Artem Dergachev via cfe-commits


@@ -231,6 +231,15 @@ class RefCounted {
   void method();
   void someFunction();
   int otherFunction();
+  unsigned recursiveTrivialFunction(int n) { return !n ? 1 : 
recursiveTrivialFunction(n - 1);  }
+  unsigned recursiveComplexFunction(int n) { return !n ? otherFunction() : 
recursiveComplexFunction(n - 1);  }
+  unsigned mutuallyRecursiveFunction1(int n) { return n < 0 ? 1 : (n % 2 ? 
mutuallyRecursiveFunction2(n - 2) : mutuallyRecursiveFunction1(n - 1)); }
+  unsigned mutuallyRecursiveFunction2(int n) { return n < 0 ? 1 : (n % 3 ? 
mutuallyRecursiveFunction2(n - 3) : mutuallyRecursiveFunction1(n - 2)); }
+  unsigned mutuallyRecursiveFunction3(int n) { return n < 0 ? 1 : (n % 5 ? 
mutuallyRecursiveFunction3(n - 5) : mutuallyRecursiveFunction4(n - 3)); }
+  unsigned mutuallyRecursiveFunction4(int n) { return n < 0 ? 1 : (n % 7 ? 
otherFunction() : mutuallyRecursiveFunction3(n - 3)); }
+  unsigned mutuallyRecursiveFunction5(unsigned n) { return n > 100 ? 2 : (n % 
2 ? mutuallyRecursiveFunction5(n + 1) : mutuallyRecursiveFunction6(n + 2)); }

haoNoQ wrote:

These probably shouldn't be called "mutually" recursive because you never 
really go back from 6 to 5 or from 7 to 6. Though, I don't have a better name 
for such contraption.

https://github.com/llvm/llvm-project/pull/91876
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [analyzer] Allow recursive functions to be trivial. (PR #91876)

2024-05-23 Thread Artem Dergachev via cfe-commits

https://github.com/haoNoQ edited https://github.com/llvm/llvm-project/pull/91876
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [analyzer] Allow recursive functions to be trivial. (PR #91876)

2024-05-15 Thread Ryosuke Niwa via cfe-commits

https://github.com/rniwa updated https://github.com/llvm/llvm-project/pull/91876

>From e40017a2750ee39bfd1a87b5ddea620076bc4419 Mon Sep 17 00:00:00 2001
From: Ryosuke Niwa 
Date: Sat, 11 May 2024 20:18:52 -0700
Subject: [PATCH 1/5] [analyzer] Allow recursive functions to be trivial.

---
 .../Checkers/WebKit/PtrTypesSemantics.cpp  | 18 +-
 .../Checkers/WebKit/uncounted-obj-arg.cpp  |  6 ++
 2 files changed, 15 insertions(+), 9 deletions(-)

diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp 
b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
index 5c797d5233089..2a4da9eeaee6d 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
@@ -517,11 +517,9 @@ class TrivialFunctionAnalysisVisitor
 
 bool TrivialFunctionAnalysis::isTrivialImpl(
 const Decl *D, TrivialFunctionAnalysis::CacheTy ) {
-  // If the function isn't in the cache, conservatively assume that
-  // it's not trivial until analysis completes. This makes every recursive
-  // function non-trivial. This also guarantees that each function
-  // will be scanned at most once.
-  auto [It, IsNew] = Cache.insert(std::make_pair(D, false));
+  // Treat every recursive function as trivial until otherwise proven.
+  // This guarantees each function is evaluated at most once.
+  auto [It, IsNew] = Cache.insert(std::make_pair(D, true));
   if (!IsNew)
 return It->second;
 
@@ -535,12 +533,14 @@ bool TrivialFunctionAnalysis::isTrivialImpl(
   }
 
   const Stmt *Body = D->getBody();
-  if (!Body)
-return false;
+  if (!Body) {
+Cache[D] = false;
+return false;
+  }
 
   bool Result = V.Visit(Body);
-  if (Result)
-Cache[D] = true;
+  if (!Result)
+Cache[D] = false;
 
   return Result;
 }
diff --git a/clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp 
b/clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp
index 96986631726fe..18af9e17f78b0 100644
--- a/clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp
+++ b/clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp
@@ -231,6 +231,8 @@ class RefCounted {
   void method();
   void someFunction();
   int otherFunction();
+  unsigned recursiveFunction(int n) { return !n ? 1 : recursiveFunction(n - 
1);  }
+  unsigned recursiveComplexFunction(int n) { return !n ? otherFunction() : 
recursiveComplexFunction(n - 1);  }
 
   int trivial1() { return 123; }
   float trivial2() { return 0.3; }
@@ -498,6 +500,10 @@ class UnrelatedClass {
 RefCounted::singleton().trivial18(); // no-warning
 RefCounted::singleton().someFunction(); // no-warning
 
+getFieldTrivial().recursiveFunction(7); // no-warning
+getFieldTrivial().recursiveComplexFunction(9);
+// expected-warning@-1{{Call argument for 'this' parameter is uncounted 
and unsafe}}
+
 getFieldTrivial().someFunction();
 // expected-warning@-1{{Call argument for 'this' parameter is uncounted 
and unsafe}}
 getFieldTrivial().nonTrivial1();

>From 5d7a259c0209a8cbb70c2718518905669db2a885 Mon Sep 17 00:00:00 2001
From: Ryosuke Niwa 
Date: Sat, 11 May 2024 20:24:10 -0700
Subject: [PATCH 2/5] Fix formatting.

---
 clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp 
b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
index 2a4da9eeaee6d..449e56be9984d 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
@@ -535,7 +535,7 @@ bool TrivialFunctionAnalysis::isTrivialImpl(
   const Stmt *Body = D->getBody();
   if (!Body) {
 Cache[D] = false;
-return false;
+return false;
   }
 
   bool Result = V.Visit(Body);

>From 9971dcdebc160acb708b548bf67ef5efa76d4fe0 Mon Sep 17 00:00:00 2001
From: Ryosuke Niwa 
Date: Sun, 12 May 2024 15:15:33 -0700
Subject: [PATCH 3/5] Fix the TrivialFunctionAnalysis::isTrivialImpl for
 mutually recursive functions.

Instead of assuming every function to be initially trivial, we explicitly track
the set of functions that we're currently visting. When one of the currently 
visited
function is determined to be not trivial, we clear this set to signal that all
mutually recursive functions are non-trivial. We conclude that a function is 
trivial
when Visit() call on the function body returned true **AND** the set still 
contains
the function.

To implement this new algorithm, a new public function, IsFunctionTrivial,
is introduced to TrivialFunctionAnalysisVisitor, and various Visit functions in
TrivialFunctionAnalysisVisitor has been updated to use this function instead of
TrivialFunctionAnalysis::isTrivialImpl, which is now a wrapper for the function.
---
 .../Checkers/WebKit/PtrTypesSemantics.cpp | 69 +++
 .../Checkers/WebKit/uncounted-obj-arg.cpp   

[clang] [analyzer] Allow recursive functions to be trivial. (PR #91876)

2024-05-13 Thread Ryosuke Niwa via cfe-commits

https://github.com/rniwa updated https://github.com/llvm/llvm-project/pull/91876

>From a4b877b240ede15260f08fcb4a4622dd45a13d0a Mon Sep 17 00:00:00 2001
From: Ryosuke Niwa 
Date: Sat, 11 May 2024 20:18:52 -0700
Subject: [PATCH 1/6] [analyzer] Allow recursive functions to be trivial.

---
 .../Checkers/WebKit/PtrTypesSemantics.cpp  | 18 +-
 .../Checkers/WebKit/uncounted-obj-arg.cpp  |  6 ++
 2 files changed, 15 insertions(+), 9 deletions(-)

diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp 
b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
index ad493587affa0..dd930ea4b4ab5 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
@@ -498,22 +498,22 @@ class TrivialFunctionAnalysisVisitor
 
 bool TrivialFunctionAnalysis::isTrivialImpl(
 const Decl *D, TrivialFunctionAnalysis::CacheTy ) {
-  // If the function isn't in the cache, conservatively assume that
-  // it's not trivial until analysis completes. This makes every recursive
-  // function non-trivial. This also guarantees that each function
-  // will be scanned at most once.
-  auto [It, IsNew] = Cache.insert(std::make_pair(D, false));
+  // Treat every recursive function as trivial until otherwise proven.
+  // This guarantees each function is evaluated at most once.
+  auto [It, IsNew] = Cache.insert(std::make_pair(D, true));
   if (!IsNew)
 return It->second;
 
   const Stmt *Body = D->getBody();
-  if (!Body)
-return false;
+  if (!Body) {
+Cache[D] = false;
+return false;
+  }
 
   TrivialFunctionAnalysisVisitor V(Cache);
   bool Result = V.Visit(Body);
-  if (Result)
-Cache[D] = true;
+  if (!Result)
+Cache[D] = false;
 
   return Result;
 }
diff --git a/clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp 
b/clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp
index 073f3252160ee..39bc76197d204 100644
--- a/clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp
+++ b/clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp
@@ -181,6 +181,8 @@ class RefCounted {
   void method();
   void someFunction();
   int otherFunction();
+  unsigned recursiveFunction(int n) { return !n ? 1 : recursiveFunction(n - 
1);  }
+  unsigned recursiveComplexFunction(int n) { return !n ? otherFunction() : 
recursiveComplexFunction(n - 1);  }
 
   int trivial1() { return 123; }
   float trivial2() { return 0.3; }
@@ -417,6 +419,10 @@ class UnrelatedClass {
 RefCounted::singleton().trivial18(); // no-warning
 RefCounted::singleton().someFunction(); // no-warning
 
+getFieldTrivial().recursiveFunction(7); // no-warning
+getFieldTrivial().recursiveComplexFunction(9);
+// expected-warning@-1{{Call argument for 'this' parameter is uncounted 
and unsafe}}
+
 getFieldTrivial().someFunction();
 // expected-warning@-1{{Call argument for 'this' parameter is uncounted 
and unsafe}}
 getFieldTrivial().nonTrivial1();

>From ceb70513d342aadb339fde6cf7ccabc96a243dfd Mon Sep 17 00:00:00 2001
From: Ryosuke Niwa 
Date: Sat, 11 May 2024 20:24:10 -0700
Subject: [PATCH 2/6] Fix formatting.

---
 clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp 
b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
index dd930ea4b4ab5..83a0300c627e8 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
@@ -507,7 +507,7 @@ bool TrivialFunctionAnalysis::isTrivialImpl(
   const Stmt *Body = D->getBody();
   if (!Body) {
 Cache[D] = false;
-return false;
+return false;
   }
 
   TrivialFunctionAnalysisVisitor V(Cache);

>From 90cf7dde6e71b1d11ee0d88cd8afe0bce47531e1 Mon Sep 17 00:00:00 2001
From: Ryosuke Niwa 
Date: Sun, 12 May 2024 15:15:33 -0700
Subject: [PATCH 3/6] Fix the TrivialFunctionAnalysis::isTrivialImpl for
 mutually recursive functions.

Instead of assuming every function to be initially trivial, we explicitly track
the set of functions that we're currently visting. When one of the currently 
visited
function is determined to be not trivial, we clear this set to signal that all
mutually recursive functions are non-trivial. We conclude that a function is 
trivial
when Visit() call on the function body returned true **AND** the set still 
contains
the function.

To implement this new algorithm, a new public function, IsFunctionTrivial,
is introduced to TrivialFunctionAnalysisVisitor, and various Visit functions in
TrivialFunctionAnalysisVisitor has been updated to use this function instead of
TrivialFunctionAnalysis::isTrivialImpl, which is now a wrapper for the function.
---
 .../Checkers/WebKit/PtrTypesSemantics.cpp | 51 +++
 .../Checkers/WebKit/uncounted-obj-arg.cpp | 20 +++-
 

[clang] [analyzer] Allow recursive functions to be trivial. (PR #91876)

2024-05-13 Thread Ryosuke Niwa via cfe-commits

https://github.com/rniwa updated https://github.com/llvm/llvm-project/pull/91876

>From a4b877b240ede15260f08fcb4a4622dd45a13d0a Mon Sep 17 00:00:00 2001
From: Ryosuke Niwa 
Date: Sat, 11 May 2024 20:18:52 -0700
Subject: [PATCH 1/5] [analyzer] Allow recursive functions to be trivial.

---
 .../Checkers/WebKit/PtrTypesSemantics.cpp  | 18 +-
 .../Checkers/WebKit/uncounted-obj-arg.cpp  |  6 ++
 2 files changed, 15 insertions(+), 9 deletions(-)

diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp 
b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
index ad493587affa0..dd930ea4b4ab5 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
@@ -498,22 +498,22 @@ class TrivialFunctionAnalysisVisitor
 
 bool TrivialFunctionAnalysis::isTrivialImpl(
 const Decl *D, TrivialFunctionAnalysis::CacheTy ) {
-  // If the function isn't in the cache, conservatively assume that
-  // it's not trivial until analysis completes. This makes every recursive
-  // function non-trivial. This also guarantees that each function
-  // will be scanned at most once.
-  auto [It, IsNew] = Cache.insert(std::make_pair(D, false));
+  // Treat every recursive function as trivial until otherwise proven.
+  // This guarantees each function is evaluated at most once.
+  auto [It, IsNew] = Cache.insert(std::make_pair(D, true));
   if (!IsNew)
 return It->second;
 
   const Stmt *Body = D->getBody();
-  if (!Body)
-return false;
+  if (!Body) {
+Cache[D] = false;
+return false;
+  }
 
   TrivialFunctionAnalysisVisitor V(Cache);
   bool Result = V.Visit(Body);
-  if (Result)
-Cache[D] = true;
+  if (!Result)
+Cache[D] = false;
 
   return Result;
 }
diff --git a/clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp 
b/clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp
index 073f3252160ee..39bc76197d204 100644
--- a/clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp
+++ b/clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp
@@ -181,6 +181,8 @@ class RefCounted {
   void method();
   void someFunction();
   int otherFunction();
+  unsigned recursiveFunction(int n) { return !n ? 1 : recursiveFunction(n - 
1);  }
+  unsigned recursiveComplexFunction(int n) { return !n ? otherFunction() : 
recursiveComplexFunction(n - 1);  }
 
   int trivial1() { return 123; }
   float trivial2() { return 0.3; }
@@ -417,6 +419,10 @@ class UnrelatedClass {
 RefCounted::singleton().trivial18(); // no-warning
 RefCounted::singleton().someFunction(); // no-warning
 
+getFieldTrivial().recursiveFunction(7); // no-warning
+getFieldTrivial().recursiveComplexFunction(9);
+// expected-warning@-1{{Call argument for 'this' parameter is uncounted 
and unsafe}}
+
 getFieldTrivial().someFunction();
 // expected-warning@-1{{Call argument for 'this' parameter is uncounted 
and unsafe}}
 getFieldTrivial().nonTrivial1();

>From ceb70513d342aadb339fde6cf7ccabc96a243dfd Mon Sep 17 00:00:00 2001
From: Ryosuke Niwa 
Date: Sat, 11 May 2024 20:24:10 -0700
Subject: [PATCH 2/5] Fix formatting.

---
 clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp 
b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
index dd930ea4b4ab5..83a0300c627e8 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
@@ -507,7 +507,7 @@ bool TrivialFunctionAnalysis::isTrivialImpl(
   const Stmt *Body = D->getBody();
   if (!Body) {
 Cache[D] = false;
-return false;
+return false;
   }
 
   TrivialFunctionAnalysisVisitor V(Cache);

>From 90cf7dde6e71b1d11ee0d88cd8afe0bce47531e1 Mon Sep 17 00:00:00 2001
From: Ryosuke Niwa 
Date: Sun, 12 May 2024 15:15:33 -0700
Subject: [PATCH 3/5] Fix the TrivialFunctionAnalysis::isTrivialImpl for
 mutually recursive functions.

Instead of assuming every function to be initially trivial, we explicitly track
the set of functions that we're currently visting. When one of the currently 
visited
function is determined to be not trivial, we clear this set to signal that all
mutually recursive functions are non-trivial. We conclude that a function is 
trivial
when Visit() call on the function body returned true **AND** the set still 
contains
the function.

To implement this new algorithm, a new public function, IsFunctionTrivial,
is introduced to TrivialFunctionAnalysisVisitor, and various Visit functions in
TrivialFunctionAnalysisVisitor has been updated to use this function instead of
TrivialFunctionAnalysis::isTrivialImpl, which is now a wrapper for the function.
---
 .../Checkers/WebKit/PtrTypesSemantics.cpp | 51 +++
 .../Checkers/WebKit/uncounted-obj-arg.cpp | 20 +++-
 

[clang] [analyzer] Allow recursive functions to be trivial. (PR #91876)

2024-05-12 Thread Ryosuke Niwa via cfe-commits

https://github.com/rniwa updated https://github.com/llvm/llvm-project/pull/91876

>From a4b877b240ede15260f08fcb4a4622dd45a13d0a Mon Sep 17 00:00:00 2001
From: Ryosuke Niwa 
Date: Sat, 11 May 2024 20:18:52 -0700
Subject: [PATCH 1/4] [analyzer] Allow recursive functions to be trivial.

---
 .../Checkers/WebKit/PtrTypesSemantics.cpp  | 18 +-
 .../Checkers/WebKit/uncounted-obj-arg.cpp  |  6 ++
 2 files changed, 15 insertions(+), 9 deletions(-)

diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp 
b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
index ad493587affa0..dd930ea4b4ab5 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
@@ -498,22 +498,22 @@ class TrivialFunctionAnalysisVisitor
 
 bool TrivialFunctionAnalysis::isTrivialImpl(
 const Decl *D, TrivialFunctionAnalysis::CacheTy ) {
-  // If the function isn't in the cache, conservatively assume that
-  // it's not trivial until analysis completes. This makes every recursive
-  // function non-trivial. This also guarantees that each function
-  // will be scanned at most once.
-  auto [It, IsNew] = Cache.insert(std::make_pair(D, false));
+  // Treat every recursive function as trivial until otherwise proven.
+  // This guarantees each function is evaluated at most once.
+  auto [It, IsNew] = Cache.insert(std::make_pair(D, true));
   if (!IsNew)
 return It->second;
 
   const Stmt *Body = D->getBody();
-  if (!Body)
-return false;
+  if (!Body) {
+Cache[D] = false;
+return false;
+  }
 
   TrivialFunctionAnalysisVisitor V(Cache);
   bool Result = V.Visit(Body);
-  if (Result)
-Cache[D] = true;
+  if (!Result)
+Cache[D] = false;
 
   return Result;
 }
diff --git a/clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp 
b/clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp
index 073f3252160ee..39bc76197d204 100644
--- a/clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp
+++ b/clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp
@@ -181,6 +181,8 @@ class RefCounted {
   void method();
   void someFunction();
   int otherFunction();
+  unsigned recursiveFunction(int n) { return !n ? 1 : recursiveFunction(n - 
1);  }
+  unsigned recursiveComplexFunction(int n) { return !n ? otherFunction() : 
recursiveComplexFunction(n - 1);  }
 
   int trivial1() { return 123; }
   float trivial2() { return 0.3; }
@@ -417,6 +419,10 @@ class UnrelatedClass {
 RefCounted::singleton().trivial18(); // no-warning
 RefCounted::singleton().someFunction(); // no-warning
 
+getFieldTrivial().recursiveFunction(7); // no-warning
+getFieldTrivial().recursiveComplexFunction(9);
+// expected-warning@-1{{Call argument for 'this' parameter is uncounted 
and unsafe}}
+
 getFieldTrivial().someFunction();
 // expected-warning@-1{{Call argument for 'this' parameter is uncounted 
and unsafe}}
 getFieldTrivial().nonTrivial1();

>From ceb70513d342aadb339fde6cf7ccabc96a243dfd Mon Sep 17 00:00:00 2001
From: Ryosuke Niwa 
Date: Sat, 11 May 2024 20:24:10 -0700
Subject: [PATCH 2/4] Fix formatting.

---
 clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp 
b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
index dd930ea4b4ab5..83a0300c627e8 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
@@ -507,7 +507,7 @@ bool TrivialFunctionAnalysis::isTrivialImpl(
   const Stmt *Body = D->getBody();
   if (!Body) {
 Cache[D] = false;
-return false;
+return false;
   }
 
   TrivialFunctionAnalysisVisitor V(Cache);

>From 90cf7dde6e71b1d11ee0d88cd8afe0bce47531e1 Mon Sep 17 00:00:00 2001
From: Ryosuke Niwa 
Date: Sun, 12 May 2024 15:15:33 -0700
Subject: [PATCH 3/4] Fix the TrivialFunctionAnalysis::isTrivialImpl for
 mutually recursive functions.

Instead of assuming every function to be initially trivial, we explicitly track
the set of functions that we're currently visting. When one of the currently 
visited
function is determined to be not trivial, we clear this set to signal that all
mutually recursive functions are non-trivial. We conclude that a function is 
trivial
when Visit() call on the function body returned true **AND** the set still 
contains
the function.

To implement this new algorithm, a new public function, IsFunctionTrivial,
is introduced to TrivialFunctionAnalysisVisitor, and various Visit functions in
TrivialFunctionAnalysisVisitor has been updated to use this function instead of
TrivialFunctionAnalysis::isTrivialImpl, which is now a wrapper for the function.
---
 .../Checkers/WebKit/PtrTypesSemantics.cpp | 51 +++
 .../Checkers/WebKit/uncounted-obj-arg.cpp | 20 +++-
 

[clang] [analyzer] Allow recursive functions to be trivial. (PR #91876)

2024-05-12 Thread Ryosuke Niwa via cfe-commits

https://github.com/rniwa updated https://github.com/llvm/llvm-project/pull/91876

>From a4b877b240ede15260f08fcb4a4622dd45a13d0a Mon Sep 17 00:00:00 2001
From: Ryosuke Niwa 
Date: Sat, 11 May 2024 20:18:52 -0700
Subject: [PATCH 1/3] [analyzer] Allow recursive functions to be trivial.

---
 .../Checkers/WebKit/PtrTypesSemantics.cpp  | 18 +-
 .../Checkers/WebKit/uncounted-obj-arg.cpp  |  6 ++
 2 files changed, 15 insertions(+), 9 deletions(-)

diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp 
b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
index ad493587affa0..dd930ea4b4ab5 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
@@ -498,22 +498,22 @@ class TrivialFunctionAnalysisVisitor
 
 bool TrivialFunctionAnalysis::isTrivialImpl(
 const Decl *D, TrivialFunctionAnalysis::CacheTy ) {
-  // If the function isn't in the cache, conservatively assume that
-  // it's not trivial until analysis completes. This makes every recursive
-  // function non-trivial. This also guarantees that each function
-  // will be scanned at most once.
-  auto [It, IsNew] = Cache.insert(std::make_pair(D, false));
+  // Treat every recursive function as trivial until otherwise proven.
+  // This guarantees each function is evaluated at most once.
+  auto [It, IsNew] = Cache.insert(std::make_pair(D, true));
   if (!IsNew)
 return It->second;
 
   const Stmt *Body = D->getBody();
-  if (!Body)
-return false;
+  if (!Body) {
+Cache[D] = false;
+return false;
+  }
 
   TrivialFunctionAnalysisVisitor V(Cache);
   bool Result = V.Visit(Body);
-  if (Result)
-Cache[D] = true;
+  if (!Result)
+Cache[D] = false;
 
   return Result;
 }
diff --git a/clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp 
b/clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp
index 073f3252160ee..39bc76197d204 100644
--- a/clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp
+++ b/clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp
@@ -181,6 +181,8 @@ class RefCounted {
   void method();
   void someFunction();
   int otherFunction();
+  unsigned recursiveFunction(int n) { return !n ? 1 : recursiveFunction(n - 
1);  }
+  unsigned recursiveComplexFunction(int n) { return !n ? otherFunction() : 
recursiveComplexFunction(n - 1);  }
 
   int trivial1() { return 123; }
   float trivial2() { return 0.3; }
@@ -417,6 +419,10 @@ class UnrelatedClass {
 RefCounted::singleton().trivial18(); // no-warning
 RefCounted::singleton().someFunction(); // no-warning
 
+getFieldTrivial().recursiveFunction(7); // no-warning
+getFieldTrivial().recursiveComplexFunction(9);
+// expected-warning@-1{{Call argument for 'this' parameter is uncounted 
and unsafe}}
+
 getFieldTrivial().someFunction();
 // expected-warning@-1{{Call argument for 'this' parameter is uncounted 
and unsafe}}
 getFieldTrivial().nonTrivial1();

>From ceb70513d342aadb339fde6cf7ccabc96a243dfd Mon Sep 17 00:00:00 2001
From: Ryosuke Niwa 
Date: Sat, 11 May 2024 20:24:10 -0700
Subject: [PATCH 2/3] Fix formatting.

---
 clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp 
b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
index dd930ea4b4ab5..83a0300c627e8 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
@@ -507,7 +507,7 @@ bool TrivialFunctionAnalysis::isTrivialImpl(
   const Stmt *Body = D->getBody();
   if (!Body) {
 Cache[D] = false;
-return false;
+return false;
   }
 
   TrivialFunctionAnalysisVisitor V(Cache);

>From 90cf7dde6e71b1d11ee0d88cd8afe0bce47531e1 Mon Sep 17 00:00:00 2001
From: Ryosuke Niwa 
Date: Sun, 12 May 2024 15:15:33 -0700
Subject: [PATCH 3/3] Fix the TrivialFunctionAnalysis::isTrivialImpl for
 mutually recursive functions.

Instead of assuming every function to be initially trivial, we explicitly track
the set of functions that we're currently visting. When one of the currently 
visited
function is determined to be not trivial, we clear this set to signal that all
mutually recursive functions are non-trivial. We conclude that a function is 
trivial
when Visit() call on the function body returned true **AND** the set still 
contains
the function.

To implement this new algorithm, a new public function, IsFunctionTrivial,
is introduced to TrivialFunctionAnalysisVisitor, and various Visit functions in
TrivialFunctionAnalysisVisitor has been updated to use this function instead of
TrivialFunctionAnalysis::isTrivialImpl, which is now a wrapper for the function.
---
 .../Checkers/WebKit/PtrTypesSemantics.cpp | 51 +++
 .../Checkers/WebKit/uncounted-obj-arg.cpp | 20 +++-
 

[clang] [analyzer] Allow recursive functions to be trivial. (PR #91876)

2024-05-12 Thread Ryosuke Niwa via cfe-commits

rniwa wrote:

> You should add a test for mutually recursive functions. I suspect something 
> like this doesn't work:
> 
> ```c++
> int non_trivial();
> int f(bool b) { return g(!b) + non_trivial(); }
> int g(bool b) { return b ? f(b) : 1; }
> 
> getFieldTrivial().f(true);  // expected-warning {{...}}
> getFieldTrivial().g(true);  // expected-warning {{...}}
> ```

Duh, of course. Thanks for pointing out the obvious flaw.

https://github.com/llvm/llvm-project/pull/91876
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [analyzer] Allow recursive functions to be trivial. (PR #91876)

2024-05-12 Thread Mital Ashok via cfe-commits

MitalAshok wrote:

You should add a test for mutually recursive functions. I suspect something 
like this doesn't work:

```c++
int non_trivial();
int f(bool b) { return g(!b) + non_trivial(); }
int g(bool b) { return b ? f(b) : 1; }

getFieldTrivial().f(true);  // expected-warning {{...}}
getFieldTrivial().g(true);  // expected-warning {{...}}
```

Since when analyzing `f`, `f` enters the cache as trivial, `g` is analyzed and 
sees `f` in the cache as trivial, so `g` is marked trivial, but then `f` is 
marked as non-trivial (so `g` should have been marked as non-trivial, but is 
marked trivial).

If that is an issue, one way to do this "properly" would be to create a graph, 
and a function is non-trivial if it has a path to a non-trivial function (this 
might be too expensive to implement directly). Or we could special case simple 
recursion only, by changing `TrivialFunctionAnalysisVisitor` to not call 
`isTrivialImpl` for the current function only.

https://github.com/llvm/llvm-project/pull/91876
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [analyzer] Allow recursive functions to be trivial. (PR #91876)

2024-05-11 Thread Ryosuke Niwa via cfe-commits

https://github.com/rniwa updated https://github.com/llvm/llvm-project/pull/91876

>From a4b877b240ede15260f08fcb4a4622dd45a13d0a Mon Sep 17 00:00:00 2001
From: Ryosuke Niwa 
Date: Sat, 11 May 2024 20:18:52 -0700
Subject: [PATCH 1/2] [analyzer] Allow recursive functions to be trivial.

---
 .../Checkers/WebKit/PtrTypesSemantics.cpp  | 18 +-
 .../Checkers/WebKit/uncounted-obj-arg.cpp  |  6 ++
 2 files changed, 15 insertions(+), 9 deletions(-)

diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp 
b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
index ad493587affa0..dd930ea4b4ab5 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
@@ -498,22 +498,22 @@ class TrivialFunctionAnalysisVisitor
 
 bool TrivialFunctionAnalysis::isTrivialImpl(
 const Decl *D, TrivialFunctionAnalysis::CacheTy ) {
-  // If the function isn't in the cache, conservatively assume that
-  // it's not trivial until analysis completes. This makes every recursive
-  // function non-trivial. This also guarantees that each function
-  // will be scanned at most once.
-  auto [It, IsNew] = Cache.insert(std::make_pair(D, false));
+  // Treat every recursive function as trivial until otherwise proven.
+  // This guarantees each function is evaluated at most once.
+  auto [It, IsNew] = Cache.insert(std::make_pair(D, true));
   if (!IsNew)
 return It->second;
 
   const Stmt *Body = D->getBody();
-  if (!Body)
-return false;
+  if (!Body) {
+Cache[D] = false;
+return false;
+  }
 
   TrivialFunctionAnalysisVisitor V(Cache);
   bool Result = V.Visit(Body);
-  if (Result)
-Cache[D] = true;
+  if (!Result)
+Cache[D] = false;
 
   return Result;
 }
diff --git a/clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp 
b/clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp
index 073f3252160ee..39bc76197d204 100644
--- a/clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp
+++ b/clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp
@@ -181,6 +181,8 @@ class RefCounted {
   void method();
   void someFunction();
   int otherFunction();
+  unsigned recursiveFunction(int n) { return !n ? 1 : recursiveFunction(n - 
1);  }
+  unsigned recursiveComplexFunction(int n) { return !n ? otherFunction() : 
recursiveComplexFunction(n - 1);  }
 
   int trivial1() { return 123; }
   float trivial2() { return 0.3; }
@@ -417,6 +419,10 @@ class UnrelatedClass {
 RefCounted::singleton().trivial18(); // no-warning
 RefCounted::singleton().someFunction(); // no-warning
 
+getFieldTrivial().recursiveFunction(7); // no-warning
+getFieldTrivial().recursiveComplexFunction(9);
+// expected-warning@-1{{Call argument for 'this' parameter is uncounted 
and unsafe}}
+
 getFieldTrivial().someFunction();
 // expected-warning@-1{{Call argument for 'this' parameter is uncounted 
and unsafe}}
 getFieldTrivial().nonTrivial1();

>From ceb70513d342aadb339fde6cf7ccabc96a243dfd Mon Sep 17 00:00:00 2001
From: Ryosuke Niwa 
Date: Sat, 11 May 2024 20:24:10 -0700
Subject: [PATCH 2/2] Fix formatting.

---
 clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp 
b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
index dd930ea4b4ab5..83a0300c627e8 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
@@ -507,7 +507,7 @@ bool TrivialFunctionAnalysis::isTrivialImpl(
   const Stmt *Body = D->getBody();
   if (!Body) {
 Cache[D] = false;
-return false;
+return false;
   }
 
   TrivialFunctionAnalysisVisitor V(Cache);

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [analyzer] Allow recursive functions to be trivial. (PR #91876)

2024-05-11 Thread via cfe-commits

github-actions[bot] wrote:




:warning: C/C++ code formatter, clang-format found issues in your code. 
:warning:



You can test this locally with the following command:


``bash
git-clang-format --diff 31774b6a8a88b435ce79f9ba048ef8bb00e2817e 
a4b877b240ede15260f08fcb4a4622dd45a13d0a -- 
clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp 
clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp
``





View the diff from clang-format here.


``diff
diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp 
b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
index dd930ea4b4..83a0300c62 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
@@ -507,7 +507,7 @@ bool TrivialFunctionAnalysis::isTrivialImpl(
   const Stmt *Body = D->getBody();
   if (!Body) {
 Cache[D] = false;
-return false;
+return false;
   }
 
   TrivialFunctionAnalysisVisitor V(Cache);

``




https://github.com/llvm/llvm-project/pull/91876
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [analyzer] Allow recursive functions to be trivial. (PR #91876)

2024-05-11 Thread Ryosuke Niwa via cfe-commits

https://github.com/rniwa edited https://github.com/llvm/llvm-project/pull/91876
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits