Skip to content

Commit

Permalink
[alpha.webkit.UncountedCallArgsChecker] Add support for Objective-C++…
Browse files Browse the repository at this point in the history
… property access (llvm#108669)

Treat a function call or property access via a Objective-C++ selector
which returns a Ref/RefPtr as safe.
  • Loading branch information
rniwa authored Sep 18, 2024
1 parent da0b9db commit 33533ba
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 6 deletions.
15 changes: 14 additions & 1 deletion clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
#include <optional>

namespace clang {
Expand All @@ -35,6 +36,12 @@ bool tryToFindPtrOrigin(
break;
}
}
if (auto *POE = dyn_cast<PseudoObjectExpr>(E)) {
if (auto *RF = POE->getResultExpr()) {
E = RF;
continue;
}
}
if (auto *tempExpr = dyn_cast<ParenExpr>(E)) {
E = tempExpr->getSubExpr();
continue;
Expand Down Expand Up @@ -88,7 +95,7 @@ bool tryToFindPtrOrigin(
continue;
}

if (isReturnValueRefCounted(callee))
if (isRefType(callee->getReturnType()))
return callback(E, true);

if (isSingleton(callee))
Expand All @@ -100,6 +107,12 @@ bool tryToFindPtrOrigin(
}
}
}
if (auto *ObjCMsgExpr = dyn_cast<ObjCMessageExpr>(E)) {
if (auto *Method = ObjCMsgExpr->getMethodDecl()) {
if (isRefType(Method->getReturnType()))
return callback(E, true);
}
}
if (auto *unaryOp = dyn_cast<UnaryOperator>(E)) {
// FIXME: Currently accepts ANY unary operator. Is it OK?
E = unaryOp->getSubExpr();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,9 +123,8 @@ bool isCtorOfRefCounted(const clang::FunctionDecl *F) {
|| FunctionName == "Identifier";
}

bool isReturnValueRefCounted(const clang::FunctionDecl *F) {
assert(F);
QualType type = F->getReturnType();
bool isRefType(const clang::QualType T) {
QualType type = T;
while (!type.isNull()) {
if (auto *elaboratedT = type->getAs<ElaboratedType>()) {
type = elaboratedT->desugar();
Expand Down
4 changes: 2 additions & 2 deletions clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,8 @@ bool isRefType(const std::string &Name);
/// false if not.
bool isCtorOfRefCounted(const clang::FunctionDecl *F);

/// \returns true if \p F returns a ref-counted object, false if not.
bool isReturnValueRefCounted(const clang::FunctionDecl *F);
/// \returns true if \p T is RefPtr, Ref, or its variant, false if not.
bool isRefType(const clang::QualType T);

/// \returns true if \p M is getter of a ref-counted class, false if not.
std::optional<bool> isGetterOfRefCounted(const clang::CXXMethodDecl* Method);
Expand Down
17 changes: 17 additions & 0 deletions clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.mm
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,20 @@ - (void)execute {
}

@end

class RefCountedObject {
public:
void ref() const;
void deref() const;
Ref<RefCountedObject> copy() const;
};

@interface WrapperObj : NSObject

- (Ref<RefCountedObject>)_protectedWebExtensionControllerConfiguration;

@end

static void foo(WrapperObj *configuration) {
configuration._protectedWebExtensionControllerConfiguration->copy();
}

0 comments on commit 33533ba

Please sign in to comment.