Canonical version of Noreturn macro for pre-C11

Summary

The problem at hand is creating a canonical version of the Noreturn macro for use in a cross-platform codebase that needs to support pre-C11 compilers. The goal is to mark functions that do not return, which aids in analysis on compilers that support this feature. A proposed macro is provided, but the question remains whether this approach is optimal or if a better, more standardized method exists.

Root Cause

The root cause of the issue is the lack of a standardized way to mark non-returning functions in pre-C11 compilers. This leads to the use of compiler-specific attributes, such as:

  • __attribute__((noreturn)) for GCC and Clang
  • __declspec(noreturn) for MSVC
  • _Noreturn for C11 and later

Why This Happens in Real Systems

This problem occurs in real systems due to several reasons:

  • Legacy code: Older codebases may not have been updated to use C11 features.
  • Cross-platform development: Supporting multiple compilers and platforms requires accommodating different standards and extensions.
  • Third-party libraries: Including libraries that use different methods for marking non-returning functions can lead to conflicts.

Real-World Impact

The impact of not having a canonical Noreturn macro includes:

  • Analysis limitations: Without a standardized way to mark non-returning functions, static analysis tools may not work optimally across different compilers and platforms.
  • Code maintenance: Maintaining code that supports multiple compilers and standards can be more complex and error-prone.
  • Portability issues: Code may not be as portable as desired due to the use of compiler-specific attributes.

Example or Code

#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
#define MY_NORETURN _Noreturn
#elif defined(__GNUC__) || defined(__clang__)
#define MY_NORETURN __attribute__((noreturn))
#elif defined(_MSC_VER) && _MSC_VER >= 1200
#define MY_NORETURN __declspec(noreturn)
#else
#define MY_NORETURN
#endif

How Senior Engineers Fix It

Senior engineers address this issue by:

  • Defining a custom macro: Creating a project-specific macro, like MY_NORETURN, that encapsulates the different compiler-specific attributes.
  • Using feature test macros: Employing feature test macros, such as __STDC_VERSION__, to determine the supported C standard and define the macro accordingly.
  • Prioritizing standard compliance: When possible, using standard C11 _Noreturn for new code to ensure portability and readability.

Why Juniors Miss It

Junior engineers might overlook this issue due to:

  • Lack of experience with legacy systems: Less familiarity with the challenges of supporting older compilers and standards.
  • Insufficient knowledge of compiler-specific extensions: Not being aware of the different attributes used by various compilers to mark non-returning functions.
  • Focus on modern standards: Primarily focusing on newer C standards and not considering the need for backwards compatibility.

Leave a Comment