Add ABORT() macro for unconditionally failing ASSERTS

This is necessary to stop MSVC complaining that "not all paths return a value", because
it is not able to infer that the expression `false ? 0 : non_returning_function()`
never returns.

In the process of debugging this I've also slightly simplified the other assert macros and
abort function, so they don't need compiler specific preprocessor-paths anymore.
This commit is contained in:
Johannes Schmidt 2025-11-17 16:55:55 +01:00
parent 9a69dd9a45
commit 4f0a24f8ab
4 changed files with 10 additions and 35 deletions

View file

@ -8,42 +8,17 @@
#ifndef I2_DEBUG
# define ASSERT(expr) ((void)0)
#else /* I2_DEBUG */
# define ASSERT(expr) ((expr) ? 0 : icinga_assert_fail(#expr, __FILE__, __LINE__))
# define ASSERT(expr) ((expr) ? void(0) : icinga_assert_fail(#expr, __FILE__, __LINE__))
#endif /* I2_DEBUG */
#define VERIFY(expr) ((expr) ? 0 : icinga_assert_fail(#expr, __FILE__, __LINE__))
#define VERIFY(expr) ((expr) ? void(0) : icinga_assert_fail(#expr, __FILE__, __LINE__))
#ifdef _MSC_VER
# define NORETURNPRE __declspec(noreturn)
#else /* _MSC_VER */
# define NORETURNPRE
#endif /* _MSC_VER */
#define ABORT(expr) icinga_assert_fail(#expr, __FILE__, __LINE__)
#ifdef __GNUC__
# define NORETURNPOST __attribute__((noreturn))
#else /* __GNUC__ */
# define NORETURNPOST
#endif /* __GNUC__ */
NORETURNPRE int icinga_assert_fail(const char *expr, const char *file, int line) NORETURNPOST;
#ifdef _MSC_VER
# pragma warning( push )
# pragma warning( disable : 4646 ) /* function declared with __declspec(noreturn) has non-void return type */
#endif /* _MSC_VER */
inline int icinga_assert_fail(const char *expr, const char *file, int line)
[[noreturn]] inline void icinga_assert_fail(const char *expr, const char *file, int line) noexcept(true)
{
fprintf(stderr, "%s:%d: assertion failed: %s\n", file, line, expr);
std::abort();
#if !defined(__GNUC__) && !defined(_MSC_VER)
return 0;
#endif /* !defined(__GNUC__) && !defined(_MSC_VER) */
}
#ifdef _MSC_VER
# pragma warning( pop )
#endif /* _MSC_VER */
#endif /* DEBUG_H */

View file

@ -554,7 +554,7 @@ ExpressionResult GetScopeExpression::DoEvaluate(ScriptFrame& frame, DebugHint *d
else if (m_ScopeSpec == ScopeGlobal)
return frame.GetGlobals();
else
VERIFY(!"Invalid scope.");
ABORT("Invalid scope.");
}
static inline

View file

@ -109,6 +109,6 @@ int Checkable::ServiceStateToFlappingFilter(ServiceState state)
case ServiceUnknown:
return StateFilterUnknown;
default:
VERIFY(!"Invalid state type.");
ABORT("Invalid state type.");
}
}

View file

@ -648,7 +648,7 @@ int icinga::ServiceStateToFilter(ServiceState state)
case ServiceUnknown:
return StateFilterUnknown;
default:
VERIFY(!"Invalid state type.");
ABORT("Invalid state type.");
}
}
@ -660,7 +660,7 @@ int icinga::HostStateToFilter(HostState state)
case HostDown:
return StateFilterDown;
default:
VERIFY(!"Invalid state type.");
ABORT("Invalid state type.");
}
}
@ -736,7 +736,7 @@ String Notification::NotificationServiceStateToString(ServiceState state)
case ServiceUnknown:
return "Unknown";
default:
VERIFY(!"Invalid state type.");
ABORT("Invalid state type.");
}
}
@ -748,7 +748,7 @@ String Notification::NotificationHostStateToString(HostState state)
case HostDown:
return "Down";
default:
VERIFY(!"Invalid state type.");
ABORT("Invalid state type.");
}
}