C++ Support
This page is a reference of the C++ language features and standard-library headers supported by ESBMC’s Clang-based C++ frontend. For what is not supported, see Limitations.
At a glance
| Standard | Language features | Library | Regression suite |
|---|---|---|---|
| C++98 / C++03 | Full | Containers, streams, strings | regression/esbmc-cpp |
| C++11 | Full | Move semantics, smart pointers, <chrono>, <atomic>, <thread> | regression/esbmc-cpp11 |
| C++14 | Full | std::make_unique | regression/esbmc-cpp14 |
| C++17 | Full | std::optional, std::variant, std::any, std::string_view | regression/esbmc-cpp17 |
| C++20 | Broad | std::span, <compare>, std::source_location | regression/esbmc-cpp20 |
| C++23 | Selected | std::expected | regression/esbmc-cpp20 |
The default is C++17. Select a different standard with --std, for example
--std c++20 or --std c++03.
Support is not gap-free at any standard — see Limitations for the known exceptions, notably constructor and destructor ordering.
Verifying a C++ program
ESBMC checks memory safety, arithmetic overflow, pointer safety and user
assertions across all inputs, rather than the single input a test would
exercise. Given shape.cpp:
#include <cassert>
class Shape
{
public:
virtual int area() const = 0;
virtual ~Shape() = default;
};
class Square : public Shape
{
int side;
public:
Square(int s) : side(s) {}
int area() const override { return side * side; }
};
int main()
{
int n = nondet_int();
__ESBMC_assume(n >= 1 && n < 100);
Shape *s = new Square(n);
assert(s->area() > n);
delete s;
return 0;
}Run it with:
esbmc shape.cpp --incremental-bmcESBMC finds the one input that breaks the assertion — n == 1, where
1 * 1 is not greater than 1:
[Counterexample]
State 1 file shape.cpp line 21 column 3 function main thread 0
----------------------------------------------------
n = 1 (00000000 00000000 00000000 00000001)
State 5 file shape.cpp line 25 column 3 function main thread 0
----------------------------------------------------
Violated property:
file shape.cpp line 25 column 3 function main
assertion main
!((_Bool)((signed long int)(!(return_value$ > n))))
VERIFICATION FAILEDTightening the assumption to n > 1 makes the property hold for every one of
the remaining inputs, and ESBMC reports VERIFICATION SUCCESSFUL.
See the Usage guide for the full set of options and the
Constructs reference for __ESBMC_assume, nondet_int and
the other verification annotations.
Operational models vs. host headers
By default ESBMC compiles C++ with -nostdinc++, so #include <vector>
resolves to ESBMC’s own operational model (OM) rather than your host standard
library. OMs are written to be verification-friendly — small, loop-free where
possible, and free of the inline assembly and compiler intrinsics that real
standard-library implementations rely on.
Two flags change this behaviour:
| Flag | Effect |
|---|---|
--no-abstracted-cpp-includes | Do not include the abstract C++ operational models at all. |
--mix-cpp-host-headers | Keep the host system headers visible alongside the OMs, so an #include not covered by the bundled models falls through to the host header. |
--mix-cpp-host-headers is the escape hatch for a header ESBMC does not model
(see Not modelled below). It is opt-in because names defined by
both the OMs and the host library — char_traits, istream and similar — can
then produce ambiguity errors at parse time.
Language features
Classes and objects
- Classes, member functions, member access control
- Constructors and destructors, including default, copy and move forms
- Static and non-static data members; default member initialisers
- Unions, including anonymous unions
typeidon a polymorphic glvalue reports the dynamic type, and thetype_infoname string is NUL-terminated
Constructors and destructors
- Delegating and inheriting constructors (
using Base::Base;), including multi-base and chained forms - Virtual bases are initialised only in the most-derived constructor
- Destructor chains for members and bases, including virtual base destructors
- Destructors run on return paths, for discarded results, and for temporaries destroyed mid-expression
References, temporaries and move semantics
- Lvalue and rvalue references
- Move constructors and move assignment operators
- Address-of distributes over a conditional lvalue; class-typed conditionals elide their temporaries; a reference parameter binds to the selected arm
Templates
- Class and function templates, partial and explicit specialisation
- Variable templates (C++14) and variable template declarations (C++17)
- Class template argument deduction (CTAD)
- Concepts and
requiresclauses (C++20)
Inheritance and polymorphism
- Single-level and multi-level polymorphism
- Pure virtual methods and abstract classes
- Virtual inheritance, including the diamond problem
- Multiple inheritance: nested base subobjects,
dynamic_cast<T*>re-offsetting across bases, override thunks keyed by each base’s virtual name and adjusted by the indirect base’s cumulative offset, and catch-by-base binding re-offset for multiple-inheritance thrown types - Virtual dispatch through a non-arrow member expression —
(*p).f()andref.f()dispatch virtually
Memory management
new/deleteandnew[]/delete[]- Detection of dangling pointers, double
deleteand mismatched operators - Placement
new, including the form without an initialiser deletedispatches through the virtual destructor slot; deleting through a base subobject whose destructor is not virtual is rejected
Exceptions
try / catch / throw are supported directly. Passing --lower-exceptions
additionally lowers exception handling into explicit control flow, which enables:
noexceptandthrow()exception specifications- Dynamic exception specifications, with
unexpected/bad_exceptionrecovery std::exception_ptrwithcurrent_exception,rethrow_exceptionandmake_exception_ptr, plus nested exceptions (throw_with_nested,rethrow_if_nested)std::uncaught_exception/std::uncaught_exceptions, via a lowered per-thread count
Other exception behaviour:
dynamic_cast<T&>throwsstd::bad_caston a failed reference caststd::vector::atandstd::string::atthrowstd::out_of_rangerather than assertingstd::bad_castandstd::bad_typeidderive fromstd::exceptionwith a virtualwhat()- The exception-state globals are thread-local, so each thread raises, catches and clears its own in-flight exception independently; concurrently-throwing programs are lowered rather than rejected
Selected C++17 / C++20 / C++23 features
| Feature | Standard |
|---|---|
Structured bindings, including binding by reference and over std::tuple | C++17 |
Three-way comparison <=>, including pointer and side-effecting operands | C++20 |
| Parenthesized aggregate initialization | C++20 |
using enum declarations | C++20 |
char8_t | C++20 |
Explicit object parameter (“deducing this”), including mutating receivers | C++23 |
static operator(), with the implicit object argument skipped | C++23 |
Standard-library coverage
The headers below are modelled by ESBMC’s own operational models and are covered
by regression tests under regression/esbmc-cpp*.
Containers and iterators
| Header | Notes |
|---|---|
<vector> | Including data(), emplace_back, shrink_to_fit, cbegin/cend; the destructor frees its buffer |
<list> | Const front/back/rbegin/rend, cbegin/cend |
<deque> | Const iteration |
<map> | Const at, emplace, try_emplace, insert_or_assign, C++20 contains |
<set> | Const-correct const iterators, emplace, C++20 contains |
<unordered_map>, <unordered_set> | |
<array> | iterator / const_iterator typedefs; usable in C++11 |
<queue>, <stack>, <bitset> | Includes std::priority_queue |
<iterator> | iterator_traits and the iterator tags |
<valarray> |
std::multimap and std::multiset track std::map and std::set, including
contains and cbegin/cend.
Strings and streams
| Header | Notes |
|---|---|
<string> | (const char*, size_t) range and fill constructors; length-aware operator</operator> including free overloads against const char*; const substr(pos, n); C++20 starts_with/ends_with; at throws std::out_of_range |
<string_view> | Search members, string → string_view conversion, hash<string_view> |
<iostream>, <istream>, <ostream>, <ios>, <iosfwd> | Standard stream objects, ios::widen/narrow, ios::exceptions, ios::copyfmt |
<sstream>, <fstream>, <streambuf>, <iomanip> | |
<locale> |
Utilities and type support
| Header | Notes |
|---|---|
<type_traits> | Classification traits and the _t aliases |
<utility>, <functional>, <memory>, <initializer_list> | |
<tuple> | std::tie, std::ignore, structured binding over a tuple |
<optional> | emplace, swap, std::make_optional |
<variant>, <any> | The converting constructor does not hijack copies |
<expected> | C++23 |
<compare> | Includable before C++20 |
<source_location>, <span>, <bit> | C++20 |
<typeinfo>, <exception>, <stdexcept>, <system_error>, <new> | |
<limits> | Works under --std c++11 and c++14 |
<filesystem> |
Algorithms and numerics
| Header | Notes |
|---|---|
<algorithm> | Including the C++11 algorithms |
<numeric> | iota, gcd, lcm, reduce |
<cmath> | The floating-point classifiers std::isnan, std::isinf, std::isfinite, std::isnormal and std::signbit are re-declared as std:: overloads lowered to ESBMC’s native FP intrinsics |
<complex>, <random>, <chrono> | <chrono> covers durations |
Concurrency
<thread>, <mutex> and <condition_variable> are lowered onto ESBMC’s pthread
model, so interleaving exploration, deadlock detection and data-race detection
apply to std::thread programs. std::promise and std::future are modelled on
the same basis, and <atomic> is modelled with atomic sections.
C library headers
<cassert>, <cctype>, <cerrno>, <cfloat>, <ciso646>, <climits>,
<clocale>, <cmath>, <csetjmp>, <csignal>, <cstdarg>, <cstddef>,
<cstdint>, <cstdio>, <cstdlib>, <cstring> and <ctime> are available.
Standard-version guards
<compare> is includable before C++20; <bit>, <span> and <expected> are
guarded by standard version; <array> is usable in C++11; <limits> works under
--std c++11 and c++14; and the C++98 container headers parse under
--std c++03.
Not modelled
The following standard headers have no operational model. Including one either
fails to resolve, or falls through to your host header under
--mix-cpp-host-headers — in which case ESBMC has to verify the real
implementation, which is frequently intractable.
<forward_list>, <regex>, <ranges>, <format>, <concepts>,
<coroutine>, <charconv>, <numbers>, <ratio>, <typeindex>,
<shared_mutex>, <barrier>, <latch>, <semaphore>, <stop_token>,
<syncstream>, <execution>, <memory_resource>, <scoped_allocator>,
<cwchar>, <cwctype>, <cfenv>, <cinttypes>.
Note that <concepts> being unmodelled does not affect the language feature —
concepts and requires clauses are supported, as listed above.
Current status
Feature support is tracked on the issue tracker under the
C++ label.
For the current pass rate, run the esbmc-cpp* regression suites or consult the
CI results.
Maintainers: see C++ Workflow and Resources for benchmark tracking and the development workflow.