Skip to content

Commit 24180ea

Browse files
authored
[analyzer] Treat break, continue, goto, and label statements as trivial in WebKit checkers. (llvm#91873)
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.
1 parent 1539758 commit 24180ea

File tree

2 files changed

+94
-7
lines changed

2 files changed

+94
-7
lines changed

clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,12 @@ class TrivialFunctionAnalysisVisitor
308308
bool VisitCaseStmt(const CaseStmt *CS) { return VisitChildren(CS); }
309309
bool VisitDefaultStmt(const DefaultStmt *DS) { return VisitChildren(DS); }
310310

311+
// break, continue, goto, and label statements are always trivial.
312+
bool VisitBreakStmt(const BreakStmt *) { return true; }
313+
bool VisitContinueStmt(const ContinueStmt *) { return true; }
314+
bool VisitGotoStmt(const GotoStmt *) { return true; }
315+
bool VisitLabelStmt(const LabelStmt *) { return true; }
316+
311317
bool VisitUnaryOperator(const UnaryOperator *UO) {
312318
// Unary operators are trivial if its operand is trivial except co_await.
313319
return UO->getOpcode() != UO_Coawait && Visit(UO->getSubExpr());
@@ -349,12 +355,17 @@ class TrivialFunctionAnalysisVisitor
349355
return false;
350356
const auto &Name = safeGetName(Callee);
351357

358+
if (Callee->isInStdNamespace() &&
359+
(Name == "addressof" || Name == "forward" || Name == "move"))
360+
return true;
361+
352362
if (Name == "WTFCrashWithInfo" || Name == "WTFBreakpointTrap" ||
363+
Name == "WTFCrashWithSecurityImplication" || Name == "WTFCrash" ||
353364
Name == "WTFReportAssertionFailure" || Name == "isMainThread" ||
354365
Name == "isMainThreadOrGCThread" || Name == "isMainRunLoop" ||
355366
Name == "isWebThread" || Name == "isUIThread" ||
356-
Name == "compilerFenceForCrash" || Name == "bitwise_cast" ||
357-
Name == "addressof" || Name.find("__builtin") == 0)
367+
Name == "mayBeGCThread" || Name == "compilerFenceForCrash" ||
368+
Name == "bitwise_cast" || Name.find("__builtin") == 0)
358369
return true;
359370

360371
return TrivialFunctionAnalysis::isTrivialImpl(Callee, Cache);
@@ -445,6 +456,14 @@ class TrivialFunctionAnalysisVisitor
445456
return Visit(VMT->getSubExpr());
446457
}
447458

459+
bool VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *BTE) {
460+
if (auto *Temp = BTE->getTemporary()) {
461+
if (!TrivialFunctionAnalysis::isTrivialImpl(Temp->getDestructor(), Cache))
462+
return false;
463+
}
464+
return Visit(BTE->getSubExpr());
465+
}
466+
448467
bool VisitExprWithCleanups(const ExprWithCleanups *EWC) {
449468
return Visit(EWC->getSubExpr());
450469
}

clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp

Lines changed: 73 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ void WTFBreakpointTrap();
77
void WTFCrashWithInfo(int, const char*, const char*, int);
88
void WTFReportAssertionFailure(const char* file, int line, const char* function, const char* assertion);
99

10+
void WTFCrash(void);
11+
void WTFCrashWithSecurityImplication(void);
12+
1013
inline void compilerFenceForCrash()
1114
{
1215
asm volatile("" ::: "memory");
@@ -62,14 +65,25 @@ void WTFCrashWithInfo(int line, const char* file, const char* function, int coun
6265
template<typename ToType, typename FromType>
6366
ToType bitwise_cast(FromType from);
6467

68+
namespace std {
69+
6570
template<typename T>
6671
T* addressof(T& arg);
6772

73+
template<typename T>
74+
T&& forward(T& arg);
75+
76+
template<typename T>
77+
T&& move( T&& t );
78+
79+
} // namespace std
80+
6881
bool isMainThread();
6982
bool isMainThreadOrGCThread();
7083
bool isMainRunLoop();
7184
bool isWebThread();
7285
bool isUIThread();
86+
bool mayBeGCThread();
7387

7488
enum class Flags : unsigned short {
7589
Flag1 = 1 << 0,
@@ -161,16 +175,42 @@ class Number {
161175

162176
class ComplexNumber {
163177
public:
164-
ComplexNumber() : real(0), complex(0) { }
178+
ComplexNumber() : realPart(0), complexPart(0) { }
165179
ComplexNumber(const ComplexNumber&);
166-
ComplexNumber& operator++() { real.someMethod(); return *this; }
180+
ComplexNumber& operator++() { realPart.someMethod(); return *this; }
167181
ComplexNumber operator++(int);
168182
ComplexNumber& operator<<(int);
169183
ComplexNumber& operator+();
170184

185+
const Number& real() const { return realPart; }
186+
171187
private:
172-
Number real;
173-
Number complex;
188+
Number realPart;
189+
Number complexPart;
190+
};
191+
192+
class ObjectWithNonTrivialDestructor {
193+
public:
194+
ObjectWithNonTrivialDestructor() { }
195+
ObjectWithNonTrivialDestructor(unsigned v) : v(v) { }
196+
~ObjectWithNonTrivialDestructor() { }
197+
198+
unsigned value() const { return v; }
199+
200+
private:
201+
unsigned v { 0 };
202+
};
203+
204+
class ObjectWithMutatingDestructor {
205+
public:
206+
ObjectWithMutatingDestructor() : n(0) { }
207+
ObjectWithMutatingDestructor(int n) : n(n) { }
208+
~ObjectWithMutatingDestructor() { n.someMethod(); }
209+
210+
unsigned value() const { return n.value(); }
211+
212+
private:
213+
Number n;
174214
};
175215

176216
class RefCounted {
@@ -248,14 +288,29 @@ class RefCounted {
248288
int trivial40() { return v << 2; }
249289
unsigned trivial41() { v = ++s_v; return v; }
250290
unsigned trivial42() { return bitwise_cast<unsigned long>(nullptr); }
251-
Number* trivial43() { return addressof(*number); }
291+
Number* trivial43() { return std::addressof(*number); }
252292
Number* trivial44() { return new Number(1); }
253293
ComplexNumber* trivial45() { return new ComplexNumber(); }
254294
void trivial46() { ASSERT(isMainThread()); }
255295
void trivial47() { ASSERT(isMainThreadOrGCThread()); }
256296
void trivial48() { ASSERT(isMainRunLoop()); }
257297
void trivial49() { ASSERT(isWebThread()); }
258298
void trivial50() { ASSERT(isUIThread()); }
299+
void trivial51() { ASSERT(mayBeGCThread()); }
300+
void trivial52() { WTFCrash(); }
301+
void trivial53() { WTFCrashWithSecurityImplication(); }
302+
unsigned trivial54() { return ComplexNumber().real().value(); }
303+
Number&& trivial55() { return std::forward(*number); }
304+
unsigned trivial56() { Number n { 5 }; return std::move(n).value(); }
305+
void trivial57() { do { break; } while (1); }
306+
void trivial58() { do { continue; } while (0); }
307+
void trivial59() {
308+
do { goto label; }
309+
while (0);
310+
label:
311+
return;
312+
}
313+
unsigned trivial60() { return ObjectWithNonTrivialDestructor { 5 }.value(); }
259314

260315
static RefCounted& singleton() {
261316
static RefCounted s_RefCounted;
@@ -335,6 +390,7 @@ class RefCounted {
335390
ComplexNumber nonTrivial17() { return complex << 2; }
336391
ComplexNumber nonTrivial18() { return +complex; }
337392
ComplexNumber* nonTrivial19() { return new ComplexNumber(complex); }
393+
unsigned nonTrivial20() { return ObjectWithMutatingDestructor { 7 }.value(); }
338394

339395
static unsigned s_v;
340396
unsigned v { 0 };
@@ -413,6 +469,16 @@ class UnrelatedClass {
413469
getFieldTrivial().trivial48(); // no-warning
414470
getFieldTrivial().trivial49(); // no-warning
415471
getFieldTrivial().trivial50(); // no-warning
472+
getFieldTrivial().trivial51(); // no-warning
473+
getFieldTrivial().trivial52(); // no-warning
474+
getFieldTrivial().trivial53(); // no-warning
475+
getFieldTrivial().trivial54(); // no-warning
476+
getFieldTrivial().trivial55(); // no-warning
477+
getFieldTrivial().trivial56(); // no-warning
478+
getFieldTrivial().trivial57(); // no-warning
479+
getFieldTrivial().trivial58(); // no-warning
480+
getFieldTrivial().trivial59(); // no-warning
481+
getFieldTrivial().trivial60(); // no-warning
416482

417483
RefCounted::singleton().trivial18(); // no-warning
418484
RefCounted::singleton().someFunction(); // no-warning
@@ -457,6 +523,8 @@ class UnrelatedClass {
457523
// expected-warning@-1{{Call argument for 'this' parameter is uncounted and unsafe}}
458524
getFieldTrivial().nonTrivial19();
459525
// expected-warning@-1{{Call argument for 'this' parameter is uncounted and unsafe}}
526+
getFieldTrivial().nonTrivial20();
527+
// expected-warning@-1{{Call argument for 'this' parameter is uncounted and unsafe}}
460528
}
461529
};
462530

0 commit comments

Comments
 (0)