Skip to content

Commit 4c75d7b

Browse files
authored
Merge pull request #80150 from rintaro/astgen-objc
[ASTGen] ObjC improvements
2 parents 962be95 + 4762985 commit 4c75d7b

File tree

7 files changed

+213
-24
lines changed

7 files changed

+213
-24
lines changed

include/swift/AST/ASTBridging.h

+21
Original file line numberDiff line numberDiff line change
@@ -2057,6 +2057,13 @@ BridgedKeyPathExpr BridgedKeyPathExpr_createParsed(
20572057
BridgedNullableExpr cParsedRoot, BridgedNullableExpr cParsedPath,
20582058
bool hasLeadingDot);
20592059

2060+
SWIFT_NAME("BridgedKeyPathExpr.createParsedPoundKeyPath(_:poundLoc:lParenLoc:"
2061+
"names:nameLocs:rParenLoc:)")
2062+
BridgedKeyPathExpr BridgedKeyPathExpr_createParsedPoundKeyPath(
2063+
BridgedASTContext cContext, BridgedSourceLoc cPoundLoc,
2064+
BridgedSourceLoc cLParenLoc, BridgedArrayRef cNames,
2065+
BridgedArrayRef cNameLocs, BridgedSourceLoc cRParenLoc);
2066+
20602067
SWIFT_NAME("BridgedMacroExpansionExpr.createParsed(_:poundLoc:macroNameRef:"
20612068
"macroNameLoc:leftAngleLoc:genericArgs:rightAngleLoc:args:)")
20622069
BridgedMacroExpansionExpr BridgedMacroExpansionExpr_createParsed(
@@ -2087,6 +2094,20 @@ BridgedNilLiteralExpr
20872094
BridgedNilLiteralExpr_createParsed(BridgedASTContext cContext,
20882095
BridgedSourceLoc cNilKeywordLoc);
20892096

2097+
enum ENUM_EXTENSIBILITY_ATTR(open) BridgedObjCSelectorKind {
2098+
BridgedObjCSelectorKindMethod,
2099+
BridgedObjCSelectorKindGetter,
2100+
BridgedObjCSelectorKindSetter,
2101+
};
2102+
2103+
SWIFT_NAME("BridgedObjCSelectorExpr.createParsed(_:kind:keywordLoc:lParenLoc:"
2104+
"modifierLoc:subExpr:rParenLoc:)")
2105+
BridgedObjCSelectorExpr BridgedObjCSelectorExpr_createParsed(
2106+
BridgedASTContext cContext, BridgedObjCSelectorKind cKind,
2107+
BridgedSourceLoc cKeywordLoc, BridgedSourceLoc cLParenLoc,
2108+
BridgedSourceLoc cModifierLoc, BridgedExpr cSubExpr,
2109+
BridgedSourceLoc cRParenLoc);
2110+
20902111
enum ENUM_EXTENSIBILITY_ATTR(open) BridgedObjectLiteralKind : size_t {
20912112
#define POUND_OBJECT_LITERAL(Name, Desc, Proto) BridgedObjectLiteralKind_##Name,
20922113
#include "swift/AST/TokenKinds.def"

lib/AST/Bridging/ExprBridging.cpp

+42
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,26 @@ BridgedKeyPathExpr BridgedKeyPathExpr_createParsed(
356356
cParsedPath.unbridged(), hasLeadingDot);
357357
}
358358

359+
BridgedKeyPathExpr BridgedKeyPathExpr_createParsedPoundKeyPath(
360+
BridgedASTContext cContext, BridgedSourceLoc cPoundLoc,
361+
BridgedSourceLoc cLParenLoc, BridgedArrayRef cNames,
362+
BridgedArrayRef cNameLocs, BridgedSourceLoc cRParenLoc) {
363+
364+
SmallVector<KeyPathExpr::Component> components;
365+
auto cNameArr = cNames.unbridged<BridgedDeclNameRef>();
366+
auto cNameLocArr = cNameLocs.unbridged<BridgedDeclNameLoc>();
367+
for (size_t i = 0, e = cNameArr.size(); i != e; ++i) {
368+
auto name = cNameArr[i].unbridged();
369+
auto loc = cNameLocArr[i].unbridged().getBaseNameLoc();
370+
components.push_back(KeyPathExpr::Component::forUnresolvedMember(
371+
name, FunctionRefInfo::unappliedBaseName(), loc));
372+
}
373+
374+
return KeyPathExpr::createParsedPoundKeyPath(
375+
cContext.unbridged(), cPoundLoc.unbridged(), cLParenLoc.unbridged(),
376+
components, cRParenLoc.unbridged());
377+
}
378+
359379
BridgedSuperRefExpr
360380
BridgedSuperRefExpr_createParsed(BridgedASTContext cContext,
361381
BridgedSourceLoc cSuperLoc) {
@@ -445,6 +465,28 @@ BridgedNilLiteralExpr_createParsed(BridgedASTContext cContext,
445465
return new (cContext.unbridged()) NilLiteralExpr(cNilKeywordLoc.unbridged());
446466
}
447467

468+
BridgedObjCSelectorExpr BridgedObjCSelectorExpr_createParsed(
469+
BridgedASTContext cContext, BridgedObjCSelectorKind cKind,
470+
BridgedSourceLoc cKeywordLoc, BridgedSourceLoc cLParenLoc,
471+
BridgedSourceLoc cModifierLoc, BridgedExpr cSubExpr,
472+
BridgedSourceLoc cRParenLoc) {
473+
ObjCSelectorExpr::ObjCSelectorKind kind;
474+
switch (cKind) {
475+
case BridgedObjCSelectorKindMethod:
476+
kind = ObjCSelectorExpr::Method;
477+
break;
478+
case BridgedObjCSelectorKindGetter:
479+
kind = ObjCSelectorExpr::Getter;
480+
break;
481+
case BridgedObjCSelectorKindSetter:
482+
kind = ObjCSelectorExpr::Setter;
483+
break;
484+
}
485+
return new (cContext.unbridged()) ObjCSelectorExpr(
486+
kind, cKeywordLoc.unbridged(), cLParenLoc.unbridged(),
487+
cModifierLoc.unbridged(), cSubExpr.unbridged(), cRParenLoc.unbridged());
488+
}
489+
448490
SWIFT_NAME("BridgedObjectLiteralKind.init(from:)")
449491
BridgedObjectLiteralKind
450492
BridgedObjectLiteralKind_fromString(BridgedStringRef cStr) {

lib/AST/Decl.cpp

+13
Original file line numberDiff line numberDiff line change
@@ -427,6 +427,19 @@ void Decl::attachParsedAttrs(DeclAttributes attrs) {
427427
for (auto attr : attrs.getAttributes<ABIAttr, /*AllowInvalid=*/true>())
428428
recordABIAttr(attr);
429429

430+
// @implementation requires an explicit @objc attribute, but
431+
// @_objcImplementation didn't. Insert one if necessary.
432+
auto implAttr = attrs.getAttribute<ObjCImplementationAttr>();
433+
if (implAttr && isa<ExtensionDecl>(this) && implAttr->isEarlyAdopter() &&
434+
!attrs.hasAttribute<ObjCAttr>()) {
435+
ObjCAttr *objcAttr =
436+
implAttr->CategoryName.empty()
437+
? ObjCAttr::createUnnamedImplicit(getASTContext())
438+
: ObjCAttr::createNullary(getASTContext(), implAttr->CategoryName,
439+
/*isNameImplicit=*/false);
440+
attrs.add(objcAttr);
441+
}
442+
430443
getAttrs() = attrs;
431444
}
432445

lib/ASTGen/Sources/ASTGen/BuiltinPound.swift

+119-6
Original file line numberDiff line numberDiff line change
@@ -70,11 +70,11 @@ extension ASTGenVisitor {
7070
switch keyword {
7171
case .selector:
7272
let selectorExpr = self.generateObjCSelectorExpr(freestandingMacroExpansion: node)
73-
return .generated(.expr(selectorExpr.asExpr))
73+
return .generated(.expr(selectorExpr))
7474

7575
case .keyPath:
7676
let keypathExpr = self.generateObjCKeyPathExpr(freestandingMacroExpansion: node)
77-
return .generated(.expr(keypathExpr.asExpr))
77+
return .generated(.expr(keypathExpr))
7878

7979
case .assert where ctx.langOptsHasFeature(.StaticAssert):
8080
let assertStmtOpt = self.generatePoundAssertStmt(freestandingMacroExpansion: node)
@@ -119,6 +119,15 @@ extension ASTGenVisitor {
119119
// return
120120
}
121121

122+
guard
123+
node.genericArgumentClause == nil,
124+
node.trailingClosure == nil,
125+
node.additionalTrailingClosures.isEmpty
126+
else {
127+
// TODO: Diagnose.
128+
fatalError("#error/#warning with generic specialization")
129+
}
130+
122131
guard node.arguments.count == 1,
123132
let arg = node.arguments.first,
124133
arg.label == nil,
@@ -194,11 +203,115 @@ extension ASTGenVisitor {
194203
)
195204
}
196205

197-
func generateObjCSelectorExpr(freestandingMacroExpansion node: some FreestandingMacroExpansionSyntax) -> BridgedObjCSelectorExpr {
198-
fatalError("unimplemented (objc selector)")
206+
func generateObjCSelectorExpr(freestandingMacroExpansion node: some FreestandingMacroExpansionSyntax) -> BridgedExpr {
207+
guard
208+
node.genericArgumentClause == nil,
209+
node.trailingClosure == nil,
210+
node.additionalTrailingClosures.isEmpty
211+
else {
212+
// TODO: Diagnose.
213+
fatalError("#selector with generic specialization")
214+
}
215+
216+
var args = node.arguments[...]
217+
guard let arg = args.popFirst() else {
218+
// TODO: Diagnose
219+
fatalError("expected an argument for #selector")
220+
// return ErrorExpr
221+
}
222+
let kind: BridgedObjCSelectorKind
223+
switch arg.label?.rawText {
224+
case nil: kind = .method
225+
case "getter": kind = .getter
226+
case "setter": kind = .setter
227+
case _?:
228+
// TODO: Diagnose
229+
fatalError("unexpected argument label in #selector")
230+
// return ErrorExpr
231+
}
232+
let expr = self.generate(expr: arg.expression)
233+
guard args.isEmpty else {
234+
// TODO: Diagnose
235+
fatalError("unexpected argument in #selector")
236+
// return ErrorExpr
237+
}
238+
return BridgedObjCSelectorExpr.createParsed(
239+
self.ctx,
240+
kind: kind,
241+
keywordLoc: self.generateSourceLoc(node.pound),
242+
lParenLoc: self.generateSourceLoc(node.leftParen),
243+
modifierLoc: self.generateSourceLoc(arg.label),
244+
subExpr: expr,
245+
rParenLoc: self.generateSourceLoc(node.rightParen)
246+
).asExpr
199247
}
200248

201-
func generateObjCKeyPathExpr(freestandingMacroExpansion node: some FreestandingMacroExpansionSyntax) -> BridgedKeyPathExpr {
202-
fatalError("unimplemented (objc keypath)")
249+
func generateObjCKeyPathExpr(freestandingMacroExpansion node: some FreestandingMacroExpansionSyntax) -> BridgedExpr {
250+
guard
251+
node.genericArgumentClause == nil,
252+
node.trailingClosure == nil,
253+
node.additionalTrailingClosures.isEmpty
254+
else {
255+
// TODO: Diagnose.
256+
fatalError("#keyPath with generic specialization")
257+
}
258+
259+
var names: [BridgedDeclNameRef] = []
260+
var nameLocs: [BridgedDeclNameLoc] = []
261+
262+
func collectNames(expr node: ExprSyntax) -> Bool {
263+
if let declRefExpr = node.as(DeclReferenceExprSyntax.self) {
264+
let nameAndLoc = self.generateDeclNameRef(declReferenceExpr: declRefExpr)
265+
names.append(nameAndLoc.name)
266+
nameLocs.append(nameAndLoc.loc)
267+
return false
268+
}
269+
if let memberExpr = node.as(MemberAccessExprSyntax.self) {
270+
guard let base = memberExpr.base else {
271+
// TODO: Diagnose
272+
fatalError("unexpected expression in #keyPath")
273+
}
274+
if collectNames(expr: base) {
275+
return true
276+
}
277+
let nameAndLoc = self.generateDeclNameRef(declReferenceExpr: memberExpr.declName)
278+
names.append(nameAndLoc.name)
279+
nameLocs.append(nameAndLoc.loc)
280+
return false
281+
}
282+
// TODO: Diagnose
283+
fatalError("unexpected expression in #keyPath")
284+
// return true
285+
}
286+
287+
var args = node.arguments[...]
288+
guard let arg = args.popFirst() else {
289+
// TODO: Diagnose
290+
fatalError("expected an argument for #keyPath")
291+
// return ErrorExpr
292+
}
293+
guard arg.label == nil else {
294+
// TODO: Diagnose
295+
fatalError("unexpected argument label #keyPath")
296+
297+
}
298+
if /*hadError=*/collectNames(expr: arg.expression) {
299+
return BridgedErrorExpr.create(self.ctx, loc: self.generateSourceRange(node)).asExpr;
300+
}
301+
302+
guard args.isEmpty else {
303+
// TODO: Diagnose
304+
fatalError("unexpected argument in #keyPath")
305+
// return ErrorExpr
306+
}
307+
308+
return BridgedKeyPathExpr.createParsedPoundKeyPath(
309+
self.ctx,
310+
poundLoc: self.generateSourceLoc(node.pound),
311+
lParenLoc: self.generateSourceLoc(node.leftParen),
312+
names: names.lazy.bridgedArray(in: self),
313+
nameLocs: nameLocs.lazy.bridgedArray(in: self),
314+
rParenLoc: self.generateSourceLoc(node.rightParen)
315+
).asExpr
203316
}
204317
}

lib/Parse/ParseDecl.cpp

-14
Original file line numberDiff line numberDiff line change
@@ -7070,20 +7070,6 @@ Parser::parseDeclExtension(ParseDeclOptions Flags, DeclAttributes &Attributes) {
70707070
status |= whereStatus;
70717071
}
70727072

7073-
// @implementation requires an explicit @objc attribute, but
7074-
// @_objcImplementation didn't. Insert one if necessary.
7075-
auto implAttr = Attributes.getAttribute<ObjCImplementationAttr>();
7076-
if (implAttr && implAttr->isEarlyAdopter()
7077-
&& !Attributes.hasAttribute<ObjCAttr>()) {
7078-
ObjCAttr *objcAttr;
7079-
if (implAttr->CategoryName.empty())
7080-
objcAttr = ObjCAttr::createUnnamedImplicit(Context);
7081-
else
7082-
objcAttr = ObjCAttr::createNullary(Context, implAttr->CategoryName,
7083-
/*isNameImplicit=*/false);
7084-
Attributes.add(objcAttr);
7085-
}
7086-
70877073
ExtensionDecl *ext = ExtensionDecl::create(Context, ExtensionLoc,
70887074
extendedType.getPtrOrNull(),
70897075
Context.AllocateCopy(Inherited),

test/ASTGen/Inputs/objc_decls.h

+3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
@import Foundation;
22

33
@interface ObjCClass: NSObject
4+
@property NSString *theValue;
5+
-(void)methodWithX:(NSInteger)x Y:(NSInteger)y;
46
@end
7+
58
@interface ObjCClass(Category1)
69
@end
710
@interface ObjCClass(Category2)

test/ASTGen/attrs_objc.swift

+15-4
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,25 @@
1717
@objc(barWithX:Y:) func foo(x: Int, y: Int) {}
1818
}
1919

20-
@objc @implementation extension ObjCClass {}
20+
@objc @implementation extension ObjCClass {
21+
var theValue: String? {
22+
get { "" }
23+
set {}
24+
}
25+
@objc(methodWithX:Y:)
26+
func methodWith(x: Int, y: Int) {}
27+
}
2128
@objc @implementation(Category1) extension ObjCClass {} // expected-error {{Objective-C category should be specified on '@objc', not '@implementation'}}
2229
@objc(Category2) @implementation extension ObjCClass {}
2330

24-
// FIXME: @_objcImplementation inserts implicit @objc attribute in C++ parser.
25-
//@_objcImplementation extension ObjCClass2 {} // xpected-error {{cannot find type 'ObjCClass2' in scope}}
26-
//@_objcImplementation(Category) extension ObjCClass2 {} // xpected-error {{cannot find type 'ObjCClass2' in scope}}
31+
@_objcImplementation extension ObjCClass2 {} // expected-warning {{'@_objcImplementation' is deprecated; use '@implementation' instead}}
2732

2833
@_objcRuntimeName(RenamedClass) class ThisWillBeRenamed {}
2934

3035
@_swift_native_objc_runtime_base(NSMagicBase) class TestNativeObjCRuntimeBase {}
36+
37+
func testPoundObjC() {
38+
let _: String = #keyPath(ObjCClass.theValue)
39+
let _: Selector = #selector(getter:ObjCClass.theValue)
40+
let _: Selector = #selector(ObjCClass.methodWith(x:y:))
41+
}

0 commit comments

Comments
 (0)