Skip to content

Commit 16c01fe

Browse files
authored
Merge pull request swiftlang#30246 from owenv/dependency-verifier-diags
[DependencyVerifier] Route DependencyVerifier diags through DiagnosticEngine
2 parents 2d6f883 + 0ffb727 commit 16c01fe

File tree

2 files changed

+74
-84
lines changed

2 files changed

+74
-84
lines changed

include/swift/AST/DiagnosticsFrontend.def

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -381,6 +381,32 @@ REMARK(interface_file_lock_failure,none,
381381
REMARK(interface_file_lock_timed_out,none,
382382
"timed out waiting to acquire lock file for module interface '%0'", (StringRef))
383383

384+
// Dependency Verifier Diagnostics
385+
ERROR(dependency_cascading_mismatch,none,
386+
"expected %select{cascading|non-cascading}0 dependency; found "
387+
"%select{cascading|non-cascading}1 dependency instead",
388+
(bool, bool))
389+
ERROR(potential_dependency_cascading_mismatch,none,
390+
"expected %select{cascading|non-cascading}0 potential member dependency; "
391+
"found %select{cascading|non-cascading}1 potential member dependency "
392+
"instead", (bool, bool))
393+
ERROR(missing_member_dependency,none,
394+
"expected "
395+
"%select{%error|provided|member|potential member|dynamic member}0 "
396+
"dependency does not exist: %1",
397+
(/*Expectation::Kind*/uint8_t, StringRef))
398+
ERROR(unexpected_dependency,none,
399+
"unexpected %0 %select{%error|%error||potential member|dynamic member}1 "
400+
"dependency: %2", (StringRef, /*Expectation::Kind*/uint8_t, StringRef))
401+
ERROR(unexpected_provided_entity,none,
402+
"unexpected provided entity: %0", (StringRef))
403+
ERROR(negative_expectation_violated,none,
404+
"unexpected dependency exists: %0", (StringRef))
405+
ERROR(expectation_missing_opening_braces,none,
406+
"expected {{ in expectation", ())
407+
ERROR(expectation_missing_closing_braces,none,
408+
"didn't find '}}' to match '{{' in expectation", ())
409+
384410
#ifndef DIAG_NO_UNDEF
385411
# if defined(DIAG)
386412
# undef DIAG

lib/Frontend/DependencyVerifier.cpp

Lines changed: 48 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,10 @@
1818
#include "swift/AST/ASTContext.h"
1919
#include "swift/AST/ASTMangler.h"
2020
#include "swift/AST/ASTPrinter.h"
21+
#include "swift/AST/DiagnosticsFrontend.h"
2122
#include "swift/AST/SourceFile.h"
22-
#include "swift/Demangling/Demangler.h"
2323
#include "swift/Basic/OptionSet.h"
24+
#include "swift/Demangling/Demangler.h"
2425
#include "swift/Frontend/DiagnosticVerifier.h"
2526
#include "swift/Parse/Lexer.h"
2627

@@ -261,7 +262,6 @@ struct Obligation {
261262
class DependencyVerifier {
262263
SourceManager &SM;
263264
const DependencyTracker &DT;
264-
std::vector<llvm::SMDiagnostic> Errors = {};
265265

266266
public:
267267
explicit DependencyVerifier(SourceManager &SM, const DependencyTracker &DT)
@@ -286,7 +286,7 @@ class DependencyVerifier {
286286
ObligationMap &Obs,
287287
NegativeExpectationMap &NegativeExpectations);
288288

289-
bool verifyNegativeExpectations(ObligationMap &Obs,
289+
bool verifyNegativeExpectations(const SourceFile *SF, ObligationMap &Obs,
290290
NegativeExpectationMap &Negs);
291291

292292
bool diagnoseUnfulfilledObligations(const SourceFile *SF, ObligationMap &OM);
@@ -328,29 +328,13 @@ class DependencyVerifier {
328328
}
329329

330330
private:
331-
template <typename... Ts>
332-
inline auto addFormattedDiagnostic(const Expectation &dep, const char *Fmt,
333-
Ts &&... Vals) {
334-
return addFormattedDiagnostic(dep.MessageRange.begin(), Fmt,
335-
std::forward<Ts>(Vals)...);
336-
}
337-
338-
template <typename... Ts>
339-
inline auto addFormattedDiagnostic(const char *Loc, const char *Fmt,
340-
Ts &&... Vals) {
341-
auto loc = SourceLoc(llvm::SMLoc::getFromPointer(Loc));
342-
auto diag =
343-
SM.GetMessage(loc, llvm::SourceMgr::DK_Error,
344-
llvm::formatv(Fmt, std::forward<Ts>(Vals)...), {}, {});
345-
Errors.push_back(diag);
331+
template <typename... ArgTypes>
332+
InFlightDiagnostic
333+
diagnose(DiagnosticEngine &Diags, const char *LocPtr, Diag<ArgTypes...> ID,
334+
typename detail::PassArgument<ArgTypes>::type... Args) const {
335+
auto Loc = SourceLoc(llvm::SMLoc::getFromPointer(LocPtr));
336+
return Diags.diagnose(Loc, ID, std::move(Args)...);
346337
}
347-
348-
void addError(const char *Loc, const Twine &Msg,
349-
ArrayRef<llvm::SMFixIt> FixIts = {}) {
350-
auto loc = SourceLoc(llvm::SMLoc::getFromPointer(Loc));
351-
auto diag = SM.GetMessage(loc, llvm::SourceMgr::DK_Error, Msg, {}, FixIts);
352-
Errors.push_back(diag);
353-
};
354338
};
355339
} // end anonymous namespace
356340

@@ -391,17 +375,19 @@ bool DependencyVerifier::parseExpectations(
391375

392376
// Skip any whitespace before the {{.
393377
MatchStart = MatchStart.substr(MatchStart.find_first_not_of(" \t"));
378+
auto &diags = SF->getASTContext().Diags;
394379

395380
const size_t TextStartIdx = MatchStart.find("{{");
396381
if (TextStartIdx == StringRef::npos) {
397-
addError(MatchStart.data(), "expected {{ in expectation");
382+
diagnose(diags, MatchStart.data(),
383+
diag::expectation_missing_opening_braces);
398384
continue;
399385
}
400386

401387
const size_t End = MatchStart.find("}}");
402388
if (End == StringRef::npos) {
403-
addError(MatchStart.data(),
404-
"didn't find '}}' to match '{{' in expectation");
389+
diagnose(diags, MatchStart.data(),
390+
diag::expectation_missing_closing_braces);
405391
continue;
406392
}
407393

@@ -483,7 +469,7 @@ bool DependencyVerifier::verifyObligations(
483469
ObligationMap &OM, llvm::StringMap<Expectation> &NegativeExpectations) {
484470
auto *tracker = SF->getReferencedNameTracker();
485471
assert(tracker && "Constructed source file without referenced name tracker!");
486-
472+
auto &diags = SF->getASTContext().Diags;
487473
for (auto &expectation : ExpectedDependencies) {
488474
const bool wantsCascade = expectation.isCascading();
489475
switch (expectation.Info.Kind) {
@@ -497,20 +483,18 @@ bool DependencyVerifier::verifyObligations(
497483
[&](Obligation &p) {
498484
const auto haveCascade = p.getCascades();
499485
if (haveCascade != wantsCascade) {
500-
addFormattedDiagnostic(
501-
expectation,
502-
"expected {0} dependency; found {1} dependency instead",
503-
wantsCascade ? "cascading" : "non-cascading",
504-
haveCascade ? "cascading" : "non-cascading");
486+
diagnose(diags, expectation.MessageRange.begin(),
487+
diag::dependency_cascading_mismatch, wantsCascade,
488+
haveCascade);
505489
return p.fail();
506490
}
507491

508492
return p.fullfill();
509493
},
510-
[this](const Expectation &e) {
511-
addFormattedDiagnostic(
512-
e, "expected member dependency does not exist: {0}",
513-
e.MessageRange);
494+
[&](const Expectation &e) {
495+
diagnose(
496+
diags, e.MessageRange.begin(), diag::missing_member_dependency,
497+
static_cast<uint8_t>(expectation.Info.Kind), e.MessageRange);
514498
});
515499
break;
516500
case Expectation::Kind::PotentialMember:
@@ -520,39 +504,36 @@ bool DependencyVerifier::verifyObligations(
520504
assert(p.getName().empty());
521505
const auto haveCascade = p.getCascades();
522506
if (haveCascade != wantsCascade) {
523-
addFormattedDiagnostic(
524-
expectation,
525-
"expected {0} potential member dependency; found {1} "
526-
"potential member dependency instead",
527-
wantsCascade ? "cascading" : "non-cascading",
528-
haveCascade ? "cascading" : "non-cascading");
507+
diagnose(diags, expectation.MessageRange.begin(),
508+
diag::potential_dependency_cascading_mismatch,
509+
wantsCascade, haveCascade);
529510
return p.fail();
530511
}
531512

532513
return p.fullfill();
533514
},
534-
[this](const Expectation &e) {
535-
addFormattedDiagnostic(
536-
e, "expected potential member dependency does not exist: {0}",
537-
e.MessageRange);
515+
[&](const Expectation &e) {
516+
diagnose(
517+
diags, e.MessageRange.begin(), diag::missing_member_dependency,
518+
static_cast<uint8_t>(expectation.Info.Kind), e.MessageRange);
538519
});
539520
break;
540521
case Expectation::Kind::Provides:
541522
matchExpectationOrFail(
542523
OM, expectation, [](Obligation &O) { return O.fullfill(); },
543-
[this](const Expectation &e) {
544-
addFormattedDiagnostic(
545-
e, "expected provided dependency does not exist: {0}",
546-
e.MessageRange);
524+
[&](const Expectation &e) {
525+
diagnose(
526+
diags, e.MessageRange.begin(), diag::missing_member_dependency,
527+
static_cast<uint8_t>(expectation.Info.Kind), e.MessageRange);
547528
});
548529
break;
549530
case Expectation::Kind::DynamicMember:
550531
matchExpectationOrFail(
551532
OM, expectation, [](Obligation &O) { return O.fullfill(); },
552-
[this](const Expectation &e) {
553-
addFormattedDiagnostic(
554-
e, "expected dynamic member dependency does not exist: {0}",
555-
e.MessageRange);
533+
[&](const Expectation &e) {
534+
diagnose(
535+
diags, e.MessageRange.begin(), diag::missing_member_dependency,
536+
static_cast<uint8_t>(expectation.Info.Kind), e.MessageRange);
556537
});
557538
break;
558539
}
@@ -562,16 +543,17 @@ bool DependencyVerifier::verifyObligations(
562543
}
563544

564545
bool DependencyVerifier::verifyNegativeExpectations(
565-
ObligationMap &Obligations, NegativeExpectationMap &NegativeExpectations) {
546+
const SourceFile *SF, ObligationMap &Obligations,
547+
NegativeExpectationMap &NegativeExpectations) {
566548
forEachOwedObligation(Obligations, [&](StringRef key, Obligation &p) {
567549
auto entry = NegativeExpectations.find(key);
568550
if (entry == NegativeExpectations.end()) {
569551
return;
570552
}
571553

572554
auto &expectation = entry->second;
573-
addFormattedDiagnostic(expectation, "unexpected dependency exists: {0}",
574-
expectation.MessageRange);
555+
diagnose(SF->getASTContext().Diags, expectation.MessageRange.begin(),
556+
diag::negative_expectation_violated, expectation.MessageRange);
575557
p.fail();
576558
});
577559
return false;
@@ -581,31 +563,23 @@ bool DependencyVerifier::diagnoseUnfulfilledObligations(
581563
const SourceFile *SF, ObligationMap &Obligations) {
582564
CharSourceRange EntireRange = SM.getRangeForBuffer(*SF->getBufferID());
583565
StringRef InputFile = SM.extractText(EntireRange);
566+
auto &diags = SF->getASTContext().Diags;
584567
forEachOwedObligation(Obligations, [&](StringRef key, Obligation &p) {
585568
// HACK: Diagnosing the end of the buffer will print a carat pointing
586569
// at the file path, but not print any of the buffer's contents, which
587570
// might be misleading.
588-
const char *Loc = InputFile.end();
571+
auto Loc = SourceLoc(llvm::SMLoc::getFromPointer(InputFile.end()));
589572
switch (p.getKind()) {
590573
case Expectation::Kind::Negative:
591574
llvm_unreachable("Obligations may not be negative; only Expectations!");
592575
case Expectation::Kind::Member:
593-
addFormattedDiagnostic(Loc, "unexpected {0} dependency: {1}",
594-
p.describeCascade(), key);
595-
break;
596576
case Expectation::Kind::DynamicMember:
597-
addFormattedDiagnostic(Loc,
598-
"unexpected {0} dynamic member dependency: {1}",
599-
p.describeCascade(), p.getName());
600-
break;
601577
case Expectation::Kind::PotentialMember:
602-
addFormattedDiagnostic(Loc,
603-
"unexpected {0} potential member dependency: {1}",
604-
p.describeCascade(), key);
578+
diags.diagnose(Loc, diag::unexpected_dependency, p.describeCascade(),
579+
static_cast<uint8_t>(p.getKind()), key);
605580
break;
606581
case Expectation::Kind::Provides:
607-
addFormattedDiagnostic(Loc, "unexpected provided entity: {0}",
608-
p.getName());
582+
diags.diagnose(Loc, diag::unexpected_provided_entity, p.getName());
609583
break;
610584
}
611585
});
@@ -629,25 +603,15 @@ bool DependencyVerifier::verifyFile(const SourceFile *SF) {
629603
return true;
630604
}
631605

632-
if (verifyNegativeExpectations(Obligations, Negatives)) {
606+
if (verifyNegativeExpectations(SF, Obligations, Negatives)) {
633607
return true;
634608
}
635609

636610
if (diagnoseUnfulfilledObligations(SF, Obligations)) {
637611
return true;
638612
}
639613

640-
// Sort the diagnostics by location so we get a stable ordering.
641-
std::sort(Errors.begin(), Errors.end(),
642-
[&](const llvm::SMDiagnostic &lhs,
643-
const llvm::SMDiagnostic &rhs) -> bool {
644-
return lhs.getLoc().getPointer() < rhs.getLoc().getPointer();
645-
});
646-
647-
for (auto Err : Errors)
648-
SM.getLLVMSourceMgr().PrintMessage(llvm::errs(), Err);
649-
650-
return !Errors.empty();
614+
return SF->getASTContext().Diags.hadAnyError();
651615
}
652616

653617
//===----------------------------------------------------------------------===//

0 commit comments

Comments
 (0)