• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

nasa / trick / 24529915492

16 Apr 2026 07:32PM UTC coverage: 55.99% (+0.2%) from 55.802%
24529915492

push

github

web-flow
1964 methods return size one pointers (#1965)

* Fixed issues pertaining to swig access and printing of pointers returned by methods in classes.

- Fixed issue determining single vs double precision printing of a floating-point variable

- Added a function to TMM to get attributes of an address and also the remaining offset of from the start of those attributes

- Refactored several attribute related functions to AttributeUtils (Hong Chen)

- Added tests to SIM_test_ip to test printing of pointers of various dimensions pointing to various parts of various variables

- Updated swig_int_typemap to use the new attributes getter for units specification and insight into the memory the returned variables and pointers pointer to.

- Removed -std=c++11 for Trick to go full minimum required standard of c++14 (Hong Chen)

* Partially addressed MR comments

* Format using PR 2011 clang-format with BreakBeforeBraces: Allman

* Remove ununsed skipIndex and commented code

* Remove space added by clang-format

* Change swig_double to use default member initialization. Removed unnecessary assignment in swig_int_typemap. Set remainingOffset after checking if traverse call succeeded. Explicitly cast isFloat to int for array indexing.

173 of 205 new or added lines in 5 files covered. (84.39%)

2 existing lines in 2 files now uncovered.

12679 of 22645 relevant lines covered (55.99%)

309062.91 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

94.87
/trick_source/sim_services/MemoryManager/AttributesUtils.cpp
1
#include "trick/AttributesUtils.hh"
2

3
// Compute the byte size occupied by a member - references, arrays, and pointers
4
size_t Trick::AttributesUtils::compute_member_byte_size(const ATTRIBUTES& member)
50,163✔
5
{
6
    // if mod bit 0 is set, member is a reference. Width of reference is stored
7
    // in bits 3-8 of mods. We could use size(void*), but that is implementation
8
    // specific and not required by C++ standard.
9
    if ((member.mods & 1) == 1)
50,163✔
10
    {
11
        return ((member.mods >> 3) & 0x3F);
5✔
12
    }
13

14
    // if array
15
    if (member.num_index != 0)
50,158✔
16
    {
17
        // if size of last valid index is 0, then we are looking at a pointer
18
        size_t total = 0;
32,909✔
19
        if (member.index[member.num_index - 1].size == 0)
32,909✔
20
        {
21
            total = sizeof(void*);
18,070✔
22
        }
23
        else
24
        {
25
            total = member.size;
14,839✔
26
        }
27
        // multiply by sizes of fixed dimensions
28
        for (int i = 0; i < member.num_index; ++i)
65,974✔
29
        {
30
            if (member.index[i].size != 0)
51,135✔
31
            {
32
                total *= member.index[i].size;
33,065✔
33
            }
34
            else
35
            {
36
                break;
18,070✔
37
            }
38
        }
39
        return total;
32,909✔
40
    }
41

42
    // just return member.size otherwise
43
    return member.size;
17,249✔
44
}
45

46
// Return the ATTRIBUTES entry that contains the given offset within the struct/class.
47
// Example: for a struct with members like this:
48
//   struct MyStruct {
49
//     int a;          // offset 0, size 4 (padding 4-7)
50
//     double b;       // offset 8, size 8
51
//     char c[10];     // offset 16, size 10
52
//   }
53
// Then:
54
//   find_member_by_offset(structAttr, 2) would return the ATTRIBUTES for 'a' because offset 2 is within 'a' (0-3).
55
//   find_member_by_offset(structAttr, 10) would return the ATTRIBUTES for 'b' because offset 10 is within 'b' (8-15).
56
//   find_member_by_offset(structAttr, 20) would return the ATTRIBUTES for 'c' because offset 20 is within 'c' (16-25).
57
ATTRIBUTES* Trick::AttributesUtils::find_member_by_offset(ATTRIBUTES* structAttr, size_t addrOffsetFromStruct)
2,952✔
58
{
59
    int ii = 0;
2,952✔
60
    size_t temp_size;
61
    // Find the member which contains the address pointed to by addr and offset
62
    while (structAttr[ii].name[0] != '\0')
50,751✔
63
    {
64
        temp_size = compute_member_byte_size(structAttr[ii]);
50,163✔
65
        if (addrOffsetFromStruct < structAttr[ii].offset || addrOffsetFromStruct >= structAttr[ii].offset + temp_size)
50,163✔
66
        {
67
            ++ii;
47,799✔
68
        }
69
        else
70
        {
71
            break;
72
        }
73
    }
74
    return &(structAttr[ii]);
2,952✔
75
}
76

77
// Count the number of fixed dimensions on an ATTRIBUTES entry.
78
int Trick::AttributesUtils::count_fixed_dims(const ATTRIBUTES& member)
1,235✔
79
{
80
    int num_fixed_dims = 0;
1,235✔
81
    for (int i = 0; i < member.num_index; ++i)
3,237✔
82
    {
83
        if (member.index[i].size > 0)
2,229✔
84
        {
85
            ++num_fixed_dims;
2,002✔
86
        }
87
        else
88
        {
89
            break;
227✔
90
        }
91
    }
92
    return num_fixed_dims;
1,235✔
93
}
94

95
// Resolve a byte offset within a structured object to the matching member and array context.
96
// This call resolves one strucural level at a time. The caller is responsible for stepping
97
// through nested structures by calling this function recursively with the found member's ATTRIBUTES
98
// and the offset within that member.
99
//
100
// Example 1: for a struct with members like this:
101
//   struct MyStruct {
102
//     int a;        // offset 0, size 4
103
//     int b[3];     // offset 4, size 4 each
104
//   }
105
// Entries would be:
106
//   myStructAttr[0] = { name="a", offset=0, size=4, num_index=0, ... }
107
//   myStructAttr[1] = { name="b", offset=4, size=4, num_index=1, index[0].size=3, ... }
108
//   myStructAttr[2] = { name="", ... } // Sentinel
109
// So member b occupies these bytes:
110
//   b[0] at offset 4-7
111
//   b[1] at offset 8-11
112
//   b[2] at offset 12-15
113
// Then call:
114
//   TraversalResult result;
115
//   traverse_for_offset(10, myStructAttr, result);
116
// Basically asking given the member layout of MyStruct, what member contains byte offset 10
117
//   The function would resolve offset 10 to member 'b' and compute the array index as 1
118
//   because b[1] occupies bytes 8-11 which contains byte 10. So result would be:
119
//     result.found_attr = b (pointer to myStructAttr[1] (the ATTRIBUTES for 'b'))
120
//     result.offset_from_found_attr = 10 - 4 = 6 (offset within member 'b')
121
//     result.array_indices = [1] (index for the first dimension of 'b')
122
//     result.num_computed_indices = 1 (because 'b' is a 1D array)
123
//     result.is_in_anonymous_member = false (because a member with a name that contains the offset was found)
124
//
125
// Example 2: for a struct with a structured array member like this:
126
//   struct Inner {
127
//     double q;   // offset 0, size 8
128
//     int r;      // offset 8, size 4
129
//   };
130
//
131
//   struct Outer {
132
//     int a;          // offset 0
133
//     Inner items[4]; // offset 8, each element size 16
134
//   };
135
//
136
// Array layout of items would be:
137
//   items[0].q at offset 8-15
138
//   items[0].r at offset 16-19
139
//   items[1].q at offset 24-31
140
//   items[1].r at offset 32-35
141
//   items[2].q at offset 40-47
142
//   items[2].r at offset 48-51
143
//   items[3].q at offset 56-63
144
//   items[3].r at offset 64-67
145
//
146
// If called with reference_offset = 44, the function would resolve it to the
147
// named member 'items', because offset 44 lies within the items member.
148
// The result would be:
149
//   result.found_attr = items (pointer to ATTRIBUTES for 'items')
150
//   result.offset_from_found_attr = 32
151
//     (initially 44 - 8 = 36, then adjusted to the base offset of items[2],
152
//      which is 2 * 16 = 32 bytes into the items array)
153
//   result.array_indices = [2]
154
//   result.num_computed_indices = 1
155
//   result.is_in_anonymous_member = false
156
//
157
// The call resolves the address to the named member 'items' and computes array
158
// index 2 because items[2] contains byte offset 44. It does not resolve to the
159
// inner members 'q' or 'r' yet; that happens after the caller recurses into
160
// items[2]. On that recursive call, the inner offset is 44 - 40 = 4, so the
161
// found_attr would be 'q' because q occupies offsets 0-7 within Inner.
162
// That is how ClassicCheckPointerAgent builds names, and how MemoryManager_get_attributes_for_address
163
// walks into nested members.
164
int Trick::AttributesUtils::traverse_for_offset(
2,952✔
165
    size_t reference_offset,
166
    ATTRIBUTES* struct_attr,
167
    TraversalResult& result)
168
{
169
    // Initialize result
170
    result = TraversalResult { };
2,952✔
171

172
    // Find the structure member that corresponds to the reference offset
173
    ATTRIBUTES* ret_attr = find_member_by_offset(struct_attr, reference_offset);
2,952✔
174

175
    // Check if we failed to find a member (anonymous/**'d out member)
176
    if (ret_attr->name[0] == '\0')
2,952✔
177
    {
178
        result.is_in_anonymous_member = true;
588✔
179
        result.offset_from_found_attr = reference_offset;
588✔
180
        return 0;
588✔
181
    }
182

183
    result.found_attr = ret_attr;
2,364✔
184
    result.offset_from_found_attr = reference_offset - ret_attr->offset;
2,364✔
185

186
    // Handle non-structured (primitive) types
187
    if (ret_attr->type != TRICK_STRUCTURED)
2,364✔
188
    {
189
        // Check if it's a scalar or unconstrained pointer
190
        if (ret_attr->num_index == 0 || ret_attr->index[0].size == 0)
1,259✔
191
        {
192
            return 0;
25✔
193
        }
194

195
        // It's an array - compute indices
196
        size_t offset_in_array = result.offset_from_found_attr;
1,234✔
197
        bool ok = compute_fixed_indices_for_linear_offset(*ret_attr, offset_in_array, result.array_indices, result.num_computed_indices);
1,234✔
198

199
        if (!ok)
1,234✔
200
        {
NEW
201
            return 1;
×
202
        }
203

204
        return 0;
1,234✔
205
    }
206

207
    // Handle TRICK_STRUCTURED types
208

209
    // If it's a reference (&), we're done
210
    if ((ret_attr->mods & 1) == 1)
1,105✔
211
    {
212
        return 0;
1✔
213
    }
214

215
    // If it's an unarrayed struct, caller should recurse into it
216
    if (ret_attr->num_index == 0)
1,104✔
217
    {
218
        // Signal to caller that recursion is needed
219
        // The found_attr and offset info are already set
220
        return 0;
1,101✔
221
    }
222

223
    // If it's a pointer (unconstrained array), we're done
224
    if (ret_attr->index[0].size == 0)
3✔
225
    {
226
        return 0;
2✔
227
    }
228

229
    // It's an arrayed struct - compute indices
230
    size_t offset_in_array = result.offset_from_found_attr;
1✔
231
    bool ok = compute_fixed_indices_for_linear_offset(*ret_attr, offset_in_array, result.array_indices, result.num_computed_indices);
1✔
232

233
    if (!ok)
1✔
234
    {
NEW
235
        return 1;
×
236
    }
237

238
    // Calculate the linear offset within the array element
239
    size_t element_offset = 0;
1✔
240
    for (int j = 0; j < ret_attr->num_index; j++)
3✔
241
    {
242
        int m = result.array_indices[j];
2✔
243
        for (int k = j + 1; m && (k < ret_attr->num_index); k++)
3✔
244
        {
245
            m *= ret_attr->index[k].size;
1✔
246
        }
247
        element_offset += m * ret_attr->size;
2✔
248
    }
249

250
    result.offset_from_found_attr = element_offset;
1✔
251

252
    return 0;
1✔
253
}
254

255
// Convert a byte offset within fixed array into concrete array indices.
256
// Example: For an array int a[3][4], assuming:
257
//   member.size = 4 (size of int in bytes)
258
//   dimensions are 3 and 4 (member.index[0].size = 3, member.index[1].size = 4)
259
//   offset_within_member_bytes = 28
260
//     Byte 28 means the 8th int overall, so the expected indices would be [1][3]
261
//     because a[1][3] is the 8th int (0-based indexing).
262
//   So, out_indices would be set to [1, 3] and out_num_fixed_dims would be set to 2.
263
bool Trick::AttributesUtils::compute_fixed_indices_for_linear_offset(
1,235✔
264
    const ATTRIBUTES& member,
265
    long offset_within_member_bytes,
266
    int out_indices[TRICK_MAX_INDEX],
267
    int& out_num_fixed_dims)
268
{
269
    out_num_fixed_dims = count_fixed_dims(member);
1,235✔
270
    if (out_num_fixed_dims == 0)
1,235✔
271
    {
NEW
272
        return true;
×
273
    }
274

275
    long size = member.size;
1,235✔
276
    int last_size = member.size;
1,235✔
277
    long remaining = offset_within_member_bytes;
1,235✔
278

279
    for (int i = out_num_fixed_dims - 1; i >= 0; --i)
3,237✔
280
    {
281
        size *= member.index[i].size;
2,002✔
282
        if (size == 0 || last_size == 0)
2,002✔
283
        {
NEW
284
            return false;
×
285
        }
286
        out_indices[i] = static_cast<int>((remaining % size) / last_size);
2,002✔
287
        remaining -= last_size * out_indices[i];
2,002✔
288
        last_size = size;
2,002✔
289
    }
290
    return true;
1,235✔
291
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc