mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-18 13:36:39 +00:00

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
512 lines
14 KiB
Plaintext
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
|