Skip to content

Commit 411b14f

Browse files
committed
api-digester: Emit JSON errors during diagnose-sdk
The diagnostic consumers for swift-api-digester -diagnose-sdk were being set up after JSON files were read in, so errors in those files were silently dropped. In at least one case this led to a crash with no hint about what was happening. Set up the diagnostic consumer before doing any serious work to avoid this problem. Fixing this required me to make `newCompilerInstance()` copy diagnostic consumers to the new instance’s diagnostic engine, since compiler instances were now being created after the consumers were added instead of before. I also had to make FilteringDiagnosticConsumer filter out clang warnings, remarks, and notes since those were now being emitted early enough to register in the digester.
1 parent 8117219 commit 411b14f

File tree

6 files changed

+65
-54
lines changed

6 files changed

+65
-54
lines changed

include/swift/APIDigester/ModuleAnalyzerNodes.h

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -234,10 +234,7 @@ class SDKContext {
234234
ArrayRef<BreakingAttributeInfo> getBreakingAttributeInfo() const { return BreakingAttrs; }
235235
llvm::Optional<uint8_t> getFixedBinaryOrder(ValueDecl *VD) const;
236236

237-
CompilerInstance &newCompilerInstance() {
238-
CIs.emplace_back(new CompilerInstance());
239-
return *CIs.back();
240-
}
237+
CompilerInstance &newCompilerInstance();
241238
template<class YAMLNodeTy, typename ...ArgTypes>
242239
void diagnose(YAMLNodeTy node, Diag<ArgTypes...> ID,
243240
typename detail::PassArgument<ArgTypes>::type... args) {

lib/APIDigester/ModuleAnalyzerNodes.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,17 @@ void SDKContext::addDiagConsumer(DiagnosticConsumer &Consumer) {
8989
}
9090
}
9191

92+
CompilerInstance &SDKContext::newCompilerInstance() {
93+
CIs.emplace_back(new CompilerInstance());
94+
95+
// Add our existing diagnostic consumers to this new compiler instance.
96+
// (Note that we do the opposite in addDiagConsumer().)
97+
for (auto &consumer : Diags.getConsumers())
98+
CIs.back()->addDiagnosticConsumer(consumer);
99+
100+
return *CIs.back();
101+
}
102+
92103
void SDKNodeRoot::registerDescendant(SDKNode *D) {
93104
// Operator doesn't have usr
94105
if (isa<SDKNodeDeclOperator>(D))

lib/APIDigester/ModuleDiagsConsumer.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
//===----------------------------------------------------------------------===//
1717

1818
#include "swift/AST/DiagnosticEngine.h"
19+
#include "swift/AST/DiagnosticsClangImporter.h"
1920
#include "swift/AST/DiagnosticsModuleDiffer.h"
2021
#include "swift/APIDigester/ModuleDiagsConsumer.h"
2122

@@ -145,6 +146,13 @@ bool swift::ide::api::FilteringDiagnosticConsumer::finishProcessing() {
145146
}
146147

147148
bool swift::ide::api::FilteringDiagnosticConsumer::shouldProceed(const DiagnosticInfo &Info) {
149+
// Suppress spurious warnings from imported headers. These were traditionally
150+
// ignored because they were emitted before the diagnostic consumer was ready.
151+
if (Info.ID == diag::warning_from_clang.ID ||
152+
Info.ID == diag::remark_from_clang.ID ||
153+
Info.ID == diag::note_from_clang.ID)
154+
return false;
155+
148156
if (allowedBreakages->empty()) {
149157
return true;
150158
}

lib/DriverTool/swift_api_digester_main.cpp

Lines changed: 43 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1915,42 +1915,20 @@ static bool readBreakageAllowlist(SDKContext &Ctx, llvm::StringSet<> &lines,
19151915
}
19161916

19171917
static int diagnoseModuleChange(SDKContext &Ctx, SDKNodeRoot *LeftModule,
1918-
SDKNodeRoot *RightModule, StringRef OutputPath,
1918+
SDKNodeRoot *RightModule,
19191919
llvm::StringSet<> ProtocolReqAllowlist,
1920-
bool DisableFailOnError,
1921-
bool CompilerStyleDiags,
1922-
StringRef SerializedDiagPath,
1923-
StringRef BreakageAllowlistPath,
1924-
bool DebugMapping) {
1920+
bool DebugMapping,
1921+
bool FailOnError,
1922+
FilteringDiagnosticConsumer *pConsumer) {
19251923
PrettyStackTraceSDKNodes trace(
19261924
"diagnosing changes between modules", LeftModule, RightModule);
19271925

19281926
assert(LeftModule);
19291927
assert(RightModule);
1930-
llvm::raw_ostream *OS = &llvm::errs();
19311928
if (!LeftModule || !RightModule) {
1932-
*OS << "Cannot diagnose null SDKNodeRoot";
1929+
llvm::errs() << "Cannot diagnose null SDKNodeRoot";
19331930
exit(1);
19341931
}
1935-
std::unique_ptr<llvm::raw_ostream> FileOS;
1936-
if (!OutputPath.empty()) {
1937-
std::error_code EC;
1938-
FileOS.reset(new llvm::raw_fd_ostream(OutputPath, EC, llvm::sys::fs::OF_None));
1939-
OS = FileOS.get();
1940-
}
1941-
bool FailOnError;
1942-
auto allowedBreakages = std::make_unique<llvm::StringSet<>>();
1943-
if (readBreakageAllowlist(Ctx, *allowedBreakages, BreakageAllowlistPath)) {
1944-
Ctx.getDiags().diagnose(SourceLoc(), diag::cannot_read_allowlist,
1945-
BreakageAllowlistPath);
1946-
}
1947-
auto pConsumer = std::make_unique<FilteringDiagnosticConsumer>(
1948-
createDiagConsumer(*OS, FailOnError, DisableFailOnError, CompilerStyleDiags,
1949-
SerializedDiagPath),
1950-
std::move(allowedBreakages),
1951-
/*DowngradeToWarning*/false);
1952-
SWIFT_DEFER { pConsumer->finishProcessing(); };
1953-
Ctx.addDiagConsumer(*pConsumer);
19541932
Ctx.setCommonVersion(std::min(LeftModule->getJsonFormatVersion(),
19551933
RightModule->getJsonFormatVersion()));
19561934
TypeAliasDiffFinder(LeftModule, RightModule,
@@ -1965,14 +1943,12 @@ static int diagnoseModuleChange(SDKContext &Ctx, SDKNodeRoot *LeftModule,
19651943
return FailOnError && pConsumer->hasError() ? 1 : 0;
19661944
}
19671945

1968-
static int diagnoseModuleChange(StringRef LeftPath, StringRef RightPath,
1969-
StringRef OutputPath, CheckerOptions Opts,
1946+
static int diagnoseModuleChange(SDKContext &Ctx, StringRef LeftPath,
1947+
StringRef RightPath,
19701948
llvm::StringSet<> ProtocolReqAllowlist,
1971-
bool DisableFailOnError,
1972-
bool CompilerStyleDiags,
1973-
StringRef SerializedDiagPath,
1974-
StringRef BreakageAllowlistPath,
1975-
bool DebugMapping) {
1949+
bool DebugMapping,
1950+
bool FailOnError,
1951+
FilteringDiagnosticConsumer *pConsumer) {
19761952
if (!fs::exists(LeftPath)) {
19771953
llvm::errs() << LeftPath << " does not exist\n";
19781954
return 1;
@@ -1981,15 +1957,13 @@ static int diagnoseModuleChange(StringRef LeftPath, StringRef RightPath,
19811957
llvm::errs() << RightPath << " does not exist\n";
19821958
return 1;
19831959
}
1984-
SDKContext Ctx(Opts);
19851960
SwiftDeclCollector LeftCollector(Ctx);
19861961
LeftCollector.deSerialize(LeftPath);
19871962
SwiftDeclCollector RightCollector(Ctx);
19881963
RightCollector.deSerialize(RightPath);
19891964
return diagnoseModuleChange(
1990-
Ctx, LeftCollector.getSDKRoot(), RightCollector.getSDKRoot(), OutputPath,
1991-
std::move(ProtocolReqAllowlist), DisableFailOnError, CompilerStyleDiags, SerializedDiagPath,
1992-
BreakageAllowlistPath, DebugMapping);
1965+
Ctx, LeftCollector.getSDKRoot(), RightCollector.getSDKRoot(),
1966+
std::move(ProtocolReqAllowlist), DebugMapping, FailOnError, pConsumer);
19931967
}
19941968

19951969
static void populateAliasChanges(NodeMap &AliasMap, DiffVector &AllItems,
@@ -2579,26 +2553,46 @@ class SwiftAPIDigesterInvocation {
25792553
OutputFile, IgnoredUsrs, CheckerOpts,
25802554
OutputInJson, DebugMapping);
25812555
}
2556+
SDKContext Ctx(CheckerOpts);
2557+
2558+
llvm::raw_ostream *OS = &llvm::errs();
2559+
std::unique_ptr<llvm::raw_ostream> FileOS;
2560+
if (!OutputFile.empty()) {
2561+
std::error_code EC;
2562+
FileOS.reset(new llvm::raw_fd_ostream(OutputFile, EC, llvm::sys::fs::OF_None));
2563+
OS = FileOS.get();
2564+
}
2565+
bool FailOnError;
2566+
auto allowedBreakages = std::make_unique<llvm::StringSet<>>();
2567+
if (readBreakageAllowlist(Ctx, *allowedBreakages, BreakageAllowlistPath)) {
2568+
Ctx.getDiags().diagnose(SourceLoc(), diag::cannot_read_allowlist,
2569+
BreakageAllowlistPath);
2570+
}
2571+
auto pConsumer = std::make_unique<FilteringDiagnosticConsumer>(
2572+
createDiagConsumer(*OS, FailOnError, DisableFailOnError, CompilerStyleDiags,
2573+
SerializedDiagPath),
2574+
std::move(allowedBreakages),
2575+
/*DowngradeToWarning*/false);
2576+
SWIFT_DEFER { pConsumer->finishProcessing(); };
2577+
Ctx.addDiagConsumer(*pConsumer);
2578+
25822579
switch (Mode) {
25832580
case ComparisonInputMode::BothJson: {
25842581
return diagnoseModuleChange(
2585-
SDKJsonPaths[0], SDKJsonPaths[1], OutputFile, CheckerOpts,
2586-
std::move(protocolAllowlist), DisableFailOnError, CompilerStyleDiags,
2587-
SerializedDiagPath, BreakageAllowlistPath, DebugMapping);
2582+
Ctx, SDKJsonPaths[0], SDKJsonPaths[1], std::move(protocolAllowlist),
2583+
DebugMapping, FailOnError, pConsumer.get());
25882584
}
25892585
case ComparisonInputMode::BaselineJson: {
2590-
SDKContext Ctx(CheckerOpts);
25912586
return diagnoseModuleChange(
2592-
Ctx, getBaselineFromJson(Ctx), getSDKRoot(Ctx, false), OutputFile,
2593-
std::move(protocolAllowlist), DisableFailOnError, CompilerStyleDiags,
2594-
SerializedDiagPath, BreakageAllowlistPath, DebugMapping);
2587+
Ctx, getBaselineFromJson(Ctx), getSDKRoot(Ctx, false),
2588+
std::move(protocolAllowlist), DebugMapping, FailOnError,
2589+
pConsumer.get());
25952590
}
25962591
case ComparisonInputMode::BothLoad: {
2597-
SDKContext Ctx(CheckerOpts);
25982592
return diagnoseModuleChange(
2599-
Ctx, getSDKRoot(Ctx, true), getSDKRoot(Ctx, false), OutputFile,
2600-
std::move(protocolAllowlist), DisableFailOnError, CompilerStyleDiags,
2601-
SerializedDiagPath, BreakageAllowlistPath, DebugMapping);
2593+
Ctx, getSDKRoot(Ctx, true), getSDKRoot(Ctx, false),
2594+
std::move(protocolAllowlist), DebugMapping, FailOnError,
2595+
pConsumer.get());
26022596
}
26032597
}
26042598
}

test/api-digester/diagnostics.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
// REQUIRES: OS=macosx
22
// RUN: not %api-digester -deserialize-sdk -input-paths %S/diagnostics.json -o - 2>&1 | %FileCheck %s
3+
// RUN: not %api-digester -diagnose-sdk -input-paths %S/diagnostics.json -input-paths %S/diagnostics.json -compiler-style-diags -o - 2>&1 | %FileCheck %s
34

45
// CHECK: diagnostics.json:5:3: error: unrecognized key 'badKey' in SDK node
56
// CHECK: diagnostics.json:8:15: error: unrecognized SDK node kind 'Zyzyx'

validation-test/WholeSDK/api-digester.test

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,7 @@ Social
224224
SoundAnalysis
225225
Speech
226226
SpriteKit
227-
// StoreKit - crash processing StoreKit.Transaction.environmentStringRepresentation in Swift CI
227+
StoreKit
228228
SwiftUI
229229
// SyncServices - error: module 'SyncServices' is incompatible with feature 'swift'
230230
SystemConfiguration

0 commit comments

Comments
 (0)