diff --git a/include/swift/AST/ASTScope.h b/include/swift/AST/ASTScope.h index 03c2f4540c545..73cf141218ea3 100644 --- a/include/swift/AST/ASTScope.h +++ b/include/swift/AST/ASTScope.h @@ -808,6 +808,8 @@ class AbstractFunctionDeclScope final : public ASTScopeImpl { protected: void printSpecifics(llvm::raw_ostream &out) const override; + bool lookupLocalsOrMembers(DeclConsumer) const override; + public: Decl *getDecl() const { return decl; } diff --git a/include/swift/AST/NameLookup.h b/include/swift/AST/NameLookup.h index d082492f1af1e..66469ef1a558c 100644 --- a/include/swift/AST/NameLookup.h +++ b/include/swift/AST/NameLookup.h @@ -528,6 +528,15 @@ void lookupVisibleMemberDecls(VisibleDeclConsumer &Consumer, bool includeProtocolExtensionMembers, GenericSignature genericSig = GenericSignature()); +/// Determine the module-scope context from which lookup should proceed. +/// +/// In the common case, module-scope context is the source file in which +/// the declaration context is nested. However, when declaration context is +/// part of an imported Clang declaration context, it won't be nested within a +/// source file. Rather, the source file will be on the side, and will be +/// provided here because it contains information about the available imports. +DeclContext *getModuleScopeLookupContext(DeclContext *dc); + namespace namelookup { /// Add semantic members to \p type before attempting a semantic lookup. diff --git a/include/swift/Basic/BasicBridging.h b/include/swift/Basic/BasicBridging.h index 5aa3a9faed9f3..46a7518111f27 100644 --- a/include/swift/Basic/BasicBridging.h +++ b/include/swift/Basic/BasicBridging.h @@ -445,6 +445,7 @@ enum ENUM_EXTENSIBILITY_ATTR(closed) BridgedGeneratedSourceFileKind { BridgedGeneratedSourceFileKindReplacedFunctionBody, BridgedGeneratedSourceFileKindPrettyPrinted, BridgedGeneratedSourceFileKindDefaultArgument, + BridgedGeneratedSourceFileKindAttribute, BridgedGeneratedSourceFileKindNone, }; diff --git a/include/swift/Basic/SourceManager.h b/include/swift/Basic/SourceManager.h index 70563b1558e38..df00da8676213 100644 --- a/include/swift/Basic/SourceManager.h +++ b/include/swift/Basic/SourceManager.h @@ -65,6 +65,9 @@ class GeneratedSourceInfo { /// The expansion of default argument at caller side DefaultArgument, + + /// A Swift attribute expressed in C headers. + Attribute, } kind; static StringRef kindToString(GeneratedSourceInfo::Kind kind) { @@ -80,6 +83,8 @@ class GeneratedSourceInfo { return "PrettyPrinted"; case DefaultArgument: return "DefaultArgument"; + case Attribute: + return "Attribute"; } llvm_unreachable("Invalid kind"); } diff --git a/include/swift/Subsystems.h b/include/swift/Subsystems.h index 5ed276dfa6169..a42436e47b775 100644 --- a/include/swift/Subsystems.h +++ b/include/swift/Subsystems.h @@ -120,6 +120,12 @@ namespace swift { /// This walks the AST to resolve imports. void performImportResolution(SourceFile &SF); + /// Resolve imports for a source file generated to adapt a given + /// Clang module. + void performImportResolutionForClangMacroBuffer( + SourceFile &SF, ModuleDecl *clangModule + ); + /// Once type-checking is complete, this instruments code with calls to an /// intrinsic that record the expected values of local variables so they can /// be compared against the results from the debugger. diff --git a/lib/AST/ASTMangler.cpp b/lib/AST/ASTMangler.cpp index 05bc77f524cd0..a1f45686c8cf3 100644 --- a/lib/AST/ASTMangler.cpp +++ b/lib/AST/ASTMangler.cpp @@ -4535,6 +4535,7 @@ void ASTMangler::appendMacroExpansionContext( case GeneratedSourceInfo::PrettyPrinted: case GeneratedSourceInfo::ReplacedFunctionBody: case GeneratedSourceInfo::DefaultArgument: + case GeneratedSourceInfo::Attribute: return appendMacroExpansionLoc(); } @@ -4586,6 +4587,7 @@ void ASTMangler::appendMacroExpansionContext( case GeneratedSourceInfo::PrettyPrinted: case GeneratedSourceInfo::ReplacedFunctionBody: case GeneratedSourceInfo::DefaultArgument: + case GeneratedSourceInfo::Attribute: llvm_unreachable("Exited above"); } diff --git a/lib/AST/ASTScopeLookup.cpp b/lib/AST/ASTScopeLookup.cpp index 2ad13b446027a..10b182a04e25e 100644 --- a/lib/AST/ASTScopeLookup.cpp +++ b/lib/AST/ASTScopeLookup.cpp @@ -30,6 +30,7 @@ #include "swift/AST/Stmt.h" #include "swift/AST/TypeRepr.h" #include "swift/Basic/STLExtras.h" +#include "swift/ClangImporter/ClangModule.h" #include "swift/Parse/Lexer.h" #include "llvm/Support/Compiler.h" @@ -264,6 +265,20 @@ bool ASTScopeImpl::lookupLocalsOrMembers(DeclConsumer) const { return false; // many kinds of scopes have none } +bool AbstractFunctionDeclScope::lookupLocalsOrMembers(DeclConsumer consumer) const { + // Special case: if we're within a function inside a type context, but the + // parent context is within a Clang module unit, we need to make sure to + // look for members in it. + auto dc = decl->getDeclContext(); + if (!dc->isTypeContext()) + return false; + + if (!isa(dc->getModuleScopeContext())) + return false; + + return consumer.lookInMembers(cast(dc->getAsDecl())); +} + bool GenericTypeOrExtensionScope::lookupLocalsOrMembers( ASTScopeImpl::DeclConsumer consumer) const { return portion->lookupMembersOf(this, consumer); diff --git a/lib/AST/AvailabilityScope.cpp b/lib/AST/AvailabilityScope.cpp index ba7279c7d90c8..d9dc19bad0f0a 100644 --- a/lib/AST/AvailabilityScope.cpp +++ b/lib/AST/AvailabilityScope.cpp @@ -55,8 +55,10 @@ AvailabilityScope::createForSourceFile(SourceFile *SF, case SourceFileKind::DefaultArgument: { // Look up the parent context in the enclosing file that this file's // root context should be nested under. - if (auto parentScope = - SF->getEnclosingSourceFile()->getAvailabilityScope()) { + auto enclosingSF = SF->getEnclosingSourceFile(); + if (!enclosingSF) + break; + if (auto parentScope = enclosingSF->getAvailabilityScope()) { auto charRange = Ctx.SourceMgr.getRangeForBuffer(SF->getBufferID()); range = SourceRange(charRange.getStart(), charRange.getEnd()); auto originalNode = SF->getNodeInEnclosingSourceFile(); diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 59720623b7918..49c74c016ccf4 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -12075,6 +12075,7 @@ MacroDiscriminatorContext MacroDiscriminatorContext::getParentOf( case GeneratedSourceInfo::PrettyPrinted: case GeneratedSourceInfo::ReplacedFunctionBody: case GeneratedSourceInfo::DefaultArgument: + case GeneratedSourceInfo::Attribute: return origDC; } } diff --git a/lib/AST/DiagnosticEngine.cpp b/lib/AST/DiagnosticEngine.cpp index 9f82161bd3dbe..cdabd311a3c46 100644 --- a/lib/AST/DiagnosticEngine.cpp +++ b/lib/AST/DiagnosticEngine.cpp @@ -1336,6 +1336,7 @@ DiagnosticEngine::diagnosticInfoForDiagnostic(const Diagnostic &diagnostic) { #include "swift/Basic/MacroRoles.def" case GeneratedSourceInfo::PrettyPrinted: case GeneratedSourceInfo::DefaultArgument: + case GeneratedSourceInfo::Attribute: fixIts = {}; break; case GeneratedSourceInfo::ReplacedFunctionBody: @@ -1381,6 +1382,7 @@ getGeneratedSourceInfoMacroName(const GeneratedSourceInfo &info) { case GeneratedSourceInfo::PrettyPrinted: case GeneratedSourceInfo::ReplacedFunctionBody: case GeneratedSourceInfo::DefaultArgument: + case GeneratedSourceInfo::Attribute: return DeclName(); } } @@ -1442,6 +1444,7 @@ DiagnosticEngine::getGeneratedSourceBufferNotes(SourceLoc loc) { case GeneratedSourceInfo::DefaultArgument: case GeneratedSourceInfo::ReplacedFunctionBody: + case GeneratedSourceInfo::Attribute: return childNotes; } diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index 62cdf97fbb8d5..2a9bcbbee86c5 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -1633,9 +1633,12 @@ Expr *DefaultArgumentExpr::getCallerSideDefaultExpr() const { assert(isCallerSide()); auto &ctx = DefaultArgsOwner.getDecl()->getASTContext(); auto *mutableThis = const_cast(this); - return evaluateOrDefault(ctx.evaluator, + if (auto result = evaluateOrDefault(ctx.evaluator, CallerSideDefaultArgExprRequest{mutableThis}, - new (ctx) ErrorExpr(getSourceRange(), getType())); + nullptr)) + return result; + + return new (ctx) ErrorExpr(getSourceRange(), getType()); } ActorIsolation diff --git a/lib/AST/Module.cpp b/lib/AST/Module.cpp index f9234c44d4817..5c3d92970b43e 100644 --- a/lib/AST/Module.cpp +++ b/lib/AST/Module.cpp @@ -862,6 +862,7 @@ ModuleDecl::getOriginalLocation(SourceLoc loc) const { // replaced function bodies. The body is actually different code to the // original file. case GeneratedSourceInfo::PrettyPrinted: + case GeneratedSourceInfo::Attribute: // No original location, return the original buffer/location return {startBufferID, startLoc}; } @@ -1148,6 +1149,7 @@ std::optional SourceFile::getFulfilledMacroRole() const { case GeneratedSourceInfo::ReplacedFunctionBody: case GeneratedSourceInfo::PrettyPrinted: case GeneratedSourceInfo::DefaultArgument: + case GeneratedSourceInfo::Attribute: return std::nullopt; } } diff --git a/lib/AST/NameLookup.cpp b/lib/AST/NameLookup.cpp index e0f585ca361a5..b4bbab2647be4 100644 --- a/lib/AST/NameLookup.cpp +++ b/lib/AST/NameLookup.cpp @@ -1698,7 +1698,7 @@ SmallVector namelookup::lookupMacros(DeclContext *dc, DeclNameRef macroName, MacroRoles roles) { SmallVector choices; - auto moduleScopeDC = dc->getModuleScopeContext(); + auto moduleScopeDC = getModuleScopeLookupContext(dc); ASTContext &ctx = moduleScopeDC->getASTContext(); auto addChoiceIfApplicable = [&](ValueDecl *decl) { diff --git a/lib/AST/UnqualifiedLookup.cpp b/lib/AST/UnqualifiedLookup.cpp index 9d36b25ea4413..0dd358a59a49d 100644 --- a/lib/AST/UnqualifiedLookup.cpp +++ b/lib/AST/UnqualifiedLookup.cpp @@ -30,6 +30,7 @@ #include "swift/Basic/STLExtras.h" #include "swift/Basic/SourceManager.h" #include "swift/Basic/Statistic.h" +#include "swift/ClangImporter/ClangModule.h" #include "swift/Parse/Lexer.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/TinyPtrVector.h" @@ -265,7 +266,8 @@ void UnqualifiedLookupFactory::performUnqualifiedLookup() { if (!isFirstResultEnough()) { // If no result has been found yet, the dependency must be on a top-level // name, since up to now, the search has been for non-top-level names. - auto *moduleScopeContext = DC->getModuleScopeContext(); + auto *moduleScopeContext = getModuleScopeLookupContext(DC); + lookUpTopLevelNamesInModuleScopeContext(moduleScopeContext); } } @@ -939,3 +941,19 @@ ValueDecl *ASTScope::lookupSingleLocalDecl(SourceFile *sf, DeclName name, return nullptr; return result[0]; } + +DeclContext *swift::getModuleScopeLookupContext(DeclContext *dc) { + auto moduleScopeContext = dc->getModuleScopeContext(); + + // When the module scope context is in a Clang module but we actually + // have a parent source file, it's because we are within a macro + // expansion triggered for the imported declaration. In such cases, + // we want to use the parent source file as the lookup context, becauae + // it has the appropriate resolved imports. + if (isa(moduleScopeContext)) { + if (auto parentSF = dc->getParentSourceFile()) + return parentSF; + } + + return moduleScopeContext; +} diff --git a/lib/ASTGen/Sources/ASTGen/SourceFile.swift b/lib/ASTGen/Sources/ASTGen/SourceFile.swift index 8684a51c85aa8..06c0b85fd1993 100644 --- a/lib/ASTGen/Sources/ASTGen/SourceFile.swift +++ b/lib/ASTGen/Sources/ASTGen/SourceFile.swift @@ -140,7 +140,8 @@ public func parseSourceFile( case .accessorMacroExpansion: // FIXME: Implement specialized parsing. parsed = Syntax(SourceFileSyntax.parse(from: &parser)) - case .memberAttributeMacroExpansion: + case .memberAttributeMacroExpansion, + .attribute: // FIXME: Implement specialized parsing. parsed = Syntax(SourceFileSyntax.parse(from: &parser)) case .bodyMacroExpansion: diff --git a/lib/Basic/SourceLoc.cpp b/lib/Basic/SourceLoc.cpp index 8d57c3956e0bb..e983266701baa 100644 --- a/lib/Basic/SourceLoc.cpp +++ b/lib/Basic/SourceLoc.cpp @@ -303,10 +303,11 @@ StringRef SourceManager::getIdentifierForBuffer( if (ForceGeneratedSourceToDisk) { if (const GeneratedSourceInfo *generatedInfo = getGeneratedSourceInfo(bufferID)) { - // We only care about macros, so skip everything else. + // We only care about macro expansion buffers, so skip everything else. if (generatedInfo->kind == GeneratedSourceInfo::ReplacedFunctionBody || generatedInfo->kind == GeneratedSourceInfo::PrettyPrinted || - generatedInfo->kind == GeneratedSourceInfo::DefaultArgument) + generatedInfo->kind == GeneratedSourceInfo::DefaultArgument || + generatedInfo->kind == GeneratedSourceInfo::Attribute) return buffer->getBufferIdentifier(); if (generatedInfo->onDiskBufferCopyFileName.empty()) { @@ -400,6 +401,7 @@ void SourceManager::setGeneratedSourceInfo( #include "swift/Basic/MacroRoles.def" case GeneratedSourceInfo::PrettyPrinted: case GeneratedSourceInfo::DefaultArgument: + case GeneratedSourceInfo::Attribute: break; case GeneratedSourceInfo::ReplacedFunctionBody: diff --git a/lib/ClangImporter/ClangImporter.cpp b/lib/ClangImporter/ClangImporter.cpp index 068996cbaa720..978f18afad634 100644 --- a/lib/ClangImporter/ClangImporter.cpp +++ b/lib/ClangImporter/ClangImporter.cpp @@ -2798,7 +2798,11 @@ ClangModuleUnit *ClangImporter::Implementation::getWrapperForModule( Identifier name = underlying->Name == "std" ? SwiftContext.Id_CxxStdlib : SwiftContext.getIdentifier(underlying->Name); - auto wrapper = ModuleDecl::create(name, SwiftContext); + ImplicitImportInfo implicitImportInfo; + if (auto mainModule = SwiftContext.MainModule) { + implicitImportInfo = mainModule->getImplicitImportInfo(); + } + auto wrapper = ModuleDecl::create(name, SwiftContext, implicitImportInfo); wrapper->setIsSystemModule(underlying->IsSystem); wrapper->setIsNonSwiftModule(); wrapper->setHasResolvedImports(); diff --git a/lib/ClangImporter/ImportDecl.cpp b/lib/ClangImporter/ImportDecl.cpp index 28a89543a11ef..3c7ecf92ec2da 100644 --- a/lib/ClangImporter/ImportDecl.cpp +++ b/lib/ClangImporter/ImportDecl.cpp @@ -8194,29 +8194,38 @@ bool importer::hasSameUnderlyingType(const clang::Type *a, return a == b->getTypeForDecl(); } -unsigned ClangImporter::Implementation::getClangSwiftAttrSourceBuffer( - StringRef attributeText) { - auto known = ClangSwiftAttrSourceBuffers.find(attributeText); - if (known != ClangSwiftAttrSourceBuffers.end()) - return known->second; +SourceFile &ClangImporter::Implementation::getClangSwiftAttrSourceFile( + ModuleDecl &module, + StringRef attributeText +) { + auto &sourceFiles = ClangSwiftAttrSourceFiles[attributeText]; + + // Check whether we've already created a source file. + for (auto sourceFile : sourceFiles) { + if (sourceFile->getParentModule() == &module) + return *sourceFile; + } - // Create a new buffer with a copy of the attribute text, so we don't need to - // rely on Clang keeping it around. + // Create a new buffer with a copy of the attribute text, + // so we don't need to rely on Clang keeping it around. auto &sourceMgr = SwiftContext.SourceMgr; auto bufferID = sourceMgr.addMemBufferCopy(attributeText); - ClangSwiftAttrSourceBuffers.insert({attributeText, bufferID}); - return bufferID; -} -SourceFile &ClangImporter::Implementation::getClangSwiftAttrSourceFile( - ModuleDecl &module, unsigned bufferID) { - auto known = ClangSwiftAttrSourceFiles.find(&module); - if (known != ClangSwiftAttrSourceFiles.end()) - return *known->second; + // Note that this is for an attribute. + sourceMgr.setGeneratedSourceInfo( + bufferID, + { + GeneratedSourceInfo::Attribute, + CharSourceRange(), + sourceMgr.getRangeForBuffer(bufferID), + &module + } + ); + // Create the source file. auto sourceFile = new (SwiftContext) SourceFile(module, SourceFileKind::Library, bufferID); - ClangSwiftAttrSourceFiles.insert({&module, sourceFile}); + sourceFiles.push_back(sourceFile); return *sourceFile; } @@ -8392,17 +8401,15 @@ ClangImporter::Implementation::importSwiftAttrAttributes(Decl *MappedDecl) { continue; } - // 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(), bufferID); + *MappedDecl->getDeclContext()->getParentModule(), + swiftAttr->getAttribute()); // Spin up a parser. swift::Parser parser( - bufferID, sourceFile, &SwiftContext.Diags, nullptr, nullptr); + sourceFile.getBufferID(), sourceFile, &SwiftContext.Diags, + nullptr, nullptr); // Prime the lexer. parser.consumeTokenWithoutFeedingReceiver(); diff --git a/lib/ClangImporter/ImporterImpl.h b/lib/ClangImporter/ImporterImpl.h index b0360910df3cc..06284eee4c65a 100644 --- a/lib/ClangImporter/ImporterImpl.h +++ b/lib/ClangImporter/ImporterImpl.h @@ -538,14 +538,11 @@ class LLVM_LIBRARY_VISIBILITY ClangImporter::Implementation /// Clang arguments used to create the Clang invocation. std::vector ClangArgs; - /// Mapping from Clang swift_attr attribute text to the Swift source buffer - /// IDs that contain that attribute text. These are re-used when parsing the - /// Swift attributes on import. - llvm::StringMap ClangSwiftAttrSourceBuffers; - - /// Mapping from modules in which a Clang swift_attr attribute occurs, to be - /// used when parsing the attribute text. - llvm::SmallDenseMap ClangSwiftAttrSourceFiles; + /// Mapping from Clang swift_attr attribute text to the Swift source file(s) + /// that contain that attribute text. + /// + /// These are re-used when parsing the Swift attributes on import. + llvm::StringMap> ClangSwiftAttrSourceFiles; public: /// The Swift lookup table for the bridging header. @@ -1058,13 +1055,9 @@ class LLVM_LIBRARY_VISIBILITY ClangImporter::Implementation /// Map a Clang identifier name to its imported Swift equivalent. StringRef getSwiftNameFromClangName(StringRef name); - /// Retrieve the Swift source buffer ID that corresponds to the given - /// swift_attr attribute text, creating one if necessary. - unsigned getClangSwiftAttrSourceBuffer(StringRef attributeText); - /// Retrieve the placeholder source file for use in parsing Swift attributes /// in the given module. - SourceFile &getClangSwiftAttrSourceFile(ModuleDecl &module, unsigned bufferID); + SourceFile &getClangSwiftAttrSourceFile(ModuleDecl &module, StringRef attributeText); /// Utility function to import Clang attributes from a source Swift decl to /// synthesized Swift decl. diff --git a/lib/IDE/Utils.cpp b/lib/IDE/Utils.cpp index 1a2061098aedd..a380b31f60d19 100644 --- a/lib/IDE/Utils.cpp +++ b/lib/IDE/Utils.cpp @@ -661,6 +661,7 @@ adjustMacroExpansionWhitespace(GeneratedSourceInfo::Kind kind, case GeneratedSourceInfo::ReplacedFunctionBody: case GeneratedSourceInfo::PrettyPrinted: case GeneratedSourceInfo::DefaultArgument: + case GeneratedSourceInfo::Attribute: return expandedCode; } } diff --git a/lib/IRGen/IRGenDebugInfo.cpp b/lib/IRGen/IRGenDebugInfo.cpp index 51bcf2581bad2..5cb94bec49688 100644 --- a/lib/IRGen/IRGenDebugInfo.cpp +++ b/lib/IRGen/IRGenDebugInfo.cpp @@ -296,9 +296,12 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo { if (!ForceGeneratedSourceToDisk) { auto BufferID = SM.findBufferContainingLoc(SL); if (auto generatedInfo = SM.getGeneratedSourceInfo(BufferID)) { - // We only care about macros, so skip everything else. + // We only care about macro expansion buffers, + // so skip everything else. if (generatedInfo->kind != GeneratedSourceInfo::ReplacedFunctionBody && - generatedInfo->kind != GeneratedSourceInfo::PrettyPrinted) + generatedInfo->kind != GeneratedSourceInfo::PrettyPrinted && + generatedInfo->kind != GeneratedSourceInfo::DefaultArgument && + generatedInfo->kind != GeneratedSourceInfo::Attribute) if (auto *MemBuf = SM.getLLVMSourceMgr().getMemoryBuffer(BufferID)) { Source = MemBuf->getBuffer(); // This is copying the buffer twice, but Xcode depends on this diff --git a/lib/Parse/ParseRequests.cpp b/lib/Parse/ParseRequests.cpp index ac0feb818bea7..ae36a5edc3365 100644 --- a/lib/Parse/ParseRequests.cpp +++ b/lib/Parse/ParseRequests.cpp @@ -114,11 +114,23 @@ ParseAbstractFunctionBodyRequest::evaluate(Evaluator &evaluator, case BodyKind::Unparsed: { // FIXME: How do we configure code completion? - SourceFile &sf = *afd->getDeclContext()->getParentSourceFile(); - SourceManager &sourceMgr = sf.getASTContext().SourceMgr; + SourceManager &sourceMgr = afd->getASTContext().SourceMgr; unsigned bufferID = sourceMgr.findBufferContainingLoc(afd->getBodySourceRange().Start); - Parser parser(bufferID, sf, /*SIL*/ nullptr); + SourceFile *sf = afd->getDeclContext()->getParentSourceFile(); + if (!sf) { + auto sourceFiles = sourceMgr.getSourceFilesForBufferID(bufferID); + auto expectedModule = afd->getParentModule(); + for (auto checkSF: sourceFiles) { + if (checkSF->getParentModule() == expectedModule) { + sf = checkSF; + break; + } + } + assert(sf && "Could not find source file containing parsed body"); + } + + Parser parser(bufferID, *sf, /*SIL*/ nullptr); auto result = parser.parseAbstractFunctionBodyDelayed(afd); afd->setBodyKind(BodyKind::Parsed); return result; @@ -150,6 +162,8 @@ getBridgedGeneratedSourceFileKind(const GeneratedSourceInfo *genInfo) { return BridgedGeneratedSourceFileKindPrettyPrinted; case GeneratedSourceInfo::Kind::DefaultArgument: return BridgedGeneratedSourceFileKindDefaultArgument; + case GeneratedSourceInfo::Attribute: + return BridgedGeneratedSourceFileKindAttribute; } } @@ -364,7 +378,8 @@ SourceFileParsingResult parseSourceFile(SourceFile &SF) { break; } - case GeneratedSourceInfo::MemberAttributeMacroExpansion: { + case GeneratedSourceInfo::MemberAttributeMacroExpansion: + case GeneratedSourceInfo::Attribute: { parser.parseExpandedAttributeList(items); break; } diff --git a/lib/SILGen/SILGenFunction.cpp b/lib/SILGen/SILGenFunction.cpp index 7637d4619a467..2422e0620e66e 100644 --- a/lib/SILGen/SILGenFunction.cpp +++ b/lib/SILGen/SILGenFunction.cpp @@ -348,6 +348,7 @@ static MacroInfo getMacroInfo(const GeneratedSourceInfo &Info, case GeneratedSourceInfo::PrettyPrinted: case GeneratedSourceInfo::ReplacedFunctionBody: case GeneratedSourceInfo::DefaultArgument: + case GeneratedSourceInfo::Attribute: break; } return Result; diff --git a/lib/Sema/ImportResolution.cpp b/lib/Sema/ImportResolution.cpp index 73bd961274b0c..2847cfb66b27b 100644 --- a/lib/Sema/ImportResolution.cpp +++ b/lib/Sema/ImportResolution.cpp @@ -192,6 +192,11 @@ class ImportResolver final : public DeclVisitor { void addImplicitImports(); + void addImplicitImport(ModuleDecl *module) { + boundImports.push_back(ImportedModule(module)); + bindPendingImports(); + } + /// Retrieve the finalized imports. ArrayRef> getFinishedImports() const { return boundImports; @@ -301,6 +306,22 @@ void swift::performImportResolution(SourceFile &SF) { verify(SF); } +void swift::performImportResolutionForClangMacroBuffer( + SourceFile &SF, ModuleDecl *clangModule +) { + // If we've already performed import resolution, bail. + if (SF.ASTStage == SourceFile::ImportsResolved) + return; + + ImportResolver resolver(SF); + resolver.addImplicitImport(clangModule); + + SF.setImports(resolver.getFinishedImports()); + SF.setImportedUnderlyingModule(resolver.getUnderlyingClangModule()); + + SF.ASTStage = SourceFile::ImportsResolved; +} + //===----------------------------------------------------------------------===// // MARK: Import handling generally //===----------------------------------------------------------------------===// diff --git a/lib/Sema/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp index c208b626f029a..fe214c6a5e6a4 100644 --- a/lib/Sema/TypeCheckDecl.cpp +++ b/lib/Sema/TypeCheckDecl.cpp @@ -52,9 +52,11 @@ #include "swift/Basic/Assertions.h" #include "swift/Basic/Defer.h" #include "swift/Bridging/ASTGen.h" +#include "swift/ClangImporter/ClangModule.h" #include "swift/Sema/IDETypeChecking.h" #include "swift/Serialization/SerializedModuleLoader.h" #include "swift/Strings.h" +#include "swift/Subsystems.h" #include "llvm/ADT/APFloat.h" #include "llvm/ADT/APInt.h" #include "llvm/ADT/APSInt.h" diff --git a/lib/Sema/TypeCheckMacros.cpp b/lib/Sema/TypeCheckMacros.cpp index 8b0c4ccc24ef3..439ae27ac5dd5 100644 --- a/lib/Sema/TypeCheckMacros.cpp +++ b/lib/Sema/TypeCheckMacros.cpp @@ -1033,8 +1033,11 @@ createMacroSourceFile(std::unique_ptr buffer, /*parsingOpts=*/{}, /*isPrimary=*/false); if (auto parentSourceFile = dc->getParentSourceFile()) macroSourceFile->setImports(parentSourceFile->getImports()); - else if (isa(dc->getModuleScopeContext())) - macroSourceFile->setImports({}); + else if (auto clangModuleUnit = + dyn_cast(dc->getModuleScopeContext())) { + auto clangModule = clangModuleUnit->getParentModule(); + performImportResolutionForClangMacroBuffer(*macroSourceFile, clangModule); + } return macroSourceFile; } diff --git a/test/Inputs/clang-importer-sdk/usr/include/completion_handler_globals.h b/test/Inputs/clang-importer-sdk/usr/include/completion_handler_globals.h index 7bf2963829fb6..e7e11c0986125 100644 --- a/test/Inputs/clang-importer-sdk/usr/include/completion_handler_globals.h +++ b/test/Inputs/clang-importer-sdk/usr/include/completion_handler_globals.h @@ -1,15 +1,17 @@ #if __SWIFT_ATTR_SUPPORTS_MACROS #define ADD_ASYNC __attribute__((swift_attr("@macro_library.AddAsync"))) +#define ADD_ASYNC_FINAL __attribute__((swift_attr("@macro_library.AddAsyncFinal"))) #else #define ADD_ASYNC +#define ADD_ASYNC_FINAL #endif -void async_divide(double x, double y, void (* _Nonnull completionHandler)(double x)) ADD_ASYNC; +void async_divide(double x, double y, void (^ _Nonnull completionHandler)(double x)) ADD_ASYNC; typedef struct SlowComputer { } SlowComputer; -void computer_divide(const SlowComputer *computer, double x, double y, void (* _Nonnull completionHandler)(double x)) +void computer_divide(const SlowComputer *computer, double x, double y, void (^ _Nonnull completionHandler)(double x)) ADD_ASYNC __attribute__((swift_name("SlowComputer.divide(self:_:_:completionHandler:)"))); @@ -19,7 +21,7 @@ void computer_divide(const SlowComputer *computer, double x, double y, void (* _ @interface Computer: NSObject -(void)multiply:(double)x by:(double)y afterDone:(void (^ _Nonnull)(double x))afterDone - ADD_ASYNC + ADD_ASYNC_FINAL __attribute__((swift_async(none))); @end #endif diff --git a/test/Macros/Inputs/macro_library.swift b/test/Macros/Inputs/macro_library.swift index 16373058cccb9..e448634a12338 100644 --- a/test/Macros/Inputs/macro_library.swift +++ b/test/Macros/Inputs/macro_library.swift @@ -56,3 +56,6 @@ public macro declareVarValuePeerShadowed() = #externalMacro(module: "MacroDefini @attached(peer, names: overloaded) public macro AddAsync() = #externalMacro(module: "MacroDefinition", type: "AddAsyncMacro") + +@attached(peer, names: overloaded) +public macro AddAsyncFinal() = #externalMacro(module: "MacroDefinition", type: "AddAsyncMacro") diff --git a/test/Macros/Inputs/syntax_macro_definitions.swift b/test/Macros/Inputs/syntax_macro_definitions.swift index 387298da85f7e..4ef96faf68b3d 100644 --- a/test/Macros/Inputs/syntax_macro_definitions.swift +++ b/test/Macros/Inputs/syntax_macro_definitions.swift @@ -935,7 +935,6 @@ public struct AddAsyncMacro: PeerMacro { providingPeersOf declaration: Declaration, in context: Context ) throws -> [DeclSyntax] { - // Only on functions at the moment. guard var funcDecl = declaration.as(FunctionDeclSyntax.self) else { throw CustomError.message("@addAsync only works on functions") @@ -1084,6 +1083,37 @@ public struct AddAsyncMacro: PeerMacro { funcDecl.attributes = newAttributeList + // If this declaration needs to be final, make it so. + let isFinal = node.attributeName.trimmedDescription.contains("AddAsyncFinal") + if isFinal { + var allModifiers = Array(funcDecl.modifiers) + if let openIndex = allModifiers.firstIndex(where: { $0.name.text == "open" }) { + allModifiers[openIndex].name = .keyword(.public) + } else { + allModifiers.append( + DeclModifierSyntax( + name: .keyword(.public), + trailingTrivia: .space + ) + ) + } + + allModifiers.append( + DeclModifierSyntax( + name: .keyword(.final), + trailingTrivia: .space + ) + ) + + funcDecl.modifiers = DeclModifierListSyntax(allModifiers) + + var allAttributes = Array(funcDecl.attributes) + allAttributes.append( + .attribute("@_alwaysEmitIntoClient ") + ) + funcDecl.attributes = AttributeListSyntax(allAttributes) + } + funcDecl.leadingTrivia = .newlines(2) return [DeclSyntax(funcDecl)] diff --git a/test/Macros/expand_on_imported.swift b/test/Macros/expand_on_imported.swift index c7efe0ed9e340..8dd3384fa937a 100644 --- a/test/Macros/expand_on_imported.swift +++ b/test/Macros/expand_on_imported.swift @@ -10,20 +10,17 @@ // Diagnostics testing // RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -typecheck -verify -swift-version 5 -enable-experimental-feature MacrosOnImports -load-plugin-library %t/%target-library-name(MacroDefinition) -module-name ModuleUser %s -I %t +// Emit IR to ensure that we are handling the created body end-to-end. +// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -emit-ir -swift-version 5 -g -enable-experimental-feature MacrosOnImports -load-plugin-library %t/%target-library-name(MacroDefinition) -module-name ModuleUser %s -I %t -validate-tbd-against-ir=none | %FileCheck %s + import CompletionHandlerGlobals import macro_library -// Make sure that @AddAsync works at all. -@AddAsync -@available(SwiftStdlib 5.1, *) -func asyncTest(_ value: Int, completionHandler: @escaping (String) -> Void) { - completionHandler(String(value)) -} - @available(SwiftStdlib 5.1, *) func testAll(x: Double, y: Double, computer: SlowComputer) async { - _ = await asyncTest(17) - let _: Double = await async_divide(1.0, 2.0) let _: Double = await computer.divide(x, y) } + +// CHECK: define{{.*}}@"$sSC12async_divideyS2d_SdtYaF" +// CHECK: define{{.*}}@"$sSo12SlowComputerV6divideyS2d_SdtYaF" diff --git a/test/Macros/expand_on_imported_objc.swift b/test/Macros/expand_on_imported_objc.swift index b0d22c6354f11..d4a9258c40cdd 100644 --- a/test/Macros/expand_on_imported_objc.swift +++ b/test/Macros/expand_on_imported_objc.swift @@ -1,5 +1,6 @@ // REQUIRES: swift_swift_parser, executable_test, objc_interop, concurrency // REQUIRES: swift_feature_MacrosOnImports +// REQUIRES: OS=macosx // RUN: %empty-directory(%t) // RUN: %host-build-swift -swift-version 5 -emit-library -o %t/%target-library-name(MacroDefinition) -module-name=MacroDefinition %S/Inputs/syntax_macro_definitions.swift -g -no-toolchain-stdlib-rpath -swift-version 5 @@ -8,7 +9,10 @@ // RUN: %target-swift-frontend -swift-version 5 -emit-module -o %t/macro_library.swiftmodule %S/Inputs/macro_library.swift -module-name macro_library -load-plugin-library %t/%target-library-name(MacroDefinition) // Diagnostics testing -// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -typecheck -verify -swift-version 5 -enable-experimental-feature MacrosOnImports -load-plugin-library %t/%target-library-name(MacroDefinition) -module-name ModuleUser %s -I %t +// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -typecheck -verify -swift-version 5 -enable-experimental-feature MacrosOnImports -load-plugin-library %t/%target-library-name(MacroDefinition) -module-name ModuleUser %s -I %t -DTEST_DIAGNOSTICS + +// Emit IR just to make sure nothing else fails. +// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -emit-ir -swift-version 5 -g -enable-experimental-feature MacrosOnImports -load-plugin-library %t/%target-library-name(MacroDefinition) -module-name ModuleUser %s -I %t | %FileCheck %s import CompletionHandlerGlobals import macro_library @@ -17,6 +21,10 @@ import macro_library func testAll(x: Double, y: Double, computer: Computer, untypedComputer: AnyObject) async { let _: Double = await computer.multiply(x, by: y) + #if TEST_DIAGNOSTICS // expected-error@+1{{missing argument for parameter 'afterDone' in call}} untypedComputer.multiply(x, by: y) + #endif } + +// CHECK: define linkonce_odr hidden swifttailcc void @"$sSo8ComputerC8multiply_2byS2d_SdtYaF" diff --git a/test/Macros/print_clang_expand_on_imported.swift b/test/Macros/print_clang_expand_on_imported.swift index c69c1f9e1f2c6..869eefb9c8ea1 100644 --- a/test/Macros/print_clang_expand_on_imported.swift +++ b/test/Macros/print_clang_expand_on_imported.swift @@ -7,14 +7,19 @@ // Build the macro library to give us access to AddAsync. // RUN: %target-swift-frontend -swift-version 5 -emit-module -o %t/macro_library.swiftmodule %S/Inputs/macro_library.swift -module-name macro_library -load-plugin-library %t/%target-library-name(MacroDefinition) -// RUN: %target-swift-ide-test(mock-sdk: %clang-importer-sdk) -print-module -print-implicit-attrs -source-filename %s -module-to-print=CompletionHandlerGlobals -I %t -function-definitions=false -load-plugin-library %t/%target-library-name(MacroDefinition) -import-module macro_library -enable-experimental-feature MacrosOnImports > %t/imported.printed.txt +// RUN: %target-swift-ide-test(mock-sdk: %clang-importer-sdk) -typecheck -print-module -print-implicit-attrs -source-filename %s -module-to-print=CompletionHandlerGlobals -I %t -function-definitions=false -load-plugin-library %t/%target-library-name(MacroDefinition) -import-module macro_library -enable-experimental-feature MacrosOnImports > %t/imported.printed.txt 2> %t/stderr.log // RUN: %FileCheck -input-file %t/imported.printed.txt %s +// RUN: echo "" >> %t/stderr.log +// RUN: %FileCheck -check-prefix DIAGS -input-file %t/stderr.log %s import CompletionHandlerGlobals -// CHECK: func async_divide(_ x: Double, _ y: Double, _ completionHandler: @convention(c) (Double) -> Void) +// CHECK: func async_divide(_ x: Double, _ y: Double, _ completionHandler: @escaping (Double) -> Void) // CHECK: extension SlowComputer // CHECK: public func divide(_ x: Double, _ y: Double) async -> Double // CHECK: func async_divide(_ x: Double, _ y: Double) async -> Double + + +// DIAGS-NOT: error diff --git a/test/Macros/print_clang_expand_on_imported_objc.swift b/test/Macros/print_clang_expand_on_imported_objc.swift index da64be37f8b32..bb49bd756841c 100644 --- a/test/Macros/print_clang_expand_on_imported_objc.swift +++ b/test/Macros/print_clang_expand_on_imported_objc.swift @@ -13,5 +13,4 @@ import CompletionHandlerGlobals // CHECK: class Computer -// FIXME: The "open" is odd here. We want this to be "final", but can't yet. -// CHECK: open func multiply(_ x: Double, by y: Double) async -> Double +// CHECK: @_alwaysEmitIntoClient public final func multiply(_ x: Double, by y: Double) async -> Double diff --git a/tools/SourceKit/lib/SwiftLang/SwiftEditor.cpp b/tools/SourceKit/lib/SwiftLang/SwiftEditor.cpp index 74a3598903a78..4795328274cbe 100644 --- a/tools/SourceKit/lib/SwiftLang/SwiftEditor.cpp +++ b/tools/SourceKit/lib/SwiftLang/SwiftEditor.cpp @@ -972,6 +972,7 @@ class SemanticAnnotator : public SourceEntityWalker { case GeneratedSourceInfo::DefaultArgument: case GeneratedSourceInfo::ReplacedFunctionBody: case GeneratedSourceInfo::PrettyPrinted: + case GeneratedSourceInfo::Attribute: break; } }