Skip to content

Commit e2a5d28

Browse files
committed
[WebKit checkers] Treat a weak property / variable as safe
Treat a weak Objective-C property, ivar, member variable, and local variable as safe.
1 parent b626282 commit e2a5d28

9 files changed

+139
-1
lines changed

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -496,6 +496,8 @@ class UnretainedLambdaCapturesChecker : public RawPtrRefLambdaCapturesChecker {
496496
}
497497

498498
std::optional<bool> isUnsafePtr(QualType QT) const final {
499+
if (QT.hasStrongOrWeakObjCLifetime())
500+
return false;
499501
return RTC->isUnretained(QT);
500502
}
501503

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -433,6 +433,8 @@ class UnretainedLocalVarsChecker final : public RawPtrRefLocalVarsChecker {
433433
RTC = RetainTypeChecker();
434434
}
435435
std::optional<bool> isUnsafePtr(const QualType T) const final {
436+
if (T.hasStrongOrWeakObjCLifetime())
437+
return false;
436438
return RTC->isUnretained(T);
437439
}
438440
bool isSafePtr(const CXXRecordDecl *Record) const final {

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -231,8 +231,10 @@ class RawPtrRefMemberChecker
231231
// "assign" property doesn't retain even under ARC so treat it as unsafe.
232232
bool ignoreARC =
233233
!PD->isReadOnly() && PD->getSetterKind() == ObjCPropertyDecl::Assign;
234+
bool IsWeak = PD->getPropertyAttributes() & ObjCPropertyAttribute::kind_weak;
235+
bool HasSafeAttr = PD->isRetaining() || IsWeak;
234236
auto IsUnsafePtr = isUnsafePtr(QT, ignoreARC);
235-
return {IsUnsafePtr && *IsUnsafePtr && !PD->isRetaining(), PropType};
237+
return {IsUnsafePtr && *IsUnsafePtr && !HasSafeAttr, PropType};
236238
}
237239

238240
bool shouldSkipDecl(const RecordDecl *RD) const {
@@ -363,6 +365,8 @@ class NoUnretainedMemberChecker final : public RawPtrRefMemberChecker {
363365
}
364366

365367
std::optional<bool> isUnsafePtr(QualType QT, bool ignoreARC) const final {
368+
if (QT.hasStrongOrWeakObjCLifetime())
369+
return false;
366370
return RTC->isUnretained(QT, ignoreARC);
367371
}
368372

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// RUN: %clang_analyze_cc1 -analyzer-checker=alpha.webkit.UnretainedLambdaCapturesChecker -fobjc-runtime-has-weak -fobjc-weak -fobjc-arc -verify %s
2+
// expected-no-diagnostics
3+
4+
#include "objc-mock-types.h"
5+
6+
void someFunction();
7+
template <typename Callback> void call(Callback callback) {
8+
someFunction();
9+
callback();
10+
}
11+
12+
NSString *provideStr();
13+
SomeObj *provideSomeObj();
14+
15+
void foo() {
16+
__weak NSString *weakStr = provideStr();
17+
__weak SomeObj *weakObj = provideSomeObj();
18+
auto lambda = [weakStr, weakObj]() {
19+
return [weakStr length] + [weakObj value];
20+
};
21+
call(lambda);
22+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// RUN: %clang_analyze_cc1 -analyzer-checker=alpha.webkit.UnretainedLambdaCapturesChecker -fobjc-runtime-has-weak -fobjc-weak -verify %s
2+
// expected-no-diagnostics
3+
4+
#include "objc-mock-types.h"
5+
6+
void someFunction();
7+
template <typename Callback> void call(Callback callback) {
8+
someFunction();
9+
callback();
10+
}
11+
12+
NSString *provideStr();
13+
SomeObj *provideSomeObj();
14+
15+
void foo() {
16+
__weak NSString *weakStr = provideStr();
17+
__weak SomeObj *weakObj = provideSomeObj();
18+
auto lambda = [weakStr, weakObj]() {
19+
return [weakStr length] + [weakObj value];
20+
};
21+
call(lambda);
22+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// RUN: %clang_analyze_cc1 -analyzer-checker=alpha.webkit.UnretainedLocalVarsChecker -fobjc-runtime-has-weak -fobjc-weak -fobjc-arc -verify %s
2+
// expected-no-diagnostics
3+
4+
#include "objc-mock-types.h"
5+
6+
NSString *provideStr();
7+
SomeObj *provideSomeObj();
8+
9+
int foo() {
10+
__weak NSString *weakStr = provideStr();
11+
__weak SomeObj *weakObj = provideSomeObj();
12+
return [weakStr length] + [weakObj value];
13+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// RUN: %clang_analyze_cc1 -analyzer-checker=alpha.webkit.UnretainedLocalVarsChecker -fobjc-runtime-has-weak -fobjc-weak -verify %s
2+
// expected-no-diagnostics
3+
4+
#include "objc-mock-types.h"
5+
6+
NSString *provideStr();
7+
SomeObj *provideSomeObj();
8+
9+
int foo() {
10+
__weak NSString *weakStr = provideStr();
11+
__weak SomeObj *weakObj = provideSomeObj();
12+
return [weakStr length] + [weakObj value];
13+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// RUN: %clang_analyze_cc1 -analyzer-checker=alpha.webkit.NoUnretainedMemberChecker -fobjc-runtime-has-weak -fobjc-weak -fobjc-arc -verify %s
2+
// expected-no-diagnostics
3+
4+
#include "objc-mock-types.h"
5+
6+
struct Foo {
7+
__weak NSString *weakPtr = nullptr;
8+
Foo();
9+
~Foo();
10+
void bar();
11+
};
12+
13+
@interface ObjectWithWeakProperty : NSObject
14+
@property(nonatomic, weak) NSString *weak_prop;
15+
@end
16+
17+
@implementation ObjectWithWeakProperty
18+
@end
19+
20+
NS_REQUIRES_PROPERTY_DEFINITIONS
21+
@interface NoSynthesisObjectWithWeakProperty : NSObject
22+
@property(nonatomic, readonly, weak) NSString *weak_prop;
23+
@end
24+
25+
@implementation NoSynthesisObjectWithWeakProperty
26+
- (NSString *)weak_prop {
27+
return nil;
28+
}
29+
@end
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// RUN: %clang_analyze_cc1 -analyzer-checker=alpha.webkit.NoUnretainedMemberChecker -fobjc-runtime-has-weak -fobjc-weak -verify %s
2+
// expected-no-diagnostics
3+
4+
#include "objc-mock-types.h"
5+
6+
struct Foo {
7+
__weak NSString *weakPtr = nullptr;
8+
Foo();
9+
~Foo();
10+
void bar();
11+
};
12+
13+
@interface ObjectWithWeakProperty : NSObject
14+
@property(nonatomic, weak) NSString *weak_prop;
15+
@end
16+
17+
@implementation ObjectWithWeakProperty
18+
@end
19+
20+
NS_REQUIRES_PROPERTY_DEFINITIONS
21+
@interface NoSynthesisObjectWithWeakProperty : NSObject
22+
@property(nonatomic, readonly, weak) NSString *weak_prop;
23+
@end
24+
25+
@implementation NoSynthesisObjectWithWeakProperty {
26+
__weak NSNumber *weak_ivar;
27+
}
28+
- (NSString *)weak_prop {
29+
return nil;
30+
}
31+
@end

0 commit comments

Comments
 (0)