From 72200fcc346bee1830d9e640e42d717a55acd74c Mon Sep 17 00:00:00 2001 From: Ryosuke Niwa Date: Wed, 15 May 2024 18:16:39 -0700 Subject: [PATCH] [analyzer] Check C++ base or member initializer in WebKit checkers. (#92220) Co-authored-by: Ryosuke Niwa --- .../Checkers/WebKit/PtrTypesSemantics.cpp | 10 ++++++++- .../Checkers/WebKit/uncounted-obj-arg.cpp | 21 +++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp index 950d35a090a3f7..5c797d5233089a 100644 --- a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp @@ -525,11 +525,19 @@ bool TrivialFunctionAnalysis::isTrivialImpl( if (!IsNew) return It->second; + TrivialFunctionAnalysisVisitor V(Cache); + + if (auto *CtorDecl = dyn_cast(D)) { + for (auto *CtorInit : CtorDecl->inits()) { + if (!V.Visit(CtorInit->getInit())) + return false; + } + } + const Stmt *Body = D->getBody(); if (!Body) return false; - TrivialFunctionAnalysisVisitor V(Cache); bool Result = V.Visit(Body); if (Result) Cache[D] = true; diff --git a/clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp b/clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp index ed37671df3d3eb..96986631726fe3 100644 --- a/clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp +++ b/clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp @@ -159,10 +159,13 @@ template class OptionSet { StorageType m_storage { 0 }; }; +int atoi(const char* str); + class Number { public: Number(int v) : v(v) { } Number(double); + Number(const char* str) : v(atoi(str)) { } Number operator+(const Number&); Number& operator++() { ++v; return *this; } Number operator++(int) { Number returnValue(v); ++v; return returnValue; } @@ -173,9 +176,16 @@ class Number { int v; }; +class DerivedNumber : public Number { +public: + DerivedNumber(char c) : Number(c - '0') { } + DerivedNumber(const char* str) : Number(atoi(str)) { } +}; + class ComplexNumber { public: ComplexNumber() : realPart(0), complexPart(0) { } + ComplexNumber(int real, const char* str) : realPart(real), complexPart(str) { } ComplexNumber(const ComplexNumber&); ComplexNumber& operator++() { realPart.someMethod(); return *this; } ComplexNumber operator++(int); @@ -311,6 +321,7 @@ class RefCounted { return; } unsigned trivial60() { return ObjectWithNonTrivialDestructor { 5 }.value(); } + unsigned trivial61() { return DerivedNumber('7').value(); } static RefCounted& singleton() { static RefCounted s_RefCounted; @@ -391,6 +402,9 @@ class RefCounted { ComplexNumber nonTrivial18() { return +complex; } ComplexNumber* nonTrivial19() { return new ComplexNumber(complex); } unsigned nonTrivial20() { return ObjectWithMutatingDestructor { 7 }.value(); } + unsigned nonTrivial21() { return Number("123").value(); } + unsigned nonTrivial22() { return ComplexNumber(123, "456").real().value(); } + unsigned nonTrivial23() { return DerivedNumber("123").value(); } static unsigned s_v; unsigned v { 0 }; @@ -479,6 +493,7 @@ class UnrelatedClass { getFieldTrivial().trivial58(); // no-warning getFieldTrivial().trivial59(); // no-warning getFieldTrivial().trivial60(); // no-warning + getFieldTrivial().trivial61(); // no-warning RefCounted::singleton().trivial18(); // no-warning RefCounted::singleton().someFunction(); // no-warning @@ -525,6 +540,12 @@ class UnrelatedClass { // expected-warning@-1{{Call argument for 'this' parameter is uncounted and unsafe}} getFieldTrivial().nonTrivial20(); // expected-warning@-1{{Call argument for 'this' parameter is uncounted and unsafe}} + getFieldTrivial().nonTrivial21(); + // expected-warning@-1{{Call argument for 'this' parameter is uncounted and unsafe}} + getFieldTrivial().nonTrivial22(); + // expected-warning@-1{{Call argument for 'this' parameter is uncounted and unsafe}} + getFieldTrivial().nonTrivial23(); + // expected-warning@-1{{Call argument for 'this' parameter is uncounted and unsafe}} } };