{"record":{"id":"af942c0794ad691e","repo":"abhigyanpatwari/GitNexus","slug":"cfg-unresolved-goto-label-label-routed-to-e","errorCode":null,"errorMessage":"[cfg] unresolved goto label \"${label}\" routed to EXIT (${froms.length} site(s))","messagePattern":"\\[cfg\\] unresolved goto label \"(.+?)\" routed to EXIT \\((.+?) site\\(s\\)\\)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"gitnexus/src/core/ingestion/cfg/visitors/c-cpp.ts","lineNumber":574,"sourceCode":"  }\n\n  private labelOf(stmt: SyntaxNode): string | undefined {\n    const id =\n      stmt.childForFieldName('label') ??\n      stmt.namedChildren.find((c) => c.type === 'statement_identifier');\n    return id?.text;\n  }\n\n  /**\n   * Drain any forward gotos whose label never appeared in the function (a label\n   * defined in a header macro, or malformed source) — route them to EXIT so the\n   * graph stays single-exit. Logs via console.warn (the builder's warn path)\n   * so a dropped jump is never silent (R4). Called once after the body walk.\n   */\n  finishGotos(): void {\n    for (const [label, froms] of this.pendingGotos) {\n      // eslint-disable-next-line no-console\n      console.warn(\n        `[cfg] unresolved goto label \"${label}\" routed to EXIT (${froms.length} site(s))`,\n      );\n      for (const from of froms) this.builder.edge(from, this.builder.exitIndex, 'seq');\n    }\n    this.pendingGotos.clear();\n  }\n}\n\n/**\n * C++ walk — extends the C core with exception flow and the range-for loop.\n * These node types never appear in a C parse, so no language conditional is\n * needed; the C core dispatches them through {@link visitExtra}.\n */\nclass CppCfgWalk extends CCfgWalk {\n  protected override visitExtra(stmt: SyntaxNode): SeqResult | undefined {\n    switch (stmt.type) {\n      case 'for_range_loop':\n        return this.visitForRange(stmt);","sourceCodeStart":556,"sourceCodeEnd":592,"githubUrl":"https://github.com/abhigyanpatwari/GitNexus/blob/aac7515d2a8c50a1f8f923c6fb77218b333560d6/gitnexus/src/core/ingestion/cfg/visitors/c-cpp.ts#L556-L592","documentation":"In the C/C++ CFG builder's finishGotos(), a forward goto statement's target label was never seen while walking the function body — typically because the label is produced by a header macro or the source is malformed. To keep the CFG single-exit the jump is routed to the EXIT node, and every unresolved label is logged via console.warn (the builder's warn path) so a dropped jump is never silent (R4).","triggerScenarios":"A goto whose label text comes from a macro defined in a header; preprocessed or partial C/C++ source where the label is absent; genuinely malformed code with a goto to a label that does not exist in the function (parses but would not compile).","commonSituations":"Macro-heavy legacy C where labels hide behind #define'd blocks; generated C being indexed; analysis of snippets that do not compile on their own.","solutions":["Check whether the label is defined inside a macro in a header; inline the label or exclude such files if full CFG fidelity is not needed","Fix malformed source — in compilable code every goto label exists in the same function","Accept the EXIT routing for analysis purposes; it is a deliberate degradation that keeps the graph single-exit and the drop is now observable"],"exampleFix":"// before — label hidden in a header macro (util.h: #define DONE done:)\nint f(void) { goto done; DONE return 0; }\n\n// after — label inline in the function\nint f(void) { goto done; done: return 0; }","handlingStrategy":"fallback","validationCode":"// Pre-check: flag gotos whose label is not literally defined in the file\nconst gotoLabels = [...source.matchAll(/\\bgoto\\s+([A-Za-z_]\\w*)\\s*;/g)].map((m) => m[1]);\nconst defined = new Set([...source.matchAll(/^\\s*([A-Za-z_]\\w*)\\s*:/gm)].map((m) => m[1]));\nconst unresolved = gotoLabels.filter((l) => !defined.has(l));\nif (unresolved.length > 0) {\n  console.warn(`macro-hidden or missing labels: ${[...new Set(unresolved)].join(', ')}`);\n}","typeGuard":"function hasResolvableGotoLabels(source: string): boolean {\n  const gotos = [...source.matchAll(/\\bgoto\\s+([A-Za-z_]\\w*)\\s*;/g)].map((m) => m[1]);\n  const defined = new Set([...source.matchAll(/^\\s*([A-Za-z_]\\w*)\\s*:/gm)].map((m) => m[1]));\n  return gotos.every((l) => defined.has(l));\n}","tryCatchPattern":null,"preventionTips":["Prefer inline labels over macro-defined labels in C/C++ destined for analysis","Compile the code (or at least syntax-check it) before indexing — undefined goto labels never compile","Treat the warning as informational: the CFG already degrades safely by routing such jumps to EXIT"],"tags":["cfg","c","cpp","goto","macro"],"backgroundTag":"unresolved-goto-label","analyzedSha":"aac7515d2a8c50a1f8f923c6fb77218b333560d6","analyzedAt":"2026-08-20T23:29:22.980Z","contentChangedAt":"2026-08-20T23:29:22.980Z","schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}