Source: Add and use CM_UNREACHABLE macro

In debug builds, we assert and abort to give more useful crashes for
development (i.e., instead of triggering UB). Otherwise, we get the
optimization benefits of `unreachable()` (or the older
platform-specific fallbacks per `cm/utility`).
This commit is contained in:
Tyler Yankee
2026-08-26 13:24:34 -04:00
parent be415ecb74
commit f460a199e3
20 changed files with 87 additions and 56 deletions
+2 -2
View File
@@ -1,6 +1,5 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file LICENSE.rst or https://cmake.org/licensing for details. */
#include <cassert>
#include <map>
#include <string>
@@ -8,6 +7,7 @@
#include "cmCMakePresetsGraph.h"
#include "cmStringAlgorithms.h"
#include "cmUnreachable.h"
template <class T>
cmCMakePresetsGraph::PresetResolveResult<T> cmCMakePresetsGraph::ResolvePreset(
@@ -94,7 +94,7 @@ cm::optional<std::string> cmCMakePresetsGraph::FormatPresetError(
case Status::Success:
return cm::nullopt;
}
assert(false && "Unreachable.");
CM_UNREACHABLE;
return cm::nullopt;
}
+3 -3
View File
@@ -2,8 +2,6 @@
file LICENSE.rst or https://cmake.org/licensing for details. */
#include "cmCryptoHash.h"
#include <cassert>
#include <cm/memory>
#include <cm3p/kwiml/int.h>
@@ -11,6 +9,8 @@
#include "cmsys/FStream.hxx"
#include "cmUnreachable.h"
static unsigned int const cmCryptoHashAlgoToId[] = {
/* clang-format needs this comment to break after the opening brace */
RHASH_MD5, //
@@ -109,7 +109,7 @@ std::string cmCryptoHash::GetHashAlgoName() const
case RHASH_SHA3_512:
return "SHA3_512";
}
assert(false);
CM_UNREACHABLE;
return "UNKNOWN";
}
+5 -5
View File
@@ -2,7 +2,6 @@
file LICENSE.rst or https://cmake.org/licensing for details. */
#include "cmCxxModuleMapper.h"
#include <cassert>
#include <cstddef>
#include <set>
#include <sstream>
@@ -16,6 +15,7 @@
#include "cmScanDepFormat.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmUnreachable.h"
CxxBmiLocation::CxxBmiLocation() = default;
@@ -216,7 +216,7 @@ std::string CxxModuleMapContentMsvc(CxxModuleLocations const& loc,
case LookupMethod::IncludeQuote:
return "-headerUnit:quote"_s;
}
assert(false && "unsupported lookup method");
CM_UNREACHABLE;
return ""_s;
};
@@ -265,7 +265,7 @@ bool CxxModuleUsage::AddReference(std::string const& logical,
case LookupMethod::IncludeQuote:
return "include-quote"_s;
}
assert(false && "unsupported lookup method");
CM_UNREACHABLE;
return ""_s;
};
@@ -432,7 +432,7 @@ std::string CxxModuleMapContent(CxxModuleMapFormat format,
return CxxModuleMapContentMsvc(loc, obj, usages);
}
assert(false);
CM_UNREACHABLE;
return {};
}
@@ -446,6 +446,6 @@ CxxModuleMapMode CxxModuleMapOpenMode(CxxModuleMapFormat format)
return CxxModuleMapMode::Default;
}
assert(false);
CM_UNREACHABLE;
return CxxModuleMapMode::Default;
}
+6 -5
View File
@@ -29,6 +29,7 @@
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTimestamp.h"
#include "cmUnreachable.h"
#include "cmake.h"
#if defined(__clang__) && defined(__has_warning)
@@ -835,7 +836,7 @@ Json::Value cmFileAPI::BuildCodeModel(Object object)
if (object.Version == 2) {
version = BuildVersion(2, CodeModelV2Minor);
} else {
return codemodel; // should be unreachable
CM_UNREACHABLE;
}
return codemodel;
@@ -870,7 +871,7 @@ Json::Value cmFileAPI::BuildConfigureLog(Object object)
if (object.Version == 1) {
version = BuildVersion(1, ConfigureLogV1Minor);
} else {
return configureLog; // should be unreachable
CM_UNREACHABLE;
}
return configureLog;
@@ -904,7 +905,7 @@ Json::Value cmFileAPI::BuildCache(Object object)
if (object.Version == 2) {
version = BuildVersion(2, CacheV2Minor);
} else {
return cache; // should be unreachable
CM_UNREACHABLE;
}
return cache;
@@ -938,7 +939,7 @@ Json::Value cmFileAPI::BuildCMakeFiles(Object object)
if (object.Version == 1) {
version = BuildVersion(1, CMakeFilesV1Minor);
} else {
return cmakeFiles; // should be unreachable
CM_UNREACHABLE;
}
return cmakeFiles;
@@ -972,7 +973,7 @@ Json::Value cmFileAPI::BuildToolchains(Object object)
if (object.Version == 1) {
version = BuildVersion(1, ToolchainsV1Minor);
} else {
return toolchains; // should be unreachable
CM_UNREACHABLE;
}
return toolchains;
+6 -5
View File
@@ -43,6 +43,7 @@
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTargetTypes.h"
#include "cmUnreachable.h"
#include "cmValue.h"
#include "cmVersionMacros.h"
#include "cmWindowsRegistry.h"
@@ -3668,7 +3669,7 @@ void cmFindPackageDebugState::WriteEvent(cmConfigureLog& log,
case pdt::Cps:
return "cps";
}
assert(false);
CM_UNREACHABLE;
return "<UNKNOWN>";
};
@@ -3712,7 +3713,7 @@ void cmFindPackageDebugState::WriteEvent(cmConfigureLog& log,
case cmFindPackageCommand::RequiredStatus::RequiredFromFindVar:
return "required_from_find_variable";
}
assert(false);
CM_UNREACHABLE;
return "<UNKNOWN>";
};
log.BeginObject("settings"_s);
@@ -3749,7 +3750,7 @@ void cmFindPackageDebugState::WriteEvent(cmConfigureLog& log,
case cmFindCommon::RootPathModeBoth:
return "BOTH";
}
assert(false);
CM_UNREACHABLE;
return "<UNKNOWN>";
};
log.BeginObject("paths"_s);
@@ -3789,7 +3790,7 @@ void cmFindPackageDebugState::WriteEvent(cmConfigureLog& log,
case cmFindPackageCommand::FoundPackageMode::Provider:
return "provider";
}
assert(false);
CM_UNREACHABLE;
return "<UNKNOWN>";
};
if (!fpc->ConsideredPaths.empty()) {
@@ -3813,7 +3814,7 @@ void cmFindPackageDebugState::WriteEvent(cmConfigureLog& log,
case cmFindPackageCommand::SearchResult::NotFound:
return "not_found";
}
assert(false);
CM_UNREACHABLE;
return "<UNKNOWN>";
};
+3 -4
View File
@@ -3,7 +3,6 @@
#include "cmGeneratorExpression.h"
#include <algorithm>
#include <cassert>
#include <cstddef>
#include <memory>
#include <stack>
@@ -26,6 +25,7 @@
#include "cmMessageType.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmUnreachable.h"
#include "cmake.h"
cmGeneratorExpression::cmGeneratorExpression(cmake& cmakeInstance,
@@ -283,7 +283,7 @@ static std::string stripExportInterface(
foundGenex = FoundGenex::BuildLocalInterface;
pos += cmStrLen("$<BUILD_LOCAL_INTERFACE:");
} else {
assert(false && "Invalid position found");
CM_UNREACHABLE;
}
nestingLevel = 1;
char const* c = input.data() + pos;
@@ -406,8 +406,7 @@ std::string cmGeneratorExpression::Preprocess(cm::string_view input,
return stripExportInterface(input, context, importPrefix);
}
assert(false &&
"cmGeneratorExpression::Preprocess called with invalid args");
CM_UNREACHABLE;
return std::string();
}
+4 -4
View File
@@ -55,6 +55,7 @@
#include "cmSystemTools.h"
#include "cmTarget.h"
#include "cmTargetTypes.h"
#include "cmUnreachable.h"
#include "cmValue.h"
#include "cmake.h"
@@ -3388,8 +3389,7 @@ static const struct ConfigurationTestNode : public cmGeneratorExpressionNode
return false;
}
// Should be unreachable
assert(false);
CM_UNREACHABLE;
return false;
}();
@@ -5140,7 +5140,7 @@ static cmPolicies::PolicyStatus statusForTarget(cmGeneratorTarget const* tgt,
#undef RETURN_POLICY
assert(false && "Unreachable code. Not a valid policy");
CM_UNREACHABLE;
return cmPolicies::WARN;
}
@@ -5155,7 +5155,7 @@ static cmPolicies::PolicyID policyForString(char const* policy_id)
#undef RETURN_POLICY_ID
assert(false && "Unreachable code. Not a valid policy");
CM_UNREACHABLE;
return cmPolicies::CMPCOUNT;
}
+3 -2
View File
@@ -11,6 +11,7 @@
#include <cmext/memory>
#include "cmGeneratorExpressionEvaluator.h"
#include "cmUnreachable.h"
cmGeneratorExpressionParser::cmGeneratorExpressionParser(
std::vector<cmGeneratorExpressionToken> tokens)
@@ -234,11 +235,11 @@ void cmGeneratorExpressionParser::ParseContent(
if (this->NestingLevel == 0) {
extendText(result, this->it);
} else {
assert(false && "Got unexpected syntax token.");
CM_UNREACHABLE;
}
assert(this->it != this->Tokens.end());
++this->it;
return;
}
assert(false && "Unhandled token in generator expression.");
CM_UNREACHABLE;
}
@@ -30,6 +30,7 @@
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTargetTypes.h"
#include "cmUnreachable.h"
#include "cmValue.h"
namespace {
@@ -136,8 +137,7 @@ char const* getLinkInterfaceDependentProperty(cmGeneratorTarget const* tgt,
{
switch (t) {
case BoolType:
assert(false &&
"String compatibility check function called for boolean");
CM_UNREACHABLE;
return nullptr;
case StringType:
return tgt->GetLinkInterfaceDependentStringProperty(prop, config);
@@ -146,7 +146,7 @@ char const* getLinkInterfaceDependentProperty(cmGeneratorTarget const* tgt,
case NumberMaxType:
return tgt->GetLinkInterfaceDependentNumberMaxProperty(prop, config);
}
assert(false && "Unreachable!");
CM_UNREACHABLE;
return nullptr;
}
@@ -367,7 +367,7 @@ static std::string compatibilityType(CompatibleType t)
case NumberMinType:
return "Numeric minimum compatibility";
}
assert(false && "Unreachable!");
CM_UNREACHABLE;
return "";
}
@@ -381,7 +381,7 @@ static std::string compatibilityAgree(CompatibleType t, bool dominant)
case NumberMinType:
return dominant ? "(Dominant)\n" : "(Ignored)\n";
}
assert(false && "Unreachable!");
CM_UNREACHABLE;
return "";
}
@@ -524,7 +524,7 @@ std::pair<bool, char const*> consistentProperty(char const* lhs,
case NumberMaxType:
return consistentNumberProperty(lhs, rhs, t);
}
assert(false && "Unreachable!");
CM_UNREACHABLE;
return { false, nullptr };
}
@@ -558,7 +558,7 @@ static std::pair<bool, std::string> consistentProperty(std::string const& lhs,
value.first ? std::string(value.second) : null_ptr };
}
}
assert(false && "Unreachable!");
CM_UNREACHABLE;
return { false, null_ptr };
}
+2 -1
View File
@@ -66,6 +66,7 @@
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTargetExport.h"
#include "cmUnreachable.h"
#include "cmValue.h"
#include "cmVersion.h"
#include "cmWorkingDirectory.h"
@@ -2423,7 +2424,7 @@ bool cmGlobalGenerator::UseShortObjectNames(
strategy = this->QtAutogenIntDirStrategy;
break;
default:
assert(false);
CM_UNREACHABLE;
break;
}
return this->SupportsShortObjectNames() &&
+2 -2
View File
@@ -3,7 +3,6 @@
#include "cmGlobalNinjaGenerator.h"
#include <algorithm>
#include <cassert>
#include <cstdio>
#include <functional>
#include <iterator>
@@ -57,6 +56,7 @@
#include "cmTargetTypes.h"
#include "cmTest.h"
#include "cmTestGenerator.h"
#include "cmUnreachable.h"
#include "cmValue.h"
#include "cmVersion.h"
#include "cmake.h"
@@ -3021,7 +3021,7 @@ bool cmGlobalNinjaGenerator::WriteDyndepFile(
case LookupMethod::IncludeQuote:
return "include-quote"_s;
}
assert(false && "unsupported lookup method");
CM_UNREACHABLE;
return ""_s;
};
+2 -2
View File
@@ -3,7 +3,6 @@
#include "cmInstallCommand.h"
#include <algorithm>
#include <cassert>
#include <cstddef>
#include <iterator>
#include <map>
@@ -58,6 +57,7 @@
#include "cmTarget.h"
#include "cmTargetExport.h"
#include "cmTargetTypes.h"
#include "cmUnreachable.h"
#include "cmValue.h"
namespace {
@@ -1490,7 +1490,7 @@ bool HandleImportedRuntimeArtifactsMode(std::vector<std::string> const& args,
}
break;
default:
assert(false && "This should never happen");
CM_UNREACHABLE;
break;
}
@@ -2,7 +2,6 @@
file LICENSE.rst or https://cmake.org/licensing for details. */
#include "cmInstallImportedRuntimeArtifactsGenerator.h"
#include <cassert>
#include <string>
#include <utility>
#include <vector>
@@ -16,6 +15,7 @@
#include "cmLocalGenerator.h"
#include "cmStringAlgorithms.h"
#include "cmTargetTypes.h"
#include "cmUnreachable.h"
namespace {
cmsys::RegularExpression const FrameworkRegularExpression(
@@ -143,7 +143,7 @@ void cmInstallImportedRuntimeArtifactsGenerator::GenerateScriptForConfig(
}
break;
default:
assert(false && "This should never happen");
CM_UNREACHABLE;
break;
}
}
+2 -2
View File
@@ -33,6 +33,7 @@
#include "cmSystemTools.h"
#include "cmTarget.h"
#include "cmTargetTypes.h"
#include "cmUnreachable.h"
#include "cmValue.h"
#include "cmake.h"
@@ -246,8 +247,7 @@ cmInstallTargetGenerator::Files cmInstallTargetGenerator::GetFiles(
case cm::TargetType::INTERFACE_LIBRARY:
// Not reachable. We never create a cmInstallTargetGenerator for
// an INTERFACE_LIBRARY.
assert(false &&
"INTERFACE_LIBRARY targets have no installable outputs.");
CM_UNREACHABLE;
break;
case cm::TargetType::OBJECT_LIBRARY: {
+2 -2
View File
@@ -3,7 +3,6 @@
#include "cmNinjaNormalTargetGenerator.h"
#include <algorithm>
#include <cassert>
#include <iterator>
#include <set>
#include <sstream>
@@ -44,6 +43,7 @@
#include "cmSystemTools.h"
#include "cmTarget.h"
#include "cmTargetTypes.h"
#include "cmUnreachable.h"
#include "cmValue.h"
cmNinjaNormalTargetGenerator::cmNinjaNormalTargetGenerator(
@@ -831,7 +831,7 @@ std::vector<std::string> cmNinjaNormalTargetGenerator::ComputeLinkCmd(
case cm::TargetType::EXECUTABLE:
break;
default:
assert(false && "Unexpected target type");
CM_UNREACHABLE;
}
return std::move(linkCmds.data());
}
+2 -1
View File
@@ -27,6 +27,7 @@
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTargetTypes.h"
#include "cmUnreachable.h"
#include "cmake.h"
namespace cmStateDetail {
@@ -78,7 +79,7 @@ std::string const& cmState::GetTargetTypeName(cm::TargetType targetType)
case cm::TargetType::UNKNOWN_LIBRARY:
return propUNKNOWN_LIBRARY;
}
assert(false && "Unexpected target type");
CM_UNREACHABLE;
return propEmpty;
}
+6 -5
View File
@@ -44,6 +44,7 @@
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTargetPropertyComputer.h"
#include "cmUnreachable.h"
#include "cmValue.h"
#include "cmXcFramework.h"
#include "cmake.h"
@@ -2972,7 +2973,7 @@ bool cmTarget::IsNormal() const
case Visibility::Foreign:
return false;
}
assert(false && "unknown visibility (IsNormal)");
CM_UNREACHABLE;
return false;
}
@@ -2987,7 +2988,7 @@ bool cmTarget::IsSynthetic() const
case Visibility::Foreign:
return false;
}
assert(false && "unknown visibility (IsSynthetic)");
CM_UNREACHABLE;
return false;
}
@@ -3002,7 +3003,7 @@ bool cmTargetInternals::IsImported() const
case cmTarget::Visibility::Generated:
return false;
}
assert(false && "unknown visibility (IsImported)");
CM_UNREACHABLE;
return false;
}
@@ -3022,7 +3023,7 @@ bool cmTarget::IsImportedGloballyVisible() const
case Visibility::Foreign:
return false;
}
assert(false && "unknown visibility (IsImportedGloballyVisible)");
CM_UNREACHABLE;
return false;
}
@@ -3037,7 +3038,7 @@ bool cmTarget::IsForeign() const
case Visibility::ImportedGlobally:
return false;
}
assert(false && "unknown visibility (isForeign)");
CM_UNREACHABLE;
return false;
}
+22
View File
@@ -0,0 +1,22 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file LICENSE.rst or https://cmake.org/licensing for details. */
#pragma once
#if defined(NDEBUG)
# include <cm/utility>
# define CM_UNREACHABLE \
do { \
cm::unreachable(); \
} while (false)
#else
# include <cassert>
# include <cstdlib>
# include <iostream>
# define CM_UNREACHABLE \
do { \
std::cerr << "unreachable code path at " << __FILE__ << ':' << __LINE__ \
<< " in " << __func__ << '\n'; \
assert(false && "unreachable code path"); \
std::abort(); \
} while (false)
#endif
+2 -1
View File
@@ -14,6 +14,7 @@
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmUnreachable.h"
#include "cmVisualStudioSlnData.h"
namespace {
@@ -182,7 +183,7 @@ LineFormat cmVisualStudioSlnParser::State::NextLineFormat() const
case FileStateIgnore:
return LineVerbatim;
default:
assert(false);
CM_UNREACHABLE;
return LineVerbatim;
}
}
+4 -1
View File
@@ -7,6 +7,8 @@
#include <cm/string_view>
#include <cmext/string_view>
#include "cmUnreachable.h"
char const* cmXCodeObject::PBXTypeNames[] = {
/* clang-format needs this comment to break after the opening brace */
"PBXGroup",
@@ -68,7 +70,8 @@ bool cmXCodeObject::IsEmpty() const
case OBJECT:
return this->Object == nullptr;
}
return true; // unreachable, but quiets warnings
CM_UNREACHABLE;
return true;
}
void cmXCodeObject::Indent(int level, std::ostream& out)