Skip to content

Commit ef428e5

Browse files
committed
[Clang importer] Consider attributes on the typedef name for an anonymous tag.
In C, one can provide a typedef name for an anonymous tag declaration in one shot, e.g., typedef struct { double x, y } Point; In this case, there are effectively two declarations at the C level: the typedef and the struct. The Clang importer was only taking attributes from the anonymous struct (i.e., the tag) and not from the typedef. However, any attributes put before the `typedef` should apply as well... so consider those, too. For now, only do this for `swift_attr` attributes, because we're seeing this primarily with `Sendable` annotations. In the future, we can look to generalizing it, but that could have source-breaking consequences. Fixes rdar://91632960.
1 parent 95274f8 commit ef428e5

File tree

3 files changed

+84
-59
lines changed

3 files changed

+84
-59
lines changed

lib/ClangImporter/ImportDecl.cpp

Lines changed: 70 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -8787,74 +8787,86 @@ ClangImporter::Implementation::importSwiftAttrAttributes(Decl *MappedDecl) {
87878787
Optional<const clang::SwiftAttrAttr *> SeenMainActorAttr;
87888788
PatternBindingInitializer *initContext = nullptr;
87898789

8790-
//
8791-
// __attribute__((swift_attr("attribute")))
8792-
//
8793-
for (auto swiftAttr : ClangDecl->specific_attrs<clang::SwiftAttrAttr>()) {
8794-
// FIXME: Hard-code @MainActor and @UIActor, because we don't have a
8795-
// point at which to do name lookup for imported entities.
8796-
if (isMainActorAttr(swiftAttr)) {
8797-
if (SeenMainActorAttr) {
8798-
// Cannot add main actor annotation twice. We'll keep the first
8799-
// one and raise a warning about the duplicate.
8800-
HeaderLoc attrLoc(swiftAttr->getLocation());
8801-
diagnose(attrLoc, diag::import_multiple_mainactor_attr,
8802-
swiftAttr->getAttribute(),
8803-
SeenMainActorAttr.getValue()->getAttribute());
8790+
auto importAttrsFromDecl = [&](const clang::NamedDecl *ClangDecl) {
8791+
//
8792+
// __attribute__((swift_attr("attribute")))
8793+
//
8794+
for (auto swiftAttr : ClangDecl->specific_attrs<clang::SwiftAttrAttr>()) {
8795+
// FIXME: Hard-code @MainActor and @UIActor, because we don't have a
8796+
// point at which to do name lookup for imported entities.
8797+
if (isMainActorAttr(swiftAttr)) {
8798+
if (SeenMainActorAttr) {
8799+
// Cannot add main actor annotation twice. We'll keep the first
8800+
// one and raise a warning about the duplicate.
8801+
HeaderLoc attrLoc(swiftAttr->getLocation());
8802+
diagnose(attrLoc, diag::import_multiple_mainactor_attr,
8803+
swiftAttr->getAttribute(),
8804+
SeenMainActorAttr.getValue()->getAttribute());
8805+
continue;
8806+
}
8807+
8808+
if (Type mainActorType = SwiftContext.getMainActorType()) {
8809+
auto typeExpr = TypeExpr::createImplicit(mainActorType, SwiftContext);
8810+
auto attr = CustomAttr::create(SwiftContext, SourceLoc(), typeExpr);
8811+
MappedDecl->getAttrs().add(attr);
8812+
SeenMainActorAttr = swiftAttr;
8813+
}
8814+
88048815
continue;
88058816
}
88068817

8807-
if (Type mainActorType = SwiftContext.getMainActorType()) {
8808-
auto typeExpr = TypeExpr::createImplicit(mainActorType, SwiftContext);
8809-
auto attr = CustomAttr::create(SwiftContext, SourceLoc(), typeExpr);
8818+
// Hard-code @actorIndependent, until Objective-C clients start
8819+
// using nonisolated.
8820+
if (swiftAttr->getAttribute() == "@actorIndependent") {
8821+
auto attr = new (SwiftContext) NonisolatedAttr(/*isImplicit=*/true);
88108822
MappedDecl->getAttrs().add(attr);
8811-
SeenMainActorAttr = swiftAttr;
8823+
continue;
88128824
}
88138825

8814-
continue;
8815-
}
8816-
8817-
// Hard-code @actorIndependent, until Objective-C clients start
8818-
// using nonisolated.
8819-
if (swiftAttr->getAttribute() == "@actorIndependent") {
8820-
auto attr = new (SwiftContext) NonisolatedAttr(/*isImplicit=*/true);
8821-
MappedDecl->getAttrs().add(attr);
8822-
continue;
8823-
}
8826+
// Dig out a buffer with the attribute text.
8827+
unsigned bufferID = getClangSwiftAttrSourceBuffer(
8828+
swiftAttr->getAttribute());
88248829

8825-
// Dig out a buffer with the attribute text.
8826-
unsigned bufferID = getClangSwiftAttrSourceBuffer(
8827-
swiftAttr->getAttribute());
8830+
// Dig out a source file we can use for parsing.
8831+
auto &sourceFile = getClangSwiftAttrSourceFile(
8832+
*MappedDecl->getDeclContext()->getParentModule());
88288833

8829-
// Dig out a source file we can use for parsing.
8830-
auto &sourceFile = getClangSwiftAttrSourceFile(
8831-
*MappedDecl->getDeclContext()->getParentModule());
8834+
// Spin up a parser.
8835+
swift::Parser parser(
8836+
bufferID, sourceFile, &SwiftContext.Diags, nullptr, nullptr);
8837+
// Prime the lexer.
8838+
parser.consumeTokenWithoutFeedingReceiver();
88328839

8833-
// Spin up a parser.
8834-
swift::Parser parser(
8835-
bufferID, sourceFile, &SwiftContext.Diags, nullptr, nullptr);
8836-
// Prime the lexer.
8837-
parser.consumeTokenWithoutFeedingReceiver();
8840+
bool hadError = false;
8841+
SourceLoc atLoc;
8842+
if (parser.consumeIf(tok::at_sign, atLoc)) {
8843+
hadError = parser.parseDeclAttribute(
8844+
MappedDecl->getAttrs(), atLoc, initContext,
8845+
/*isFromClangAttribute=*/true).isError();
8846+
} else {
8847+
SourceLoc staticLoc;
8848+
StaticSpellingKind staticSpelling;
8849+
hadError = parser.parseDeclModifierList(
8850+
MappedDecl->getAttrs(), staticLoc, staticSpelling,
8851+
/*isFromClangAttribute=*/true);
8852+
}
88388853

8839-
bool hadError = false;
8840-
SourceLoc atLoc;
8841-
if (parser.consumeIf(tok::at_sign, atLoc)) {
8842-
hadError = parser.parseDeclAttribute(
8843-
MappedDecl->getAttrs(), atLoc, initContext,
8844-
/*isFromClangAttribute=*/true).isError();
8845-
} else {
8846-
SourceLoc staticLoc;
8847-
StaticSpellingKind staticSpelling;
8848-
hadError = parser.parseDeclModifierList(
8849-
MappedDecl->getAttrs(), staticLoc, staticSpelling,
8850-
/*isFromClangAttribute=*/true);
8851-
}
8852-
8853-
if (hadError) {
8854-
// Complain about the unhandled attribute or modifier.
8855-
HeaderLoc attrLoc(swiftAttr->getLocation());
8856-
diagnose(attrLoc, diag::clang_swift_attr_unhandled,
8857-
swiftAttr->getAttribute());
8854+
if (hadError) {
8855+
// Complain about the unhandled attribute or modifier.
8856+
HeaderLoc attrLoc(swiftAttr->getLocation());
8857+
diagnose(attrLoc, diag::clang_swift_attr_unhandled,
8858+
swiftAttr->getAttribute());
8859+
}
8860+
}
8861+
};
8862+
importAttrsFromDecl(ClangDecl);
8863+
8864+
// If the Clang declaration is from an anonymous tag that was given a
8865+
// name via a typedef, look for attributes on the typedef as well.
8866+
if (auto tag = dyn_cast<clang::TagDecl>(ClangDecl)) {
8867+
if (tag->getName().empty()) {
8868+
if (auto typedefDecl = tag->getTypedefNameForAnonDecl())
8869+
importAttrsFromDecl(typedefDecl);
88588870
}
88598871
}
88608872

test/ClangImporter/objc_async.swift

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,8 +177,16 @@ actor MySubclassCheckingSwiftAttributes : ProtocolWithSwiftAttributes {
177177

178178
// Sendable conformance inference for imported types.
179179
func acceptCV<T: Sendable>(_: T) { }
180-
func testCV(r: NSRange) {
180+
181+
struct MyStruct: Sendable {
182+
var range: NSRange
183+
var inner: SendableStructWithNonSendable
184+
}
185+
186+
@available(SwiftStdlib 5.5, *)
187+
func testCV(r: NSRange, someStruct: SendableStructWithNonSendable) async {
181188
acceptCV(r)
189+
acceptCV(someStruct)
182190
}
183191

184192
// Global actor (unsafe) isolation.

test/Inputs/clang-importer-sdk/usr/include/ObjCConcurrency.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,11 @@ typedef NSString *NonSendableStringEnum NS_STRING_ENUM NONSENDABLE;
265265
typedef NSString *SendableStringStruct NS_EXTENSIBLE_STRING_ENUM;
266266
typedef NSString *NonSendableStringStruct NS_EXTENSIBLE_STRING_ENUM NONSENDABLE;
267267

268+
SENDABLE
269+
typedef struct {
270+
void *ptr;
271+
} SendableStructWithNonSendable;
272+
268273
ASSUME_NONSENDABLE_END
269274

270275
typedef id ObjectTypedef;

0 commit comments

Comments
 (0)