Skip to content

Commit 2ec619c

Browse files
committed
[AST] Add a few parsing flags to SourceFile
Add flags for whether delayed body parsing or #if condition evaluation is disabled, as well as whether warnings should be suppressed. Then pass down these flags from the frontend. This is in preparation for the requestification of source file parsing where the SourceFile will need to be able to parse itself on demand.
1 parent a9870ac commit 2ec619c

File tree

5 files changed

+73
-13
lines changed

5 files changed

+73
-13
lines changed

include/swift/AST/SourceFile.h

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,36 @@ class SourceFile final : public FileUnit {
9090
}
9191
};
9292

93+
/// Flags that direct how the source file is parsed.
94+
enum class ParsingFlags : uint8_t {
95+
/// Whether to disable delayed parsing for nominal type, extension, and
96+
/// function bodies.
97+
///
98+
/// If set, type and function bodies will be parsed eagerly. Otherwise they
99+
/// will be lazily parsed when their contents is queried. This lets us avoid
100+
/// building AST nodes when they're not needed.
101+
///
102+
/// This is set for primary files, since we want to type check all
103+
/// declarations and function bodies anyway, so there's no benefit in lazy
104+
/// parsing.
105+
DisableDelayedBodies = 1 << 0,
106+
107+
/// Whether to disable evaluating the conditions of #if decls.
108+
///
109+
/// If set, #if decls are parsed as-is. Otherwise, the bodies of any active
110+
/// clauses are hoisted such that they become sibling nodes with the #if
111+
/// decl.
112+
///
113+
/// FIXME: When condition evaluation moves to a later phase, remove this
114+
/// and adjust the client call 'performParseOnly'.
115+
DisablePoundIfEvaluation = 1 << 1,
116+
117+
/// Whether to suppress warnings when parsing. This is set for secondary
118+
/// files, as they get parsed multiple times.
119+
SuppressWarnings = 1 << 2
120+
};
121+
using ParsingOptions = OptionSet<ParsingFlags>;
122+
93123
private:
94124
std::unique_ptr<SourceLookupCache> Cache;
95125
SourceLookupCache &getCache() const;
@@ -132,6 +162,9 @@ class SourceFile final : public FileUnit {
132162
/// If not, we can fast-path module checks.
133163
bool HasImplementationOnlyImports = false;
134164

165+
/// The parsing options for the file.
166+
ParsingOptions ParsingOpts;
167+
135168
/// The scope map that describes this source file.
136169
std::unique_ptr<ASTScope> Scope;
137170

@@ -196,6 +229,9 @@ class SourceFile final : public FileUnit {
196229
Decls.resize(count);
197230
}
198231

232+
/// Retrieve the parsing options for the file.
233+
ParsingOptions getParsingOptions() const { return ParsingOpts; }
234+
199235
/// A cache of syntax nodes that can be reused when creating the syntax tree
200236
/// for this file.
201237
swift::SyntaxParsingCache *SyntaxParsingCache = nullptr;
@@ -270,7 +306,7 @@ class SourceFile final : public FileUnit {
270306

271307
SourceFile(ModuleDecl &M, SourceFileKind K, Optional<unsigned> bufferID,
272308
ImplicitModuleImportKind ModImpKind, bool KeepParsedTokens = false,
273-
bool KeepSyntaxTree = false);
309+
bool KeepSyntaxTree = false, ParsingOptions parsingOpts = {});
274310

275311
~SourceFile();
276312

@@ -556,6 +592,11 @@ class SourceFile final : public FileUnit {
556592
std::unique_ptr<SourceFileSyntaxInfo> SyntaxInfo;
557593
};
558594

595+
inline SourceFile::ParsingOptions operator|(SourceFile::ParsingFlags lhs,
596+
SourceFile::ParsingFlags rhs) {
597+
return SourceFile::ParsingOptions(lhs) | rhs;
598+
}
599+
559600
inline SourceFile &
560601
ModuleDecl::getMainSourceFile(SourceFileKind expectedKind) const {
561602
assert(!Files.empty() && "No files added yet");

include/swift/Frontend/Frontend.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -632,7 +632,8 @@ class CompilerInstance {
632632
SourceFile *
633633
createSourceFileForMainModule(SourceFileKind FileKind,
634634
SourceFile::ImplicitModuleImportKind ImportKind,
635-
Optional<unsigned> BufferID);
635+
Optional<unsigned> BufferID,
636+
SourceFile::ParsingOptions options = {});
636637

637638
public:
638639
void freeASTContext();

lib/AST/Module.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1896,10 +1896,11 @@ static void performAutoImport(
18961896
SourceFile::SourceFile(ModuleDecl &M, SourceFileKind K,
18971897
Optional<unsigned> bufferID,
18981898
ImplicitModuleImportKind ModImpKind,
1899-
bool KeepParsedTokens, bool BuildSyntaxTree)
1900-
: FileUnit(FileUnitKind::Source, M),
1901-
BufferID(bufferID ? *bufferID : -1),
1902-
Kind(K), SyntaxInfo(new SourceFileSyntaxInfo(BuildSyntaxTree)) {
1899+
bool KeepParsedTokens, bool BuildSyntaxTree,
1900+
ParsingOptions parsingOpts)
1901+
: FileUnit(FileUnitKind::Source, M), BufferID(bufferID ? *bufferID : -1),
1902+
ParsingOpts(parsingOpts), Kind(K),
1903+
SyntaxInfo(new SourceFileSyntaxInfo(BuildSyntaxTree)) {
19031904
M.getASTContext().addDestructorCleanup(*this);
19041905
performAutoImport(*this, ModImpKind);
19051906

lib/Frontend/Frontend.cpp

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1081,17 +1081,27 @@ void CompilerInstance::finishTypeChecking() {
10811081

10821082
SourceFile *CompilerInstance::createSourceFileForMainModule(
10831083
SourceFileKind fileKind, SourceFile::ImplicitModuleImportKind importKind,
1084-
Optional<unsigned> bufferID) {
1084+
Optional<unsigned> bufferID, SourceFile::ParsingOptions opts) {
10851085
ModuleDecl *mainModule = getMainModule();
1086+
1087+
auto isPrimary = bufferID && isPrimaryInput(*bufferID);
1088+
if (isPrimary || isWholeModuleCompilation()) {
1089+
// Disable delayed body parsing for primaries.
1090+
opts |= SourceFile::ParsingFlags::DisableDelayedBodies;
1091+
} else {
1092+
// Suppress parse warnings for non-primaries, as they'll get parsed multiple
1093+
// times.
1094+
opts |= SourceFile::ParsingFlags::SuppressWarnings;
1095+
}
1096+
10861097
SourceFile *inputFile = new (*Context)
10871098
SourceFile(*mainModule, fileKind, bufferID, importKind,
10881099
Invocation.getLangOptions().CollectParsedToken,
1089-
Invocation.getLangOptions().BuildSyntaxTree);
1100+
Invocation.getLangOptions().BuildSyntaxTree, opts);
10901101
MainModule->addFile(*inputFile);
10911102

1092-
if (bufferID && isPrimaryInput(*bufferID)) {
1103+
if (isPrimary)
10931104
recordPrimarySourceFile(inputFile);
1094-
}
10951105

10961106
if (bufferID == SourceMgr.getCodeCompletionBufferID()) {
10971107
assert(!CodeCompletionFile && "Multiple code completion files?");
@@ -1113,14 +1123,20 @@ void CompilerInstance::performParseOnly(bool EvaluateConditionals,
11131123
"only supports parsing .swift files");
11141124
(void)Kind;
11151125

1126+
SourceFile::ParsingOptions parsingOpts;
1127+
if (!EvaluateConditionals)
1128+
parsingOpts |= SourceFile::ParsingFlags::DisablePoundIfEvaluation;
1129+
if (!CanDelayBodies)
1130+
parsingOpts |= SourceFile::ParsingFlags::DisableDelayedBodies;
1131+
11161132
// Make sure the main file is the first file in the module but parse it last,
11171133
// to match the parsing logic used when performing Sema.
11181134
if (MainBufferID != NO_SUCH_BUFFER) {
11191135
assert(Kind == InputFileKind::Swift ||
11201136
Kind == InputFileKind::SwiftModuleInterface);
11211137
createSourceFileForMainModule(Invocation.getSourceFileKind(),
11221138
SourceFile::ImplicitModuleImportKind::None,
1123-
MainBufferID);
1139+
MainBufferID, parsingOpts);
11241140
}
11251141

11261142
auto shouldDelayBodies = [&](unsigned bufferID) -> bool {
@@ -1138,7 +1154,7 @@ void CompilerInstance::performParseOnly(bool EvaluateConditionals,
11381154

11391155
SourceFile *NextInput = createSourceFileForMainModule(
11401156
SourceFileKind::Library, SourceFile::ImplicitModuleImportKind::None,
1141-
BufferID);
1157+
BufferID, parsingOpts);
11421158

11431159
parseIntoSourceFile(*NextInput, BufferID, shouldDelayBodies(BufferID),
11441160
EvaluateConditionals);

lib/Parse/Parser.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1174,7 +1174,8 @@ struct ParserUnit::Implementation {
11741174
SF(new (Ctx) SourceFile(
11751175
*ModuleDecl::create(Ctx.getIdentifier(ModuleName), Ctx), SFKind,
11761176
BufferID, SourceFile::ImplicitModuleImportKind::None,
1177-
Opts.CollectParsedToken, Opts.BuildSyntaxTree)) {}
1177+
Opts.CollectParsedToken, Opts.BuildSyntaxTree,
1178+
SourceFile::ParsingFlags::DisableDelayedBodies)) {}
11781179

11791180
~Implementation() {
11801181
// We need to delete the parser before the context so that it can finalize

0 commit comments

Comments
 (0)