Skip to content

Commit 4ea157e

Browse files
committed
Frontend: Parse diagnostic options earlier.
Diagnostics may be emitted while parsing command line arguments. This implies that the options which affect how diagnostics are emitted and presented need to be parsed first.
1 parent 29bcd2c commit 4ea157e

File tree

4 files changed

+78
-45
lines changed

4 files changed

+78
-45
lines changed

include/swift/Frontend/Frontend.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,12 +116,17 @@ class CompilerInvocation {
116116
public:
117117
CompilerInvocation();
118118

119-
/// Initializes the compiler invocation for the list of arguments.
119+
/// Initializes the compiler invocation and diagnostic engine for the list of
120+
/// arguments.
120121
///
121122
/// All parsing should be additive, i.e. options should not be reset to their
122123
/// default values given the /absence/ of a flag. This is because \c parseArgs
123124
/// may be used to modify an already partially configured invocation.
124125
///
126+
/// As a side-effect of parsing, the diagnostic engine will be configured with
127+
/// the options specified by the parsed arguments. This ensures that the
128+
/// arguments can effect the behavior of diagnostics emitted during parsing.
129+
///
125130
/// Any configuration files loaded as a result of parsing arguments will be
126131
/// stored in \p ConfigurationFileBuffers, if non-null. The contents of these
127132
/// buffers should \e not be interpreted by the caller; they are only present
@@ -160,6 +165,9 @@ class CompilerInvocation {
160165
StringRef SDKPath,
161166
StringRef ResourceDir);
162167

168+
/// Configures the diagnostic engine for the invocation's options.
169+
void setUpDiagnosticEngine(DiagnosticEngine &diags);
170+
163171
void setTargetTriple(const llvm::Triple &Triple);
164172
void setTargetTriple(StringRef Triple);
165173

lib/Frontend/CompilerInvocation.cpp

Lines changed: 64 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "swift/Basic/Assertions.h"
2121
#include "swift/Basic/Feature.h"
2222
#include "swift/Basic/Platform.h"
23+
#include "swift/Basic/Version.h"
2324
#include "swift/Option/Options.h"
2425
#include "swift/Option/SanitizerOptions.h"
2526
#include "swift/Parse/Lexer.h"
@@ -92,20 +93,6 @@ void CompilerInvocation::setMainExecutablePath(StringRef Path) {
9293
llvm::sys::path::remove_filename(clangPath);
9394
llvm::sys::path::append(clangPath, "clang");
9495
ClangImporterOpts.clangPath = std::string(clangPath);
95-
96-
llvm::SmallString<128> DiagnosticDocsPath(Path);
97-
llvm::sys::path::remove_filename(DiagnosticDocsPath); // Remove /swift
98-
llvm::sys::path::remove_filename(DiagnosticDocsPath); // Remove /bin
99-
llvm::sys::path::append(DiagnosticDocsPath, "share", "doc", "swift",
100-
"diagnostics");
101-
DiagnosticOpts.DiagnosticDocumentationPath = std::string(DiagnosticDocsPath.str());
102-
103-
// Compute the path to the diagnostic translations in the toolchain/build.
104-
llvm::SmallString<128> DiagnosticMessagesDir(Path);
105-
llvm::sys::path::remove_filename(DiagnosticMessagesDir); // Remove /swift
106-
llvm::sys::path::remove_filename(DiagnosticMessagesDir); // Remove /bin
107-
llvm::sys::path::append(DiagnosticMessagesDir, "share", "swift", "diagnostics");
108-
DiagnosticOpts.LocalizationPath = std::string(DiagnosticMessagesDir.str());
10996
}
11097

11198
static std::string
@@ -2369,6 +2356,9 @@ static bool ParseSearchPathArgs(SearchPathOptions &Opts, ArgList &Args,
23692356

23702357
static bool ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args,
23712358
DiagnosticEngine &Diags) {
2359+
// NOTE: This executes at the beginning of parsing the command line and cannot
2360+
// depend on the results of parsing other options.
2361+
23722362
using namespace options;
23732363

23742364
if (Args.hasArg(OPT_verify))
@@ -2492,6 +2482,56 @@ static bool ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args,
24922482
return false;
24932483
}
24942484

2485+
static void configureDiagnosticEngine(
2486+
const DiagnosticOptions &Options,
2487+
std::optional<version::Version> effectiveLanguageVersion,
2488+
StringRef mainExecutablePath, DiagnosticEngine &Diagnostics) {
2489+
if (Options.ShowDiagnosticsAfterFatalError) {
2490+
Diagnostics.setShowDiagnosticsAfterFatalError();
2491+
}
2492+
if (Options.SuppressWarnings) {
2493+
Diagnostics.setSuppressWarnings(true);
2494+
}
2495+
if (Options.SuppressRemarks) {
2496+
Diagnostics.setSuppressRemarks(true);
2497+
}
2498+
Diagnostics.setWarningsAsErrorsRules(Options.WarningsAsErrorsRules);
2499+
Diagnostics.setPrintDiagnosticNamesMode(Options.PrintDiagnosticNames);
2500+
2501+
std::string docsPath = Options.DiagnosticDocumentationPath;
2502+
if (docsPath.empty()) {
2503+
// Default to a location relative to the compiler.
2504+
llvm::SmallString<128> docsPathBuffer(mainExecutablePath);
2505+
llvm::sys::path::remove_filename(docsPathBuffer); // Remove /swift
2506+
llvm::sys::path::remove_filename(docsPathBuffer); // Remove /bin
2507+
llvm::sys::path::append(docsPathBuffer, "share", "doc", "swift",
2508+
"diagnostics");
2509+
docsPath = docsPathBuffer.str();
2510+
}
2511+
Diagnostics.setDiagnosticDocumentationPath(docsPath);
2512+
2513+
if (!Options.LocalizationCode.empty()) {
2514+
std::string locPath = Options.LocalizationPath;
2515+
if (locPath.empty()) {
2516+
llvm::SmallString<128> locPathBuffer(mainExecutablePath);
2517+
llvm::sys::path::remove_filename(locPathBuffer); // Remove /swift
2518+
llvm::sys::path::remove_filename(locPathBuffer); // Remove /bin
2519+
llvm::sys::path::append(locPathBuffer, "share", "swift", "diagnostics");
2520+
locPath = locPathBuffer.str();
2521+
}
2522+
Diagnostics.setLocalization(Options.LocalizationCode, locPath);
2523+
}
2524+
2525+
if (effectiveLanguageVersion)
2526+
Diagnostics.setLanguageVersion(*effectiveLanguageVersion);
2527+
}
2528+
2529+
/// Configures the diagnostic engine for the invocation's options.
2530+
void CompilerInvocation::setUpDiagnosticEngine(DiagnosticEngine &diags) {
2531+
configureDiagnosticEngine(DiagnosticOpts, LangOpts.EffectiveLanguageVersion,
2532+
FrontendOpts.MainExecutablePath, diags);
2533+
}
2534+
24952535
/// Parse -enforce-exclusivity=... options
24962536
void parseExclusivityEnforcementOptions(const llvm::opt::Arg *A,
24972537
SILOptions &Opts,
@@ -3742,6 +3782,16 @@ bool CompilerInvocation::parseArgs(
37423782
return true;
37433783
}
37443784

3785+
// Parse options that control diagnostic behavior as early as possible, so
3786+
// that they can influence the behavior of diagnostics emitted during the
3787+
// rest of parsing.
3788+
if (ParseDiagnosticArgs(DiagnosticOpts, ParsedArgs, Diags)) {
3789+
return true;
3790+
}
3791+
configureDiagnosticEngine(DiagnosticOpts,
3792+
/*effectiveLanguageVersion=*/std::nullopt,
3793+
mainExecutablePath, Diags);
3794+
37453795
ParseAssertionArgs(ParsedArgs);
37463796

37473797
if (ParseFrontendArgs(FrontendOpts, ParsedArgs, Diags,
@@ -3796,10 +3846,6 @@ bool CompilerInvocation::parseArgs(
37963846
return true;
37973847
}
37983848

3799-
if (ParseDiagnosticArgs(DiagnosticOpts, ParsedArgs, Diags)) {
3800-
return true;
3801-
}
3802-
38033849
if (ParseMigratorArgs(MigratorOpts, LangOpts, FrontendOpts,
38043850
SearchPathOpts.RuntimeResourcePath, ParsedArgs, Diags)) {
38053851
return true;

lib/Frontend/Frontend.cpp

Lines changed: 5 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -727,28 +727,11 @@ void CompilerInstance::setUpLLVMArguments() {
727727
}
728728

729729
void CompilerInstance::setUpDiagnosticOptions() {
730-
if (Invocation.getDiagnosticOptions().ShowDiagnosticsAfterFatalError) {
731-
Diagnostics.setShowDiagnosticsAfterFatalError();
732-
}
733-
if (Invocation.getDiagnosticOptions().SuppressWarnings) {
734-
Diagnostics.setSuppressWarnings(true);
735-
}
736-
if (Invocation.getDiagnosticOptions().SuppressRemarks) {
737-
Diagnostics.setSuppressRemarks(true);
738-
}
739-
Diagnostics.setWarningsAsErrorsRules(
740-
Invocation.getDiagnosticOptions().WarningsAsErrorsRules);
741-
Diagnostics.setPrintDiagnosticNamesMode(
742-
Invocation.getDiagnosticOptions().PrintDiagnosticNames);
743-
Diagnostics.setDiagnosticDocumentationPath(
744-
Invocation.getDiagnosticOptions().DiagnosticDocumentationPath);
745-
Diagnostics.setLanguageVersion(
746-
Invocation.getLangOptions().EffectiveLanguageVersion);
747-
if (!Invocation.getDiagnosticOptions().LocalizationCode.empty()) {
748-
Diagnostics.setLocalization(
749-
Invocation.getDiagnosticOptions().LocalizationCode,
750-
Invocation.getDiagnosticOptions().LocalizationPath);
751-
}
730+
// As a side-effect, argument parsing will have already partially configured
731+
// the diagnostic engine. However, it needs to be reconfigured here in case
732+
// there is any new configuration that should effect diagnostics for the rest
733+
// of the compile.
734+
Invocation.setUpDiagnosticEngine(Diagnostics);
752735
}
753736

754737
// The ordering of ModuleLoaders is important!

lib/Frontend/ModuleInterfaceLoader.cpp

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2248,10 +2248,6 @@ InterfaceSubContextDelegateImpl::runInSubCompilerInstance(StringRef moduleName,
22482248
subInstance.addDiagnosticConsumer(&noopConsumer);
22492249
}
22502250

2251-
// Eagerly suppress warnings if necessary, before parsing arguments.
2252-
if (subInvocation.getDiagnosticOptions().SuppressWarnings)
2253-
subInstance.getDiags().setSuppressWarnings(true);
2254-
22552251
SwiftInterfaceInfo interfaceInfo;
22562252
// Extract compiler arguments from the interface file and use them to configure
22572253
// the compiler invocation.

0 commit comments

Comments
 (0)