c-next 0.2.9 → 0.2.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +941 -210
- package/dist/index.js.map +4 -4
- package/package.json +1 -1
- package/src/transpiler/Transpiler.ts +102 -7
- package/src/transpiler/__tests__/Transpiler.coverage.test.ts +170 -0
- package/src/transpiler/__tests__/needsConditionalPreprocessing.test.ts +246 -0
- package/src/transpiler/logic/analysis/ArrayIndexTypeAnalyzer.ts +12 -1
- package/src/transpiler/logic/analysis/__tests__/ArrayIndexTypeAnalyzer.test.ts +172 -0
- package/src/transpiler/logic/symbols/SymbolTable.ts +150 -0
- package/src/transpiler/logic/symbols/__tests__/SymbolTable.test.ts +98 -0
- package/src/transpiler/logic/symbols/__tests__/TransitiveEnumCollector.test.ts +1 -0
- package/src/transpiler/logic/symbols/c/__tests__/CResolver.integration.test.ts +98 -1
- package/src/transpiler/logic/symbols/c/__tests__/PointerTypedef.test.ts +47 -0
- package/src/transpiler/logic/symbols/c/collectors/FunctionCollector.ts +23 -5
- package/src/transpiler/logic/symbols/c/collectors/StructCollector.ts +118 -8
- package/src/transpiler/logic/symbols/c/index.ts +107 -30
- package/src/transpiler/logic/symbols/c/utils/DeclaratorUtils.ts +35 -0
- package/src/transpiler/logic/symbols/cnext/__tests__/TSymbolInfoAdapter.test.ts +90 -0
- package/src/transpiler/logic/symbols/cnext/adapters/TSymbolInfoAdapter.ts +40 -39
- package/src/transpiler/output/codegen/CodeGenerator.ts +32 -1
- package/src/transpiler/output/codegen/TypeResolver.ts +14 -0
- package/src/transpiler/output/codegen/__tests__/CodeGenerator.test.ts +19 -14
- package/src/transpiler/output/codegen/__tests__/TypeResolver.test.ts +7 -7
- package/src/transpiler/output/codegen/analysis/__tests__/MemberChainAnalyzer.test.ts +1 -0
- package/src/transpiler/output/codegen/assignment/AssignmentClassifier.ts +27 -4
- package/src/transpiler/output/codegen/assignment/AssignmentKind.ts +6 -0
- package/src/transpiler/output/codegen/assignment/__tests__/AssignmentClassifier.test.ts +73 -0
- package/src/transpiler/output/codegen/assignment/handlers/BitAccessHandlers.ts +4 -0
- package/src/transpiler/output/codegen/assignment/handlers/SimpleHandler.ts +92 -0
- package/src/transpiler/output/codegen/assignment/handlers/__tests__/BitAccessHandlers.test.ts +5 -2
- package/src/transpiler/output/codegen/assignment/handlers/__tests__/handlerTestUtils.ts +1 -0
- package/src/transpiler/output/codegen/generators/IOrchestrator.ts +20 -0
- package/src/transpiler/output/codegen/generators/declarationGenerators/ScopeGenerator.ts +23 -2
- package/src/transpiler/output/codegen/generators/declarationGenerators/__tests__/ScopeGenerator.test.ts +51 -0
- package/src/transpiler/output/codegen/generators/expressions/AccessExprGenerator.ts +17 -5
- package/src/transpiler/output/codegen/generators/expressions/CallExprGenerator.ts +5 -0
- package/src/transpiler/output/codegen/generators/expressions/LiteralGenerator.ts +16 -0
- package/src/transpiler/output/codegen/generators/expressions/PostfixExpressionGenerator.ts +41 -5
- package/src/transpiler/output/codegen/generators/expressions/UnaryExprGenerator.ts +25 -1
- package/src/transpiler/output/codegen/generators/statements/AtomicGenerator.ts +2 -17
- package/src/transpiler/output/codegen/helpers/ArrayAccessHelper.ts +3 -0
- package/src/transpiler/output/codegen/helpers/BitRangeHelper.ts +19 -3
- package/src/transpiler/output/codegen/helpers/NarrowingCastHelper.ts +191 -0
- package/src/transpiler/output/codegen/helpers/VariableDeclHelper.ts +35 -4
- package/src/transpiler/output/codegen/helpers/__tests__/ArrayAccessHelper.test.ts +131 -1
- package/src/transpiler/output/codegen/helpers/__tests__/AssignmentExpectedTypeResolver.test.ts +1 -0
- package/src/transpiler/output/codegen/helpers/__tests__/AssignmentValidator.test.ts +1 -0
- package/src/transpiler/output/codegen/helpers/__tests__/BitRangeHelper.test.ts +53 -2
- package/src/transpiler/output/codegen/helpers/__tests__/FunctionContextManager.test.ts +1 -0
- package/src/transpiler/output/codegen/helpers/__tests__/NarrowingCastHelper.test.ts +159 -0
- package/src/transpiler/output/codegen/helpers/__tests__/TypeRegistrationEngine.test.ts +1 -0
- package/src/transpiler/output/codegen/types/COMPOUND_TO_BINARY.ts +21 -0
- package/src/transpiler/output/codegen/types/IArrayAccessInfo.ts +2 -0
- package/src/transpiler/state/CodeGenState.ts +58 -0
- package/src/transpiler/state/__tests__/CodeGenState.test.ts +53 -0
- package/src/transpiler/state/__tests__/TranspilerState.test.ts +1 -0
- package/src/transpiler/types/ICachedFileEntry.ts +4 -0
- package/src/transpiler/types/ICodeGenSymbols.ts +8 -0
- package/src/utils/BitUtils.ts +33 -4
- package/src/utils/cache/CacheManager.ts +17 -1
- package/src/utils/cache/__tests__/CacheManager.test.ts +1 -1
package/dist/index.js
CHANGED
|
@@ -10,7 +10,7 @@ import { hideBin } from "yargs/helpers";
|
|
|
10
10
|
// package.json
|
|
11
11
|
var package_default = {
|
|
12
12
|
name: "c-next",
|
|
13
|
-
version: "0.2.
|
|
13
|
+
version: "0.2.11",
|
|
14
14
|
description: "A safer C for embedded systems development. Transpiles to clean, readable C.",
|
|
15
15
|
packageManager: "npm@11.9.0",
|
|
16
16
|
type: "module",
|
|
@@ -109966,6 +109966,26 @@ var SymbolTable = class {
|
|
|
109966
109966
|
* In C, they must be referred to as 'struct Name', not just 'Name'
|
|
109967
109967
|
*/
|
|
109968
109968
|
needsStructKeyword = /* @__PURE__ */ new Set();
|
|
109969
|
+
/**
|
|
109970
|
+
* Issue #948: Track typedef names that alias incomplete (forward-declared) struct types.
|
|
109971
|
+
* These are "opaque" types that can only be used as pointers.
|
|
109972
|
+
*/
|
|
109973
|
+
opaqueTypes = /* @__PURE__ */ new Set();
|
|
109974
|
+
/**
|
|
109975
|
+
* Issue #958: Track typedef struct type names with their source files.
|
|
109976
|
+
* Maps typeName -> sourceFile. Used for scope variables which should be pointers
|
|
109977
|
+
* when the struct definition comes from a different file than the typedef.
|
|
109978
|
+
* If definition is in the same file as typedef, the entry is removed (value type).
|
|
109979
|
+
* If definition is in a different file, the entry remains (pointer type).
|
|
109980
|
+
*/
|
|
109981
|
+
typedefStructTypes = /* @__PURE__ */ new Map();
|
|
109982
|
+
/**
|
|
109983
|
+
* Issue #948: Track struct tag -> typedef name relationships.
|
|
109984
|
+
* When a typedef declares an alias for a struct tag (e.g., typedef struct _foo foo_t),
|
|
109985
|
+
* we record structTagAliases["_foo"] = "foo_t". This allows us to unmark the typedef
|
|
109986
|
+
* as opaque when the full struct definition is later found.
|
|
109987
|
+
*/
|
|
109988
|
+
structTagAliases = /* @__PURE__ */ new Map();
|
|
109969
109989
|
/**
|
|
109970
109990
|
* Issue #208: Track enum backing type bit widths
|
|
109971
109991
|
* C++14 typed enums: enum Name : uint8_t { ... } have explicit bit widths
|
|
@@ -110594,6 +110614,116 @@ Rename the C-Next symbol to resolve.`
|
|
|
110594
110614
|
}
|
|
110595
110615
|
}
|
|
110596
110616
|
// ========================================================================
|
|
110617
|
+
// Opaque Type Tracking (Issue #948)
|
|
110618
|
+
// ========================================================================
|
|
110619
|
+
/**
|
|
110620
|
+
* Issue #948: Mark a typedef as aliasing an opaque (forward-declared) struct type.
|
|
110621
|
+
* @param typeName Typedef name (e.g., "widget_t")
|
|
110622
|
+
*/
|
|
110623
|
+
markOpaqueType(typeName) {
|
|
110624
|
+
this.opaqueTypes.add(typeName);
|
|
110625
|
+
}
|
|
110626
|
+
/**
|
|
110627
|
+
* Issue #948: Unmark a typedef when full struct definition is found.
|
|
110628
|
+
* Handles edge case: typedef before definition.
|
|
110629
|
+
* @param typeName Typedef name
|
|
110630
|
+
*/
|
|
110631
|
+
unmarkOpaqueType(typeName) {
|
|
110632
|
+
this.opaqueTypes.delete(typeName);
|
|
110633
|
+
}
|
|
110634
|
+
/**
|
|
110635
|
+
* Issue #948: Check if a typedef aliases an opaque struct type.
|
|
110636
|
+
* @param typeName Typedef name
|
|
110637
|
+
* @returns true if the type is opaque (forward-declared)
|
|
110638
|
+
*/
|
|
110639
|
+
isOpaqueType(typeName) {
|
|
110640
|
+
return this.opaqueTypes.has(typeName);
|
|
110641
|
+
}
|
|
110642
|
+
/**
|
|
110643
|
+
* Issue #948: Get all opaque type names for cache serialization.
|
|
110644
|
+
* @returns Array of opaque typedef names
|
|
110645
|
+
*/
|
|
110646
|
+
getAllOpaqueTypes() {
|
|
110647
|
+
return Array.from(this.opaqueTypes);
|
|
110648
|
+
}
|
|
110649
|
+
/**
|
|
110650
|
+
* Issue #948: Restore opaque types from cache.
|
|
110651
|
+
* @param typeNames Array of opaque typedef names
|
|
110652
|
+
*/
|
|
110653
|
+
restoreOpaqueTypes(typeNames) {
|
|
110654
|
+
for (const name of typeNames) {
|
|
110655
|
+
this.opaqueTypes.add(name);
|
|
110656
|
+
}
|
|
110657
|
+
}
|
|
110658
|
+
/**
|
|
110659
|
+
* Issue #948: Register a struct tag -> typedef name relationship.
|
|
110660
|
+
* Called when processing: typedef struct _foo foo_t;
|
|
110661
|
+
* This allows unmarking foo_t when struct _foo { ... } is later defined.
|
|
110662
|
+
* @param structTag The struct tag name (e.g., "_foo")
|
|
110663
|
+
* @param typedefName The typedef alias name (e.g., "foo_t")
|
|
110664
|
+
*/
|
|
110665
|
+
registerStructTagAlias(structTag, typedefName) {
|
|
110666
|
+
this.structTagAliases.set(structTag, typedefName);
|
|
110667
|
+
}
|
|
110668
|
+
/**
|
|
110669
|
+
* Issue #948: Get the typedef alias for a struct tag, if any.
|
|
110670
|
+
* @param structTag The struct tag name
|
|
110671
|
+
* @returns The typedef alias name, or undefined if none registered
|
|
110672
|
+
*/
|
|
110673
|
+
getStructTagAlias(structTag) {
|
|
110674
|
+
return this.structTagAliases.get(structTag);
|
|
110675
|
+
}
|
|
110676
|
+
// ========================================================================
|
|
110677
|
+
// Issue #958: Typedef Struct Type Tracking
|
|
110678
|
+
// ========================================================================
|
|
110679
|
+
/**
|
|
110680
|
+
* Issue #958: Mark a typedef as aliasing a struct type.
|
|
110681
|
+
* Records the source file to enable same-file vs cross-file distinction.
|
|
110682
|
+
* @param typedefName The typedef name (e.g., "widget_t")
|
|
110683
|
+
* @param sourceFile The file where the typedef was declared
|
|
110684
|
+
*/
|
|
110685
|
+
markTypedefStructType(typedefName, sourceFile) {
|
|
110686
|
+
this.typedefStructTypes.set(typedefName, sourceFile);
|
|
110687
|
+
}
|
|
110688
|
+
/**
|
|
110689
|
+
* Issue #958: Unmark a typedef struct type when full definition is found.
|
|
110690
|
+
* Only unmarks if the definition is in the SAME file as the typedef declaration.
|
|
110691
|
+
* Cross-file definitions keep the typedef marked (pointer semantics).
|
|
110692
|
+
* @param typeName The typedef name to unmark
|
|
110693
|
+
* @param sourceFile The file where the definition was found
|
|
110694
|
+
*/
|
|
110695
|
+
unmarkTypedefStructType(typeName, sourceFile) {
|
|
110696
|
+
const typedefFile = this.typedefStructTypes.get(typeName);
|
|
110697
|
+
if (typedefFile === sourceFile) {
|
|
110698
|
+
this.typedefStructTypes.delete(typeName);
|
|
110699
|
+
}
|
|
110700
|
+
}
|
|
110701
|
+
/**
|
|
110702
|
+
* Issue #958: Check if a typedef aliases a struct type.
|
|
110703
|
+
* Used for scope variables which should be pointers for external struct types.
|
|
110704
|
+
* @param typeName The type name to check
|
|
110705
|
+
* @returns true if this is a typedef'd struct type from C headers
|
|
110706
|
+
*/
|
|
110707
|
+
isTypedefStructType(typeName) {
|
|
110708
|
+
return this.typedefStructTypes.has(typeName);
|
|
110709
|
+
}
|
|
110710
|
+
/**
|
|
110711
|
+
* Issue #958: Get all typedef struct types for cache serialization.
|
|
110712
|
+
* @returns Map entries as [typeName, sourceFile] pairs
|
|
110713
|
+
*/
|
|
110714
|
+
getAllTypedefStructTypes() {
|
|
110715
|
+
return Array.from(this.typedefStructTypes.entries());
|
|
110716
|
+
}
|
|
110717
|
+
/**
|
|
110718
|
+
* Issue #958: Restore typedef struct types from cache.
|
|
110719
|
+
* @param entries Array of [typeName, sourceFile] pairs
|
|
110720
|
+
*/
|
|
110721
|
+
restoreTypedefStructTypes(entries) {
|
|
110722
|
+
for (const [name, sourceFile] of entries) {
|
|
110723
|
+
this.typedefStructTypes.set(name, sourceFile);
|
|
110724
|
+
}
|
|
110725
|
+
}
|
|
110726
|
+
// ========================================================================
|
|
110597
110727
|
// Enum Bit Width Tracking
|
|
110598
110728
|
// ========================================================================
|
|
110599
110729
|
/**
|
|
@@ -110710,7 +110840,10 @@ Rename the C-Next symbol to resolve.`
|
|
|
110710
110840
|
this.cppSymbolsByFile.clear();
|
|
110711
110841
|
this.structFields.clear();
|
|
110712
110842
|
this.needsStructKeyword.clear();
|
|
110843
|
+
this.opaqueTypes.clear();
|
|
110844
|
+
this.structTagAliases.clear();
|
|
110713
110845
|
this.enumBitWidth.clear();
|
|
110846
|
+
this.typedefStructTypes.clear();
|
|
110714
110847
|
}
|
|
110715
110848
|
};
|
|
110716
110849
|
var SymbolTable_default = SymbolTable;
|
|
@@ -110871,6 +111004,16 @@ var CodeGenState = class {
|
|
|
110871
111004
|
/** Issue #473: IRQ wrappers for critical sections */
|
|
110872
111005
|
static needsIrqWrappers = false;
|
|
110873
111006
|
// ===========================================================================
|
|
111007
|
+
// OPAQUE TYPE SCOPE VARIABLES (Issue #948)
|
|
111008
|
+
// ===========================================================================
|
|
111009
|
+
/**
|
|
111010
|
+
* Tracks scope variables with opaque (forward-declared) struct types.
|
|
111011
|
+
* These are generated as pointers with NULL initialization and should
|
|
111012
|
+
* be passed directly (not with &) since they're already pointers.
|
|
111013
|
+
* Maps qualified name (e.g., "MyScope_widget") to true.
|
|
111014
|
+
*/
|
|
111015
|
+
static opaqueScopeVariables = /* @__PURE__ */ new Set();
|
|
111016
|
+
// ===========================================================================
|
|
110874
111017
|
// C++ MODE STATE (Issue #250)
|
|
110875
111018
|
// ===========================================================================
|
|
110876
111019
|
/** Use temp vars instead of compound literals */
|
|
@@ -110954,6 +111097,7 @@ var CodeGenState = class {
|
|
|
110954
111097
|
this.tempVarCounter = 0;
|
|
110955
111098
|
this.pendingCppClassAssignments = [];
|
|
110956
111099
|
this.selfIncludeAdded = false;
|
|
111100
|
+
this.opaqueScopeVariables = /* @__PURE__ */ new Set();
|
|
110957
111101
|
this.sourcePath = null;
|
|
110958
111102
|
this.includeDirs = [];
|
|
110959
111103
|
this.inputs = [];
|
|
@@ -111043,6 +111187,22 @@ var CodeGenState = class {
|
|
|
111043
111187
|
static isKnownRegister(name) {
|
|
111044
111188
|
return this.symbols?.knownRegisters.has(name) ?? false;
|
|
111045
111189
|
}
|
|
111190
|
+
/**
|
|
111191
|
+
* Issue #948: Check if a type name is an opaque (forward-declared) struct type.
|
|
111192
|
+
* Opaque types are incomplete types that can only be used as pointers.
|
|
111193
|
+
* Example: `typedef struct _widget_t widget_t;` without a body makes `widget_t` opaque.
|
|
111194
|
+
*/
|
|
111195
|
+
static isOpaqueType(typeName) {
|
|
111196
|
+
return this.symbols?.opaqueTypes.has(typeName) ?? false;
|
|
111197
|
+
}
|
|
111198
|
+
/**
|
|
111199
|
+
* Issue #958: Check if a type name is an external typedef struct type.
|
|
111200
|
+
* External typedef struct types should use pointer semantics for scope variables.
|
|
111201
|
+
* Unlike isOpaqueType, this returns true for both forward-declared and complete structs.
|
|
111202
|
+
*/
|
|
111203
|
+
static isTypedefStructType(typeName) {
|
|
111204
|
+
return this.symbolTable?.isTypedefStructType(typeName) ?? false;
|
|
111205
|
+
}
|
|
111046
111206
|
/**
|
|
111047
111207
|
* Get type info for a variable.
|
|
111048
111208
|
* Checks local typeRegistry first, then falls back to SymbolTable
|
|
@@ -111482,6 +111642,28 @@ var CodeGenState = class {
|
|
|
111482
111642
|
return this.floatShadowCurrent.has(name);
|
|
111483
111643
|
}
|
|
111484
111644
|
// ===========================================================================
|
|
111645
|
+
// OPAQUE SCOPE VARIABLE HELPERS (Issue #948)
|
|
111646
|
+
// ===========================================================================
|
|
111647
|
+
/**
|
|
111648
|
+
* Mark a scope variable as having an opaque (forward-declared) struct type.
|
|
111649
|
+
* These are generated as pointers with NULL initialization.
|
|
111650
|
+
*
|
|
111651
|
+
* @param qualifiedName - The fully qualified variable name (e.g., "MyScope_widget")
|
|
111652
|
+
*/
|
|
111653
|
+
static markOpaqueScopeVariable(qualifiedName) {
|
|
111654
|
+
this.opaqueScopeVariables.add(qualifiedName);
|
|
111655
|
+
}
|
|
111656
|
+
/**
|
|
111657
|
+
* Check if a scope variable has an opaque type (and is thus a pointer).
|
|
111658
|
+
* Used during access generation to determine if & prefix is needed.
|
|
111659
|
+
*
|
|
111660
|
+
* @param qualifiedName - The fully qualified variable name (e.g., "MyScope_widget")
|
|
111661
|
+
* @returns true if this is an opaque scope variable (already a pointer)
|
|
111662
|
+
*/
|
|
111663
|
+
static isOpaqueScopeVariable(qualifiedName) {
|
|
111664
|
+
return this.opaqueScopeVariables.has(qualifiedName);
|
|
111665
|
+
}
|
|
111666
|
+
// ===========================================================================
|
|
111485
111667
|
// C++ MODE HELPERS
|
|
111486
111668
|
// ===========================================================================
|
|
111487
111669
|
/**
|
|
@@ -113191,6 +113373,12 @@ var TypeResolver2 = class _TypeResolver {
|
|
|
113191
113373
|
if (floatMatch) {
|
|
113192
113374
|
return "f" + floatMatch[1];
|
|
113193
113375
|
}
|
|
113376
|
+
if (/^\d+$/.test(text) || /^0[xXbBoO][\da-fA-F]+$/.test(text)) {
|
|
113377
|
+
return "int";
|
|
113378
|
+
}
|
|
113379
|
+
if (/^\d*\.\d+([eE][+-]?\d+)?$/.test(text) || /^\d+[eE][+-]?\d+$/.test(text)) {
|
|
113380
|
+
return "f64";
|
|
113381
|
+
}
|
|
113194
113382
|
return null;
|
|
113195
113383
|
}
|
|
113196
113384
|
/**
|
|
@@ -114450,6 +114638,229 @@ var GeneratorRegistry = class {
|
|
|
114450
114638
|
}
|
|
114451
114639
|
};
|
|
114452
114640
|
|
|
114641
|
+
// src/transpiler/output/codegen/helpers/CppModeHelper.ts
|
|
114642
|
+
var CppModeHelper = class {
|
|
114643
|
+
/**
|
|
114644
|
+
* Get address-of expression for struct parameter passing.
|
|
114645
|
+
* C mode: `&expr` (pass pointer to struct)
|
|
114646
|
+
* C++ mode: `expr` (pass reference directly)
|
|
114647
|
+
*
|
|
114648
|
+
* @param expr - The expression to potentially wrap
|
|
114649
|
+
* @returns The expression with address-of operator in C mode
|
|
114650
|
+
*/
|
|
114651
|
+
static maybeAddressOf(expr) {
|
|
114652
|
+
return CodeGenState.cppMode ? expr : `&${expr}`;
|
|
114653
|
+
}
|
|
114654
|
+
/**
|
|
114655
|
+
* Get dereference expression for struct parameter access.
|
|
114656
|
+
* C mode: `(*expr)` (dereference pointer)
|
|
114657
|
+
* C++ mode: `expr` (reference can be used directly)
|
|
114658
|
+
*
|
|
114659
|
+
* @param expr - The expression to potentially dereference
|
|
114660
|
+
* @returns The expression with dereference in C mode
|
|
114661
|
+
*/
|
|
114662
|
+
static maybeDereference(expr) {
|
|
114663
|
+
return CodeGenState.cppMode ? expr : `(*${expr})`;
|
|
114664
|
+
}
|
|
114665
|
+
/**
|
|
114666
|
+
* Get the type modifier for struct parameter declarations.
|
|
114667
|
+
* C mode: `*` (pointer type)
|
|
114668
|
+
* C++ mode: `&` (reference type)
|
|
114669
|
+
*
|
|
114670
|
+
* @returns The type modifier character
|
|
114671
|
+
*/
|
|
114672
|
+
static refOrPtr() {
|
|
114673
|
+
return CodeGenState.cppMode ? "&" : "*";
|
|
114674
|
+
}
|
|
114675
|
+
/**
|
|
114676
|
+
* Get the member access separator for struct parameters.
|
|
114677
|
+
* C mode: `->` (pointer member access)
|
|
114678
|
+
* C++ mode: `.` (reference member access)
|
|
114679
|
+
*
|
|
114680
|
+
* @returns The member access separator
|
|
114681
|
+
*/
|
|
114682
|
+
static memberSeparator() {
|
|
114683
|
+
return CodeGenState.cppMode ? "." : "->";
|
|
114684
|
+
}
|
|
114685
|
+
/**
|
|
114686
|
+
* Get NULL literal for the current mode.
|
|
114687
|
+
* C mode: `NULL`
|
|
114688
|
+
* C++ mode: `nullptr`
|
|
114689
|
+
*
|
|
114690
|
+
* @returns The null pointer literal
|
|
114691
|
+
*/
|
|
114692
|
+
static nullLiteral() {
|
|
114693
|
+
return CodeGenState.cppMode ? "nullptr" : "NULL";
|
|
114694
|
+
}
|
|
114695
|
+
/**
|
|
114696
|
+
* Generate a cast expression for the current mode.
|
|
114697
|
+
* C mode: `(type)expr`
|
|
114698
|
+
* C++ mode: `static_cast<type>(expr)`
|
|
114699
|
+
*
|
|
114700
|
+
* @param type - The target type
|
|
114701
|
+
* @param expr - The expression to cast
|
|
114702
|
+
* @returns The cast expression
|
|
114703
|
+
*/
|
|
114704
|
+
static cast(type, expr) {
|
|
114705
|
+
return CodeGenState.cppMode ? `static_cast<${type}>(${expr})` : `(${type})${expr}`;
|
|
114706
|
+
}
|
|
114707
|
+
/**
|
|
114708
|
+
* Generate a reinterpret cast expression for the current mode.
|
|
114709
|
+
* C mode: `(type)expr`
|
|
114710
|
+
* C++ mode: `reinterpret_cast<type>(expr)`
|
|
114711
|
+
*
|
|
114712
|
+
* @param type - The target type
|
|
114713
|
+
* @param expr - The expression to cast
|
|
114714
|
+
* @returns The cast expression
|
|
114715
|
+
*/
|
|
114716
|
+
static reinterpretCast(type, expr) {
|
|
114717
|
+
return CodeGenState.cppMode ? `reinterpret_cast<${type}>(${expr})` : `(${type})${expr}`;
|
|
114718
|
+
}
|
|
114719
|
+
/**
|
|
114720
|
+
* Check if we're in C++ mode.
|
|
114721
|
+
*
|
|
114722
|
+
* @returns True if generating C++ code
|
|
114723
|
+
*/
|
|
114724
|
+
static isCppMode() {
|
|
114725
|
+
return CodeGenState.cppMode;
|
|
114726
|
+
}
|
|
114727
|
+
};
|
|
114728
|
+
var CppModeHelper_default = CppModeHelper;
|
|
114729
|
+
|
|
114730
|
+
// src/transpiler/output/codegen/helpers/NarrowingCastHelper.ts
|
|
114731
|
+
var EXTENDED_TYPE_WIDTH = {
|
|
114732
|
+
...TYPE_WIDTH_default,
|
|
114733
|
+
int: 32
|
|
114734
|
+
// C's int after promotion
|
|
114735
|
+
};
|
|
114736
|
+
var PROMOTED_TO_INT = /* @__PURE__ */ new Set(["u8", "i8", "u16", "i16", "bool"]);
|
|
114737
|
+
var FLOAT_TYPES2 = /* @__PURE__ */ new Set(["f32", "f64", "float", "double"]);
|
|
114738
|
+
var INTEGER_TYPES2 = /* @__PURE__ */ new Set([
|
|
114739
|
+
"u8",
|
|
114740
|
+
"u16",
|
|
114741
|
+
"u32",
|
|
114742
|
+
"u64",
|
|
114743
|
+
"i8",
|
|
114744
|
+
"i16",
|
|
114745
|
+
"i32",
|
|
114746
|
+
"i64",
|
|
114747
|
+
"uint8_t",
|
|
114748
|
+
"uint16_t",
|
|
114749
|
+
"uint32_t",
|
|
114750
|
+
"uint64_t",
|
|
114751
|
+
"int8_t",
|
|
114752
|
+
"int16_t",
|
|
114753
|
+
"int32_t",
|
|
114754
|
+
"int64_t",
|
|
114755
|
+
"int"
|
|
114756
|
+
]);
|
|
114757
|
+
var NarrowingCastHelper = class _NarrowingCastHelper {
|
|
114758
|
+
/**
|
|
114759
|
+
* Check if a cast is needed for MISRA 10.3 compliance.
|
|
114760
|
+
* Returns true if:
|
|
114761
|
+
* - Source is wider than target (narrowing)
|
|
114762
|
+
* - Source and target are different essential type categories
|
|
114763
|
+
*
|
|
114764
|
+
* @param sourceType - Type of the expression (C-Next type or "int" for promoted)
|
|
114765
|
+
* @param targetType - Type of the target variable (C-Next type)
|
|
114766
|
+
*/
|
|
114767
|
+
static needsCast(sourceType, targetType) {
|
|
114768
|
+
if (sourceType === targetType) {
|
|
114769
|
+
return false;
|
|
114770
|
+
}
|
|
114771
|
+
if (targetType === "bool" && sourceType !== "bool") {
|
|
114772
|
+
return true;
|
|
114773
|
+
}
|
|
114774
|
+
const sourceWidth = EXTENDED_TYPE_WIDTH[sourceType];
|
|
114775
|
+
const targetWidth = EXTENDED_TYPE_WIDTH[targetType];
|
|
114776
|
+
if (sourceWidth === void 0 || targetWidth === void 0) {
|
|
114777
|
+
return false;
|
|
114778
|
+
}
|
|
114779
|
+
return sourceWidth > targetWidth;
|
|
114780
|
+
}
|
|
114781
|
+
/**
|
|
114782
|
+
* Wrap expression with cast if needed for MISRA 10.3 compliance.
|
|
114783
|
+
*
|
|
114784
|
+
* @param expr - The generated C expression
|
|
114785
|
+
* @param sourceType - Type of the expression (C-Next type or "int")
|
|
114786
|
+
* @param targetType - Type of the assignment target (C-Next type)
|
|
114787
|
+
* @returns Expression with cast wrapper if needed, or original expression
|
|
114788
|
+
*/
|
|
114789
|
+
static wrap(expr, sourceType, targetType) {
|
|
114790
|
+
if (!_NarrowingCastHelper.needsCast(sourceType, targetType)) {
|
|
114791
|
+
return expr;
|
|
114792
|
+
}
|
|
114793
|
+
if (targetType === "bool") {
|
|
114794
|
+
return `((${expr}) != 0U)`;
|
|
114795
|
+
}
|
|
114796
|
+
const cType = TYPE_MAP_default[targetType] ?? targetType;
|
|
114797
|
+
return CppModeHelper_default.cast(cType, expr);
|
|
114798
|
+
}
|
|
114799
|
+
/**
|
|
114800
|
+
* Determine the result type of C integer promotion for a given type.
|
|
114801
|
+
*
|
|
114802
|
+
* In C, operations on types smaller than int are promoted:
|
|
114803
|
+
* - u8, i8, u16, i16, bool -> int (32-bit)
|
|
114804
|
+
* - u32, i32, u64, i64 -> no promotion (already >= int width)
|
|
114805
|
+
*
|
|
114806
|
+
* @param baseType - The C-Next type of the operand
|
|
114807
|
+
* @returns "int" for promoted types, or the original type
|
|
114808
|
+
*/
|
|
114809
|
+
static getPromotedType(baseType) {
|
|
114810
|
+
if (PROMOTED_TO_INT.has(baseType)) {
|
|
114811
|
+
return "int";
|
|
114812
|
+
}
|
|
114813
|
+
return baseType;
|
|
114814
|
+
}
|
|
114815
|
+
/**
|
|
114816
|
+
* Check if a type is a floating-point type.
|
|
114817
|
+
*/
|
|
114818
|
+
static isFloatType(typeName) {
|
|
114819
|
+
return FLOAT_TYPES2.has(typeName);
|
|
114820
|
+
}
|
|
114821
|
+
/**
|
|
114822
|
+
* Check if a type is an integer type.
|
|
114823
|
+
*/
|
|
114824
|
+
static isIntegerType(typeName) {
|
|
114825
|
+
return INTEGER_TYPES2.has(typeName);
|
|
114826
|
+
}
|
|
114827
|
+
/**
|
|
114828
|
+
* Check if conversion between source and target is a cross-type-category conversion.
|
|
114829
|
+
* MISRA 10.3 requires explicit casts for different essential type categories.
|
|
114830
|
+
*/
|
|
114831
|
+
static isCrossTypeCategoryConversion(sourceType, targetType) {
|
|
114832
|
+
const sourceIsFloat = _NarrowingCastHelper.isFloatType(sourceType);
|
|
114833
|
+
const targetIsFloat = _NarrowingCastHelper.isFloatType(targetType);
|
|
114834
|
+
const sourceIsInt = _NarrowingCastHelper.isIntegerType(sourceType);
|
|
114835
|
+
const targetIsInt = _NarrowingCastHelper.isIntegerType(targetType);
|
|
114836
|
+
return sourceIsFloat && targetIsInt || sourceIsInt && targetIsFloat;
|
|
114837
|
+
}
|
|
114838
|
+
/**
|
|
114839
|
+
* Get the appropriate C float type for a C-Next type.
|
|
114840
|
+
*/
|
|
114841
|
+
static getCFloatType(typeName) {
|
|
114842
|
+
if (typeName === "f32" || typeName === "float") {
|
|
114843
|
+
return "float";
|
|
114844
|
+
}
|
|
114845
|
+
if (typeName === "f64" || typeName === "double") {
|
|
114846
|
+
return "double";
|
|
114847
|
+
}
|
|
114848
|
+
return "double";
|
|
114849
|
+
}
|
|
114850
|
+
/**
|
|
114851
|
+
* Wrap int-to-float conversion with explicit cast for MISRA 10.3.
|
|
114852
|
+
*
|
|
114853
|
+
* @param expr - The integer expression
|
|
114854
|
+
* @param targetType - The float target type (f32/f64)
|
|
114855
|
+
* @returns Expression with cast
|
|
114856
|
+
*/
|
|
114857
|
+
static wrapIntToFloat(expr, targetType) {
|
|
114858
|
+
const floatType = _NarrowingCastHelper.getCFloatType(targetType);
|
|
114859
|
+
return CppModeHelper_default.cast(floatType, expr);
|
|
114860
|
+
}
|
|
114861
|
+
};
|
|
114862
|
+
var NarrowingCastHelper_default = NarrowingCastHelper;
|
|
114863
|
+
|
|
114453
114864
|
// src/transpiler/output/codegen/generators/expressions/LiteralGenerator.ts
|
|
114454
114865
|
var UNSIGNED_64_TYPES = /* @__PURE__ */ new Set(["u64", "uint64_t"]);
|
|
114455
114866
|
var UNSIGNED_TYPES3 = /* @__PURE__ */ new Set([
|
|
@@ -114490,6 +114901,18 @@ var generateLiteral = (node, _input, state, _orchestrator) => {
|
|
|
114490
114901
|
effects.push({ type: "include", header: "stdbool" });
|
|
114491
114902
|
return { code: literalText, effects };
|
|
114492
114903
|
}
|
|
114904
|
+
if (literalText.startsWith("'")) {
|
|
114905
|
+
const expectedType2 = state?.expectedType;
|
|
114906
|
+
if (expectedType2) {
|
|
114907
|
+
const wrappedCode = NarrowingCastHelper_default.wrap(
|
|
114908
|
+
literalText,
|
|
114909
|
+
"int",
|
|
114910
|
+
expectedType2
|
|
114911
|
+
);
|
|
114912
|
+
return { code: wrappedCode, effects };
|
|
114913
|
+
}
|
|
114914
|
+
return { code: literalText, effects };
|
|
114915
|
+
}
|
|
114493
114916
|
if (/[fF]32$/.test(literalText)) {
|
|
114494
114917
|
literalText = literalText.replace(/[fF]32$/, "f");
|
|
114495
114918
|
return { code: literalText, effects };
|
|
@@ -114851,96 +115274,9 @@ var binaryExprGenerators = {
|
|
|
114851
115274
|
};
|
|
114852
115275
|
var BinaryExprGenerator_default = binaryExprGenerators;
|
|
114853
115276
|
|
|
114854
|
-
// src/transpiler/output/codegen/helpers/CppModeHelper.ts
|
|
114855
|
-
var CppModeHelper = class {
|
|
114856
|
-
/**
|
|
114857
|
-
* Get address-of expression for struct parameter passing.
|
|
114858
|
-
* C mode: `&expr` (pass pointer to struct)
|
|
114859
|
-
* C++ mode: `expr` (pass reference directly)
|
|
114860
|
-
*
|
|
114861
|
-
* @param expr - The expression to potentially wrap
|
|
114862
|
-
* @returns The expression with address-of operator in C mode
|
|
114863
|
-
*/
|
|
114864
|
-
static maybeAddressOf(expr) {
|
|
114865
|
-
return CodeGenState.cppMode ? expr : `&${expr}`;
|
|
114866
|
-
}
|
|
114867
|
-
/**
|
|
114868
|
-
* Get dereference expression for struct parameter access.
|
|
114869
|
-
* C mode: `(*expr)` (dereference pointer)
|
|
114870
|
-
* C++ mode: `expr` (reference can be used directly)
|
|
114871
|
-
*
|
|
114872
|
-
* @param expr - The expression to potentially dereference
|
|
114873
|
-
* @returns The expression with dereference in C mode
|
|
114874
|
-
*/
|
|
114875
|
-
static maybeDereference(expr) {
|
|
114876
|
-
return CodeGenState.cppMode ? expr : `(*${expr})`;
|
|
114877
|
-
}
|
|
114878
|
-
/**
|
|
114879
|
-
* Get the type modifier for struct parameter declarations.
|
|
114880
|
-
* C mode: `*` (pointer type)
|
|
114881
|
-
* C++ mode: `&` (reference type)
|
|
114882
|
-
*
|
|
114883
|
-
* @returns The type modifier character
|
|
114884
|
-
*/
|
|
114885
|
-
static refOrPtr() {
|
|
114886
|
-
return CodeGenState.cppMode ? "&" : "*";
|
|
114887
|
-
}
|
|
114888
|
-
/**
|
|
114889
|
-
* Get the member access separator for struct parameters.
|
|
114890
|
-
* C mode: `->` (pointer member access)
|
|
114891
|
-
* C++ mode: `.` (reference member access)
|
|
114892
|
-
*
|
|
114893
|
-
* @returns The member access separator
|
|
114894
|
-
*/
|
|
114895
|
-
static memberSeparator() {
|
|
114896
|
-
return CodeGenState.cppMode ? "." : "->";
|
|
114897
|
-
}
|
|
114898
|
-
/**
|
|
114899
|
-
* Get NULL literal for the current mode.
|
|
114900
|
-
* C mode: `NULL`
|
|
114901
|
-
* C++ mode: `nullptr`
|
|
114902
|
-
*
|
|
114903
|
-
* @returns The null pointer literal
|
|
114904
|
-
*/
|
|
114905
|
-
static nullLiteral() {
|
|
114906
|
-
return CodeGenState.cppMode ? "nullptr" : "NULL";
|
|
114907
|
-
}
|
|
114908
|
-
/**
|
|
114909
|
-
* Generate a cast expression for the current mode.
|
|
114910
|
-
* C mode: `(type)expr`
|
|
114911
|
-
* C++ mode: `static_cast<type>(expr)`
|
|
114912
|
-
*
|
|
114913
|
-
* @param type - The target type
|
|
114914
|
-
* @param expr - The expression to cast
|
|
114915
|
-
* @returns The cast expression
|
|
114916
|
-
*/
|
|
114917
|
-
static cast(type, expr) {
|
|
114918
|
-
return CodeGenState.cppMode ? `static_cast<${type}>(${expr})` : `(${type})${expr}`;
|
|
114919
|
-
}
|
|
114920
|
-
/**
|
|
114921
|
-
* Generate a reinterpret cast expression for the current mode.
|
|
114922
|
-
* C mode: `(type)expr`
|
|
114923
|
-
* C++ mode: `reinterpret_cast<type>(expr)`
|
|
114924
|
-
*
|
|
114925
|
-
* @param type - The target type
|
|
114926
|
-
* @param expr - The expression to cast
|
|
114927
|
-
* @returns The cast expression
|
|
114928
|
-
*/
|
|
114929
|
-
static reinterpretCast(type, expr) {
|
|
114930
|
-
return CodeGenState.cppMode ? `reinterpret_cast<${type}>(${expr})` : `(${type})${expr}`;
|
|
114931
|
-
}
|
|
114932
|
-
/**
|
|
114933
|
-
* Check if we're in C++ mode.
|
|
114934
|
-
*
|
|
114935
|
-
* @returns True if generating C++ code
|
|
114936
|
-
*/
|
|
114937
|
-
static isCppMode() {
|
|
114938
|
-
return CodeGenState.cppMode;
|
|
114939
|
-
}
|
|
114940
|
-
};
|
|
114941
|
-
var CppModeHelper_default = CppModeHelper;
|
|
114942
|
-
|
|
114943
115277
|
// src/transpiler/output/codegen/generators/expressions/UnaryExprGenerator.ts
|
|
115278
|
+
var INT32_MIN_LITERAL = "2147483648";
|
|
115279
|
+
var INT64_MIN_LITERAL = "9223372036854775808";
|
|
114944
115280
|
var generateUnaryExpr = (node, _input, _state, orchestrator) => {
|
|
114945
115281
|
if (node.postfixExpression()) {
|
|
114946
115282
|
return {
|
|
@@ -114951,7 +115287,18 @@ var generateUnaryExpr = (node, _input, _state, orchestrator) => {
|
|
|
114951
115287
|
const inner = orchestrator.generateUnaryExpr(node.unaryExpression());
|
|
114952
115288
|
const text = node.getText();
|
|
114953
115289
|
if (text.startsWith("!")) return { code: `!${inner}`, effects: [] };
|
|
114954
|
-
if (text.startsWith("-"))
|
|
115290
|
+
if (text.startsWith("-")) {
|
|
115291
|
+
const effects = [];
|
|
115292
|
+
if (inner === INT32_MIN_LITERAL) {
|
|
115293
|
+
effects.push({ type: "include", header: "limits" });
|
|
115294
|
+
return { code: "(int32_t)INT32_MIN", effects };
|
|
115295
|
+
}
|
|
115296
|
+
if (inner === INT64_MIN_LITERAL || inner === INT64_MIN_LITERAL + "LL") {
|
|
115297
|
+
effects.push({ type: "include", header: "limits" });
|
|
115298
|
+
return { code: "(int64_t)INT64_MIN", effects };
|
|
115299
|
+
}
|
|
115300
|
+
return { code: `-${inner}`, effects };
|
|
115301
|
+
}
|
|
114955
115302
|
if (text.startsWith("~")) {
|
|
114956
115303
|
const innerType = TypeResolver_default2.getUnaryExpressionType(
|
|
114957
115304
|
node.unaryExpression()
|
|
@@ -115014,15 +115361,18 @@ var generateSizeProperty = (typeInfo) => {
|
|
|
115014
115361
|
throw new Error(`Error: .size is only available on string types`);
|
|
115015
115362
|
};
|
|
115016
115363
|
var generateBitmapFieldAccess = (result, fieldInfo) => {
|
|
115364
|
+
let expr;
|
|
115017
115365
|
if (fieldInfo.width === 1) {
|
|
115018
|
-
|
|
115366
|
+
expr = `((${result} >> ${fieldInfo.offset}) & 1)`;
|
|
115019
115367
|
} else {
|
|
115020
115368
|
const mask = (1 << fieldInfo.width) - 1;
|
|
115021
|
-
|
|
115022
|
-
|
|
115023
|
-
|
|
115024
|
-
|
|
115369
|
+
expr = `((${result} >> ${fieldInfo.offset}) & 0x${mask.toString(16).toUpperCase()})`;
|
|
115370
|
+
}
|
|
115371
|
+
const targetType = CodeGenState.expectedType;
|
|
115372
|
+
if (targetType) {
|
|
115373
|
+
expr = NarrowingCastHelper_default.wrap(expr, "int", targetType);
|
|
115025
115374
|
}
|
|
115375
|
+
return { code: expr, effects: [] };
|
|
115026
115376
|
};
|
|
115027
115377
|
var accessGenerators = {
|
|
115028
115378
|
generateCapacityProperty,
|
|
@@ -115199,7 +115549,8 @@ var _generateCFunctionArg = (e, targetParam, input, orchestrator) => {
|
|
|
115199
115549
|
if (typeInfo?.isPointer) {
|
|
115200
115550
|
isPointerVariable = true;
|
|
115201
115551
|
}
|
|
115202
|
-
const
|
|
115552
|
+
const isOpaqueScopeVar = CodeGenState.isOpaqueScopeVariable(argCode);
|
|
115553
|
+
const needsAddressOf = argType && !argType.endsWith("*") && !argCode.startsWith("&") && !targetParam.isArray && !isPointerVariable && !isOpaqueScopeVar && (orchestrator.isStructType(argType) || _parameterExpectsAddressOf(targetParam.baseType, argType, orchestrator));
|
|
115203
115554
|
const finalArgCode = needsAddressOf ? `&${argCode}` : argCode;
|
|
115204
115555
|
return wrapWithCppEnumCast(
|
|
115205
115556
|
finalArgCode,
|
|
@@ -115337,7 +115688,7 @@ var trackPassThroughModifications = (funcName, argExprs, orchestrator) => {
|
|
|
115337
115688
|
var CallExprGenerator_default = generateFunctionCall;
|
|
115338
115689
|
|
|
115339
115690
|
// src/utils/TypeCheckUtils.ts
|
|
115340
|
-
var
|
|
115691
|
+
var INTEGER_TYPES3 = [
|
|
115341
115692
|
"u8",
|
|
115342
115693
|
"u16",
|
|
115343
115694
|
"u32",
|
|
@@ -115349,7 +115700,7 @@ var INTEGER_TYPES2 = [
|
|
|
115349
115700
|
];
|
|
115350
115701
|
var UNSIGNED_TYPES4 = ["u8", "u16", "u32", "u64"];
|
|
115351
115702
|
var SIGNED_TYPES3 = ["i8", "i16", "i32", "i64"];
|
|
115352
|
-
var
|
|
115703
|
+
var FLOAT_TYPES3 = ["f32", "f64"];
|
|
115353
115704
|
var STANDARD_WIDTHS = [8, 16, 32];
|
|
115354
115705
|
var TypeCheckUtils = class {
|
|
115355
115706
|
/**
|
|
@@ -115359,7 +115710,7 @@ var TypeCheckUtils = class {
|
|
|
115359
115710
|
* @returns true if it's u8, u16, u32, u64, i8, i16, i32, or i64
|
|
115360
115711
|
*/
|
|
115361
115712
|
static isInteger(typeName) {
|
|
115362
|
-
return
|
|
115713
|
+
return INTEGER_TYPES3.includes(typeName);
|
|
115363
115714
|
}
|
|
115364
115715
|
/**
|
|
115365
115716
|
* Check if a type name is an unsigned integer type.
|
|
@@ -115386,7 +115737,7 @@ var TypeCheckUtils = class {
|
|
|
115386
115737
|
* @returns true if it's f32 or f64
|
|
115387
115738
|
*/
|
|
115388
115739
|
static isFloat(typeName) {
|
|
115389
|
-
return
|
|
115740
|
+
return FLOAT_TYPES3.includes(typeName);
|
|
115390
115741
|
}
|
|
115391
115742
|
/**
|
|
115392
115743
|
* Check if a type name is a string type (string<N>).
|
|
@@ -116618,7 +116969,12 @@ var handleSingleSubscript = (ctx, expr, input, orchestrator, output) => {
|
|
|
116618
116969
|
const isRegisterAccess = checkRegisterAccess(ctx, input);
|
|
116619
116970
|
const identifierTypeInfo = getIdentifierTypeInfo(ctx, input);
|
|
116620
116971
|
if (isRegisterAccess) {
|
|
116621
|
-
|
|
116972
|
+
let expr2 = index === "0" || index === "0U" ? `((${ctx.result}) & 1)` : `((${ctx.result} >> ${index}) & 1)`;
|
|
116973
|
+
const targetType = CodeGenState.expectedType;
|
|
116974
|
+
if (targetType) {
|
|
116975
|
+
expr2 = NarrowingCastHelper_default.wrap(expr2, "int", targetType);
|
|
116976
|
+
}
|
|
116977
|
+
output.result = expr2;
|
|
116622
116978
|
return output;
|
|
116623
116979
|
}
|
|
116624
116980
|
if (ctx.currentMemberIsArray) {
|
|
@@ -116632,7 +116988,12 @@ var handleSingleSubscript = (ctx, expr, input, orchestrator, output) => {
|
|
|
116632
116988
|
}
|
|
116633
116989
|
const isPrimitiveIntMember = ctx.currentStructType && TypeCheckUtils_default.isInteger(ctx.currentStructType);
|
|
116634
116990
|
if (isPrimitiveIntMember) {
|
|
116635
|
-
|
|
116991
|
+
let expr2 = index === "0" || index === "0U" ? `((${ctx.result}) & 1)` : `((${ctx.result} >> ${index}) & 1)`;
|
|
116992
|
+
const targetType = CodeGenState.expectedType;
|
|
116993
|
+
if (targetType) {
|
|
116994
|
+
expr2 = NarrowingCastHelper_default.wrap(expr2, "int", targetType);
|
|
116995
|
+
}
|
|
116996
|
+
output.result = expr2;
|
|
116636
116997
|
output.currentStructType = void 0;
|
|
116637
116998
|
return output;
|
|
116638
116999
|
}
|
|
@@ -116691,7 +117052,12 @@ var handleDefaultSubscript = (ctx, index, typeInfo, output) => {
|
|
|
116691
117052
|
isRegisterAccess: false
|
|
116692
117053
|
});
|
|
116693
117054
|
if (subscriptKind === "bit_single") {
|
|
116694
|
-
|
|
117055
|
+
let expr = index === "0" || index === "0U" ? `((${ctx.result}) & 1)` : `((${ctx.result} >> ${index}) & 1)`;
|
|
117056
|
+
const targetType = CodeGenState.expectedType;
|
|
117057
|
+
if (targetType) {
|
|
117058
|
+
expr = NarrowingCastHelper_default.wrap(expr, "int", targetType);
|
|
117059
|
+
}
|
|
117060
|
+
output.result = expr;
|
|
116695
117061
|
} else {
|
|
116696
117062
|
output.result = `${ctx.result}[${index}]`;
|
|
116697
117063
|
}
|
|
@@ -116718,10 +117084,24 @@ var handleBitRangeSubscript = (ctx, exprs, input, state, orchestrator, effects,
|
|
|
116718
117084
|
);
|
|
116719
117085
|
} else {
|
|
116720
117086
|
const mask = orchestrator.generateBitMask(width);
|
|
117087
|
+
let expr;
|
|
116721
117088
|
if (start === "0" || start === "0U") {
|
|
116722
|
-
|
|
117089
|
+
expr = `((${ctx.result}) & ${mask})`;
|
|
117090
|
+
} else {
|
|
117091
|
+
expr = `((${ctx.result} >> ${start}) & ${mask})`;
|
|
117092
|
+
}
|
|
117093
|
+
const targetType = CodeGenState.expectedType;
|
|
117094
|
+
if (targetType && ctx.primaryTypeInfo?.baseType) {
|
|
117095
|
+
const promotedSourceType = NarrowingCastHelper_default.getPromotedType(
|
|
117096
|
+
ctx.primaryTypeInfo.baseType
|
|
117097
|
+
);
|
|
117098
|
+
output.result = NarrowingCastHelper_default.wrap(
|
|
117099
|
+
expr,
|
|
117100
|
+
promotedSourceType,
|
|
117101
|
+
targetType
|
|
117102
|
+
);
|
|
116723
117103
|
} else {
|
|
116724
|
-
output.result =
|
|
117104
|
+
output.result = expr;
|
|
116725
117105
|
}
|
|
116726
117106
|
}
|
|
116727
117107
|
return output;
|
|
@@ -117031,6 +117411,21 @@ var generateCriticalStatement = (node, _input, _state, orchestrator) => {
|
|
|
117031
117411
|
};
|
|
117032
117412
|
var CriticalGenerator_default = generateCriticalStatement;
|
|
117033
117413
|
|
|
117414
|
+
// src/transpiler/output/codegen/types/COMPOUND_TO_BINARY.ts
|
|
117415
|
+
var COMPOUND_TO_BINARY = {
|
|
117416
|
+
"+=": "+",
|
|
117417
|
+
"-=": "-",
|
|
117418
|
+
"*=": "*",
|
|
117419
|
+
"/=": "/",
|
|
117420
|
+
"%=": "%",
|
|
117421
|
+
"&=": "&",
|
|
117422
|
+
"|=": "|",
|
|
117423
|
+
"^=": "^",
|
|
117424
|
+
"<<=": "<<",
|
|
117425
|
+
">>=": ">>"
|
|
117426
|
+
};
|
|
117427
|
+
var COMPOUND_TO_BINARY_default = COMPOUND_TO_BINARY;
|
|
117428
|
+
|
|
117034
117429
|
// src/transpiler/output/codegen/generators/statements/AtomicGenerator.ts
|
|
117035
117430
|
var TYPE_MAP2 = {
|
|
117036
117431
|
u8: "uint8_t",
|
|
@@ -117058,18 +117453,6 @@ var STREX_MAP = {
|
|
|
117058
117453
|
u32: "__STREXW",
|
|
117059
117454
|
i32: "__STREXW"
|
|
117060
117455
|
};
|
|
117061
|
-
var SIMPLE_OP_MAP = {
|
|
117062
|
-
"+=": "+",
|
|
117063
|
-
"-=": "-",
|
|
117064
|
-
"*=": "*",
|
|
117065
|
-
"/=": "/",
|
|
117066
|
-
"%=": "%",
|
|
117067
|
-
"&=": "&",
|
|
117068
|
-
"|=": "|",
|
|
117069
|
-
"^=": "^",
|
|
117070
|
-
"<<=": "<<",
|
|
117071
|
-
">>=": ">>"
|
|
117072
|
-
};
|
|
117073
117456
|
var CLAMP_OP_MAP = {
|
|
117074
117457
|
"+=": "add",
|
|
117075
117458
|
"-=": "sub",
|
|
@@ -117083,7 +117466,7 @@ function getClampHelperOp(cOp, typeInfo) {
|
|
|
117083
117466
|
}
|
|
117084
117467
|
function generateInnerAtomicOp(cOp, value, typeInfo) {
|
|
117085
117468
|
const effects = [];
|
|
117086
|
-
const simpleOp =
|
|
117469
|
+
const simpleOp = COMPOUND_TO_BINARY_default[cOp] || "+";
|
|
117087
117470
|
const helperOp = getClampHelperOp(cOp, typeInfo);
|
|
117088
117471
|
if (helperOp) {
|
|
117089
117472
|
effects.push({
|
|
@@ -117748,8 +118131,14 @@ function generateRegularVariable(varDecl, varName, scopeName, isPrivate, orchest
|
|
|
117748
118131
|
const arrayDims = varDecl.arrayDimension();
|
|
117749
118132
|
const arrayTypeCtx = varDecl.type().arrayType?.() ?? null;
|
|
117750
118133
|
const isArray = arrayDims.length > 0 || arrayTypeCtx !== null;
|
|
117751
|
-
|
|
118134
|
+
let type = orchestrator.generateType(varDecl.type());
|
|
117752
118135
|
const fullName = QualifiedNameGenerator_default.forMember(scopeName, varName);
|
|
118136
|
+
const isOpaque = orchestrator.isOpaqueType(type);
|
|
118137
|
+
const isExternalStruct = orchestrator.isTypedefStructType(type);
|
|
118138
|
+
if (isOpaque || isExternalStruct) {
|
|
118139
|
+
type = `${type}*`;
|
|
118140
|
+
orchestrator.markOpaqueScopeVariable(fullName);
|
|
118141
|
+
}
|
|
117753
118142
|
const constPrefix = isConst ? "const " : "";
|
|
117754
118143
|
const prefix = isPrivate ? "static " : "";
|
|
117755
118144
|
let decl = `${prefix}${constPrefix}${type} ${fullName}`;
|
|
@@ -117761,7 +118150,11 @@ function generateRegularVariable(varDecl, varName, scopeName, isPrivate, orchest
|
|
|
117761
118150
|
decl += orchestrator.generateArrayDimensions(arrayDims);
|
|
117762
118151
|
}
|
|
117763
118152
|
decl += ArrayDimensionUtils_default.generateStringCapacityDim(varDecl.type());
|
|
117764
|
-
|
|
118153
|
+
if (isOpaque || isExternalStruct) {
|
|
118154
|
+
decl += " = NULL";
|
|
118155
|
+
} else {
|
|
118156
|
+
decl += generateInitializer(varDecl, isArray, orchestrator);
|
|
118157
|
+
}
|
|
117765
118158
|
return decl + ";";
|
|
117766
118159
|
}
|
|
117767
118160
|
function generateScopeFunction(funcDecl, scopeName, isPrivate, orchestrator) {
|
|
@@ -117973,6 +118366,7 @@ function generateScopedStructInline(node, scopeName, _input, orchestrator) {
|
|
|
117973
118366
|
var ScopeGenerator_default = generateScope;
|
|
117974
118367
|
|
|
117975
118368
|
// src/utils/BitUtils.ts
|
|
118369
|
+
var NARROW_TYPES = /* @__PURE__ */ new Set(["u8", "u16", "i8", "i16"]);
|
|
117976
118370
|
var BitUtils = class _BitUtils {
|
|
117977
118371
|
/**
|
|
117978
118372
|
* Convert a boolean expression to an unsigned integer (0U or 1U).
|
|
@@ -118063,6 +118457,21 @@ var BitUtils = class _BitUtils {
|
|
|
118063
118457
|
static formatHex(value) {
|
|
118064
118458
|
return `0x${value.toString(16).toUpperCase()}U`;
|
|
118065
118459
|
}
|
|
118460
|
+
/**
|
|
118461
|
+
* Wrap an expression with a cast for MISRA 10.3 compliance on narrow types.
|
|
118462
|
+
* Bit manipulation operations promote to int; this casts back to the target type.
|
|
118463
|
+
*
|
|
118464
|
+
* @param expr - The expression to potentially wrap
|
|
118465
|
+
* @param targetType - The C-Next type name (e.g., "u8", "u16")
|
|
118466
|
+
* @returns Expression wrapped with cast if narrow, or original expression
|
|
118467
|
+
*/
|
|
118468
|
+
static wrapNarrowCast(expr, targetType) {
|
|
118469
|
+
if (!targetType || !NARROW_TYPES.has(targetType)) {
|
|
118470
|
+
return expr;
|
|
118471
|
+
}
|
|
118472
|
+
const cType = TYPE_MAP_default[targetType] ?? targetType;
|
|
118473
|
+
return `(${cType})(${expr})`;
|
|
118474
|
+
}
|
|
118066
118475
|
/**
|
|
118067
118476
|
* Generate code to read a single bit from a value.
|
|
118068
118477
|
* Pattern: ((target >> offset) & 1)
|
|
@@ -118109,7 +118518,8 @@ var BitUtils = class _BitUtils {
|
|
|
118109
118518
|
const is64Bit = targetType === "u64" || targetType === "i64";
|
|
118110
118519
|
const one = is64Bit ? "1ULL" : "1U";
|
|
118111
118520
|
const valueShift = is64Bit ? `((uint64_t)${intValue} << ${offset})` : `(${intValue} << ${offset})`;
|
|
118112
|
-
|
|
118521
|
+
const rhs = `(${target} & ~(${one} << ${offset})) | ${valueShift}`;
|
|
118522
|
+
return `${target} = ${_BitUtils.wrapNarrowCast(rhs, targetType)};`;
|
|
118113
118523
|
}
|
|
118114
118524
|
/**
|
|
118115
118525
|
* Generate read-modify-write code for multi-bit assignment.
|
|
@@ -118124,7 +118534,8 @@ var BitUtils = class _BitUtils {
|
|
|
118124
118534
|
*/
|
|
118125
118535
|
static multiBitWrite(target, offset, width, value, targetType) {
|
|
118126
118536
|
const mask = _BitUtils.generateMask(width, targetType);
|
|
118127
|
-
|
|
118537
|
+
const rhs = `(${target} & ~(${mask} << ${offset})) | ((${value} & ${mask}) << ${offset})`;
|
|
118538
|
+
return `${target} = ${_BitUtils.wrapNarrowCast(rhs, targetType)};`;
|
|
118128
118539
|
}
|
|
118129
118540
|
/**
|
|
118130
118541
|
* Generate write-only register code for single bit assignment.
|
|
@@ -118140,7 +118551,8 @@ var BitUtils = class _BitUtils {
|
|
|
118140
118551
|
static writeOnlySingleBit(target, offset, value, targetType) {
|
|
118141
118552
|
const intValue = _BitUtils.boolToInt(value);
|
|
118142
118553
|
const castPrefix = targetType === "u64" || targetType === "i64" ? "(uint64_t)" : "";
|
|
118143
|
-
|
|
118554
|
+
const rhs = `(${castPrefix}${intValue} << ${offset})`;
|
|
118555
|
+
return `${target} = ${_BitUtils.wrapNarrowCast(rhs, targetType)};`;
|
|
118144
118556
|
}
|
|
118145
118557
|
/**
|
|
118146
118558
|
* Generate write-only register code for multi-bit assignment.
|
|
@@ -118156,7 +118568,8 @@ var BitUtils = class _BitUtils {
|
|
|
118156
118568
|
*/
|
|
118157
118569
|
static writeOnlyMultiBit(target, offset, width, value, targetType) {
|
|
118158
118570
|
const mask = _BitUtils.generateMask(width, targetType);
|
|
118159
|
-
|
|
118571
|
+
const rhs = `((${value} & ${mask}) << ${offset})`;
|
|
118572
|
+
return `${target} = ${_BitUtils.wrapNarrowCast(rhs, targetType)};`;
|
|
118160
118573
|
}
|
|
118161
118574
|
};
|
|
118162
118575
|
var BitUtils_default = BitUtils;
|
|
@@ -120717,8 +121130,10 @@ var AssignmentKind = /* @__PURE__ */ ((AssignmentKind2) => {
|
|
|
120717
121130
|
AssignmentKind2[AssignmentKind2["GLOBAL_REGISTER_BIT"] = 28] = "GLOBAL_REGISTER_BIT";
|
|
120718
121131
|
AssignmentKind2[AssignmentKind2["THIS_MEMBER"] = 29] = "THIS_MEMBER";
|
|
120719
121132
|
AssignmentKind2[AssignmentKind2["THIS_ARRAY"] = 30] = "THIS_ARRAY";
|
|
120720
|
-
AssignmentKind2[AssignmentKind2["
|
|
120721
|
-
AssignmentKind2[AssignmentKind2["
|
|
121133
|
+
AssignmentKind2[AssignmentKind2["THIS_BIT"] = 31] = "THIS_BIT";
|
|
121134
|
+
AssignmentKind2[AssignmentKind2["THIS_BIT_RANGE"] = 32] = "THIS_BIT_RANGE";
|
|
121135
|
+
AssignmentKind2[AssignmentKind2["MEMBER_CHAIN"] = 33] = "MEMBER_CHAIN";
|
|
121136
|
+
AssignmentKind2[AssignmentKind2["SIMPLE"] = 34] = "SIMPLE";
|
|
120722
121137
|
return AssignmentKind2;
|
|
120723
121138
|
})(AssignmentKind || {});
|
|
120724
121139
|
var AssignmentKind_default = AssignmentKind;
|
|
@@ -120760,8 +121175,55 @@ var handlers_default = AssignmentHandlerRegistry;
|
|
|
120760
121175
|
function gen() {
|
|
120761
121176
|
return CodeGenState.generator;
|
|
120762
121177
|
}
|
|
121178
|
+
function tryHandleCompoundNarrowingCast(ctx, target) {
|
|
121179
|
+
if (!ctx.isCompound || !ctx.firstIdTypeInfo) {
|
|
121180
|
+
return null;
|
|
121181
|
+
}
|
|
121182
|
+
const baseType = ctx.firstIdTypeInfo.baseType;
|
|
121183
|
+
const promotedType = NarrowingCastHelper_default.getPromotedType(baseType);
|
|
121184
|
+
if (promotedType !== "int" || baseType === "int") {
|
|
121185
|
+
return null;
|
|
121186
|
+
}
|
|
121187
|
+
const binaryOp = COMPOUND_TO_BINARY_default[ctx.cOp];
|
|
121188
|
+
if (!binaryOp) {
|
|
121189
|
+
return null;
|
|
121190
|
+
}
|
|
121191
|
+
const cType = TYPE_MAP_default[baseType] ?? baseType;
|
|
121192
|
+
const expr = `(${target} ${binaryOp} ${ctx.generatedValue})`;
|
|
121193
|
+
const castExpr = CppModeHelper_default.cast(cType, expr);
|
|
121194
|
+
return `${target} = ${castExpr};`;
|
|
121195
|
+
}
|
|
121196
|
+
function tryHandleIntToFloatConversion(ctx, target) {
|
|
121197
|
+
if (ctx.isCompound || !ctx.firstIdTypeInfo || !ctx.valueCtx) {
|
|
121198
|
+
return null;
|
|
121199
|
+
}
|
|
121200
|
+
const targetType = ctx.firstIdTypeInfo.baseType;
|
|
121201
|
+
const valueType = TypeResolver_default2.getExpressionType(ctx.valueCtx);
|
|
121202
|
+
if (!valueType) {
|
|
121203
|
+
return null;
|
|
121204
|
+
}
|
|
121205
|
+
if (!NarrowingCastHelper_default.isCrossTypeCategoryConversion(valueType, targetType)) {
|
|
121206
|
+
return null;
|
|
121207
|
+
}
|
|
121208
|
+
if (!NarrowingCastHelper_default.isIntegerType(valueType) || !NarrowingCastHelper_default.isFloatType(targetType)) {
|
|
121209
|
+
return null;
|
|
121210
|
+
}
|
|
121211
|
+
const castedValue = NarrowingCastHelper_default.wrapIntToFloat(
|
|
121212
|
+
ctx.generatedValue,
|
|
121213
|
+
targetType
|
|
121214
|
+
);
|
|
121215
|
+
return `${target} ${ctx.cOp} ${castedValue};`;
|
|
121216
|
+
}
|
|
120763
121217
|
function handleSimpleAssignment(ctx) {
|
|
120764
121218
|
const target = gen().generateAssignmentTarget(ctx.targetCtx);
|
|
121219
|
+
const compoundResult = tryHandleCompoundNarrowingCast(ctx, target);
|
|
121220
|
+
if (compoundResult) {
|
|
121221
|
+
return compoundResult;
|
|
121222
|
+
}
|
|
121223
|
+
const conversionResult = tryHandleIntToFloatConversion(ctx, target);
|
|
121224
|
+
if (conversionResult) {
|
|
121225
|
+
return conversionResult;
|
|
121226
|
+
}
|
|
120765
121227
|
return `${target} ${ctx.cOp} ${ctx.generatedValue};`;
|
|
120766
121228
|
}
|
|
120767
121229
|
var SimpleHandler_default = handleSimpleAssignment;
|
|
@@ -121414,6 +121876,8 @@ function handleStructChainBitRange(ctx) {
|
|
|
121414
121876
|
var bitAccessHandlers = [
|
|
121415
121877
|
[AssignmentKind_default.INTEGER_BIT, handleIntegerBit],
|
|
121416
121878
|
[AssignmentKind_default.INTEGER_BIT_RANGE, handleIntegerBitRange],
|
|
121879
|
+
[AssignmentKind_default.THIS_BIT, handleIntegerBit],
|
|
121880
|
+
[AssignmentKind_default.THIS_BIT_RANGE, handleIntegerBitRange],
|
|
121417
121881
|
[AssignmentKind_default.STRUCT_MEMBER_BIT, handleStructMemberBit],
|
|
121418
121882
|
[AssignmentKind_default.ARRAY_ELEMENT_BIT, handleArrayElementBit],
|
|
121419
121883
|
[AssignmentKind_default.STRUCT_CHAIN_BIT_RANGE, handleStructChainBitRange]
|
|
@@ -121965,14 +122429,28 @@ var AssignmentClassifier = class _AssignmentClassifier {
|
|
|
121965
122429
|
return AssignmentKind_default.THIS_MEMBER;
|
|
121966
122430
|
}
|
|
121967
122431
|
/**
|
|
121968
|
-
* Classify this.reg[bit] / this.arr[i] patterns with array access.
|
|
122432
|
+
* Classify this.reg[bit] / this.arr[i] / this.flags[3] patterns with array access.
|
|
122433
|
+
* Issue #954: Uses SubscriptClassifier to distinguish array vs bit access.
|
|
121969
122434
|
*/
|
|
121970
122435
|
static classifyThisWithArrayAccess(ctx, scopedRegName) {
|
|
121971
122436
|
if (CodeGenState.symbols.knownRegisters.has(scopedRegName)) {
|
|
121972
122437
|
const hasBitRange = ctx.postfixOps.some((op) => op.COMMA() !== null);
|
|
121973
122438
|
return hasBitRange ? AssignmentKind_default.SCOPED_REGISTER_BIT_RANGE : AssignmentKind_default.SCOPED_REGISTER_BIT;
|
|
121974
122439
|
}
|
|
121975
|
-
|
|
122440
|
+
const typeInfo = CodeGenState.getVariableTypeInfo(scopedRegName);
|
|
122441
|
+
const subscriptKind = SubscriptClassifier_default.classify({
|
|
122442
|
+
typeInfo: typeInfo ?? null,
|
|
122443
|
+
subscriptCount: ctx.lastSubscriptExprCount,
|
|
122444
|
+
isRegisterAccess: false
|
|
122445
|
+
});
|
|
122446
|
+
switch (subscriptKind) {
|
|
122447
|
+
case "bit_single":
|
|
122448
|
+
return AssignmentKind_default.THIS_BIT;
|
|
122449
|
+
case "bit_range":
|
|
122450
|
+
return AssignmentKind_default.THIS_BIT_RANGE;
|
|
122451
|
+
default:
|
|
122452
|
+
return AssignmentKind_default.THIS_ARRAY;
|
|
122453
|
+
}
|
|
121976
122454
|
}
|
|
121977
122455
|
/**
|
|
121978
122456
|
* Classify simple array/bit access (no prefix, no member access).
|
|
@@ -122045,7 +122523,8 @@ var AssignmentClassifier = class _AssignmentClassifier {
|
|
|
122045
122523
|
if (isGlobalAtomic) {
|
|
122046
122524
|
return AssignmentKind_default.ATOMIC_RMW;
|
|
122047
122525
|
}
|
|
122048
|
-
|
|
122526
|
+
const ARITHMETIC_COMPOUND_OPS = /* @__PURE__ */ new Set(["+=", "-=", "*="]);
|
|
122527
|
+
if (typeInfo.overflowBehavior === "clamp" && TypeCheckUtils_default.isInteger(typeInfo.baseType) && ARITHMETIC_COMPOUND_OPS.has(ctx.cOp)) {
|
|
122049
122528
|
return AssignmentKind_default.OVERFLOW_CLAMP;
|
|
122050
122529
|
}
|
|
122051
122530
|
return null;
|
|
@@ -124446,10 +124925,20 @@ ${assignments}`;
|
|
|
124446
124925
|
_VariableDeclHelper.validateIntegerInitializer(ctx, typeName, {
|
|
124447
124926
|
getExpressionType: callbacks.getExpressionType
|
|
124448
124927
|
});
|
|
124449
|
-
return CodeGenState.withExpectedType(
|
|
124450
|
-
|
|
124451
|
-
|
|
124452
|
-
|
|
124928
|
+
return CodeGenState.withExpectedType(typeName, () => {
|
|
124929
|
+
let exprCode = callbacks.generateExpression(ctx.expression());
|
|
124930
|
+
const exprType = callbacks.getExpressionType(ctx.expression());
|
|
124931
|
+
if (exprType && NarrowingCastHelper_default.isCrossTypeCategoryConversion(exprType, typeName)) {
|
|
124932
|
+
if (NarrowingCastHelper_default.isIntegerType(exprType) && NarrowingCastHelper_default.isFloatType(typeName)) {
|
|
124933
|
+
exprCode = NarrowingCastHelper_default.wrapIntToFloat(exprCode, typeName);
|
|
124934
|
+
}
|
|
124935
|
+
if (NarrowingCastHelper_default.isFloatType(exprType) && NarrowingCastHelper_default.isIntegerType(typeName)) {
|
|
124936
|
+
const cType = TYPE_MAP_default[typeName] ?? typeName;
|
|
124937
|
+
exprCode = CppModeHelper_default.cast(cType, exprCode);
|
|
124938
|
+
}
|
|
124939
|
+
}
|
|
124940
|
+
return `${decl} = ${exprCode}`;
|
|
124941
|
+
});
|
|
124453
124942
|
}
|
|
124454
124943
|
// ========================================================================
|
|
124455
124944
|
// Tier 4: Orchestrators (main entry points)
|
|
@@ -125310,7 +125799,7 @@ var TypeGenerationHelper_default = TypeGenerationHelper;
|
|
|
125310
125799
|
var SIGNED_INTEGERS = /* @__PURE__ */ new Set(["i8", "i16", "i32", "i64"]);
|
|
125311
125800
|
var UNSIGNED_INTEGERS = /* @__PURE__ */ new Set(["u8", "u16", "u32", "u64"]);
|
|
125312
125801
|
var ALL_INTEGERS = /* @__PURE__ */ new Set([...SIGNED_INTEGERS, ...UNSIGNED_INTEGERS]);
|
|
125313
|
-
var
|
|
125802
|
+
var FLOAT_TYPES4 = /* @__PURE__ */ new Set(["f32", "f64"]);
|
|
125314
125803
|
var CastValidator = class _CastValidator {
|
|
125315
125804
|
/**
|
|
125316
125805
|
* Check if a type is an integer type.
|
|
@@ -125322,7 +125811,7 @@ var CastValidator = class _CastValidator {
|
|
|
125322
125811
|
* Check if a type is a floating-point type.
|
|
125323
125812
|
*/
|
|
125324
125813
|
static isFloatType(typeName) {
|
|
125325
|
-
return
|
|
125814
|
+
return FLOAT_TYPES4.has(typeName);
|
|
125326
125815
|
}
|
|
125327
125816
|
/**
|
|
125328
125817
|
* Check if a type is signed.
|
|
@@ -128368,6 +128857,30 @@ typedef ${callbackInfo.returnType} (*${callbackInfo.typedefName})(${paramList});
|
|
|
128368
128857
|
isFloatShadowCurrent(shadowName) {
|
|
128369
128858
|
return CodeGenState.floatShadowCurrent.has(shadowName);
|
|
128370
128859
|
}
|
|
128860
|
+
/**
|
|
128861
|
+
* Issue #948: Check if a type is an opaque (forward-declared) struct type.
|
|
128862
|
+
* Opaque types can only be used as pointers (cannot be instantiated).
|
|
128863
|
+
* Part of IOrchestrator interface.
|
|
128864
|
+
*/
|
|
128865
|
+
isOpaqueType(typeName) {
|
|
128866
|
+
return CodeGenState.isOpaqueType(typeName);
|
|
128867
|
+
}
|
|
128868
|
+
/**
|
|
128869
|
+
* Issue #958: Check if a type is an external typedef struct type.
|
|
128870
|
+
* Used for scope variables which should always be pointers for external struct types.
|
|
128871
|
+
* Part of IOrchestrator interface.
|
|
128872
|
+
*/
|
|
128873
|
+
isTypedefStructType(typeName) {
|
|
128874
|
+
return CodeGenState.isTypedefStructType(typeName);
|
|
128875
|
+
}
|
|
128876
|
+
/**
|
|
128877
|
+
* Issue #948: Mark a scope variable as having an opaque type.
|
|
128878
|
+
* These variables are generated as pointers with NULL initialization.
|
|
128879
|
+
* Part of IOrchestrator interface.
|
|
128880
|
+
*/
|
|
128881
|
+
markOpaqueScopeVariable(qualifiedName) {
|
|
128882
|
+
CodeGenState.markOpaqueScopeVariable(qualifiedName);
|
|
128883
|
+
}
|
|
128371
128884
|
// ===========================================================================
|
|
128372
128885
|
// End IOrchestrator Implementation
|
|
128373
128886
|
// ===========================================================================
|
|
@@ -130334,7 +130847,9 @@ typedef ${callbackInfo.returnType} (*${callbackInfo.typedefName})(${paramList});
|
|
|
130334
130847
|
const minComparison = minValue === "0" ? `0.0${floatSuffix}` : `((${floatCastType})${minValue})`;
|
|
130335
130848
|
const maxComparison = `((${floatCastType})${maxValue})`;
|
|
130336
130849
|
const finalCast = CppModeHelper_default.cast(targetType, `(${expr})`);
|
|
130337
|
-
|
|
130850
|
+
const castMax = CppModeHelper_default.cast(targetType, maxValue);
|
|
130851
|
+
const castMin = minValue === "0" ? "0" : CppModeHelper_default.cast(targetType, minValue);
|
|
130852
|
+
return `((${expr}) > ${maxComparison} ? ${castMax} : (${expr}) < ${minComparison} ? ${castMin} : ${finalCast})`;
|
|
130338
130853
|
}
|
|
130339
130854
|
/**
|
|
130340
130855
|
* ADR-023: Generate sizeof expression
|
|
@@ -132527,6 +133042,7 @@ var TSymbolInfoAdapter = class _TSymbolInfoAdapter {
|
|
|
132527
133042
|
const registerMemberCTypes = /* @__PURE__ */ new Map();
|
|
132528
133043
|
const scopePrivateConstValues = /* @__PURE__ */ new Map();
|
|
132529
133044
|
const functionReturnTypes = /* @__PURE__ */ new Map();
|
|
133045
|
+
const opaqueTypes = /* @__PURE__ */ new Set();
|
|
132530
133046
|
for (const symbol of symbols) {
|
|
132531
133047
|
switch (symbol.kind) {
|
|
132532
133048
|
case "struct":
|
|
@@ -132614,6 +133130,8 @@ var TSymbolInfoAdapter = class _TSymbolInfoAdapter {
|
|
|
132614
133130
|
scopePrivateConstValues,
|
|
132615
133131
|
// Function return types
|
|
132616
133132
|
functionReturnTypes,
|
|
133133
|
+
// Issue #948: Opaque types
|
|
133134
|
+
opaqueTypes,
|
|
132617
133135
|
// Methods
|
|
132618
133136
|
getSingleFunctionForVariable: (scopeName, varName) => _TSymbolInfoAdapter.getSingleFunctionForVariable(
|
|
132619
133137
|
scopeVariableUsage,
|
|
@@ -132811,42 +133329,35 @@ var TSymbolInfoAdapter = class _TSymbolInfoAdapter {
|
|
|
132811
133329
|
);
|
|
132812
133330
|
}
|
|
132813
133331
|
return {
|
|
132814
|
-
|
|
133332
|
+
...base,
|
|
132815
133333
|
knownScopes: mergedKnownScopes,
|
|
132816
|
-
knownStructs: base.knownStructs,
|
|
132817
133334
|
knownEnums: mergedKnownEnums,
|
|
132818
|
-
knownBitmaps: base.knownBitmaps,
|
|
132819
|
-
knownRegisters: base.knownRegisters,
|
|
132820
|
-
// Scope info
|
|
132821
|
-
scopeMembers: base.scopeMembers,
|
|
132822
|
-
scopeMemberVisibility: base.scopeMemberVisibility,
|
|
132823
|
-
scopeVariableUsage: base.scopeVariableUsage,
|
|
132824
|
-
// Struct info
|
|
132825
|
-
structFields: base.structFields,
|
|
132826
|
-
structFieldArrays: base.structFieldArrays,
|
|
132827
|
-
structFieldDimensions: base.structFieldDimensions,
|
|
132828
|
-
// Enum info - merged
|
|
132829
133335
|
enumMembers: mergedEnumMembers,
|
|
132830
|
-
|
|
132831
|
-
bitmapFields: base.bitmapFields,
|
|
132832
|
-
bitmapBackingType: base.bitmapBackingType,
|
|
132833
|
-
bitmapBitWidth: base.bitmapBitWidth,
|
|
132834
|
-
// Register info
|
|
132835
|
-
scopedRegisters: base.scopedRegisters,
|
|
132836
|
-
registerMemberAccess: base.registerMemberAccess,
|
|
132837
|
-
registerMemberTypes: base.registerMemberTypes,
|
|
132838
|
-
registerBaseAddresses: base.registerBaseAddresses,
|
|
132839
|
-
registerMemberOffsets: base.registerMemberOffsets,
|
|
132840
|
-
registerMemberCTypes: base.registerMemberCTypes,
|
|
132841
|
-
// Private const values
|
|
132842
|
-
scopePrivateConstValues: base.scopePrivateConstValues,
|
|
132843
|
-
// Function return types - merged
|
|
132844
|
-
functionReturnTypes: mergedFunctionReturnTypes,
|
|
132845
|
-
// Methods - delegate to base's implementation
|
|
132846
|
-
getSingleFunctionForVariable: base.getSingleFunctionForVariable,
|
|
132847
|
-
hasPublicSymbols: base.hasPublicSymbols
|
|
133336
|
+
functionReturnTypes: mergedFunctionReturnTypes
|
|
132848
133337
|
};
|
|
132849
133338
|
}
|
|
133339
|
+
/**
|
|
133340
|
+
* Issue #948: Merge opaque types from an external source (e.g., SymbolTable)
|
|
133341
|
+
* into an existing ICodeGenSymbols.
|
|
133342
|
+
*
|
|
133343
|
+
* Opaque types are forward-declared struct types (like `typedef struct _foo foo;`)
|
|
133344
|
+
* that come from C headers and need to be tracked for correct scope variable
|
|
133345
|
+
* generation (as pointers with NULL initialization).
|
|
133346
|
+
*
|
|
133347
|
+
* @param base The ICodeGenSymbols from the current file
|
|
133348
|
+
* @param externalOpaqueTypes Array of opaque type names from external sources
|
|
133349
|
+
* @returns New ICodeGenSymbols with merged opaque types
|
|
133350
|
+
*/
|
|
133351
|
+
static mergeOpaqueTypes(base, externalOpaqueTypes) {
|
|
133352
|
+
if (externalOpaqueTypes.length === 0) {
|
|
133353
|
+
return base;
|
|
133354
|
+
}
|
|
133355
|
+
const mergedOpaqueTypes = new Set(base.opaqueTypes);
|
|
133356
|
+
for (const typeName of externalOpaqueTypes) {
|
|
133357
|
+
mergedOpaqueTypes.add(typeName);
|
|
133358
|
+
}
|
|
133359
|
+
return { ...base, opaqueTypes: mergedOpaqueTypes };
|
|
133360
|
+
}
|
|
132850
133361
|
};
|
|
132851
133362
|
var TSymbolInfoAdapter_default = TSymbolInfoAdapter;
|
|
132852
133363
|
|
|
@@ -133233,6 +133744,30 @@ var DeclaratorUtils = class _DeclaratorUtils {
|
|
|
133233
133744
|
}
|
|
133234
133745
|
return void 0;
|
|
133235
133746
|
}
|
|
133747
|
+
/**
|
|
133748
|
+
* Extract the first declarator name from an init-declarator-list.
|
|
133749
|
+
* For "typedef struct _widget_t widget_t;", this returns "widget_t".
|
|
133750
|
+
* Used for Issue #948 opaque type detection.
|
|
133751
|
+
*/
|
|
133752
|
+
static extractFirstDeclaratorName(initDeclList) {
|
|
133753
|
+
const initDeclarators = initDeclList.initDeclarator?.();
|
|
133754
|
+
if (!initDeclarators || initDeclarators.length === 0) return void 0;
|
|
133755
|
+
const firstDeclarator = initDeclarators[0].declarator?.();
|
|
133756
|
+
if (!firstDeclarator) return void 0;
|
|
133757
|
+
return _DeclaratorUtils.extractDeclaratorName(firstDeclarator) ?? void 0;
|
|
133758
|
+
}
|
|
133759
|
+
/**
|
|
133760
|
+
* Check if the first declarator in an init-declarator-list has a pointer.
|
|
133761
|
+
* For "typedef struct X *handle_t;", the declarator is "*handle_t" which has a pointer.
|
|
133762
|
+
* Used for Issue #957 to distinguish pointer typedefs from opaque struct typedefs.
|
|
133763
|
+
*/
|
|
133764
|
+
static firstDeclaratorHasPointer(initDeclList) {
|
|
133765
|
+
const initDeclarators = initDeclList.initDeclarator?.();
|
|
133766
|
+
if (!initDeclarators || initDeclarators.length === 0) return false;
|
|
133767
|
+
const firstDeclarator = initDeclarators[0].declarator?.();
|
|
133768
|
+
if (!firstDeclarator) return false;
|
|
133769
|
+
return Boolean(firstDeclarator.pointer?.());
|
|
133770
|
+
}
|
|
133236
133771
|
};
|
|
133237
133772
|
var DeclaratorUtils_default = DeclaratorUtils;
|
|
133238
133773
|
|
|
@@ -133245,15 +133780,15 @@ var StructCollector2 = class _StructCollector {
|
|
|
133245
133780
|
* @param sourceFile Source file path
|
|
133246
133781
|
* @param line Source line number
|
|
133247
133782
|
* @param symbolTable Optional symbol table for field tracking
|
|
133248
|
-
* @param
|
|
133249
|
-
* @param isTypedef Whether this is part of a typedef declaration
|
|
133250
|
-
* @param warnings Array to collect warnings
|
|
133783
|
+
* @param options Optional collection options (typedef info, warnings)
|
|
133251
133784
|
*/
|
|
133252
|
-
static collect(structSpec, sourceFile, line, symbolTable,
|
|
133785
|
+
static collect(structSpec, sourceFile, line, symbolTable, options = {}) {
|
|
133786
|
+
const { typedefName, isTypedef, warnings, isPointerTypedef } = options;
|
|
133253
133787
|
const identifier = structSpec.Identifier();
|
|
133254
133788
|
const name = identifier?.getText() || typedefName;
|
|
133255
133789
|
if (!name) return null;
|
|
133256
133790
|
const isUnion = structSpec.structOrUnion()?.getText() === "union";
|
|
133791
|
+
const hasBody = structSpec.structDeclarationList() !== null;
|
|
133257
133792
|
const fields = _StructCollector.collectFields(
|
|
133258
133793
|
structSpec,
|
|
133259
133794
|
name,
|
|
@@ -133261,8 +133796,15 @@ var StructCollector2 = class _StructCollector {
|
|
|
133261
133796
|
warnings
|
|
133262
133797
|
);
|
|
133263
133798
|
const needsStructKeyword = Boolean(identifier && !isTypedef);
|
|
133264
|
-
if (symbolTable
|
|
133265
|
-
|
|
133799
|
+
if (symbolTable) {
|
|
133800
|
+
_StructCollector.updateSymbolTable(symbolTable, name, sourceFile, {
|
|
133801
|
+
needsStructKeyword,
|
|
133802
|
+
hasBody,
|
|
133803
|
+
isTypedef,
|
|
133804
|
+
typedefName,
|
|
133805
|
+
structTag: identifier?.getText(),
|
|
133806
|
+
isPointerTypedef
|
|
133807
|
+
});
|
|
133266
133808
|
}
|
|
133267
133809
|
return {
|
|
133268
133810
|
kind: "struct",
|
|
@@ -133276,6 +133818,60 @@ var StructCollector2 = class _StructCollector {
|
|
|
133276
133818
|
fields: fields.size > 0 ? fields : void 0
|
|
133277
133819
|
};
|
|
133278
133820
|
}
|
|
133821
|
+
/**
|
|
133822
|
+
* Update symbol table with struct metadata.
|
|
133823
|
+
* Extracted to reduce cognitive complexity of collect().
|
|
133824
|
+
*/
|
|
133825
|
+
static updateSymbolTable(symbolTable, name, sourceFile, options) {
|
|
133826
|
+
const {
|
|
133827
|
+
needsStructKeyword,
|
|
133828
|
+
hasBody,
|
|
133829
|
+
isTypedef,
|
|
133830
|
+
typedefName,
|
|
133831
|
+
structTag,
|
|
133832
|
+
isPointerTypedef
|
|
133833
|
+
} = options;
|
|
133834
|
+
if (needsStructKeyword) {
|
|
133835
|
+
symbolTable.markNeedsStructKeyword(name);
|
|
133836
|
+
}
|
|
133837
|
+
if (isTypedef && !hasBody && typedefName && !isPointerTypedef) {
|
|
133838
|
+
symbolTable.markOpaqueType(typedefName);
|
|
133839
|
+
if (structTag) {
|
|
133840
|
+
symbolTable.registerStructTagAlias(structTag, typedefName);
|
|
133841
|
+
}
|
|
133842
|
+
}
|
|
133843
|
+
if (isTypedef && typedefName && !isPointerTypedef) {
|
|
133844
|
+
symbolTable.markTypedefStructType(typedefName, sourceFile);
|
|
133845
|
+
}
|
|
133846
|
+
if (hasBody) {
|
|
133847
|
+
_StructCollector.unmarkOpaqueTypesOnDefinition(
|
|
133848
|
+
symbolTable,
|
|
133849
|
+
sourceFile,
|
|
133850
|
+
structTag,
|
|
133851
|
+
typedefName
|
|
133852
|
+
);
|
|
133853
|
+
}
|
|
133854
|
+
}
|
|
133855
|
+
/**
|
|
133856
|
+
* Unmark opaque and typedef struct types when a full struct definition is encountered.
|
|
133857
|
+
* Handles: typedef struct _foo foo; struct _foo { ... };
|
|
133858
|
+
* Issue #958: Only unmarks typedefStructTypes when definition is in SAME file.
|
|
133859
|
+
*/
|
|
133860
|
+
static unmarkOpaqueTypesOnDefinition(symbolTable, sourceFile, structTag, typedefName) {
|
|
133861
|
+
if (structTag) {
|
|
133862
|
+
const typedefAlias = symbolTable.getStructTagAlias(structTag);
|
|
133863
|
+
symbolTable.unmarkOpaqueType(structTag);
|
|
133864
|
+
symbolTable.unmarkTypedefStructType(structTag, sourceFile);
|
|
133865
|
+
if (typedefAlias) {
|
|
133866
|
+
symbolTable.unmarkOpaqueType(typedefAlias);
|
|
133867
|
+
symbolTable.unmarkTypedefStructType(typedefAlias, sourceFile);
|
|
133868
|
+
}
|
|
133869
|
+
}
|
|
133870
|
+
if (typedefName) {
|
|
133871
|
+
symbolTable.unmarkOpaqueType(typedefName);
|
|
133872
|
+
symbolTable.unmarkTypedefStructType(typedefName, sourceFile);
|
|
133873
|
+
}
|
|
133874
|
+
}
|
|
133279
133875
|
/**
|
|
133280
133876
|
* Collect fields from a struct/union definition.
|
|
133281
133877
|
*/
|
|
@@ -133412,6 +134008,15 @@ var FunctionCollector2 = class _FunctionCollector {
|
|
|
133412
134008
|
isArray: p.isArray
|
|
133413
134009
|
}));
|
|
133414
134010
|
}
|
|
134011
|
+
/**
|
|
134012
|
+
* Resolve return type, appending '*' if declarator has a pointer.
|
|
134013
|
+
* Issue #895 Bug B / Issue #945: C grammar puts pointer before directDeclarator
|
|
134014
|
+
* (e.g., `widget_t *func()` has declarator.pointer() !== null)
|
|
134015
|
+
*/
|
|
134016
|
+
static _resolveReturnType(baseType, declarator) {
|
|
134017
|
+
const hasPointer = declarator.pointer() !== null;
|
|
134018
|
+
return hasPointer ? `${baseType}*` : baseType;
|
|
134019
|
+
}
|
|
133415
134020
|
/**
|
|
133416
134021
|
* Collect a function symbol from a function definition.
|
|
133417
134022
|
*
|
|
@@ -133425,7 +134030,11 @@ var FunctionCollector2 = class _FunctionCollector {
|
|
|
133425
134030
|
if (!name) return null;
|
|
133426
134031
|
const line = funcDef.start?.line ?? 0;
|
|
133427
134032
|
const declSpecs = funcDef.declarationSpecifiers();
|
|
133428
|
-
const
|
|
134033
|
+
const baseType = declSpecs ? DeclaratorUtils_default.extractTypeFromDeclSpecs(declSpecs) : "int";
|
|
134034
|
+
const returnType = _FunctionCollector._resolveReturnType(
|
|
134035
|
+
baseType,
|
|
134036
|
+
declarator
|
|
134037
|
+
);
|
|
133429
134038
|
const parameters = _FunctionCollector._mapParameters(
|
|
133430
134039
|
DeclaratorUtils_default.extractFunctionParameters(declarator)
|
|
133431
134040
|
);
|
|
@@ -133455,8 +134064,10 @@ var FunctionCollector2 = class _FunctionCollector {
|
|
|
133455
134064
|
const parameters = _FunctionCollector._mapParameters(
|
|
133456
134065
|
DeclaratorUtils_default.extractFunctionParameters(declarator)
|
|
133457
134066
|
);
|
|
133458
|
-
const
|
|
133459
|
-
|
|
134067
|
+
const returnType = _FunctionCollector._resolveReturnType(
|
|
134068
|
+
baseType,
|
|
134069
|
+
declarator
|
|
134070
|
+
);
|
|
133460
134071
|
return {
|
|
133461
134072
|
kind: "function",
|
|
133462
134073
|
name,
|
|
@@ -133599,39 +134210,33 @@ var CResolver = class _CResolver {
|
|
|
133599
134210
|
const line = decl.start?.line ?? 0;
|
|
133600
134211
|
const isTypedef = DeclaratorUtils_default.hasStorageClass(declSpecs, "typedef");
|
|
133601
134212
|
const isExtern = DeclaratorUtils_default.hasStorageClass(declSpecs, "extern");
|
|
134213
|
+
const ctx = {
|
|
134214
|
+
sourceFile,
|
|
134215
|
+
line,
|
|
134216
|
+
isTypedef,
|
|
134217
|
+
isExtern,
|
|
134218
|
+
symbols
|
|
134219
|
+
};
|
|
133602
134220
|
const structSpec = DeclaratorUtils_default.findStructOrUnionSpecifier(declSpecs);
|
|
133603
134221
|
if (structSpec) {
|
|
133604
|
-
|
|
133605
|
-
const structSymbol = StructCollector_default2.collect(
|
|
134222
|
+
_CResolver.collectStructSymbol(
|
|
133606
134223
|
structSpec,
|
|
133607
|
-
|
|
133608
|
-
|
|
134224
|
+
decl,
|
|
134225
|
+
declSpecs,
|
|
134226
|
+
ctx,
|
|
133609
134227
|
symbolTable,
|
|
133610
|
-
typedefName,
|
|
133611
|
-
isTypedef,
|
|
133612
134228
|
warnings
|
|
133613
134229
|
);
|
|
133614
|
-
if (structSymbol) {
|
|
133615
|
-
symbols.push(structSymbol);
|
|
133616
|
-
}
|
|
133617
134230
|
}
|
|
133618
134231
|
const enumSpec = DeclaratorUtils_default.findEnumSpecifier(declSpecs);
|
|
133619
134232
|
if (enumSpec) {
|
|
133620
|
-
|
|
133621
|
-
|
|
133622
|
-
|
|
133623
|
-
|
|
133624
|
-
|
|
133625
|
-
|
|
133626
|
-
}
|
|
134233
|
+
_CResolver.collectEnumSymbols(
|
|
134234
|
+
enumSpec,
|
|
134235
|
+
ctx.sourceFile,
|
|
134236
|
+
ctx.line,
|
|
134237
|
+
ctx.symbols
|
|
134238
|
+
);
|
|
133627
134239
|
}
|
|
133628
|
-
const ctx = {
|
|
133629
|
-
sourceFile,
|
|
133630
|
-
line,
|
|
133631
|
-
isTypedef,
|
|
133632
|
-
isExtern,
|
|
133633
|
-
symbols
|
|
133634
|
-
};
|
|
133635
134240
|
const initDeclList = decl.initDeclaratorList();
|
|
133636
134241
|
if (initDeclList) {
|
|
133637
134242
|
const baseType = DeclaratorUtils_default.extractTypeFromDeclSpecs(declSpecs);
|
|
@@ -133645,6 +134250,63 @@ var CResolver = class _CResolver {
|
|
|
133645
134250
|
);
|
|
133646
134251
|
}
|
|
133647
134252
|
}
|
|
134253
|
+
/**
|
|
134254
|
+
* Collect struct symbol from a struct specifier.
|
|
134255
|
+
* Extracted to reduce cognitive complexity of collectDeclaration().
|
|
134256
|
+
*/
|
|
134257
|
+
static collectStructSymbol(structSpec, decl, declSpecs, ctx, symbolTable, warnings) {
|
|
134258
|
+
const typedefName = ctx.isTypedef ? _CResolver.extractTypedefName(decl, declSpecs) : void 0;
|
|
134259
|
+
const isPointerTypedef = ctx.isTypedef ? _CResolver.isPointerTypedef(decl) : false;
|
|
134260
|
+
const structSymbol = StructCollector_default2.collect(
|
|
134261
|
+
structSpec,
|
|
134262
|
+
ctx.sourceFile,
|
|
134263
|
+
ctx.line,
|
|
134264
|
+
symbolTable,
|
|
134265
|
+
{
|
|
134266
|
+
typedefName,
|
|
134267
|
+
isTypedef: ctx.isTypedef,
|
|
134268
|
+
warnings,
|
|
134269
|
+
isPointerTypedef
|
|
134270
|
+
}
|
|
134271
|
+
);
|
|
134272
|
+
if (structSymbol) {
|
|
134273
|
+
ctx.symbols.push(structSymbol);
|
|
134274
|
+
}
|
|
134275
|
+
}
|
|
134276
|
+
/**
|
|
134277
|
+
* Extract typedef name from declaration.
|
|
134278
|
+
* First try from init-declarator-list, then fall back to specifiers.
|
|
134279
|
+
*/
|
|
134280
|
+
static extractTypedefName(decl, declSpecs) {
|
|
134281
|
+
const initDeclList = decl.initDeclaratorList();
|
|
134282
|
+
if (initDeclList) {
|
|
134283
|
+
const name = DeclaratorUtils_default.extractFirstDeclaratorName(initDeclList);
|
|
134284
|
+
if (name) return name;
|
|
134285
|
+
}
|
|
134286
|
+
return DeclaratorUtils_default.extractTypedefNameFromSpecs(declSpecs);
|
|
134287
|
+
}
|
|
134288
|
+
/**
|
|
134289
|
+
* Check if a typedef declaration has a pointer declarator.
|
|
134290
|
+
* For "typedef struct X *Y", the declarator is "*Y" which has a pointer.
|
|
134291
|
+
* Used for Issue #957 to distinguish pointer typedefs from opaque struct typedefs.
|
|
134292
|
+
*/
|
|
134293
|
+
static isPointerTypedef(decl) {
|
|
134294
|
+
const initDeclList = decl.initDeclaratorList();
|
|
134295
|
+
if (!initDeclList) return false;
|
|
134296
|
+
return DeclaratorUtils_default.firstDeclaratorHasPointer(initDeclList);
|
|
134297
|
+
}
|
|
134298
|
+
/**
|
|
134299
|
+
* Collect enum symbols from an enum specifier.
|
|
134300
|
+
* Extracted to reduce cognitive complexity of collectDeclaration().
|
|
134301
|
+
*/
|
|
134302
|
+
static collectEnumSymbols(enumSpec, sourceFile, line, symbols) {
|
|
134303
|
+
const enumResult = EnumCollector_default2.collect(enumSpec, sourceFile, line);
|
|
134304
|
+
if (!enumResult) return;
|
|
134305
|
+
symbols.push(enumResult.enum);
|
|
134306
|
+
for (const member of enumResult.members) {
|
|
134307
|
+
symbols.push(member);
|
|
134308
|
+
}
|
|
134309
|
+
}
|
|
133648
134310
|
/**
|
|
133649
134311
|
* Collect symbols from init declarator list.
|
|
133650
134312
|
*/
|
|
@@ -137838,6 +138500,9 @@ var IndexTypeListener = class extends CNextListener {
|
|
|
137838
138500
|
if (TypeConstants_default.UNSIGNED_INDEX_TYPES.includes(resolvedType)) {
|
|
137839
138501
|
continue;
|
|
137840
138502
|
}
|
|
138503
|
+
if (CodeGenState.isKnownEnum(resolvedType)) {
|
|
138504
|
+
continue;
|
|
138505
|
+
}
|
|
137841
138506
|
const { line, column } = ParserUtils_default.getPosition(ctx);
|
|
137842
138507
|
this.analyzer.addError(line, column, "E0852", resolvedType);
|
|
137843
138508
|
return;
|
|
@@ -137927,6 +138592,10 @@ var IndexTypeListener = class extends CNextListener {
|
|
|
137927
138592
|
if (TypeConstants_default.SIGNED_TYPES.includes(currentType)) {
|
|
137928
138593
|
return "bool";
|
|
137929
138594
|
}
|
|
138595
|
+
const strippedType = currentType.replace(/\[[^\]]*\]$/, "");
|
|
138596
|
+
if (strippedType !== currentType) {
|
|
138597
|
+
return strippedType;
|
|
138598
|
+
}
|
|
137930
138599
|
return currentType;
|
|
137931
138600
|
}
|
|
137932
138601
|
if (op.LPAREN()) {
|
|
@@ -138327,7 +138996,7 @@ var CacheKeyGenerator_default = CacheKeyGenerator;
|
|
|
138327
138996
|
|
|
138328
138997
|
// src/utils/cache/CacheManager.ts
|
|
138329
138998
|
var defaultFs7 = NodeFileSystem_default.instance;
|
|
138330
|
-
var CACHE_VERSION =
|
|
138999
|
+
var CACHE_VERSION = 6;
|
|
138331
139000
|
var TRANSPILER_VERSION = package_default.version;
|
|
138332
139001
|
var CacheManager = class {
|
|
138333
139002
|
projectRoot;
|
|
@@ -138427,14 +139096,16 @@ var CacheManager = class {
|
|
|
138427
139096
|
symbols,
|
|
138428
139097
|
structFields,
|
|
138429
139098
|
needsStructKeyword: cachedEntry.needsStructKeyword ?? [],
|
|
138430
|
-
enumBitWidth
|
|
139099
|
+
enumBitWidth,
|
|
139100
|
+
opaqueTypes: cachedEntry.opaqueTypes ?? [],
|
|
139101
|
+
typedefStructTypes: cachedEntry.typedefStructTypes ?? []
|
|
138431
139102
|
};
|
|
138432
139103
|
}
|
|
138433
139104
|
/**
|
|
138434
139105
|
* Store symbols and struct fields for a file
|
|
138435
139106
|
* ADR-055 Phase 7: Takes ISerializedSymbol[] directly
|
|
138436
139107
|
*/
|
|
138437
|
-
setSymbols(filePath, symbols, structFields, needsStructKeyword, enumBitWidth) {
|
|
139108
|
+
setSymbols(filePath, symbols, structFields, needsStructKeyword, enumBitWidth, opaqueTypes, typedefStructTypes) {
|
|
138438
139109
|
if (!this.cache) return;
|
|
138439
139110
|
let cacheKey;
|
|
138440
139111
|
try {
|
|
@@ -138462,7 +139133,9 @@ var CacheManager = class {
|
|
|
138462
139133
|
symbols: serializedSymbols,
|
|
138463
139134
|
structFields: serializedFields,
|
|
138464
139135
|
needsStructKeyword,
|
|
138465
|
-
enumBitWidth: serializedEnumBitWidth
|
|
139136
|
+
enumBitWidth: serializedEnumBitWidth,
|
|
139137
|
+
opaqueTypes,
|
|
139138
|
+
typedefStructTypes
|
|
138466
139139
|
};
|
|
138467
139140
|
this.cache.setKey(filePath, entry);
|
|
138468
139141
|
this.dirty = true;
|
|
@@ -138490,12 +139163,16 @@ var CacheManager = class {
|
|
|
138490
139163
|
filePath,
|
|
138491
139164
|
symbolTable
|
|
138492
139165
|
);
|
|
139166
|
+
const opaqueTypes = symbolTable.getAllOpaqueTypes();
|
|
139167
|
+
const typedefStructTypes = symbolTable.getAllTypedefStructTypes();
|
|
138493
139168
|
this.setSymbols(
|
|
138494
139169
|
filePath,
|
|
138495
139170
|
symbols,
|
|
138496
139171
|
structFields,
|
|
138497
139172
|
needsStructKeyword,
|
|
138498
|
-
enumBitWidth
|
|
139173
|
+
enumBitWidth,
|
|
139174
|
+
opaqueTypes,
|
|
139175
|
+
typedefStructTypes
|
|
138499
139176
|
);
|
|
138500
139177
|
}
|
|
138501
139178
|
/**
|
|
@@ -138938,7 +139615,7 @@ var Transpiler = class {
|
|
|
138938
139615
|
* Stage 6: Generate headers (per-file)
|
|
138939
139616
|
*/
|
|
138940
139617
|
async _executePipeline(input, result) {
|
|
138941
|
-
this._collectAllHeaderSymbols(input.headerFiles, result);
|
|
139618
|
+
await this._collectAllHeaderSymbols(input.headerFiles, result);
|
|
138942
139619
|
CodeGenState.buildExternalStructFields();
|
|
138943
139620
|
if (!this._collectAllCNextSymbolsFromPipeline(input.cnextFiles, result)) {
|
|
138944
139621
|
return;
|
|
@@ -139047,6 +139724,13 @@ var Transpiler = class {
|
|
|
139047
139724
|
externalEnumSources
|
|
139048
139725
|
);
|
|
139049
139726
|
}
|
|
139727
|
+
const externalOpaqueTypes = CodeGenState.symbolTable.getAllOpaqueTypes();
|
|
139728
|
+
if (externalOpaqueTypes.length > 0) {
|
|
139729
|
+
symbolInfo = TSymbolInfoAdapter_default.mergeOpaqueTypes(
|
|
139730
|
+
symbolInfo,
|
|
139731
|
+
externalOpaqueTypes
|
|
139732
|
+
);
|
|
139733
|
+
}
|
|
139050
139734
|
CodeGenState.symbols = symbolInfo;
|
|
139051
139735
|
const analyzerErrors = runAnalyzers_default(tree, tokenStream);
|
|
139052
139736
|
if (analyzerErrors.length > 0) {
|
|
@@ -139220,11 +139904,12 @@ var Transpiler = class {
|
|
|
139220
139904
|
}
|
|
139221
139905
|
/**
|
|
139222
139906
|
* Stage 2: Collect symbols from all C/C++ headers
|
|
139907
|
+
* Issue #945: Made async for preprocessing support.
|
|
139223
139908
|
*/
|
|
139224
|
-
_collectAllHeaderSymbols(headerFiles, result) {
|
|
139909
|
+
async _collectAllHeaderSymbols(headerFiles, result) {
|
|
139225
139910
|
for (const file of headerFiles) {
|
|
139226
139911
|
try {
|
|
139227
|
-
this.doCollectHeaderSymbols(file);
|
|
139912
|
+
await this.doCollectHeaderSymbols(file);
|
|
139228
139913
|
result.filesProcessed++;
|
|
139229
139914
|
} catch (err) {
|
|
139230
139915
|
this.warnings.push(`Failed to process header ${file.path}: ${err}`);
|
|
@@ -139503,15 +140188,16 @@ var Transpiler = class {
|
|
|
139503
140188
|
/**
|
|
139504
140189
|
* Stage 2: Collect symbols from a single C/C++ header
|
|
139505
140190
|
* Issue #592: Recursive include processing moved to IncludeResolver.resolveHeadersTransitively()
|
|
140191
|
+
* Issue #945: Added preprocessing support for conditional compilation
|
|
139506
140192
|
* SonarCloud S3776: Refactored to use helper methods for reduced complexity.
|
|
139507
140193
|
*/
|
|
139508
|
-
doCollectHeaderSymbols(file) {
|
|
140194
|
+
async doCollectHeaderSymbols(file) {
|
|
139509
140195
|
const absolutePath = resolve12(file.path);
|
|
139510
140196
|
this.state.markHeaderProcessed(absolutePath);
|
|
139511
140197
|
if (this.tryRestoreFromCache(file)) {
|
|
139512
140198
|
return;
|
|
139513
140199
|
}
|
|
139514
|
-
const content = this.
|
|
140200
|
+
const content = await this.getHeaderContent(file);
|
|
139515
140201
|
this.parseHeaderFile(file, content);
|
|
139516
140202
|
if (this.config.debugMode) {
|
|
139517
140203
|
const symbols = CodeGenState.symbolTable.getSymbolsByFile(file.path);
|
|
@@ -139542,9 +140228,54 @@ var Transpiler = class {
|
|
|
139542
140228
|
cached.needsStructKeyword
|
|
139543
140229
|
);
|
|
139544
140230
|
CodeGenState.symbolTable.restoreEnumBitWidths(cached.enumBitWidth);
|
|
140231
|
+
CodeGenState.symbolTable.restoreOpaqueTypes(cached.opaqueTypes);
|
|
140232
|
+
CodeGenState.symbolTable.restoreTypedefStructTypes(
|
|
140233
|
+
cached.typedefStructTypes
|
|
140234
|
+
);
|
|
139545
140235
|
this.detectCppFromFileType(file);
|
|
139546
140236
|
return true;
|
|
139547
140237
|
}
|
|
140238
|
+
/**
|
|
140239
|
+
* Get header content, optionally preprocessed.
|
|
140240
|
+
* Issue #945: Evaluates #if/#ifdef directives using system preprocessor.
|
|
140241
|
+
*
|
|
140242
|
+
* Only preprocesses when necessary to avoid side effects from full expansion.
|
|
140243
|
+
* Preprocessing is needed when the file has conditional compilation patterns
|
|
140244
|
+
* like #if MACRO != 0 that require expression evaluation.
|
|
140245
|
+
*/
|
|
140246
|
+
async getHeaderContent(file) {
|
|
140247
|
+
const rawContent = this.fs.readFile(file.path);
|
|
140248
|
+
if (this.config.preprocess === false) {
|
|
140249
|
+
return rawContent;
|
|
140250
|
+
}
|
|
140251
|
+
if (!this.preprocessor.isAvailable()) {
|
|
140252
|
+
return rawContent;
|
|
140253
|
+
}
|
|
140254
|
+
if (!this.needsConditionalPreprocessing(rawContent)) {
|
|
140255
|
+
return rawContent;
|
|
140256
|
+
}
|
|
140257
|
+
const result = await this.preprocessor.preprocess(file.path, {
|
|
140258
|
+
defines: this.config.defines,
|
|
140259
|
+
includePaths: this.config.includeDirs,
|
|
140260
|
+
keepLineDirectives: false
|
|
140261
|
+
// We don't need line mappings for symbol collection
|
|
140262
|
+
});
|
|
140263
|
+
if (!result.success) {
|
|
140264
|
+
this.warnings.push(
|
|
140265
|
+
`Preprocessing failed for ${file.path}: ${result.error}. Using raw content.`
|
|
140266
|
+
);
|
|
140267
|
+
return rawContent;
|
|
140268
|
+
}
|
|
140269
|
+
return result.content;
|
|
140270
|
+
}
|
|
140271
|
+
/**
|
|
140272
|
+
* Check if a header file needs conditional preprocessing.
|
|
140273
|
+
* Issue #945: Only preprocess files with #if expressions that need evaluation.
|
|
140274
|
+
*/
|
|
140275
|
+
needsConditionalPreprocessing(content) {
|
|
140276
|
+
const ifExpressionPattern = /#(?:if|elif)\s+(?!defined\s*\()(?![01]\s*(?:$|\n|\/\*|\/\/))\w+/m;
|
|
140277
|
+
return ifExpressionPattern.test(content);
|
|
140278
|
+
}
|
|
139548
140279
|
/**
|
|
139549
140280
|
* Restore cached symbols to the symbol table.
|
|
139550
140281
|
* ADR-055 Phase 7: Converts ISerializedSymbol[] from cache to typed symbols.
|