28
28
#include " llvm/ADT/SmallString.h"
29
29
#include " llvm/ADT/Twine.h"
30
30
#include " llvm/Support/raw_ostream.h"
31
+
31
32
using namespace swift ;
32
33
34
+ namespace {
33
35
enum class DiagnosticOptions {
34
36
// / No options.
35
37
none,
@@ -46,29 +48,48 @@ enum class DiagnosticOptions {
46
48
Fatal,
47
49
};
48
50
49
- struct StoredDiagnosticInfo {
50
- // / \brief The kind of diagnostic we're dealing with.
51
- DiagnosticKind Kind;
52
-
53
- DiagnosticOptions Options;
51
+ // Reproduce the DiagIDs, as we want both the size and access to the raw ids
52
+ // themselves.
53
+ enum LocalDiagID : uint32_t {
54
+ #define DIAG (KIND, ID, Category, Options, Text, Signature ) ID,
55
+ #include " swift/AST/DiagnosticsAll.def"
56
+ NumDiags
57
+ };
58
+ }
54
59
55
- // FIXME: Category
56
-
57
- // / \brief Text associated with the diagnostic
58
- const char *Text;
60
+ static const char *DiagnosticStrings[] = {
61
+ #define ERROR (ID, Category, Options, Text, Signature ) Text,
62
+ #define WARNING (ID, Category, Options, Text, Signature ) Text,
63
+ #define NOTE (ID, Category, Options, Text, Signature ) Text,
64
+ #include " swift/AST/DiagnosticsAll.def"
65
+ " <not a diagnostic>" ,
59
66
};
60
67
61
- static StoredDiagnosticInfo StoredDiagnosticInfos [] = {
62
- #define ERROR (ID,Category,Options,Text,Signature ) \
63
- { DiagnosticKind::Error, DiagnosticOptions::Options, Text } ,
64
- #define WARNING (ID,Category,Options,Text,Signature ) \
65
- { DiagnosticKind::Warning, DiagnosticOptions::Options, Text } ,
66
- #define NOTE (ID,Category,Options,Text,Signature ) \
67
- { DiagnosticKind::Note, DiagnosticOptions::Options, Text } ,
68
+ static bool DiagnosticPointsToFirstBadToken [] = {
69
+ #define ERROR (ID, Category, Options, Text, Signature ) \
70
+ DiagnosticOptions::Options == DiagnosticOptions::PointsToFirstBadToken ,
71
+ #define WARNING (ID, Category, Options, Text, Signature ) \
72
+ DiagnosticOptions::Options == DiagnosticOptions::PointsToFirstBadToken ,
73
+ #define NOTE (ID, Category, Options, Text, Signature ) \
74
+ DiagnosticOptions::Options == DiagnosticOptions::PointsToFirstBadToken ,
68
75
#include " swift/AST/DiagnosticsAll.def"
69
- { DiagnosticKind::Error, DiagnosticOptions::none, " <not a diagnostic>" }
76
+ " <not a diagnostic>" ,
70
77
};
71
78
79
+ DiagnosticState::DiagnosticState () {
80
+ // Initialize our per-diagnostic state to the default
81
+ perDiagnosticState.resize (LocalDiagID::NumDiags);
82
+ #define ERROR (ID, Category, Options, Text, Signature ) \
83
+ perDiagnosticState[LocalDiagID::ID] = \
84
+ DiagnosticOptions::Options == DiagnosticOptions::Fatal ? Behavior::Fatal \
85
+ : Behavior::Error;
86
+ #define WARNING (ID, Category, Options, Text, Signature ) \
87
+ perDiagnosticState[LocalDiagID::ID] = Behavior::Warning;
88
+ #define NOTE (ID, Category, Options, Text, Signature ) \
89
+ perDiagnosticState[LocalDiagID::ID] = Behavior::Note;
90
+ #include " swift/AST/DiagnosticsAll.def"
91
+ }
92
+
72
93
static CharSourceRange toCharSourceRange (SourceManager &SM, SourceRange SR) {
73
94
return CharSourceRange (SM, SR.Start , Lexer::getLocForEndOfToken (SM, SR.End ));
74
95
}
@@ -175,15 +196,7 @@ void InFlightDiagnostic::flush() {
175
196
}
176
197
177
198
bool DiagnosticEngine::isDiagnosticPointsToFirstBadToken (DiagID ID) const {
178
- const StoredDiagnosticInfo &StoredInfo =
179
- StoredDiagnosticInfos[(unsigned ) ID];
180
- return StoredInfo.Options == DiagnosticOptions::PointsToFirstBadToken;
181
- }
182
-
183
- bool DiagnosticEngine::isDiagnosticFatal (DiagID ID) const {
184
- const StoredDiagnosticInfo &StoredInfo =
185
- StoredDiagnosticInfos[(unsigned ) ID];
186
- return StoredInfo.Options == DiagnosticOptions::Fatal;
199
+ return DiagnosticPointsToFirstBadToken[(unsigned )ID];
187
200
}
188
201
189
202
// / \brief Skip forward to one of the given delimiters.
@@ -443,12 +456,63 @@ static void formatDiagnosticText(StringRef InText,
443
456
(void )Result;
444
457
assert (ArgIndex < Args.size () && " Out-of-range argument index" );
445
458
InText = InText.substr (Length);
446
-
459
+
447
460
// Convert the argument to a string.
448
461
formatDiagnosticArgument (Modifier, ModifierArguments, Args, ArgIndex, Out);
449
462
}
450
463
}
451
464
465
+ static DiagnosticKind toDiagnosticKind (DiagnosticState::Behavior behavior) {
466
+ switch (behavior) {
467
+ case DiagnosticState::Behavior::Unspecified:
468
+ llvm_unreachable (" unspecified behavior" );
469
+ case DiagnosticState::Behavior::Ignore:
470
+ llvm_unreachable (" trying to map an ignored diagnostic" );
471
+ case DiagnosticState::Behavior::Error:
472
+ case DiagnosticState::Behavior::Fatal:
473
+ return DiagnosticKind::Error;
474
+ case DiagnosticState::Behavior::Note:
475
+ return DiagnosticKind::Note;
476
+ case DiagnosticState::Behavior::Warning:
477
+ return DiagnosticKind::Warning;
478
+ }
479
+ }
480
+
481
+ DiagnosticState::Behavior DiagnosticState::determineBehavior (DiagID id) {
482
+ auto set = [this ](DiagnosticState::Behavior lvl) {
483
+ if (lvl == Behavior::Fatal) {
484
+ fatalErrorOccurred = true ;
485
+ anyErrorOccurred = true ;
486
+ } else if (lvl == Behavior::Error) {
487
+ anyErrorOccurred = true ;
488
+ }
489
+
490
+ previousBehavior = lvl;
491
+ return lvl;
492
+ };
493
+
494
+ auto behavior = perDiagnosticState[(unsigned )id];
495
+
496
+ // Notes relating to ignored diagnostics should also be ignored
497
+ if (previousBehavior == Behavior::Ignore && behavior == Behavior::Note)
498
+ return set (Behavior::Ignore);
499
+
500
+ // Suppress diagnostics when in a fatal state, except for follow-on notes
501
+ // about the original fatal diag
502
+ if (fatalErrorOccurred) {
503
+ bool emitAnyways = showDiagnosticsAfterFatalError ||
504
+ (behavior == Behavior::Note &&
505
+ previousBehavior != Behavior::Ignore);
506
+ if (!emitAnyways)
507
+ return set (Behavior::Ignore);
508
+ }
509
+
510
+ if (behavior == Behavior::Warning && ignoreAllWarnings)
511
+ return set (Behavior::Ignore);
512
+
513
+ return set (behavior);
514
+ }
515
+
452
516
void DiagnosticEngine::flushActiveDiagnostic () {
453
517
assert (ActiveDiagnostic && " No active diagnostic to flush" );
454
518
if (TransactionCount == 0 ) {
@@ -467,33 +531,9 @@ void DiagnosticEngine::emitTentativeDiagnostics() {
467
531
}
468
532
469
533
void DiagnosticEngine::emitDiagnostic (const Diagnostic &diagnostic) {
470
- const StoredDiagnosticInfo &StoredInfo
471
- = StoredDiagnosticInfos[(unsigned )diagnostic.getID ()];
472
-
473
- if (FatalState != FatalErrorState::None) {
474
- bool shouldIgnore = true ;
475
- if (StoredInfo.Kind == DiagnosticKind::Note)
476
- shouldIgnore = (FatalState == FatalErrorState::Fatal);
477
- else
478
- FatalState = FatalErrorState::Fatal;
479
-
480
- if (shouldIgnore && !ShowDiagnosticsAfterFatalError) {
481
- return ;
482
- }
483
- }
484
-
485
- // Check whether this is an error.
486
- switch (StoredInfo.Kind ) {
487
- case DiagnosticKind::Error:
488
- HadAnyError = true ;
489
- if (isDiagnosticFatal (diagnostic.getID ()))
490
- FatalState = FatalErrorState::JustEmitted;
491
- break ;
492
-
493
- case DiagnosticKind::Note:
494
- case DiagnosticKind::Warning:
495
- break ;
496
- }
534
+ auto behavior = state.determineBehavior (diagnostic.getID ());
535
+ if (behavior == DiagnosticState::Behavior::Ignore)
536
+ return ;
497
537
498
538
// Figure out the source location.
499
539
SourceLoc loc = diagnostic.getLoc ();
@@ -613,7 +653,7 @@ void DiagnosticEngine::emitDiagnostic(const Diagnostic &diagnostic) {
613
653
llvm::SmallString<256 > Text;
614
654
{
615
655
llvm::raw_svector_ostream Out (Text);
616
- formatDiagnosticText (StoredInfo. Text , diagnostic.getArgs (), Out);
656
+ formatDiagnosticText (DiagnosticStrings[( unsigned )diagnostic. getID ()] , diagnostic.getArgs (), Out);
617
657
}
618
658
619
659
// Pass the diagnostic off to the consumer.
@@ -622,7 +662,7 @@ void DiagnosticEngine::emitDiagnostic(const Diagnostic &diagnostic) {
622
662
Info.Ranges = diagnostic.getRanges ();
623
663
Info.FixIts = diagnostic.getFixIts ();
624
664
for (auto &Consumer : Consumers) {
625
- Consumer->handleDiagnostic (SourceMgr, loc, StoredInfo. Kind , Text, Info);
665
+ Consumer->handleDiagnostic (SourceMgr, loc, toDiagnosticKind (behavior) , Text, Info);
626
666
}
627
667
}
628
668
0 commit comments