[clang] [analyzer] Allow recurisve 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] [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 &Cache) {
-  // 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();

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


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

2024-05-11 Thread via cfe-commits

llvmbot wrote:




@llvm/pr-subscribers-clang

Author: Ryosuke Niwa (rniwa)


Changes



---
Full diff: https://github.com/llvm/llvm-project/pull/91876.diff


2 Files Affected:

- (modified) clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp 
(+9-9) 
- (modified) clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp (+6) 


``diff
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 &Cache) {
-  // 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();

``




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 recurisve functions to be trivial. (PR #91876)

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

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

None

>From aac9ea105506ff933d773337f3260f7770a2c5e6 Mon Sep 17 00:00:00 2001
From: Ryosuke Niwa 
Date: Sat, 11 May 2024 20:18:52 -0700
Subject: [PATCH] [analyzer] Allow recurisve 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 &Cache) {
-  // 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();

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