diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/Basic/Diagnostic.cpp | 85 | ||||
-rw-r--r-- | clang/lib/Basic/DiagnosticIDs.cpp | 21 | ||||
-rw-r--r-- | clang/lib/Basic/SourceManager.cpp | 23 | ||||
-rw-r--r-- | clang/lib/Frontend/Rewrite/FixItRewriter.cpp | 4 | ||||
-rw-r--r-- | clang/lib/Frontend/TextDiagnosticPrinter.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Sema/Sema.cpp | 19 | ||||
-rw-r--r-- | clang/lib/Sema/SemaBase.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTReader.cpp | 15 |
8 files changed, 100 insertions, 71 deletions
diff --git a/clang/lib/Basic/Diagnostic.cpp b/clang/lib/Basic/Diagnostic.cpp index ffb3cd4..ecff80a 100644 --- a/clang/lib/Basic/Diagnostic.cpp +++ b/clang/lib/Basic/Diagnostic.cpp @@ -126,7 +126,9 @@ void DiagnosticsEngine::Reset(bool soft /*=false*/) { TrapNumErrorsOccurred = 0; TrapNumUnrecoverableErrorsOccurred = 0; + CurDiagID = std::numeric_limits<unsigned>::max(); LastDiagLevel = DiagnosticIDs::Ignored; + DelayedDiagID = 0; if (!soft) { // Clear state related to #pragma diagnostic. @@ -141,6 +143,23 @@ void DiagnosticsEngine::Reset(bool soft /*=false*/) { } } +void DiagnosticsEngine::SetDelayedDiagnostic(unsigned DiagID, StringRef Arg1, + StringRef Arg2, StringRef Arg3) { + if (DelayedDiagID) + return; + + DelayedDiagID = DiagID; + DelayedDiagArg1 = Arg1.str(); + DelayedDiagArg2 = Arg2.str(); + DelayedDiagArg3 = Arg3.str(); +} + +void DiagnosticsEngine::ReportDelayed() { + unsigned ID = DelayedDiagID; + DelayedDiagID = 0; + Report(ID) << DelayedDiagArg1 << DelayedDiagArg2 << DelayedDiagArg3; +} + DiagnosticMapping & DiagnosticsEngine::DiagState::getOrAddMapping(diag::kind Diag) { std::pair<iterator, bool> Result = @@ -484,31 +503,39 @@ void DiagnosticsEngine::setSeverityForAll(diag::Flavor Flavor, } void DiagnosticsEngine::Report(const StoredDiagnostic &storedDiag) { - DiagnosticStorage DiagStorage; + assert(CurDiagID == std::numeric_limits<unsigned>::max() && + "Multiple diagnostics in flight at once!"); + + CurDiagLoc = storedDiag.getLocation(); + CurDiagID = storedDiag.getID(); + DiagStorage.NumDiagArgs = 0; + + DiagStorage.DiagRanges.clear(); DiagStorage.DiagRanges.append(storedDiag.range_begin(), storedDiag.range_end()); + DiagStorage.FixItHints.clear(); DiagStorage.FixItHints.append(storedDiag.fixit_begin(), storedDiag.fixit_end()); assert(Client && "DiagnosticConsumer not set!"); Level DiagLevel = storedDiag.getLevel(); - Diagnostic Info(this, storedDiag.getLocation(), storedDiag.getID(), - DiagStorage, storedDiag.getMessage()); + Diagnostic Info(this, storedDiag.getMessage()); Client->HandleDiagnostic(DiagLevel, Info); if (Client->IncludeInDiagnosticCounts()) { if (DiagLevel == DiagnosticsEngine::Warning) ++NumWarnings; } + + CurDiagID = std::numeric_limits<unsigned>::max(); } -bool DiagnosticsEngine::EmitDiagnostic(const DiagnosticBuilder &DB, - bool Force) { +bool DiagnosticsEngine::EmitCurrentDiagnostic(bool Force) { assert(getClient() && "DiagnosticClient not set!"); bool Emitted; if (Force) { - Diagnostic Info(this, DB); + Diagnostic Info(this); // Figure out the diagnostic level of this message. DiagnosticIDs::Level DiagLevel @@ -517,50 +544,24 @@ bool DiagnosticsEngine::EmitDiagnostic(const DiagnosticBuilder &DB, Emitted = (DiagLevel != DiagnosticIDs::Ignored); if (Emitted) { // Emit the diagnostic regardless of suppression level. - Diags->EmitDiag(*this, DB, DiagLevel); + Diags->EmitDiag(*this, DiagLevel); } } else { // Process the diagnostic, sending the accumulated information to the // DiagnosticConsumer. - Emitted = ProcessDiag(DB); + Emitted = ProcessDiag(); } - return Emitted; -} + // Clear out the current diagnostic object. + Clear(); -DiagnosticBuilder::DiagnosticBuilder(DiagnosticsEngine *DiagObj, - SourceLocation DiagLoc, unsigned DiagID) - : StreamingDiagnostic(DiagObj->DiagAllocator), DiagObj(DiagObj), - DiagLoc(DiagLoc), DiagID(DiagID), IsActive(true) { - assert(DiagObj && "DiagnosticBuilder requires a valid DiagnosticsEngine!"); -} + // If there was a delayed diagnostic, emit it now. + if (!Force && DelayedDiagID) + ReportDelayed(); -DiagnosticBuilder::DiagnosticBuilder(const DiagnosticBuilder &D) - : StreamingDiagnostic() { - DiagLoc = D.DiagLoc; - DiagID = D.DiagID; - FlagValue = D.FlagValue; - DiagObj = D.DiagObj; - DiagStorage = D.DiagStorage; - D.DiagStorage = nullptr; - Allocator = D.Allocator; - IsActive = D.IsActive; - IsForceEmit = D.IsForceEmit; - D.Clear(); + return Emitted; } -Diagnostic::Diagnostic(const DiagnosticsEngine *DO, - const DiagnosticBuilder &DiagBuilder) - : DiagObj(DO), DiagLoc(DiagBuilder.DiagLoc), - DiagID(DiagBuilder.DiagID), FlagValue(DiagBuilder.FlagValue), - DiagStorage(*DiagBuilder.getStorage()) {} - -Diagnostic::Diagnostic(const DiagnosticsEngine *DO, SourceLocation DiagLoc, - unsigned DiagID, const DiagnosticStorage &DiagStorage, - StringRef StoredDiagMessage) - : DiagObj(DO), DiagLoc(DiagLoc), DiagID(DiagID), - DiagStorage(DiagStorage), StoredDiagMessage(StoredDiagMessage) {} - DiagnosticConsumer::~DiagnosticConsumer() = default; void DiagnosticConsumer::HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, @@ -1215,13 +1216,13 @@ bool ForwardingDiagnosticConsumer::IncludeInDiagnosticCounts() const { return Target.IncludeInDiagnosticCounts(); } -DiagStorageAllocator::DiagStorageAllocator() { +PartialDiagnostic::DiagStorageAllocator::DiagStorageAllocator() { for (unsigned I = 0; I != NumCached; ++I) FreeList[I] = Cached + I; NumFreeListEntries = NumCached; } -DiagStorageAllocator::~DiagStorageAllocator() { +PartialDiagnostic::DiagStorageAllocator::~DiagStorageAllocator() { // Don't assert if we are in a CrashRecovery context, as this invariant may // be invalidated during a crash. assert((NumFreeListEntries == NumCached || diff --git a/clang/lib/Basic/DiagnosticIDs.cpp b/clang/lib/Basic/DiagnosticIDs.cpp index 031d9d7..cae6642 100644 --- a/clang/lib/Basic/DiagnosticIDs.cpp +++ b/clang/lib/Basic/DiagnosticIDs.cpp @@ -566,7 +566,7 @@ DiagnosticIDs::getDiagnosticSeverity(unsigned DiagID, SourceLocation Loc, // If explicitly requested, map fatal errors to errors. if (Result == diag::Severity::Fatal && - DiagID != diag::fatal_too_many_errors && Diag.FatalsAsError) + Diag.CurDiagID != diag::fatal_too_many_errors && Diag.FatalsAsError) Result = diag::Severity::Error; bool ShowInSystemHeader = @@ -800,9 +800,8 @@ StringRef DiagnosticIDs::getNearestOption(diag::Flavor Flavor, /// ProcessDiag - This is the method used to report a diagnostic that is /// finally fully formed. -bool DiagnosticIDs::ProcessDiag(DiagnosticsEngine &Diag, - const DiagnosticBuilder &DiagBuilder) const { - Diagnostic Info(&Diag, DiagBuilder); +bool DiagnosticIDs::ProcessDiag(DiagnosticsEngine &Diag) const { + Diagnostic Info(&Diag); assert(Diag.getClient() && "DiagnosticClient not set!"); @@ -868,24 +867,22 @@ bool DiagnosticIDs::ProcessDiag(DiagnosticsEngine &Diag, // stop a flood of bogus errors. if (Diag.ErrorLimit && Diag.NumErrors > Diag.ErrorLimit && DiagLevel == DiagnosticIDs::Error) { - Diag.Report(diag::fatal_too_many_errors); + Diag.SetDelayedDiagnostic(diag::fatal_too_many_errors); return false; } } // Make sure we set FatalErrorOccurred to ensure that the notes from the // diagnostic that caused `fatal_too_many_errors` won't be emitted. - if (Info.getID() == diag::fatal_too_many_errors) + if (Diag.CurDiagID == diag::fatal_too_many_errors) Diag.FatalErrorOccurred = true; // Finally, report it. - EmitDiag(Diag, DiagBuilder, DiagLevel); + EmitDiag(Diag, DiagLevel); return true; } -void DiagnosticIDs::EmitDiag(DiagnosticsEngine &Diag, - const DiagnosticBuilder &DiagBuilder, - Level DiagLevel) const { - Diagnostic Info(&Diag, DiagBuilder); +void DiagnosticIDs::EmitDiag(DiagnosticsEngine &Diag, Level DiagLevel) const { + Diagnostic Info(&Diag); assert(DiagLevel != DiagnosticIDs::Ignored && "Cannot emit ignored diagnostics!"); Diag.Client->HandleDiagnostic((DiagnosticsEngine::Level)DiagLevel, Info); @@ -893,6 +890,8 @@ void DiagnosticIDs::EmitDiag(DiagnosticsEngine &Diag, if (DiagLevel == DiagnosticIDs::Warning) ++Diag.NumWarnings; } + + Diag.CurDiagID = ~0U; } bool DiagnosticIDs::isUnrecoverable(unsigned DiagID) const { diff --git a/clang/lib/Basic/SourceManager.cpp b/clang/lib/Basic/SourceManager.cpp index 65a8a72..d6ec26a 100644 --- a/clang/lib/Basic/SourceManager.cpp +++ b/clang/lib/Basic/SourceManager.cpp @@ -130,8 +130,13 @@ ContentCache::getBufferOrNone(DiagnosticsEngine &Diag, FileManager &FM, // the file could also have been removed during processing. Since we can't // really deal with this situation, just create an empty buffer. if (!BufferOrError) { - Diag.Report(Loc, diag::err_cannot_open_file) - << ContentsEntry->getName() << BufferOrError.getError().message(); + if (Diag.isDiagnosticInFlight()) + Diag.SetDelayedDiagnostic(diag::err_cannot_open_file, + ContentsEntry->getName(), + BufferOrError.getError().message()); + else + Diag.Report(Loc, diag::err_cannot_open_file) + << ContentsEntry->getName() << BufferOrError.getError().message(); return std::nullopt; } @@ -148,7 +153,12 @@ ContentCache::getBufferOrNone(DiagnosticsEngine &Diag, FileManager &FM, // ContentsEntry::getSize() could have the wrong size. Use // MemoryBuffer::getBufferSize() instead. if (Buffer->getBufferSize() >= std::numeric_limits<unsigned>::max()) { - Diag.Report(Loc, diag::err_file_too_large) << ContentsEntry->getName(); + if (Diag.isDiagnosticInFlight()) + Diag.SetDelayedDiagnostic(diag::err_file_too_large, + ContentsEntry->getName()); + else + Diag.Report(Loc, diag::err_file_too_large) + << ContentsEntry->getName(); return std::nullopt; } @@ -158,7 +168,12 @@ ContentCache::getBufferOrNone(DiagnosticsEngine &Diag, FileManager &FM, // have come from a stat cache). if (!ContentsEntry->isNamedPipe() && Buffer->getBufferSize() != (size_t)ContentsEntry->getSize()) { - Diag.Report(Loc, diag::err_file_modified) << ContentsEntry->getName(); + if (Diag.isDiagnosticInFlight()) + Diag.SetDelayedDiagnostic(diag::err_file_modified, + ContentsEntry->getName()); + else + Diag.Report(Loc, diag::err_file_modified) + << ContentsEntry->getName(); return std::nullopt; } diff --git a/clang/lib/Frontend/Rewrite/FixItRewriter.cpp b/clang/lib/Frontend/Rewrite/FixItRewriter.cpp index 7309553..44dfaf2 100644 --- a/clang/lib/Frontend/Rewrite/FixItRewriter.cpp +++ b/clang/lib/Frontend/Rewrite/FixItRewriter.cpp @@ -200,8 +200,10 @@ void FixItRewriter::HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, /// Emit a diagnostic via the adapted diagnostic client. void FixItRewriter::Diag(SourceLocation Loc, unsigned DiagID) { // When producing this diagnostic, we temporarily bypass ourselves, - // and let the downstream client format the diagnostic. + // clear out any current diagnostic, and let the downstream client + // format the diagnostic. Diags.setClient(Client, false); + Diags.Clear(); Diags.Report(Loc, DiagID); Diags.setClient(this, false); } diff --git a/clang/lib/Frontend/TextDiagnosticPrinter.cpp b/clang/lib/Frontend/TextDiagnosticPrinter.cpp index 28f7218..c2fea3d 100644 --- a/clang/lib/Frontend/TextDiagnosticPrinter.cpp +++ b/clang/lib/Frontend/TextDiagnosticPrinter.cpp @@ -84,7 +84,7 @@ static void printDiagnosticOptions(raw_ostream &OS, if (!Opt.empty()) { OS << (Started ? "," : " [") << (Level == DiagnosticsEngine::Remark ? "-R" : "-W") << Opt; - StringRef OptValue = Info.getFlagValue(); + StringRef OptValue = Info.getDiags()->getFlagValue(); if (!OptValue.empty()) OS << "=" << OptValue; Started = true; diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp index e950ad6..d567de7 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -1589,7 +1589,7 @@ LangAS Sema::getDefaultCXXMethodAddrSpace() const { return LangAS::Default; } -void Sema::EmitDiagnostic(unsigned DiagID, const DiagnosticBuilder &DB) { +void Sema::EmitCurrentDiagnostic(unsigned DiagID) { // FIXME: It doesn't make sense to me that DiagID is an incoming argument here // and yet we also use the current diag ID on the DiagnosticsEngine. This has // been made more painfully obvious by the refactor that introduced this @@ -1597,9 +1597,9 @@ void Sema::EmitDiagnostic(unsigned DiagID, const DiagnosticBuilder &DB) { // eliminated. If it truly cannot be (for example, there is some reentrancy // issue I am not seeing yet), then there should at least be a clarifying // comment somewhere. - Diagnostic DiagInfo(&Diags, DB); if (std::optional<TemplateDeductionInfo *> Info = isSFINAEContext()) { - switch (DiagnosticIDs::getDiagnosticSFINAEResponse(DiagInfo.getID())) { + switch (DiagnosticIDs::getDiagnosticSFINAEResponse( + Diags.getCurrentDiagID())) { case DiagnosticIDs::SFINAE_Report: // We'll report the diagnostic below. break; @@ -1612,11 +1612,13 @@ void Sema::EmitDiagnostic(unsigned DiagID, const DiagnosticBuilder &DB) { // Make a copy of this suppressed diagnostic and store it with the // template-deduction information. if (*Info && !(*Info)->hasSFINAEDiagnostic()) { + Diagnostic DiagInfo(&Diags); (*Info)->addSFINAEDiagnostic(DiagInfo.getLocation(), PartialDiagnostic(DiagInfo, Context.getDiagAllocator())); } Diags.setLastDiagnosticIgnored(true); + Diags.Clear(); return; case DiagnosticIDs::SFINAE_AccessControl: { @@ -1627,7 +1629,7 @@ void Sema::EmitDiagnostic(unsigned DiagID, const DiagnosticBuilder &DB) { if (!AccessCheckingSFINAE && !getLangOpts().CPlusPlus11) break; - SourceLocation Loc = DiagInfo.getLocation(); + SourceLocation Loc = Diags.getCurrentDiagLoc(); // Suppress this diagnostic. ++NumSFINAEErrors; @@ -1635,13 +1637,16 @@ void Sema::EmitDiagnostic(unsigned DiagID, const DiagnosticBuilder &DB) { // Make a copy of this suppressed diagnostic and store it with the // template-deduction information. if (*Info && !(*Info)->hasSFINAEDiagnostic()) { + Diagnostic DiagInfo(&Diags); (*Info)->addSFINAEDiagnostic(DiagInfo.getLocation(), PartialDiagnostic(DiagInfo, Context.getDiagAllocator())); } Diags.setLastDiagnosticIgnored(true); + Diags.Clear(); - // Now produce a C++98 compatibility warning. + // Now the diagnostic state is clear, produce a C++98 compatibility + // warning. Diag(Loc, diag::warn_cxx98_compat_sfinae_access_control); // The last diagnostic which Sema produced was ignored. Suppress any @@ -1654,12 +1659,14 @@ void Sema::EmitDiagnostic(unsigned DiagID, const DiagnosticBuilder &DB) { // Make a copy of this suppressed diagnostic and store it with the // template-deduction information; if (*Info) { + Diagnostic DiagInfo(&Diags); (*Info)->addSuppressedDiagnostic(DiagInfo.getLocation(), PartialDiagnostic(DiagInfo, Context.getDiagAllocator())); } // Suppress this diagnostic. Diags.setLastDiagnosticIgnored(true); + Diags.Clear(); return; } } @@ -1669,7 +1676,7 @@ void Sema::EmitDiagnostic(unsigned DiagID, const DiagnosticBuilder &DB) { Context.setPrintingPolicy(getPrintingPolicy()); // Emit the diagnostic. - if (!Diags.EmitDiagnostic(DB)) + if (!Diags.EmitCurrentDiagnostic()) return; // If this is not a note, and we're in a template instantiation diff --git a/clang/lib/Sema/SemaBase.cpp b/clang/lib/Sema/SemaBase.cpp index 5c24f21..a2f12d6 100644 --- a/clang/lib/Sema/SemaBase.cpp +++ b/clang/lib/Sema/SemaBase.cpp @@ -26,7 +26,7 @@ SemaBase::ImmediateDiagBuilder::~ImmediateDiagBuilder() { Clear(); // Dispatch to Sema to emit the diagnostic. - SemaRef.EmitDiagnostic(DiagID, *this); + SemaRef.EmitCurrentDiagnostic(DiagID); } PartialDiagnostic SemaBase::PDiag(unsigned DiagID) { diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 7efcc81..4fae6ff 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -1382,7 +1382,7 @@ bool ASTReader::ReadVisibleDeclContextStorage(ModuleFile &M, void ASTReader::Error(StringRef Msg) const { Error(diag::err_fe_pch_malformed, Msg); - if (PP.getLangOpts().Modules && + if (PP.getLangOpts().Modules && !Diags.isDiagnosticInFlight() && !PP.getHeaderSearchInfo().getModuleCachePath().empty()) { Diag(diag::note_module_cache_path) << PP.getHeaderSearchInfo().getModuleCachePath(); @@ -1391,7 +1391,10 @@ void ASTReader::Error(StringRef Msg) const { void ASTReader::Error(unsigned DiagID, StringRef Arg1, StringRef Arg2, StringRef Arg3) const { - Diag(DiagID) << Arg1 << Arg2 << Arg3; + if (Diags.isDiagnosticInFlight()) + Diags.SetDelayedDiagnostic(DiagID, Arg1, Arg2, Arg3); + else + Diag(DiagID) << Arg1 << Arg2 << Arg3; } void ASTReader::Error(llvm::Error &&Err) const { @@ -2710,7 +2713,7 @@ InputFile ASTReader::getInputFile(ModuleFile &F, unsigned ID, bool Complain) { // For an overridden file, there is nothing to validate. if (!Overridden && FileChange.Kind != Change::None) { - if (Complain) { + if (Complain && !Diags.isDiagnosticInFlight()) { // Build a list of the PCH imports that got us here (in reverse). SmallVector<ModuleFile *, 4> ImportStack(1, &F); while (!ImportStack.back()->ImportedBy.empty()) @@ -3686,8 +3689,10 @@ llvm::Error ASTReader::ReadASTBlock(ModuleFile &F, SourceMgr.AllocateLoadedSLocEntries(F.LocalNumSLocEntries, SLocSpaceSize); if (!F.SLocEntryBaseID) { - Diags.Report(SourceLocation(), diag::remark_sloc_usage); - SourceMgr.noteSLocAddressSpaceUsage(Diags); + if (!Diags.isDiagnosticInFlight()) { + Diags.Report(SourceLocation(), diag::remark_sloc_usage); + SourceMgr.noteSLocAddressSpaceUsage(Diags); + } return llvm::createStringError(std::errc::invalid_argument, "ran out of source locations"); } |