Skip to content

feat(io): direct READS_FROM/WRITES_TO sinks for C++ (#714)#753

Merged
vitali87 merged 2 commits into
mainfrom
feat/714-cpp-io
Jul 14, 2026
Merged

feat(io): direct READS_FROM/WRITES_TO sinks for C++ (#714)#753
vitali87 merged 2 commits into
mainfrom
feat/714-cpp-io

Conversation

@vitali87

Copy link
Copy Markdown
Owner

Extends the language-agnostic io direct-sink walk (issue #714) to C++, the last per-language item in the #714 list. Built on the same descriptor-driven design as Go/JS/TS/Java/Rust.

What lands

  • std::getenv / getenv / secure_getenvREADS_FROM resource::ENV::<name>
  • printf / puts (and std:: forms) → WRITES_TO resource::STDOUT::<dynamic>
  • std::cout / std::cerr / std::clog <<WRITES_TO resource::STDOUT::<dynamic>

Both the bare (C linkage / using namespace std) and std::-qualified forms are keyed.

New capability

C++ is the first language whose stdout path is an operator (std::cout << x), not a call. Added a stream_sink_type/stream_sink_operator descriptor pair + an IO_STREAM_SINKS table + _emit_stream_sink, which walks the left-associative << chain down its left spine to the base operand and matches cout/cerr/clog. Emits once at the chain top; an arithmetic x << 2 resolves to a non-sink base and emits nothing. This parallels Rust's macro mechanism.

Deliberately excluded (ambiguous by name — deferred to follow-ups)

  • fprintf / fputs / fwrite — first arg is a FILE* that may be stdout/stderr or a file handle; needs handle tracking to classify.
  • remove / renamestd::remove/std::rename overload the STL erase-remove algorithm on iterators, so keying them by name would false-match the ubiquitous erase-remove idiom.
  • fstream/ofstream/fopen file handles — the shared stream-handle follow-up.

Ceilings (ponytail-commented)

Shadowing of an I/O sink name by a C++ local/param (a variable named getenv/cout) is pathological, so the shadow machinery is intentionally inert; plain-name matching is sound here.

Tests

test_cpp_io_e2e.py: direct sinks + stream insertion, unqualified getenv, nested-lambda pruning. io/flow regression 184 green; lint/ty clean.

@vitali87

Copy link
Copy Markdown
Owner Author

@greptile review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces support for parsing C++ I/O direct-sinks and stream-insertion operations (such as std::cout << x). It adds C++ AST constants, defines a C++ language descriptor, updates the I/O processor to handle left-associative stream-insertion chains, registers standard C++ direct-call and stream sinks, and includes comprehensive integration tests. The review feedback suggests expanding the registered sinks to include putchar for direct calls and wide-character streams (wcout, wcerr, wclog) for stream-insertion operations.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread codebase_rag/parsers/io_access/registry.py
Comment thread codebase_rag/parsers/io_access/registry.py
@greptile-apps

greptile-apps Bot commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR extends the descriptor-driven direct I/O sink walk to C++. The main changes are:

  • Adds C++ environment read sinks for getenv, std::getenv, and secure_getenv.
  • Adds C++ stdout write sinks for printf, puts, putchar, and std::-qualified forms.
  • Adds stream-insertion detection for std::cout, std::cerr, std::clog, and wide stream variants.
  • Adds integration coverage for direct calls, stream insertion, wide streams, and nested-lambda pruning.

Confidence Score: 5/5

Safe to merge with minimal risk.

Changes are localized to the existing I/O sink descriptor path and include targeted integration tests for the new C++ behavior.

No files require special attention.

T-Rex T-Rex Logs

What T-Rex did

  • Environment check confirmed uv exists while cmake, cmake3, and docker were not found on PATH.
  • The end-to-end pytest run could not start due to missing CMake tools, with messages that cmake3 and cmake are not accessible and no suitable cmake could be found.
  • The harness after-generation passed all targeted checks and reported EXIT_CODE: 0, including secure_getenv_reads_env: True, printf_writes_stdout: True, cout_stream_stdout: True, and stream_operator_left_shift: True.

View all artifacts

T-Rex Ran code and verified through T-Rex

Important Files Changed

Filename Overview
codebase_rag/constants/ast_cpp.py Adds C++ AST constants for I/O sink detection, including stream insertion and field/subscript shapes.
codebase_rag/parsers/io_access/descriptor.py Registers a C++ language descriptor for direct calls, nested-scope pruning, and stream-insertion sinks.
codebase_rag/parsers/io_access/processor.py Threads stream sink tables through the direct-sink walk and emits one stdout edge for top-level C++ insertion chains.
codebase_rag/parsers/io_access/registry.py Adds C++ call sinks and stream sinks keyed for both bare and std-qualified names.
codebase_rag/tests/integration/test_cpp_io_e2e.py Adds integration coverage for C++ getenv, stdout calls, stream insertion, wide streams, and nested-lambda pruning.
uv.lock Updates the editable package version in the lockfile.

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
participant GU as GraphUpdater
participant IO as IOAccessProcessor
participant Desc as C++ LanguageDescriptor
participant Reg as IO registry
participant Graph as Resource edges

GU->>IO: run capture group IO for C++ caller
IO->>Desc: load C++ call and stream sink settings
IO->>Reg: load IO_SINKS and IO_STREAM_SINKS
IO->>IO: walk caller body, pruning nested scopes
alt call_expression sink
    IO->>Graph: emit READS_FROM/WRITES_TO resource
else "binary_expression << chain"
    IO->>IO: walk left spine to cout/cerr/clog base
    IO->>Graph: "emit WRITES_TO STDOUT::<dynamic>"
end
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
participant GU as GraphUpdater
participant IO as IOAccessProcessor
participant Desc as C++ LanguageDescriptor
participant Reg as IO registry
participant Graph as Resource edges

GU->>IO: run capture group IO for C++ caller
IO->>Desc: load C++ call and stream sink settings
IO->>Reg: load IO_SINKS and IO_STREAM_SINKS
IO->>IO: walk caller body, pruning nested scopes
alt call_expression sink
    IO->>Graph: emit READS_FROM/WRITES_TO resource
else "binary_expression << chain"
    IO->>IO: walk left spine to cout/cerr/clog base
    IO->>Graph: "emit WRITES_TO STDOUT::<dynamic>"
end
Loading

Reviews (3): Last reviewed commit: "feat(io): add C++ putchar and wide-char ..." | Re-trigger Greptile

@greptile-apps

greptile-apps Bot commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds C++ support to the descriptor-driven direct I/O sink walk. The main changes are:

  • C++ environment reads for std::getenv, getenv, and secure_getenv.
  • C++ stdout writes for printf, puts, and their std:: forms.
  • Stream insertion detection for std::cout, std::cerr, and std::clog << chains.
  • Integration tests for direct sinks, unqualified getenv, stream insertion, and nested lambda pruning.
  • Lockfile package version update.

Confidence Score: 5/5

Safe to merge with minimal risk.

The changes are localized to the existing descriptor-driven I/O sink path and include focused integration tests for the new C++ behavior. No correctness or security issues were found in the changed files.

No files require special attention.

T-Rex T-Rex Logs

What T-Rex did

  • Reviewed the general contract validation results and confirmed that direct_getenv_printf_puts_streams emits reads from ENV resources SECRET, TOKEN, and SAFE, along with STDOUT writes for printf, puts, and the cout/cerr/clog stream chains.
  • Verified that arithmetic_shift_only produced no edges, supporting that arithmetic left-shift expressions are not treated as stream sinks.
  • Checked that nested_lambda_pruned produced no edges for getenv/printf inside a lambda nested under the enclosing function.
  • Validated that stream_operand_call emitted both READS_FROM resource::ENV::INLINE and one WRITES_TO resource::STDOUT::<dynamic>, proving descent into stream operands while writing once for the top insertion chain.

View all artifacts

T-Rex Ran code and verified through T-Rex

Important Files Changed

Filename Overview
codebase_rag/constants/ast_cpp.py Adds C++ tree-sitter constants used by the new direct I/O sink descriptor and stream insertion detection; no issues found.
codebase_rag/parsers/io_access/descriptor.py Adds the C++ language descriptor and stream sink descriptor fields for operator-based stdout sinks; no issues found.
codebase_rag/parsers/io_access/processor.py Threads stream sink tables through the direct I/O walk and emits one stdout edge for top-level C++ insertion chains; no issues found.
codebase_rag/parsers/io_access/registry.py Registers C++ call sinks and stream insertion sinks for environment reads and stdout writes; no issues found.
codebase_rag/tests/integration/test_cpp_io_e2e.py Adds integration coverage for C++ direct calls, stream insertion, unqualified getenv, and nested lambda pruning; no issues found.
uv.lock Updates the editable package version in the lockfile; no issues found.

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
participant GU as GraphUpdater
participant P as IOAccessProcessor
participant D as C++ LanguageDescriptor
participant R as IO registries
participant G as Graph ingestor

GU->>P: run IO capture for C++ caller
P->>D: load C++ AST node and operator fields
P->>R: load call sinks and stream sinks
P->>P: walk caller body and prune nested scopes
alt call_expression sink
    P->>R: resolve getenv/printf/puts name
    P->>G: emit READS_FROM or WRITES_TO resource
else "binary_expression << chain"
    P->>P: find top insertion and left-spine base
    P->>R: match cout/cerr/clog stream sink
    P->>G: "emit WRITES_TO resource::STDOUT::<dynamic>"
end
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
participant GU as GraphUpdater
participant P as IOAccessProcessor
participant D as C++ LanguageDescriptor
participant R as IO registries
participant G as Graph ingestor

GU->>P: run IO capture for C++ caller
P->>D: load C++ AST node and operator fields
P->>R: load call sinks and stream sinks
P->>P: walk caller body and prune nested scopes
alt call_expression sink
    P->>R: resolve getenv/printf/puts name
    P->>G: emit READS_FROM or WRITES_TO resource
else "binary_expression << chain"
    P->>P: find top insertion and left-spine base
    P->>R: match cout/cerr/clog stream sink
    P->>G: "emit WRITES_TO resource::STDOUT::<dynamic>"
end
Loading

Reviews (2): Last reviewed commit: "feat(io): direct READS_FROM/WRITES_TO si..." | Re-trigger Greptile

@vitali87

Copy link
Copy Markdown
Owner Author

@greptile review

@vitali87
vitali87 merged commit df23003 into main Jul 14, 2026
21 of 22 checks passed
@vitali87
vitali87 deleted the feat/714-cpp-io branch July 14, 2026 14:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

1 participant