Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -496,6 +496,8 @@ class UnretainedLambdaCapturesChecker : public RawPtrRefLambdaCapturesChecker {
}

std::optional<bool> isUnsafePtr(QualType QT) const final {
if (QT.hasStrongOrWeakObjCLifetime())
return false;
return RTC->isUnretained(QT);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -433,6 +433,8 @@ class UnretainedLocalVarsChecker final : public RawPtrRefLocalVarsChecker {
RTC = RetainTypeChecker();
}
std::optional<bool> isUnsafePtr(const QualType T) const final {
if (T.hasStrongOrWeakObjCLifetime())
return false;
return RTC->isUnretained(T);
}
bool isSafePtr(const CXXRecordDecl *Record) const final {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -231,8 +231,11 @@ class RawPtrRefMemberChecker
// "assign" property doesn't retain even under ARC so treat it as unsafe.
bool ignoreARC =
!PD->isReadOnly() && PD->getSetterKind() == ObjCPropertyDecl::Assign;
bool IsWeak =
PD->getPropertyAttributes() & ObjCPropertyAttribute::kind_weak;
bool HasSafeAttr = PD->isRetaining() || IsWeak;
auto IsUnsafePtr = isUnsafePtr(QT, ignoreARC);
return {IsUnsafePtr && *IsUnsafePtr && !PD->isRetaining(), PropType};
return {IsUnsafePtr && *IsUnsafePtr && !HasSafeAttr, PropType};
}

bool shouldSkipDecl(const RecordDecl *RD) const {
Expand Down Expand Up @@ -363,6 +366,8 @@ class NoUnretainedMemberChecker final : public RawPtrRefMemberChecker {
}

std::optional<bool> isUnsafePtr(QualType QT, bool ignoreARC) const final {
if (QT.hasStrongOrWeakObjCLifetime())
return false;
return RTC->isUnretained(QT, ignoreARC);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// RUN: %clang_analyze_cc1 -analyzer-checker=alpha.webkit.UnretainedLambdaCapturesChecker -fobjc-runtime-has-weak -fobjc-weak -fobjc-arc -verify %s
// expected-no-diagnostics

#include "objc-mock-types.h"

void someFunction();
template <typename Callback> void call(Callback callback) {
someFunction();
callback();
}

NSString *provideStr();
SomeObj *provideSomeObj();

void foo() {
__weak NSString *weakStr = provideStr();
__weak SomeObj *weakObj = provideSomeObj();
auto lambda = [weakStr, weakObj]() {
return [weakStr length] + [weakObj value];
};
call(lambda);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// RUN: %clang_analyze_cc1 -analyzer-checker=alpha.webkit.UnretainedLambdaCapturesChecker -fobjc-runtime-has-weak -fobjc-weak -verify %s
// expected-no-diagnostics

#include "objc-mock-types.h"

void someFunction();
template <typename Callback> void call(Callback callback) {
someFunction();
callback();
}

NSString *provideStr();
SomeObj *provideSomeObj();

void foo() {
__weak NSString *weakStr = provideStr();
__weak SomeObj *weakObj = provideSomeObj();
auto lambda = [weakStr, weakObj]() {
return [weakStr length] + [weakObj value];
};
call(lambda);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// RUN: %clang_analyze_cc1 -analyzer-checker=alpha.webkit.UnretainedLocalVarsChecker -fobjc-runtime-has-weak -fobjc-weak -fobjc-arc -verify %s
// expected-no-diagnostics

#include "objc-mock-types.h"

NSString *provideStr();
SomeObj *provideSomeObj();

int foo() {
__weak NSString *weakStr = provideStr();
__weak SomeObj *weakObj = provideSomeObj();
return [weakStr length] + [weakObj value];
}
13 changes: 13 additions & 0 deletions clang/test/Analysis/Checkers/WebKit/unretained-local-vars-weak.mm
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// RUN: %clang_analyze_cc1 -analyzer-checker=alpha.webkit.UnretainedLocalVarsChecker -fobjc-runtime-has-weak -fobjc-weak -verify %s
// expected-no-diagnostics

#include "objc-mock-types.h"

NSString *provideStr();
SomeObj *provideSomeObj();

int foo() {
__weak NSString *weakStr = provideStr();
__weak SomeObj *weakObj = provideSomeObj();
return [weakStr length] + [weakObj value];
}
29 changes: 29 additions & 0 deletions clang/test/Analysis/Checkers/WebKit/unretained-members-weak-arc.mm
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// RUN: %clang_analyze_cc1 -analyzer-checker=alpha.webkit.NoUnretainedMemberChecker -fobjc-runtime-has-weak -fobjc-weak -fobjc-arc -verify %s
// expected-no-diagnostics

#include "objc-mock-types.h"

struct Foo {
__weak NSString *weakPtr = nullptr;
Foo();
~Foo();
void bar();
};

@interface ObjectWithWeakProperty : NSObject
@property(nonatomic, weak) NSString *weak_prop;
@end

@implementation ObjectWithWeakProperty
@end

NS_REQUIRES_PROPERTY_DEFINITIONS
@interface NoSynthesisObjectWithWeakProperty : NSObject
@property(nonatomic, readonly, weak) NSString *weak_prop;
@end

@implementation NoSynthesisObjectWithWeakProperty
- (NSString *)weak_prop {
return nil;
}
@end
31 changes: 31 additions & 0 deletions clang/test/Analysis/Checkers/WebKit/unretained-members-weak.mm
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// RUN: %clang_analyze_cc1 -analyzer-checker=alpha.webkit.NoUnretainedMemberChecker -fobjc-runtime-has-weak -fobjc-weak -verify %s
// expected-no-diagnostics

#include "objc-mock-types.h"

struct Foo {
__weak NSString *weakPtr = nullptr;
Foo();
~Foo();
void bar();
};

@interface ObjectWithWeakProperty : NSObject
@property(nonatomic, weak) NSString *weak_prop;
@end

@implementation ObjectWithWeakProperty
@end

NS_REQUIRES_PROPERTY_DEFINITIONS
@interface NoSynthesisObjectWithWeakProperty : NSObject
@property(nonatomic, readonly, weak) NSString *weak_prop;
@end

@implementation NoSynthesisObjectWithWeakProperty {
__weak NSNumber *weak_ivar;
}
- (NSString *)weak_prop {
return nil;
}
@end
Loading