feat(io): direct READS_FROM/WRITES_TO sinks for C++ (#714)#753
Conversation
|
@greptile review |
There was a problem hiding this comment.
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.
Greptile SummaryThis PR extends the descriptor-driven direct I/O sink walk to C++. The main changes are:
Confidence Score: 5/5Safe 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.
What T-Rex did
Important Files Changed
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
%%{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
Reviews (3): Last reviewed commit: "feat(io): add C++ putchar and wide-char ..." | Re-trigger Greptile |
Greptile SummaryThis PR adds C++ support to the descriptor-driven direct I/O sink walk. The main changes are:
Confidence Score: 5/5Safe 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.
What T-Rex did
Important Files Changed
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
%%{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
Reviews (2): Last reviewed commit: "feat(io): direct READS_FROM/WRITES_TO si..." | Re-trigger Greptile |
|
@greptile review |
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_getenv→READS_FROM resource::ENV::<name>printf/puts(andstd::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) andstd::-qualified forms are keyed.New capability
C++ is the first language whose stdout path is an operator (
std::cout << x), not a call. Added astream_sink_type/stream_sink_operatordescriptor pair + anIO_STREAM_SINKStable +_emit_stream_sink, which walks the left-associative<<chain down itsleftspine to the base operand and matchescout/cerr/clog. Emits once at the chain top; an arithmeticx << 2resolves 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 aFILE*that may bestdout/stderror a file handle; needs handle tracking to classify.remove/rename—std::remove/std::renameoverload the STL erase-remove algorithm on iterators, so keying them by name would false-match the ubiquitous erase-remove idiom.fstream/ofstream/fopenfile 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, unqualifiedgetenv, nested-lambda pruning. io/flow regression 184 green; lint/ty clean.