Skip to content

Commit f802b67

Browse files
authored
Merge pull request #77580 from DougGregor/swift-attr-parsing-fixes
Ensure that buffers containing Clang swift_attr attributes are parsed as attributes
2 parents 6aa9d43 + 75aae22 commit f802b67

34 files changed

+238
-71
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/Basic/BasicBridging.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -445,6 +445,7 @@ enum ENUM_EXTENSIBILITY_ATTR(closed) BridgedGeneratedSourceFileKind {
445445
BridgedGeneratedSourceFileKindReplacedFunctionBody,
446446
BridgedGeneratedSourceFileKindPrettyPrinted,
447447
BridgedGeneratedSourceFileKindDefaultArgument,
448+
BridgedGeneratedSourceFileKindAttribute,
448449

449450
BridgedGeneratedSourceFileKindNone,
450451
};

include/swift/Basic/SourceManager.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,9 @@ class GeneratedSourceInfo {
6565

6666
/// The expansion of default argument at caller side
6767
DefaultArgument,
68+
69+
/// A Swift attribute expressed in C headers.
70+
Attribute,
6871
} kind;
6972

7073
static StringRef kindToString(GeneratedSourceInfo::Kind kind) {
@@ -80,6 +83,8 @@ class GeneratedSourceInfo {
8083
return "PrettyPrinted";
8184
case DefaultArgument:
8285
return "DefaultArgument";
86+
case Attribute:
87+
return "Attribute";
8388
}
8489
llvm_unreachable("Invalid kind");
8590
}

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/ASTMangler.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4535,6 +4535,7 @@ void ASTMangler::appendMacroExpansionContext(
45354535
case GeneratedSourceInfo::PrettyPrinted:
45364536
case GeneratedSourceInfo::ReplacedFunctionBody:
45374537
case GeneratedSourceInfo::DefaultArgument:
4538+
case GeneratedSourceInfo::Attribute:
45384539
return appendMacroExpansionLoc();
45394540
}
45404541

@@ -4586,6 +4587,7 @@ void ASTMangler::appendMacroExpansionContext(
45864587
case GeneratedSourceInfo::PrettyPrinted:
45874588
case GeneratedSourceInfo::ReplacedFunctionBody:
45884589
case GeneratedSourceInfo::DefaultArgument:
4590+
case GeneratedSourceInfo::Attribute:
45894591
llvm_unreachable("Exited above");
45904592
}
45914593

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/Decl.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12075,6 +12075,7 @@ MacroDiscriminatorContext MacroDiscriminatorContext::getParentOf(
1207512075
case GeneratedSourceInfo::PrettyPrinted:
1207612076
case GeneratedSourceInfo::ReplacedFunctionBody:
1207712077
case GeneratedSourceInfo::DefaultArgument:
12078+
case GeneratedSourceInfo::Attribute:
1207812079
return origDC;
1207912080
}
1208012081
}

lib/AST/DiagnosticEngine.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1336,6 +1336,7 @@ DiagnosticEngine::diagnosticInfoForDiagnostic(const Diagnostic &diagnostic) {
13361336
#include "swift/Basic/MacroRoles.def"
13371337
case GeneratedSourceInfo::PrettyPrinted:
13381338
case GeneratedSourceInfo::DefaultArgument:
1339+
case GeneratedSourceInfo::Attribute:
13391340
fixIts = {};
13401341
break;
13411342
case GeneratedSourceInfo::ReplacedFunctionBody:
@@ -1381,6 +1382,7 @@ getGeneratedSourceInfoMacroName(const GeneratedSourceInfo &info) {
13811382
case GeneratedSourceInfo::PrettyPrinted:
13821383
case GeneratedSourceInfo::ReplacedFunctionBody:
13831384
case GeneratedSourceInfo::DefaultArgument:
1385+
case GeneratedSourceInfo::Attribute:
13841386
return DeclName();
13851387
}
13861388
}
@@ -1442,6 +1444,7 @@ DiagnosticEngine::getGeneratedSourceBufferNotes(SourceLoc loc) {
14421444

14431445
case GeneratedSourceInfo::DefaultArgument:
14441446
case GeneratedSourceInfo::ReplacedFunctionBody:
1447+
case GeneratedSourceInfo::Attribute:
14451448
return childNotes;
14461449
}
14471450

lib/AST/Expr.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1633,9 +1633,12 @@ Expr *DefaultArgumentExpr::getCallerSideDefaultExpr() const {
16331633
assert(isCallerSide());
16341634
auto &ctx = DefaultArgsOwner.getDecl()->getASTContext();
16351635
auto *mutableThis = const_cast<DefaultArgumentExpr *>(this);
1636-
return evaluateOrDefault(ctx.evaluator,
1636+
if (auto result = evaluateOrDefault(ctx.evaluator,
16371637
CallerSideDefaultArgExprRequest{mutableThis},
1638-
new (ctx) ErrorExpr(getSourceRange(), getType()));
1638+
nullptr))
1639+
return result;
1640+
1641+
return new (ctx) ErrorExpr(getSourceRange(), getType());
16391642
}
16401643

16411644
ActorIsolation

lib/AST/Module.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -862,6 +862,7 @@ ModuleDecl::getOriginalLocation(SourceLoc loc) const {
862862
// replaced function bodies. The body is actually different code to the
863863
// original file.
864864
case GeneratedSourceInfo::PrettyPrinted:
865+
case GeneratedSourceInfo::Attribute:
865866
// No original location, return the original buffer/location
866867
return {startBufferID, startLoc};
867868
}
@@ -1148,6 +1149,7 @@ std::optional<MacroRole> SourceFile::getFulfilledMacroRole() const {
11481149
case GeneratedSourceInfo::ReplacedFunctionBody:
11491150
case GeneratedSourceInfo::PrettyPrinted:
11501151
case GeneratedSourceInfo::DefaultArgument:
1152+
case GeneratedSourceInfo::Attribute:
11511153
return std::nullopt;
11521154
}
11531155
}

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/ASTGen/Sources/ASTGen/SourceFile.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,8 @@ public func parseSourceFile(
140140
case .accessorMacroExpansion:
141141
// FIXME: Implement specialized parsing.
142142
parsed = Syntax(SourceFileSyntax.parse(from: &parser))
143-
case .memberAttributeMacroExpansion:
143+
case .memberAttributeMacroExpansion,
144+
.attribute:
144145
// FIXME: Implement specialized parsing.
145146
parsed = Syntax(SourceFileSyntax.parse(from: &parser))
146147
case .bodyMacroExpansion:

lib/Basic/SourceLoc.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -303,10 +303,11 @@ StringRef SourceManager::getIdentifierForBuffer(
303303
if (ForceGeneratedSourceToDisk) {
304304
if (const GeneratedSourceInfo *generatedInfo =
305305
getGeneratedSourceInfo(bufferID)) {
306-
// We only care about macros, so skip everything else.
306+
// We only care about macro expansion buffers, so skip everything else.
307307
if (generatedInfo->kind == GeneratedSourceInfo::ReplacedFunctionBody ||
308308
generatedInfo->kind == GeneratedSourceInfo::PrettyPrinted ||
309-
generatedInfo->kind == GeneratedSourceInfo::DefaultArgument)
309+
generatedInfo->kind == GeneratedSourceInfo::DefaultArgument ||
310+
generatedInfo->kind == GeneratedSourceInfo::Attribute)
310311
return buffer->getBufferIdentifier();
311312

312313
if (generatedInfo->onDiskBufferCopyFileName.empty()) {
@@ -400,6 +401,7 @@ void SourceManager::setGeneratedSourceInfo(
400401
#include "swift/Basic/MacroRoles.def"
401402
case GeneratedSourceInfo::PrettyPrinted:
402403
case GeneratedSourceInfo::DefaultArgument:
404+
case GeneratedSourceInfo::Attribute:
403405
break;
404406

405407
case GeneratedSourceInfo::ReplacedFunctionBody:

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/ClangImporter/ImportDecl.cpp

Lines changed: 29 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -8194,29 +8194,38 @@ bool importer::hasSameUnderlyingType(const clang::Type *a,
81948194
return a == b->getTypeForDecl();
81958195
}
81968196

8197-
unsigned ClangImporter::Implementation::getClangSwiftAttrSourceBuffer(
8198-
StringRef attributeText) {
8199-
auto known = ClangSwiftAttrSourceBuffers.find(attributeText);
8200-
if (known != ClangSwiftAttrSourceBuffers.end())
8201-
return known->second;
8197+
SourceFile &ClangImporter::Implementation::getClangSwiftAttrSourceFile(
8198+
ModuleDecl &module,
8199+
StringRef attributeText
8200+
) {
8201+
auto &sourceFiles = ClangSwiftAttrSourceFiles[attributeText];
8202+
8203+
// Check whether we've already created a source file.
8204+
for (auto sourceFile : sourceFiles) {
8205+
if (sourceFile->getParentModule() == &module)
8206+
return *sourceFile;
8207+
}
82028208

8203-
// Create a new buffer with a copy of the attribute text, so we don't need to
8204-
// rely on Clang keeping it around.
8209+
// Create a new buffer with a copy of the attribute text,
8210+
// so we don't need to rely on Clang keeping it around.
82058211
auto &sourceMgr = SwiftContext.SourceMgr;
82068212
auto bufferID = sourceMgr.addMemBufferCopy(attributeText);
8207-
ClangSwiftAttrSourceBuffers.insert({attributeText, bufferID});
8208-
return bufferID;
8209-
}
82108213

8211-
SourceFile &ClangImporter::Implementation::getClangSwiftAttrSourceFile(
8212-
ModuleDecl &module, unsigned bufferID) {
8213-
auto known = ClangSwiftAttrSourceFiles.find(&module);
8214-
if (known != ClangSwiftAttrSourceFiles.end())
8215-
return *known->second;
8214+
// Note that this is for an attribute.
8215+
sourceMgr.setGeneratedSourceInfo(
8216+
bufferID,
8217+
{
8218+
GeneratedSourceInfo::Attribute,
8219+
CharSourceRange(),
8220+
sourceMgr.getRangeForBuffer(bufferID),
8221+
&module
8222+
}
8223+
);
82168224

8225+
// Create the source file.
82178226
auto sourceFile = new (SwiftContext)
82188227
SourceFile(module, SourceFileKind::Library, bufferID);
8219-
ClangSwiftAttrSourceFiles.insert({&module, sourceFile});
8228+
sourceFiles.push_back(sourceFile);
82208229

82218230
return *sourceFile;
82228231
}
@@ -8392,17 +8401,15 @@ ClangImporter::Implementation::importSwiftAttrAttributes(Decl *MappedDecl) {
83928401
continue;
83938402
}
83948403

8395-
// Dig out a buffer with the attribute text.
8396-
unsigned bufferID = getClangSwiftAttrSourceBuffer(
8397-
swiftAttr->getAttribute());
8398-
83998404
// Dig out a source file we can use for parsing.
84008405
auto &sourceFile = getClangSwiftAttrSourceFile(
8401-
*MappedDecl->getDeclContext()->getParentModule(), bufferID);
8406+
*MappedDecl->getDeclContext()->getParentModule(),
8407+
swiftAttr->getAttribute());
84028408

84038409
// Spin up a parser.
84048410
swift::Parser parser(
8405-
bufferID, sourceFile, &SwiftContext.Diags, nullptr, nullptr);
8411+
sourceFile.getBufferID(), sourceFile, &SwiftContext.Diags,
8412+
nullptr, nullptr);
84068413
// Prime the lexer.
84078414
parser.consumeTokenWithoutFeedingReceiver();
84088415

lib/ClangImporter/ImporterImpl.h

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -538,14 +538,11 @@ class LLVM_LIBRARY_VISIBILITY ClangImporter::Implementation
538538
/// Clang arguments used to create the Clang invocation.
539539
std::vector<std::string> ClangArgs;
540540

541-
/// Mapping from Clang swift_attr attribute text to the Swift source buffer
542-
/// IDs that contain that attribute text. These are re-used when parsing the
543-
/// Swift attributes on import.
544-
llvm::StringMap<unsigned> ClangSwiftAttrSourceBuffers;
545-
546-
/// Mapping from modules in which a Clang swift_attr attribute occurs, to be
547-
/// used when parsing the attribute text.
548-
llvm::SmallDenseMap<ModuleDecl *, SourceFile *> ClangSwiftAttrSourceFiles;
541+
/// Mapping from Clang swift_attr attribute text to the Swift source file(s)
542+
/// that contain that attribute text.
543+
///
544+
/// These are re-used when parsing the Swift attributes on import.
545+
llvm::StringMap<llvm::TinyPtrVector<SourceFile *>> ClangSwiftAttrSourceFiles;
549546

550547
public:
551548
/// The Swift lookup table for the bridging header.
@@ -1058,13 +1055,9 @@ class LLVM_LIBRARY_VISIBILITY ClangImporter::Implementation
10581055
/// Map a Clang identifier name to its imported Swift equivalent.
10591056
StringRef getSwiftNameFromClangName(StringRef name);
10601057

1061-
/// Retrieve the Swift source buffer ID that corresponds to the given
1062-
/// swift_attr attribute text, creating one if necessary.
1063-
unsigned getClangSwiftAttrSourceBuffer(StringRef attributeText);
1064-
10651058
/// Retrieve the placeholder source file for use in parsing Swift attributes
10661059
/// in the given module.
1067-
SourceFile &getClangSwiftAttrSourceFile(ModuleDecl &module, unsigned bufferID);
1060+
SourceFile &getClangSwiftAttrSourceFile(ModuleDecl &module, StringRef attributeText);
10681061

10691062
/// Utility function to import Clang attributes from a source Swift decl to
10701063
/// synthesized Swift decl.

lib/IDE/Utils.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -661,6 +661,7 @@ adjustMacroExpansionWhitespace(GeneratedSourceInfo::Kind kind,
661661
case GeneratedSourceInfo::ReplacedFunctionBody:
662662
case GeneratedSourceInfo::PrettyPrinted:
663663
case GeneratedSourceInfo::DefaultArgument:
664+
case GeneratedSourceInfo::Attribute:
664665
return expandedCode;
665666
}
666667
}

0 commit comments

Comments
 (0)