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

nasa / trick / 20283694683

16 Dec 2025 09:44PM UTC coverage: 55.586% (-0.3%) from 55.934%
20283694683

push

github

web-flow
Add vs support for stl vector, deque, and array containers of supported data types (#1996)

* Added TV GUI side support for vectors

* Initial check-in for variable server to support vector.

* Added accessor functions to ATTRIBUTES to get stl container size and element at index so mm ref_dim can get element at index for a vector as getting element of an array plus bounds check for vector.

* Added support to deque and array as they be treated similar to vector.

* Updated the test due to vs vector support change.

* Added vector/deque/array of TRICK_STRUCTURED data type support.

* Updated to support vector<bool>.

* Updated to support vector/deque/array of *.

* Updated to support vector/deque/array of TRICK_ENUMERATED and display enum name for the stl enum elements for TV; also updated to show bool element as normal bool var for TV.

* Made elements of vector/array/deque to be editable from TV.

* Not to change the stl type to element when not indexing.

* Added special handling for updating vector of bool since std::vector<bool> is optimized to store bits compactly (8 bools per byte) in c++.

* Need to print NULL for the newly added ATTRIBUTES assessor function for filed attributes in io src file.

* Added var_get_stl_size command to vs sesssion and updated tv to show index range as constraint arrays for vector/deque/array when adding a var.

* Added test cases for vector/deque/array and also changed to use its own vs msg type for var_get_stl_size.

* Removed the unused function as it was changed to use clang api instead.

* Updated not to use static temp attr for working on storing vector<boo> to its ref_attr.

---------

Co-authored-by: plherrin <pherring04@gmail.com>

46 of 212 new or added lines in 8 files covered. (21.7%)

2 existing lines in 2 files now uncovered.

12508 of 22502 relevant lines covered (55.59%)

304713.82 hits per line

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

42.96
/trick_source/sim_services/MemoryManager/MemoryManager_ref_dim.cpp
1
#include <stdio.h>
2
#include <sys/types.h>
3
#include <string.h>
4
#include <sstream>
5
#include <array>
6
#include <algorithm>
7
#include <regex>
8

9
#include "trick/MemoryManager.hh"
10
#include "trick/vval.h"
11
#include "trick/attributes.h"
12
#include "trick/reference.h"
13
#include "trick/parameter_types.h"
14

15
/*
16
 Updates R, a reference to an arrayed object, to a reference to the indexed sub-element of that arrayed object.
17
*/
18
int Trick::MemoryManager::ref_dim( REF2* R, V_DATA* V) {
23,026✔
19

20
    int jj;
21
    int item_size;
22
    int index_value = vval_int(V);
23,026✔
23

24
    if (R->ref_type != REF_ADDRESS) {
23,026✔
25
        emitError("Attempt to index into a non-address reference is bogus in ref_dim.") ;
×
26
        return (1);
×
27
    }
28

29
    // Special handling for STL vectors, deques, and arrays - use the generated accessor function that
30
    // calls [] operator for element access
31
    if (R->attr->type == TRICK_STL &&
23,026✔
32
        (R->attr->stl_type == TRICK_STL_VECTOR ||
1✔
NEW
33
         R->attr->stl_type == TRICK_STL_DEQUE ||
×
NEW
34
         R->attr->stl_type == TRICK_STL_ARRAY) &&
×
35
        R->num_index == 0)
1✔
36
    {
37
        // Use the generated accessor functions to get vector/ deque/ array size and element address
38
        // These functions are generated by ICG and know the actual vector/ deque/ array type
39

40
        if (R->attr->get_stl_size == NULL || R->attr->get_stl_element == NULL)
1✔
41
        {
NEW
42
            emitError("STL vector accessor functions are NULL in ref_dim.");
×
NEW
43
            return (TRICK_PARAMETER_ARRAY_SIZE);
×
44
        }
45

46
        // Currently supported STL element types
47
        static constexpr std::array<TRICK_TYPE, 14> supported_stl_elem_types = {
48
            TRICK_STRING,
49
            //TRICK_CHARACTER,
50
            //TRICK_UNSIGNED_CHARACTER,
51
            TRICK_ENUMERATED,
52
            TRICK_SHORT,
53
            TRICK_UNSIGNED_SHORT,
54
            TRICK_INTEGER,
55
            TRICK_UNSIGNED_INTEGER,
56
            TRICK_LONG,
57
            TRICK_UNSIGNED_LONG,
58
            TRICK_FLOAT,
59
            TRICK_DOUBLE,
60
            TRICK_LONG_LONG,
61
            TRICK_UNSIGNED_LONG_LONG,
62
            TRICK_BOOLEAN,
63
            TRICK_STRUCTURED
64
        };
65

66
        // Check if element type is supported
67
        if (std::find(supported_stl_elem_types.begin(), 
1✔
68
                      supported_stl_elem_types.end(), 
69
                      R->attr->stl_elem_type) == supported_stl_elem_types.end())
2✔
70
        {
NEW
71
            emitError("Unsupported STL element type in ref_dim.");
×
NEW
72
            return (TRICK_PARAMETER_ARRAY_SIZE);
×
73
        }
74

75
        // Get the number of elements using the type-safe accessor function
76
        size_t num_elements = R->attr->get_stl_size(R->address);
1✔
77

78
        // Check bounds
79
        if (index_value < 0 || (size_t)index_value >= num_elements)
1✔
80
        {
NEW
81
            if (debug_level > 1)
×
82
            {
NEW
83
                std::stringstream message;
×
NEW
84
                message << index_value << " is out of bounds for STL vector/ deque/ array " << R->reference
×
NEW
85
                        << " (size=" << num_elements << ").";
×
NEW
86
                emitError(message.str());
×
87
            }
NEW
88
            return (TRICK_PARAMETER_ARRAY_SIZE);
×
89
        }
90

91
        // For vector<bool>, preserve container address and index for later use in assignment
92
        // vector<bool> needs special handling because get_stl_element returns a temp buffer
93
        void *container_address = nullptr;
1✔
94
        size_t element_index = 0;
1✔
95
        ATTRIBUTES *container_attr = nullptr;
1✔
96
        if (R->attr->stl_elem_type == TRICK_BOOLEAN && R->attr->set_stl_element != NULL)
1✔
97
        {
NEW
98
            container_address = R->address;
×
NEW
99
            element_index = index_value;
×
NEW
100
            container_attr = R->attr;
×
101
        }
102

103
        // Get the address of the indexed element using the type-safe accessor function
104
        R->address = R->attr->get_stl_element(R->address, index_value);
1✔
105

106
        // Store vector<bool> context in ref_attr for use in ref_assignment
107
        if (container_address != nullptr)
1✔
108
        {
109
            // Allocate on heap for thread safety and reentrancy
110
            // We'll use attr->attr to store container_address and attr->offset to store index
111
            // Allocate only if not already allocated
NEW
112
            if (R->ref_attr == NULL) {
×
NEW
113
                R->ref_attr = (ATTRIBUTES*)calloc(1, sizeof(ATTRIBUTES));
×
114
            } else {
115
                // Reset existing allocation
NEW
116
                memset(R->ref_attr, 0, sizeof(ATTRIBUTES));
×
117
            }
118
            // Set the fields
NEW
119
            R->ref_attr->attr = container_address;
×
NEW
120
            R->ref_attr->offset = element_index;
×
NEW
121
            R->ref_attr->type = TRICK_STL;
×
NEW
122
            R->ref_attr->stl_elem_type = TRICK_BOOLEAN;
×
NEW
123
            R->ref_attr->name = (const char *)container_attr;
×
124
        }
125

126
        // For structured types, ref_name will handle the attribute lookup dynamically
127
        // For enumerated types, we need to update attr to point to the enum attributes
128
        // For primitive types, DO NOT increment num_index because primitive attributes have num_index=0
129
        // and incrementing would cause a mismatch in ref_assignment (remaining_dimensions would be negative)
130
        if (R->attr->stl_elem_type == TRICK_ENUMERATED && R->attr->stl_elem_type_name != NULL)
1✔
131
        {
132
            // Increment num_index first
NEW
133
            R->num_index++;
×
134
            // Look up the enum attributes using the element type name
NEW
135
            ENUMERATION_MAP::iterator enum_pos = enumeration_map.find(R->attr->stl_elem_type_name);
×
NEW
136
            if (enum_pos != enumeration_map.end())
×
137
            {
138
                // Create a temporary attribute structure for the enum element
139
                static ATTRIBUTES temp_enum_attr;
NEW
140
                memset(&temp_enum_attr, 0, sizeof(ATTRIBUTES));
×
NEW
141
                temp_enum_attr.type = TRICK_ENUMERATED;
×
NEW
142
                temp_enum_attr.type_name = R->attr->stl_elem_type_name;
×
NEW
143
                temp_enum_attr.attr = enum_pos->second; // Point to ENUM_ATTR array
×
144
                // Get actual enum size using generated io_src_sizeof function
NEW
145
                size_t enum_size = io_src_sizeof_user_type(R->attr->stl_elem_type_name);
×
NEW
146
                temp_enum_attr.size = (enum_size > 0) ? enum_size : sizeof(int); // Fall back to sizeof(int) if not found
×
NEW
147
                temp_enum_attr.num_index = R->num_index; // Match the incremented indexing level
×
NEW
148
                temp_enum_attr.units = (char*)"1"; // Default units for enums
×
NEW
149
                temp_enum_attr.io = R->attr->io; // Preserve io flags from container
×
NEW
150
                R->attr = &temp_enum_attr;
×
151
            }
152
        }
153
        // For primitive types, the variable server and other code handle STL types
154
        // by checking stl_elem_type when type == TRICK_STL
155

156
        return (TRICK_NO_ERROR);
1✔
157
    } // End of special STL handling
158

159
    R->num_index_left--;
23,025✔
160
    if (R->num_index_left < 0) {
23,025✔
161
        /* if we have too many dimensions, flag an error */
162
        emitError("Too many dimensions in ref_dim.\n") ;
×
163
        return (TRICK_PARAMETER_ARRAY_SIZE);
×
164
    }
165

166
    /*Calculate the size of the items in this array. */
167
    item_size =  R->attr->size;
23,025✔
168
    for (jj = (R->attr->num_index - 1); jj > R->num_index; jj--) {
24,398✔
169
        if (R->attr->index[jj].size > 0) {
1,373✔
170
            item_size *= R->attr->index[jj].size;
635✔
171
        } else {
172
            item_size = sizeof(void *);
738✔
173
            R->pointer_present = 1 ;
738✔
174
        }
175
    }
176

177
    /* if current dimension is a constrained ... */
178
    if (R->attr->index[R->num_index].size != 0) {
23,025✔
179

180
        /* for constrained dimensions, we can check the validity of the index value */
181
        if (index_value >= R->attr->index[R->num_index].size || index_value < 0) {
22,913✔
182
            /* print out of bounds error message if MM debug_level is greater than 1 */
183
            if (debug_level > 1) {
3✔
184
                emitError("Memory Manager ERROR: Array index out of bounds.") ;
×
185
            }
186
            return (TRICK_PARAMETER_ARRAY_SIZE);
3✔
187
        }
188

189
    } else {
190

191
        /* for unconstrained dimensions, we can check that the index value is non-negative
192
           and that it is less than the size of the array */
193
        if (index_value >= (get_size(*(void**)(R->address))) || index_value < 0) {
112✔
194

195
            if (index_value >= 0 && get_size(*(void**)(R->address)) == 0) {
×
196
                // Special case (do nothing here):
197
                //   For regular pointers as an equivalent to ->
198
                //   For array pointers that are not yet allocated
199
                // If a pointer is not allocated regardless of regular pointer or array pointer, an error message will be emitted below
200
                //   However, if the pointer is already assigned to a valid address, the error message will NOT be emitted below
201
            } else {
202
                /* print out of bounds error message if MM debug_level is greater than 1 */
203
                if (debug_level > 1) {
×
204
                    std::stringstream message;
×
205
                    message << index_value << " is out of bounds for " << R->reference << " (size=" << get_size(*(void**)(R->address)) << ").";
×
206
                    emitError(message.str());
×
207
                }
208
                return (TRICK_PARAMETER_ARRAY_SIZE);
×
209
            }
210
        }
211

212
        R->pointer_present = 1 ;
112✔
213
        if ( R->create_add_path ) {
112✔
214
            ADDRESS_NODE * address_node ;
215

216
            address_node = new ADDRESS_NODE ;
112✔
217
            address_node->operator_ = AO_DEREFERENCE ;
112✔
218
            address_node->operand.address = NULL ;
112✔
219
            DLL_AddTail(address_node , R->address_path) ;
112✔
220
        }
221

222
        // Dereference the pointer.
223
        R->address = *(void**)R->address;
112✔
224
        if ( R->address == NULL) {
112✔
225
            std::stringstream message;
×
226
            message << "Reference (" << R->reference << ") address is NULL in ref_dim.";
×
227
            emitError(message.str());
×
228
            return(TRICK_PARAMETER_ADDRESS_NULL) ;
×
229
        }
230

231
        // Get allocation information for the address
232
        ALLOC_INFO *alloc_info = get_alloc_info_of(R->address);
112✔
233

234
        // Skip if allocation name is NULL
235
        if (alloc_info != NULL && alloc_info->name != NULL) {
112✔
236
            // Get the reference name from the address that R points if exists and contains & at front
237
            // Otherwise, the pointer is not assigned to anything else rather itself is allocated
238
            std::string ref_name = ref_name_from_address(R->address);
×
239
            if (!ref_name.empty() && ref_name.front() == '&') {
×
240
                ref_name = ref_name.substr(1);
×
241

242
                // Get the reference attributes for what the pointer points to
243
                REF2 *ref2 = ref_attributes((char*)ref_name.c_str());
×
244

245
                // Check if the reference that the pointer points to is valid. Return error if not.
246
                if (ref2 == NULL) {
×
247
                    std::stringstream message;
×
248
                    message << "Reference (" << R->reference << ") is not allocated in ref_dim.";
×
249
                    emitError(message.str());
×
250
                    return(TRICK_PARAMETER_ADDRESS_NULL);
×
251
                }
252

253
                // Only check bounds if ref2 is array-ed
254
                if (ref2->num_index > 0) {
×
255
                    // Check if the pointer points to a static array or a dynamic array and if array index is out of bounds
256
                    if (ref2->attr && ref2->attr->index[ref2->attr->num_index-1].size != 0) { // Static array case
×
257
                        // Check if the index is out of bounds if the pointer points to a static array
258
                        if (index_value >= ref2->attr->index[ref2->attr->num_index-1].size || index_value < 0) {
×
259
                            /* print out of bounds error message if MM debug_level is greater than 1 */
260
                            if (debug_level > 1) {
×
261
                                emitError("Memory Manager ERROR: Array index out of bounds.") ;
×
262
                            }
263
                            free(ref2);
×
264
                            return (TRICK_PARAMETER_ARRAY_SIZE);
×
265
                        }
266
                    } else { // Dynamic array case
267
                        // Check if the index is out of bounds if the pointer points to a dynamic array
268
                        if (index_value >= (get_size(*(void**)(R->address)))) {
×
269
                            /* print out of bounds error message if MM debug_level is greater than 1 */
270
                            if (debug_level > 1) {
×
271
                                std::stringstream message;
×
272
                                message << index_value << " is out of bounds for " << R->reference << " (size=" << get_size(*(void**)(R->address)) << ").";
×
273
                                emitError(message.str());
×
274
                            }
275
                            free(ref2);
×
276
                            return (TRICK_PARAMETER_ARRAY_SIZE);
×
277
                        }
278
                    }
279
                }
280
            } // if (!ref_name.empty() && ref_name.front() == '&') {
281
        } // if (alloc_info->name != NULL) {
282
    } // if (R->attr->index[R->num_index].size != 0) {
283

284
    if ( R->create_add_path ) {
23,022✔
285

286
        ADDRESS_NODE * address_node ;
287

288
        if ( index_value > 0 ) {
9,798✔
289
            address_node = (ADDRESS_NODE *)DLL_GetAt(DLL_GetTailPosition(R->address_path), R->address_path) ;
9,191✔
290
            switch ( address_node->operator_ ) {
9,191✔
291
                case AO_ADDRESS:
9,079✔
292
                    address_node->operand.address = (void *)((char *)address_node->operand.address +  index_value * item_size) ;
9,079✔
293
                    break ;
9,079✔
294
                case AO_DEREFERENCE:
112✔
295
                    address_node = new ADDRESS_NODE ;
112✔
296
                    address_node->operator_ = AO_OFFSET ;
112✔
297
                    address_node->operand.offset = index_value * item_size ;
112✔
298
                    DLL_AddTail(address_node , R->address_path) ;
112✔
299
                    break ;
112✔
300
                case AO_OFFSET:
×
301
                    address_node->operand.offset += index_value * item_size ;
×
302
                    break ;
×
303
            }
304
        }
305
    }
306

307
    R->address =  (void*)((char*)R->address + index_value * item_size);
23,022✔
308
    R->num_index++;
23,022✔
309

310
    return (TRICK_NO_ERROR);
23,022✔
311
}
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

© 2025 Coveralls, Inc