aboutsummaryrefslogtreecommitdiff
path: root/clang/lib
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/Basic/Diagnostic.cpp85
-rw-r--r--clang/lib/Basic/DiagnosticIDs.cpp21
-rw-r--r--clang/lib/Basic/SourceManager.cpp23
-rw-r--r--clang/lib/Frontend/Rewrite/FixItRewriter.cpp4
-rw-r--r--clang/lib/Frontend/TextDiagnosticPrinter.cpp2
-rw-r--r--clang/lib/Sema/Sema.cpp19
-rw-r--r--clang/lib/Sema/SemaBase.cpp2
-rw-r--r--clang/lib/Serialization/ASTReader.cpp15
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");
}