Hi @NoQ!
Thanks for the feedback.
As you suggested I created a snippet, where I actually use a bound variable.
int main()
{
int arr[2];
auto [a,b] = arr;
int i = a;
return 0;
}
In the AST a
is referenced.
|-DeclStmt <line:8:5, col:14>
| `-VarDecl <col:5, col:13> col:9 i 'int' cinit
| `-ImplicitCastExpr <col:13> 'int' <LValueToRValue>
| `-DeclRefExpr <col:13> 'int' lvalue Binding 0x56452d8d0a10 'a' 'int'
After checking on the snippet it turnes out that ExprEngine::VisitCommonDeclRefExpr
is called (in my proposal I falsely stated it isn’t).
Inside the function the state object looks like this:
...
"store": { "pointer": "0x555563d1d488", "items": [
{ "cluster": "NonParamVarRegion{D646}", "pointer": "0x555563d1d3d0", "items": [
{ "kind": "Default", "offset": 0, "value": "Unknown" }
]}
]},
...
It seems like the temporary array is in the store (?). I checked what happens if I use b
in the program later, but the store looks the same. If neither a
nor b
is referenced, the store is empty, like arr
itself is not stored at all.
Let’s assume a ponter to the first element of the temporary array is put in the store, as an array can be identified by a pointer to it’s first element, thus arr == &arr[0] == arr + 0
. The problem here is that later we want to read the value of a
and we don’t know the index.
So based on this I deny that the field name and the store binding is enough to get the value. An index should be associated with the field name.
In the following snippet
...
std::tuple<float, char, int> tpl(x, y, z);
auto [a, b, c] = tpl;
float i = a;
...
the use site looks like a regular assignment referencing the tuple element.
|-DeclStmt <line:12:5, col:16>
| `-VarDecl <col:5, col:15> col:11 i 'float' cinit
| `-ImplicitCastExpr <col:15> 'std::tuple_element<0, std::tuple<float, char, int>>::type':'float' <LValueToRValue>
| `-DeclRefExpr <col:15> 'std::tuple_element<0, std::tuple<float, char, int>>::type':'float' lvalue Binding 0x55906f9e0120 'a' 'std::tuple_element<0, std::tuple<float, char, int>>::type':'float'
In the program state it seems the tuple is stored and the name of the tuple is mapped to the representation:
"program_state": {
{ "cluster": "NonParamVarRegion{D418913}", "pointer": "0x555564269930", "items": [
{ "kind": "Default", "offset": 0, "value": "lazyCompoundVal{0x555564267f08,tpl}" }
]}
]},
"environment": { "pointer": "0x555563cfe590", "items": [
{ "lctx_id": 1, "location_context": "#0 Call", "calling": "main", "location": null, "items": [
{ "stmt_id": 432130, "pretty": "tpl", "value": "lazyCompoundVal{0x555564267f08,tpl}" }
]}
]},
Opposed to arrays, knowing about tpl
and the field name makes it possible to read the specific value, as the AST contains the index of the element, which is 0 in this case.
I’d also like to have a question regarding how should I translate this cluster.
"cluster": "NonParamVarRegion{D418913}", "pointer": "0x555564269930", "items": [
{ "kind": "Default", "offset": 0, "value": "lazyCompoundVal{0x555564267f08,tpl}" }
]}
At first glance I assume, the cluster is just a location in memory, where the data is stored, which in this case is a tuple. But in that case why is the value Unknown
({ "kind": "Default", "offset": 0, "value": "Unknown" }
) when an array is stored? Is it supposed to be the value of the first element in the array?