[clang] [analyzer] Allow recurisve functions to be trivial. (PR #91876)
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)
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)
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