diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index a5910ef815..231d0704ad 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -189,6 +189,8 @@ add_library( cmDependsJavaParserHelper.h cmDependsCompiler.cxx cmDependsCompiler.h + cmDiagnosticContext.h + cmDiagnosticContext.cxx cmDiagnostics.h cmDiagnostics.cxx cmDocumentation.cxx diff --git a/Source/cmDiagnosticContext.cxx b/Source/cmDiagnosticContext.cxx new file mode 100644 index 0000000000..665201f03d --- /dev/null +++ b/Source/cmDiagnosticContext.cxx @@ -0,0 +1,14 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file LICENSE.rst or https://cmake.org/licensing for details. */ +#include "cmDiagnosticContext.h" + +#include + +#include "cmStateSnapshot.h" + +void cmDiagnosticContext::RecordDiagnostic(cmDiagnosticCategory category, + cmStateSnapshot const& state) +{ + this->DiagnosticState[category] = state.GetDiagnostic(category); + this->HasState = true; +} diff --git a/Source/cmDiagnosticContext.h b/Source/cmDiagnosticContext.h new file mode 100644 index 0000000000..9f7224404f --- /dev/null +++ b/Source/cmDiagnosticContext.h @@ -0,0 +1,39 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file LICENSE.rst or https://cmake.org/licensing for details. */ +#pragma once + +#include "cmConfigure.h" // IWYU pragma: keep + +#include + +#include "cmDiagnostics.h" +#include "cmListFileCache.h" + +class cmStateSnapshot; + +/** \class cmDiagnosticContext + * \brief Records context for issuing diagnostics + */ +class cmDiagnosticContext +{ +public: + explicit cmDiagnosticContext(cmListFileBacktrace backtrace) + : Backtrace{ std::move(backtrace) } + { + } + cmDiagnosticContext() = default; + cmDiagnosticContext(cmDiagnosticContext&&) = default; + cmDiagnosticContext(cmDiagnosticContext const&) = default; + + void RecordDiagnostic(cmDiagnosticCategory category, + cmStateSnapshot const& state); + + cmListFileBacktrace const& GetBacktrace() const { return this->Backtrace; } + +protected: + friend class cmMessenger; + + cmListFileBacktrace Backtrace; + cmDiagnostics::DiagnosticMap DiagnosticState; + bool HasState = false; +}; diff --git a/Source/cmFLTKWrapUICommand.cxx b/Source/cmFLTKWrapUICommand.cxx index b43eb67943..b0ef2d01a7 100644 --- a/Source/cmFLTKWrapUICommand.cxx +++ b/Source/cmFLTKWrapUICommand.cxx @@ -12,6 +12,7 @@ #include "cmCustomCommandLines.h" #include "cmDiagnostics.h" #include "cmExecutionStatus.h" +#include "cmListFileCache.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" #include "cmRange.h" @@ -19,7 +20,6 @@ #include "cmStringAlgorithms.h" #include "cmSystemTools.h" -class cmListFileBacktrace; class cmTarget; static void FinalAction(cmMakefile& makefile, std::string const& name, diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index 03dceb744e..fbc4253791 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -246,11 +246,11 @@ void cmLocalGenerator::IssueMessage(MessageType type, std::string const& text, this->GetMakefile()->IssueMessage(type, text, bt); } -void cmLocalGenerator::IssueDiagnostic(cmDiagnosticCategory category, - std::string const& text, - cmListFileBacktrace const& bt) const +void cmLocalGenerator::IssueDiagnostic( + cmDiagnosticCategory category, std::string const& text, + cmDiagnosticContext const& context) const { - this->GetMakefile()->IssueDiagnostic(category, text, bt); + this->GetMakefile()->IssueDiagnostic(category, text, context); } void cmLocalGenerator::ComputeObjectMaxPath() diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h index 77f1e30a0f..7a0227e712 100644 --- a/Source/cmLocalGenerator.h +++ b/Source/cmLocalGenerator.h @@ -17,6 +17,7 @@ #include #include "cmCustomCommandTypes.h" +#include "cmDiagnosticContext.h" #include "cmDiagnostics.h" #include "cmGeneratorOptions.h" #include "cmGeneratorTarget.h" @@ -581,10 +582,16 @@ public: void IssueDiagnostic(cmDiagnosticCategory category, std::string const& text) const { - this->IssueDiagnostic(category, text, this->DirectoryBacktrace); + this->IssueDiagnostic(category, text, + cmDiagnosticContext{ this->DirectoryBacktrace }); } void IssueDiagnostic(cmDiagnosticCategory category, std::string const& text, - cmListFileBacktrace const& bt) const; + cmListFileBacktrace const& bt) const + { + this->IssueDiagnostic(category, text, cmDiagnosticContext{ bt }); + } + void IssueDiagnostic(cmDiagnosticCategory category, std::string const& text, + cmDiagnosticContext const& context) const; void CreateEvaluationFileOutputs(); void CreateEvaluationFileOutputs(std::string const& config); diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index e2b454959b..b5a02fe34b 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -228,7 +228,7 @@ void cmMakefile::IssueMessage(MessageType t, std::string const& text, void cmMakefile::IssueDiagnostic(cmDiagnosticCategory category, std::string const& text, - cmListFileBacktrace const& bt) const + cmDiagnosticContext const& context) const { if (!this->ExecutionStatusStack.empty()) { cmDiagnosticAction const action = this->GetDiagnosticAction(category); @@ -237,7 +237,7 @@ void cmMakefile::IssueDiagnostic(cmDiagnosticCategory category, } } this->GetCMakeInstance()->IssueDiagnostic(category, text, - this->GetStateSnapshot(), bt); + this->GetStateSnapshot(), context); } Message::LogLevel cmMakefile::GetCurrentLogLevel() const diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h index 41fff122c8..c8e062ad2d 100644 --- a/Source/cmMakefile.h +++ b/Source/cmMakefile.h @@ -25,6 +25,7 @@ #include "cmAlgorithms.h" #include "cmCustomCommand.h" +#include "cmDiagnosticContext.h" #include "cmDiagnostics.h" #include "cmFindPackageStack.h" #include "cmFunctionBlocker.h" @@ -1047,10 +1048,17 @@ public: void IssueDiagnostic(cmDiagnosticCategory category, std::string const& text) const { - this->IssueDiagnostic(category, text, this->Backtrace); + this->IssueDiagnostic(category, text, + cmDiagnosticContext{ this->Backtrace }); } void IssueDiagnostic(cmDiagnosticCategory category, std::string const& text, - cmListFileBacktrace const& bt) const; + cmListFileBacktrace backtrace) const + { + this->IssueDiagnostic(category, text, + cmDiagnosticContext{ std::move(backtrace) }); + } + void IssueDiagnostic(cmDiagnosticCategory category, std::string const& text, + cmDiagnosticContext const& context) const; Message::LogLevel GetCurrentLogLevel() const; /** Set whether or not to report a CMP0000 violation. */ diff --git a/Source/cmMessenger.cxx b/Source/cmMessenger.cxx index cbfe69f3f8..ebe24166c1 100644 --- a/Source/cmMessenger.cxx +++ b/Source/cmMessenger.cxx @@ -7,6 +7,8 @@ #include #include +#include + #include "cmDocumentationFormatter.h" #include "cmMessageMetadata.h" #include "cmMessageType.h" @@ -161,10 +163,29 @@ void cmMessenger::IssueMessage(MessageType t, std::string const& text, void cmMessenger::IssueDiagnostic(cmDiagnosticCategory category, std::string const& text, - cmStateSnapshot const& context, - cmListFileBacktrace const& backtrace) const + cmStateSnapshot const& fallbackContext, + cmDiagnosticContext const& context) const { - cmDiagnosticAction const action = context.GetDiagnostic(category); + cmDiagnosticAction const action = [&] { + if (context.HasState) { + cmDiagnosticAction const ca = context.DiagnosticState[category]; + if (ca != cmDiagnostics::Undefined) { + return ca; + } + + // If the context has recorded states, but not the state we want, this + // implies that we had the opportunity to record the state and failed to + // do so. Ask users to report this. + std::string msg = + cmStrCat("Stored diagnostic context did not record state for "_s, + cmDiagnostics::GetCategoryString(category), + ". Please report this as a bug.\n"_s); + this->IssueMessage(MessageType::LOG, msg, context.GetBacktrace()); + } + + return fallbackContext.GetDiagnostic(category); + }(); + switch (action) { case cmDiagnostics::FatalError: cmSystemTools::SetFatalErrorOccurred(); @@ -172,10 +193,11 @@ void cmMessenger::IssueDiagnostic(cmDiagnosticCategory category, case cmDiagnostics::SendError: cmSystemTools::SetErrorOccurred(); this->DisplayMessage(MessageType::FATAL_ERROR, category, text, - backtrace); + context.GetBacktrace()); break; case cmDiagnostics::Warn: - this->DisplayMessage(MessageType::WARNING, category, text, backtrace); + this->DisplayMessage(MessageType::WARNING, category, text, + context.GetBacktrace()); break; default: return; diff --git a/Source/cmMessenger.h b/Source/cmMessenger.h index 17e09b7863..60f736b864 100644 --- a/Source/cmMessenger.h +++ b/Source/cmMessenger.h @@ -10,6 +10,7 @@ #include +#include "cmDiagnosticContext.h" #include "cmDiagnostics.h" #include "cmListFileCache.h" #include "cmMessageType.h" // IWYU pragma: keep @@ -33,10 +34,9 @@ public: MessageType type, std::string const& text, cmListFileBacktrace const& backtrace = cmListFileBacktrace()) const; - void IssueDiagnostic( - cmDiagnosticCategory category, std::string const& text, - cmStateSnapshot const& context, - cmListFileBacktrace const& backtrace = cmListFileBacktrace()) const; + void IssueDiagnostic(cmDiagnosticCategory category, std::string const& text, + cmStateSnapshot const& fallbackContext, + cmDiagnosticContext const& context = {}) const; void DisplayMessage(MessageType type, cmDiagnosticCategory category, std::string const& text, diff --git a/Source/cmake.cxx b/Source/cmake.cxx index 2918cd1136..c26ff3f0cf 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -3894,9 +3894,9 @@ void cmake::IssueMessage(MessageType t, std::string const& text, void cmake::IssueDiagnostic(cmDiagnosticCategory category, std::string const& text, cmStateSnapshot const& state, - cmListFileBacktrace const& backtrace) const + cmDiagnosticContext const& context) const { - this->Messenger->IssueDiagnostic(category, text, state, backtrace); + this->Messenger->IssueDiagnostic(category, text, state, context); } std::vector cmake::GetDebugConfigs() diff --git a/Source/cmake.h b/Source/cmake.h index 900cbb44f1..6344339e4f 100644 --- a/Source/cmake.h +++ b/Source/cmake.h @@ -19,6 +19,7 @@ #include #include "cmBuildArgs.h" +#include "cmDiagnosticContext.h" #include "cmDiagnostics.h" #include "cmDocumentationEntry.h" // IWYU pragma: keep #include "cmGeneratedFileStream.h" @@ -605,15 +606,19 @@ public: void IssueMessage( MessageType t, std::string const& text, cmListFileBacktrace const& backtrace = cmListFileBacktrace()) const; - void IssueDiagnostic( - cmDiagnosticCategory category, std::string const& text, - cmStateSnapshot const& state, - cmListFileBacktrace const& backtrace = cmListFileBacktrace()) const; - void IssueDiagnostic( - cmDiagnosticCategory category, std::string const& text, - cmListFileBacktrace const& backtrace = cmListFileBacktrace()) const + void IssueDiagnostic(cmDiagnosticCategory category, std::string const& text, + cmStateSnapshot const& state, + cmDiagnosticContext const& context = {}) const; + void IssueDiagnostic(cmDiagnosticCategory category, std::string const& text, + cmDiagnosticContext const& context = {}) const { - this->IssueDiagnostic(category, text, this->CurrentSnapshot, backtrace); + this->IssueDiagnostic(category, text, this->CurrentSnapshot, context); + } + void IssueDiagnostic(cmDiagnosticCategory category, std::string const& text, + cmListFileBacktrace backtrace) const + { + this->IssueDiagnostic(category, text, this->CurrentSnapshot, + cmDiagnosticContext{ std::move(backtrace) }); } //! run the --build option diff --git a/bootstrap b/bootstrap index 56ef84d0ea..2739a0ba16 100755 --- a/bootstrap +++ b/bootstrap @@ -314,6 +314,7 @@ CMAKE_CXX_SOURCES="\ cmDefinePropertyCommand \ cmDefinitions \ cmDiagnostics \ + cmDiagnosticContext \ cmDiscoverTestsCommand \ cmDocumentationFormatter \ cmELF \