mirror of
https://github.com/github/codeql.git
synced 2026-02-12 05:01:06 +01:00
Merge pull request #21126 from jketema/subscript
C++: Add predicates to support C++23 multidimensional subscript operators
This commit is contained in:
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: feature
|
||||
---
|
||||
* Predicates `getArrayOffset/1` and `getAnArrayOffset` have been added to the `OverloadedArrayExpr` class to support C++23 multidimensional subscript operators.
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: deprecated
|
||||
---
|
||||
* The `OverloadedArrayExpr::getArrayOffset/0` predicate has been deprecated. Use `OverloadedArrayExpr::getArrayOffset/1` and `OverloadedArrayExpr::getAnArrayOffset` instead.
|
||||
@@ -1050,10 +1050,10 @@ private predicate namedExprChildPredicates(Expr expr, Element ele, string pred)
|
||||
expr.(Call).getQualifier() = ele and
|
||||
pred = "getQualifier()"
|
||||
or
|
||||
// OverloadedArrayExpr::getArrayBase/0 and OverloadedArrayExpr::getArrayOffset/0 also consider arguments, and are already handled below.
|
||||
// OverloadedArrayExpr::getArrayBase/0 and OverloadedArrayExpr::getArrayOffset/1 also consider arguments, and are already handled below.
|
||||
exists(int n, Expr arg | expr.(Call).getArgument(n) = arg |
|
||||
not expr.(OverloadedArrayExpr).getArrayBase() = arg and
|
||||
not expr.(OverloadedArrayExpr).getArrayOffset() = arg and
|
||||
not expr.(OverloadedArrayExpr).getAnArrayOffset() = arg and
|
||||
arg = ele and
|
||||
pred = "getArgument(" + n.toString() + ")"
|
||||
)
|
||||
@@ -1062,7 +1062,10 @@ private predicate namedExprChildPredicates(Expr expr, Element ele, string pred)
|
||||
or
|
||||
expr.(OverloadedArrayExpr).getArrayBase() = ele and pred = "getArrayBase()"
|
||||
or
|
||||
expr.(OverloadedArrayExpr).getArrayOffset() = ele and pred = "getArrayOffset()"
|
||||
exists(int n |
|
||||
expr.(OverloadedArrayExpr).getArrayOffset(n) = ele and
|
||||
pred = "getArrayOffset(" + n.toString() + ")"
|
||||
)
|
||||
or
|
||||
// OverloadedPointerDereferenceExpr::getExpr/0 also considers qualifiers, and is already handled above for all Call classes.
|
||||
not expr.(OverloadedPointerDereferenceExpr).getQualifier() =
|
||||
|
||||
@@ -387,10 +387,23 @@ class OverloadedArrayExpr extends FunctionCall {
|
||||
|
||||
/**
|
||||
* Gets the expression giving the index.
|
||||
*
|
||||
* DEPRECATED: Use getArrayOffset/1 instead.
|
||||
*/
|
||||
Expr getArrayOffset() {
|
||||
if exists(this.getQualifier()) then result = this.getChild(0) else result = this.getChild(1)
|
||||
deprecated Expr getArrayOffset() { result = this.getArrayOffset(0) }
|
||||
|
||||
/**
|
||||
* Gets the expression giving the nth index.
|
||||
*/
|
||||
Expr getArrayOffset(int n) {
|
||||
n >= 0 and
|
||||
if exists(this.getQualifier()) then result = this.getChild(n) else result = this.getChild(n + 1)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an expression giving an index.
|
||||
*/
|
||||
Expr getAnArrayOffset() { result = this.getArrayOffset(_) }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -13,7 +13,7 @@ class SizeofImpureExprOperator extends SizeofExprOperator {
|
||||
not e.(OverloadedPointerDereferenceExpr).getExpr().isPure() and
|
||||
not exists(OverloadedArrayExpr op | op = e |
|
||||
op.getArrayBase().isPure() and
|
||||
op.getArrayOffset().isPure()
|
||||
forall(Expr offset | offset = op.getAnArrayOffset() | offset.isPure())
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -24309,7 +24309,7 @@ ir.cpp:
|
||||
# 2727| getArrayBase(): [VariableAccess] x
|
||||
# 2727| Type = [SpecifiedType] const WithBracketOperator
|
||||
# 2727| ValueCategory = lvalue
|
||||
# 2727| getArrayOffset(): [VariableAccess] i
|
||||
# 2727| getArrayOffset(0): [VariableAccess] i
|
||||
# 2727| Type = [IntType] int
|
||||
# 2727| ValueCategory = prvalue(load)
|
||||
# 2727| getExpr().getFullyConverted(): [ReferenceDereferenceExpr] (reference dereference)
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
#-----| [CopyAssignmentOperator] __va_list_tag& __va_list_tag::operator=(__va_list_tag const&)
|
||||
#-----| <params>:
|
||||
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
|
||||
#-----| Type = [LValueReferenceType] const __va_list_tag &
|
||||
#-----| [MoveAssignmentOperator] __va_list_tag& __va_list_tag::operator=(__va_list_tag&&)
|
||||
#-----| <params>:
|
||||
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
|
||||
#-----| Type = [RValueReferenceType] __va_list_tag &&
|
||||
test.cpp:
|
||||
# 3| [CopyAssignmentOperator] S& S::operator=(S const&)
|
||||
# 3| <params>:
|
||||
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
|
||||
#-----| Type = [LValueReferenceType] const S &
|
||||
# 3| [MoveAssignmentOperator] S& S::operator=(S&&)
|
||||
# 3| <params>:
|
||||
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
|
||||
#-----| Type = [RValueReferenceType] S &&
|
||||
# 5| [MemberFunction] int S::operator[](int, int)
|
||||
# 5| <params>:
|
||||
# 5| getParameter(0): [Parameter] i
|
||||
# 5| Type = [IntType] int
|
||||
# 5| getParameter(1): [Parameter] j
|
||||
# 5| Type = [IntType] int
|
||||
# 5| getEntryPoint(): [BlockStmt] { ... }
|
||||
# 6| getStmt(0): [ReturnStmt] return ...
|
||||
# 6| getExpr(): [ArrayExpr] access to array
|
||||
# 6| Type = [IntType] int
|
||||
# 6| ValueCategory = prvalue(load)
|
||||
# 6| getArrayBase(): [ArrayExpr] access to array
|
||||
# 6| Type = [ArrayType] int[2]
|
||||
# 6| ValueCategory = lvalue
|
||||
# 6| getArrayBase(): [ImplicitThisFieldAccess,PointerFieldAccess] xs
|
||||
# 6| Type = [ArrayType] int[2][2]
|
||||
# 6| ValueCategory = lvalue
|
||||
# 6| getQualifier(): [ThisExpr] this
|
||||
# 6| Type = [PointerType] S *
|
||||
# 6| ValueCategory = prvalue(load)
|
||||
# 6| getArrayOffset(): [VariableAccess] i
|
||||
# 6| Type = [IntType] int
|
||||
# 6| ValueCategory = prvalue(load)
|
||||
#-----| getArrayBase().getFullyConverted(): [ArrayToPointerConversion] array to pointer conversion
|
||||
#-----| Type = [PointerType] int(*)[2]
|
||||
#-----| ValueCategory = prvalue
|
||||
# 6| getArrayOffset(): [VariableAccess] j
|
||||
# 6| Type = [IntType] int
|
||||
# 6| ValueCategory = prvalue(load)
|
||||
# 6| getArrayBase().getFullyConverted(): [ArrayToPointerConversion] array to pointer conversion
|
||||
# 6| Type = [IntPointerType] int *
|
||||
# 6| ValueCategory = prvalue
|
||||
# 10| [TopLevelFunction] int foo(S)
|
||||
# 10| <params>:
|
||||
# 10| getParameter(0): [Parameter] s
|
||||
# 10| Type = [Struct] S
|
||||
# 10| getEntryPoint(): [BlockStmt] { ... }
|
||||
# 11| getStmt(0): [ReturnStmt] return ...
|
||||
# 11| getExpr(): [OverloadedArrayExpr] call to operator[]
|
||||
# 11| Type = [IntType] int
|
||||
# 11| ValueCategory = prvalue
|
||||
# 11| getArrayBase(): [VariableAccess] s
|
||||
# 11| Type = [Struct] S
|
||||
# 11| ValueCategory = lvalue
|
||||
# 11| getArrayOffset(0): [Literal] 1
|
||||
# 11| Type = [IntType] int
|
||||
# 11| Value = [Literal] 1
|
||||
# 11| ValueCategory = prvalue
|
||||
# 11| getArrayOffset(1): [Literal] 2
|
||||
# 11| Type = [IntType] int
|
||||
# 11| Value = [Literal] 2
|
||||
# 11| ValueCategory = prvalue
|
||||
@@ -0,0 +1 @@
|
||||
semmle/code/cpp/PrintAST.ql
|
||||
12
cpp/ql/test/library-tests/subscript_operator/test.cpp
Normal file
12
cpp/ql/test/library-tests/subscript_operator/test.cpp
Normal file
@@ -0,0 +1,12 @@
|
||||
// semmle-extractor-options: -std=c++23
|
||||
|
||||
struct S {
|
||||
int xs[2][2];
|
||||
int operator[](int i, int j) {
|
||||
return xs[i][j];
|
||||
}
|
||||
};
|
||||
|
||||
int foo(S s) {
|
||||
return s[1, 2];
|
||||
}
|
||||
Reference in New Issue
Block a user