Skip to content

C++ Mode v0.3.0

Latest

Choose a tag to compare

@pepc84 pepc84 released this 15 Jul 00:24

v0.3.0 — Parser Hardening: C++17/20 Syntax Coverage

This release is a major parser hardening milestone. Across stress test rounds 4 through 10, the recursive-descent parser was pushed against increasingly exotic C++17/20 constructs until it either passed or was fixed. The result is substantially broader syntax coverage with fewer silent misparsings.


Critical Bug Fix

peek() was mutating pos as a side effect. peek() called skipCommentsAt() which advanced pos past comment tokens. This meant that when a comment appeared between two tokens, checkKeyword("template") would see the keyword correctly, but the immediately following checkOp("<") would see the keyword again instead of <, because pos had already moved. This caused template<Numeric T> to be misidentified as an explicit template instantiation, silently swallowing entire function definitions. Fixed by making peek() scan forward without mutating pos.


Parser

  • consteval and constinit added to the keyword set and all qualifier loops
  • Explicit template instantiation (template class std::vector<int>;) consumed verbatim before namespace wrapping
  • Concept-constrained template parameters (template<Numeric T> where Numeric is a concept name)
  • Global structured binding (auto [a, b] = MyPair{...}; at file scope) hoisted to namespace scope
  • Bit field declarations (unsigned int x : 1; in struct members)
  • __attribute__((...)) in trailing and inline positions after function declarations and variable names
  • Variadic pack expansion in params (Args&&... args) now sets isVariadic from the type-level ...
  • Pack expansion in call arguments (f(args...)) emits correctly
  • Local struct definitions inside function bodies now emit the struct before the following variable declaration
  • Local struct forward declarations (struct Foo; inside a function) consumed silently
  • Variable template specialization (zero<float> = 0.0f) parsed correctly in parseFunctionOrVariableName
  • extern "C" and extern "C++" linkage specifications parsed; block form recurses into items
  • explicit(...) conditional explicit specifier (C++20) consumed before constructor dispatch
  • friend declarations and definitions consumed verbatim in class bodies, including templated friends with bodies
  • alignas(...) before struct/class names (struct alignas(64) CacheLine)
  • [[attributes]] before struct/class names consumed in parseTypeDef
  • Constructor name matching for specializations (Grid<T, N, false> matches constructor Grid(...) by base name)
  • parseTemplateDefaultValue now tracks {} depth so < inside lambda bodies does not abort angle bracket parsing
  • looksLikeTemplateArgList now tracks () and {} depth so { inside decltype(T{}) does not cause the lookahead to bail
  • Brace initialization in constructor initializer lists (m{{1,0},{0,1}})
  • Specialization args in parseTypeDef use a manual depth-tracked token scan rather than parseTemplateArgList, which handles cases like Grid<T, N, false>
  • System header filtering in preprocessMacros: g++ -E output is now filtered to only keep tokens from the sketch file itself, preventing STL internals from reaching the parser

AST

  • FunctionDecl.isDefault and FunctionDecl.isDelete store and emit = default and = delete, fixing linker errors from virtual ~Base() = default
  • LambdaExpr.isMutable stores the mutable keyword

CodeGen

  • = default and = delete emitted for function declarations
  • mutable emitted after the lambda parameter list, before the -> return type
  • Trailing decltype(...) return types emitted as auto name(params) -> decltype(...)

CppBuild

  • TopLevelStatement items like structured bindings hoisted to namespace scope rather than emitted as struct Sketch members
  • Explicit template instantiations emitted before namespace Processing {
  • preprocessMacros filters system header content out of g++ -E output

Stress Test Coverage

Rounds 4 through 10 cover: nested namespaces, constexpr virtual, designated initializers, pack expansion, operator new/delete overloads, placement new, partial template specialization, variadic templates, template template parameters, requires clauses, the spaceship operator, constexpr if, multiple inheritance, user-defined literals, CRTP, policy-based design, concept constraints, variable templates, lambda default template arguments, structured bindings, three-way comparison, __builtin_* functions, enum class with bitwise operators, nested initializer lists, and complex SFINAE patterns.