llvm-project/clang/test/SemaObjC/arc-repeated-weak.mm
Aaron Ballman 0f1c1be196 [clang] Remove rdar links; NFC
We have a new policy in place making links to private resources
something we try to avoid in source and test files. Normally, we'd
organically switch to the new policy rather than make a sweeping change
across a project. However, Clang is in a somewhat special circumstance
currently: recently, I've had several new contributors run into rdar
links around test code which their patch was changing the behavior of.
This turns out to be a surprisingly bad experience, especially for
newer folks, for a handful of reasons: not understanding what the link
is and feeling intimidated by it, wondering whether their changes are
actually breaking something important to a downstream in some way,
having to hunt down strangers not involved with the patch to impose on
them for help, accidental pressure from asking for potentially private
IP to be made public, etc. Because folks run into these links entirely
by chance (through fixing bugs or working on new features), there's not
really a set of problematic links to focus on -- all of the links have
basically the same potential for causing these problems. As a result,
this is an omnibus patch to remove all such links.

This was not a mechanical change; it was done by manually searching for
rdar, radar, radr, and other variants to find all the various
problematic links. From there, I tried to retain or reword the
surrounding comments so that we would lose as little context as
possible. However, because most links were just a plain link with no
supporting context, the majority of the changes are simple removals.

Differential Review: https://reviews.llvm.org/D158071
2023-08-28 12:13:42 -04:00

512 lines
14 KiB
Plaintext

// RUN: %clang_cc1 -fsyntax-only -fobjc-runtime-has-weak -fobjc-arc -fblocks -Wno-objc-root-class -std=c++11 -Warc-repeated-use-of-weak -verify %s
// RUN: %clang_cc1 -fsyntax-only -fobjc-runtime-has-weak -fobjc-weak -fblocks -Wno-objc-root-class -std=c++11 -Warc-repeated-use-of-weak -verify %s
@interface Test {
@public
Test *ivar;
__weak id weakIvar;
}
@property(weak) Test *weakProp;
@property(strong) Test *strongProp;
- (__weak id)implicitProp;
+ (__weak id)weakProp;
@end
extern void use(id);
extern id get();
extern bool condition();
#define nil ((id)0)
void basicCorrectnessTest(Test *a) {
use(a.weakProp); // expected-warning{{weak property 'weakProp' is accessed multiple times in this function but may be unpredictably set to nil; assign to a strong variable to keep the object alive}}
use(a.weakProp); // expected-note{{also accessed here}}
use(a.strongProp);
use(a.strongProp); // no-warning
use(a.weakProp); // expected-note{{also accessed here}}
}
void singleUse(Test *a) {
use(a.weakProp); // no-warning
use(a.strongProp); // no-warning
}
void assignsOnly(Test *a) {
a.weakProp = get(); // no-warning
id next = get();
if (next)
a.weakProp = next; // no-warning
a->weakIvar = get(); // no-warning
next = get();
if (next)
a->weakIvar = next; // no-warning
extern __weak id x;
x = get(); // no-warning
next = get();
if (next)
x = next; // no-warning
}
void assignThenRead(Test *a) {
a.weakProp = get(); // expected-note{{also accessed here}}
use(a.weakProp); // expected-warning{{weak property 'weakProp' is accessed multiple times}}
}
void twoVariables(Test *a, Test *b) {
use(a.weakProp); // no-warning
use(b.weakProp); // no-warning
}
void doubleLevelAccess(Test *a) {
use(a.strongProp.weakProp); // expected-warning{{weak property 'weakProp' may be accessed multiple times in this function and may be unpredictably set to nil; assign to a strong variable to keep the object alive}}
use(a.strongProp.weakProp); // expected-note{{also accessed here}}
}
void doubleLevelAccessIvar(Test *a) {
use(a.strongProp.weakProp); // expected-warning{{weak property 'weakProp' may be accessed multiple times}}
use(a.strongProp.weakProp); // expected-note{{also accessed here}}
}
void implicitProperties(Test *a) {
use(a.implicitProp); // expected-warning{{weak implicit property 'implicitProp' is accessed multiple times}}
use(a.implicitProp); // expected-note{{also accessed here}}
}
void classProperties() {
use(Test.weakProp); // expected-warning{{weak implicit property 'weakProp' is accessed multiple times}}
use(Test.weakProp); // expected-note{{also accessed here}}
}
void classPropertiesAreDifferent(Test *a) {
use(Test.weakProp); // no-warning
use(a.weakProp); // no-warning
use(a.strongProp.weakProp); // no-warning
}
void ivars(Test *a) {
use(a->weakIvar); // expected-warning{{weak instance variable 'weakIvar' is accessed multiple times}}
use(a->weakIvar); // expected-note{{also accessed here}}
}
void globals() {
extern __weak id a;
use(a); // expected-warning{{weak variable 'a' is accessed multiple times}}
use(a); // expected-note{{also accessed here}}
}
void messageGetter(Test *a) {
use([a weakProp]); // expected-warning{{weak property 'weakProp' is accessed multiple times}}
use([a weakProp]); // expected-note{{also accessed here}}
}
void messageSetter(Test *a) {
[a setWeakProp:get()]; // no-warning
[a setWeakProp:get()]; // no-warning
}
void messageSetterAndGetter(Test *a) {
[a setWeakProp:get()]; // expected-note{{also accessed here}}
use([a weakProp]); // expected-warning{{weak property 'weakProp' is accessed multiple times}}
}
void mixDotAndMessageSend(Test *a, Test *b) {
use(a.weakProp); // expected-warning{{weak property 'weakProp' is accessed multiple times}}
use([a weakProp]); // expected-note{{also accessed here}}
use([b weakProp]); // expected-warning{{weak property 'weakProp' is accessed multiple times}}
use(b.weakProp); // expected-note{{also accessed here}}
}
void assignToStrongWrongInit(Test *a) {
id val = a.weakProp; // expected-note{{also accessed here}}
use(a.weakProp); // expected-warning{{weak property 'weakProp' is accessed multiple times}}
}
void assignToStrongWrong(Test *a) {
id val;
val = a.weakProp; // expected-note{{also accessed here}}
use(a.weakProp); // expected-warning{{weak property 'weakProp' is accessed multiple times}}
}
void assignToIvarWrong(Test *a) {
a->weakIvar = get(); // expected-note{{also accessed here}}
use(a->weakIvar); // expected-warning{{weak instance variable 'weakIvar' is accessed multiple times}}
}
void assignToGlobalWrong() {
extern __weak id a;
a = get(); // expected-note{{also accessed here}}
use(a); // expected-warning{{weak variable 'a' is accessed multiple times}}
}
void assignToStrongOK(Test *a) {
if (condition()) {
id val = a.weakProp; // no-warning
(void)val;
} else {
id val;
val = a.weakProp; // no-warning
(void)val;
}
}
void assignToStrongConditional(Test *a) {
id val = (condition() ? a.weakProp : a.weakProp); // no-warning
id val2 = a.implicitProp ?: a.implicitProp; // no-warning
}
void testBlock(Test *a) {
use(a.weakProp); // no-warning
use(^{
use(a.weakProp); // expected-warning{{weak property 'weakProp' is accessed multiple times in this block}}
use(a.weakProp); // expected-note{{also accessed here}}
});
}
void assignToStrongWithCasts(Test *a) {
if (condition()) {
Test *val = (Test *)a.weakProp; // no-warning
(void)val;
} else {
id val;
val = (Test *)a.weakProp; // no-warning
(void)val;
}
}
void assignToStrongWithMessages(Test *a) {
if (condition()) {
id val = [a weakProp]; // no-warning
(void)val;
} else {
id val;
val = [a weakProp]; // no-warning
(void)val;
}
}
void assignAfterRead(Test *a) {
// Special exception for a single read before any writes.
if (!a.weakProp) // no-warning
a.weakProp = get(); // no-warning
}
void readOnceWriteMany(Test *a) {
if (!a.weakProp) { // no-warning
a.weakProp = get(); // no-warning
a.weakProp = get(); // no-warning
}
}
void readOnceAfterWrite(Test *a) {
a.weakProp = get(); // expected-note{{also accessed here}}
if (!a.weakProp) { // expected-warning{{weak property 'weakProp' is accessed multiple times in this function}}
a.weakProp = get(); // expected-note{{also accessed here}}
}
}
void readOnceWriteManyLoops(Test *a, Test *b, Test *c, Test *d, Test *e) {
while (condition()) {
if (!a.weakProp) { // expected-warning{{weak property 'weakProp' is accessed multiple times in this function}}
a.weakProp = get(); // expected-note{{also accessed here}}
a.weakProp = get(); // expected-note{{also accessed here}}
}
}
do {
if (!b.weakProp) { // expected-warning{{weak property 'weakProp' is accessed multiple times in this function}}
b.weakProp = get(); // expected-note{{also accessed here}}
b.weakProp = get(); // expected-note{{also accessed here}}
}
} while (condition());
for (id x = get(); x; x = get()) {
if (!c.weakProp) { // expected-warning{{weak property 'weakProp' is accessed multiple times in this function}}
c.weakProp = get(); // expected-note{{also accessed here}}
c.weakProp = get(); // expected-note{{also accessed here}}
}
}
for (id x in get()) {
if (!d.weakProp) { // expected-warning{{weak property 'weakProp' is accessed multiple times in this function}}
d.weakProp = get(); // expected-note{{also accessed here}}
d.weakProp = get(); // expected-note{{also accessed here}}
}
}
int array[] = { 1, 2, 3 };
for (int i : array) {
if (!e.weakProp) { // expected-warning{{weak property 'weakProp' is accessed multiple times in this function}}
e.weakProp = get(); // expected-note{{also accessed here}}
e.weakProp = get(); // expected-note{{also accessed here}}
}
}
}
void readOnlyLoop(Test *a) {
while (condition()) {
use(a.weakProp); // expected-warning{{weak property 'weakProp' is accessed multiple times in this function}}
}
}
void readInIterationLoop() {
for (Test *a in get())
use(a.weakProp); // no-warning
}
void readDoubleLevelAccessInLoop() {
for (Test *a in get()) {
use(a.strongProp.weakProp); // no-warning
}
}
void readParameterInLoop(Test *a) {
for (id unused in get()) {
use(a.weakProp); // expected-warning{{weak property 'weakProp' is accessed multiple times in this function}}
(void)unused;
}
}
void readGlobalInLoop() {
static __weak id a;
for (id unused in get()) {
use(a); // expected-warning{{weak variable 'a' is accessed multiple times in this function}}
(void)unused;
}
}
void doWhileLoop(Test *a) {
do {
use(a.weakProp); // no-warning
} while(0);
}
struct S {
int a;
id b;
};
@interface C
@property S p;
@end
void test_list_init(C *c) {
c.p = {0, c.p.b};
}
@interface Test (Methods)
@end
@implementation Test (Methods)
- (void)basicCorrectnessTest {
use(self.weakProp); // expected-warning{{weak property 'weakProp' is accessed multiple times in this method but may be unpredictably set to nil; assign to a strong variable to keep the object alive}}
use(self.weakProp); // expected-note{{also accessed here}}
}
- (void)ivars {
use(weakIvar); // expected-warning{{weak instance variable 'weakIvar' is accessed multiple times in this method but may be unpredictably set to nil; assign to a strong variable to keep the object alive}}
use(weakIvar); // expected-note{{also accessed here}}
}
- (void)doubleLevelAccessForSelf {
use(self.strongProp.weakProp); // expected-warning{{weak property 'weakProp' is accessed multiple times}}
use(self.strongProp.weakProp); // expected-note{{also accessed here}}
use(self->ivar.weakProp); // expected-warning{{weak property 'weakProp' is accessed multiple times}}
use(self->ivar.weakProp); // expected-note{{also accessed here}}
use(self->ivar->weakIvar); // expected-warning{{weak instance variable 'weakIvar' is accessed multiple times}}
use(self->ivar->weakIvar); // expected-note{{also accessed here}}
}
- (void)distinctFromOther:(Test *)other {
use(self.strongProp.weakProp); // no-warning
use(other.strongProp.weakProp); // no-warning
use(self->ivar.weakProp); // no-warning
use(other->ivar.weakProp); // no-warning
use(self.strongProp->weakIvar); // no-warning
use(other.strongProp->weakIvar); // no-warning
}
@end
@interface Base1
@end
@interface Sub1 : Base1
@end
@interface Sub1(cat)
-(id)prop;
@end
void test1(Sub1 *s) {
use([s prop]);
use([s prop]);
}
@interface Base1(cat)
@property (weak) id prop;
@end
void test2(Sub1 *s) {
// This does not warn because the "prop" in "Base1(cat)" was introduced
// after the method declaration and we don't find it as overridden.
// Always looking for overridden methods after the method declaration is expensive
// and it's not clear it is worth it currently.
use([s prop]);
use([s prop]);
}
class Wrapper {
Test *a;
public:
void fields() {
use(a.weakProp); // expected-warning{{weak property 'weakProp' is accessed multiple times in this function but may be unpredictably set to nil; assign to a strong variable to keep the object alive}}
use(a.weakProp); // expected-note{{also accessed here}}
}
void distinctFromOther(Test *b, const Wrapper &w) {
use(a.weakProp); // no-warning
use(b.weakProp); // no-warning
use(w.a.weakProp); // no-warning
}
static void doubleLevelAccessField(const Wrapper &x, const Wrapper &y) {
use(x.a.weakProp); // expected-warning{{weak property 'weakProp' may be accessed multiple times}}
use(y.a.weakProp); // expected-note{{also accessed here}}
}
};
// -----------------------
// False positives
// -----------------------
// Most of these would require flow-sensitive analysis to silence correctly.
void assignNil(Test *a) {
if (condition())
a.weakProp = nil; // expected-note{{also accessed here}}
use(a.weakProp); // expected-warning{{weak property 'weakProp' is accessed multiple times}}
}
void branch(Test *a) {
if (condition())
use(a.weakProp); // expected-warning{{weak property 'weakProp' is accessed multiple times}}
else
use(a.weakProp); // expected-note{{also accessed here}}
}
void doubleLevelAccess(Test *a, Test *b) {
use(a.strongProp.weakProp); // expected-warning{{weak property 'weakProp' may be accessed multiple times}}
use(b.strongProp.weakProp); // expected-note{{also accessed here}}
use(a.weakProp.weakProp); // no-warning
}
void doubleLevelAccessIvar(Test *a, Test *b) {
use(a->ivar.weakProp); // expected-warning{{weak property 'weakProp' may be accessed multiple times}}
use(b->ivar.weakProp); // expected-note{{also accessed here}}
use(a.strongProp.weakProp); // no-warning
}
@interface X
@end
@implementation X
- (int) warningAboutWeakVariableInsideTypeof {
__typeof__(self) __weak weakSelf = self;
^(){
__typeof__(weakSelf) blockSelf = weakSelf;
use(blockSelf);
}();
return sizeof(weakSelf);
}
@end
@interface NSNull
+ (NSNull *)null;
@end
@interface INTF @end
@implementation INTF
- (void) Meth : (id) data
{
data = data ?: NSNull.null;
}
@end
// This used to crash in WeakObjectProfileTy::getBaseInfo when getBase() was
// called on an ObjCPropertyRefExpr object whose receiver was an interface.
@class NSString;
@interface NSBundle
+(NSBundle *)foo;
@property (class, strong) NSBundle *foo2;
@property (strong) NSString *prop;
@property(weak) NSString *weakProp;
@end
@interface NSBundle2 : NSBundle
@end
void foo() {
NSString * t = NSBundle.foo.prop;
use(NSBundle.foo.weakProp); // expected-warning{{weak property 'weakProp' may be accessed multiple times}}
use(NSBundle2.foo.weakProp); // expected-note{{also accessed here}}
NSString * t2 = NSBundle.foo2.prop;
use(NSBundle.foo2.weakProp); // expected-warning{{weak property 'weakProp' may be accessed multiple times}}
use(NSBundle2.foo2.weakProp); // expected-note{{also accessed here}}
decltype([NSBundle2.foo2 weakProp]) t3;
decltype(NSBundle2.foo2.weakProp) t4;
__typeof__(NSBundle2.foo2.weakProp) t5;
}
// This used to crash in the constructor of WeakObjectProfileTy when a
// DeclRefExpr was passed that didn't reference a VarDecl.
typedef INTF * INTFPtrTy;
enum E {
e1
};
void foo1() {
INTFPtrTy tmp = (INTFPtrTy)e1;
#if __has_feature(objc_arc)
// expected-error@-2{{cast of 'E' to 'INTFPtrTy' (aka 'INTF *') is disallowed with ARC}}
#endif
}
@class NSString;
static NSString* const kGlobal = @"";
@interface NSDictionary
- (id)objectForKeyedSubscript:(id)key;
@end
@interface WeakProp
@property (weak) NSDictionary *nd;
@end
@implementation WeakProp
-(void)m {
(void)self.nd[@""]; // no warning
}
@end