Missing Features and C++20 Conformance
April 28, 2026 · View on GitHub
This document tracks missing C++20 features and implementation gaps in FlashCpp.
Last Updated: 2026-03-05 Overall C++20 Conformance Grade: A
- Parser: 97% complete
- AST: 97% complete
- Code Generation: 90% complete
- Standard Library: 81% of headers compile on Linux/GCC mode
Summary
Core C++20 Parsing: Nearly complete! The parser has excellent coverage of C++20 features including concepts, requires expressions, templates, and modern syntax. Most missing features are in code generation edge cases and advanced language constructs.
Status: All critical parsing features for C++20 are implemented. Main remaining gaps are:
- Coroutines (keywords recognized, parsing incomplete)
- Modules (not implemented)
- Some code generation edge cases
- Advanced standard library features (ranges, coroutines)
C++20 Features Status
Fully Implemented ✅
Concepts and Constraints (A+)
- Concept definitions:
concept Arithmetic = std::is_arithmetic_v<T>; - Requires clauses on templates:
template<typename T> requires Concept<T> - Trailing requires on functions:
void func() requires constraint { } - Requires expressions (all 4 requirement types):
- Type requirements:
typename T::type; - Simple requirements:
expression; - Compound requirements:
{ expr } noexcept -> Concept; - Nested requirements:
requires constraint;
- Type requirements:
- Constraint composition: conjunctions and disjunctions
- Abbreviated function templates:
void func(Concept auto x) - Concept subsumption and ordering
Template System (A)
- Template parameters: type, non-type, template template parameters
- Parameter packs:
typename... Args - Non-type template parameters with
auto:template<auto V> - Template specializations: partial and full
- Fold expressions:
(args + ...)and all variants - Template template parameters:
template<typename> class Container - Variadic templates: All patterns including nested instantiation
- Perfect forwarding:
std::forwardpreserves reference types - SFINAE: Substitution failures handled gracefully
- Out-of-line template member definitions
- Out-of-line nested class member definitions:
template<T> class Foo<T>::Bar { ... }
Spaceship Operator <=> (A+)
- Parsing: Complete
- Defaulted
operator<=>with memberwise comparison: ✅ Implemented - Synthesized comparison operators (==, !=, <, >, <=, >=) from defaulted
<=>: ✅ Implemented - Multi-member structs compared in declaration order: ✅ Works
- Nested struct member delegation (calls inner
<=>for struct members): ✅ Implemented - Inline expression use
(a <=> b) < 0in ternary/if/comparisons: ✅ Implemented - Mixed member types (int + char + short + long long): ✅ Works
- Signed/unsigned member comparisons: ✅ Correct (uses
isSignedType()) - User-defined
operator<=>with custom return types: ✅ Works - Reversed operand order and self-comparison: ✅ Works
- Template struct
operator<=>: ✅ Works std::strong_ordering/std::weak_ordering/std::partial_orderingreturn types: ✅ Works (<compare>header compiles)
Modern Syntax (A)
- Constexpr if:
if constexpr (condition)with nesting - Range-based for loops:
for (auto x : container)with arrays, begin/end iterators, const refs - Range-based for with initializer:
for (int i = 0; auto x : container) - Spaceship operator
<=>: Complete (see above) - Designated initializers: Full support
- Auto type deduction: Basic patterns working
- Structured bindings:
auto [a, b] = expr; - Using declarations and aliases: Full support (namespace-level; member using-declarations for inheritance not yet supported — see Known Issues)
- Enum classes: Full support
- constinit variables: Full support (global and local static)
- consteval functions and immediate-invocation enforcement: Full support
Type System (A)
- Type traits: 37+ compiler intrinsics (
__is_integral,__is_void, etc.) - Type properties: const, volatile, signed/unsigned traits
- Type relationships:
__is_same,__is_base_of,__is_convertible - Array traits: bounded/unbounded array detection
- RTTI:
dynamic_cast,typeidsupport - Pointer types: multi-level pointers, pointers to members
- Function pointers: Full support
- Member function pointers: Full support
- Reference types: lvalue and rvalue references
Control Flow (A)
- All loops: for/while/do-while (with C++20 init statements)
- Range-based for: Arrays and user-defined iterator types
- Switch statements: case/default labels, fallthrough
- Goto: Basic support
- Exception handling: try/catch/throw with multiple handlers, rethrow, nested try-catch
- Return statements: With and without expressions
- Break/continue: Full support
Exception Handling (A)
- Try/catch/throw: Full implementation
- Multiple catch handlers and catch-by-type matching
- Nested try-catch blocks
- Rethrow (
throw;) - LSDA (.gcc_except_table) generation
- .eh_frame / DWARF CFI generation
- Funclet-style catch block codegen
- Integration with
__cxa_throw,__cxa_begin_catch,__cxa_end_catch
OOP Features (A)
- Classes and structs: Full support
- Inheritance: Single, multiple, virtual inheritance
- Virtual functions: Full support with vtables
- Abstract classes: Pure virtual functions
- Constructors and destructors: Full support
- Conversion operators: Full support
- Static members: Full support
- Const member functions: Full support
- Access specifiers: public/protected/private
finalkeyword: Full support (class-level and method-level)
Variadic Functions (A)
- System V AMD64 ABI: Fully implemented
- Register save area for integer and floating-point registers
- va_list structure initialization
- va_arg with integer, floating-point, and struct arguments (≤8 bytes and 9–16 bytes)
- Overflow to stack arguments
__VA_OPT__preprocessor macro: Fully implemented
Partially Implemented ⚠️
Variable Template Partial Specialization (100% complete)
- Structural pattern matching for multi-arg and dependent initializers/types: ✅ Works
- Simple type, pointer, reference, rvalue-reference specializations: ✅ Works
- Inner template argument deduction (e.g.,
v<pair<T,U>>deducing T and U): ✅ Works - Deeply nested patterns with distinct templates (e.g.,
v<A<B<T,U>,C<V>>>): ✅ Works - Same template in multiple nested positions (e.g.,
v<Pair<Pair<A,B>,Pair<C,D>>>): ✅ Works
Code Generation Edge Cases
- Complex template instantiations (90% complete)
- Basic specializations: Work
- Complex dependent types: May have issues
- Advanced pack expansion patterns:
- Simple pack expansion: Works
- Nested pack expansion: May have issues
- Pack expansion in complex contexts: May have issues
Coroutines (20% complete)
- Keywords recognized:
co_await,co_yield,co_return - Basic parsing skeleton exists
- Full expression parsing and code generation not implemented
- Coroutine frame management not implemented
- Awaitable type checking not implemented
- Required for:
<coroutine>header support
Standard Library Support
- Linux/GCC mode (55/68 headers compile, 81%):
- Compiling:
<limits>,<type_traits>,<compare>,<version>,<source_location>,<numbers>,<initializer_list>,<optional>,<any>,<utility>,<concepts>,<bit>,<string_view>,<string>,<algorithm>,<span>,<tuple>,<vector>,<map>,<set>,<iostream>,<atomic>,<new>,<exception>,<typeinfo>,<typeindex>,<numeric>,<variant>pending fix,<cset*>,<c*>C headers,<barrier>,<latch>,<stdfloat>,<spanstream>,<print>,<expected>,<text_encoding>,<stacktrace>, and more - Parse errors remaining:
<ratio>,<array>,<memory>,<functional>,<ranges>,<chrono>,<shared_mutex>,<coroutine>,<variant>
- Compiling:
- MSVC/Windows mode: Limited support (most headers fail on MSVC-specific constructs)
<type_traits>: Good support (most common traits work, 37+ intrinsics)<utility>:std::forward,std::move,std::swapwork
Not Implemented ❌
Modules (0% complete)
- No
importkeyword support - No
modulekeyword support - No module dependency tracking
- No module interface/unit separation
- Traditional header-based compilation only
- Required for: C++20 module system
Ranges Library (range views/adaptors)
- Range concepts: Implemented (via
<concepts>) - Range views/adaptors: Not implemented
std::views::transformstd::views::filterstd::views::takestd::views::drop- Other adaptors
- Range algorithms: Not implemented
std::ranges::for_eachstd::ranges::findstd::ranges::count- Other algorithms
Advanced C++20 Features
- Comparison category types enforcement:
std::strong_orderingparsing: works via<compare>header- Compiler-synthesized comparison categories: Not auto-selected
- Some constexpr evaluation edge cases
- Constexpr
std::stringandstd::vector - Advanced SFINAE patterns (very complex cases)
MSVC Standard Library Compatibility
- Most MSVC headers fail at parse time due to SAL annotations,
_When_macros, and UCRT wrapper patterns - Current top blockers: SAL macro parse path, UCRT formatted I/O wrapper call resolution, MSVC STL
yvals.hcompatibility
Implementation Priorities
High Priority (Blocking Real-World Code)
-
Standard Library Remaining Parse Errors
- Fix aggregate brace initialization for template types (
std::array<int,5> arr = {1,2,3,4,5}) - Fix dependent base class resolution in template structs
- Fix variable template evaluation in
static_assertcontexts - Fix
<variant>struct/class definition parse error
- Fix aggregate brace initialization for template types (
-
MSVC Standard Library Compatibility
- Improve SAL annotation handling
- Fix UCRT wrapper call resolution
- Improve MSVC STL compatibility
-
Constexpr Evaluation
- Improve constexpr evaluation engine
- Support constexpr in more contexts
Medium Priority (Important Features)
-
Coroutines
- Implement coroutine frame allocation
- Implement awaitable type checking
- Add coroutine-specific code generation
- Support
co_await,co_yield,co_returnfully
-
Ranges Library
- Implement range adaptors (views)
- Implement range algorithms
- Add range constraint checking
-
Code Generation Edge Cases
- Improve complex template instantiation reliability
- Stabilize pack expansion in all contexts
Low Priority (Advanced Features)
-
Modules
- Implement
import/exportkeywords - Add module dependency tracking
- Implement module interface parsing
- Support module partitions
- Implement
-
Advanced Metaprogramming
- Support more complex SFINAE patterns
- Improve template instantiation performance
- Add better error messages for template failures
-
Implicit Conversion in Non-Subscript Operators
- Extend the sema selection infrastructure (currently used for built-in subscript) to other built-in operators that may require implicit pointer/array conversion.
- Unify the general user-defined conversion selection path across sema and codegen so that all implicit-conversion-sequence selection is owned entirely by sema and codegen only emits the already-selected conversion.
-
Conversion Operators Returning Array References
- Support
operator T(&)[N]()(conversion operator returning a reference to array) in contexts that require array-to-pointer conversion (e.g. built-in subscript). - Currently only pointer-returning conversion operators are handled.
- Support
Grammar Coverage Analysis
Expression Grammar: 97% Complete
Implemented:
- All binary operators (precedence 3-17)
- All unary operators
- All postfix operators
- Primary expressions (literals, identifiers, lambdas)
- C++ casts (static, dynamic, const, reinterpret)
- Ternary conditional operator
- Spaceship operator
<=> - Fold expressions
- Lambda expressions (including captures, constexpr lambdas, template lambdas)
- Requires expressions
- Range-based for loop syntax
Partially Implemented:
- Some complex expression patterns may fail
- Coroutine expressions (co_await, co_yield, co_return)
Declaration Grammar: 100% Complete
Implemented:
- All declaration forms
- Function declarations and definitions
- Variable declarations with all initialization forms
- Class and struct declarations (including
final) - Template declarations (all forms)
- Concept declarations
- Enum declarations
- Using declarations and aliases
- Namespace declarations
- Out-of-line member definitions
- Out-of-line nested class member definitions
- Conversion operators
- consteval/constexpr/constinit specifiers
Statement Grammar: 97% Complete
Implemented:
- if/else (with C++20 init statements)
- for loops (with C++20 init statements)
- Range-based for loops
- while loops
- do-while loops
- switch statements
- goto and labels
- return statements
- break/continue
- try/catch/throw
- Expression statements
- Compound statements (blocks)
Partially Implemented:
- Some complex control flow patterns may have issues
Template Grammar: 97% Complete
Implemented:
- Type parameters (
typename T,class T) - Non-type parameters (int N, bool B, auto V)
- Template template parameters (
template<typename> class C) - Parameter packs (
typename... Args) - Template specializations (partial and full)
- Default template arguments
- Variadic templates
- Template member functions
- Template member classes
- Template aliases
- Template argument deduction
- SFINAE
- Out-of-line nested class definitions
- Deeply nested variable template deduction: same template in multiple positions (e.g.,
v<Pair<Pair<A,B>,Pair<C,D>>>)
Partially Implemented:
- Some complex template patterns may fail
Code Reuse and Architecture
Parser Architecture Quality: 8.5/10
Strengths:
- Unified declaration parsing with context-driven dispatch
- Shared specifier parsing for all declaration types
- RAII scope guards for resource management
- Expression context system for template disambiguation
- Clean 1:1 mapping from C++ grammar to parser functions
Code Reuse Opportunities:
- Template argument parsing - 3+ locations have similar logic (~200 lines to consolidate)
- Cast parsing - C++ casts, C-style casts, functional casts share type parsing (~150 lines)
- Member access patterns -
.,->,.*,->*could be unified (~100 lines) - Error handling - Common patterns could be extracted (~300 lines)
Test Coverage
Total Test Cases: 1280+ (1250+ .cpp files in tests/, plus 34 standard header tests in tests/std/)
Categories with Good Coverage:
- Basic arithmetic: ✅
- Control flow: ✅
- Templates: ✅
- C++20 concepts: ✅
- Type traits: ✅
- SFINAE: ✅
- OOP features: ✅
- Exception handling: ✅
- Variadic functions: ✅
- Spaceship operator: ✅
- Range-based for: ✅
Categories with Partial Coverage:
- Standard library headers: ⚠️ (55/68 on Linux/GCC, limited on MSVC)
- Complex templates: ⚠️
- Constexpr evaluation edge cases: ⚠️
Categories with Poor Coverage:
- Coroutines: ❌
- Modules: ❌
- Ranges library (adaptors/algorithms): ⚠️
How to Update This Document
When updating C++20 conformance status:
- Update conformance percentages in Summary section
- Move features between sections (Not Implemented → Partially Implemented → Fully Implemented)
- Add newly discovered missing features
- Update test coverage statistics
- Update priority levels based on blocking impact
When implementing a missing feature:
- Change status in appropriate section
- Add implementation notes
- Update test coverage
- Document any limitations or known issues
- Cross-reference with related features
References
Parser Code: src/Parser.cpp - Main parsing logic
Parser Types: src/ParserTypes.h - Shared parsing structures
AST Definitions: src/AstNodeTypes.h - AST node types
Code Generator: src/IrGenerator.h - AST to IR translation
IR Converter: src/IRConverter.h - IR to assembly conversion
ELF Writer: src/ElfFileWriter.h - ELF object file generation (exception tables, DWARF)
LSDA Generator: src/LSDAGenerator.h - Language-Specific Data Area for exceptions
Test Directory: tests/ - Test suite (1200+ test cases)
tests/cpp20_integration/- C++20 feature teststests/std/- Standard library header teststests/test_type_traits_intrinsics.cpp- Type trait intrinsicstests/test_sfinae_*.cpp- SFINAE test casestests/test_exceptions_*.cpp- Exception handling teststests/test_spaceship_*.cpp- Spaceship operator tests
Known Issues
Enum ADL may fail for enums in anonymous namespaces
Severity: Low (conformance issue, edge case)
Enum ADL (src/SymbolTable.h, lookup_adl and lookup_adl_only) relies on TypeInfo::namespaceHandle() returning the correct enclosing namespace for enum types. This is set by add_enum_type() in src/AstNodeTypes.cpp, which receives a NamespaceHandle from the parser.
Enums declared inside named namespaces and enums nested inside class bodies within named
namespaces now work correctly (fixed 2026-03-18 — nested enum qualified-name registration
walks the full struct_parsing_context_stack_).
However, enums in anonymous namespaces have not been verified. Anonymous namespaces have a unique internal handle. If this handle is not correctly propagated, ADL would fail to find functions in the anonymous namespace.
Example (untested):
namespace {
enum class Color { Red, Green, Blue };
int classify(Color c) { return static_cast<int>(c); }
}
int main() {
// ADL should find the anonymous-namespace classify() because
// Color's associated namespace is the anonymous namespace.
return classify(Color::Red);
}
Fix: Verify that parse_enum_declaration passes the correct anonymous namespace handle to add_enum_type. Add tests for anonymous namespace enum ADL.
Member using-declarations for inherited names not supported
Severity: Medium (conformance issue, affects idiomatic C++ inheritance patterns)
C++ [namespace.udecl]/1 allows a using-declaration inside a derived class to re-introduce hidden base-class members:
struct Base {
int getValue(int x) const { return x; }
};
struct Derived : Base {
using Base::getValue; // un-hides Base::getValue(int)
int getValue() const { return 42; }
};
int main() {
Derived d;
d.getValue(); // OK — calls Derived::getValue()
d.getValue(10); // OK — calls Base::getValue(int) via using-declaration
}
FlashCpp currently parses using X::Y; inside a struct body and registers the member name
in the struct parsing context (imported_members), but this path is designed for dependent
template base classes (e.g., using std::__is_integer<_Tp>::__value;). It does not:
- Resolve
Baseas a base class of the enclosing struct - Copy or alias the base-class member function overloads into the derived class's member function list
- Interact with the name-hiding logic in
StructTypeInfo::findMemberFunctionRecursiveorsearchStructMembersto allow hidden overloads to become visible again
Without this, derived classes that use using Base::foo; to bring base overloads into scope
will not have those overloads available for overload resolution.
Fix: When parsing using Base::member; inside a struct body where Base is a known base
class, copy the matching base-class StructMemberFunction entries into the derived struct's
member_functions list (or add a separate using_imported_members list consulted during
lookup). Update findMemberFunctionRecursive and searchStructMembers to include
using-imported members before applying the name-hiding early-return.