Skip to content

Commit 9146b8e

Browse files
committed
C++: Add example of conditional destruction
The QL CFG and extractor CFG are the same, so the test passes. Neither of them model that `ref` may or may not be destructed.
1 parent 8ac826a commit 9146b8e

File tree

2 files changed

+62
-0
lines changed

2 files changed

+62
-0
lines changed

cpp/ql/test/library-tests/qlcfg/cfg.expected

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6084,6 +6084,48 @@
60846084
| caller | true | 21161 | 21159 | |
60856085
| caller | true | 21163 | 21116 | |
60866086
| caller | true | 21165 | 21126 | |
6087+
| cond_destruct::C::C | false | 4133 | 4133 | C |
6088+
| cond_destruct::C::C | false | 4173 | 4173 | C |
6089+
| cond_destruct::C::getInt | false | 4119 | 4119 | getInt |
6090+
| cond_destruct::C::operator= | false | 4167 | 4167 | operator= |
6091+
| cond_destruct::C::~C | false | 4163 | 4163 | ~C |
6092+
| cond_destruct::f | false | 4107 | 4107 | f |
6093+
| cond_destruct::f | false | 4115 | 4115 | declaration |
6094+
| cond_destruct::f | false | 4117 | 4117 | declaration |
6095+
| cond_destruct::f | false | 4122 | 4122 | call to getInt |
6096+
| cond_destruct::f | false | 4128 | 4128 | x |
6097+
| cond_destruct::f | false | 4130 | 4130 | (bool)... |
6098+
| cond_destruct::f | false | 4131 | 4131 | call to C |
6099+
| cond_destruct::f | false | 4134 | 4134 | (const C)... |
6100+
| cond_destruct::f | false | 4137 | 4137 | call to C |
6101+
| cond_destruct::f | false | 4139 | 4139 | initializer for local |
6102+
| cond_destruct::f | false | 4142 | 4142 | local |
6103+
| cond_destruct::f | false | 4144 | 4144 | (const C)... |
6104+
| cond_destruct::f | false | 4146 | 4146 | ... ? ... : ... |
6105+
| cond_destruct::f | false | 4148 | 4148 | (reference to) |
6106+
| cond_destruct::f | false | 4149 | 4149 | initializer for ref |
6107+
| cond_destruct::f | false | 4153 | 4153 | ref |
6108+
| cond_destruct::f | false | 4155 | 4155 | (reference dereference) |
6109+
| cond_destruct::f | false | 4156 | 4156 | return ... |
6110+
| cond_destruct::f | false | 4158 | 4158 | { ... } |
6111+
| cond_destruct::f | false | 4160 | 4160 | local |
6112+
| cond_destruct::f | false | 4162 | 4162 | call to local.~C |
6113+
| cond_destruct::f | true | 4115 | 4139 | |
6114+
| cond_destruct::f | true | 4117 | 4149 | |
6115+
| cond_destruct::f | true | 4122 | 4160 | |
6116+
| cond_destruct::f | true | 4128 | 4131 | T |
6117+
| cond_destruct::f | true | 4128 | 4142 | F |
6118+
| cond_destruct::f | true | 4131 | 4156 | |
6119+
| cond_destruct::f | true | 4137 | 4117 | |
6120+
| cond_destruct::f | true | 4139 | 4137 | |
6121+
| cond_destruct::f | true | 4142 | 4156 | |
6122+
| cond_destruct::f | true | 4146 | 4128 | |
6123+
| cond_destruct::f | true | 4149 | 4146 | |
6124+
| cond_destruct::f | true | 4153 | 4122 | |
6125+
| cond_destruct::f | true | 4156 | 4153 | |
6126+
| cond_destruct::f | true | 4158 | 4115 | |
6127+
| cond_destruct::f | true | 4160 | 4162 | |
6128+
| cond_destruct::f | true | 4162 | 4107 | |
60876129
| cpp_fun | false | 22196 | 22196 | cpp_fun |
60886130
| cpp_fun | false | 22201 | 22201 | declaration |
60896131
| cpp_fun | false | 22203 | 22203 | declaration |

cpp/ql/test/library-tests/qlcfg/destructors.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,3 +36,23 @@ void destructor_catch() {
3636
HasDtor d2 = { 0 };
3737
}
3838
}
39+
40+
namespace cond_destruct {
41+
struct C {
42+
C();
43+
C(const C&) = delete;
44+
~C();
45+
int getInt() const;
46+
void *data;
47+
};
48+
49+
int f(int x) {
50+
C local;
51+
const C &ref = x ? (const C&)C() : (const C&)local;
52+
return ref.getInt();
53+
// If `x` was true, `ref` refers to a temporary object whose lifetime was
54+
// extended to coincide with `ref`. Before the function returns, it
55+
// should destruct `ref` if and only if the first branch was taken in the
56+
// ?: expression.
57+
}
58+
}

0 commit comments

Comments
 (0)