[clang] [analyzer] Treat break, continue, goto, and label statements as trivial in WebKit checkers. (PR #91873)
Ryosuke Niwa via cfe-commits
cfe-commits at lists.llvm.org
Sat May 11 16:49:41 PDT 2024
https://github.com/rniwa updated https://github.com/llvm/llvm-project/pull/91873
>From 433852bd5e360bcf0dfe41e401c3aa73f29a2092 Mon Sep 17 00:00:00 2001
From: Ryosuke Niwa <rniwa at apple.com>
Date: Sat, 11 May 2024 16:45:56 -0700
Subject: [PATCH] [analyzer] Treat break, continue, goto, and label statements
as trivial in WebKit checkers.
Also allow CXXBindTemporaryExpr, which creates a temporary object with a non-trivial destructor,
and add a few more std and WTF functions to the explicitly allowed list.
---
.../Checkers/WebKit/PtrTypesSemantics.cpp | 19 +++++-
.../Checkers/WebKit/uncounted-obj-arg.cpp | 63 +++++++++++++++++--
2 files changed, 75 insertions(+), 7 deletions(-)
diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
index ad493587affa0..e6d014e3ba8e1 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
@@ -308,6 +308,12 @@ class TrivialFunctionAnalysisVisitor
bool VisitCaseStmt(const CaseStmt *CS) { return VisitChildren(CS); }
bool VisitDefaultStmt(const DefaultStmt *DS) { return VisitChildren(DS); }
+ // break, continue, goto, and label statements are always trivial.
+ bool VisitBreakStmt(const BreakStmt*) { return true; }
+ bool VisitContinueStmt(const ContinueStmt*) { return true; }
+ bool VisitGotoStmt(const GotoStmt*) { return true; }
+ bool VisitLabelStmt(const LabelStmt*) { return true; }
+
bool VisitUnaryOperator(const UnaryOperator *UO) {
// Unary operators are trivial if its operand is trivial except co_await.
return UO->getOpcode() != UO_Coawait && Visit(UO->getSubExpr());
@@ -349,12 +355,17 @@ class TrivialFunctionAnalysisVisitor
return false;
const auto &Name = safeGetName(Callee);
+ if (Callee->isInStdNamespace() && (Name == "addressof" ||
+ Name == "forward" || Name == "move"))
+ return true;
+
if (Name == "WTFCrashWithInfo" || Name == "WTFBreakpointTrap" ||
+ Name == "WTFCrashWithSecurityImplication" || Name == "WTFCrash" ||
Name == "WTFReportAssertionFailure" || Name == "isMainThread" ||
Name == "isMainThreadOrGCThread" || Name == "isMainRunLoop" ||
Name == "isWebThread" || Name == "isUIThread" ||
- Name == "compilerFenceForCrash" || Name == "bitwise_cast" ||
- Name == "addressof" || Name.find("__builtin") == 0)
+ Name == "mayBeGCThread" || Name == "compilerFenceForCrash" ||
+ Name == "bitwise_cast" || Name.find("__builtin") == 0)
return true;
return TrivialFunctionAnalysis::isTrivialImpl(Callee, Cache);
@@ -445,6 +456,10 @@ class TrivialFunctionAnalysisVisitor
return Visit(VMT->getSubExpr());
}
+ bool VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr* BTE) {
+ return Visit(BTE->getSubExpr());
+ }
+
bool VisitExprWithCleanups(const ExprWithCleanups *EWC) {
return Visit(EWC->getSubExpr());
}
diff --git a/clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp b/clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp
index 073f3252160ee..a6589f6fad14b 100644
--- a/clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp
+++ b/clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp
@@ -7,6 +7,9 @@ void WTFBreakpointTrap();
void WTFCrashWithInfo(int, const char*, const char*, int);
void WTFReportAssertionFailure(const char* file, int line, const char* function, const char* assertion);
+void WTFCrash(void);
+void WTFCrashWithSecurityImplication(void);
+
inline void compilerFenceForCrash()
{
asm volatile("" ::: "memory");
@@ -62,14 +65,25 @@ void WTFCrashWithInfo(int line, const char* file, const char* function, int coun
template<typename ToType, typename FromType>
ToType bitwise_cast(FromType from);
+namespace std {
+
template<typename T>
T* addressof(T& arg);
+template<typename T>
+T&& forward(T& arg);
+
+template<typename T>
+T&& move( T&& t );
+
+} // namespace std
+
bool isMainThread();
bool isMainThreadOrGCThread();
bool isMainRunLoop();
bool isWebThread();
bool isUIThread();
+bool mayBeGCThread();
enum class Flags : unsigned short {
Flag1 = 1 << 0,
@@ -161,16 +175,30 @@ class Number {
class ComplexNumber {
public:
- ComplexNumber() : real(0), complex(0) { }
+ ComplexNumber() : realPart(0), complexPart(0) { }
ComplexNumber(const ComplexNumber&);
- ComplexNumber& operator++() { real.someMethod(); return *this; }
+ ComplexNumber& operator++() { realPart.someMethod(); return *this; }
ComplexNumber operator++(int);
ComplexNumber& operator<<(int);
ComplexNumber& operator+();
+ const Number& real() const { return realPart; }
+
private:
- Number real;
- Number complex;
+ Number realPart;
+ Number complexPart;
+};
+
+class ObjectWithNonTrivialDestructor {
+public:
+ ObjectWithNonTrivialDestructor() { }
+ ObjectWithNonTrivialDestructor(unsigned v) : v(v) { }
+ ~ObjectWithNonTrivialDestructor() { }
+
+ unsigned value() const { return v; }
+
+private:
+ unsigned v { 0 };
};
class RefCounted {
@@ -248,7 +276,7 @@ class RefCounted {
int trivial40() { return v << 2; }
unsigned trivial41() { v = ++s_v; return v; }
unsigned trivial42() { return bitwise_cast<unsigned long>(nullptr); }
- Number* trivial43() { return addressof(*number); }
+ Number* trivial43() { return std::addressof(*number); }
Number* trivial44() { return new Number(1); }
ComplexNumber* trivial45() { return new ComplexNumber(); }
void trivial46() { ASSERT(isMainThread()); }
@@ -256,6 +284,21 @@ class RefCounted {
void trivial48() { ASSERT(isMainRunLoop()); }
void trivial49() { ASSERT(isWebThread()); }
void trivial50() { ASSERT(isUIThread()); }
+ void trivial51() { ASSERT(mayBeGCThread()); }
+ void trivial52() { WTFCrash(); }
+ void trivial53() { WTFCrashWithSecurityImplication(); }
+ unsigned trivial54() { return ComplexNumber().real().value(); }
+ Number&& trivial55() { return std::forward(*number); }
+ unsigned trivial56() { Number n { 5 }; return std::move(n).value(); }
+ void trivial57() { do { break; } while (1); }
+ void trivial58() { do { continue; } while (0); }
+ void trivial59() {
+ do { goto label; }
+ while (0);
+ label:
+ return;
+ }
+ unsigned trivial60() { return ObjectWithNonTrivialDestructor { 5 }.value(); }
static RefCounted& singleton() {
static RefCounted s_RefCounted;
@@ -413,6 +456,16 @@ class UnrelatedClass {
getFieldTrivial().trivial48(); // no-warning
getFieldTrivial().trivial49(); // no-warning
getFieldTrivial().trivial50(); // no-warning
+ getFieldTrivial().trivial51(); // no-warning
+ getFieldTrivial().trivial52(); // no-warning
+ getFieldTrivial().trivial53(); // no-warning
+ getFieldTrivial().trivial54(); // no-warning
+ getFieldTrivial().trivial55(); // no-warning
+ getFieldTrivial().trivial56(); // no-warning
+ getFieldTrivial().trivial57(); // no-warning
+ getFieldTrivial().trivial58(); // no-warning
+ getFieldTrivial().trivial59(); // no-warning
+ getFieldTrivial().trivial60(); // no-warning
RefCounted::singleton().trivial18(); // no-warning
RefCounted::singleton().someFunction(); // no-warning
More information about the cfe-commits
mailing list