C++: Add predicates to support C++23 multidimensional subscript operators#21126
C++: Add predicates to support C++23 multidimensional subscript operators#21126jketema merged 6 commits intogithub:mainfrom
Conversation
There was a problem hiding this comment.
Pull request overview
This PR adds support for C++23 multidimensional subscript operators, which allow operator[] to accept multiple indices (e.g., array[i, j] instead of array[i][j]). The PR updates the CodeQL library to handle this new language feature.
- Deprecates the
OverloadedArrayExpr::getArrayOffset/0predicate in favor of indexed access - Adds
getArrayOffset/1to retrieve a specific index by position, andgetAnArrayOffsetto retrieve any index - Updates existing code to use the new predicates
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| cpp/ql/lib/semmle/code/cpp/exprs/Call.qll | Adds new predicates getArrayOffset(int n) and getAnArrayOffset(), deprecates getArrayOffset() |
| cpp/ql/lib/semmle/code/cpp/PrintAST.qll | Updates AST printing to use indexed array offset predicates |
| cpp/ql/src/jsf/lib/section_4_21_Operators/AV_Rule_166.qll | Updates to check all array offsets are pure using getAnArrayOffset() |
| cpp/ql/test/library-tests/subscript_operator/test.cpp | Test case demonstrating C++23 multidimensional subscript operator syntax |
| cpp/ql/test/library-tests/subscript_operator/PrintAST.qlref | Test reference to PrintAST query |
| cpp/ql/test/library-tests/subscript_operator/PrintAST.expected | Expected AST output showing indexed array offsets |
| cpp/ql/test/library-tests/ir/ir/PrintAST.expected | Updated expected output to use getArrayOffset(0) |
| cpp/ql/lib/change-notes/2026-01-08-multidimensional-subscript-operator-1.md | Feature change note documenting new predicates |
| cpp/ql/lib/change-notes/2026-01-08-multidimensional-subscript-operator-2.md | Deprecation change note for old predicate |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| deprecated Expr getArrayOffset() { result = this.getArrayOffset(0) } | ||
|
|
||
| /** | ||
| * Gets the expression giving the nth index. |
There was a problem hiding this comment.
The documentation comment "Gets the expression giving the nth index" could be clearer. Consider specifying that n is 0-indexed (i.e., n=0 gives the first index, n=1 gives the second index, etc.) to make the usage more explicit for users.
| * Gets the expression giving the nth index. | |
| * Gets the expression giving the nth index, where `n` is 0-based | |
| * (that is, `n = 0` gives the first index, `n = 1` gives the second, etc.). |
There was a problem hiding this comment.
Perhaps one of these changes, both feels excessive, and frankly 0-based is generally the default for both C and CodeQL.
There was a problem hiding this comment.
I thought the same 😄
| Expr getArrayOffset() { | ||
| if exists(this.getQualifier()) then result = this.getChild(0) else result = this.getChild(1) | ||
| Expr getArrayOffset(int n) { | ||
| n >= 0 and |
There was a problem hiding this comment.
I gather it is safe to assume there are no further children (i.e. that this won't return a result if n is greater than the highest array dimension)?
There was a problem hiding this comment.
With the current extractor implementation it is.
This is supported out-of-the-box by the extractor.
See also https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2128r6.pdf
DCA is uneventful.