mirror of
https://github.com/abhigyanpatwari/GitNexus.git
synced 2026-10-11 03:38:07 +00:00
fix(cfg): model C++ co_return as a return terminator to EXIT (#2195)
co_return_statement was neither in CPP_CONTROL_FLOW_TYPES nor dispatched, so a coroutine's co_return coalesced into a straight-line block and emitted a spurious seq fallthrough to the following statement instead of an edge to EXIT — statements after co_return looked reachable and the terminator edge was missing, corrupting CFG/CDG for coroutines. Add the node type to the C++ control-flow set and dispatch it through visitReturn (block -> EXIT 'return', no fallthrough). C path untouched; co_await/co_yield remain plain expressions. Characterization test added; c-cpp suite + grammar-literal gate green, bench --check unchanged. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
5165d71d7b
commit
a654c1c764
2 changed files with 19 additions and 0 deletions
|
|
@ -93,6 +93,7 @@ const CPP_CONTROL_FLOW_TYPES = new Set([
|
|||
'for_range_loop',
|
||||
'try_statement',
|
||||
'throw_statement',
|
||||
'co_return_statement',
|
||||
]);
|
||||
|
||||
const LOOP_OR_SWITCH_TYPES = new Set([
|
||||
|
|
@ -589,6 +590,11 @@ class CppCfgWalk extends CCfgWalk {
|
|||
return this.visitTry(stmt);
|
||||
case 'throw_statement':
|
||||
return this.visitThrow(stmt);
|
||||
case 'co_return_statement':
|
||||
// A coroutine `co_return` terminates the coroutine like an ordinary
|
||||
// return: edge to EXIT, no fallthrough (`co_await`/`co_yield` are plain
|
||||
// expressions that continue, so they need no control-flow handling).
|
||||
return this.visitReturn(stmt);
|
||||
default:
|
||||
return undefined;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -253,6 +253,19 @@ describe('C++ CfgVisitor — structured bindings (#2195 P1)', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('C++ CfgVisitor — coroutines (#2195 P1)', () => {
|
||||
it('co_return edges to EXIT (return), not a seq fallthrough to the next statement', () => {
|
||||
const cfg = cpp.cfgOf(`Task f(int x) { if (x) co_return early(); main(); }`);
|
||||
const co = block(cfg, 'co_return early();');
|
||||
// co_return is a return terminator: it edges to EXIT…
|
||||
expect(
|
||||
cfg.edges.some((e) => e.from === co && e.to === cfg.exitIndex && e.kind === 'return'),
|
||||
).toBe(true);
|
||||
// …and never falls through to the following statement.
|
||||
expect(cfg.edges.some((e) => e.from === co && e.kind === 'seq')).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('C CfgVisitor — functionStartColumn', () => {
|
||||
it('two same-line functions get distinct functionStartColumn', () => {
|
||||
const cfgs = c.cfgsOf(`int a(){return 1;} int b(){return 2;}`);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue