llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: Ryosuke Niwa (rniwa) <details> <summary>Changes</summary> 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. --- Full diff: https://github.com/llvm/llvm-project/pull/91873.diff 2 Files Affected: - (modified) clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp (+17-2) - (modified) clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp (+58-5) ``````````diff 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 `````````` </details> https://github.com/llvm/llvm-project/pull/91873 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits