Skip to content

Commit 97fd7b4

Browse files
C++: Add tests for filtering bad ASTs
1 parent 7db36b2 commit 97fd7b4

File tree

6 files changed

+303
-0
lines changed

6 files changed

+303
-0
lines changed

cpp/ql/test/library-tests/ir/ir/PrintAST.expected

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,142 @@
3434
#-----| Type = unsigned long
3535
#-----| 1: p#1
3636
#-----| Type = align_val_t
37+
bad_asts.cpp:
38+
# 5| Bad::S::operator=(S &&) -> S &
39+
# 5| params:
40+
#-----| 0: p#0
41+
#-----| Type = S &&
42+
# 5| Bad::S::operator=(const S &) -> S &
43+
# 5| params:
44+
#-----| 0: p#0
45+
#-----| Type = const S &
46+
# 9| Bad::S::MemberFunction(int) -> int
47+
# 9| params:
48+
# 9| 0: y
49+
# 9| Type = int
50+
# 9| body: { ... }
51+
# 10| 0: return ...
52+
# 10| 0: ... + ...
53+
# 10| Type = int
54+
# 10| ValueCategory = prvalue
55+
# 10| 0: ... + ...
56+
# 10| Type = int
57+
# 10| ValueCategory = prvalue
58+
# 10| 0: Unknown literal
59+
# 10| Type = int
60+
# 10| ValueCategory = prvalue
61+
# 10| 1: x
62+
# 10| Type = int
63+
# 10| ValueCategory = prvalue(load)
64+
#-----| -1: this
65+
#-----| Type = S *
66+
#-----| ValueCategory = prvalue(load)
67+
# 10| 1: y
68+
# 10| Type = int
69+
# 10| ValueCategory = prvalue(load)
70+
# 9| MemberFunction(int) -> int
71+
# 9| params:
72+
# 9| 0: y
73+
# 9| Type = int
74+
# 9| body: { ... }
75+
# 10| 0: return ...
76+
# 10| 0: ... + ...
77+
# 10| Type = int
78+
# 10| ValueCategory = prvalue
79+
# 10| 0: ... + ...
80+
# 10| Type = int
81+
# 10| ValueCategory = prvalue
82+
# 10| 0: 6
83+
# 10| Type = int
84+
# 10| Value = 6
85+
# 10| ValueCategory = prvalue
86+
# 10| 1: x
87+
# 10| Type = int
88+
# 10| ValueCategory = prvalue(load)
89+
#-----| -1: this
90+
#-----| Type = S *
91+
#-----| ValueCategory = prvalue(load)
92+
# 10| 1: y
93+
# 10| Type = int
94+
# 10| ValueCategory = prvalue(load)
95+
# 14| Bad::CallBadMemberFunction() -> void
96+
# 14| params:
97+
# 14| body: { ... }
98+
# 15| 0: declaration
99+
# 15| 0: definition of s
100+
# 15| Type = S
101+
# 15| init: initializer for s
102+
# 15| expr: {...}
103+
# 15| Type = S
104+
# 15| ValueCategory = prvalue
105+
# 16| 1: ExprStmt
106+
# 16| 0: call to MemberFunction
107+
# 16| Type = int
108+
# 16| ValueCategory = prvalue
109+
# 16| -1: s
110+
# 16| Type = S
111+
# 16| ValueCategory = lvalue
112+
# 16| 0: 1
113+
# 16| Type = int
114+
# 16| Value = 1
115+
# 16| ValueCategory = prvalue
116+
# 17| 2: return ...
117+
# 19| Bad::Point::Point(Point &&) -> void
118+
# 19| params:
119+
#-----| 0: p#0
120+
#-----| Type = Point &&
121+
# 19| Bad::Point::Point(const Point &) -> void
122+
# 19| params:
123+
#-----| 0: p#0
124+
#-----| Type = const Point &
125+
# 19| initializations:
126+
# 19| 0: constructor init of field x
127+
# 19| Type = int
128+
# 19| ValueCategory = prvalue
129+
# 19| 0: Unknown literal
130+
# 19| Type = int
131+
# 19| ValueCategory = prvalue
132+
# 19| 1: constructor init of field y
133+
# 19| Type = int
134+
# 19| ValueCategory = prvalue
135+
# 19| 0: Unknown literal
136+
# 19| Type = int
137+
# 19| ValueCategory = prvalue
138+
# 19| body: { ... }
139+
# 19| 0: return ...
140+
# 19| Bad::Point::operator=(Point &&) -> Point &
141+
# 19| params:
142+
#-----| 0: p#0
143+
#-----| Type = Point &&
144+
# 19| Bad::Point::operator=(const Point &) -> Point &
145+
# 19| params:
146+
#-----| 0: p#0
147+
#-----| Type = const Point &
148+
# 22| Bad::Point::Point() -> void
149+
# 22| params:
150+
# 22| initializations:
151+
# 22| body: { ... }
152+
# 23| 0: return ...
153+
# 26| Bad::CallCopyConstructor(const Point &) -> void
154+
# 26| params:
155+
# 26| 0: a
156+
# 26| Type = const Point &
157+
# 26| body: { ... }
158+
# 27| 0: declaration
159+
# 27| 0: definition of b
160+
# 27| Type = Point
161+
# 27| init: initializer for b
162+
# 27| expr: (Point)...
163+
# 27| Conversion = glvalue conversion
164+
# 27| Type = Point
165+
# 27| ValueCategory = prvalue(load)
166+
# 27| expr: (reference dereference)
167+
# 27| Type = const Point
168+
# 27| ValueCategory = lvalue
169+
# 27| expr: a
170+
# 27| Type = const Point &
171+
# 27| ValueCategory = prvalue(load)
172+
# 28| 1: return ...
37173
ir.cpp:
38174
# 1| Constants() -> void
39175
# 1| params:

cpp/ql/test/library-tests/ir/ir/aliased_ssa_ir.expected

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,48 @@
1+
bad_asts.cpp:
2+
# 14| Bad::CallBadMemberFunction() -> void
3+
# 14| Block 0
4+
# 14| v0_0(void) = EnterFunction :
5+
# 14| mu0_1(unknown) = UnmodeledDefinition :
6+
# 15| r0_2(glval<S>) = VariableAddress[s] :
7+
# 15| r0_3(glval<int>) = FieldAddress[x] : r0_2
8+
# 15| r0_4(int) = Constant[0] :
9+
# 15| mu0_5(int) = Store : r0_3, r0_4
10+
# 16| r0_6(glval<S>) = VariableAddress[s] :
11+
# 16| r0_7(glval<unknown>) = FunctionAddress[MemberFunction] :
12+
# 16| r0_8(int) = Constant[1] :
13+
# 16| r0_9(int) = Call : r0_7, this:r0_6, r0_8
14+
# 17| v0_10(void) = NoOp :
15+
# 14| v0_11(void) = ReturnVoid :
16+
# 14| v0_12(void) = UnmodeledUse : mu*
17+
# 14| v0_13(void) = ExitFunction :
18+
19+
# 22| Bad::Point::Point() -> void
20+
# 22| Block 0
21+
# 22| v0_0(void) = EnterFunction :
22+
# 22| mu0_1(unknown) = UnmodeledDefinition :
23+
# 22| r0_2(glval<Point>) = InitializeThis :
24+
# 23| v0_3(void) = NoOp :
25+
# 22| v0_4(void) = ReturnVoid :
26+
# 22| v0_5(void) = UnmodeledUse : mu*
27+
# 22| v0_6(void) = ExitFunction :
28+
29+
# 26| Bad::CallCopyConstructor(const Point &) -> void
30+
# 26| Block 0
31+
# 26| v0_0(void) = EnterFunction :
32+
# 26| mu0_1(unknown) = UnmodeledDefinition :
33+
# 26| r0_2(glval<Point &>) = VariableAddress[a] :
34+
# 26| m0_3(Point &) = InitializeParameter[a] : r0_2
35+
# 27| r0_4(glval<Point>) = VariableAddress[b] :
36+
# 27| r0_5(glval<Point &>) = VariableAddress[a] :
37+
# 27| r0_6(Point &) = Load : r0_5, m0_3
38+
# 27| r0_7(glval<Point>) = Convert : r0_6
39+
# 27| r0_8(Point) = Load : r0_7, mu0_1
40+
# 27| m0_9(Point) = Store : r0_4, r0_8
41+
# 28| v0_10(void) = NoOp :
42+
# 26| v0_11(void) = ReturnVoid :
43+
# 26| v0_12(void) = UnmodeledUse : mu*
44+
# 26| v0_13(void) = ExitFunction :
45+
146
ir.cpp:
247
# 1| Constants() -> void
348
# 1| Block 0
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// semmle-extractor-options: -std=c++17
2+
3+
// Test cases that illustrate known bad ASTs that we have to work around in IR generation.
4+
namespace Bad {
5+
struct S {
6+
int x;
7+
8+
template<int t>
9+
int MemberFunction(int y) {
10+
return t + x + y;
11+
}
12+
};
13+
14+
void CallBadMemberFunction() {
15+
S s = {};
16+
s.MemberFunction<6>(1); // Not marked as member function in AST.
17+
}
18+
19+
struct Point {
20+
int x;
21+
int y;
22+
Point() {
23+
}
24+
};
25+
26+
void CallCopyConstructor(const Point& a) {
27+
Point b = a; // Copy constructor contains literal expressions with no values.
28+
}
29+
}

cpp/ql/test/library-tests/ir/ir/raw_ir.expected

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,48 @@
1+
bad_asts.cpp:
2+
# 14| Bad::CallBadMemberFunction() -> void
3+
# 14| Block 0
4+
# 14| v0_0(void) = EnterFunction :
5+
# 14| mu0_1(unknown) = UnmodeledDefinition :
6+
# 15| r0_2(glval<S>) = VariableAddress[s] :
7+
# 15| r0_3(glval<int>) = FieldAddress[x] : r0_2
8+
# 15| r0_4(int) = Constant[0] :
9+
# 15| mu0_5(int) = Store : r0_3, r0_4
10+
# 16| r0_6(glval<S>) = VariableAddress[s] :
11+
# 16| r0_7(glval<unknown>) = FunctionAddress[MemberFunction] :
12+
# 16| r0_8(int) = Constant[1] :
13+
# 16| r0_9(int) = Call : r0_7, this:r0_6, r0_8
14+
# 17| v0_10(void) = NoOp :
15+
# 14| v0_11(void) = ReturnVoid :
16+
# 14| v0_12(void) = UnmodeledUse : mu*
17+
# 14| v0_13(void) = ExitFunction :
18+
19+
# 22| Bad::Point::Point() -> void
20+
# 22| Block 0
21+
# 22| v0_0(void) = EnterFunction :
22+
# 22| mu0_1(unknown) = UnmodeledDefinition :
23+
# 22| r0_2(glval<Point>) = InitializeThis :
24+
# 23| v0_3(void) = NoOp :
25+
# 22| v0_4(void) = ReturnVoid :
26+
# 22| v0_5(void) = UnmodeledUse : mu*
27+
# 22| v0_6(void) = ExitFunction :
28+
29+
# 26| Bad::CallCopyConstructor(const Point &) -> void
30+
# 26| Block 0
31+
# 26| v0_0(void) = EnterFunction :
32+
# 26| mu0_1(unknown) = UnmodeledDefinition :
33+
# 26| r0_2(glval<Point &>) = VariableAddress[a] :
34+
# 26| mu0_3(Point &) = InitializeParameter[a] : r0_2
35+
# 27| r0_4(glval<Point>) = VariableAddress[b] :
36+
# 27| r0_5(glval<Point &>) = VariableAddress[a] :
37+
# 27| r0_6(Point &) = Load : r0_5, mu0_1
38+
# 27| r0_7(glval<Point>) = Convert : r0_6
39+
# 27| r0_8(Point) = Load : r0_7, mu0_1
40+
# 27| mu0_9(Point) = Store : r0_4, r0_8
41+
# 28| v0_10(void) = NoOp :
42+
# 26| v0_11(void) = ReturnVoid :
43+
# 26| v0_12(void) = UnmodeledUse : mu*
44+
# 26| v0_13(void) = ExitFunction :
45+
146
ir.cpp:
247
# 1| Constants() -> void
348
# 1| Block 0

cpp/ql/test/library-tests/ir/ir/ssa_block_count.expected

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
| IR: C | 1 |
99
| IR: Call | 1 |
1010
| IR: CallAdd | 1 |
11+
| IR: CallBadMemberFunction | 1 |
12+
| IR: CallCopyConstructor | 1 |
1113
| IR: CallMethods | 1 |
1214
| IR: CallMin | 1 |
1315
| IR: CallNestedTemplateFunc | 1 |
@@ -73,6 +75,7 @@
7375
| IR: OperatorNew | 1 |
7476
| IR: OperatorNewArray | 1 |
7577
| IR: Parameters | 1 |
78+
| IR: Point | 1 |
7679
| IR: PointerCompare | 1 |
7780
| IR: PointerCrement | 1 |
7881
| IR: PointerOps | 1 |

cpp/ql/test/library-tests/ir/ir/unaliased_ssa_ir.expected

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,48 @@
1+
bad_asts.cpp:
2+
# 14| Bad::CallBadMemberFunction() -> void
3+
# 14| Block 0
4+
# 14| v0_0(void) = EnterFunction :
5+
# 14| mu0_1(unknown) = UnmodeledDefinition :
6+
# 15| r0_2(glval<S>) = VariableAddress[s] :
7+
# 15| r0_3(glval<int>) = FieldAddress[x] : r0_2
8+
# 15| r0_4(int) = Constant[0] :
9+
# 15| mu0_5(int) = Store : r0_3, r0_4
10+
# 16| r0_6(glval<S>) = VariableAddress[s] :
11+
# 16| r0_7(glval<unknown>) = FunctionAddress[MemberFunction] :
12+
# 16| r0_8(int) = Constant[1] :
13+
# 16| r0_9(int) = Call : r0_7, this:r0_6, r0_8
14+
# 17| v0_10(void) = NoOp :
15+
# 14| v0_11(void) = ReturnVoid :
16+
# 14| v0_12(void) = UnmodeledUse : mu*
17+
# 14| v0_13(void) = ExitFunction :
18+
19+
# 22| Bad::Point::Point() -> void
20+
# 22| Block 0
21+
# 22| v0_0(void) = EnterFunction :
22+
# 22| mu0_1(unknown) = UnmodeledDefinition :
23+
# 22| r0_2(glval<Point>) = InitializeThis :
24+
# 23| v0_3(void) = NoOp :
25+
# 22| v0_4(void) = ReturnVoid :
26+
# 22| v0_5(void) = UnmodeledUse : mu*
27+
# 22| v0_6(void) = ExitFunction :
28+
29+
# 26| Bad::CallCopyConstructor(const Point &) -> void
30+
# 26| Block 0
31+
# 26| v0_0(void) = EnterFunction :
32+
# 26| mu0_1(unknown) = UnmodeledDefinition :
33+
# 26| r0_2(glval<Point &>) = VariableAddress[a] :
34+
# 26| m0_3(Point &) = InitializeParameter[a] : r0_2
35+
# 27| r0_4(glval<Point>) = VariableAddress[b] :
36+
# 27| r0_5(glval<Point &>) = VariableAddress[a] :
37+
# 27| r0_6(Point &) = Load : r0_5, m0_3
38+
# 27| r0_7(glval<Point>) = Convert : r0_6
39+
# 27| r0_8(Point) = Load : r0_7, mu0_1
40+
# 27| m0_9(Point) = Store : r0_4, r0_8
41+
# 28| v0_10(void) = NoOp :
42+
# 26| v0_11(void) = ReturnVoid :
43+
# 26| v0_12(void) = UnmodeledUse : mu*
44+
# 26| v0_13(void) = ExitFunction :
45+
146
ir.cpp:
247
# 1| Constants() -> void
348
# 1| Block 0

0 commit comments

Comments
 (0)