Skip to content

Commit 04256dc

Browse files
authored
Merge pull request #58881 from artemcm/EarlyParseableOutputExit
[Parseable Output] Emit parseable messages on failure in `CompilerInstance.setup`
2 parents 78f937f + 0ddd1a9 commit 04256dc

File tree

2 files changed

+93
-73
lines changed

2 files changed

+93
-73
lines changed

lib/FrontendTool/FrontendTool.cpp

Lines changed: 84 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -2092,57 +2092,8 @@ int swift::performFrontend(ArrayRef<const char *> Args,
20922092
PDC.setSuppressOutput(true);
20932093
}
20942094

2095-
// Because the serialized diagnostics consumer is initialized here,
2096-
// diagnostics emitted above, within CompilerInvocation::parseArgs, are never
2097-
// serialized. This is a non-issue because, in nearly all cases, frontend
2098-
// arguments are generated by the driver, not directly by a user. The driver
2099-
// is responsible for emitting diagnostics for its own errors. See SR-2683
2100-
// for details.
2101-
std::unique_ptr<DiagnosticConsumer> SerializedConsumerDispatcher =
2102-
createSerializedDiagnosticConsumerIfNeeded(
2103-
Invocation.getFrontendOptions().InputsAndOutputs);
2104-
if (SerializedConsumerDispatcher)
2105-
Instance->addDiagnosticConsumer(SerializedConsumerDispatcher.get());
2106-
2107-
std::unique_ptr<DiagnosticConsumer> FixItsConsumer =
2108-
createJSONFixItDiagnosticConsumerIfNeeded(Invocation);
2109-
if (FixItsConsumer)
2110-
Instance->addDiagnosticConsumer(FixItsConsumer.get());
2111-
2112-
if (Invocation.getDiagnosticOptions().UseColor)
2113-
PDC.forceColors();
2114-
2115-
PDC.setPrintEducationalNotes(
2116-
Invocation.getDiagnosticOptions().PrintEducationalNotes);
2117-
2118-
PDC.setFormattingStyle(
2119-
Invocation.getDiagnosticOptions().PrintedFormattingStyle);
2120-
2121-
if (Invocation.getFrontendOptions().PrintStats) {
2122-
llvm::EnableStatistics();
2123-
}
2124-
2125-
const DiagnosticOptions &diagOpts = Invocation.getDiagnosticOptions();
2126-
bool verifierEnabled = diagOpts.VerifyMode != DiagnosticOptions::NoVerify;
2127-
2128-
std::string InstanceSetupError;
2129-
if (Instance->setup(Invocation, InstanceSetupError)) {
2130-
return finishDiagProcessing(1, /*verifierEnabled*/ false);
2131-
}
2132-
2133-
// The compiler instance has been configured; notify our observer.
2134-
if (observer) {
2135-
observer->configuredCompiler(*Instance);
2136-
}
2137-
2138-
if (verifierEnabled) {
2139-
// Suppress printed diagnostic output during the compile if the verifier is
2140-
// enabled.
2141-
PDC.setSuppressOutput(true);
2142-
}
2143-
2144-
if (Invocation.getFrontendOptions().FrontendParseableOutput) {
2145-
const auto &IO = Invocation.getFrontendOptions().InputsAndOutputs;
2095+
auto emitParseableBeganMessage = [&Invocation, &Args]() {
2096+
const auto &IO = Invocation.getFrontendOptions().InputsAndOutputs;
21462097
const auto OSPid = getpid();
21472098
const auto ProcInfo = sys::TaskProcessInformation(OSPid);
21482099

@@ -2171,27 +2122,9 @@ int swift::performFrontend(ArrayRef<const char *> Args,
21712122
constructDetailedTaskDescription(Invocation, IO.getAllInputs(), Args),
21722123
OSPid, ProcInfo);
21732124
}
2174-
}
2175-
2176-
int ReturnValue = 0;
2177-
bool HadError = performCompile(*Instance, ReturnValue, observer);
2178-
2179-
if (verifierEnabled) {
2180-
DiagnosticEngine &diags = Instance->getDiags();
2181-
if (diags.hasFatalErrorOccurred() &&
2182-
!Invocation.getDiagnosticOptions().ShowDiagnosticsAfterFatalError) {
2183-
diags.resetHadAnyError();
2184-
PDC.setSuppressOutput(false);
2185-
diags.diagnose(SourceLoc(), diag::verify_encountered_fatal);
2186-
HadError = true;
2187-
}
2188-
}
2189-
2190-
auto r = finishDiagProcessing(HadError ? 1 : ReturnValue, verifierEnabled);
2191-
if (auto *StatsReporter = Instance->getStatsReporter())
2192-
StatsReporter->noteCurrentProcessExitStatus(r);
2125+
};
21932126

2194-
if (Invocation.getFrontendOptions().FrontendParseableOutput) {
2127+
auto emitParseableFinishedMessage = [&Invocation, &Args, &FileSpecificDiagnostics](int ExitStatus) {
21952128
const auto &IO = Invocation.getFrontendOptions().InputsAndOutputs;
21962129
const auto OSPid = getpid();
21972130
const auto ProcInfo = sys::TaskProcessInformation(OSPid);
@@ -2217,7 +2150,7 @@ int swift::performFrontend(ArrayRef<const char *> Args,
22172150

22182151
emitFinishedMessage(llvm::errs(),
22192152
mapFrontendInvocationToAction(Invocation),
2220-
JoinedDiags.str(), r, Pid - idx, ProcInfo);
2153+
JoinedDiags.str(), ExitStatus, Pid - idx, ProcInfo);
22212154
return false;
22222155
});
22232156
} else {
@@ -2234,10 +2167,88 @@ int swift::performFrontend(ArrayRef<const char *> Args,
22342167
std::ostream_iterator<std::string>(JoinedDiags, Delim));
22352168
emitFinishedMessage(llvm::errs(),
22362169
mapFrontendInvocationToAction(Invocation),
2237-
JoinedDiags.str(), r, OSPid, ProcInfo);
2170+
JoinedDiags.str(), ExitStatus, OSPid, ProcInfo);
22382171
}
2172+
};
2173+
2174+
// Because the serialized diagnostics consumer is initialized here,
2175+
// diagnostics emitted above, within CompilerInvocation::parseArgs, are never
2176+
// serialized. This is a non-issue because, in nearly all cases, frontend
2177+
// arguments are generated by the driver, not directly by a user. The driver
2178+
// is responsible for emitting diagnostics for its own errors. See SR-2683
2179+
// for details.
2180+
std::unique_ptr<DiagnosticConsumer> SerializedConsumerDispatcher =
2181+
createSerializedDiagnosticConsumerIfNeeded(
2182+
Invocation.getFrontendOptions().InputsAndOutputs);
2183+
if (SerializedConsumerDispatcher)
2184+
Instance->addDiagnosticConsumer(SerializedConsumerDispatcher.get());
2185+
2186+
std::unique_ptr<DiagnosticConsumer> FixItsConsumer =
2187+
createJSONFixItDiagnosticConsumerIfNeeded(Invocation);
2188+
if (FixItsConsumer)
2189+
Instance->addDiagnosticConsumer(FixItsConsumer.get());
2190+
2191+
if (Invocation.getDiagnosticOptions().UseColor)
2192+
PDC.forceColors();
2193+
2194+
PDC.setPrintEducationalNotes(
2195+
Invocation.getDiagnosticOptions().PrintEducationalNotes);
2196+
2197+
PDC.setFormattingStyle(
2198+
Invocation.getDiagnosticOptions().PrintedFormattingStyle);
2199+
2200+
if (Invocation.getFrontendOptions().PrintStats) {
2201+
llvm::EnableStatistics();
22392202
}
22402203

2204+
2205+
if (Invocation.getFrontendOptions().FrontendParseableOutput)
2206+
emitParseableBeganMessage();
2207+
2208+
const DiagnosticOptions &diagOpts = Invocation.getDiagnosticOptions();
2209+
bool verifierEnabled = diagOpts.VerifyMode != DiagnosticOptions::NoVerify;
2210+
2211+
std::string InstanceSetupError;
2212+
if (Instance->setup(Invocation, InstanceSetupError)) {
2213+
int ReturnCode = 1;
2214+
if (Invocation.getFrontendOptions().FrontendParseableOutput)
2215+
emitParseableFinishedMessage(ReturnCode);
2216+
2217+
return finishDiagProcessing(ReturnCode, /*verifierEnabled*/ false);
2218+
}
2219+
2220+
// The compiler instance has been configured; notify our observer.
2221+
if (observer) {
2222+
observer->configuredCompiler(*Instance);
2223+
}
2224+
2225+
if (verifierEnabled) {
2226+
// Suppress printed diagnostic output during the compile if the verifier is
2227+
// enabled.
2228+
PDC.setSuppressOutput(true);
2229+
}
2230+
2231+
int ReturnValue = 0;
2232+
bool HadError = performCompile(*Instance, ReturnValue, observer);
2233+
2234+
if (verifierEnabled) {
2235+
DiagnosticEngine &diags = Instance->getDiags();
2236+
if (diags.hasFatalErrorOccurred() &&
2237+
!Invocation.getDiagnosticOptions().ShowDiagnosticsAfterFatalError) {
2238+
diags.resetHadAnyError();
2239+
PDC.setSuppressOutput(false);
2240+
diags.diagnose(SourceLoc(), diag::verify_encountered_fatal);
2241+
HadError = true;
2242+
}
2243+
}
2244+
2245+
auto r = finishDiagProcessing(HadError ? 1 : ReturnValue, verifierEnabled);
2246+
if (auto *StatsReporter = Instance->getStatsReporter())
2247+
StatsReporter->noteCurrentProcessExitStatus(r);
2248+
2249+
if (Invocation.getFrontendOptions().FrontendParseableOutput)
2250+
emitParseableFinishedMessage(r);
2251+
22412252
return r;
22422253
}
22432254

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// RUN: not %target-swift-frontend(mock-sdk: -sdk %/S/../ModuleInterface/Inputs/BadStdlib.sdk -module-cache-path %/t/module-cache -resource-dir %/S/../ModuleInterface/Inputs/BadStdlib.sdk) -primary-file %s -o %t.out -emit-module -emit-module-path %t.swiftmodule -module-name parseable_output_early -frontend-parseable-output 2>&1 | %FileCheck %s
2+
3+
// CHECK: {{[1-9][0-9]*}}
4+
// CHECK-NEXT: {
5+
// CHECK-NEXT: "kind": "began",
6+
// CHECK-NEXT: "name": "compile",
7+
8+
// CHECK: "kind": "finished",
9+
// CHECK-NEXT: "name": "compile",

0 commit comments

Comments
 (0)