Skip to content

Commit 45da672

Browse files
AlexPapadakishkaiser
authored andcommitted
Adding minimal contract support (see p2900)
- updated cmake option for enchanced asserts to follow convention - updated fallback logic, added config test for experimental builds - improved documentation - added config test to automatically run the appropriate tests for either native or fallback mode - contracts: Restructure test suite for clarity and completeness - Add comprehensive declaration-based contract failure tests: * declaration_contracts_fail_pre.cpp * declaration_contracts_fail_post.cpp * declaration_contracts_fail_contract_assert.cpp - Remove redundant test files (contract_fail.cpp, simple_contracts_*) - Update CMakeLists.txt with proper test organization: * Declaration tests: C++26 syntax (__cpp_contracts mode) * Fallback tests: Simple syntax (fallback mode) * Disabled tests: No-op behavior testing - Set appropriate WILL_FAIL properties for all failure tests - Test structure now clearly separates native C++26 contract testing from HPX_ASSERT fallback behavior testing, providing comprehensive coverage of all contract modes. - added contracts in core
1 parent 35bd323 commit 45da672

20 files changed

Lines changed: 821 additions & 0 deletions

CMakeLists.txt

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1503,6 +1503,24 @@ if(NOT "${HPX_PLATFORM_UC}" STREQUAL "BLUEGENEQ")
15031503
endif()
15041504

15051505
# Debugging related build options
1506+
hpx_option(
1507+
HPX_WITH_CONTRACTS BOOL "Enable C++ contracts support in HPX" OFF
1508+
CATEGORY "Debugging"
1509+
)
1510+
1511+
if(HPX_WITH_CONTRACTS)
1512+
hpx_add_config_define(HPX_HAVE_CONTRACTS)
1513+
endif()
1514+
1515+
hpx_option(
1516+
HPX_WITH_ASSERTS_AS_CONTRACT_ASSERTS BOOL
1517+
"Swap hpx_assert with hpx_contract_assert" OFF CATEGORY "Debugging"
1518+
)
1519+
1520+
if(HPX_WITH_ASSERTS_AS_CONTRACT_ASSERTS)
1521+
hpx_add_config_define(HPX_HAVE_ASSERTS_AS_CONTRACT_ASSERTS)
1522+
endif()
1523+
15061524
hpx_option(
15071525
HPX_WITH_VALGRIND BOOL "Enable Valgrind instrumentation support." OFF
15081526
CATEGORY "Debugging"

cmake/tests/contracts.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// Copyright (c) 2025 Alexandros Papadakis
2+
// Copyright (c) 2025 Panagiotis Syskakis
3+
//
4+
// SPDX-License-Identifier: BSL-1.0
5+
// Distributed under the Boost Software License, Version 1.0. (See accompanying
6+
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7+
8+
// This tests whether C++26 contracts are supported by the compiler
9+
10+
#if __cpp_contracts
11+
// Test native contract syntax
12+
int divide(int a, int b) pre(b != 0) post(r; r == a / b)
13+
{
14+
return a / b;
15+
}
16+
17+
void test_contract_assert()
18+
{
19+
contract_assert(true);
20+
}
21+
22+
int main()
23+
{
24+
int result = divide(10, 2);
25+
test_contract_assert();
26+
return result == 5 ? 0 : 1;
27+
}
28+
29+
#else
30+
// Fallback test - contracts not available
31+
int main()
32+
{
33+
// Test would fail if contracts were required but not available
34+
return 0;
35+
}
36+
#endif

libs/core/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ set(_hpx_core_modules
3030
concurrency
3131
config
3232
config_registry
33+
contracts
3334
coroutines
3435
datastructures
3536
debugging

libs/core/contracts/CMakeLists.txt

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# Copyright (c) 2025 The STE||AR-Group
2+
# Copyright (c) 2025 Alexandros Papadakis
3+
#
4+
# SPDX-License-Identifier: BSL-1.0
5+
# Distributed under the Boost Software License, Version 1.0. (See accompanying
6+
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7+
8+
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
9+
10+
# Default location is $HPX_ROOT/libs/contracts/include
11+
set(contracts_headers hpx/contracts.hpp hpx/modules/contracts.hpp)
12+
13+
# Default location is $HPX_ROOT/libs/contracts/include_compatibility
14+
# cmake-format: off
15+
set(contracts_compat_headers
16+
# Add any legacy header mappings here if needed in the future
17+
# hpx/old_contracts.hpp => hpx/contracts.hpp
18+
)
19+
# cmake-format: on
20+
21+
# Default location is $HPX_ROOT/libs/contracts/src
22+
set(contracts_sources # Add source files here when implementation is added
23+
# contracts.cpp
24+
)
25+
26+
include(HPX_AddModule)
27+
add_hpx_module(
28+
core contracts
29+
GLOBAL_HEADER_GEN OFF
30+
SOURCES ${contracts_sources}
31+
HEADERS ${contracts_headers}
32+
COMPAT_HEADERS ${contracts_compat_headers}
33+
MODULE_DEPENDENCIES hpx_config hpx_preprocessor hpx_assertion
34+
CMAKE_SUBDIRS examples tests
35+
)

libs/core/contracts/README.md

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
<!--
2+
Copyright (c) 2025 The STE||AR-Group
3+
Copyright (c) 2025 Alexandros Papadakis
4+
5+
SPDX-License-Identifier: BSL-1.0
6+
Distributed under the Boost Software License, Version 1.0. (See accompanying
7+
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
8+
-->
9+
10+
# HPX Contracts Module
11+
12+
A forward-compatible C++ contracts implementation for HPX with intelligent fallback to assertions.
13+
14+
## Quick Start
15+
16+
```cpp
17+
#include <hpx/contracts.hpp>
18+
19+
// Preconditions and postconditions with return value access
20+
int factorial(int n) HPX_PRE(n >= 0) HPX_POST(r: r > 0) {
21+
return n <= 1 ? 1 : n * factorial(n - 1);
22+
}
23+
24+
// Contract assertions (always available)
25+
void process(std::vector<int>& data, size_t index) {
26+
HPX_CONTRACT_ASSERT(index < data.size());
27+
data[index] *= 2;
28+
}
29+
```
30+
31+
## Build Configuration
32+
33+
```bash
34+
# Enable contracts
35+
cmake -DHPX_WITH_CONTRACTS=ON -DCMAKE_CXX_STANDARD=26
36+
37+
# Enable contract-enhanced assertions (optional)
38+
cmake -DHPX_WITH_CONTRACTS=ON -DHPX_WITH_ASSERTS_AS_CONTRACT_ASSERTS=ON
39+
40+
# Contracts disabled (hpx_contract_assert will work as hpx_assert)
41+
cmake -DHPX_WITH_CONTRACTS=OFF #default
42+
```
43+
44+
## Advanced Features
45+
46+
### Contract-Enhanced Assertions
47+
When `HPX_WITH_ASSERTS_AS_CONTRACT_ASSERTS=ON`, regular `HPX_ASSERT` calls are automatically upgraded to use contract assertions:
48+
49+
```cpp
50+
void process_data(std::vector<int>& data, size_t index) {
51+
HPX_ASSERT(index < data.size()); // Becomes HPX_CONTRACT_ASSERT() -> adapts to current mode
52+
data[index] *= 2;
53+
}
54+
```
55+
56+
**Important**: Enhanced assertions only provide benefits when native C++26 contracts are supported by the compiler. Without native contract support, `HPX_ASSERT` → `HPX_CONTRACT_ASSERT` → `HPX_ASSERT` (no enhancement). CMake will warn you if you enable this option without native contract support.
57+
58+
The implementation works by overriding the `HPX_ASSERT` macro in `contracts.hpp` to use `HPX_CONTRACT_ASSERT`, which automatically adapts to the current contract mode (native C++26 contracts when available, or assertion fallback otherwise).
59+
60+
## API Reference
61+
62+
- **`HPX_PRE(condition)`**: Precondition contracts
63+
- **`HPX_POST(condition)`**: Postcondition contracts
64+
- **`HPX_CONTRACT_ASSERT(condition)`**: Contract assertions (always available)
65+
66+
## Documentation
67+
68+
See [Module Documentation](docs/index.rst) for comprehensive usage guide, API reference, and implementation details.
69+
70+
## Features
71+
72+
- ✅ Automatic C++26 native contract detection
73+
- ✅ Graceful fallback: HPX_PRE/HPX_POST become no-ops, HPX_CONTRACT_ASSERT maps to HPX_ASSERT
74+
- ✅ Zero overhead when disabled
75+
- ✅ Forward-compatible API
76+
- ✅ Comprehensive test suite with automatic mode detection

libs/core/contracts/docs/index.rst

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
..
2+
Copyright (c) 2025 The STE||AR-Group
3+
Copyright (c) 2025 Alexandros Papadakis
4+
5+
SPDX-License-Identifier: BSL-1.0
6+
Distributed under the Boost Software License, Version 1.0. (See accompanying
7+
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
8+
9+
.. _modules_contracts:
10+
11+
=========
12+
contracts
13+
=========
14+
15+
The contracts module provides C++ contracts support for HPX with intelligent
16+
fallback to assertions when native contracts are not available. This module
17+
implements a forward-compatible API that works across different C++ standards
18+
and compiler capabilities.
19+
20+
The module provides three primary macros: :c:macro:`HPX_PRE`,
21+
:c:macro:`HPX_POST`, and :c:macro:`HPX_CONTRACT_ASSERT`. These macros
22+
automatically adapt their behavior based on compiler capabilities:
23+
24+
* When C++26 native contracts are available (``__cpp_contracts`` defined),
25+
they map to standard contract syntax
26+
* When contracts are not available but ``HPX_WITH_CONTRACTS=ON``, preconditions
27+
and postconditions become no-ops while contract assertions fall back to
28+
:c:macro:`HPX_ASSERT` for compatibility
29+
* When ``HPX_WITH_CONTRACTS=OFF``, preconditions and postconditions become
30+
no-ops while contract assertions remain available as enhanced assertions
31+
32+
Configuration
33+
=============
34+
35+
Enable contracts in CMake::
36+
37+
cmake -DHPX_WITH_CONTRACTS=ON -DCMAKE_CXX_STANDARD=26
38+
39+
Enable contract-enhanced assertions (optional)::
40+
41+
cmake -DHPX_WITH_CONTRACTS=ON -DHPX_WITH_ASSERTS_AS_CONTRACT_ASSERTS=ON
42+
43+
Contract assertions work even when contracts are disabled::
44+
45+
cmake -DHPX_WITH_CONTRACTS=OFF # HPX_CONTRACT_ASSERT still maps to HPX_ASSERT
46+
47+
Advanced Features
48+
=================
49+
50+
Contract-Enhanced Assertions
51+
----------------------------
52+
53+
When ``HPX_WITH_ASSERTS_AS_CONTRACT_ASSERTS=ON`` is enabled, regular
54+
:c:macro:`HPX_ASSERT` calls are automatically upgraded to use contract
55+
assertions in C++26 mode::
56+
57+
void example_function(int value)
58+
{
59+
HPX_ASSERT(value > 0); // Becomes contract_assert(value > 0) in C++26 mode
60+
// ... rest of function
61+
}
62+
63+
.. warning::
64+
Enhanced assertions only provide benefits when native C++26 contracts are
65+
supported by the compiler. Without native contract support,
66+
``HPX_ASSERT`` → ``HPX_CONTRACT_ASSERT`` → ``HPX_ASSERT`` (no enhancement).
67+
CMake will issue a warning if you enable this option without native contract support.
68+
69+
This provides enhanced contract semantics throughout your existing codebase
70+
without requiring changes to assertion code. The transformation occurs in the
71+
contracts module (``contracts.hpp``) where the ``HPX_ASSERT`` macro is
72+
overridden to use ``HPX_CONTRACT_ASSERT`` when ``HPX_WITH_ASSERTS_AS_CONTRACT_ASSERTS=ON``:
73+
74+
* ``HPX_WITH_CONTRACTS=ON`` - Contracts module is enabled
75+
* ``HPX_WITH_ASSERTS_AS_CONTRACT_ASSERTS=ON`` - Assertion enhancement is enabled
76+
* ``HPX_HAVE_NATIVE_CONTRACTS=ON`` - C++26 native contracts are available (from config test)
77+
78+
The implementation works by redefining ``HPX_ASSERT`` in ``contracts.hpp`` to
79+
use ``HPX_CONTRACT_ASSERT``, which automatically adapts to the current contract
80+
mode (native C++26 contracts or assertion fallback). This ensures all existing
81+
``HPX_ASSERT`` calls throughout the HPX codebase automatically gain contract
82+
semantics when available.
83+
84+
Usage Examples
85+
==============
86+
87+
Preconditions and postconditions using declaration syntax (C++26)::
88+
89+
int divide(int a, int b) HPX_PRE(b != 0)
90+
{
91+
return a / b;
92+
}
93+
94+
int factorial(int n) HPX_PRE(n >= 0) HPX_POST(r; r > 0)
95+
{
96+
return n <= 1 ? 1 : n * factorial(n - 1);
97+
}
98+
99+
Contract assertions (available in all modes)::
100+
101+
void process_array(std::vector<int>& arr, size_t index)
102+
{
103+
HPX_CONTRACT_ASSERT(index < arr.size());
104+
arr[index] *= 2;
105+
}
106+
107+
Design Philosophy
108+
=================
109+
110+
**HPX_CONTRACT_ASSERT**: Enhanced assertion mechanism
111+
Available even when ``HPX_WITH_CONTRACTS=OFF`` because it provides value
112+
as an enhanced assertion. Maps to :c:macro:`HPX_ASSERT` in all configurations.
113+
114+
**HPX_PRE/HPX_POST**: True contract syntax
115+
Represent language-level contract semantics. When contracts are enabled but
116+
native C++26 contracts are not available, these become no-ops to maintain
117+
forward compatibility. When ``HPX_WITH_CONTRACTS=OFF``, they are also no-ops.
118+
This prepares for C++26 migration where they will be attached to function
119+
declarations rather than used in function bodies.
120+
121+
Migration Strategy
122+
==================
123+
124+
The module is designed for smooth migration to C++26 native contracts:
125+
126+
Current (transition mode)::
127+
128+
int func(int x)
129+
{
130+
HPX_PRE(x > 0); // No-op in fallback mode, active in native mode
131+
return x;
132+
}
133+
134+
Target (C++26 native)::
135+
136+
int func(int x) HPX_PRE(x > 0)
137+
{
138+
return x;
139+
}
140+
141+
Note: In fallback mode, ``HPX_PRE`` and ``HPX_POST`` become no-ops to maintain
142+
forward compatibility and avoid performance overhead. Use ``HPX_CONTRACT_ASSERT``
143+
when you need runtime validation in all modes.
144+
145+
Testing
146+
=======
147+
148+
The module includes comprehensive testing with automatic compiler capability
149+
detection. Tests are organized into three categories:
150+
151+
* **Declaration tests**: Test C++26 native contract syntax when ``__cpp_contracts`` is available
152+
* **Fallback tests**: Test assertion fallback behavior when contracts are not natively supported
153+
* **Disabled tests**: Test no-op behavior when contracts are disabled
154+
155+
The test suite automatically detects compiler capabilities at configure time
156+
and builds only the appropriate tests for the current configuration.
157+
158+
See the :ref:`API reference <modules_contracts_api>` of the module for more details.
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# Copyright (c) 2025 Alexandros Papadakis
2+
# Copyright (c) 2025 Panagiotis Syskakis
3+
# HPX Contracts Module Examples
4+
#
5+
# SPDX-License-Identifier: BSL-1.0
6+
# Distributed under the Boost Software License, Version 1.0. (See accompanying
7+
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
8+
9+
# Currently no examples for contracts module Examples will be added in future
10+
# iterations when the contract API is stabilized
11+
12+
if(HPX_WITH_EXAMPLES)
13+
# Future: Add contract usage examples here
14+
# add_hpx_executable(contract_examples SOURCES basic_contract_usage.cpp
15+
# COMPONENT_DEPENDENCIES hpx_core )
16+
endif()
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// Copyright (c) 2025 The STE||AR-Group
2+
// Copyright (c) 2025 Alexandros Papadakis
3+
//
4+
// SPDX-License-Identifier: BSL-1.0
5+
// Distributed under the Boost Software License, Version 1.0. (See accompanying
6+
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7+
8+
#pragma once
9+
10+
#include <hpx/modules/contracts.hpp>

0 commit comments

Comments
 (0)