|
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,32 @@ static bool isObjCMethodLikelyAsyncHandler(
|
7737 | 7738 | return false;
|
7738 | 7739 | }
|
7739 | 7740 |
|
| 7741 | +unsigned ClangImporter::Implementation::getClangSwiftAttrSourceBuffer( |
| 7742 | + StringRef attributeText) { |
| 7743 | + auto known = ClangSwiftAttrSourceBuffers.find(attributeText); |
| 7744 | + if (known != ClangSwiftAttrSourceBuffers.end()) |
| 7745 | + return known->second; |
| 7746 | + |
| 7747 | + // Create a new buffer with a copy of the attribute text, so we don't need to |
| 7748 | + // rely on Clang keeping it around. |
| 7749 | + auto &sourceMgr = SwiftContext.SourceMgr; |
| 7750 | + auto bufferID = sourceMgr.addMemBufferCopy(attributeText); |
| 7751 | + ClangSwiftAttrSourceBuffers.insert({attributeText, bufferID}); |
| 7752 | + return bufferID; |
| 7753 | +} |
| 7754 | + |
| 7755 | +SourceFile &ClangImporter::Implementation::getClangSwiftAttrSourceFile( |
| 7756 | + ModuleDecl &module) { |
| 7757 | + auto known = ClangSwiftAttrSourceFiles.find(&module); |
| 7758 | + if (known != ClangSwiftAttrSourceFiles.end()) |
| 7759 | + return *known->second; |
| 7760 | + |
| 7761 | + auto sourceFile = new (SwiftContext) SourceFile( |
| 7762 | + module, SourceFileKind::Library, None); |
| 7763 | + ClangSwiftAttrSourceFiles.insert({&module, sourceFile}); |
| 7764 | + return *sourceFile; |
| 7765 | +} |
| 7766 | + |
7740 | 7767 | /// Import Clang attributes as Swift attributes.
|
7741 | 7768 | void ClangImporter::Implementation::importAttributes(
|
7742 | 7769 | const clang::NamedDecl *ClangDecl,
|
@@ -7889,6 +7916,41 @@ void ClangImporter::Implementation::importAttributes(
|
7889 | 7916 |
|
7890 | 7917 | MappedDecl->getAttrs().add(AvAttr);
|
7891 | 7918 | }
|
| 7919 | + |
| 7920 | + // __attribute__((swift_attr("attribute"))) |
| 7921 | + // |
| 7922 | + if (auto swiftAttr = dyn_cast<clang::SwiftAttrAttr>(*AI)) { |
| 7923 | + // Dig out a buffer with the attribute text. |
| 7924 | + unsigned bufferID = getClangSwiftAttrSourceBuffer( |
| 7925 | + swiftAttr->getAttribute()); |
| 7926 | + |
| 7927 | + // Dig out a source file we can use for parsing. |
| 7928 | + auto &sourceFile = getClangSwiftAttrSourceFile( |
| 7929 | + *MappedDecl->getDeclContext()->getParentModule()); |
| 7930 | + |
| 7931 | + // Spin up a parser. |
| 7932 | + swift::Parser parser( |
| 7933 | + bufferID, sourceFile, &SwiftContext.Diags, nullptr, nullptr); |
| 7934 | + // Prime the lexer. |
| 7935 | + parser.consumeTokenWithoutFeedingReceiver(); |
| 7936 | + |
| 7937 | + |
| 7938 | + SourceLoc atLoc; |
| 7939 | + if (parser.consumeIf(tok::at_sign, atLoc)) { |
| 7940 | + (void)parser.parseDeclAttribute(MappedDecl->getAttrs(), atLoc); |
| 7941 | + } else { |
| 7942 | + // Complain about the missing '@'. |
| 7943 | + auto &clangSrcMgr = getClangASTContext().getSourceManager(); |
| 7944 | + ClangSourceBufferImporter &bufferImporter = |
| 7945 | + getBufferImporterForDiagnostics(); |
| 7946 | + SourceLoc attrLoc = bufferImporter.resolveSourceLocation( |
| 7947 | + clangSrcMgr, swiftAttr->getLocation()); |
| 7948 | + SwiftContext.Diags.diagnose( |
| 7949 | + attrLoc, diag::clang_swift_attr_without_at, |
| 7950 | + swiftAttr->getAttribute()); |
| 7951 | + } |
| 7952 | + continue; |
| 7953 | + } |
7892 | 7954 | }
|
7893 | 7955 |
|
7894 | 7956 | if (auto method = dyn_cast<clang::ObjCMethodDecl>(ClangDecl)) {
|
|
0 commit comments