diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Basic/Diagnostic.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Basic/Diagnostic.cpp | 191 |
1 files changed, 112 insertions, 79 deletions
diff --git a/contrib/llvm/tools/clang/lib/Basic/Diagnostic.cpp b/contrib/llvm/tools/clang/lib/Basic/Diagnostic.cpp index 7529c47..c355445d 100644 --- a/contrib/llvm/tools/clang/lib/Basic/Diagnostic.cpp +++ b/contrib/llvm/tools/clang/lib/Basic/Diagnostic.cpp @@ -16,6 +16,7 @@ #include "clang/Basic/DiagnosticOptions.h" #include "clang/Basic/IdentifierTable.h" #include "clang/Basic/PartialDiagnostic.h" +#include "clang/Basic/SourceManager.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/CrashRecoveryContext.h" @@ -66,18 +67,12 @@ DiagnosticsEngine::DiagnosticsEngine(IntrusiveRefCntPtr<DiagnosticIDs> diags, ArgToStringCookie = nullptr; AllExtensionsSilenced = 0; - IgnoreAllWarnings = false; - WarningsAsErrors = false; - EnableAllWarnings = false; - ErrorsAsFatal = false; - FatalsAsError = false; - SuppressSystemWarnings = false; + SuppressAfterFatalError = true; SuppressAllDiagnostics = false; ElideType = true; PrintTemplateTree = false; ShowColors = false; ShowOverloads = Ovl_All; - ExtBehavior = diag::Severity::Ignored; ErrorLimit = 0; TemplateBacktraceLimit = 0; @@ -131,13 +126,13 @@ void DiagnosticsEngine::Reset() { // Clear state related to #pragma diagnostic. DiagStates.clear(); - DiagStatePoints.clear(); + DiagStatesByLoc.clear(); DiagStateOnPushStack.clear(); // Create a DiagState and DiagStatePoint representing diagnostic changes // through command-line. DiagStates.emplace_back(); - DiagStatePoints.push_back(DiagStatePoint(&DiagStates.back(), FullSourceLoc())); + DiagStatesByLoc.appendFirst(&DiagStates.back()); } void DiagnosticsEngine::SetDelayedDiagnostic(unsigned DiagID, StringRef Arg1, @@ -151,33 +146,99 @@ void DiagnosticsEngine::SetDelayedDiagnostic(unsigned DiagID, StringRef Arg1, } void DiagnosticsEngine::ReportDelayed() { - Report(DelayedDiagID) << DelayedDiagArg1 << DelayedDiagArg2; + unsigned ID = DelayedDiagID; DelayedDiagID = 0; - DelayedDiagArg1.clear(); - DelayedDiagArg2.clear(); + Report(ID) << DelayedDiagArg1 << DelayedDiagArg2; } -DiagnosticsEngine::DiagStatePointsTy::iterator -DiagnosticsEngine::GetDiagStatePointForLoc(SourceLocation L) const { - assert(!DiagStatePoints.empty()); - assert(DiagStatePoints.front().Loc.isInvalid() && - "Should have created a DiagStatePoint for command-line"); +void DiagnosticsEngine::DiagStateMap::appendFirst( + DiagState *State) { + assert(Files.empty() && "not first"); + FirstDiagState = CurDiagState = State; + CurDiagStateLoc = SourceLocation(); +} + +void DiagnosticsEngine::DiagStateMap::append(SourceManager &SrcMgr, + SourceLocation Loc, + DiagState *State) { + CurDiagState = State; + CurDiagStateLoc = Loc; + + std::pair<FileID, unsigned> Decomp = SrcMgr.getDecomposedLoc(Loc); + unsigned Offset = Decomp.second; + for (File *F = getFile(SrcMgr, Decomp.first); F; + Offset = F->ParentOffset, F = F->Parent) { + F->HasLocalTransitions = true; + auto &Last = F->StateTransitions.back(); + assert(Last.Offset <= Offset && "state transitions added out of order"); + + if (Last.Offset == Offset) { + if (Last.State == State) + break; + Last.State = State; + continue; + } + + F->StateTransitions.push_back({State, Offset}); + } +} - if (!SourceMgr) - return DiagStatePoints.end() - 1; +DiagnosticsEngine::DiagState * +DiagnosticsEngine::DiagStateMap::lookup(SourceManager &SrcMgr, + SourceLocation Loc) const { + // Common case: we have not seen any diagnostic pragmas. + if (Files.empty()) + return FirstDiagState; - FullSourceLoc Loc(L, *SourceMgr); - if (Loc.isInvalid()) - return DiagStatePoints.end() - 1; + std::pair<FileID, unsigned> Decomp = SrcMgr.getDecomposedLoc(Loc); + const File *F = getFile(SrcMgr, Decomp.first); + return F->lookup(Decomp.second); +} + +DiagnosticsEngine::DiagState * +DiagnosticsEngine::DiagStateMap::File::lookup(unsigned Offset) const { + auto OnePastIt = std::upper_bound( + StateTransitions.begin(), StateTransitions.end(), Offset, + [](unsigned Offset, const DiagStatePoint &P) { + return Offset < P.Offset; + }); + assert(OnePastIt != StateTransitions.begin() && "missing initial state"); + return OnePastIt[-1].State; +} + +DiagnosticsEngine::DiagStateMap::File * +DiagnosticsEngine::DiagStateMap::getFile(SourceManager &SrcMgr, + FileID ID) const { + // Get or insert the File for this ID. + auto Range = Files.equal_range(ID); + if (Range.first != Range.second) + return &Range.first->second; + auto &F = Files.insert(Range.first, std::make_pair(ID, File()))->second; + + // We created a new File; look up the diagnostic state at the start of it and + // initialize it. + if (ID.isValid()) { + std::pair<FileID, unsigned> Decomp = SrcMgr.getDecomposedIncludedLoc(ID); + F.Parent = getFile(SrcMgr, Decomp.first); + F.ParentOffset = Decomp.second; + F.StateTransitions.push_back({F.Parent->lookup(Decomp.second), 0}); + } else { + // This is the (imaginary) root file into which we pretend all top-level + // files are included; it descends from the initial state. + // + // FIXME: This doesn't guarantee that we use the same ordering as + // isBeforeInTranslationUnit in the cases where someone invented another + // top-level file and added diagnostic pragmas to it. See the code at the + // end of isBeforeInTranslationUnit for the quirks it deals with. + F.StateTransitions.push_back({FirstDiagState, 0}); + } + return &F; +} - DiagStatePointsTy::iterator Pos = DiagStatePoints.end(); - FullSourceLoc LastStateChangePos = DiagStatePoints.back().Loc; - if (LastStateChangePos.isValid() && - Loc.isBeforeInTranslationUnitThan(LastStateChangePos)) - Pos = std::upper_bound(DiagStatePoints.begin(), DiagStatePoints.end(), - DiagStatePoint(nullptr, Loc)); - --Pos; - return Pos; +void DiagnosticsEngine::PushDiagStatePoint(DiagState *State, + SourceLocation Loc) { + assert(Loc.isValid() && "Adding invalid loc point"); + DiagStatesByLoc.append(*SourceMgr, Loc, State); } void DiagnosticsEngine::setSeverity(diag::kind Diag, diag::Severity Map, @@ -187,65 +248,38 @@ void DiagnosticsEngine::setSeverity(diag::kind Diag, diag::Severity Map, assert((Diags->isBuiltinWarningOrExtension(Diag) || (Map == diag::Severity::Fatal || Map == diag::Severity::Error)) && "Cannot map errors into warnings!"); - assert(!DiagStatePoints.empty()); assert((L.isInvalid() || SourceMgr) && "No SourceMgr for valid location"); - FullSourceLoc Loc = SourceMgr? FullSourceLoc(L, *SourceMgr) : FullSourceLoc(); - FullSourceLoc LastStateChangePos = DiagStatePoints.back().Loc; // Don't allow a mapping to a warning override an error/fatal mapping. + bool WasUpgradedFromWarning = false; if (Map == diag::Severity::Warning) { DiagnosticMapping &Info = GetCurDiagState()->getOrAddMapping(Diag); if (Info.getSeverity() == diag::Severity::Error || - Info.getSeverity() == diag::Severity::Fatal) + Info.getSeverity() == diag::Severity::Fatal) { Map = Info.getSeverity(); + WasUpgradedFromWarning = true; + } } DiagnosticMapping Mapping = makeUserMapping(Map, L); + Mapping.setUpgradedFromWarning(WasUpgradedFromWarning); // Common case; setting all the diagnostics of a group in one place. - if (Loc.isInvalid() || Loc == LastStateChangePos) { - GetCurDiagState()->setMapping(Diag, Mapping); + if ((L.isInvalid() || L == DiagStatesByLoc.getCurDiagStateLoc()) && + DiagStatesByLoc.getCurDiagState()) { + // FIXME: This is theoretically wrong: if the current state is shared with + // some other location (via push/pop) we will change the state for that + // other location as well. This cannot currently happen, as we can't update + // the diagnostic state at the same location at which we pop. + DiagStatesByLoc.getCurDiagState()->setMapping(Diag, Mapping); return; } - // Another common case; modifying diagnostic state in a source location - // after the previous one. - if ((Loc.isValid() && LastStateChangePos.isInvalid()) || - LastStateChangePos.isBeforeInTranslationUnitThan(Loc)) { - // A diagnostic pragma occurred, create a new DiagState initialized with - // the current one and a new DiagStatePoint to record at which location - // the new state became active. - DiagStates.push_back(*GetCurDiagState()); - PushDiagStatePoint(&DiagStates.back(), Loc); - GetCurDiagState()->setMapping(Diag, Mapping); - return; - } - - // We allow setting the diagnostic state in random source order for - // completeness but it should not be actually happening in normal practice. - - DiagStatePointsTy::iterator Pos = GetDiagStatePointForLoc(Loc); - assert(Pos != DiagStatePoints.end()); - - // Update all diagnostic states that are active after the given location. - for (DiagStatePointsTy::iterator - I = Pos+1, E = DiagStatePoints.end(); I != E; ++I) { - I->State->setMapping(Diag, Mapping); - } - - // If the location corresponds to an existing point, just update its state. - if (Pos->Loc == Loc) { - Pos->State->setMapping(Diag, Mapping); - return; - } - - // Create a new state/point and fit it into the vector of DiagStatePoints - // so that the vector is always ordered according to location. - assert(Pos->Loc.isBeforeInTranslationUnitThan(Loc)); - DiagStates.push_back(*Pos->State); - DiagState *NewState = &DiagStates.back(); - NewState->setMapping(Diag, Mapping); - DiagStatePoints.insert(Pos+1, DiagStatePoint(NewState, - FullSourceLoc(Loc, *SourceMgr))); + // A diagnostic pragma occurred, create a new DiagState initialized with + // the current one and a new DiagStatePoint to record at which location + // the new state became active. + DiagStates.push_back(*GetCurDiagState()); + DiagStates.back().setMapping(Diag, Mapping); + PushDiagStatePoint(&DiagStates.back(), L); } bool DiagnosticsEngine::setSeverityForGroup(diag::Flavor Flavor, @@ -302,8 +336,8 @@ bool DiagnosticsEngine::setDiagnosticGroupErrorAsFatal(StringRef Group, return setSeverityForGroup(diag::Flavor::WarningOrError, Group, diag::Severity::Fatal); - // Otherwise, we want to set the diagnostic mapping's "no Werror" bit, and - // potentially downgrade anything already mapped to be an error. + // Otherwise, we want to set the diagnostic mapping's "no Wfatal-errors" bit, + // and potentially downgrade anything already mapped to be a fatal error. // Get the diagnostics in this group. SmallVector<diag::kind, 8> GroupDiags; @@ -385,11 +419,10 @@ bool DiagnosticsEngine::EmitCurrentDiagnostic(bool Force) { } // Clear out the current diagnostic object. - unsigned DiagID = CurDiagID; Clear(); // If there was a delayed diagnostic, emit it now. - if (!Force && DelayedDiagID && DelayedDiagID != DiagID) + if (!Force && DelayedDiagID) ReportDelayed(); return Emitted; |