Skip to content

Commit 85b9220

Browse files
committed
[objc_direct] Allow for direct messages be sent to self when it is a Class
Sending a message to `self` when it is const and within a class method is safe because we know that `self` is the Class itself. We can only relax this warning in ARC. Signed-off-by: Pierre Habouzit <[email protected]> Radar-Id: rdar://problem/58581965 Differential Revision: https://reviews.llvm.org/D72747 (cherry picked from commit 7596d3c)
1 parent 7e391ca commit 85b9220

File tree

3 files changed

+56
-1
lines changed

3 files changed

+56
-1
lines changed

clang/lib/Sema/SemaExprObjC.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3009,7 +3009,11 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
30093009
<< Method->getDeclName();
30103010
}
30113011

3012-
if (ReceiverType->isObjCClassType() && !isImplicit) {
3012+
// Under ARC, self can't be assigned, and doing a direct call to `self`
3013+
// when it's a Class is hence safe. For other cases, we can't trust `self`
3014+
// is what we think it is, so we reject it.
3015+
if (ReceiverType->isObjCClassType() && !isImplicit &&
3016+
!(Receiver->isObjCSelfExpr() && getLangOpts().ObjCAutoRefCount)) {
30133017
Diag(Receiver->getExprLoc(),
30143018
diag::err_messaging_class_with_direct_method);
30153019
Diag(Method->getLocation(), diag::note_direct_method_declared_at)
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// RUN: %clang_cc1 -fobjc-arc -fsyntax-only -verify -Wselector-type-mismatch %s
2+
3+
extern Class object_getClass(id);
4+
5+
__attribute__((objc_root_class))
6+
@interface Root
7+
- (Class)class;
8+
+ (void)directMethod __attribute__((objc_direct)); // expected-note {{direct method 'directMethod' declared here}}
9+
+ (void)anotherDirectMethod __attribute__((objc_direct));
10+
@end
11+
12+
@implementation Root
13+
- (Class)class
14+
{
15+
return object_getClass(self);
16+
}
17+
+ (void)directMethod {
18+
}
19+
+ (void)anotherDirectMethod {
20+
[self directMethod]; // this should not warn
21+
}
22+
+ (void)regularMethod {
23+
[self directMethod]; // this should not warn
24+
[self anotherDirectMethod]; // this should not warn
25+
}
26+
- (void)regularInstanceMethod {
27+
[[self class] directMethod]; // expected-error {{messaging a Class with a method that is possibly direct}}
28+
}
29+
@end
30+
31+
@interface Sub : Root
32+
@end
33+
34+
@implementation Sub
35+
+ (void)foo {
36+
[self directMethod]; // this should not warn
37+
}
38+
@end
39+
40+
__attribute__((objc_root_class))
41+
@interface Other
42+
@end
43+
44+
@implementation Other
45+
+ (void)bar {
46+
[self directMethod]; // expected-error {{no known class method for selector 'directMethod'}}
47+
}
48+
@end

clang/test/SemaObjC/method-direct.m

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,10 @@ + (void)classRootDirect {
8989
}
9090
- (void)otherRootDirect {
9191
}
92+
+ (void)someRootDirectMethod { // expected-note {{direct method 'someRootDirectMethod' declared here}}
93+
}
9294
+ (void)otherClassRootDirect {
95+
[self someRootDirectMethod]; // expected-error {{messaging a Class with a method that is possibly direct}}
9396
}
9497
- (void)rootExtensionDirect {
9598
}

0 commit comments

Comments
 (0)