Skip to content

Commit de768e8

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 b372ff6 commit de768e8

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,
@@ -4099,7 +4103,7 @@ namespace {
40994103
auto resultTy = importedType.getType();
41004104

41014105
FuncDecl *func =
4102-
createFuncOrAccessor(Impl.SwiftContext, loc, accessorInfo, name,
4106+
createFuncOrAccessor(Impl, loc, accessorInfo, name,
41034107
nameLoc, genericParams, bodyParams, resultTy,
41044108
/*async=*/false, /*throws=*/false, dc,
41054109
clangNode);
@@ -4911,7 +4915,7 @@ namespace {
49114915
}
49124916
}
49134917

4914-
auto result = createFuncOrAccessor(Impl.SwiftContext,
4918+
auto result = createFuncOrAccessor(Impl,
49154919
/*funcLoc*/ SourceLoc(), accessorInfo,
49164920
importedName.getDeclName(),
49174921
/*nameLoc*/ SourceLoc(),
@@ -8399,6 +8403,100 @@ Optional<bool> swift::importer::isMainActorAttr(
83998403
return None;
84008404
}
84018405

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

84398537
// Scan through Clang attributes and map them onto Swift
84408538
// equivalents.
8441-
PatternBindingInitializer *initContext = nullptr;
8442-
Optional<const clang::SwiftAttrAttr *> SeenMainActorAttr;
84438539
bool AnyUnavailable = MappedDecl->getAttrs().isUnavailable(C);
84448540
for (clang::NamedDecl::attr_iterator AI = ClangDecl->attr_begin(),
84458541
AE = ClangDecl->attr_end(); AI != AE; ++AI) {
@@ -8594,79 +8690,8 @@ void ClangImporter::Implementation::importAttributes(
85948690
MappedDecl->getAttrs().add(AvAttr);
85958691
}
85968692

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

86728697
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
@@ -1479,9 +1479,16 @@ class LLVM_LIBRARY_VISIBILITY ClangImporter::Implementation
14791479
D->setAccess(access);
14801480
if (auto ASD = dyn_cast<AbstractStorageDecl>(D))
14811481
ASD->setSetterAccess(access);
1482+
1483+
// SwiftAttrs on ParamDecls are interpreted by applyParamAttributes().
1484+
if (!isa<ParamDecl>(D))
1485+
importSwiftAttrAttributes(D);
1486+
14821487
return D;
14831488
}
14841489

1490+
void importSwiftAttrAttributes(Decl *decl);
1491+
14851492
/// Find the lookup table that corresponds to the given Clang module.
14861493
///
14871494
/// \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)