Skip to content

Commit a99cb96

Browse files
authored
[alpha.webkit.UncountedCallArgsChecker] Allow trivial operator++ (llvm#91102)
This PR adds the support for trivial operator++ implementations. T& operator++() and T operator++(int) are trivial if the callee is trivial. Also allow incrementing and decrementing of a POD member variable. Also treat any __builtin_ functions as trivial.
1 parent 5d51db7 commit a99cb96

File tree

2 files changed

+56
-16
lines changed

2 files changed

+56
-16
lines changed

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

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -309,21 +309,8 @@ class TrivialFunctionAnalysisVisitor
309309
bool VisitDefaultStmt(const DefaultStmt *DS) { return VisitChildren(DS); }
310310

311311
bool VisitUnaryOperator(const UnaryOperator *UO) {
312-
// Operator '*' and '!' are allowed as long as the operand is trivial.
313-
auto op = UO->getOpcode();
314-
if (op == UO_Deref || op == UO_AddrOf || op == UO_LNot || op == UO_Not)
315-
return Visit(UO->getSubExpr());
316-
317-
if (UO->isIncrementOp() || UO->isDecrementOp()) {
318-
// Allow increment or decrement of a POD type.
319-
if (auto *RefExpr = dyn_cast<DeclRefExpr>(UO->getSubExpr())) {
320-
if (auto *Decl = dyn_cast<VarDecl>(RefExpr->getDecl()))
321-
return Decl->isLocalVarDeclOrParm() &&
322-
Decl->getType().isPODType(Decl->getASTContext());
323-
}
324-
}
325-
// Other operators are non-trivial.
326-
return false;
312+
// Unary operators are trivial if its operand is trivial except co_await.
313+
return UO->getOpcode() != UO_Coawait && Visit(UO->getSubExpr());
327314
}
328315

329316
bool VisitBinaryOperator(const BinaryOperator *BO) {
@@ -364,7 +351,7 @@ class TrivialFunctionAnalysisVisitor
364351

365352
if (Name == "WTFCrashWithInfo" || Name == "WTFBreakpointTrap" ||
366353
Name == "WTFReportAssertionFailure" ||
367-
Name == "compilerFenceForCrash" || Name == "__builtin_unreachable")
354+
Name == "compilerFenceForCrash" || Name.find("__builtin") == 0)
368355
return true;
369356

370357
return TrivialFunctionAnalysis::isTrivialImpl(Callee, Cache);
@@ -405,6 +392,16 @@ class TrivialFunctionAnalysisVisitor
405392
return TrivialFunctionAnalysis::isTrivialImpl(Callee, Cache);
406393
}
407394

395+
bool VisitCXXOperatorCallExpr(const CXXOperatorCallExpr *OCE) {
396+
if (!checkArguments(OCE))
397+
return false;
398+
auto *Callee = OCE->getCalleeDecl();
399+
if (!Callee)
400+
return false;
401+
// Recursively descend into the callee to confirm that it's trivial as well.
402+
return TrivialFunctionAnalysis::isTrivialImpl(Callee, Cache);
403+
}
404+
408405
bool VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *E) {
409406
if (auto *Expr = E->getExpr()) {
410407
if (!Visit(Expr))

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

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,11 +138,29 @@ class Number {
138138
Number(int v) : v(v) { }
139139
Number(double);
140140
Number operator+(const Number&);
141+
Number& operator++() { ++v; return *this; }
142+
Number operator++(int) { Number returnValue(v); ++v; return returnValue; }
141143
const int& value() const { return v; }
144+
void someMethod();
145+
142146
private:
143147
int v;
144148
};
145149

150+
class ComplexNumber {
151+
public:
152+
ComplexNumber() : real(0), complex(0) { }
153+
ComplexNumber(const ComplexNumber&);
154+
ComplexNumber& operator++() { real.someMethod(); return *this; }
155+
ComplexNumber operator++(int);
156+
ComplexNumber& operator<<(int);
157+
ComplexNumber& operator+();
158+
159+
private:
160+
Number real;
161+
Number complex;
162+
};
163+
146164
class RefCounted {
147165
public:
148166
void ref() const;
@@ -210,6 +228,12 @@ class RefCounted {
210228
unsigned trivial32() { return sizeof(int); }
211229
unsigned trivial33() { return ~0xff; }
212230
template <unsigned v> unsigned trivial34() { return v; }
231+
void trivial35() { v++; }
232+
void trivial36() { ++(*number); }
233+
void trivial37() { (*number)++; }
234+
void trivial38() { v++; if (__builtin_expect(!!(number), 1)) (*number)++; }
235+
int trivial39() { return -v; }
236+
int trivial40() { return v << 2; }
213237

214238
static RefCounted& singleton() {
215239
static RefCounted s_RefCounted;
@@ -284,9 +308,14 @@ class RefCounted {
284308

285309
int nonTrivial13() { return ~otherFunction(); }
286310
int nonTrivial14() { int r = 0xff; r |= otherFunction(); return r; }
311+
void nonTrivial15() { ++complex; }
312+
void nonTrivial16() { complex++; }
313+
ComplexNumber nonTrivial17() { return complex << 2; }
314+
ComplexNumber nonTrivial18() { return +complex; }
287315

288316
unsigned v { 0 };
289317
Number* number { nullptr };
318+
ComplexNumber complex;
290319
Enum enumValue { Enum::Value1 };
291320
};
292321

@@ -342,6 +371,12 @@ class UnrelatedClass {
342371
getFieldTrivial().trivial32(); // no-warning
343372
getFieldTrivial().trivial33(); // no-warning
344373
getFieldTrivial().trivial34<7>(); // no-warning
374+
getFieldTrivial().trivial35(); // no-warning
375+
getFieldTrivial().trivial36(); // no-warning
376+
getFieldTrivial().trivial37(); // no-warning
377+
getFieldTrivial().trivial38(); // no-warning
378+
getFieldTrivial().trivial39(); // no-warning
379+
getFieldTrivial().trivial40(); // no-warning
345380

346381
RefCounted::singleton().trivial18(); // no-warning
347382
RefCounted::singleton().someFunction(); // no-warning
@@ -376,6 +411,14 @@ class UnrelatedClass {
376411
// expected-warning@-1{{Call argument for 'this' parameter is uncounted and unsafe}}
377412
getFieldTrivial().nonTrivial14();
378413
// expected-warning@-1{{Call argument for 'this' parameter is uncounted and unsafe}}
414+
getFieldTrivial().nonTrivial15();
415+
// expected-warning@-1{{Call argument for 'this' parameter is uncounted and unsafe}}
416+
getFieldTrivial().nonTrivial16();
417+
// expected-warning@-1{{Call argument for 'this' parameter is uncounted and unsafe}}
418+
getFieldTrivial().nonTrivial17();
419+
// expected-warning@-1{{Call argument for 'this' parameter is uncounted and unsafe}}
420+
getFieldTrivial().nonTrivial18();
421+
// expected-warning@-1{{Call argument for 'this' parameter is uncounted and unsafe}}
379422
}
380423
};
381424

0 commit comments

Comments
 (0)