Skip to content

Commit 4527d02

Browse files
authored
Merge pull request #75117 from artemcm/60ScannerFailureMinimalDiagnostics
[6.0 🍒][Dependency Scanning] Emit diagnostics on scan query failure during initialization or cycle detection
2 parents 84f116f + acd2da7 commit 4527d02

File tree

6 files changed

+258
-98
lines changed

6 files changed

+258
-98
lines changed

include/swift/DependencyScan/DependencyScanningTool.h

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ class DependencyScanDiagnosticCollector;
2828

2929
struct ScanQueryInstance {
3030
std::unique_ptr<CompilerInstance> ScanInstance;
31-
std::unique_ptr<DependencyScanDiagnosticCollector> ScanDiagnostics;
31+
std::shared_ptr<DependencyScanDiagnosticCollector> ScanDiagnostics;
3232
};
3333

3434
/// Diagnostic consumer that simply collects the diagnostics emitted so-far
@@ -124,15 +124,10 @@ class DependencyScanningTool {
124124
/// that will be used for this scan.
125125
llvm::ErrorOr<ScanQueryInstance>
126126
initCompilerInstanceForScan(ArrayRef<const char *> Command,
127-
StringRef WorkingDirectory);
127+
StringRef WorkingDirectory,
128+
std::shared_ptr<DependencyScanDiagnosticCollector> scannerDiagnosticsCollector);
128129

129130
private:
130-
/// Using the specified invocation command, initialize the scanner instance
131-
/// for this scan. Returns the `CompilerInstance` that will be used.
132-
llvm::ErrorOr<ScanQueryInstance>
133-
initScannerForAction(ArrayRef<const char *> Command,
134-
StringRef WorkingDirectory);
135-
136131
/// Shared cache of module dependencies, re-used by individual full-scan queries
137132
/// during the lifetime of this Tool.
138133
std::unique_ptr<SwiftDependencyScanningService> ScanningService;
@@ -150,6 +145,8 @@ class DependencyScanningTool {
150145
llvm::StringSaver Saver;
151146
};
152147

148+
swiftscan_diagnostic_set_t *mapCollectedDiagnosticsForOutput(const DependencyScanDiagnosticCollector *diagnosticCollector);
149+
153150
} // end namespace dependencies
154151
} // end namespace swift
155152

lib/DependencyScan/DependencyScanningTool.cpp

Lines changed: 155 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,120 @@ void LockingDependencyScanDiagnosticCollector::addDiagnostic(
140140
DependencyScanDiagnosticCollector::addDiagnostic(SM, Info);
141141
}
142142

143+
swiftscan_diagnostic_set_t *mapCollectedDiagnosticsForOutput(
144+
const DependencyScanDiagnosticCollector *diagnosticCollector) {
145+
auto collectedDiagnostics = diagnosticCollector->getDiagnostics();
146+
auto numDiagnostics = collectedDiagnostics.size();
147+
swiftscan_diagnostic_set_t *diagnosticOutput = new swiftscan_diagnostic_set_t;
148+
diagnosticOutput->count = numDiagnostics;
149+
diagnosticOutput->diagnostics =
150+
new swiftscan_diagnostic_info_t[numDiagnostics];
151+
for (size_t i = 0; i < numDiagnostics; ++i) {
152+
const auto &Diagnostic = collectedDiagnostics[i];
153+
swiftscan_diagnostic_info_s *diagnosticInfo =
154+
new swiftscan_diagnostic_info_s;
155+
diagnosticInfo->message =
156+
swift::c_string_utils::create_clone(Diagnostic.Message.c_str());
157+
switch (Diagnostic.Severity) {
158+
case llvm::SourceMgr::DK_Error:
159+
diagnosticInfo->severity = SWIFTSCAN_DIAGNOSTIC_SEVERITY_ERROR;
160+
break;
161+
case llvm::SourceMgr::DK_Warning:
162+
diagnosticInfo->severity = SWIFTSCAN_DIAGNOSTIC_SEVERITY_WARNING;
163+
break;
164+
case llvm::SourceMgr::DK_Note:
165+
diagnosticInfo->severity = SWIFTSCAN_DIAGNOSTIC_SEVERITY_NOTE;
166+
break;
167+
case llvm::SourceMgr::DK_Remark:
168+
diagnosticInfo->severity = SWIFTSCAN_DIAGNOSTIC_SEVERITY_REMARK;
169+
break;
170+
}
171+
172+
if (Diagnostic.ImportLocation.has_value()) {
173+
auto importLocation = Diagnostic.ImportLocation.value();
174+
swiftscan_source_location_s *sourceLoc = new swiftscan_source_location_s;
175+
if (importLocation.bufferIdentifier.empty())
176+
sourceLoc->buffer_identifier = swift::c_string_utils::create_null();
177+
else
178+
sourceLoc->buffer_identifier = swift::c_string_utils::create_clone(
179+
importLocation.bufferIdentifier.c_str());
180+
sourceLoc->line_number = importLocation.lineNumber;
181+
sourceLoc->column_number = importLocation.columnNumber;
182+
diagnosticInfo->source_location = sourceLoc;
183+
} else {
184+
diagnosticInfo->source_location = nullptr;
185+
}
186+
187+
diagnosticOutput->diagnostics[i] = diagnosticInfo;
188+
}
189+
return diagnosticOutput;
190+
}
191+
192+
// Generate an instance of the `swiftscan_dependency_graph_s` which contains no
193+
// module dependnecies but captures the diagnostics emitted during the attempted
194+
// scan query.
195+
static swiftscan_dependency_graph_t generateHollowDiagnosticOutput(
196+
const DependencyScanDiagnosticCollector &ScanDiagnosticConsumer) {
197+
// Create a dependency graph instance
198+
swiftscan_dependency_graph_t hollowResult = new swiftscan_dependency_graph_s;
199+
200+
// Populate the `modules` with a single info for the main module
201+
// containing no dependencies
202+
swiftscan_dependency_set_t *dependencySet = new swiftscan_dependency_set_t;
203+
dependencySet->count = 1;
204+
dependencySet->modules = new swiftscan_dependency_info_t[1];
205+
swiftscan_dependency_info_s *hollowMainModuleInfo =
206+
new swiftscan_dependency_info_s;
207+
dependencySet->modules[0] = hollowMainModuleInfo;
208+
hollowResult->dependencies = dependencySet;
209+
210+
// Other main module details empty
211+
hollowMainModuleInfo->direct_dependencies =
212+
c_string_utils::create_empty_set();
213+
hollowMainModuleInfo->source_files = c_string_utils::create_empty_set();
214+
hollowMainModuleInfo->module_path = c_string_utils::create_null();
215+
hollowResult->main_module_name = c_string_utils::create_clone("unknown");
216+
hollowMainModuleInfo->module_name =
217+
c_string_utils::create_clone("swiftTextual:unknown");
218+
219+
// Hollow info details
220+
swiftscan_module_details_s *hollowDetails = new swiftscan_module_details_s;
221+
hollowDetails->kind = SWIFTSCAN_DEPENDENCY_INFO_SWIFT_TEXTUAL;
222+
hollowDetails->swift_textual_details = {c_string_utils::create_null(),
223+
c_string_utils::create_empty_set(),
224+
c_string_utils::create_null(),
225+
c_string_utils::create_empty_set(),
226+
c_string_utils::create_empty_set(),
227+
c_string_utils::create_empty_set(),
228+
c_string_utils::create_empty_set(),
229+
c_string_utils::create_empty_set(),
230+
c_string_utils::create_empty_set(),
231+
c_string_utils::create_null(),
232+
false,
233+
c_string_utils::create_null(),
234+
c_string_utils::create_null(),
235+
c_string_utils::create_null()};
236+
hollowMainModuleInfo->details = hollowDetails;
237+
238+
// Populate the diagnostic info
239+
hollowResult->diagnostics =
240+
mapCollectedDiagnosticsForOutput(&ScanDiagnosticConsumer);
241+
return hollowResult;
242+
}
243+
244+
// Generate an instance of the `swiftscan_import_set_t` which contains no
245+
// imports but captures the diagnostics emitted during the attempted
246+
// scan query.
247+
static swiftscan_import_set_t generateHollowDiagnosticOutputImportSet(
248+
const DependencyScanDiagnosticCollector &ScanDiagnosticConsumer) {
249+
// Create an dependency graph instance
250+
swiftscan_import_set_t hollowResult = new swiftscan_import_set_s;
251+
hollowResult->imports = c_string_utils::create_empty_set();
252+
hollowResult->diagnostics =
253+
mapCollectedDiagnosticsForOutput(&ScanDiagnosticConsumer);
254+
return hollowResult;
255+
}
256+
143257
DependencyScanningTool::DependencyScanningTool()
144258
: ScanningService(std::make_unique<SwiftDependencyScanningService>()),
145259
VersionedPCMInstanceCacheCache(
@@ -148,12 +262,20 @@ DependencyScanningTool::DependencyScanningTool()
148262

149263
llvm::ErrorOr<swiftscan_dependency_graph_t>
150264
DependencyScanningTool::getDependencies(
151-
ArrayRef<const char *> Command, const llvm::StringSet<> &PlaceholderModules,
265+
ArrayRef<const char *> Command,
266+
const llvm::StringSet<> &PlaceholderModules,
152267
StringRef WorkingDirectory) {
268+
// There may be errors as early as in instance initialization, so we must ensure
269+
// we can catch those.
270+
auto ScanDiagnosticConsumer = std::make_shared<DependencyScanDiagnosticCollector>();
271+
153272
// The primary instance used to scan the query Swift source-code
154-
auto QueryContextOrErr = initScannerForAction(Command, WorkingDirectory);
155-
if (std::error_code EC = QueryContextOrErr.getError())
156-
return EC;
273+
auto QueryContextOrErr = initCompilerInstanceForScan(Command,
274+
WorkingDirectory,
275+
ScanDiagnosticConsumer);
276+
if (QueryContextOrErr.getError())
277+
return generateHollowDiagnosticOutput(*ScanDiagnosticConsumer);
278+
157279
auto QueryContext = std::move(*QueryContextOrErr);
158280

159281
// Local scan cache instance, wrapping the shared global cache.
@@ -166,19 +288,24 @@ DependencyScanningTool::getDependencies(
166288
QueryContext.ScanDiagnostics.get(),
167289
cache);
168290
if (DependenciesOrErr.getError())
169-
return std::make_error_code(std::errc::not_supported);
170-
auto Dependencies = std::move(*DependenciesOrErr);
291+
return generateHollowDiagnosticOutput(*ScanDiagnosticConsumer);
171292

172-
return Dependencies;
293+
return std::move(*DependenciesOrErr);
173294
}
174295

175296
llvm::ErrorOr<swiftscan_import_set_t>
176297
DependencyScanningTool::getImports(ArrayRef<const char *> Command,
177298
StringRef WorkingDirectory) {
299+
// There may be errors as early as in instance initialization, so we must ensure
300+
// we can catch those
301+
auto ScanDiagnosticConsumer = std::make_shared<DependencyScanDiagnosticCollector>();
178302
// The primary instance used to scan the query Swift source-code
179-
auto QueryContextOrErr = initScannerForAction(Command, WorkingDirectory);
180-
if (std::error_code EC = QueryContextOrErr.getError())
181-
return EC;
303+
auto QueryContextOrErr = initCompilerInstanceForScan(Command,
304+
WorkingDirectory,
305+
ScanDiagnosticConsumer);
306+
if (QueryContextOrErr.getError())
307+
return generateHollowDiagnosticOutputImportSet(*ScanDiagnosticConsumer);
308+
182309
auto QueryContext = std::move(*QueryContextOrErr);
183310

184311
// Local scan cache instance, wrapping the shared global cache.
@@ -190,10 +317,9 @@ DependencyScanningTool::getImports(ArrayRef<const char *> Command,
190317
QueryContext.ScanDiagnostics.get(),
191318
cache);
192319
if (DependenciesOrErr.getError())
193-
return std::make_error_code(std::errc::not_supported);
194-
auto Dependencies = std::move(*DependenciesOrErr);
320+
return generateHollowDiagnosticOutputImportSet(*ScanDiagnosticConsumer);
195321

196-
return Dependencies;
322+
return std::move(*DependenciesOrErr);
197323
}
198324

199325
std::vector<llvm::ErrorOr<swiftscan_dependency_graph_t>>
@@ -202,10 +328,14 @@ DependencyScanningTool::getDependencies(
202328
const std::vector<BatchScanInput> &BatchInput,
203329
const llvm::StringSet<> &PlaceholderModules, StringRef WorkingDirectory) {
204330
// The primary instance used to scan Swift modules
205-
auto QueryContextOrErr = initScannerForAction(Command, WorkingDirectory);
331+
auto ScanDiagnosticConsumer = std::make_shared<DependencyScanDiagnosticCollector>();
332+
auto QueryContextOrErr = initCompilerInstanceForScan(Command,
333+
WorkingDirectory,
334+
ScanDiagnosticConsumer);
206335
if (std::error_code EC = QueryContextOrErr.getError())
207336
return std::vector<llvm::ErrorOr<swiftscan_dependency_graph_t>>(
208337
BatchInput.size(), std::make_error_code(std::errc::invalid_argument));
338+
209339
auto QueryContext = std::move(*QueryContextOrErr);
210340

211341
// Local scan cache instance, wrapping the shared global cache.
@@ -264,26 +394,26 @@ void DependencyScanningTool::resetDiagnostics() {
264394
}
265395

266396
llvm::ErrorOr<ScanQueryInstance>
267-
DependencyScanningTool::initScannerForAction(
268-
ArrayRef<const char *> Command, StringRef WorkingDirectory) {
397+
DependencyScanningTool::initCompilerInstanceForScan(
398+
ArrayRef<const char *> CommandArgs,
399+
StringRef WorkingDir,
400+
std::shared_ptr<DependencyScanDiagnosticCollector> scannerDiagnosticsCollector) {
269401
// The remainder of this method operates on shared state in the
270402
// scanning service and global LLVM state with:
271403
// llvm::cl::ResetAllOptionOccurrences
272404
llvm::sys::SmartScopedLock<true> Lock(DependencyScanningToolStateLock);
273-
return initCompilerInstanceForScan(Command, WorkingDirectory);
274-
}
405+
// FIXME: Instead, target-info and supported-features queries must use
406+
// `DependencyScanningToolStateLock`, but this currently requires further
407+
// client-side API plumbing.
408+
llvm::sys::SmartScopedLock<true> TargetInfoLock(TargetInfoMutex);
275409

276-
llvm::ErrorOr<ScanQueryInstance>
277-
DependencyScanningTool::initCompilerInstanceForScan(
278-
ArrayRef<const char *> CommandArgs, StringRef WorkingDir) {
279410
// State unique to an individual scan
280411
auto Instance = std::make_unique<CompilerInstance>();
281-
auto ScanDiagnosticConsumer = std::make_unique<DependencyScanDiagnosticCollector>();
282412

283413
// FIXME: The shared CDC must be deprecated once all clients have switched
284414
// to using per-scan diagnostic output embedded in the `swiftscan_dependency_graph_s`
285415
Instance->addDiagnosticConsumer(&CDC);
286-
Instance->addDiagnosticConsumer(ScanDiagnosticConsumer.get());
416+
Instance->addDiagnosticConsumer(scannerDiagnosticsCollector.get());
287417

288418
// Basic error checking on the arguments
289419
if (CommandArgs.empty()) {
@@ -327,6 +457,7 @@ DependencyScanningTool::initCompilerInstanceForScan(
327457
if (Instance->setup(Invocation, InstanceSetupError)) {
328458
return std::make_error_code(std::errc::not_supported);
329459
}
460+
Invocation.getFrontendOptions().LLVMArgs.clear();
330461

331462
// Setup the caching service after the instance finishes setup.
332463
if (ScanningService->setupCachingDependencyScanningService(*Instance))
@@ -335,7 +466,7 @@ DependencyScanningTool::initCompilerInstanceForScan(
335466
(void)Instance->getMainModule();
336467

337468
return ScanQueryInstance{std::move(Instance),
338-
std::move(ScanDiagnosticConsumer)};
469+
scannerDiagnosticsCollector};
339470
}
340471

341472
} // namespace dependencies

lib/DependencyScan/ModuleDependencyScanner.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,8 @@ ModuleDependencyScanningWorker::ModuleDependencyScanningWorker(
195195
ScanASTContext.getModuleInterfaceChecker()),
196196
&DependencyTracker,
197197
ScanCompilerInvocation.getSearchPathOptions().ModuleLoadMode);
198+
199+
llvm::cl::ResetAllOptionOccurrences();
198200
}
199201

200202
ModuleDependencyVector

lib/DependencyScan/ScanDependencies.cpp

Lines changed: 3 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -579,56 +579,6 @@ static void bridgeDependencyIDs(const ArrayRef<ModuleDependencyID> dependencies,
579579
}
580580
}
581581

582-
static swiftscan_diagnostic_set_t *mapCollectedDiagnosticsForOutput(
583-
const SourceManager &SM,
584-
const DependencyScanDiagnosticCollector *diagnosticCollector) {
585-
auto collectedDiagnostics = diagnosticCollector->getDiagnostics();
586-
auto numDiagnostics = collectedDiagnostics.size();
587-
swiftscan_diagnostic_set_t *diagnosticOutput = new swiftscan_diagnostic_set_t;
588-
diagnosticOutput->count = numDiagnostics;
589-
diagnosticOutput->diagnostics =
590-
new swiftscan_diagnostic_info_t[numDiagnostics];
591-
for (size_t i = 0; i < numDiagnostics; ++i) {
592-
const auto &Diagnostic = collectedDiagnostics[i];
593-
swiftscan_diagnostic_info_s *diagnosticInfo =
594-
new swiftscan_diagnostic_info_s;
595-
diagnosticInfo->message =
596-
swift::c_string_utils::create_clone(Diagnostic.Message.c_str());
597-
switch (Diagnostic.Severity) {
598-
case llvm::SourceMgr::DK_Error:
599-
diagnosticInfo->severity = SWIFTSCAN_DIAGNOSTIC_SEVERITY_ERROR;
600-
break;
601-
case llvm::SourceMgr::DK_Warning:
602-
diagnosticInfo->severity = SWIFTSCAN_DIAGNOSTIC_SEVERITY_WARNING;
603-
break;
604-
case llvm::SourceMgr::DK_Note:
605-
diagnosticInfo->severity = SWIFTSCAN_DIAGNOSTIC_SEVERITY_NOTE;
606-
break;
607-
case llvm::SourceMgr::DK_Remark:
608-
diagnosticInfo->severity = SWIFTSCAN_DIAGNOSTIC_SEVERITY_REMARK;
609-
break;
610-
}
611-
612-
if (Diagnostic.ImportLocation.has_value()) {
613-
auto importLocation = Diagnostic.ImportLocation.value();
614-
swiftscan_source_location_s *sourceLoc = new swiftscan_source_location_s;
615-
if (importLocation.bufferIdentifier.empty())
616-
sourceLoc->buffer_identifier = swift::c_string_utils::create_null();
617-
else
618-
sourceLoc->buffer_identifier = swift::c_string_utils::create_clone(
619-
importLocation.bufferIdentifier.c_str());
620-
sourceLoc->line_number = importLocation.lineNumber;
621-
sourceLoc->column_number = importLocation.columnNumber;
622-
diagnosticInfo->source_location = sourceLoc;
623-
} else {
624-
diagnosticInfo->source_location = nullptr;
625-
}
626-
627-
diagnosticOutput->diagnostics[i] = diagnosticInfo;
628-
}
629-
return diagnosticOutput;
630-
}
631-
632582
static swiftscan_dependency_graph_t
633583
generateFullDependencyGraph(const CompilerInstance &instance,
634584
const DependencyScanDiagnosticCollector *diagnosticCollector,
@@ -811,8 +761,7 @@ generateFullDependencyGraph(const CompilerInstance &instance,
811761
result->dependencies = dependencySet;
812762
result->diagnostics =
813763
diagnosticCollector
814-
? mapCollectedDiagnosticsForOutput(instance.getSourceMgr(),
815-
diagnosticCollector)
764+
? mapCollectedDiagnosticsForOutput(diagnosticCollector)
816765
: nullptr;
817766
return result;
818767
}
@@ -1484,13 +1433,11 @@ swift::dependencies::performModulePrescan(CompilerInstance &instance,
14841433
importSet->imports = create_set(importIdentifiers);
14851434
importSet->diagnostics =
14861435
diagnosticCollector
1487-
? mapCollectedDiagnosticsForOutput(instance.getSourceMgr(),
1488-
diagnosticCollector)
1436+
? mapCollectedDiagnosticsForOutput(diagnosticCollector)
14891437
: nullptr;
14901438
importSet->diagnostics =
14911439
diagnosticCollector
1492-
? mapCollectedDiagnosticsForOutput(instance.getSourceMgr(),
1493-
diagnosticCollector)
1440+
? mapCollectedDiagnosticsForOutput(diagnosticCollector)
14941441
: nullptr;
14951442
return importSet;
14961443
}

0 commit comments

Comments
 (0)