|
45 | 45 | #include "swift/ClangImporter/ClangModule.h"
|
46 | 46 | #include "swift/Config.h"
|
47 | 47 | #include "swift/Parse/Lexer.h"
|
| 48 | +#include "swift/Parse/Parser.h" |
48 | 49 | #include "swift/Strings.h"
|
49 | 50 |
|
50 | 51 | #include "clang/AST/ASTContext.h"
|
@@ -7737,6 +7738,61 @@ static bool isObjCMethodLikelyAsyncHandler(
|
7737 | 7738 | return false;
|
7738 | 7739 | }
|
7739 | 7740 |
|
| 7741 | +Type ClangImporter::Implementation::getMainActorType() { |
| 7742 | + if (MainActorType) |
| 7743 | + return *MainActorType; |
| 7744 | + |
| 7745 | + auto finish = [&](Type type) -> Type { |
| 7746 | + MainActorType = type; |
| 7747 | + return type; |
| 7748 | + }; |
| 7749 | + |
| 7750 | + if (!SwiftContext.LangOpts.EnableExperimentalConcurrency) { |
| 7751 | + return finish(Type()); |
| 7752 | + } |
| 7753 | + |
| 7754 | + auto module = SwiftContext.getLoadedModule(SwiftContext.Id_Concurrency); |
| 7755 | + if (!module) |
| 7756 | + return finish(Type()); |
| 7757 | + |
| 7758 | + SmallVector<ValueDecl *, 1> decls; |
| 7759 | + module->lookupValue( |
| 7760 | + SwiftContext.getIdentifier("MainActor"), |
| 7761 | + NLKind::QualifiedLookup, decls); |
| 7762 | + for (auto decl : decls) { |
| 7763 | + if (auto typeDecl = dyn_cast<TypeDecl>(decl)) |
| 7764 | + return finish(typeDecl->getDeclaredInterfaceType()); |
| 7765 | + } |
| 7766 | + |
| 7767 | + return finish(Type()); |
| 7768 | +} |
| 7769 | + |
| 7770 | +unsigned ClangImporter::Implementation::getClangSwiftAttrSourceBuffer( |
| 7771 | + StringRef attributeText) { |
| 7772 | + auto known = ClangSwiftAttrSourceBuffers.find(attributeText); |
| 7773 | + if (known != ClangSwiftAttrSourceBuffers.end()) |
| 7774 | + return known->second; |
| 7775 | + |
| 7776 | + // Create a new buffer with a copy of the attribute text, so we don't need to |
| 7777 | + // rely on Clang keeping it around. |
| 7778 | + auto &sourceMgr = SwiftContext.SourceMgr; |
| 7779 | + auto bufferID = sourceMgr.addMemBufferCopy(attributeText); |
| 7780 | + ClangSwiftAttrSourceBuffers.insert({attributeText, bufferID}); |
| 7781 | + return bufferID; |
| 7782 | +} |
| 7783 | + |
| 7784 | +SourceFile &ClangImporter::Implementation::getClangSwiftAttrSourceFile( |
| 7785 | + ModuleDecl &module) { |
| 7786 | + auto known = ClangSwiftAttrSourceFiles.find(&module); |
| 7787 | + if (known != ClangSwiftAttrSourceFiles.end()) |
| 7788 | + return *known->second; |
| 7789 | + |
| 7790 | + auto sourceFile = new (SwiftContext) SourceFile( |
| 7791 | + module, SourceFileKind::Library, None); |
| 7792 | + ClangSwiftAttrSourceFiles.insert({&module, sourceFile}); |
| 7793 | + return *sourceFile; |
| 7794 | +} |
| 7795 | + |
7740 | 7796 | /// Import Clang attributes as Swift attributes.
|
7741 | 7797 | void ClangImporter::Implementation::importAttributes(
|
7742 | 7798 | const clang::NamedDecl *ClangDecl,
|
@@ -7889,6 +7945,53 @@ void ClangImporter::Implementation::importAttributes(
|
7889 | 7945 |
|
7890 | 7946 | MappedDecl->getAttrs().add(AvAttr);
|
7891 | 7947 | }
|
| 7948 | + |
| 7949 | + // __attribute__((swift_attr("attribute"))) |
| 7950 | + // |
| 7951 | + if (auto swiftAttr = dyn_cast<clang::SwiftAttrAttr>(*AI)) { |
| 7952 | + // FIXME: Hard-core @MainActor, because we don't have a point at which to |
| 7953 | + // do name lookup for imported entities. |
| 7954 | + if (swiftAttr->getAttribute() == "@MainActor") { |
| 7955 | + if (Type mainActorType = getMainActorType()) { |
| 7956 | + auto typeExpr = TypeExpr::createImplicit(mainActorType, SwiftContext); |
| 7957 | + auto attr = CustomAttr::create(SwiftContext, SourceLoc(), typeExpr); |
| 7958 | + MappedDecl->getAttrs().add(attr); |
| 7959 | + } |
| 7960 | + |
| 7961 | + continue; |
| 7962 | + } |
| 7963 | + |
| 7964 | + // Dig out a buffer with the attribute text. |
| 7965 | + unsigned bufferID = getClangSwiftAttrSourceBuffer( |
| 7966 | + swiftAttr->getAttribute()); |
| 7967 | + |
| 7968 | + // Dig out a source file we can use for parsing. |
| 7969 | + auto &sourceFile = getClangSwiftAttrSourceFile( |
| 7970 | + *MappedDecl->getDeclContext()->getParentModule()); |
| 7971 | + |
| 7972 | + // Spin up a parser. |
| 7973 | + swift::Parser parser( |
| 7974 | + bufferID, sourceFile, &SwiftContext.Diags, nullptr, nullptr); |
| 7975 | + // Prime the lexer. |
| 7976 | + parser.consumeTokenWithoutFeedingReceiver(); |
| 7977 | + |
| 7978 | + SourceLoc atLoc; |
| 7979 | + if (parser.consumeIf(tok::at_sign, atLoc)) { |
| 7980 | + (void)parser.parseDeclAttribute( |
| 7981 | + MappedDecl->getAttrs(), atLoc, /*isFromClangAttribute=*/true); |
| 7982 | + } else { |
| 7983 | + // Complain about the missing '@'. |
| 7984 | + auto &clangSrcMgr = getClangASTContext().getSourceManager(); |
| 7985 | + ClangSourceBufferImporter &bufferImporter = |
| 7986 | + getBufferImporterForDiagnostics(); |
| 7987 | + SourceLoc attrLoc = bufferImporter.resolveSourceLocation( |
| 7988 | + clangSrcMgr, swiftAttr->getLocation()); |
| 7989 | + SwiftContext.Diags.diagnose( |
| 7990 | + attrLoc, diag::clang_swift_attr_without_at, |
| 7991 | + swiftAttr->getAttribute()); |
| 7992 | + } |
| 7993 | + continue; |
| 7994 | + } |
7892 | 7995 | }
|
7893 | 7996 |
|
7894 | 7997 | if (auto method = dyn_cast<clang::ObjCMethodDecl>(ClangDecl)) {
|
|
0 commit comments