Skip to content

Commit 9df6394

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 a1a8dd7 commit 9df6394

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
@@ -8795,74 +8795,86 @@ ClangImporter::Implementation::importSwiftAttrAttributes(Decl *MappedDecl) {
87958795
Optional<const clang::SwiftAttrAttr *> SeenMainActorAttr;
87968796
PatternBindingInitializer *initContext = nullptr;
87978797

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

8815-
if (Type mainActorType = SwiftContext.getMainActorType()) {
8816-
auto typeExpr = TypeExpr::createImplicit(mainActorType, SwiftContext);
8817-
auto attr = CustomAttr::create(SwiftContext, SourceLoc(), typeExpr);
8826+
// Hard-code @actorIndependent, until Objective-C clients start
8827+
// using nonisolated.
8828+
if (swiftAttr->getAttribute() == "@actorIndependent") {
8829+
auto attr = new (SwiftContext) NonisolatedAttr(/*isImplicit=*/true);
88188830
MappedDecl->getAttrs().add(attr);
8819-
SeenMainActorAttr = swiftAttr;
8831+
continue;
88208832
}
88218833

8822-
continue;
8823-
}
8824-
8825-
// Hard-code @actorIndependent, until Objective-C clients start
8826-
// using nonisolated.
8827-
if (swiftAttr->getAttribute() == "@actorIndependent") {
8828-
auto attr = new (SwiftContext) NonisolatedAttr(/*isImplicit=*/true);
8829-
MappedDecl->getAttrs().add(attr);
8830-
continue;
8831-
}
8834+
// Dig out a buffer with the attribute text.
8835+
unsigned bufferID = getClangSwiftAttrSourceBuffer(
8836+
swiftAttr->getAttribute());
88328837

8833-
// Dig out a buffer with the attribute text.
8834-
unsigned bufferID = getClangSwiftAttrSourceBuffer(
8835-
swiftAttr->getAttribute());
8838+
// Dig out a source file we can use for parsing.
8839+
auto &sourceFile = getClangSwiftAttrSourceFile(
8840+
*MappedDecl->getDeclContext()->getParentModule());
88368841

8837-
// Dig out a source file we can use for parsing.
8838-
auto &sourceFile = getClangSwiftAttrSourceFile(
8839-
*MappedDecl->getDeclContext()->getParentModule());
8842+
// Spin up a parser.
8843+
swift::Parser parser(
8844+
bufferID, sourceFile, &SwiftContext.Diags, nullptr, nullptr);
8845+
// Prime the lexer.
8846+
parser.consumeTokenWithoutFeedingReceiver();
88408847

8841-
// Spin up a parser.
8842-
swift::Parser parser(
8843-
bufferID, sourceFile, &SwiftContext.Diags, nullptr, nullptr);
8844-
// Prime the lexer.
8845-
parser.consumeTokenWithoutFeedingReceiver();
8848+
bool hadError = false;
8849+
SourceLoc atLoc;
8850+
if (parser.consumeIf(tok::at_sign, atLoc)) {
8851+
hadError = parser.parseDeclAttribute(
8852+
MappedDecl->getAttrs(), atLoc, initContext,
8853+
/*isFromClangAttribute=*/true).isError();
8854+
} else {
8855+
SourceLoc staticLoc;
8856+
StaticSpellingKind staticSpelling;
8857+
hadError = parser.parseDeclModifierList(
8858+
MappedDecl->getAttrs(), staticLoc, staticSpelling,
8859+
/*isFromClangAttribute=*/true);
8860+
}
88468861

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

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)