diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Frontend/VerifyDiagnosticConsumer.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Frontend/VerifyDiagnosticConsumer.cpp | 471 |
1 files changed, 293 insertions, 178 deletions
diff --git a/contrib/llvm/tools/clang/lib/Frontend/VerifyDiagnosticConsumer.cpp b/contrib/llvm/tools/clang/lib/Frontend/VerifyDiagnosticConsumer.cpp index 552282d..a9378a1 100644 --- a/contrib/llvm/tools/clang/lib/Frontend/VerifyDiagnosticConsumer.cpp +++ b/contrib/llvm/tools/clang/lib/Frontend/VerifyDiagnosticConsumer.cpp @@ -11,58 +11,108 @@ // //===----------------------------------------------------------------------===// +#include "clang/Basic/FileManager.h" #include "clang/Frontend/VerifyDiagnosticConsumer.h" #include "clang/Frontend/FrontendDiagnostic.h" #include "clang/Frontend/TextDiagnosticBuffer.h" +#include "clang/Lex/HeaderSearch.h" #include "clang/Lex/Preprocessor.h" #include "llvm/ADT/SmallString.h" #include "llvm/Support/Regex.h" #include "llvm/Support/raw_ostream.h" -#include <climits> +#include <cctype> using namespace clang; +typedef VerifyDiagnosticConsumer::Directive Directive; +typedef VerifyDiagnosticConsumer::DirectiveList DirectiveList; +typedef VerifyDiagnosticConsumer::ExpectedData ExpectedData; VerifyDiagnosticConsumer::VerifyDiagnosticConsumer(DiagnosticsEngine &_Diags) - : Diags(_Diags), PrimaryClient(Diags.getClient()), - OwnsPrimaryClient(Diags.ownsClient()), - Buffer(new TextDiagnosticBuffer()), CurrentPreprocessor(0) + : Diags(_Diags), + PrimaryClient(Diags.getClient()), OwnsPrimaryClient(Diags.ownsClient()), + Buffer(new TextDiagnosticBuffer()), CurrentPreprocessor(0), + ActiveSourceFiles(0) { Diags.takeClient(); } VerifyDiagnosticConsumer::~VerifyDiagnosticConsumer() { + assert(!ActiveSourceFiles && "Incomplete parsing of source files!"); + assert(!CurrentPreprocessor && "CurrentPreprocessor should be invalid!"); CheckDiagnostics(); Diags.takeClient(); if (OwnsPrimaryClient) delete PrimaryClient; } +#ifndef NDEBUG +namespace { +class VerifyFileTracker : public PPCallbacks { + typedef VerifyDiagnosticConsumer::FilesParsedForDirectivesSet ListType; + ListType &FilesList; + SourceManager &SM; + +public: + VerifyFileTracker(ListType &FilesList, SourceManager &SM) + : FilesList(FilesList), SM(SM) { } + + /// \brief Hook into the preprocessor and update the list of parsed + /// files when the preprocessor indicates a new file is entered. + virtual void FileChanged(SourceLocation Loc, FileChangeReason Reason, + SrcMgr::CharacteristicKind FileType, + FileID PrevFID) { + if (const FileEntry *E = SM.getFileEntryForID(SM.getFileID(Loc))) + FilesList.insert(E); + } +}; +} // End anonymous namespace. +#endif + // DiagnosticConsumer interface. void VerifyDiagnosticConsumer::BeginSourceFile(const LangOptions &LangOpts, const Preprocessor *PP) { - // FIXME: Const hack, we screw up the preprocessor but in practice its ok - // because it doesn't get reused. It would be better if we could make a copy - // though. - CurrentPreprocessor = const_cast<Preprocessor*>(PP); + // Attach comment handler on first invocation. + if (++ActiveSourceFiles == 1) { + if (PP) { + CurrentPreprocessor = PP; + const_cast<Preprocessor*>(PP)->addCommentHandler(this); +#ifndef NDEBUG + VerifyFileTracker *V = new VerifyFileTracker(FilesParsedForDirectives, + PP->getSourceManager()); + const_cast<Preprocessor*>(PP)->addPPCallbacks(V); +#endif + } + } + assert((!PP || CurrentPreprocessor == PP) && "Preprocessor changed!"); PrimaryClient->BeginSourceFile(LangOpts, PP); } void VerifyDiagnosticConsumer::EndSourceFile() { - CheckDiagnostics(); - + assert(ActiveSourceFiles && "No active source files!"); PrimaryClient->EndSourceFile(); - CurrentPreprocessor = 0; + // Detach comment handler once last active source file completed. + if (--ActiveSourceFiles == 0) { + if (CurrentPreprocessor) + const_cast<Preprocessor*>(CurrentPreprocessor)->removeCommentHandler(this); + + // Check diagnostics once last file completed. + CheckDiagnostics(); + CurrentPreprocessor = 0; + } } void VerifyDiagnosticConsumer::HandleDiagnostic( DiagnosticsEngine::Level DiagLevel, const Diagnostic &Info) { - if (FirstErrorFID.isInvalid() && Info.hasSourceManager()) { - const SourceManager &SM = Info.getSourceManager(); - FirstErrorFID = SM.getFileID(Info.getLocation()); +#ifndef NDEBUG + if (Info.hasSourceManager()) { + FileID FID = Info.getSourceManager().getFileID(Info.getLocation()); + if (!FID.isInvalid()) + FilesWithDiagnostics.insert(FID); } +#endif // Send the diagnostic to the buffer, we will check it once we reach the end // of the source file (or are destructed). Buffer->HandleDiagnostic(DiagLevel, Info); @@ -77,54 +127,21 @@ typedef TextDiagnosticBuffer::const_iterator const_diag_iterator; namespace { -/// Directive - Abstract class representing a parsed verify directive. -/// -class Directive { -public: - static Directive* Create(bool RegexKind, const SourceLocation &Location, - const std::string &Text, unsigned Count); -public: - /// Constant representing one or more matches aka regex "+". - static const unsigned OneOrMoreCount = UINT_MAX; - - SourceLocation Location; - const std::string Text; - unsigned Count; - - virtual ~Directive() { } - - // Returns true if directive text is valid. - // Otherwise returns false and populates E. - virtual bool isValid(std::string &Error) = 0; - - // Returns true on match. - virtual bool Match(const std::string &S) = 0; - -protected: - Directive(const SourceLocation &Location, const std::string &Text, - unsigned Count) - : Location(Location), Text(Text), Count(Count) { } - -private: - Directive(const Directive&); // DO NOT IMPLEMENT - void operator=(const Directive&); // DO NOT IMPLEMENT -}; - /// StandardDirective - Directive with string matching. /// class StandardDirective : public Directive { public: - StandardDirective(const SourceLocation &Location, const std::string &Text, - unsigned Count) - : Directive(Location, Text, Count) { } + StandardDirective(SourceLocation DirectiveLoc, SourceLocation DiagnosticLoc, + StringRef Text, unsigned Min, unsigned Max) + : Directive(DirectiveLoc, DiagnosticLoc, Text, Min, Max) { } virtual bool isValid(std::string &Error) { // all strings are considered valid; even empty ones return true; } - virtual bool Match(const std::string &S) { - return S.find(Text) != std::string::npos; + virtual bool match(StringRef S) { + return S.find(Text) != StringRef::npos; } }; @@ -132,9 +149,9 @@ public: /// class RegexDirective : public Directive { public: - RegexDirective(const SourceLocation &Location, const std::string &Text, - unsigned Count) - : Directive(Location, Text, Count), Regex(Text) { } + RegexDirective(SourceLocation DirectiveLoc, SourceLocation DiagnosticLoc, + StringRef Text, unsigned Min, unsigned Max) + : Directive(DirectiveLoc, DiagnosticLoc, Text, Min, Max), Regex(Text) { } virtual bool isValid(std::string &Error) { if (Regex.isValid(Error)) @@ -142,7 +159,7 @@ public: return false; } - virtual bool Match(const std::string &S) { + virtual bool match(StringRef S) { return Regex.match(S); } @@ -150,30 +167,11 @@ private: llvm::Regex Regex; }; -typedef std::vector<Directive*> DirectiveList; - -/// ExpectedData - owns directive objects and deletes on destructor. -/// -struct ExpectedData { - DirectiveList Errors; - DirectiveList Warnings; - DirectiveList Notes; - - ~ExpectedData() { - DirectiveList* Lists[] = { &Errors, &Warnings, &Notes, 0 }; - for (DirectiveList **PL = Lists; *PL; ++PL) { - DirectiveList * const L = *PL; - for (DirectiveList::iterator I = L->begin(), E = L->end(); I != E; ++I) - delete *I; - } - } -}; - class ParseHelper { public: - ParseHelper(const char *Begin, const char *End) - : Begin(Begin), End(End), C(Begin), P(Begin), PEnd(NULL) { } + ParseHelper(StringRef S) + : Begin(S.begin()), End(S.end()), C(Begin), P(Begin), PEnd(NULL) { } // Return true if string literal is next. bool Next(StringRef S) { @@ -240,78 +238,134 @@ private: /// ParseDirective - Go through the comment and see if it indicates expected /// diagnostics. If so, then put them in the appropriate directive list. /// -static void ParseDirective(const char *CommentStart, unsigned CommentLen, - ExpectedData &ED, Preprocessor &PP, - SourceLocation Pos) { +/// Returns true if any valid directives were found. +static bool ParseDirective(StringRef S, ExpectedData *ED, SourceManager &SM, + SourceLocation Pos, DiagnosticsEngine &Diags) { // A single comment may contain multiple directives. - for (ParseHelper PH(CommentStart, CommentStart+CommentLen); !PH.Done();) { - // search for token: expected + bool FoundDirective = false; + for (ParseHelper PH(S); !PH.Done();) { + // Search for token: expected if (!PH.Search("expected")) break; PH.Advance(); - // next token: - + // Next token: - if (!PH.Next("-")) continue; PH.Advance(); - // next token: { error | warning | note } + // Next token: { error | warning | note } DirectiveList* DL = NULL; if (PH.Next("error")) - DL = &ED.Errors; + DL = ED ? &ED->Errors : NULL; else if (PH.Next("warning")) - DL = &ED.Warnings; + DL = ED ? &ED->Warnings : NULL; else if (PH.Next("note")) - DL = &ED.Notes; + DL = ED ? &ED->Notes : NULL; else continue; PH.Advance(); - // default directive kind + // If a directive has been found but we're not interested + // in storing the directive information, return now. + if (!DL) + return true; + + // Default directive kind. bool RegexKind = false; const char* KindStr = "string"; - // next optional token: - + // Next optional token: - if (PH.Next("-re")) { PH.Advance(); RegexKind = true; KindStr = "regex"; } - // skip optional whitespace + // Next optional token: @ + SourceLocation ExpectedLoc; + if (!PH.Next("@")) { + ExpectedLoc = Pos; + } else { + PH.Advance(); + unsigned Line = 0; + bool FoundPlus = PH.Next("+"); + if (FoundPlus || PH.Next("-")) { + // Relative to current line. + PH.Advance(); + bool Invalid = false; + unsigned ExpectedLine = SM.getSpellingLineNumber(Pos, &Invalid); + if (!Invalid && PH.Next(Line) && (FoundPlus || Line < ExpectedLine)) { + if (FoundPlus) ExpectedLine += Line; + else ExpectedLine -= Line; + ExpectedLoc = SM.translateLineCol(SM.getFileID(Pos), ExpectedLine, 1); + } + } else { + // Absolute line number. + if (PH.Next(Line) && Line > 0) + ExpectedLoc = SM.translateLineCol(SM.getFileID(Pos), Line, 1); + } + + if (ExpectedLoc.isInvalid()) { + Diags.Report(Pos.getLocWithOffset(PH.C-PH.Begin), + diag::err_verify_missing_line) << KindStr; + continue; + } + PH.Advance(); + } + + // Skip optional whitespace. PH.SkipWhitespace(); - // next optional token: positive integer or a '+'. - unsigned Count = 1; - if (PH.Next(Count)) + // Next optional token: positive integer or a '+'. + unsigned Min = 1; + unsigned Max = 1; + if (PH.Next(Min)) { PH.Advance(); - else if (PH.Next("+")) { - Count = Directive::OneOrMoreCount; + // A positive integer can be followed by a '+' meaning min + // or more, or by a '-' meaning a range from min to max. + if (PH.Next("+")) { + Max = Directive::MaxCount; + PH.Advance(); + } else if (PH.Next("-")) { + PH.Advance(); + if (!PH.Next(Max) || Max < Min) { + Diags.Report(Pos.getLocWithOffset(PH.C-PH.Begin), + diag::err_verify_invalid_range) << KindStr; + continue; + } + PH.Advance(); + } else { + Max = Min; + } + } else if (PH.Next("+")) { + // '+' on its own means "1 or more". + Max = Directive::MaxCount; PH.Advance(); } - // skip optional whitespace + // Skip optional whitespace. PH.SkipWhitespace(); - // next token: {{ + // Next token: {{ if (!PH.Next("{{")) { - PP.Diag(Pos.getLocWithOffset(PH.C-PH.Begin), - diag::err_verify_missing_start) << KindStr; + Diags.Report(Pos.getLocWithOffset(PH.C-PH.Begin), + diag::err_verify_missing_start) << KindStr; continue; } PH.Advance(); const char* const ContentBegin = PH.C; // mark content begin - // search for token: }} + // Search for token: }} if (!PH.Search("}}")) { - PP.Diag(Pos.getLocWithOffset(PH.C-PH.Begin), - diag::err_verify_missing_end) << KindStr; + Diags.Report(Pos.getLocWithOffset(PH.C-PH.Begin), + diag::err_verify_missing_end) << KindStr; continue; } const char* const ContentEnd = PH.P; // mark content end PH.Advance(); - // build directive text; convert \n to newlines + // Build directive text; convert \n to newlines. std::string Text; StringRef NewlineStr = "\\n"; StringRef Content(ContentBegin, ContentEnd-ContentBegin); @@ -325,25 +379,83 @@ static void ParseDirective(const char *CommentStart, unsigned CommentLen, if (Text.empty()) Text.assign(ContentBegin, ContentEnd); - // construct new directive - Directive *D = Directive::Create(RegexKind, Pos, Text, Count); + // Construct new directive. + Directive *D = Directive::create(RegexKind, Pos, ExpectedLoc, Text, + Min, Max); std::string Error; - if (D->isValid(Error)) + if (D->isValid(Error)) { DL->push_back(D); - else { - PP.Diag(Pos.getLocWithOffset(ContentBegin-PH.Begin), - diag::err_verify_invalid_content) + FoundDirective = true; + } else { + Diags.Report(Pos.getLocWithOffset(ContentBegin-PH.Begin), + diag::err_verify_invalid_content) << KindStr << Error; } } + + return FoundDirective; } -/// FindExpectedDiags - Lex the main source file to find all of the -// expected errors and warnings. -static void FindExpectedDiags(Preprocessor &PP, ExpectedData &ED, FileID FID) { +/// HandleComment - Hook into the preprocessor and extract comments containing +/// expected errors and warnings. +bool VerifyDiagnosticConsumer::HandleComment(Preprocessor &PP, + SourceRange Comment) { + SourceManager &SM = PP.getSourceManager(); + SourceLocation CommentBegin = Comment.getBegin(); + + const char *CommentRaw = SM.getCharacterData(CommentBegin); + StringRef C(CommentRaw, SM.getCharacterData(Comment.getEnd()) - CommentRaw); + + if (C.empty()) + return false; + + // Fold any "\<EOL>" sequences + size_t loc = C.find('\\'); + if (loc == StringRef::npos) { + ParseDirective(C, &ED, SM, CommentBegin, PP.getDiagnostics()); + return false; + } + + std::string C2; + C2.reserve(C.size()); + + for (size_t last = 0;; loc = C.find('\\', last)) { + if (loc == StringRef::npos || loc == C.size()) { + C2 += C.substr(last); + break; + } + C2 += C.substr(last, loc-last); + last = loc + 1; + + if (C[last] == '\n' || C[last] == '\r') { + ++last; + + // Escape \r\n or \n\r, but not \n\n. + if (last < C.size()) + if (C[last] == '\n' || C[last] == '\r') + if (C[last] != C[last-1]) + ++last; + } else { + // This was just a normal backslash. + C2 += '\\'; + } + } + + if (!C2.empty()) + ParseDirective(C2, &ED, SM, CommentBegin, PP.getDiagnostics()); + return false; +} + +#ifndef NDEBUG +/// \brief Lex the specified source file to determine whether it contains +/// any expected-* directives. As a Lexer is used rather than a full-blown +/// Preprocessor, directives inside skipped #if blocks will still be found. +/// +/// \return true if any directives were found. +static bool findDirectives(const Preprocessor &PP, FileID FID) { // Create a raw lexer to pull all the comments out of FID. if (FID.isInvalid()) - return; + return false; SourceManager& SM = PP.getSourceManager(); // Create a lexer to lex all the tokens of the main file in raw mode. @@ -355,6 +467,7 @@ static void FindExpectedDiags(Preprocessor &PP, ExpectedData &ED, FileID FID) { Token Tok; Tok.setKind(tok::comment); + bool Found = false; while (Tok.isNot(tok::eof)) { RawLex.Lex(Tok); if (!Tok.is(tok::comment)) continue; @@ -363,19 +476,19 @@ static void FindExpectedDiags(Preprocessor &PP, ExpectedData &ED, FileID FID) { if (Comment.empty()) continue; // Find all expected errors/warnings/notes. - ParseDirective(&Comment[0], Comment.size(), ED, PP, Tok.getLocation()); - }; + Found |= ParseDirective(Comment, 0, SM, Tok.getLocation(), + PP.getDiagnostics()); + } + return Found; } - -/// PrintProblem - This takes a diagnostic map of the delta between expected and -/// seen diagnostics. If there's anything in it, then something unexpected -/// happened. Print the map out in a nice format and return "true". If the map -/// is empty and we're not going to print things, then return "false". -/// -static unsigned PrintProblem(DiagnosticsEngine &Diags, SourceManager *SourceMgr, - const_diag_iterator diag_begin, - const_diag_iterator diag_end, - const char *Kind, bool Expected) { +#endif // !NDEBUG + +/// \brief Takes a list of diagnostics that have been generated but not matched +/// by an expected-* directive and produces a diagnostic to the user from this. +static unsigned PrintUnexpected(DiagnosticsEngine &Diags, SourceManager *SourceMgr, + const_diag_iterator diag_begin, + const_diag_iterator diag_end, + const char *Kind) { if (diag_begin == diag_end) return 0; SmallString<256> Fmt; @@ -388,30 +501,32 @@ static unsigned PrintProblem(DiagnosticsEngine &Diags, SourceManager *SourceMgr, OS << ": " << I->second; } - Diags.Report(diag::err_verify_inconsistent_diags) - << Kind << !Expected << OS.str(); + Diags.Report(diag::err_verify_inconsistent_diags).setForceEmit() + << Kind << /*Unexpected=*/true << OS.str(); return std::distance(diag_begin, diag_end); } -static unsigned PrintProblem(DiagnosticsEngine &Diags, SourceManager *SourceMgr, - DirectiveList &DL, const char *Kind, - bool Expected) { +/// \brief Takes a list of diagnostics that were expected to have been generated +/// but were not and produces a diagnostic to the user from this. +static unsigned PrintExpected(DiagnosticsEngine &Diags, SourceManager &SourceMgr, + DirectiveList &DL, const char *Kind) { if (DL.empty()) return 0; SmallString<256> Fmt; llvm::raw_svector_ostream OS(Fmt); for (DirectiveList::iterator I = DL.begin(), E = DL.end(); I != E; ++I) { - Directive& D = **I; - if (D.Location.isInvalid() || !SourceMgr) - OS << "\n (frontend)"; - else - OS << "\n Line " << SourceMgr->getPresumedLineNumber(D.Location); + Directive &D = **I; + OS << "\n Line " << SourceMgr.getPresumedLineNumber(D.DiagnosticLoc); + if (D.DirectiveLoc != D.DiagnosticLoc) + OS << " (directive at " + << SourceMgr.getFilename(D.DirectiveLoc) << ":" + << SourceMgr.getPresumedLineNumber(D.DirectiveLoc) << ")"; OS << ": " << D.Text; } - Diags.Report(diag::err_verify_inconsistent_diags) - << Kind << !Expected << OS.str(); + Diags.Report(diag::err_verify_inconsistent_diags).setForceEmit() + << Kind << /*Unexpected=*/false << OS.str(); return DL.size(); } @@ -428,10 +543,9 @@ static unsigned CheckLists(DiagnosticsEngine &Diags, SourceManager &SourceMgr, for (DirectiveList::iterator I = Left.begin(), E = Left.end(); I != E; ++I) { Directive& D = **I; - unsigned LineNo1 = SourceMgr.getPresumedLineNumber(D.Location); - bool FoundOnce = false; + unsigned LineNo1 = SourceMgr.getPresumedLineNumber(D.DiagnosticLoc); - for (unsigned i = 0; i < D.Count; ++i) { + for (unsigned i = 0; i < D.Max; ++i) { DiagList::iterator II, IE; for (II = Right.begin(), IE = Right.end(); II != IE; ++II) { unsigned LineNo2 = SourceMgr.getPresumedLineNumber(II->first); @@ -439,29 +553,22 @@ static unsigned CheckLists(DiagnosticsEngine &Diags, SourceManager &SourceMgr, continue; const std::string &RightText = II->second; - if (D.Match(RightText)) + if (D.match(RightText)) break; } if (II == IE) { - if (D.Count == D.OneOrMoreCount) { - if (!FoundOnce) - LeftOnly.push_back(*I); - // We are only interested in at least one match, so exit the loop. - break; - } // Not found. + if (i >= D.Min) break; LeftOnly.push_back(*I); } else { // Found. The same cannot be found twice. Right.erase(II); - FoundOnce = true; } } } // Now all that's left in Right are those that were not matched. - unsigned num = PrintProblem(Diags, &SourceMgr, LeftOnly, Label, true); - num += PrintProblem(Diags, &SourceMgr, Right.begin(), Right.end(), - Label, false); + unsigned num = PrintExpected(Diags, SourceMgr, LeftOnly, Label); + num += PrintUnexpected(Diags, &SourceMgr, Right.begin(), Right.end(), Label); return num; } @@ -495,8 +602,6 @@ static unsigned CheckResults(DiagnosticsEngine &Diags, SourceManager &SourceMgr, } void VerifyDiagnosticConsumer::CheckDiagnostics() { - ExpectedData ED; - // Ensure any diagnostics go to the primary client. bool OwnsCurClient = Diags.ownsClient(); DiagnosticConsumer *CurClient = Diags.takeClient(); @@ -506,32 +611,38 @@ void VerifyDiagnosticConsumer::CheckDiagnostics() { // markers. If not then any diagnostics are unexpected. if (CurrentPreprocessor) { SourceManager &SM = CurrentPreprocessor->getSourceManager(); - // Extract expected-error strings from main file. - FindExpectedDiags(*CurrentPreprocessor, ED, SM.getMainFileID()); - // Only check for expectations in other diagnostic locations - // if they are not the main file (via ID or FileEntry) - the main - // file has already been looked at, and its expectations must not - // be added twice. - if (!FirstErrorFID.isInvalid() && FirstErrorFID != SM.getMainFileID() - && (!SM.getFileEntryForID(FirstErrorFID) - || (SM.getFileEntryForID(FirstErrorFID) != - SM.getFileEntryForID(SM.getMainFileID())))) { - FindExpectedDiags(*CurrentPreprocessor, ED, FirstErrorFID); - FirstErrorFID = FileID(); + +#ifndef NDEBUG + // In a debug build, scan through any files that may have been missed + // during parsing and issue a fatal error if directives are contained + // within these files. If a fatal error occurs, this suggests that + // this file is being parsed separately from the main file. + HeaderSearch &HS = CurrentPreprocessor->getHeaderSearchInfo(); + for (FilesWithDiagnosticsSet::iterator I = FilesWithDiagnostics.begin(), + End = FilesWithDiagnostics.end(); + I != End; ++I) { + const FileEntry *E = SM.getFileEntryForID(*I); + // Don't check files already parsed or those handled as modules. + if (E && (FilesParsedForDirectives.count(E) + || HS.findModuleForHeader(E))) + continue; + + if (findDirectives(*CurrentPreprocessor, *I)) + llvm::report_fatal_error(Twine("-verify directives found after rather" + " than during normal parsing of ", + StringRef(E ? E->getName() : "(unknown)"))); } +#endif // Check that the expected diagnostics occurred. NumErrors += CheckResults(Diags, SM, *Buffer, ED); } else { - NumErrors += (PrintProblem(Diags, 0, - Buffer->err_begin(), Buffer->err_end(), - "error", false) + - PrintProblem(Diags, 0, - Buffer->warn_begin(), Buffer->warn_end(), - "warn", false) + - PrintProblem(Diags, 0, - Buffer->note_begin(), Buffer->note_end(), - "note", false)); + NumErrors += (PrintUnexpected(Diags, 0, Buffer->err_begin(), + Buffer->err_end(), "error") + + PrintUnexpected(Diags, 0, Buffer->warn_begin(), + Buffer->warn_end(), "warn") + + PrintUnexpected(Diags, 0, Buffer->note_begin(), + Buffer->note_end(), "note")); } Diags.takeClient(); @@ -539,6 +650,9 @@ void VerifyDiagnosticConsumer::CheckDiagnostics() { // Reset the buffer, we have processed all the diagnostics in it. Buffer.reset(new TextDiagnosticBuffer()); + ED.Errors.clear(); + ED.Warnings.clear(); + ED.Notes.clear(); } DiagnosticConsumer * @@ -549,9 +663,10 @@ VerifyDiagnosticConsumer::clone(DiagnosticsEngine &Diags) const { return new VerifyDiagnosticConsumer(Diags); } -Directive* Directive::Create(bool RegexKind, const SourceLocation &Location, - const std::string &Text, unsigned Count) { +Directive *Directive::create(bool RegexKind, SourceLocation DirectiveLoc, + SourceLocation DiagnosticLoc, StringRef Text, + unsigned Min, unsigned Max) { if (RegexKind) - return new RegexDirective(Location, Text, Count); - return new StandardDirective(Location, Text, Count); + return new RegexDirective(DirectiveLoc, DiagnosticLoc, Text, Min, Max); + return new StandardDirective(DirectiveLoc, DiagnosticLoc, Text, Min, Max); } |