Building C++26 Contracts Support for HPX

A Journey Through Experimental Features to Production-Ready Code
Google Summer of Code 2025 • Final Report
by Alexandros Papadakis • HPX Project

What Are Contracts?

According to the C++26 Contracts proposal P2900R14, "The primary goal of this facility is to enable identifying, in code, when a program is correct or incorrect in ways that does not, just by being used, change whether a program is correct or incorrect."

Contracts are used to clearly state what each function expects and guarantees. They help make assumptions in the code explicit and catch mistakes early. By adding preconditions, postconditions, and contract assertions, we can:

Overall, contracts in HPX can help ensure that its components work together safely and consistently in parallel execution.


Introduction

This summer, I had the opportunity to work on implementing C++26 contracts support for HPX (High Performance ParalleX) as part of Google Summer of Code. My goal was to create a contracts module that could use native C++26 contract syntax when available, but fall back to regular assertions when the compiler doesn't support contracts yet. Later, we decided to also include an option of upgrading regular assertions to contract assertions.


Understanding the HPX Module Structure

First, I needed to understand how HPX structures its modules. HPX follows a clean separation of concerns with modules located in libs/core/ and libs/full/. Each module maintains a consistent structure:

libs/core/contracts/
├── CMakeLists.txt              # Module configuration
├── include/hpx/
│   ├── contracts.hpp           # Public API header
│   └── modules/contracts.hpp   # Implementation header
├── tests/
│   ├── unit/                   # Unit tests
│   ├── performance/            # Performance tests
│   └── regressions/            # Regression tests
├── docs/
│   └── index.rst               # Sphinx documentation
└── README.md                   # Quick reference

This structure ensures that each module is self-contained, testable, and follows HPX's documentation standards.

Header File Architecture and Design Logic

The contracts module follows HPX's dual-header pattern with specific design considerations:

Public API Header: include/hpx/contracts.hpp

This is the user-facing header that provides a clean, simple interface:

// include/hpx/contracts.hpp
#pragma once

#include <hpx/modules/contracts.hpp>

// Simple forwarding header that includes the implementation
// This separation allows for future API evolution without breaking user code

Implementation Header: include/hpx/modules/contracts.hpp

This contains the actual implementation with sophisticated conditional compilation logic:

// include/hpx/modules/contracts.hpp
#pragma once

#include <hpx/config.hpp>
#include <hpx/assert.hpp>  // Crucial: HPX_ASSERT must be defined first

// Contract implementation: automatically selects native C++26 contracts 
// or falls back to HPX_ASSERT based on compiler capabilities
#ifdef HPX_HAVE_CONTRACTS
    #if HPX_HAVE_NATIVE_CONTRACTS
        // Native C++26 contracts mode
        #define HPX_PRE(x) pre(x)
        #define HPX_CONTRACT_ASSERT(x) contract_assert(x)
        #define HPX_POST(x) post(x)
    #else
        // Fallback mode: PRE/POST become no-ops, CONTRACT_ASSERT maps to assertions
        #pragma message("HPX Contracts: Using assertion fallback mode. " \
                       "HPX_PRE/HPX_POST are no-ops, HPX_CONTRACT_ASSERT maps to HPX_ASSERT.")
        #define HPX_PRE(x) 
        #define HPX_CONTRACT_ASSERT(x) HPX_ASSERT((x))  
        #define HPX_POST(x) 
    #endif
#else
    // Contracts disabled: PRE/POST are no-ops, CONTRACT_ASSERT remains available
    #define HPX_PRE(x)
    #define HPX_CONTRACT_ASSERT(x) HPX_ASSERT((x))
    #define HPX_POST(x)
#endif

#ifdef HPX_HAVE_ASSERTS_AS_CONTRACT_ASSERTS 
    // Override HPX_ASSERT to use contract assertions 
    #define HPX_ASSERT(x) HPX_CONTRACT_ASSERT(x)
#endif

Design Logic and Decision Tree

The header implements a sophisticated decision tree based on three key factors:

  1. User Configuration: HPX_HAVE_CONTRACTS (set by CMake)
  2. Compiler Capability: HPX_HAVE_NATIVE_CONTRACTS (detected by CMake)
  3. Enhancement Mode: HPX_HAVE_ASSERTS_AS_CONTRACT_ASSERTS flag
Decision Matrix:

┌─────────────────┬──────────────────┬─────────────────┬────────────────────────┐
│ HPX_HAVE_       │ HPX_HAVE_NATIVE_ │ Enhancement     │ Result                 │
│ CONTRACTS       │ CONTRACTS        │ Mode            │                        │
├─────────────────┼──────────────────┼─────────────────┼────────────────────────┤
│ ON              │ YES              │ OFF             │ Native C++26 contracts │
│ ON              │ YES              │ ON              │ Native + Enhanced      │
│ ON              │ NO               │ ANY             │ Assertion fallback     │
│ OFF             │ NO               │ ANY             │ Debug assert           │
└─────────────────┴──────────────────┴─────────────────┴────────────────────────┘

Note: HPX_HAVE_NATIVE_CONTRACTS is determined by CMake's compiler capability 
detection. When Enhancement Mode is ON but native contracts are unavailable,
CMake issues a warning that enhanced assertions provide no actual benefits.

CMake Integration and Build System Design

The contracts module integrates deeply with HPX's CMake build system, providing multiple configuration options and automatic compiler detection.

CMake Configuration Options

The module introduces CMake variables that control contract behavior:

# Primary contract control
-DHPX_WITH_CONTRACTS=ON|OFF           # Enable/disable contracts module

# Contract enhancement options  
-DHPX_HAVE_ASSERTS_AS_CONTRACT_ASSERTS=ON|OFF  # Upgrade existing assertions

# Contract evaluation behavior requires experimental compiler support
# Example for Clang with contracts:
-DCMAKE_CXX_STANDARD=26
-DCMAKE_CXX_FLAGS="-fcontracts -fcontract-evaluation-semantic=enforce"

Automatic Compiler Detection Logic

The build system automatically detects compiler contract support using CMake's add_hpx_config_test in the test configuration and sets the HPX_HAVE_NATIVE_CONTRACTS configuration variable:

# In libs/core/contracts/tests/unit/CMakeLists.txt

# Detect if __cpp_contracts is available at configure time
add_hpx_config_test(
    HPX_HAVE_NATIVE_CONTRACTS
    SOURCE "
        #ifndef __cpp_contracts
        #error No native contracts support
        #endif
        int main() { return 0; }
    "
)

Complete Build Command Examples

Here are comprehensive examples of how to build HPX with different contract configurations:

Example 1: Future C++26 Standard Build

cmake /path/to/hpx -GNinja \
  -DCMAKE_BUILD_TYPE=Debug \
  -DCMAKE_CXX_STANDARD=26 \
  -DHPX_WITH_CONTRACTS=ON \
  -DHPX_HAVE_ASSERTS_AS_CONTRACT_ASSERTS=ON \
  -DHPX_WITH_TESTS=ON \
  -DHPX_WITH_EXAMPLES=ON \
  -DCMAKE_CXX_COMPILER=clang++ \
  -DCMAKE_CXX_FLAGS="-fcontract-evaluation-semantic=enforce"

# This configuration (for future C++26 compilers):
# - Enables contracts module
# - Uses standard C++26 contract syntax (no experimental flags needed)
# - Only evaluation semantic flag needed to control contract behavior
# - Upgrades all HPX_ASSERT calls to contract assertions

Example 2: Current Experimental Build (EricWF's Clang fork)

cmake /path/to/hpx -GNinja \
  -DCMAKE_BUILD_TYPE=Debug \
  -DCMAKE_CXX_STANDARD=23 \
  -DHPX_WITH_CONTRACTS=ON \
  -DHPX_HAVE_ASSERTS_AS_CONTRACT_ASSERTS=ON \
  -DHPX_WITH_TESTS=ON \
  -DHPX_WITH_EXAMPLES=ON \
  -DCMAKE_CXX_COMPILER=/opt/clang-nightly/bin/clang++ \
  -DCMAKE_CXX_FLAGS="-stdlib=libc++ -fcontracts -fcontract-evaluation-semantic=enforce"

# This configuration (for current experimental Clang):
# - Uses EricWF's experimental Clang with contracts support 
# - Requires -fcontracts flag to enable experimental contracts
# - Needs -stdlib=libc++ for proper standard library support
# - Falls back to assertions when contracts fail to link
EricWF's Clang fork Contract Flags

The experimental Clang nightly build supports these contract-specific options:

Example 3: Production Build with Assertion Fallback

cmake /path/to/hpx -GNinja \
  -DCMAKE_BUILD_TYPE=Debug \
  -DCMAKE_CXX_STANDARD=23 \
  -DHPX_WITH_CONTRACTS=ON \
  -DHPX_HAVE_ASSERTS_AS_CONTRACT_ASSERTS=OFF \
  -DHPX_WITH_TESTS=OFF \
  -DHPX_WITH_EXAMPLES=OFF \
  -DCMAKE_CXX_COMPILER=g++

# This configuration:
# - Uses standard GCC (no contract support)
# - Contracts automatically fall back to assertions
# - Optimized for production with minimal overhead
# - Contracts provide documentation value and debugging aid

Example 4: Release for Maximum Performance

cmake /path/to/hpx -GNinja \
  -DCMAKE_BUILD_TYPE=Release \
  -DCMAKE_CXX_STANDARD=20 \
  -DHPX_WITH_CONTRACTS=OFF \
  -DHPX_WITH_TESTS=OFF \
  -DCMAKE_CXX_COMPILER=g++ \
  -DCMAKE_CXX_FLAGS="-O3 -DNDEBUG"

# This configuration:
# - Completely disables contracts and assertions 
# - Maximum performance for production deployment

CMake Module Integration

The contracts module's CMakeLists.txt shows how it integrates with HPX's build system:

# libs/core/contracts/CMakeLists.txt

# Define the module headers
set(contracts_headers
    hpx/contracts.hpp hpx/modules/contracts.hpp
)

# Create the module target using HPX's module system
add_hpx_module(
  core contracts
  GLOBAL_HEADER_GEN OFF
  SOURCES ${contracts_sources}
  HEADERS ${contracts_headers}
  COMPAT_HEADERS ${contracts_compat_headers}
  MODULE_DEPENDENCIES hpx_config hpx_preprocessor hpx_assertion
  CMAKE_SUBDIRS examples tests
)

# Contract-specific configuration is handled through HPX's config system
# HPX_HAVE_CONTRACTS and related variables are set by the main build
# HPX_HAVE_NATIVE_CONTRACTS is detected in the test CMakeLists.txt

Integration with User Projects

When users build their own projects against HPX with contracts, they can leverage the same system:

# User's CMakeLists.txt
find_package(HPX REQUIRED)

add_executable(my_app main.cpp)
target_link_libraries(my_app HPX::hpx)

# If HPX was built with contracts support, this automatically enables:
# - Contract macros (HPX_PRE, HPX_POST, HPX_CONTRACT_ASSERT)
# - Fallback behavior based on compiler capabilities

# User code can now use contracts:
# void my_function(int x) HPX_PRE(x > 0) HPX_POST(r: r >= x) {
#     return x + 1;
# }

Testing Strategy: Multi-Mode Validation

Testing a system that behaves differently based on compiler capabilities required a sophisticated approach. I implemented automatic test mode detection using CMake:

Compiler Capability Detection

# Detection happens in the test CMakeLists.txt
add_hpx_config_test(
    HPX_HAVE_NATIVE_CONTRACTS
    SOURCE "
        #ifndef __cpp_contracts
        #error No native contracts support
        #endif
        int main() { return 0; }
    "
)

Conditional Test Generation

Based on the detection results, different test suites are built:

Declaration Tests (Native C++26 mode):

int factorial(int n) HPX_PRE(n >= 0) HPX_POST(r: r > 0) {
    return n <= 1 ? 1 : n * factorial(n - 1);
}

Fallback Tests (Assertion mode):

int main(){ 
    HPX_PRE(true); //no-op in fallback mode
    HPX_POST(true);
    
    HPX_CONTRACT_ASSERT(true); //Maps to HPX_ASSERT in fallback mode

    // Add a failing assertion to test WILL_FAIL behavior
    HPX_CONTRACT_ASSERT(false);  // This should abort in Debug mode
    HPX_TEST(true);
    
    return hpx::util::report_errors();
}

Disabled Tests: Verify that preconditions and postconditions become no-ops while contract assertions remain functional.

Test Categories by Design

Each test category validates different aspects:

Running Contract Tests

To run the contract tests specifically, use these commands:

# Run all contract module tests
ninja tests.unit.modules.contracts

# Run contract tests with verbose output
ctest -R contract -V

These commands will execute the appropriate test suite based on your compiler capabilities and build configuration, whether using native C++26 contracts or assertion fallback mode.

Advanced Testing Infrastructure

The testing system automatically generates different test suites based on detected compiler capabilities:

Automatic Test Configuration

# CMake test generation logic from actual implementation
if(HPX_HAVE_NATIVE_CONTRACTS)
    message(STATUS "HPX Contracts: Native C++26 contracts detected - building declaration tests")
    
    # Declaration contracts tests (C++26 declaration syntax)
    set(contract_tests 
        declaration_contracts_succeed
        declaration_contracts_fail_pre 
        declaration_contracts_fail_post 
        declaration_contracts_fail_contract_assert
    )
    foreach(test ${contract_tests})
        add_hpx_executable(
            ${test}_test INTERNAL_FLAGS
            SOURCES ${test}.cpp
            NOLIBS
            DEPENDENCIES hpx_core
            EXCLUDE_FROM_ALL
            FOLDER "Tests/Unit/Modules/Core/Contracts/"
        )
        add_hpx_unit_test("modules.contracts" ${test})
    endforeach()
        
else()
    message(STATUS "HPX Contracts: Fallback mode detected - building fallback tests")
    
    # Fallback contracts tests (simple syntax for fallback mode)
    set(contract_tests 
        fallback_contracts_succeed
        fallback_contracts_fail
    )
    foreach(test ${contract_tests})
        add_hpx_executable(
            ${test}_test INTERNAL_FLAGS
            SOURCES ${test}.cpp
            NOLIBS
            DEPENDENCIES hpx_core
            EXCLUDE_FROM_ALL
            FOLDER "Tests/Unit/Modules/Core/Contracts/"
        )
        add_hpx_unit_test("modules.contracts" ${test})
    endforeach()
endif()

Example Test Files

The actual test files in the repository are simpler than complex examples might suggest. The testing focuses on basic contract functionality and mode detection rather than elaborate scenarios.


Technical Challenges and Solutions

Challenge 1: Development Environment Limitations

Working on Windows with experimental compiler builds presented immediate challenges. Building LLVM from source required extensive memory (16GB+) and long build times, which were not feasible on my development machine.

Solution: Used mentor-provided dockerized development environment with pre-built EricWF's experimental Clang, ensuring reproducible builds across different platforms.

Challenge 2: Contract Linking Errors

Early testing revealed linker errors when using contract violations: undefined reference to '__handle_contract_violation_v3'. The experimental runtime support was incomplete.

Solution: Implemented intelligent fallback system that gracefully degrades to assertion-based contracts when native contract runtime support fails to link properly.

Challenge 3: Multi-Mode Compatibility

The module needed to work seamlessly across different compiler capabilities and configuration combinations without breaking existing HPX code.

Solution: Designed layered configuration system with automatic capability detection and adaptive macro definitions that maintain compatibility across all modes.


Development Environment Setup

Development was conducted using Windows Subsystem for Linux (WSL) to access a Linux-like environment. The process involved:

  1. HPX Environment Verification: Built and tested standard HPX examples to ensure proper setup
  2. Experimental Compiler Access: Used pre-built Docker container with EricWF's experimental Clang
  3. Contract Integration Testing: Validated contract syntax compilation and identified linking limitations
  4. Module Implementation: Added HPX_WITH_CONTRACTS configuration and implemented the contracts module

The final working environment was preserved in a Docker image for reproducible development and testing.


Results and Impact

The contracts module successfully delivers on all its goals:

✅ Forward Compatibility Achieved: The module seamlessly adapts between experimental contracts and production assertions, providing a clear migration path to C++26.
✅ Zero-Impact Integration Delivered: Existing HPX code gains contract benefits with just a configuration flag - no source code changes required.
✅ Production Ready: Comprehensive testing across all modes ensures reliability regardless of compiler capabilities.
✅ HPX Standards Compliant: Full integration with HPX's build system, documentation standards, and testing framework.

Real-World Usage Examples

The module enables contract specifications in user code. Here's a simple example of how it works:

// Basic usage example
#include <hpx/contracts.hpp>

int safe_divide(int a, int b)
    HPX_PRE(b != 0)                    // Precondition: no division by zero
    HPX_POST(r: r == a / b)            // Postcondition: verify result  
{
    return a / b;
}

void process_data(std::vector<int>& data, size_t index) {
    HPX_CONTRACT_ASSERT(index < data.size());  // Contract assertion
    data[index] *= 2;
}

The behavior adapts automatically based on compiler support and configuration:


Lessons Learned

This project taught me several valuable lessons:

Configuration System Insights

I learned how HPX's configuration system works through practical implementation:

# Build files generate defines.hpp with configuration
hpx_build_clang_nightly/libs/core/config/include/hpx/config/defines.hpp:
#define HPX_HAVE_CONTRACTS

# Source includes the configuration
./libs/core/config/include/hpx/config.hpp:
#include <hpx/config/defines.hpp>

# Convention: HPX_HAVE_FEATURE for capability flags

Future Directions

This contracts module provides a foundation for further development in HPX:

Immediate Enhancements

Algorithm Hardening

The next major goal is implementing algorithm hardening for HPX's parallel algorithms, similar to the approach described in P3471R2. This would involve adding contract-based safety checks to algorithms like:

Long-term Benefits



Acknowledgments

This project would not have been possible without the support and guidance of many individuals:

Mentors: Panagiotis Syskakis and Isidoros Tsaousis-Seiras provided invaluable guidance throughout the development process, helping navigate both technical challenges and project planning.

HPX Community: Special thanks to Hartmut Kaiser and the entire HPX community for creating such a welcoming environment and providing crucial insights into HPX's architecture and design philosophy.

Google Summer of Code: Thank you to the Google Summer of Code program for providing this incredible opportunity to contribute to open-source software and advance the state of C++ parallel programming.

Special Recognition: EricWF for providing the experimental Clang builds that made native contract testing possible during this early phase of C++26 development.


Conclusion

The HPX contracts module successfully implements C++26 contract support with intelligent fallback behavior. The implementation handles the transition from experimental contract syntax to standardized C++26 contracts through a layered configuration system that adapts to compiler capabilities.

The module integrates cleanly with HPX's existing build system and maintains backward compatibility. By providing native contract support when available and appropriate fallback behavior (no-ops for HPX_PRE/HPX_POST, assertion mapping for HPX_CONTRACT_ASSERT), it offers a practical path forward as C++26 contracts become more widely available. The implementation is available for testing and integration into the main HPX codebase.

Complete implementation available at: https://github.com/AlexPapadakis/hpx/tree/contract_test