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

nasa / trick / 21296718347

23 Jan 2026 06:24PM UTC coverage: 55.589% (+0.009%) from 55.58%
21296718347

Pull #2031

github

web-flow
Merge 050505a97 into e4390df66
Pull Request #2031: Frame log choose buffering

8 of 9 new or added lines in 1 file covered. (88.89%)

172 existing lines in 8 files now uncovered.

12507 of 22499 relevant lines covered (55.59%)

308951.89 hits per line

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

43.38
/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✔
33
         R->attr->stl_type == TRICK_STL_DEQUE ||
×
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
        {
42
            emitError("STL vector accessor functions are NULL in ref_dim.");
×
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
        {
71
            emitError("Unsupported STL element type in ref_dim.");
×
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
        {
81
            if (debug_level > 1)
×
82
            {
83
                std::stringstream message;
×
84
                message << index_value << " is out of bounds for STL vector/ deque/ array " << R->reference
×
85
                        << " (size=" << num_elements << ").";
×
86
                emitError(message.str());
×
87
            }
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
        {
98
            container_address = R->address;
×
99
            element_index = index_value;
×
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
        // Mark that STL indexing was used in this reference path
107
        R->stl_present = 1;
1✔
108

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

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

159
        return (TRICK_NO_ERROR);
1✔
160
    } // End of special STL handling
161

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

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

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

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

192
    } else {
193

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

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

215
        R->pointer_present = 1 ;
112✔
216
        if ( R->create_add_path ) {
112✔
217
            ADDRESS_NODE * address_node ;
218

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

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

234
        // Get allocation information for the address
235
        ALLOC_INFO *alloc_info = get_alloc_info_of(R->address);
112✔
236

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

245
                // Get the reference attributes for what the pointer points to
246
                REF2 *ref2 = ref_attributes((char*)ref_name.c_str());
×
247

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

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

287
    if ( R->create_add_path ) {
23,022✔
288

289
        ADDRESS_NODE * address_node ;
290

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

310
    R->address =  (void*)((char*)R->address + index_value * item_size);
23,022✔
311
    R->num_index++;
23,022✔
312

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