Skip to content

Commit 1695d61

Browse files
committed
[ClangImporter] Import SwiftAttrs early
This change applies SwiftAttr attributes as soon as possible after creating an instance of a Decl, rather than waiting until the declaration is "finished". That makes sure the attributes can influence the declaration very early in its lifecycle, and in particular, before its conformance table is initialized. Mostly NFC in this commit (other than affecting the order that attributes are printed in), but necessary for future changes in this PR.
1 parent d2d786a commit 1695d61

File tree

3 files changed

+117
-85
lines changed

3 files changed

+117
-85
lines changed

lib/ClangImporter/ImportDecl.cpp

Lines changed: 107 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -160,15 +160,17 @@ createVarWithPattern(ASTContext &ctx, DeclContext *dc, Identifier name, Type ty,
160160
return {var, patternBinding};
161161
}
162162

163-
static FuncDecl *createFuncOrAccessor(ASTContext &ctx, SourceLoc funcLoc,
163+
static FuncDecl *createFuncOrAccessor(ClangImporter::Implementation &impl,
164+
SourceLoc funcLoc,
164165
Optional<AccessorInfo> accessorInfo,
165166
DeclName name, SourceLoc nameLoc,
166167
GenericParamList *genericParams,
167168
ParameterList *bodyParams, Type resultTy,
168169
bool async, bool throws, DeclContext *dc,
169170
ClangNode clangNode) {
171+
FuncDecl *decl;
170172
if (accessorInfo) {
171-
return AccessorDecl::create(ctx, funcLoc,
173+
decl = AccessorDecl::create(impl.SwiftContext, funcLoc,
172174
/*accessorKeywordLoc*/ SourceLoc(),
173175
accessorInfo->Kind, accessorInfo->Storage,
174176
/*StaticLoc*/ SourceLoc(),
@@ -178,10 +180,12 @@ static FuncDecl *createFuncOrAccessor(ASTContext &ctx, SourceLoc funcLoc,
178180
genericParams, bodyParams,
179181
resultTy, dc, clangNode);
180182
} else {
181-
return FuncDecl::createImported(ctx, funcLoc, name, nameLoc, async, throws,
182-
bodyParams, resultTy, genericParams, dc,
183-
clangNode);
183+
decl = FuncDecl::createImported(impl.SwiftContext, funcLoc, name, nameLoc,
184+
async, throws, bodyParams, resultTy,
185+
genericParams, dc, clangNode);
184186
}
187+
impl.importSwiftAttrAttributes(decl);
188+
return decl;
185189
}
186190

187191
static void makeComputed(AbstractStorageDecl *storage,
@@ -4101,7 +4105,7 @@ namespace {
41014105
auto resultTy = importedType.getType();
41024106

41034107
FuncDecl *func =
4104-
createFuncOrAccessor(Impl.SwiftContext, loc, accessorInfo, name,
4108+
createFuncOrAccessor(Impl, loc, accessorInfo, name,
41054109
nameLoc, genericParams, bodyParams, resultTy,
41064110
/*async=*/false, /*throws=*/false, dc,
41074111
clangNode);
@@ -4913,7 +4917,7 @@ namespace {
49134917
}
49144918
}
49154919

4916-
auto result = createFuncOrAccessor(Impl.SwiftContext,
4920+
auto result = createFuncOrAccessor(Impl,
49174921
/*funcLoc*/ SourceLoc(), accessorInfo,
49184922
importedName.getDeclName(),
49194923
/*nameLoc*/ SourceLoc(),
@@ -8401,6 +8405,100 @@ Optional<bool> swift::importer::isMainActorAttr(
84018405
return None;
84028406
}
84038407

8408+
void
8409+
ClangImporter::Implementation::importSwiftAttrAttributes(Decl *MappedDecl) {
8410+
auto ClangDecl =
8411+
dyn_cast_or_null<clang::NamedDecl>(MappedDecl->getClangDecl());
8412+
if (!ClangDecl)
8413+
return;
8414+
8415+
// Subscripts are special-cased since there isn't a 1:1 mapping
8416+
// from its accessor(s) to the subscript declaration.
8417+
if (isa<SubscriptDecl>(MappedDecl))
8418+
return;
8419+
8420+
if (auto maybeDefinition = getDefinitionForClangTypeDecl(ClangDecl))
8421+
if (maybeDefinition.getValue())
8422+
ClangDecl = cast<clang::NamedDecl>(maybeDefinition.getValue());
8423+
8424+
Optional<const clang::SwiftAttrAttr *> SeenMainActorAttr;
8425+
PatternBindingInitializer *initContext = nullptr;
8426+
8427+
//
8428+
// __attribute__((swift_attr("attribute")))
8429+
//
8430+
for (auto swiftAttr : ClangDecl->specific_attrs<clang::SwiftAttrAttr>()) {
8431+
// FIXME: Hard-code @MainActor and @UIActor, because we don't have a
8432+
// point at which to do name lookup for imported entities.
8433+
if (auto isMainActor = isMainActorAttr(SwiftContext, swiftAttr)) {
8434+
bool isUnsafe = *isMainActor;
8435+
8436+
if (SeenMainActorAttr) {
8437+
// Cannot add main actor annotation twice. We'll keep the first
8438+
// one and raise a warning about the duplicate.
8439+
HeaderLoc attrLoc(swiftAttr->getLocation());
8440+
diagnose(attrLoc, diag::import_multiple_mainactor_attr,
8441+
swiftAttr->getAttribute(),
8442+
SeenMainActorAttr.getValue()->getAttribute());
8443+
continue;
8444+
}
8445+
8446+
if (Type mainActorType = SwiftContext.getMainActorType()) {
8447+
auto typeExpr = TypeExpr::createImplicit(mainActorType, SwiftContext);
8448+
auto attr = CustomAttr::create(SwiftContext, SourceLoc(), typeExpr);
8449+
attr->setArgIsUnsafe(isUnsafe);
8450+
MappedDecl->getAttrs().add(attr);
8451+
SeenMainActorAttr = swiftAttr;
8452+
}
8453+
8454+
continue;
8455+
}
8456+
8457+
// Hard-code @actorIndependent, until Objective-C clients start
8458+
// using nonisolated.
8459+
if (swiftAttr->getAttribute() == "@actorIndependent") {
8460+
auto attr = new (SwiftContext) NonisolatedAttr(/*isImplicit=*/true);
8461+
MappedDecl->getAttrs().add(attr);
8462+
continue;
8463+
}
8464+
8465+
// Dig out a buffer with the attribute text.
8466+
unsigned bufferID = getClangSwiftAttrSourceBuffer(
8467+
swiftAttr->getAttribute());
8468+
8469+
// Dig out a source file we can use for parsing.
8470+
auto &sourceFile = getClangSwiftAttrSourceFile(
8471+
*MappedDecl->getDeclContext()->getParentModule());
8472+
8473+
// Spin up a parser.
8474+
swift::Parser parser(
8475+
bufferID, sourceFile, &SwiftContext.Diags, nullptr, nullptr);
8476+
// Prime the lexer.
8477+
parser.consumeTokenWithoutFeedingReceiver();
8478+
8479+
bool hadError = false;
8480+
SourceLoc atLoc;
8481+
if (parser.consumeIf(tok::at_sign, atLoc)) {
8482+
hadError = parser.parseDeclAttribute(
8483+
MappedDecl->getAttrs(), atLoc, initContext,
8484+
/*isFromClangAttribute=*/true).isError();
8485+
} else {
8486+
SourceLoc staticLoc;
8487+
StaticSpellingKind staticSpelling;
8488+
hadError = parser.parseDeclModifierList(
8489+
MappedDecl->getAttrs(), staticLoc, staticSpelling,
8490+
/*isFromClangAttribute=*/true);
8491+
}
8492+
8493+
if (hadError) {
8494+
// Complain about the unhandled attribute or modifier.
8495+
HeaderLoc attrLoc(swiftAttr->getLocation());
8496+
diagnose(attrLoc, diag::clang_swift_attr_unhandled,
8497+
swiftAttr->getAttribute());
8498+
}
8499+
}
8500+
}
8501+
84048502
static bool isUsingMacroName(clang::SourceManager &SM,
84058503
clang::SourceLocation loc,
84068504
StringRef MacroName) {
@@ -8440,8 +8538,6 @@ void ClangImporter::Implementation::importAttributes(
84408538

84418539
// Scan through Clang attributes and map them onto Swift
84428540
// equivalents.
8443-
PatternBindingInitializer *initContext = nullptr;
8444-
Optional<const clang::SwiftAttrAttr *> SeenMainActorAttr;
84458541
bool AnyUnavailable = MappedDecl->getAttrs().isUnavailable(C);
84468542
for (clang::NamedDecl::attr_iterator AI = ClangDecl->attr_begin(),
84478543
AE = ClangDecl->attr_end(); AI != AE; ++AI) {
@@ -8596,79 +8692,8 @@ void ClangImporter::Implementation::importAttributes(
85968692
MappedDecl->getAttrs().add(AvAttr);
85978693
}
85988694

8599-
// __attribute__((swift_attr("attribute")))
8600-
//
8601-
if (auto swiftAttr = dyn_cast<clang::SwiftAttrAttr>(*AI)) {
8602-
// FIXME: Hard-code @MainActor and @UIActor, because we don't have a
8603-
// point at which to do name lookup for imported entities.
8604-
if (auto isMainActor = isMainActorAttr(SwiftContext, swiftAttr)) {
8605-
bool isUnsafe = *isMainActor;
8606-
8607-
if (SeenMainActorAttr) {
8608-
// Cannot add main actor annotation twice. We'll keep the first
8609-
// one and raise a warning about the duplicate.
8610-
HeaderLoc attrLoc(swiftAttr->getLocation());
8611-
diagnose(attrLoc, diag::import_multiple_mainactor_attr,
8612-
swiftAttr->getAttribute(),
8613-
SeenMainActorAttr.getValue()->getAttribute());
8614-
continue;
8615-
}
8616-
8617-
if (Type mainActorType = SwiftContext.getMainActorType()) {
8618-
auto typeExpr = TypeExpr::createImplicit(mainActorType, SwiftContext);
8619-
auto attr = CustomAttr::create(SwiftContext, SourceLoc(), typeExpr);
8620-
attr->setArgIsUnsafe(isUnsafe);
8621-
MappedDecl->getAttrs().add(attr);
8622-
SeenMainActorAttr = swiftAttr;
8623-
}
8624-
8625-
continue;
8626-
}
8627-
8628-
// Hard-code @actorIndependent, until Objective-C clients start
8629-
// using nonisolated.
8630-
if (swiftAttr->getAttribute() == "@actorIndependent") {
8631-
auto attr = new (SwiftContext) NonisolatedAttr(/*isImplicit=*/true);
8632-
MappedDecl->getAttrs().add(attr);
8633-
continue;
8634-
}
8635-
8636-
// Dig out a buffer with the attribute text.
8637-
unsigned bufferID = getClangSwiftAttrSourceBuffer(
8638-
swiftAttr->getAttribute());
8639-
8640-
// Dig out a source file we can use for parsing.
8641-
auto &sourceFile = getClangSwiftAttrSourceFile(
8642-
*MappedDecl->getDeclContext()->getParentModule());
8643-
8644-
// Spin up a parser.
8645-
swift::Parser parser(
8646-
bufferID, sourceFile, &SwiftContext.Diags, nullptr, nullptr);
8647-
// Prime the lexer.
8648-
parser.consumeTokenWithoutFeedingReceiver();
8649-
8650-
bool hadError = false;
8651-
SourceLoc atLoc;
8652-
if (parser.consumeIf(tok::at_sign, atLoc)) {
8653-
hadError = parser.parseDeclAttribute(
8654-
MappedDecl->getAttrs(), atLoc, initContext,
8655-
/*isFromClangAttribute=*/true).isError();
8656-
} else {
8657-
SourceLoc staticLoc;
8658-
StaticSpellingKind staticSpelling;
8659-
hadError = parser.parseDeclModifierList(
8660-
MappedDecl->getAttrs(), staticLoc, staticSpelling,
8661-
/*isFromClangAttribute=*/true);
8662-
}
8663-
8664-
if (hadError) {
8665-
// Complain about the unhandled attribute or modifier.
8666-
HeaderLoc attrLoc(swiftAttr->getLocation());
8667-
diagnose(attrLoc, diag::clang_swift_attr_unhandled,
8668-
swiftAttr->getAttribute());
8669-
}
8670-
continue;
8671-
}
8695+
// __attribute__((swift_attr("attribute"))) are handled by
8696+
// importSwiftAttrAttributes(). Other attributes are ignored.
86728697
}
86738698

86748699
if (auto method = dyn_cast<clang::ObjCMethodDecl>(ClangDecl)) {

lib/ClangImporter/ImporterImpl.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1465,9 +1465,16 @@ class LLVM_LIBRARY_VISIBILITY ClangImporter::Implementation
14651465
D->setAccess(access);
14661466
if (auto ASD = dyn_cast<AbstractStorageDecl>(D))
14671467
ASD->setSetterAccess(access);
1468+
1469+
// SwiftAttrs on ParamDecls are interpreted by applyParamAttributes().
1470+
if (!isa<ParamDecl>(D))
1471+
importSwiftAttrAttributes(D);
1472+
14681473
return D;
14691474
}
14701475

1476+
void importSwiftAttrAttributes(Decl *decl);
1477+
14711478
/// Find the lookup table that corresponds to the given Clang module.
14721479
///
14731480
/// \param clangModule The module, or null to indicate that we're talking

test/IDE/print_clang_objc_async.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -99,13 +99,13 @@ import _Concurrency
9999
// CHECK-LABEL: protocol ProtocolWithSwiftAttributes {
100100
// CHECK-NEXT: nonisolated func independentMethod()
101101
// CHECK-NEXT: nonisolated func nonisolatedMethod()
102-
// CHECK-NEXT: {{^}} @objc @MainActor func mainActorMethod()
103-
// CHECK-NEXT: {{^}} @objc @MainActor func uiActorMethod()
102+
// CHECK-NEXT: {{^}} @MainActor @objc func mainActorMethod()
103+
// CHECK-NEXT: {{^}} @MainActor @objc func uiActorMethod()
104104
// CHECK-NEXT: {{^}} @objc optional func missingAtAttributeMethod()
105105
// CHECK-NEXT: {{^[}]$}}
106106

107107
// CHECK: {{^}}nonisolated var MAGIC_NUMBER: Int32 { get }
108108

109109
// CHECK: func doSomethingConcurrently(_ block: @Sendable () -> Void)
110110

111-
// CHECK: @MainActor protocol TripleMainActor {
111+
// CHECK: @MainActor @objc protocol TripleMainActor {

0 commit comments

Comments
 (0)