Skip to content

Commit febd060

Browse files
committed
C++: Add testcase where two destructor calls are remapped to a temporary object expression.
1 parent d40fa4c commit febd060

File tree

5 files changed

+175
-0
lines changed

5 files changed

+175
-0
lines changed

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

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2326,6 +2326,47 @@ destructors_for_temps.cpp:
23262326
# 83| Type = [Class] ClassWithDestructor2
23272327
# 83| ValueCategory = xvalue
23282328
# 85| getStmt(1): [ReturnStmt] return ...
2329+
# 87| [CopyAssignmentOperator] ClassWithDestructor3& ClassWithDestructor3::operator=(ClassWithDestructor3 const&)
2330+
# 87| <params>:
2331+
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
2332+
#-----| Type = [LValueReferenceType] const ClassWithDestructor3 &
2333+
# 87| [Constructor] void ClassWithDestructor3::ClassWithDestructor3()
2334+
# 87| <params>:
2335+
# 88| [Destructor] void ClassWithDestructor3::~ClassWithDestructor3()
2336+
# 88| <params>:
2337+
# 89| [MemberFunction] ClassWithDestructor2 ClassWithDestructor3::getClassWithDestructor2()
2338+
# 89| <params>:
2339+
# 92| [TopLevelFunction] ClassWithDestructor3 makeClassWithDestructor3()
2340+
# 92| <params>:
2341+
# 94| [TopLevelFunction] void temp_test11()
2342+
# 94| <params>:
2343+
# 94| getEntryPoint(): [BlockStmt] { ... }
2344+
# 99| getStmt(0): [ExprStmt] ExprStmt
2345+
# 99| getExpr(): [FunctionCall] call to getClassWithDestructor2
2346+
# 99| Type = [Class] ClassWithDestructor2
2347+
# 99| ValueCategory = prvalue
2348+
# 99| getQualifier(): [FunctionCall] call to makeClassWithDestructor3
2349+
# 99| Type = [Struct] ClassWithDestructor3
2350+
# 99| ValueCategory = prvalue
2351+
# 99| getQualifier().getFullyConverted(): [TemporaryObjectExpr] temporary object
2352+
# 99| Type = [Struct] ClassWithDestructor3
2353+
# 99| ValueCategory = prvalue(load)
2354+
# 99| getExpr().getFullyConverted(): [TemporaryObjectExpr] temporary object
2355+
# 99| Type = [Class] ClassWithDestructor2
2356+
# 99| ValueCategory = prvalue
2357+
# 99| getImplicitDestructorCall(0): [DestructorCall] call to ~ClassWithDestructor2
2358+
# 99| Type = [VoidType] void
2359+
# 99| ValueCategory = prvalue
2360+
# 99| getQualifier(): [ReuseExpr] reuse of temporary object
2361+
# 99| Type = [Class] ClassWithDestructor2
2362+
# 99| ValueCategory = xvalue
2363+
# 99| getImplicitDestructorCall(1): [DestructorCall] call to ~ClassWithDestructor3
2364+
# 99| Type = [VoidType] void
2365+
# 99| ValueCategory = prvalue
2366+
# 99| getQualifier(): [ReuseExpr] reuse of temporary object
2367+
# 99| Type = [Struct] ClassWithDestructor3
2368+
# 99| ValueCategory = xvalue
2369+
# 100| getStmt(1): [ReturnStmt] return ...
23292370
ir.c:
23302371
# 5| [TopLevelFunction] int getX(MyCoords*)
23312372
# 5| <params>:

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

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1502,6 +1502,48 @@ destructors_for_temps.cpp:
15021502
# 81| v81_8(void) = AliasedUse : ~m82_1
15031503
# 81| v81_9(void) = ExitFunction :
15041504

1505+
# 94| void temp_test11()
1506+
# 94| Block 0
1507+
# 94| v94_1(void) = EnterFunction :
1508+
# 94| m94_2(unknown) = AliasedDefinition :
1509+
# 94| m94_3(unknown) = InitializeNonLocal :
1510+
# 94| m94_4(unknown) = Chi : total:m94_2, partial:m94_3
1511+
# 99| r99_1(glval<ClassWithDestructor2>) = VariableAddress[#temp99:5] :
1512+
# 99| r99_2(glval<ClassWithDestructor3>) = VariableAddress[#temp99:5] :
1513+
# 99| r99_3(glval<unknown>) = FunctionAddress[makeClassWithDestructor3] :
1514+
# 99| r99_4(ClassWithDestructor3) = Call[makeClassWithDestructor3] : func:r99_3
1515+
# 99| m99_5(unknown) = ^CallSideEffect : ~m94_4
1516+
# 99| m99_6(unknown) = Chi : total:m94_4, partial:m99_5
1517+
# 99| m99_7(ClassWithDestructor3) = Store[#temp99:5] : &:r99_2, r99_4
1518+
# 99| r99_8(glval<unknown>) = FunctionAddress[getClassWithDestructor2] :
1519+
# 99| r99_9(ClassWithDestructor2) = Call[getClassWithDestructor2] : func:r99_8, this:r99_2
1520+
# 99| m99_10(unknown) = ^CallSideEffect : ~m99_6
1521+
# 99| m99_11(unknown) = Chi : total:m99_6, partial:m99_10
1522+
# 99| v99_12(void) = ^IndirectReadSideEffect[-1] : &:r99_2, m99_7
1523+
# 99| m99_13(ClassWithDestructor3) = ^IndirectMayWriteSideEffect[-1] : &:r99_2
1524+
# 99| m99_14(ClassWithDestructor3) = Chi : total:m99_7, partial:m99_13
1525+
# 99| m99_15(ClassWithDestructor2) = Store[#temp99:5] : &:r99_1, r99_9
1526+
# 99| r99_16(glval<ClassWithDestructor2>) = CopyValue : r99_1
1527+
# 99| r99_17(glval<unknown>) = FunctionAddress[~ClassWithDestructor2] :
1528+
# 99| v99_18(void) = Call[~ClassWithDestructor2] : func:r99_17, this:r99_16
1529+
# 99| m99_19(unknown) = ^CallSideEffect : ~m99_11
1530+
# 99| m99_20(unknown) = Chi : total:m99_11, partial:m99_19
1531+
# 99| v99_21(void) = ^IndirectReadSideEffect[-1] : &:r99_16, m99_15
1532+
# 99| m99_22(ClassWithDestructor2) = ^IndirectMayWriteSideEffect[-1] : &:r99_16
1533+
# 99| m99_23(ClassWithDestructor2) = Chi : total:m99_15, partial:m99_22
1534+
# 99| r99_24(glval<ClassWithDestructor3>) = CopyValue : r99_2
1535+
# 99| r99_25(glval<unknown>) = FunctionAddress[~ClassWithDestructor3] :
1536+
# 99| v99_26(void) = Call[~ClassWithDestructor3] : func:r99_25, this:r99_24
1537+
# 99| m99_27(unknown) = ^CallSideEffect : ~m99_20
1538+
# 99| m99_28(unknown) = Chi : total:m99_20, partial:m99_27
1539+
# 99| v99_29(void) = ^IndirectReadSideEffect[-1] : &:r99_24, m99_14
1540+
# 99| m99_30(ClassWithDestructor3) = ^IndirectMayWriteSideEffect[-1] : &:r99_24
1541+
# 99| m99_31(ClassWithDestructor3) = Chi : total:m99_14, partial:m99_30
1542+
# 100| v100_1(void) = NoOp :
1543+
# 94| v94_5(void) = ReturnVoid :
1544+
# 94| v94_6(void) = AliasedUse : ~m99_28
1545+
# 94| v94_7(void) = ExitFunction :
1546+
15051547
ir.c:
15061548
# 7| void MyCoordsTest(int)
15071549
# 7| Block 0

cpp/ql/test/library-tests/ir/ir/destructors_for_temps.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,4 +82,19 @@ void temp_test10(int i) {
8282
while(i < 10) {
8383
make();
8484
}
85+
}
86+
87+
struct ClassWithDestructor3 {
88+
~ClassWithDestructor3();
89+
ClassWithDestructor2 getClassWithDestructor2();
90+
};
91+
92+
ClassWithDestructor3 makeClassWithDestructor3();
93+
94+
void temp_test11() {
95+
// Two destructors are called at the semicolon (i.e., they're both attached
96+
// to the call to `getClassWithDestructor2()`):
97+
// First, ~ClassWithDestructor2::ClassWithDestructor2(), and then the call
98+
// to `~ClassWithDestructor3::ClassWithDestructor3()`.
99+
makeClassWithDestructor3().getClassWithDestructor2();
85100
}

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

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1332,6 +1332,49 @@
13321332
| destructors_for_temps.cpp:83:9:83:14 | SideEffect | m83_6 |
13331333
| destructors_for_temps.cpp:83:9:83:14 | SideEffect | ~m83_5 |
13341334
| destructors_for_temps.cpp:83:9:83:14 | Unary | r83_1 |
1335+
| destructors_for_temps.cpp:94:6:94:16 | ChiPartial | partial:m94_3 |
1336+
| destructors_for_temps.cpp:94:6:94:16 | ChiTotal | total:m94_2 |
1337+
| destructors_for_temps.cpp:94:6:94:16 | SideEffect | ~m99_28 |
1338+
| destructors_for_temps.cpp:99:5:99:28 | CallTarget | func:r99_3 |
1339+
| destructors_for_temps.cpp:99:5:99:28 | ChiPartial | partial:m99_5 |
1340+
| destructors_for_temps.cpp:99:5:99:28 | ChiTotal | total:m94_4 |
1341+
| destructors_for_temps.cpp:99:5:99:28 | SideEffect | ~m94_4 |
1342+
| destructors_for_temps.cpp:99:5:99:28 | StoreValue | r99_4 |
1343+
| destructors_for_temps.cpp:99:5:99:30 | Address | &:r99_2 |
1344+
| destructors_for_temps.cpp:99:5:99:30 | Address | &:r99_2 |
1345+
| destructors_for_temps.cpp:99:5:99:30 | Address | &:r99_2 |
1346+
| destructors_for_temps.cpp:99:5:99:30 | Address | &:r99_24 |
1347+
| destructors_for_temps.cpp:99:5:99:30 | Address | &:r99_24 |
1348+
| destructors_for_temps.cpp:99:5:99:30 | Arg(this) | this:r99_2 |
1349+
| destructors_for_temps.cpp:99:5:99:30 | Arg(this) | this:r99_24 |
1350+
| destructors_for_temps.cpp:99:5:99:30 | CallTarget | func:r99_25 |
1351+
| destructors_for_temps.cpp:99:5:99:30 | ChiPartial | partial:m99_13 |
1352+
| destructors_for_temps.cpp:99:5:99:30 | ChiPartial | partial:m99_27 |
1353+
| destructors_for_temps.cpp:99:5:99:30 | ChiPartial | partial:m99_30 |
1354+
| destructors_for_temps.cpp:99:5:99:30 | ChiTotal | total:m99_7 |
1355+
| destructors_for_temps.cpp:99:5:99:30 | ChiTotal | total:m99_14 |
1356+
| destructors_for_temps.cpp:99:5:99:30 | ChiTotal | total:m99_20 |
1357+
| destructors_for_temps.cpp:99:5:99:30 | SideEffect | m99_7 |
1358+
| destructors_for_temps.cpp:99:5:99:30 | SideEffect | m99_14 |
1359+
| destructors_for_temps.cpp:99:5:99:30 | SideEffect | ~m99_20 |
1360+
| destructors_for_temps.cpp:99:5:99:30 | Unary | r99_2 |
1361+
| destructors_for_temps.cpp:99:5:99:56 | Address | &:r99_1 |
1362+
| destructors_for_temps.cpp:99:5:99:56 | Address | &:r99_16 |
1363+
| destructors_for_temps.cpp:99:5:99:56 | Address | &:r99_16 |
1364+
| destructors_for_temps.cpp:99:5:99:56 | Arg(this) | this:r99_16 |
1365+
| destructors_for_temps.cpp:99:5:99:56 | CallTarget | func:r99_17 |
1366+
| destructors_for_temps.cpp:99:5:99:56 | ChiPartial | partial:m99_19 |
1367+
| destructors_for_temps.cpp:99:5:99:56 | ChiPartial | partial:m99_22 |
1368+
| destructors_for_temps.cpp:99:5:99:56 | ChiTotal | total:m99_11 |
1369+
| destructors_for_temps.cpp:99:5:99:56 | ChiTotal | total:m99_15 |
1370+
| destructors_for_temps.cpp:99:5:99:56 | SideEffect | m99_15 |
1371+
| destructors_for_temps.cpp:99:5:99:56 | SideEffect | ~m99_11 |
1372+
| destructors_for_temps.cpp:99:5:99:56 | Unary | r99_1 |
1373+
| destructors_for_temps.cpp:99:32:99:54 | CallTarget | func:r99_8 |
1374+
| destructors_for_temps.cpp:99:32:99:54 | ChiPartial | partial:m99_10 |
1375+
| destructors_for_temps.cpp:99:32:99:54 | ChiTotal | total:m99_6 |
1376+
| destructors_for_temps.cpp:99:32:99:54 | SideEffect | ~m99_6 |
1377+
| destructors_for_temps.cpp:99:32:99:54 | StoreValue | r99_9 |
13351378
| file://:0:0:0:0 | Address | &:r0_1 |
13361379
| file://:0:0:0:0 | Address | &:r0_1 |
13371380
| file://:0:0:0:0 | Address | &:r0_1 |

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

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1365,6 +1365,40 @@ destructors_for_temps.cpp:
13651365
# 81| v81_7(void) = AliasedUse : ~m?
13661366
# 81| v81_8(void) = ExitFunction :
13671367

1368+
# 94| void temp_test11()
1369+
# 94| Block 0
1370+
# 94| v94_1(void) = EnterFunction :
1371+
# 94| mu94_2(unknown) = AliasedDefinition :
1372+
# 94| mu94_3(unknown) = InitializeNonLocal :
1373+
# 99| r99_1(glval<ClassWithDestructor2>) = VariableAddress[#temp99:5] :
1374+
# 99| r99_2(glval<ClassWithDestructor3>) = VariableAddress[#temp99:5] :
1375+
# 99| r99_3(glval<unknown>) = FunctionAddress[makeClassWithDestructor3] :
1376+
# 99| r99_4(ClassWithDestructor3) = Call[makeClassWithDestructor3] : func:r99_3
1377+
# 99| mu99_5(unknown) = ^CallSideEffect : ~m?
1378+
# 99| mu99_6(ClassWithDestructor3) = Store[#temp99:5] : &:r99_2, r99_4
1379+
# 99| r99_7(glval<unknown>) = FunctionAddress[getClassWithDestructor2] :
1380+
# 99| r99_8(ClassWithDestructor2) = Call[getClassWithDestructor2] : func:r99_7, this:r99_2
1381+
# 99| mu99_9(unknown) = ^CallSideEffect : ~m?
1382+
# 99| v99_10(void) = ^IndirectReadSideEffect[-1] : &:r99_2, ~m?
1383+
# 99| mu99_11(ClassWithDestructor3) = ^IndirectMayWriteSideEffect[-1] : &:r99_2
1384+
# 99| mu99_12(ClassWithDestructor2) = Store[#temp99:5] : &:r99_1, r99_8
1385+
# 99| r99_13(glval<ClassWithDestructor2>) = CopyValue : r99_1
1386+
# 99| r99_14(glval<unknown>) = FunctionAddress[~ClassWithDestructor2] :
1387+
# 99| v99_15(void) = Call[~ClassWithDestructor2] : func:r99_14, this:r99_13
1388+
# 99| mu99_16(unknown) = ^CallSideEffect : ~m?
1389+
# 99| v99_17(void) = ^IndirectReadSideEffect[-1] : &:r99_13, ~m?
1390+
# 99| mu99_18(ClassWithDestructor2) = ^IndirectMayWriteSideEffect[-1] : &:r99_13
1391+
# 99| r99_19(glval<ClassWithDestructor3>) = CopyValue : r99_2
1392+
# 99| r99_20(glval<unknown>) = FunctionAddress[~ClassWithDestructor3] :
1393+
# 99| v99_21(void) = Call[~ClassWithDestructor3] : func:r99_20, this:r99_19
1394+
# 99| mu99_22(unknown) = ^CallSideEffect : ~m?
1395+
# 99| v99_23(void) = ^IndirectReadSideEffect[-1] : &:r99_19, ~m?
1396+
# 99| mu99_24(ClassWithDestructor3) = ^IndirectMayWriteSideEffect[-1] : &:r99_19
1397+
# 100| v100_1(void) = NoOp :
1398+
# 94| v94_4(void) = ReturnVoid :
1399+
# 94| v94_5(void) = AliasedUse : ~m?
1400+
# 94| v94_6(void) = ExitFunction :
1401+
13681402
ir.c:
13691403
# 7| void MyCoordsTest(int)
13701404
# 7| Block 0

0 commit comments

Comments
 (0)