20
20
#include " clang/Lex/Lexer.h"
21
21
#include " clang/Lex/Token.h"
22
22
#include " llvm/ADT/ArrayRef.h"
23
+ #include " llvm/ADT/DenseSet.h"
23
24
#include " llvm/ADT/StringRef.h"
24
25
#include " llvm/ADT/Twine.h"
25
26
#include " llvm/Support/Capacity.h"
@@ -107,8 +108,13 @@ Range diagnosticRange(const clang::Diagnostic &D, const LangOptions &L) {
107
108
return halfOpenToRange (M, R);
108
109
}
109
110
110
- void adjustDiagFromHeader (Diag &D, const clang::Diagnostic &Info,
111
+ // Returns whether the \p D is modified.
112
+ bool adjustDiagFromHeader (Diag &D, const clang::Diagnostic &Info,
111
113
const LangOptions &LangOpts) {
114
+ // We only report diagnostics with at least error severity from headers.
115
+ if (D.Severity < DiagnosticsEngine::Level::Error)
116
+ return false ;
117
+
112
118
const SourceLocation &DiagLoc = Info.getLocation ();
113
119
const SourceManager &SM = Info.getSourceManager ();
114
120
SourceLocation IncludeInMainFile;
@@ -119,13 +125,14 @@ void adjustDiagFromHeader(Diag &D, const clang::Diagnostic &Info,
119
125
IncludeLocation = GetIncludeLoc (IncludeLocation))
120
126
IncludeInMainFile = IncludeLocation;
121
127
if (IncludeInMainFile.isInvalid ())
122
- return ;
128
+ return false ;
123
129
124
130
// Update diag to point at include inside main file.
125
131
D.File = SM.getFileEntryForID (SM.getMainFileID ())->getName ().str ();
126
132
D.Range .start = sourceLocToPosition (SM, IncludeInMainFile);
127
133
D.Range .end = sourceLocToPosition (
128
134
SM, Lexer::getLocForEndOfToken (IncludeInMainFile, 0 , SM, LangOpts));
135
+ D.InsideMainFile = true ;
129
136
130
137
// Add a note that will point to real diagnostic.
131
138
const auto *FE = SM.getFileEntryForID (SM.getFileID (DiagLoc));
@@ -138,6 +145,7 @@ void adjustDiagFromHeader(Diag &D, const clang::Diagnostic &Info,
138
145
139
146
// Update message to mention original file.
140
147
D.Message = llvm::Twine (" in included file: " , D.Message ).str ();
148
+ return true ;
141
149
}
142
150
143
151
bool isInsideMainFile (const clang::Diagnostic &D) {
@@ -465,15 +473,15 @@ void StoreDiags::HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
465
473
}
466
474
467
475
bool InsideMainFile = isInsideMainFile (Info);
476
+ SourceManager &SM = Info.getSourceManager ();
468
477
469
478
auto FillDiagBase = [&](DiagBase &D) {
470
479
D.Range = diagnosticRange (Info, *LangOpts);
471
480
llvm::SmallString<64 > Message;
472
481
Info.FormatDiagnostic (Message);
473
482
D.Message = Message.str ();
474
483
D.InsideMainFile = InsideMainFile;
475
- D.File = Info.getSourceManager ().getFilename (Info.getLocation ());
476
- auto &SM = Info.getSourceManager ();
484
+ D.File = SM.getFilename (Info.getLocation ());
477
485
D.AbsFile = getCanonicalPath (
478
486
SM.getFileEntryForID (SM.getFileID (Info.getLocation ())), SM);
479
487
D.Severity = DiagLevel;
@@ -496,19 +504,18 @@ void StoreDiags::HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
496
504
if (FixIt.RemoveRange .getBegin ().isMacroID () ||
497
505
FixIt.RemoveRange .getEnd ().isMacroID ())
498
506
return false ;
499
- if (!isInsideMainFile (FixIt.RemoveRange .getBegin (),
500
- Info.getSourceManager ()))
507
+ if (!isInsideMainFile (FixIt.RemoveRange .getBegin (), SM))
501
508
return false ;
502
- Edits.push_back (toTextEdit (FixIt, Info. getSourceManager () , *LangOpts));
509
+ Edits.push_back (toTextEdit (FixIt, SM , *LangOpts));
503
510
}
504
511
505
512
llvm::SmallString<64 > Message;
506
513
// If requested and possible, create a message like "change 'foo' to 'bar'".
507
514
if (SyntheticMessage && Info.getNumFixItHints () == 1 ) {
508
515
const auto &FixIt = Info.getFixItHint (0 );
509
516
bool Invalid = false ;
510
- llvm::StringRef Remove = Lexer::getSourceText (
511
- FixIt.RemoveRange , Info. getSourceManager () , *LangOpts, &Invalid);
517
+ llvm::StringRef Remove =
518
+ Lexer::getSourceText ( FixIt.RemoveRange , SM , *LangOpts, &Invalid);
512
519
llvm::StringRef Insert = FixIt.CodeToInsert ;
513
520
if (!Invalid) {
514
521
llvm::raw_svector_ostream M (Message);
@@ -553,7 +560,9 @@ void StoreDiags::HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
553
560
LastDiag = Diag ();
554
561
LastDiag->ID = Info.getID ();
555
562
FillDiagBase (*LastDiag);
556
- adjustDiagFromHeader (*LastDiag, Info, *LangOpts);
563
+ LastDiagWasAdjusted = false ;
564
+ if (!InsideMainFile)
565
+ LastDiagWasAdjusted = adjustDiagFromHeader (*LastDiag, Info, *LangOpts);
557
566
558
567
if (!Info.getFixItHints ().empty ())
559
568
AddFix (true /* try to invent a message instead of repeating the diag */ );
@@ -595,10 +604,9 @@ void StoreDiags::HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
595
604
void StoreDiags::flushLastDiag () {
596
605
if (!LastDiag)
597
606
return ;
598
- // Only keeps diagnostics inside main file or the first one coming from a
599
- // header.
600
- if (mentionsMainFile (*LastDiag) ||
601
- (LastDiag->Severity >= DiagnosticsEngine::Level::Error &&
607
+ if (mentionsMainFile (*LastDiag) &&
608
+ (!LastDiagWasAdjusted ||
609
+ // Only report the first diagnostic coming from each particular header.
602
610
IncludeLinesWithErrors.insert (LastDiag->Range .start .line ).second )) {
603
611
Output.push_back (std::move (*LastDiag));
604
612
} else {
0 commit comments