Skip to content

[Clang importer] Consider attributes on the typedef name for an anonymous tag #42604

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
128 changes: 70 additions & 58 deletions lib/ClangImporter/ImportDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8787,74 +8787,86 @@ ClangImporter::Implementation::importSwiftAttrAttributes(Decl *MappedDecl) {
Optional<const clang::SwiftAttrAttr *> SeenMainActorAttr;
PatternBindingInitializer *initContext = nullptr;

//
// __attribute__((swift_attr("attribute")))
//
for (auto swiftAttr : ClangDecl->specific_attrs<clang::SwiftAttrAttr>()) {
// FIXME: Hard-code @MainActor and @UIActor, because we don't have a
// point at which to do name lookup for imported entities.
if (isMainActorAttr(swiftAttr)) {
if (SeenMainActorAttr) {
// Cannot add main actor annotation twice. We'll keep the first
// one and raise a warning about the duplicate.
HeaderLoc attrLoc(swiftAttr->getLocation());
diagnose(attrLoc, diag::import_multiple_mainactor_attr,
swiftAttr->getAttribute(),
SeenMainActorAttr.getValue()->getAttribute());
auto importAttrsFromDecl = [&](const clang::NamedDecl *ClangDecl) {
//
// __attribute__((swift_attr("attribute")))
//
for (auto swiftAttr : ClangDecl->specific_attrs<clang::SwiftAttrAttr>()) {
// FIXME: Hard-code @MainActor and @UIActor, because we don't have a
// point at which to do name lookup for imported entities.
if (isMainActorAttr(swiftAttr)) {
if (SeenMainActorAttr) {
// Cannot add main actor annotation twice. We'll keep the first
// one and raise a warning about the duplicate.
HeaderLoc attrLoc(swiftAttr->getLocation());
diagnose(attrLoc, diag::import_multiple_mainactor_attr,
swiftAttr->getAttribute(),
SeenMainActorAttr.getValue()->getAttribute());
continue;
}

if (Type mainActorType = SwiftContext.getMainActorType()) {
auto typeExpr = TypeExpr::createImplicit(mainActorType, SwiftContext);
auto attr = CustomAttr::create(SwiftContext, SourceLoc(), typeExpr);
MappedDecl->getAttrs().add(attr);
SeenMainActorAttr = swiftAttr;
}

continue;
}

if (Type mainActorType = SwiftContext.getMainActorType()) {
auto typeExpr = TypeExpr::createImplicit(mainActorType, SwiftContext);
auto attr = CustomAttr::create(SwiftContext, SourceLoc(), typeExpr);
// Hard-code @actorIndependent, until Objective-C clients start
// using nonisolated.
if (swiftAttr->getAttribute() == "@actorIndependent") {
auto attr = new (SwiftContext) NonisolatedAttr(/*isImplicit=*/true);
MappedDecl->getAttrs().add(attr);
SeenMainActorAttr = swiftAttr;
continue;
}

continue;
}

// Hard-code @actorIndependent, until Objective-C clients start
// using nonisolated.
if (swiftAttr->getAttribute() == "@actorIndependent") {
auto attr = new (SwiftContext) NonisolatedAttr(/*isImplicit=*/true);
MappedDecl->getAttrs().add(attr);
continue;
}
// Dig out a buffer with the attribute text.
unsigned bufferID = getClangSwiftAttrSourceBuffer(
swiftAttr->getAttribute());

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

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

// Spin up a parser.
swift::Parser parser(
bufferID, sourceFile, &SwiftContext.Diags, nullptr, nullptr);
// Prime the lexer.
parser.consumeTokenWithoutFeedingReceiver();
bool hadError = false;
SourceLoc atLoc;
if (parser.consumeIf(tok::at_sign, atLoc)) {
hadError = parser.parseDeclAttribute(
MappedDecl->getAttrs(), atLoc, initContext,
/*isFromClangAttribute=*/true).isError();
} else {
SourceLoc staticLoc;
StaticSpellingKind staticSpelling;
hadError = parser.parseDeclModifierList(
MappedDecl->getAttrs(), staticLoc, staticSpelling,
/*isFromClangAttribute=*/true);
}

bool hadError = false;
SourceLoc atLoc;
if (parser.consumeIf(tok::at_sign, atLoc)) {
hadError = parser.parseDeclAttribute(
MappedDecl->getAttrs(), atLoc, initContext,
/*isFromClangAttribute=*/true).isError();
} else {
SourceLoc staticLoc;
StaticSpellingKind staticSpelling;
hadError = parser.parseDeclModifierList(
MappedDecl->getAttrs(), staticLoc, staticSpelling,
/*isFromClangAttribute=*/true);
}

if (hadError) {
// Complain about the unhandled attribute or modifier.
HeaderLoc attrLoc(swiftAttr->getLocation());
diagnose(attrLoc, diag::clang_swift_attr_unhandled,
swiftAttr->getAttribute());
if (hadError) {
// Complain about the unhandled attribute or modifier.
HeaderLoc attrLoc(swiftAttr->getLocation());
diagnose(attrLoc, diag::clang_swift_attr_unhandled,
swiftAttr->getAttribute());
}
}
};
importAttrsFromDecl(ClangDecl);

// If the Clang declaration is from an anonymous tag that was given a
// name via a typedef, look for attributes on the typedef as well.
if (auto tag = dyn_cast<clang::TagDecl>(ClangDecl)) {
if (tag->getName().empty()) {
if (auto typedefDecl = tag->getTypedefNameForAnonDecl())
importAttrsFromDecl(typedefDecl);
}
}

Expand Down
10 changes: 9 additions & 1 deletion test/ClangImporter/objc_async.swift
Original file line number Diff line number Diff line change
Expand Up @@ -177,8 +177,16 @@ actor MySubclassCheckingSwiftAttributes : ProtocolWithSwiftAttributes {

// Sendable conformance inference for imported types.
func acceptCV<T: Sendable>(_: T) { }
func testCV(r: NSRange) {

struct MyStruct: Sendable {
var range: NSRange
var inner: SendableStructWithNonSendable
}

@available(SwiftStdlib 5.5, *)
func testCV(r: NSRange, someStruct: SendableStructWithNonSendable) async {
acceptCV(r)
acceptCV(someStruct)
}

// Global actor (unsafe) isolation.
Expand Down
5 changes: 5 additions & 0 deletions test/Inputs/clang-importer-sdk/usr/include/ObjCConcurrency.h
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,11 @@ typedef NSString *NonSendableStringEnum NS_STRING_ENUM NONSENDABLE;
typedef NSString *SendableStringStruct NS_EXTENSIBLE_STRING_ENUM;
typedef NSString *NonSendableStringStruct NS_EXTENSIBLE_STRING_ENUM NONSENDABLE;

SENDABLE
typedef struct {
void *ptr;
} SendableStructWithNonSendable;

ASSUME_NONSENDABLE_END

typedef id ObjectTypedef;
Expand Down