Diagnostics: Add class to record state

Create new cmDiagnosticContext used to capture the diagnostic state for
instances when the issuing of a diagnostic might happen at a point far
separated from processing the CMake command ultimately responsible for
the diagnostic. (This is particularly the case for diagnostics that get
emitted during the generation phase.) In such cases, it is preferred
that we record the diagnostic state that pertained when the ultimately
instigating command was processed, so that users can control the
diagnostic in a natural manner.  Copying the entire cmStateSnapshot is
unreasonably expensive; this will provide a lighter-weight mechanism for
capturing the relevant diagnostic state for later use.

Since it is almost universal that the points where we would capture this
state also capture a stack trace (which is likewise used to issue
diagnostics), the new class contains a stack trace, and replaces the
stack trace in some diagnostic calls. (In some instances, an overload
which implicitly converts a stack trace to the new context class is
retained for convenience. These will behave the same, since capturing
diagnostic state is an optional function of the new class.)
This commit is contained in:
Matthew Woehlke committed 2026-05-07 17:10:46 -04:00
1 parent 0556d1cfe9
commit 42c7a97446
13 files changed
+128 -30

No files matched your search

+2
View File
@@ -189,6 +189,8 @@ add_library(
cmDependsJavaParserHelper.h
cmDependsCompiler.cxx
cmDependsCompiler.h
cmDiagnosticContext.h
cmDiagnosticContext.cxx
cmDiagnostics.h
cmDiagnostics.cxx
cmDocumentation.cxx
+14
View File
@@ -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 <array>
#include "cmStateSnapshot.h"
void cmDiagnosticContext::RecordDiagnostic(cmDiagnosticCategory category,
cmStateSnapshot const& state)
{
this->DiagnosticState[category] = state.GetDiagnostic(category);
this->HasState = true;
}
+39
View File
@@ -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 <utility>
#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;
};
+1 -1
View File
@@ -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,
+4 -4
View File
@@ -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()
+9 -2
View File
@@ -17,6 +17,7 @@
#include <cm/optional>
#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);
+2 -2
View File
@@ -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
+10 -2
View File
@@ -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. */
+27 -5
View File
@@ -7,6 +7,8 @@
#include <sstream>
#include <utility>
#include <cmext/string_view>
#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;
+4 -4
View File
@@ -10,6 +10,7 @@
#include <cm/optional>
#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,
+2 -2
View File
@@ -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<std::string> cmake::GetDebugConfigs()
+13 -8
View File
@@ -19,6 +19,7 @@
#include <cmext/string_view>
#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
+1
View File
@@ -314,6 +314,7 @@ CMAKE_CXX_SOURCES="\
cmDefinePropertyCommand \
cmDefinitions \
cmDiagnostics \
cmDiagnosticContext \
cmDiscoverTestsCommand \
cmDocumentationFormatter \
cmELF \