Skip to content

Commit 5036a55

Browse files
beccadaxxymus
authored andcommitted
[Frontend] Allow additional files for diagnostic verifier
This change adds a frontend flag, -verify-additional-file, which can be used to pass extra files directly to the diagnostic verifier. These files are not otherwise considered to be Swift source files; they are not compiled or even properly parsed. This feature can be used to verify diagnostics emitted in non-source files, such as in module interfaces or header files.
1 parent ba00258 commit 5036a55

File tree

7 files changed

+50
-12
lines changed

7 files changed

+50
-12
lines changed

include/swift/Basic/DiagnosticOptions.h

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,10 @@ class DiagnosticOptions {
4141
/// Indicates whether diagnostic passes should be skipped.
4242
bool SkipDiagnosticPasses = false;
4343

44+
/// Additional non-source files which will have diagnostics emitted in them,
45+
/// and which should be scanned for expectations by the diagnostic verifier.
46+
std::vector<std::string> AdditionalVerifierFiles;
47+
4448
/// Keep emitting subsequent diagnostics after a fatal error.
4549
bool ShowDiagnosticsAfterFatalError = false;
4650

@@ -54,22 +58,23 @@ class DiagnosticOptions {
5458
/// Treat all warnings as errors
5559
bool WarningsAsErrors = false;
5660

57-
// When printing diagnostics, include the diagnostic name at the end
61+
/// When printing diagnostics, include the diagnostic name (diag::whatever) at
62+
/// the end.
5863
bool PrintDiagnosticNames = false;
5964

6065
/// If set to true, include educational notes in printed output if available.
6166
/// Educational notes are documentation which supplement diagnostics.
6267
bool PrintEducationalNotes = false;
6368

64-
// If set to true, use the more descriptive experimental formatting style for
65-
// diagnostics.
69+
/// Whether to emit diagnostics in the terse LLVM style or in a more
70+
/// descriptive style that's specific to Swift (currently experimental).
6671
FormattingStyle PrintedFormattingStyle = FormattingStyle::LLVM;
6772

6873
std::string DiagnosticDocumentationPath = "";
6974

7075
std::string LocalizationCode = "";
7176

72-
// Diagnostic messages directory path.
77+
/// Path to a directory of diagnostic localization tables.
7378
std::string LocalizationPath = "";
7479

7580
/// Return a hash code of any components from these options that should

include/swift/Frontend/DiagnosticVerifier.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ class DiagnosticVerifier : public DiagnosticConsumer {
6565
SourceManager &SM;
6666
std::vector<CapturedDiagnosticInfo> CapturedDiagnostics;
6767
ArrayRef<unsigned> BufferIDs;
68+
SmallVector<unsigned, 4> AdditionalBufferIDs;
6869
bool AutoApplyFixes;
6970
bool IgnoreUnknown;
7071

@@ -74,6 +75,10 @@ class DiagnosticVerifier : public DiagnosticConsumer {
7475
: SM(SM), BufferIDs(BufferIDs), AutoApplyFixes(AutoApplyFixes),
7576
IgnoreUnknown(IgnoreUnknown) {}
7677

78+
void appendAdditionalBufferID(unsigned bufferID) {
79+
AdditionalBufferIDs.push_back(bufferID);
80+
}
81+
7782
virtual void handleDiagnostic(SourceManager &SM,
7883
const DiagnosticInfo &Info) override;
7984

include/swift/Frontend/Frontend.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -560,8 +560,11 @@ class CompilerInstance {
560560
bool setUpInputs();
561561
bool setUpASTContextIfNeeded();
562562
void setupStatsReporter();
563-
void setupDiagnosticVerifierIfNeeded();
564563
void setupDependencyTrackerIfNeeded();
564+
565+
/// \return false if successsful, true on error.
566+
bool setupDiagnosticVerifierIfNeeded();
567+
565568
Optional<unsigned> setUpCodeCompletionBuffer();
566569

567570
/// Find a buffer for a given input file and ensure it is recorded in

include/swift/Option/FrontendOptions.td

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,8 @@ def tbd_is_installapi: Flag<["-"], "tbd-is-installapi">,
114114
def verify : Flag<["-"], "verify">,
115115
HelpText<"Verify diagnostics against expected-{error|warning|note} "
116116
"annotations">;
117+
def verify_additional_file : Separate<["-"], "verify-additional-file">,
118+
HelpText<"Verify diagnostics in this file in addition to source files">;
117119
def verify_apply_fixes : Flag<["-"], "verify-apply-fixes">,
118120
HelpText<"Like -verify, but updates the original source file">;
119121
def verify_ignore_unknown: Flag<["-"], "verify-ignore-unknown">,

lib/Frontend/CompilerInvocation.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -957,6 +957,9 @@ static bool ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args,
957957
Opts.ShowDiagnosticsAfterFatalError |=
958958
Args.hasArg(OPT_show_diagnostics_after_fatal);
959959

960+
for (Arg *A : Args.filtered(OPT_verify_additional_file))
961+
Opts.AdditionalVerifierFiles.push_back(A->getValue());
962+
960963
Opts.UseColor |=
961964
Args.hasFlag(OPT_color_diagnostics,
962965
OPT_no_color_diagnostics,

lib/Frontend/DiagnosticVerifier.cpp

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -978,11 +978,13 @@ void DiagnosticVerifier::handleDiagnostic(SourceManager &SM,
978978
bool DiagnosticVerifier::finishProcessing() {
979979
DiagnosticVerifier::Result Result = {false, false};
980980

981-
for (auto &BufferID : BufferIDs) {
982-
DiagnosticVerifier::Result FileResult = verifyFile(BufferID);
983-
Result.HadError |= FileResult.HadError;
984-
Result.HadUnexpectedDiag |= FileResult.HadUnexpectedDiag;
985-
}
981+
ArrayRef<unsigned> BufferIDLists[2] = { BufferIDs, AdditionalBufferIDs };
982+
for (ArrayRef<unsigned> BufferIDList : BufferIDLists)
983+
for (auto &BufferID : BufferIDList) {
984+
DiagnosticVerifier::Result FileResult = verifyFile(BufferID);
985+
Result.HadError |= FileResult.HadError;
986+
Result.HadUnexpectedDiag |= FileResult.HadUnexpectedDiag;
987+
}
986988
if (!IgnoreUnknown) {
987989
bool HadError = verifyUnknown(SM, CapturedDiagnostics);
988990
Result.HadError |= HadError;

lib/Frontend/Frontend.cpp

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -290,15 +290,31 @@ void CompilerInstance::setupStatsReporter() {
290290
Stats = std::move(Reporter);
291291
}
292292

293-
void CompilerInstance::setupDiagnosticVerifierIfNeeded() {
293+
bool CompilerInstance::setupDiagnosticVerifierIfNeeded() {
294294
auto &diagOpts = Invocation.getDiagnosticOptions();
295+
bool hadError = false;
296+
295297
if (diagOpts.VerifyMode != DiagnosticOptions::NoVerify) {
296298
DiagVerifier = std::make_unique<DiagnosticVerifier>(
297299
SourceMgr, InputSourceCodeBufferIDs,
298300
diagOpts.VerifyMode == DiagnosticOptions::VerifyAndApplyFixes,
299301
diagOpts.VerifyIgnoreUnknown);
302+
for (const auto &filename : diagOpts.AdditionalVerifierFiles) {
303+
auto result = getFileSystem().getBufferForFile(filename);
304+
if (!result) {
305+
Diagnostics.diagnose(SourceLoc(), diag::error_open_input_file,
306+
filename, result.getError().message());
307+
hadError |= true;
308+
}
309+
310+
auto bufferID = SourceMgr.addNewSourceBuffer(std::move(result.get()));
311+
DiagVerifier->appendAdditionalBufferID(bufferID);
312+
}
313+
300314
addDiagnosticConsumer(DiagVerifier.get());
301315
}
316+
317+
return hadError;
302318
}
303319

304320
void CompilerInstance::setupDependencyTrackerIfNeeded() {
@@ -347,7 +363,9 @@ bool CompilerInstance::setup(const CompilerInvocation &Invok) {
347363
return true;
348364

349365
setupStatsReporter();
350-
setupDiagnosticVerifierIfNeeded();
366+
367+
if (setupDiagnosticVerifierIfNeeded())
368+
return true;
351369

352370
return false;
353371
}

0 commit comments

Comments
 (0)