Skip to content

Commit 11ed132

Browse files
committed
[Clang importer + macros] Handle name lookup and type checking for expanded macros
Introduce a number of fixes to allow us to fully use declarations that are produced by applying a peer macro to an imported declarations. These changes include: * Ensuring that we have the right set of imports in the source file containing the macro expansion, because it depends only on the module it comes from * Ensuring that name lookup looks in that file even when the DeclContext hierarchy doesn't contain the source file (because it's based on the Clang module structure) Expand testing to be sure that we're getting the right calls, diagnostics, and generated IR symbols.
1 parent 1769ae9 commit 11ed132

19 files changed

+159
-27
lines changed

include/swift/AST/ASTScope.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -808,6 +808,8 @@ class AbstractFunctionDeclScope final : public ASTScopeImpl {
808808
protected:
809809
void printSpecifics(llvm::raw_ostream &out) const override;
810810

811+
bool lookupLocalsOrMembers(DeclConsumer) const override;
812+
811813
public:
812814
Decl *getDecl() const { return decl; }
813815

include/swift/AST/NameLookup.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -528,6 +528,15 @@ void lookupVisibleMemberDecls(VisibleDeclConsumer &Consumer,
528528
bool includeProtocolExtensionMembers,
529529
GenericSignature genericSig = GenericSignature());
530530

531+
/// Determine the module-scope context from which lookup should proceed.
532+
///
533+
/// In the common case, module-scope context is the source file in which
534+
/// the declaration context is nested. However, when declaration context is
535+
/// part of an imported Clang declaration context, it won't be nested within a
536+
/// source file. Rather, the source file will be on the side, and will be
537+
/// provided here because it contains information about the available imports.
538+
DeclContext *getModuleScopeLookupContext(DeclContext *dc);
539+
531540
namespace namelookup {
532541

533542
/// Add semantic members to \p type before attempting a semantic lookup.

include/swift/Subsystems.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,12 @@ namespace swift {
120120
/// This walks the AST to resolve imports.
121121
void performImportResolution(SourceFile &SF);
122122

123+
/// Resolve imports for a source file generated to adapt a given
124+
/// Clang module.
125+
void performImportResolutionForClangMacroBuffer(
126+
SourceFile &SF, ModuleDecl *clangModule
127+
);
128+
123129
/// Once type-checking is complete, this instruments code with calls to an
124130
/// intrinsic that record the expected values of local variables so they can
125131
/// be compared against the results from the debugger.

lib/AST/ASTScopeLookup.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include "swift/AST/Stmt.h"
3131
#include "swift/AST/TypeRepr.h"
3232
#include "swift/Basic/STLExtras.h"
33+
#include "swift/ClangImporter/ClangModule.h"
3334
#include "swift/Parse/Lexer.h"
3435
#include "llvm/Support/Compiler.h"
3536

@@ -264,6 +265,20 @@ bool ASTScopeImpl::lookupLocalsOrMembers(DeclConsumer) const {
264265
return false; // many kinds of scopes have none
265266
}
266267

268+
bool AbstractFunctionDeclScope::lookupLocalsOrMembers(DeclConsumer consumer) const {
269+
// Special case: if we're within a function inside a type context, but the
270+
// parent context is within a Clang module unit, we need to make sure to
271+
// look for members in it.
272+
auto dc = decl->getDeclContext();
273+
if (!dc->isTypeContext())
274+
return false;
275+
276+
if (!isa<ClangModuleUnit>(dc->getModuleScopeContext()))
277+
return false;
278+
279+
return consumer.lookInMembers(cast<GenericContext>(dc->getAsDecl()));
280+
}
281+
267282
bool GenericTypeOrExtensionScope::lookupLocalsOrMembers(
268283
ASTScopeImpl::DeclConsumer consumer) const {
269284
return portion->lookupMembersOf(this, consumer);

lib/AST/AvailabilityScope.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,10 @@ AvailabilityScope::createForSourceFile(SourceFile *SF,
5555
case SourceFileKind::DefaultArgument: {
5656
// Look up the parent context in the enclosing file that this file's
5757
// root context should be nested under.
58-
if (auto parentScope =
59-
SF->getEnclosingSourceFile()->getAvailabilityScope()) {
58+
auto enclosingSF = SF->getEnclosingSourceFile();
59+
if (!enclosingSF)
60+
break;
61+
if (auto parentScope = enclosingSF->getAvailabilityScope()) {
6062
auto charRange = Ctx.SourceMgr.getRangeForBuffer(SF->getBufferID());
6163
range = SourceRange(charRange.getStart(), charRange.getEnd());
6264
auto originalNode = SF->getNodeInEnclosingSourceFile();

lib/AST/NameLookup.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1698,7 +1698,7 @@ SmallVector<MacroDecl *, 1> namelookup::lookupMacros(DeclContext *dc,
16981698
DeclNameRef macroName,
16991699
MacroRoles roles) {
17001700
SmallVector<MacroDecl *, 1> choices;
1701-
auto moduleScopeDC = dc->getModuleScopeContext();
1701+
auto moduleScopeDC = getModuleScopeLookupContext(dc);
17021702
ASTContext &ctx = moduleScopeDC->getASTContext();
17031703

17041704
auto addChoiceIfApplicable = [&](ValueDecl *decl) {

lib/AST/UnqualifiedLookup.cpp

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include "swift/Basic/STLExtras.h"
3131
#include "swift/Basic/SourceManager.h"
3232
#include "swift/Basic/Statistic.h"
33+
#include "swift/ClangImporter/ClangModule.h"
3334
#include "swift/Parse/Lexer.h"
3435
#include "llvm/ADT/DenseMap.h"
3536
#include "llvm/ADT/TinyPtrVector.h"
@@ -265,7 +266,8 @@ void UnqualifiedLookupFactory::performUnqualifiedLookup() {
265266
if (!isFirstResultEnough()) {
266267
// If no result has been found yet, the dependency must be on a top-level
267268
// name, since up to now, the search has been for non-top-level names.
268-
auto *moduleScopeContext = DC->getModuleScopeContext();
269+
auto *moduleScopeContext = getModuleScopeLookupContext(DC);
270+
269271
lookUpTopLevelNamesInModuleScopeContext(moduleScopeContext);
270272
}
271273
}
@@ -939,3 +941,19 @@ ValueDecl *ASTScope::lookupSingleLocalDecl(SourceFile *sf, DeclName name,
939941
return nullptr;
940942
return result[0];
941943
}
944+
945+
DeclContext *swift::getModuleScopeLookupContext(DeclContext *dc) {
946+
auto moduleScopeContext = dc->getModuleScopeContext();
947+
948+
// When the module scope context is in a Clang module but we actually
949+
// have a parent source file, it's because we are within a macro
950+
// expansion triggered for the imported declaration. In such cases,
951+
// we want to use the parent source file as the lookup context, becauae
952+
// it has the appropriate resolved imports.
953+
if (isa<ClangModuleUnit>(moduleScopeContext)) {
954+
if (auto parentSF = dc->getParentSourceFile())
955+
return parentSF;
956+
}
957+
958+
return moduleScopeContext;
959+
}

lib/ClangImporter/ClangImporter.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2798,7 +2798,11 @@ ClangModuleUnit *ClangImporter::Implementation::getWrapperForModule(
27982798
Identifier name = underlying->Name == "std"
27992799
? SwiftContext.Id_CxxStdlib
28002800
: SwiftContext.getIdentifier(underlying->Name);
2801-
auto wrapper = ModuleDecl::create(name, SwiftContext);
2801+
ImplicitImportInfo implicitImportInfo;
2802+
if (auto mainModule = SwiftContext.MainModule) {
2803+
implicitImportInfo = mainModule->getImplicitImportInfo();
2804+
}
2805+
auto wrapper = ModuleDecl::create(name, SwiftContext, implicitImportInfo);
28022806
wrapper->setIsSystemModule(underlying->IsSystem);
28032807
wrapper->setIsNonSwiftModule();
28042808
wrapper->setHasResolvedImports();

lib/Parse/ParseRequests.cpp

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -114,11 +114,23 @@ ParseAbstractFunctionBodyRequest::evaluate(Evaluator &evaluator,
114114

115115
case BodyKind::Unparsed: {
116116
// FIXME: How do we configure code completion?
117-
SourceFile &sf = *afd->getDeclContext()->getParentSourceFile();
118-
SourceManager &sourceMgr = sf.getASTContext().SourceMgr;
117+
SourceManager &sourceMgr = afd->getASTContext().SourceMgr;
119118
unsigned bufferID =
120119
sourceMgr.findBufferContainingLoc(afd->getBodySourceRange().Start);
121-
Parser parser(bufferID, sf, /*SIL*/ nullptr);
120+
SourceFile *sf = afd->getDeclContext()->getParentSourceFile();
121+
if (!sf) {
122+
auto sourceFiles = sourceMgr.getSourceFilesForBufferID(bufferID);
123+
auto expectedModule = afd->getParentModule();
124+
for (auto checkSF: sourceFiles) {
125+
if (checkSF->getParentModule() == expectedModule) {
126+
sf = checkSF;
127+
break;
128+
}
129+
}
130+
assert(sf && "Could not find source file containing parsed body");
131+
}
132+
133+
Parser parser(bufferID, *sf, /*SIL*/ nullptr);
122134
auto result = parser.parseAbstractFunctionBodyDelayed(afd);
123135
afd->setBodyKind(BodyKind::Parsed);
124136
return result;

lib/Sema/ImportResolution.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,11 @@ class ImportResolver final : public DeclVisitor<ImportResolver> {
192192

193193
void addImplicitImports();
194194

195+
void addImplicitImport(ModuleDecl *module) {
196+
boundImports.push_back(ImportedModule(module));
197+
bindPendingImports();
198+
}
199+
195200
/// Retrieve the finalized imports.
196201
ArrayRef<AttributedImport<ImportedModule>> getFinishedImports() const {
197202
return boundImports;
@@ -301,6 +306,22 @@ void swift::performImportResolution(SourceFile &SF) {
301306
verify(SF);
302307
}
303308

309+
void swift::performImportResolutionForClangMacroBuffer(
310+
SourceFile &SF, ModuleDecl *clangModule
311+
) {
312+
// If we've already performed import resolution, bail.
313+
if (SF.ASTStage == SourceFile::ImportsResolved)
314+
return;
315+
316+
ImportResolver resolver(SF);
317+
resolver.addImplicitImport(clangModule);
318+
319+
SF.setImports(resolver.getFinishedImports());
320+
SF.setImportedUnderlyingModule(resolver.getUnderlyingClangModule());
321+
322+
SF.ASTStage = SourceFile::ImportsResolved;
323+
}
324+
304325
//===----------------------------------------------------------------------===//
305326
// MARK: Import handling generally
306327
//===----------------------------------------------------------------------===//

0 commit comments

Comments
 (0)