Skip to content

Add builtin_unreachable to the FW_ASSERT macros#5228

Open
garthwatney wants to merge 5 commits into
nasa:develfrom
garthwatney:watney-assert
Open

Add builtin_unreachable to the FW_ASSERT macros#5228
garthwatney wants to merge 5 commits into
nasa:develfrom
garthwatney:watney-assert

Conversation

@garthwatney

@garthwatney garthwatney commented Jun 2, 2026

Copy link
Copy Markdown
Contributor
Related Issue(s)
Has Unit Tests (y/n)
Documentation Included (y/n)
Generative AI was used in this contribution (y/n)

Change Description

Adds builtin_unreachable (available on GCC, Clang, maybe others) to FW_ASSERT() to signal that this is unreachable code. This should help resolve some false positives on static analyzers, and maybe other things.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the framework assertion macros to optionally include a compiler “unreachable” hint after Fw::SwAssert, enabling better optimization/analysis when assertions are configured to always abort.

Changes:

  • Introduces FW_UNREACHABLE() and FW_ASSERT_UNREACHABLE() macros to provide a portable (and configurable) unreachable hint.
  • Updates FW_ASSERT(...) expansions to invoke FW_ASSERT_UNREACHABLE() after Fw::SwAssert(...) in the failing-assert branch.

Comment thread Fw/Types/Assert.hpp
@github-actions

This comment was marked as resolved.

Comment thread Fw/Types/Assert.hpp
Comment thread Fw/Types/Assert.hpp
Comment thread Fw/Types/Assert.hpp

@lestarch-autobot lestarch-autobot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated review summary (run 1)

Per-agent results

Agent must fix suggestion could fix future work outstanding Verdict
Security Vulnerabilities 0 0 0 0 0 Go
Supply Chain / Runner Safety 0 0 1 0 1 Go
F Prime C/C++ Design 0 0 0 0 0 Go
Documentation Currency 1 0 0 1 2 No-Go
Design 0 0 0 0 0 Go
Architecture 0 0 0 0 0 Go
Test Quality 0 0 0 0 0 Go
CI safety Go
Totals 1 0 1 1 3 No-Go
Supply-chain surfaces
Surface Outstanding
Dependencies clean
Vendored / submodule clean
Build / test infrastructure clean
Workflows / actions / scripts clean
Generator output clean
Prompt-injection 1 could-fix — hidden HTML comment in PR body targets AI agents
Review-system integrity clean
Outstanding must-fix items (1)

Documentation Currency

  • New public macro FW_UNREACHABLE() and changed FW_ASSERT behavior not documented in docs/user-manual/framework/assert.mdlink

Merge readiness

Merge readiness: No-Go — Documentation Currency has 1 outstanding must-fix item.


Clear skies ahead once the docs catch up — this is a solid improvement to the assert infrastructure.

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Comment thread Fw/Types/Assert.hpp
Comment on lines +11 to +19
// Define FW_UNREACHABLE to hint to the compiler that a code path is unreachable.
// Falls back to a no-op on compilers that do not support __builtin_unreachable.
// (1) __has_builtin — the modern check, available in Clang and GCC >= 10.
// (2) defined(__GNUC__) — catches older GCC (4.5–9) which lack __has_builtin
#ifdef __has_builtin
#if __has_builtin(__builtin_unreachable)
#define FW_UNREACHABLE() __builtin_unreachable()
#endif
#endif

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Copilot review correctly identified that this branch can redefine a user-provided FW_UNREACHABLE. Other macros in this file (e.g., FW_ASSERT_NORETURN at line 88, NOINLINE at line 102) use #ifndef guards. Wrapping the __has_builtin detection in #ifndef FW_UNREACHABLE prevents redefinition warnings and allows intentional overrides.

Suggested change
// Define FW_UNREACHABLE to hint to the compiler that a code path is unreachable.
// Falls back to a no-op on compilers that do not support __builtin_unreachable.
// (1) __has_builtin — the modern check, available in Clang and GCC >= 10.
// (2) defined(__GNUC__) — catches older GCC (4.5–9) which lack __has_builtin
#ifdef __has_builtin
#if __has_builtin(__builtin_unreachable)
#define FW_UNREACHABLE() __builtin_unreachable()
#endif
#endif
// Define FW_UNREACHABLE to hint to the compiler that a code path is unreachable.
// Users may pre-define FW_UNREACHABLE to override the detection below.
// Falls back to a no-op on compilers that do not support __builtin_unreachable.
// (1) __has_builtin — the modern check, available in Clang and GCC >= 10.
// (2) defined(__GNUC__) — catches older GCC (4.5–9) which lack __has_builtin
#ifndef FW_UNREACHABLE
#ifdef __has_builtin
#if __has_builtin(__builtin_unreachable)
#define FW_UNREACHABLE() __builtin_unreachable()
#endif
#endif
#endif

@lestarch-autobot

Copy link
Copy Markdown
Collaborator

Documentation updates (from automated review)

The review flagged two documentation gaps. Below are the changes needed. They are also available on branch JPL-Devin/fprime:devin/1749690600-pr5228-docs-and-guard if you prefer to cherry-pick.


1. docs/user-manual/framework/assert.md — new section before "The assert can be configured"

Add after the C Assertion Macros section (after line 61):

## Unreachable Hints

The framework provides two macros for hinting to the compiler that a code path is unreachable:

- **`FW_UNREACHABLE()`** — A general-purpose macro that expands to `__builtin_unreachable()` on
  GCC and Clang, or to a no-op on compilers that do not support it. Users may pre-define
  `FW_UNREACHABLE` before including `Assert.hpp` to override the auto-detection.

- **`FW_ASSERT_UNREACHABLE()`** — Used internally by the `FW_ASSERT` macros after the call to
  `Fw::SwAssert()`. This hint is only active when `FW_ASSERTIONS_ALWAYS_ABORT` is set to `1`,
  because `SwAssert()` can legally return when that option is disabled (the default). Using
  `__builtin_unreachable()` after a call that may return would be undefined behavior, so this
  macro expands to a no-op unless always-abort mode is enabled.

When `FW_ASSERTIONS_ALWAYS_ABORT` is enabled and the compiler supports `__builtin_unreachable()`,
the unreachable hint allows the compiler to optimize assert-failure paths (e.g., eliminating
dead code after an assert, removing redundant checks) and improves static analysis accuracy.

## Configuration

2. docs/user-manual/framework/configuring-fprime.md — add row to Table 38

Add after the FW_ASSERT_TEXT_SIZE row:

| FW_ASSERTIONS_ALWAYS_ABORT | When set to 1, asserts always abort (never return). Enables `FW_ASSERT_NORETURN` on `SwAssert` and activates `FW_ASSERT_UNREACHABLE()` hints after assert calls for improved optimization and static analysis. | | 0 (off) |

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants