Fix `noreturn` visibility for Clang Static Analyzer

XMLWordPrintableJSON

    • Type: Task
    • Resolution: Won't Do
    • Priority: Major - P3
    • None
    • Affects Version/s: None
    • Component/s: None
    • None
    • Server Programmability
    • Programmability 2026-02-02
    • None
    • None
    • None
    • None
    • None
    • None
    • None

      The main objective is to make the analyzer aware of our custom assertion functions (e.g. uassert, iassert, invariant) so that it does not take paths that are impossible. I have a PoC that works, but I am sure there is a better way to fix this issue:

      diff --git a/src/mongo/util/assert_util.h b/src/mongo/util/assert_util.h
      index 5b3167edc37..f3e7d8202cd 100644
      --- a/src/mongo/util/assert_util.h
      +++ b/src/mongo/util/assert_util.h
      @@ -491,6 +491,8 @@ MONGO_MOD_PUBLIC_FOR_TECHNICAL_REASONS constexpr T checkNoTrace(
       
       namespace error_details {
       
      +inline bool toBool(Status s) { return s.isOK(); }
      +
       MONGO_MOD_PUBLIC_FOR_TECHNICAL_REASONS inline const Status& makeStatus(const Status& s) {
           return s;
       }
      diff --git a/src/mongo/util/assert_util_core.h b/src/mongo/util/assert_util_core.h
      index f7c1bbfe76a..4fa68ca77ee 100644
      --- a/src/mongo/util/assert_util_core.h
      +++ b/src/mongo/util/assert_util_core.h
      @@ -35,6 +35,7 @@
       #include "mongo/util/modules.h"
       
       #include <string>
      +#include <utility>
       
       /**
        * This header is separated from assert_util.h so that the low-level
      @@ -123,9 +124,26 @@ MONGO_MOD_PUBLIC_FOR_TECHNICAL_REASONS constexpr void invariantWithContextAndLoc
       
       #define MONGO_invariant_EXPAND(x) x /**< MSVC workaround */
       #define MONGO_invariant_PICK(_1, _2, x, ...) x
      +#ifdef __clang_analyzer__
      +template <typename T>
      +bool toBool(T&&);
      +
      +template <typename T>
      +inline bool convertExpressionToBool(T&& expr) {
      +    if constexpr (std::is_trivially_constructible_v<bool, T>) {
      +        return static_cast<bool>(expr);
      +    } else {
      +        return toBool(std::forward<T>(expr));
      +    }
      +}
      +
      +#define GET_FIRST_ARG(X, ...) X
      +#define invariant(...) assert(convertExpressionToBool(GET_FIRST_ARG(__VA_ARGS__))) // NOLINT
      +#else
       #define invariant(...)      \
           MONGO_invariant_EXPAND( \
               MONGO_invariant_PICK(__VA_ARGS__, MONGO_invariant_2, MONGO_invariant_1)(__VA_ARGS__))
      +#endif
       
       /** An `invariant` that's only active in debug builds. Use for slow checks. */
       #define MONGO_dassert(...)                  \
      

            Assignee:
            Ronald Steinke
            Reporter:
            Amirsaman Memaripour
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated:
              Resolved: