Supported C++ Feature Matrix

cppbolt implements a defined, correctness-oriented subset of C++17. Every supported feature is covered by automated corpus tests and pinned by cryptographic golden hashes. Features outside the subset are either explicitly rejected with clear diagnostics or tracked as planned future extensions.

The baseline test status is tracked in tests/PASSING.txt. Run the test runner to verify status locally:

cargo run --bin cppbolt-testrunner -- target/release/cppbolt-cli

Feature Matrix

FeatureStatusNotesTest
Scalar Types (int, long long, short, char, float, double, bool)DoneILP32 32-bit data model; unsigned overflow wrapping; binary literals (0b), octal, and single-quote digit separators (')tests/c_basics/types/arithmetic.cpp, tests/c_basics/types/numeric_literals.cpp, tests/c_basics/types/long_long.cpp, tests/c_basics/types/floats.cpp
Pointers & ConversionsDone32-bit Wasm i32 addresses; array decay; nullptr (std::nullptr_t); C++17 null pointer constants (0, 0u); multi-level const qualification rules; implicit object pointer to void*; explicit static_cast for void* to typed pointertests/c_basics/pointers_arrays/pointers_arrays.cpp, tests/c_basics/types/pointer_conversions.cpp
String LiteralsDoneTyped as const char[N] with trailing null terminator (sizeof("hello") == 6); decay to const char*; immutable (rejected for char*)tests/c_basics/types/pointer_conversions.cpp
Function PointersDoneIndirect calls via WebAssembly function table; comparator callbackstests/classes_oop/methods/function_pointer_comparator.cpp
Multi-Dimensional ArraysDoneNested dimensions wrap inside-out; contiguous row-major layout; pointer-to-array decaytests/c_basics/pointers_arrays/multidim_arrays.cpp, tests/c_basics/pointers_arrays/multidim_pointer_deref.cpp
Lvalue References (T&)DoneReference binding, parameters, reference return valuestests/classes_oop/statics_namespaces/references.cpp, tests/classes_oop/methods/member_reference_return.cpp
const QualifiersDoneconst variables, const pointers, const member methodstests/c_basics/types/const_qualifiers.cpp, tests/classes_oop/methods/const_methods.cpp
auto Type DeductionDoneLocal variable and reference type deductiontests/c_basics/types/auto_type.cpp
Type Aliases (typedef, using)DoneStandard typedef and C++11 using Alias = Type;tests/c_basics/types/auto_type.cpp
Multi-Declarator DeclarationsDoneComma-separated declarators sharing base specifiers (int *p, q = 2;)tests/c_basics/misc/multi_declarator.cpp
Array Function ParametersDoneParameter adjustment decaying int arr[] and int arr[N] to int* arrtests/c_basics/pointers_arrays/array_parameter_decay.cpp
EnumsDoneScoped (enum class) with qualified lookup (Scope::Val) and unscoped enumtests/c_basics/enums/enums.cpp, tests/c_basics/enums/scoped_enums.cpp
Control Flow (if, switch, loops)Doneif/else, ternary ?:, while, for, do-while, switch/case/default (with enum & const-expr case labels)tests/c_basics/control_flow/control_if_else.cpp, tests/c_basics/control_flow/control_loops.cpp, tests/c_basics/control_flow/switch_enum_case.cpp
Functions & OverloadingDoneExact match > reference binding > promotion > conversion; default arguments; global init reachabilitytests/c_basics/functions/functions_call.cpp, tests/c_basics/functions/constexpr_global_init_call.cpp, tests/c_basics/functions/overload_resolution.cpp
Static VariablesDoneFunction-local statics with arguments; class static memberstests/classes_oop/statics_namespaces/function_local_statics.cpp, tests/classes_oop/statics_namespaces/static_members.cpp
Structs & ClassesDoneAggregate init, member variables/methods, access controltests/classes_oop/structs/struct_basic.cpp, tests/classes_oop/structs/initializer_lists.cpp
Constructors & DestructorsDoneDefault, parameterized, copy, delegating (C() : C(x) {}); initializer list ordering; implicit synthesis for trivial/empty classes and prvalues (Value().get()); global parenthesized constructiontests/classes_oop/constructors_destructors/copy_semantics.cpp, tests/classes_oop/constructors_destructors/delegating_constructor.cpp, tests/classes_oop/constructors_destructors/prvalue_default_constructor.cpp, tests/classes_oop/statics_namespaces/global_constructor_args.cpp
Conversion OperatorsDoneUser-defined conversion operators operator T() const with explicit qualification checks; disambiguated from copy constructorstests/classes_oop/operators/conversion_operator.cpp, tests/classes_oop/operators/regress_user_conversion_param.cpp, tests/classes_oop/operators/regress_byval_param_conversion.cpp
Ref-Qualified MethodsDoneLvalue and rvalue ref-qualified member functions (get() &, get() &&) with receiver value-category dispatchtests/classes_oop/methods/ref_qualified_methods.cpp
Structured BindingsDoneAggregate decomposition (auto [a, b] = p;, auto&, const auto&)tests/classes_oop/structs/structured_bindings.cpp
RAII Lifecycle & Scope CleanupsDoneCleanups on scope exit, early return, break, continue, statement temporariestests/classes_oop/memory_raii/class_raii.cpp, tests/classes_oop/memory_raii/raii_early_return.cpp, tests/classes_oop/memory_raii/raii_temporaries.cpp
C++17 Copy ElisionDonePrvalue construction in place (direct init and function return)tests/classes_oop/memory_raii/prvalue_elision.cpp, tests/classes_oop/memory_raii/direct_initialization_elision.cpp
Dynamic Memory (new / delete)DoneSingle object and array new[]/delete[]; placement newtests/classes_oop/memory_raii/new_delete.cpp, tests/classes_oop/memory_raii/new_delete_object_arrays.cpp, tests/classes_oop/memory_raii/placement_new.cpp
Single & Linear InheritanceDoneBase subobjects, slicing, constructor/destructor chainstests/classes_oop/inheritance/single_inheritance.cpp, tests/classes_oop/inheritance/multi_level_inheritance.cpp
Virtual Functions & PolymorphismDoneVtable dispatch, virtual destructors, pure virtual (= 0)tests/classes_oop/inheritance/virtual_functions.cpp, tests/classes_oop/inheritance/virtual_destructor.cpp, tests/classes_oop/inheritance/pure_virtual.cpp
NamespacesDoneNested namespaces, using namespace, qualified lookupstests/classes_oop/statics_namespaces/namespaces_comprehensive.cpp
Operator Overloading (Binary & Compound)Done+, -, *, /, %, ==, !=, <, <=, >, >=, <<, >>, &, ^, |, =, +=, -=, *=tests/templates_operators/op_overload_binary.cpp, tests/classes_oop/operators/chained_compound_assign.cpp
Operator Overloading (Prefix & Subscript)DoneUnary +, -, !, ~, prefix ++/--, subscript [], operator bool()tests/templates_operators/op_overload_unary.cpp, tests/templates_operators/op_overload_subscript.cpp, tests/classes_oop/operators/contextual_bool_comprehensive.cpp
PreprocessorDone#define (function/object, #, raw ##), #undef, #include, #if/#elif, #error, #warning, \tests/c_basics/preprocessor/preprocessor.cpp, tests/c_basics/preprocessor/macro_rescan.cpp, tests/c_basics/preprocessor/macro_token_paste_raw.cpp, tests/c_basics/preprocessor/warning_directive.cpp
C Standard I/O (<cstdio>)Doneprintf (all conversions %d, %i, %u, %o, %x, %X, %c, %s, %e, %E, %f, %g, %G), sprintf, snprintf, putstests/c_basics/io_printf/printf_conversions.cpp, tests/c_basics/io_printf/printf_table.cpp, tests/mini_stl/cstdio_basic.cpp
C++ Streams (<iostream>)Donestd::cout, std::cin, std::getline, custom stream operatorstests/mini_stl/iostream_basic.cpp, tests/mini_stl/iostream_cin.cpp, tests/mini_stl/stream_operator_overload.cpp
Standard String (<string>)Donestd::string, .c_str(), .length(), .append(), concatenationtests/mini_stl/string_basic.cpp, tests/mini_stl/string_comprehensive.cpp
Math & Formatting (<cmath>, <iomanip>)DoneMath intrinsics, std::abs integer overloads for long and long long, std::setprecision, std::fixed, std::setwtests/mini_stl/cmath_basic.cpp, tests/c_basics/functions/std_abs_long.cpp, tests/mini_stl/iostream_precision_after_fixed.cpp
Templates & Member Templates (template <typename T>)DoneClass templates, out-of-class member method definitions, member function templates, dependent member type aliases, lazy method instantiation, multi-arity function overloads, and deduction for callables and pointerstests/templates_operators/template_class_basic.cpp, tests/templates_operators/template_class_methods.cpp, tests/templates_operators/template_func_basic.cpp, tests/templates_operators/template_multi_param.cpp, tests/templates_operators/template_pair.cpp, tests/mini_stl/pair_basic.cpp
Containers: Vector & Utility (<vector>, <utility>)Donestd::vector (dynamic growth, capacity doubling, element access, iterators, brace initialization, push_back self-aliasing protection, RAII lifecycle cleanup), std::pair and std::make_pairtests/mini_stl/vector_basic.cpp, tests/mini_stl/vector_brace_init.cpp, tests/mini_stl/vector_objects.cpp, tests/mini_stl/vector_aliasing.cpp, tests/mini_stl/iterators_range_for.cpp, tests/mini_stl/combined_integration.cpp
Algorithms (<algorithm>)Donestd::sort (default comparator and custom functor), std::reverse, std::min, std::max, std::swaptests/mini_stl/algorithm_basic.cpp, tests/mini_stl/algorithm_sort.cpp, tests/mini_stl/sort_comparator.cpp
Associative Containers (<map>, <set>)DoneBalanced binary search tree (detail::AVLTree), bidirectional iterators, insertion, lookup, range traversal, deletion, and differential fuzzingtests/mini_stl/map_basic.cpp, tests/mini_stl/set_basic.cpp, tests/mini_stl/differential_fuzz.cpp
Nested Classes & StructsDoneMember classes in non-template and template classes, access control validation, fixed-point dependent type alias resolution, and scoped member registrationtests/classes_oop/structs/nested_classes.cpp, tests/classes_oop/structs/nested_classes_scopes.cpp, tests/templates_operators/template_nested_classes.cpp, tests/templates_operators/template_nested_alias_chain.cpp
Dependent Types (typename)DoneDisambiguation of dependent member types (typename T::Type), rejection of unqualified typenametests/templates_operators/typename_dependent_syntax.cpp, tests/negative/typename_unqualified.cpp
Range-Based for LoopsDoneC++11 for (decl : range) over fixed-size arrays (1D and multi-dimensional) and classes with .begin()/.end(); supports auto, const auto, auto&, const auto&tests/c_basics/pointers_arrays/range_for_array.cpp, tests/mini_stl/range_for_string.cpp
Overloaded Postfix ++ / --DoneOverloaded operator++(int) and operator--(int) distinguish postfix from prefix via dummy int parametertests/classes_oop/operators/operator_postfix_incdec.cpp
Overloaded ->, *(), ()DoneSmart-pointer and functor operators: operator-> (recursive chaining with cycle detection), dereference operator*(), and function call operator()tests/classes_oop/operators/operator_smart_pointer.cpp, tests/classes_oop/operators/operator_arrow_chaining.cpp, tests/classes_oop/operators/operator_call_functor.cpp
Lambda Expressions (C++17)Done[], [x], [&x], [=], [&], mutable, trailing return type (-> T), return type deduction, auto storage, direct invocation, unary + decay, and implicit conversion of captureless lambdas to C function pointers (R (*)(P...)) including return targetstests/classes_oop/lambdas/lambda_basic.cpp, tests/classes_oop/lambdas/lambda_default_captures.cpp, tests/classes_oop/lambdas/lambda_function_pointer.cpp, tests/classes_oop/lambdas/lambda_return_fn_ptr.cpp, tests/classes_oop/lambdas/lambda_range_for_capture.cpp, tests/classes_oop/lambdas/lambda_unary_plus.cpp
List Initialization & AggregatesDoneDirect-list (T x{...}), copy-list (T x = {...}), empty brace value initialization ({}), namespace-scope (global) brace initialization, aggregate base subobjects, brace elision, narrowing conversion checks ([dcl.init.list] p7), dynamic allocation (new T{...}, new T[n]{...}), typed temporaries (Type{...}.get()), and explicit constructor enforcementtests/classes_oop/structs/brace_init_scalars.cpp, tests/classes_oop/structs/brace_init_classes.cpp, tests/classes_oop/structs/brace_init_aggregates.cpp, tests/classes_oop/structs/brace_init_brace_elision.cpp, tests/classes_oop/structs/brace_init_temporaries.cpp, tests/classes_oop/structs/brace_init_dynamic_new.cpp
std::initializer_listDoneCompiler-created contiguous backing arrays, begin()/end()/size(), constructor preference for braced containers (ranked by exact, promotion, and standard conversions), empty-brace fallback to an initializer-list constructor, nested brace lists, namespace-scope lists, auto deduction, homogeneity checks, narrowing diagnostics, and parenthesized braced argumentstests/mini_stl/initializer_list_basic.cpp, tests/mini_stl/vector_brace_init.cpp, tests/mini_stl/initializer_list_ctor_ranking.cpp, tests/mini_stl/initializer_list_nested.cpp, tests/mini_stl/initializer_list_global.cpp, tests/negative/initializer_list_narrowing.cpp, tests/negative/initializer_list_mismatched_types.cpp
Const-Ref Method Overloading (T m() const &)Plannedconst methods supported; const & method ref-qualifiers are rejected with const overloading is not supportedtests/negative/const_overload_unsupported.cpp
Namespace Aliases (namespace A = B;)DoneC++17 namespace alias declarations at namespace, file, and block scope with chained and qualified resolutiontests/classes_oop/statics_namespaces/namespace_aliases.cpp, tests/negative/namespace_alias.cpp
Extended Casts (reinterpret_cast)DoneC++17 reinterpret_cast<T>(expr) across scalar integers, pointers, and reference types within the ILP32 data model; bit-preserving conversions between integers and pointers, pointer conversions without adjusting offsets, and byte inspection; disallows scalar float conversionstests/c_basics/types/reinterpret_cast.cpp
Functional Casts & Value InitializationDoneValue initialization of scalars and typedef aliases (T(), zero-initialized) and explicit functional conversions (Type(val))tests/c_basics/types/value_init_scalar.cpp
Scalar Pseudo-DestructorsDoneNo-op pseudo-destructor calls on scalar types (p->~T(), x.~T()), preserving receiver evaluation and side effectstests/c_basics/types/pseudo_destructor_scalar.cpp
Destructors via Typedef AliasesDoneExplicit destructor calls resolved through typedef aliases (sp->~ClassT()), verifying target class identitytests/classes_oop/constructors_destructors/destructor_via_typedef.cpp
Multiple & Virtual InheritanceOut of ScopeSingle/linear inheritance supported; multiple and virtual base specifiers are rejectedtests/negative/multiple_inheritance.cpp, tests/negative/virtual_inheritance.cpp
Exceptions (throw)Diagnosedthrow keyword recognized and rejected with explicit target diagnostic (C++ exception handling ('throw') is not supported on this WebAssembly target)tests/negative/throw_unsupported.cpp

Known Limitations & Design Rules

1. Language Semantics & Edge Cases

  • Copy Elision: Prvalue initialization is elided as guaranteed by C++17 (T x = T(1);). However, return of named local variables requires running the copy constructor.
  • Null Pointer Constants & Pointer Conversions:
    • Integer literal zeroes (0, 0u) and nullptr (std::nullptr_t, decltype(nullptr)) qualify as null pointer constants. Zero-valued variables, non-zero integers, and false are rejected.
    • Qualification conversions require every subsequent indirection level to be const when adding const to an intermediate level (int** converts to const int* const*, but not const int**).
    • Object pointers convert implicitly to void*; converting void* to a typed pointer requires static_cast<T*>.
  • String Literal Semantics: String literals have type const char[N] with a null terminator (sizeof("hello") == 6). They decay to const char* for call arguments and pointer assignments, and cannot bind to char*.
  • Multiple and Virtual Inheritance: Explicitly rejected at parse time:
    • Second base specifier yields: multiple inheritance is not supported
    • virtual base specifier yields: virtual inheritance is not supported
  • Operator Overloading Boundaries: User-defined operator overloads for arithmetic, relational, bitwise, assignment, subscript [], smart-pointer ->, dereference *(), functor (), postfix ++/--, and conversion operators operator T() are supported. Method ref-qualifier overloading with const-lvalue references (const &) is explicitly rejected with const overloading is not supported.
  • Chained operator-> & Cycle Detection: In accordance with C++17, member access via -> recursively resolves through chained operator->() overloads returning class objects or references until a raw struct pointer is reached. Cycle detection prevents compile-time recursion loops (circular operator-> delegation on '<class>'), and recursion depth is budgeted to 128 hops.
  • C++17 Lambda Expressions: Lambdas desugar into anonymous closure structs (__lambda_N) holding captured state as either by-value copies or references. The synthesized operator() is const-qualified unless marked mutable, enforcing immutability on by-value captures. Return types can be explicitly annotated with trailing return syntax (-> T) or automatically deduced from return statements. Captureless lambdas ([]) synthesize a static __invoke trampoline enabling implicit conversion to standard C function pointers (R (*)(P...)), including as return statement targets and via unary + decay (+[](){}). Default captures (=, &) must strictly appear first in the capture list, and free-variable discovery traverses RangeFor, StructuredBinding, and nested Lambda/New constructs.
  • List Initialization & Aggregates: Braced initializer lists ({...}) work across variable declarations, namespace-scope (global) variables, constructor member initializers (: member{val}), returns, call arguments, assignments, typed temporaries (Type{args...}.member()), and heap allocations (new T{...}, new T[n]{...}).
    • Direct-list initialization allows selecting explicit constructors; copy-list initialization rejects them. Empty braces ({}) value-initialize scalars and enums to zero, clear aggregate fields, or call default constructors.
    • Under C++17 aggregate rules, classes qualify as aggregates when they have no user-declared constructors, no private or protected non-static data members, no virtual functions, and no virtual or private base classes. Public non-virtual bases initialize as initial subobjects, either with nested braces (Derived{{base_args}, derived_args}) or flattened across the outer list.
    • Narrowing conversion checks follow C++17 [dcl.init.list] p7, rejecting conversions from floating-point to integer, double to float (unless an exact constant literal), and between integer types with sign changes or smaller ranges. Compile-time constant expressions, including negative integer literals, are accepted when the value fits the destination type.
    • Single-object new T{...} direct-initializes the heap object. Array new T[n]{...} initializes explicit elements and runs a WebAssembly loop to value-initialize omitted trailing elements up to n.
    • Initializer-list constructors taking std::initializer_list<T> receive a frame-backed pointer-and-size view. The backing array stays live through the full expression; elements of local initializer-list variables are destroyed at scope exit.
    • Multiple viable initializer-list constructors are ranked by element conversions: exact matches beat integral promotions, which beat other standard conversions. A narrowing candidate is discarded, and its diagnostic is reported only when no viable candidate remains. Empty braces use the initializer-list constructor when the class has no default constructor.
    • Nested brace lists such as std::vector<std::vector<int>> v{{1, 2}, {3, 4}} are resolved against the chosen element type after constructor selection.
    • Namespace-scope lists and braced containers are initialized before main runs. The backing array of a namespace-scope std::initializer_list is placed in main's frame, which outlives every use of the list.
  • Extended Casts (reinterpret_cast): Supports C++17 reinterpret_cast<T>(expr) between pointer types, pointer and integer types (matching the 32-bit ILP32 pointer width), and reference types (reinterpret_cast<T&>(v)). Does not invoke user-defined conversion operators or constructors. Scalar floating-point reinterpretations by value are rejected; bit patterns of floats can be inspected via pointer or reference reinterpretation (e.g. *reinterpret_cast<uint32_t*>(&f)).
  • Template Core:
    • Class templates and function templates support type parameters (template <typename T>). Non-type parameters, template template parameters, variadic templates, and explicit specializations (template <>) are rejected with explicit diagnostics.
    • Instantiation follows a single-phase lookup model (ADR 0010). The parser preserves template declarations in the AST (TemplateDecl), and semantic analysis resolves names and types during concrete specialization.
    • Type resolution recursively unwraps pointers, references, const qualifiers, and arrays, generating concrete struct layouts before calculating member access offsets.
    • Non-template structs compute layouts after resolving template fields, giving fields valid offsets and sizes. Non-template functions accept and return template instance types.
    • Class template member methods instantiate lazily on first call, address-of reference, or operator overload lookup (operator[], unary operators). Unused member methods are neither typechecked nor emitted into WebAssembly.
    • Non-virtual class template destructors instantiate eagerly alongside virtual methods so synthesized cleanup logic can drop values on scope exit. Dynamically instantiated template classes containing fields with non-trivial destructors synthesize cleanup methods and copy operations.
    • Function template overload resolution deduces type arguments from values, references, const references, top-level const pointers, and template instance arguments. Candidate registration tracks overloads sharing identical parameter counts by signature. Explicit template arguments (func<int>(val), func<Inner<int>>(val)) override deduction and parse nested template types. Default argument expressions fill omitted trailing parameters for both free and member template functions. Exact non-template function overloads take precedence over template specializations.
    • Out-of-class method definitions match class template and concrete struct declarations by parameter types and const qualification, including across multi-part namespace paths (Outer::Inner::Class::Class()).
    • Member template parameters shadow outer class template parameters with identical names during class instantiation.
    • Expression calls on struct instances dispatch to operator() only when an explicit call operator or member template operator() exists.
    • Nested class declarations inside class templates clone and specialize on outer template instantiation, generating qualified types (such as Container<int>::Node), computing distinct field layouts, and registering member methods.
    • Nested class type specifiers (Outer::Inner) enforce access control during type resolution. Private nested types can only be referenced from within the enclosing class, its member methods, or template specializations parameterized with the nested type. Referencing private nested types externally triggers a compile diagnostic (tests/negative/nested_type_private_access.cpp). Nested class short names remain scoped to the outer struct and do not pollute the global namespace (tests/negative/nested_class_unqualified_leak.cpp).
    • Chained dependent type aliases resolve iteratively to a fixed point during template specialization, supporting arbitrary alias chains without fixed loop bounds (tests/templates_operators/template_nested_alias_chain.cpp). Member type aliases in the std namespace are restricted to templates actually defined within std.
    • Dependent member type specifiers require the typename prefix (typename Container<T>::iterator). Unqualified typename or non-type usage is rejected at parse time.
    • Instantiation recursion is limited to 500 levels (template instantiation depth exceeded (limit: 500)).

2. Nesting Limits per Construct

To protect WebAssembly engine shadow stacks from exhaustion when compiling deep programs in Web Workers, the compiler enforces per-construct nesting budgets (src/depth.rs). One construct cannot exhaust the budget of another:

ConstructLimitDeepest Accepted Input (Native & Wasm)
Expressions4,000Parenthesized conditional costs 2 levels
Parentheses1,6001,600 nested parentheses
Call Argument Lists1,5001,500 nested calls
Statements1,6001,599 nested if statements
Compound Blocks1,6001,599 nested {} blocks
Declarations1,6001,600 nested declarations
Type Expressions1,6001,600 nested type qualifiers
Preprocessor Conditions1,6001,600 nested #if conditions
Include Depth128128 nested #include directives (129 is rejected)

These limits are verified by tests/nesting.rs and tests/wasm_stack_safety.rs.

Wide left-associative expressions (sums of 20,000 terms), string concatenations (4,000 terms), and else-if chains (5,000 branches) are flattened iteratively and do not consume recursion depth.

3. Printf Runtime Specifications

The embedded printf engine (src/runtime/format.rs) supports:

  • Specifiers: %d, %i, %u, %o, %x, %X, %c, %s, %e, %E, %f, %g, %G.
  • Modifiers: h, hh, l, ll, and z.
  • Flags: 0 (zero-pad), - (left-align), + (sign), (space sign), # (alternate form).
  • Dynamic precision: .* is supported. (Dynamic width * is not implemented).
  • Unsupported conversions: %p and %n.
  • NaN and Infinities: Zero padding falls back to spaces; sign of NaN is implementation-defined.