Skip to content

Commit de74836

Browse files
committed
Wire up FileSpecificDiagnosticConsumer for serialized diagnostics
It appears to work!
1 parent 57087c4 commit de74836

File tree

7 files changed

+106
-21
lines changed

7 files changed

+106
-21
lines changed

include/swift/Frontend/InputFile.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,10 @@ class InputFile {
9191
std::string loadedModuleTracePath() const {
9292
return getPrimarySpecificPaths().SupplementaryOutputs.LoadedModuleTracePath;
9393
}
94+
std::string serializedDiagnosticsPath() const {
95+
return getPrimarySpecificPaths().SupplementaryOutputs
96+
.SerializedDiagnosticsPath;
97+
}
9498
};
9599
} // namespace swift
96100

include/swift/Frontend/SerializedDiagnosticConsumer.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,14 @@ namespace swift {
2929
class DiagnosticConsumer;
3030

3131
namespace serialized_diagnostics {
32-
/// \brief Create a DiagnosticConsumer that serializes diagnostics to a
33-
/// file.
32+
/// Create a DiagnosticConsumer that serializes diagnostics to a file, using
33+
/// Clang's serialized diagnostics format.
3434
///
35-
/// \param serializedDiagnosticsPath the file path to write the diagnostics.
35+
/// \param outputPath the file path to write the diagnostics to.
3636
///
3737
/// \returns A new diagnostic consumer that serializes diagnostics.
38-
DiagnosticConsumer *createConsumer(llvm::StringRef serializedDiagnosticsPath);
38+
std::unique_ptr<DiagnosticConsumer>
39+
createConsumer(llvm::StringRef outputPath);
3940
}
4041
}
4142

lib/Frontend/SerializedDiagnosticConsumer.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -222,9 +222,10 @@ class SerializedDiagnosticConsumer : public DiagnosticConsumer {
222222
};
223223
} // end anonymous namespace
224224

225-
namespace swift { namespace serialized_diagnostics {
226-
DiagnosticConsumer *createConsumer(StringRef serializedDiagnosticsPath) {
227-
return new SerializedDiagnosticConsumer(serializedDiagnosticsPath);
225+
namespace swift {
226+
namespace serialized_diagnostics {
227+
std::unique_ptr<DiagnosticConsumer> createConsumer(StringRef outputPath) {
228+
return llvm::make_unique<SerializedDiagnosticConsumer>(outputPath);
228229
}
229230
} // namespace serialized_diagnostics
230231
} // namespace swift

lib/FrontendTool/FrontendTool.cpp

Lines changed: 51 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1334,7 +1334,7 @@ static bool performCompileStepsPostSILGen(
13341334

13351335
// Just because we had an AST error it doesn't mean we can't performLLVM.
13361336
bool HadError = Instance.getASTContext().hadError();
1337-
1337+
13381338
// If the AST Context has no errors but no IRModule is available,
13391339
// parallelIRGen happened correctly, since parallel IRGen produces multiple
13401340
// modules.
@@ -1508,6 +1508,50 @@ computeStatsReporter(const CompilerInvocation &Invocation, CompilerInstance *Ins
15081508
ProfileEvents, ProfileEntities);
15091509
}
15101510

1511+
/// Creates a diagnostic consumer that handles serializing diagnostics, based on
1512+
/// the supplementary output paths specified by \p inputsAndOutputs.
1513+
///
1514+
/// The returned consumer will handle producing multiple serialized diagnostics
1515+
/// files if necessary, by using sub-consumers for each file and dispatching to
1516+
/// the right one.
1517+
///
1518+
/// If no serialized diagnostics are being produced, returns null.
1519+
static std::unique_ptr<DiagnosticConsumer>
1520+
createSerializedDiagnosticConsumerIfNeeded(
1521+
const FrontendInputsAndOutputs &inputsAndOutputs) {
1522+
1523+
// The "4" here is somewhat arbitrary. In practice we're going to have one
1524+
// sub-consumer for each .dia file we're trying to output, which (again in
1525+
// practice) is going to be 1 in WMO mode and equal to the number of primary
1526+
// inputs in batch mode. That in turn is going to be "the number of files we
1527+
// need to recompile in this build, divided by the number of jobs". So a
1528+
// value of "4" here means that there would be no heap allocation on a clean
1529+
// build of a module with up to 32 files on an 8-core machine, if the user
1530+
// doesn't customize anything.
1531+
SmallVector<FileSpecificDiagnosticConsumer::ConsumerPair, 4>
1532+
serializedConsumers;
1533+
1534+
inputsAndOutputs.forEachInputProducingSupplementaryOutput(
1535+
[&](const InputFile &Input) -> bool {
1536+
std::string serializedDiagnosticsPath = Input.serializedDiagnosticsPath();
1537+
if (serializedDiagnosticsPath.empty())
1538+
return false;
1539+
1540+
serializedConsumers.emplace_back(
1541+
Input.file(),
1542+
serialized_diagnostics::createConsumer(serializedDiagnosticsPath));
1543+
1544+
// Continue for other inputs.
1545+
return false;
1546+
});
1547+
1548+
if (serializedConsumers.empty())
1549+
return nullptr;
1550+
if (serializedConsumers.size() == 1)
1551+
return std::move(serializedConsumers.front()).second;
1552+
return llvm::make_unique<FileSpecificDiagnosticConsumer>(serializedConsumers);
1553+
}
1554+
15111555
int swift::performFrontend(ArrayRef<const char *> Args,
15121556
const char *Argv0, void *MainAddr,
15131557
FrontendObserver *observer) {
@@ -1623,20 +1667,13 @@ int swift::performFrontend(ArrayRef<const char *> Args,
16231667
// arguments are generated by the driver, not directly by a user. The driver
16241668
// is responsible for emitting diagnostics for its own errors. See SR-2683
16251669
// for details.
1626-
//
1627-
// FIXME: Do we need one SerializedConsumer per primary? Owned by the
1628-
// SourceFile?
1629-
std::unique_ptr<DiagnosticConsumer> SerializedConsumer;
1630-
{
1631-
const std::string &SerializedDiagnosticsPath =
1632-
Invocation.getSerializedDiagnosticsPathForAtMostOnePrimary();
1633-
if (!SerializedDiagnosticsPath.empty()) {
1634-
SerializedConsumer.reset(
1635-
serialized_diagnostics::createConsumer(SerializedDiagnosticsPath));
1636-
Instance->addDiagnosticConsumer(SerializedConsumer.get());
1637-
}
1638-
}
1670+
std::unique_ptr<DiagnosticConsumer> SerializedConsumerDispatcher =
1671+
createSerializedDiagnosticConsumerIfNeeded(
1672+
Invocation.getFrontendOptions().InputsAndOutputs);
1673+
if (SerializedConsumerDispatcher)
1674+
Instance->addDiagnosticConsumer(SerializedConsumerDispatcher.get());
16391675

1676+
// FIXME: The fix-its need to be multiplexed like the serialized diagnostics.
16401677
std::unique_ptr<DiagnosticConsumer> FixitsConsumer;
16411678
{
16421679
const std::string &FixitsOutputPath =
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
func testHelper() {
2+
nonexistent()
3+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
func foo() {}
2+
func foo() {}
3+
4+
func bar() {
5+
shouldNotShowUpInOutput()
6+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// RUN: rm -f %t.*
2+
3+
// RUN: not %target-swift-frontend -typecheck -primary-file %s -serialize-diagnostics-path %t.main.dia -primary-file %S/Inputs/serialized-diagnostics-batch-mode-helper.swift -serialize-diagnostics-path %t.helper.dia %S/Inputs/serialized-diagnostics-batch-mode-other.swift 2> %t.stderr.txt
4+
// RUN: %FileCheck -check-prefix=CHECK-STDERR %s < %t.stderr.txt
5+
// RUN: %FileCheck -check-prefix=NEGATIVE-STDERR %s < %t.stderr.txt
6+
7+
// RUN: c-index-test -read-diagnostics %t.main.dia 2> %t.main.txt
8+
// RUN: %FileCheck -check-prefix=CHECK-MAIN %s < %t.main.txt
9+
// RUN: %FileCheck -check-prefix=NEGATIVE-MAIN %s < %t.main.txt
10+
11+
// RUN: c-index-test -read-diagnostics %t.helper.dia 2> %t.helper.txt
12+
// RUN: %FileCheck -check-prefix=CHECK-HELPER %s < %t.helper.txt
13+
// RUN: %FileCheck -check-prefix=NEGATIVE-HELPER %s < %t.helper.txt
14+
15+
// NEGATIVE-MAIN-NOT: shouldNotShowUpInOutput
16+
// NEGATIVE-HELPER-NOT: shouldNotShowUpInOutput
17+
// NEGATIVE-STDERR-NOT: shouldNotShowUpInOutput
18+
19+
// NEGATIVE-MAIN-NOT: serialized-diagnostics-batch-mode-helper.swift
20+
// NEGATIVE-HELPER-NOT: serialized-diagnostics-batch-mode.swift
21+
22+
// CHECK-MAIN-DAG: serialized-diagnostics-batch-mode-other.swift:{{[0-9]+}}:6: error: invalid redeclaration of 'foo()'
23+
// CHECK-HELPER-DAG: serialized-diagnostics-batch-mode-other.swift:{{[0-9]+}}:6: error: invalid redeclaration of 'foo()'
24+
// CHECK-STDERR-DAG: serialized-diagnostics-batch-mode-other.swift:{{[0-9]+}}:6: error: invalid redeclaration of 'foo()'
25+
26+
func test() {
27+
nonexistent() // CHECK-MAIN-DAG: serialized-diagnostics-batch-mode.swift:[[@LINE]]:3: error: use of unresolved identifier 'nonexistent'
28+
// CHECK-STDERR-DAG: serialized-diagnostics-batch-mode.swift:[[@LINE-1]]:3: error: use of unresolved identifier 'nonexistent'
29+
30+
// The other file has a similar call.
31+
// CHECK-HELPER-DAG: serialized-diagnostics-batch-mode-helper.swift:{{[0-9]+}}:3: error: use of unresolved identifier 'nonexistent'
32+
// CHECK-STDERR-DAG: serialized-diagnostics-batch-mode-helper.swift:{{[0-9]+}}:3: error: use of unresolved identifier 'nonexistent'
33+
}

0 commit comments

Comments
 (0)