You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This document is the authoritative registry of all C-Next compiler error codes. When adding new error codes, assign the next available code in the appropriate range and update this document.
A row marked (reserved) names a code that is spoken for but not yet implemented. It is
listed because "next available" is read from this table: a code reserved elsewhere and
recorded nowhere gets assigned a second time, and the collision is silent — the registry
is hand-maintained and has no gate, while npm run diagnostics:manifest:check only sees
codes that already have a fixture.
Identifier ends with, or contains consecutive, underscores
Remove the trailing underscore, or collapse __ to _
logic/analysis/IdentifierSyntaxAnalyzer.ts
E0202
Identifier begins with the reserved prefix cnx_
Drop the reserved prefix
logic/analysis/IdentifierSyntaxAnalyzer.ts
E0203
Two source files produce the same include guard
Rename one so the generated headers stay distinguishable
Transpiler.ts
E0204
External identifiers not distinct within the target's significant characters
Shorten the scope name or the member names
Transpiler.ts, logic/symbols/SymbolTable.ts
E0227
Parameter cannot start with function name prefix
Consider renaming to a name that doesn't start with function name
logic/analysis/ParameterNamingAnalyzer.ts
Related: ADR-063 and Issue #1117 (E0201); ADR-063 and Issues #1131/#1132 (E0202);
ADR-063 and Issues #1133/#1134 (E0203); ADR-063 and Issue #1307 (E0204); Issue #227 (E0227)
E0201 reserves __ as the qualified-name separator so that Scope__member cannot
collide with a plain identifier. A leading underscore is legal — injectivity
constrains only the separator's left boundary. Checked on declarations only, so
references to C/C++ header symbols such as __disable_irq() are unaffected.
E0202 reserves the cnx_ prefix, compared case-insensitively, for names the
transpiler generates — cnx_tmp<N>, cnx_len_<var>, cnx_clamp_<op>_<type> and
the CNX_<PATH>_H include guard. It is a different guarantee from E0201: __
says which components built a qualified name, while cnx_ keeps the transpiler's
namespace and the user's disjoint. Prefix-only, so my_cnx_buffer is legal, and
declarations-only, so calling an external C symbol named cnx_foo() is fine.
E0204 is the same injectivity question asked against a budget rather than
against the whole string. E0201 makes the Scope__member join injective; C99
§5.2.4.1 then guarantees only 31 significant initial characters in an external
identifier, so a join that is injective can still land on one identifier once the
target truncates it. The __ separator costs two characters per level and the
scope name costs its full length, so the budget is consumed by the encoding, not
by the author's naming (#1307). Reported against
the target description's external_identifier_chars, not a hardcoded 31 —
the limit belongs to the C target. Rule 5.1 is a whole-program property, and a
program has exactly one target (ADR-049), so the budget is that target's. Scoped to identifiers C-Next generates with
external linkage: private members are static and get the 63-character
internal budget (#1338), types have no linkage, and a C/C++ header's identifiers
are not C-Next's to rename. The message names cnxScopedName rather than the
generated identifier, per #1292.
E0203 fires when two files in one compilation map to the same include guard.
Guards are built from the project-relative path, and conversion to upper case
is lossy, so
mod-a.cnx and mod_a.cnx collide, as do filenames differing only by case.
ADR-063 diagnoses that residue rather than hashing or escape-encoding the path,
which would trade away the readability of the generated artifact. The requirement
is only that it is never silent: before this check the preprocessor skipped the
second header and the program ran with a wrong value.
E03xx — Struct Fields and Initializers
Code
Message
Help
Source
E0355
Struct field uses a reserved property name
Reserved names (e.g., .length). Use 'len', 'size', or 'count'
logic/analysis/StructFieldAnalyzer.ts
E0356
(retired) — was: redundant type in a struct initializer
Removed with the grammar alternative it rejected (#1322): Point { x: 1 } was never valid C-Next, since every position that consumes a value already declares the type. It is a parse error now. Not reassigned
TRANSPILE/1-Analyze/StructLiteralAnalyzer.ts
E0357
A struct initializer with no written type, in a position that declares none
Move it where a type is declared: a variable, an assignment target, a field, an argument, or a return
TRANSPILE/1-Analyze/StructLiteralAnalyzer.ts
E0358
A struct initializer gives a value to a type that is not a struct (a primitive, a string, a bitmap, an enum, a function type, or a header's scalar, pointer or function pointer)
Give a value of the type itself; a bitmap's is its backing integer, set field by field after (ADR-034)
TRANSPILE/1-Analyze/StructLiteralAnalyzer.ts
E04xx — Symbol Resolution / Initialization
Code
Message
Help
Source
E0381
Use of possibly/uninitialized variable
Variable must be initialized before use
logic/analysis/InitializationAnalyzer.ts
E0422
Function called before definition
Define function before calling it
TRANSPILE/1-Analyze/FunctionCallAnalyzer.ts
E0423
Recursive function call (MISRA C:2012 Rule 17.2)
Remove recursive call
TRANSPILE/1-Analyze/FunctionCallAnalyzer.ts
E0424
Unqualified enum member — did you mean Enum.member?
Compare the enum with a member of the same enum, or cast explicitly
TRANSPILE/1-Analyze/EnumTypeSafetyAnalyzer.ts
E0435
Scope's own member referenced through the scope's name (ADR-016)
Use this.member inside the scope; global.Scope.member is allowed when deliberate
TRANSPILE/1-Analyze/ScopeAccessAnalyzer.ts
E0436
Private scope member reached from outside its scope (ADR-016)
Mark the member public, or reach it through a public one
TRANSPILE/1-Analyze/ScopeAccessAnalyzer.ts
E0437
Global enum or register shadowed inside a scope and reached bare (ADR-016)
Write global.Name.member; the bare name resolves to the shadow
TRANSPILE/1-Analyze/ScopeAccessAnalyzer.ts
Related: ADR-030 (E0422, E0423, E0426, E0427 — one define-before-use promise
enforced in the call, type and value positions; the ADR's ## Diagnostics table
is where the promise is stated), ADR-016 (E0425 — a reopened scope composes, but
its members stay unique)
E0429 (#1336) is the type position's other answer: the name IS declared, as a
register, and a register is not a type. ADR-004 makes a register a binding to memory,
not a type name, so Control c; had no type behind it and the transpiler emitted C the
compiler rejects at exit 0. Reporting E0426 ("not defined") for a register declared a
few lines up would describe the transpiler rather than the source, which is why this is
its own code rather than a second message on E0426.
ADR-111 would make a register name a type. It is Research, and its own header states
that while it is Research "a register is still not a type", so ADR-004 governs and this
diagnostic is correct today. When ADR-111 is implemented, E0429 is retired outright —
Control c(0x40000000) becomes the instantiation form that ADR designs. Grep ADR-111
to find every site that has to change together.
E0426/E0427 (#1312, #1353, #1398) complete the set: an undeclared name is diagnosed
in a type position, a value position and a call position (E0422) rather than only the
last. The value position is both halves of it — a name READ and the same name WRITTEN
(#1582) — in all three of ADR-016's spellings, since this.x and global.x each state
which level to search and a name visible at one level is not thereby visible at another.
What is diagnosed is the name a spelling starts from; whether a member further along a
chain exists is a separate question neither code answers.
Both are reported only where the transpiler knows the file's whole name universe —
a file including an unparsed C/C++ header keeps the previous permissive behavior, because
rejecting a type the compiler will supply is a regression while failing to diagnose is
the status quo.
Both also answer per FILE, not per run (#1398). A value declared in a sibling this file
never included is undefined here, exactly as a type is — the value check reads the
include-filtered name set rather than the run-wide symbol table, which answers "declared
anywhere in this run" and so could never reject a sibling reference. E0426 had a per-file
view from the start and E0427 did not, which is why the type case was diagnosed and the
identical value case compiled to C that gcc rejects. What remains permissive is the
foreign-header case above: no edge connects a .cnx to the headers it includes, so
include-visibility is not derivable for a C or C++ name.
E05xx — Include/Preprocessor
Code
Message
Help
Source
E0501
Function-like macro not allowed
Use inline functions instead
TRANSPILE/1-Analyze/DefineDirectiveAnalyzer.ts
E0502
#define with value not allowed
Use const u32 NAME <- value; instead
TRANSPILE/1-Analyze/DefineDirectiveAnalyzer.ts
E0503
Cannot #include implementation file
Only .h and .hpp files are allowed
TRANSPILE/1-Analyze/IncludeDirectiveAnalyzer.ts
E0504
.cnx alternative exists for included header
Use #include "file.cnx" for the C-Next version
TRANSPILE/1-Analyze/IncludeDirectiveAnalyzer.ts
E0505
(retired) — was: header names a pointer typedef it cannot declare
Reclassified as an internal invariant by #1322: for it to fire, a name would have to be in a header's external types and absent from the enumeration those types are collected by — a transpiler defect, not a program. Not reassigned
output/headers/BaseHeaderGenerator.ts
E0506
Included C-Next file not found
A quoted include resolves relative to the file it appears in; check the spelling
TRANSPILE/1-Analyze/IncludeDirectiveAnalyzer.ts
E0507
C++ header in a run that does not target C++
Set cppRequired: true in the config, or pass --cpp
Transpiler.ts
E0508
C++ class with a constructor initialized outside a function body
A class with a constructor is not an aggregate, so its fields are assigned one at a time, and a declaration outside a function body has no statement to assign them in
Generated header names a C-Next source that is not there
A generated header records the source it was written from; check that source is present and reachable from the include path
Transpiler.ts
E0510
Not a known target
Name a target from the catalog, exactly as it is spelled there; cnext --help lists them (ADR-049)
PARSE/4-Resolve/RunTarget.ts
E0511
Target declarations in one program disagree
A program has one target: declare the same one in every file that declares one, or declare it once (ADR-049)
PARSE/4-Resolve/RunTarget.ts
E0512
Unknown pragma
A pragma names the program's target: target, or a target description field (ADR-049)
PARSE/4-Resolve/RunTarget.ts
E0513
Invalid value for a pragma key
An integer field takes decimal digits from the schema's allowed values, a Boolean field takes true or false, and each key takes exactly one value (ADR-049)
PARSE/4-Resolve/RunTarget.ts
E0514
Incomplete target description
An inline description gives every field, like a catalog row; the help lists what is missing (ADR-049)
PARSE/4-Resolve/RunTarget.ts
E0515
The program names no target
Name one with #pragma target <name>, --target <name>, "target" in cnext.config.json, or a PlatformIO environment's board (ADR-049)
PARSE/4-Resolve/RunTarget.ts
E06xx — Sizeof Expressions (ADR-023)
Code
Message
Help
Source
E0601
sizeof() on an array parameter measures a pointer, not the array
Use .element_count for the count, or sizeof(elementType) * .element_count for the bytes
TRANSPILE/1-Analyze/SizeofAnalyzer.ts
E0602
sizeof() operand must not have side effects
MISRA C:2012 Rule 13.6: sizeof never evaluates its operand, so a call inside it does not run
Length property not available on this type (ADR-058)
.element_count needs an array, .char_count a string, .bit_length/.byte_length a sized type
TRANSPILE/1-Analyze/LengthPropertyAnalyzer.ts
E0868
Integer literal does not fit the target type's range (ADR-024)
Widen the target type, or narrow the value; an unsigned type holds no negative
TRANSPILE/1-Analyze/IntegerConversionAnalyzer.ts
E0869
Implicit narrowing or sign-changing integer conversion (ADR-024)
Use bit indexing to say which bits you mean, e.g. value[0, 8]
TRANSPILE/1-Analyze/IntegerConversionAnalyzer.ts
Register Access Modifiers (ADR-004)
Code
Message
Help
Source
E0870
Read of a write-only (wo) register member
A wo member returns nothing meaningful; read the register's readable member or keep a shadow copy
TRANSPILE/1-Analyze/RegisterAccessAnalyzer.ts
E0871
Write to a read-only (ro) register member
An ro member is const hardware; write the register's writable member, or change the declaration
TRANSPILE/1-Analyze/RegisterAccessAnalyzer.ts
E0872
Zero assigned to a write-1 (wo/w1s/w1c) register bit
Writing 0 to a write-1 register does not clear the bit; use the corresponding CLEAR register
TRANSPILE/1-Analyze/RegisterAccessAnalyzer.ts
Each subscript peels one array dimension (ADR-036) and a scalar integer/float may be
bit-indexed once (ADR-007), so flags[4][3] on a scalar u8 indexes the single bit
flags[4] — a value that is not an array. Raised for every ADR-016 spelling of the
base: bare, this. and global..
Shift Range (MISRA C:2012 Rule 12.2)
Code
Message
Help
Source
E0873
Shift amount is negative, or not below the shifted operand's bit width
Keep the amount in 0 .. width-1; shifting by the width or more is undefined behavior
TRANSPILE/1-Analyze/ShiftAnalyzer.ts
Array Declarations (ADR-035 / ADR-036)
Code
Message
Help
Source
E0874
C-style array declaration or parameter (dimensions after the name)
Put every dimension in the type: u8[4] arr, not u8 arr[4]
TRANSPILE/1-Analyze/ArrayDeclarationAnalyzer.ts
E0875
Unbounded array parameter
Write every dimension's size; the callee can trust only what is declared
TRANSPILE/1-Analyze/ArrayDeclarationAnalyzer.ts
E0876
Fill-all initializer on an array whose size is inferred
An inferred size is counted from a list; write the dimension for [v*]
TRANSPILE/1-Analyze/ArrayDeclarationAnalyzer.ts
Const Enforcement (ADR-013)
Code
Message
Help
Source
E0877
Assignment to a const variable or parameter, whole or through an element or field
Remove const from the declaration if the value must change
TRANSPILE/1-Analyze/ConstAssignmentAnalyzer.ts
E0878
A const value passed to a function's non-const parameter
Declare the parameter const, or pass a mutable copy
TRANSPILE/1-Analyze/ConstAssignmentAnalyzer.ts
Callback Typing (ADR-029)
Code
Message
Help
Source
E0879
A function's declared signature does not match the callback type it is given to
Match the type exactly: return type, parameter count, and each parameter's type, const and array-ness
TRANSPILE/1-Analyze/CallbackAssignmentAnalyzer.ts
E0880
A function that is itself a callback type given to a slot of another type
Nominal typing: only a function that is not a type may stand in for one
TRANSPILE/1-Analyze/CallbackAssignmentAnalyzer.ts
Bitmap Access (ADR-034)
Code
Message
Help
Source
E0881
A constant value, a const included, too wide for the bitmap field it is assigned to
Widen the field in the bitmap declaration, or write a value that fits
TRANSPILE/1-Analyze/BitmapAccessAnalyzer.ts
E0882
A member the bitmap does not declare
Use one of the bitmap's declared fields
TRANSPILE/1-Analyze/BitmapAccessAnalyzer.ts
E0883
Bracket indexing on a bitmap
A bitmap is addressed by named field, not by bit index
TRANSPILE/1-Analyze/BitmapAccessAnalyzer.ts
Safe Division Call Shape (ADR-051)
Code
Message
Help
Source
E0884
safe_div/safe_mod called with other than four arguments
Pass output, numerator, divisor and the value used when the divisor is zero
TRANSPILE/1-Analyze/SafeDivisionAnalyzer.ts
E0885
The first argument is not a variable to receive the result
The helper takes the output's address; declare a variable and pass it
TRANSPILE/1-Analyze/SafeDivisionAnalyzer.ts
Value Properties (ADR-058 / ADR-045)
Code
Message
Help
Source
E0886
.length is deprecated
Use .char_count, .element_count, .bit_length or .byte_length
TRANSPILE/1-Analyze/LengthPropertyAnalyzer.ts
E0887
.capacity or .size on something with no buffer
Both describe a string's buffer; use .element_count or .byte_length
TRANSPILE/1-Analyze/LengthPropertyAnalyzer.ts
Bit Access and Declaration Modifiers (ADR-007 / ADR-049)
Code
Message
Help
Source
E0888
A float bit range read at file scope
The union copy it lowers to is a statement; read it inside a function