Skip to content

Commit 863e6c8

Browse files
authored
Merge pull request #15427 from MathiasVP/asexpr-and-asindirectexpr-tests
C++: Add `asExpr` and `asIndirectExpr` library tests (and fix more duplication)
2 parents 2db76c7 + 7916616 commit 863e6c8

File tree

6 files changed

+110
-1
lines changed

6 files changed

+110
-1
lines changed

cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1484,12 +1484,17 @@ private module IndirectNodeToIndirectExpr<IndirectNodeToIndirectExprSig Sig> {
14841484
indirectNodeHasIndirectExpr(node, e, n, indirectionIndex) and
14851485
not exists(Expr conv, int adjustedIndirectionIndex |
14861486
adjustForReference(e, indirectionIndex, conv, adjustedIndirectionIndex) and
1487-
indirectNodeHasIndirectExpr(_, conv, n + 1, adjustedIndirectionIndex)
1487+
indirectExprNodeShouldBe(conv, n + 1, adjustedIndirectionIndex)
14881488
)
14891489
)
14901490
}
14911491
}
14921492

1493+
private predicate indirectExprNodeShouldBe(Expr e, int n, int indirectionIndex) {
1494+
indirectExprNodeShouldBeIndirectOperand(_, e, n, indirectionIndex) or
1495+
indirectExprNodeShouldBeIndirectInstruction(_, e, n, indirectionIndex)
1496+
}
1497+
14931498
private module IndirectOperandIndirectExprNodeImpl implements IndirectNodeToIndirectExprSig {
14941499
class IndirectNode = IndirectOperand;
14951500

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
testFailures
2+
failures
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import cpp
2+
import TestUtilities.InlineExpectationsTest
3+
import semmle.code.cpp.dataflow.new.DataFlow::DataFlow
4+
5+
bindingset[s]
6+
string quote(string s) { if s.matches("% %") then result = "\"" + s + "\"" else result = s }
7+
8+
string formatNumberOfNodesForIndirectExpr(Expr e) {
9+
exists(int n | n = strictcount(Node node | node.asIndirectExpr() = e) |
10+
n > 1 and result = ": " + n
11+
)
12+
}
13+
14+
module AsIndirectExprTest implements TestSig {
15+
string getARelevantTag() { result = ["asIndirectExpr", "numberOfIndirectNodes"] }
16+
17+
predicate hasActualResult(Location location, string element, string tag, string value) {
18+
exists(Node n, Expr e, string exprString |
19+
e = n.asIndirectExpr() and
20+
location = e.getLocation() and
21+
element = n.toString() and
22+
exprString = e.toString()
23+
|
24+
tag = "asIndirectExpr" and
25+
(
26+
// The toString on an indirect is often formatted like `***myExpr`.
27+
// If the node's `toString` is of that form then we don't show it in
28+
// the expected output.
29+
if element.matches("%" + exprString)
30+
then value = quote(exprString)
31+
else value = quote(exprString + "(" + element + ")")
32+
)
33+
or
34+
tag = "numberOfIndirectNodes" and
35+
value = quote(exprString + formatNumberOfNodesForIndirectExpr(e))
36+
)
37+
}
38+
}
39+
40+
import MakeTest<AsIndirectExprTest>
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
void take_const_ref_int(const int &);
2+
3+
void test_materialize_temp_int()
4+
{
5+
take_const_ref_int(42); // $ asExpr=42 numberOfNodes="42: 2" asIndirectExpr=42
6+
}
7+
8+
struct A {};
9+
10+
A get();
11+
void take_const_ref(const A &);
12+
13+
void test1(){
14+
take_const_ref(get()); // $ asExpr="call to get" numberOfNodes="call to get: 2" asIndirectExpr="call to get"
15+
}
16+
17+
void take_ref(A &);
18+
19+
A& get_ref();
20+
21+
void test2() {
22+
take_ref(get_ref()); // $ asExpr="call to get_ref" asIndirectExpr="call to get_ref"
23+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
testFailures
2+
failures
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import cpp
2+
import TestUtilities.InlineExpectationsTest
3+
import semmle.code.cpp.dataflow.new.DataFlow::DataFlow
4+
5+
bindingset[s]
6+
string quote(string s) { if s.matches("% %") then result = "\"" + s + "\"" else result = s }
7+
8+
string formatNumberOfNodesForExpr(Expr e) {
9+
exists(int n | n = strictcount(Node node | node.asExpr() = e) | n > 1 and result = ": " + n)
10+
}
11+
12+
module AsExprTest implements TestSig {
13+
string getARelevantTag() { result = ["asExpr", "numberOfNodes"] }
14+
15+
predicate hasActualResult(Location location, string element, string tag, string value) {
16+
exists(Node n, Expr e, string exprString |
17+
e = n.asExpr() and
18+
location = e.getLocation() and
19+
element = n.toString() and
20+
exprString = e.toString()
21+
|
22+
tag = "asExpr" and
23+
(
24+
// If the `toString` on the node is identical to the `toString` of the
25+
// expression then we don't show it in the expected output.
26+
if exprString = element
27+
then value = quote(exprString)
28+
else value = quote(exprString + "(" + element + ")")
29+
)
30+
or
31+
tag = "numberOfNodes" and
32+
value = quote(exprString + formatNumberOfNodesForExpr(e))
33+
)
34+
}
35+
}
36+
37+
import MakeTest<AsExprTest>

0 commit comments

Comments
 (0)