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

nickg / nvc / 14229470486

02 Apr 2025 08:26PM UTC coverage: 92.323% (+0.004%) from 92.319%
14229470486

push

github

nickg
Fix incorrect handling of array-of-array aggregate

4 of 4 new or added lines in 1 file covered. (100.0%)

206 existing lines in 7 files now uncovered.

68754 of 74471 relevant lines covered (92.32%)

422127.68 hits per line

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

98.58
/src/bounds.c
1
//
2
//  Copyright (C) 2011-2024  Nick Gasson
3
//
4
//  This program is free software: you can redistribute it and/or modify
5
//  it under the terms of the GNU General Public License as published by
6
//  the Free Software Foundation, either version 3 of the License, or
7
//  (at your option) any later version.
8
//
9
//  This program is distributed in the hope that it will be useful,
10
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
11
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
//  GNU General Public License for more details.
13
//
14
//  You should have received a copy of the GNU General Public License
15
//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
16
//
17

18
#include "util.h"
19
#include "common.h"
20
#include "diag.h"
21
#include "phase.h"
22
#include "type.h"
23

24
#include <assert.h>
25
#include <string.h>
26
#include <stdarg.h>
27
#include <stdlib.h>
28
#include <inttypes.h>
29

30
static void bounds_check_assignment(tree_t target, tree_t value);
31

32
typedef struct interval interval_t;
33

34
struct interval {
35
   int64_t     low;
36
   int64_t     high;
37
   interval_t *next;
38
};
39

40
#define bounds_error(t, ...) \
41
   do { error_at(tree_loc(t), __VA_ARGS__); } while (0)
42

43
static void bounds_check_string_literal(tree_t t)
23,969✔
44
{
45
   type_t type = tree_type(t);
23,969✔
46
   assert(!type_is_unconstrained(type));
23,969✔
47

48
   int64_t expect;
23,969✔
49
   if (folded_length(range_of(type, 0), &expect) && expect != tree_chars(t))
23,969✔
50
      bounds_error(t, "expected %"PRIi64" elements in string literal but "
23,969✔
51
                   "have %d", expect, tree_chars(t));
52
}
23,969✔
53

54
static void format_type_range(diag_t *d, type_t type, range_kind_t dir,
78✔
55
                              int64_t low, int64_t high)
56
{
57
   text_buf_t *tb = diag_text_buf(d);
78✔
58

59
   if (dir == RANGE_DOWNTO) {
78✔
60
      to_string(tb, type, high);
17✔
61
      tb_cat(tb, " downto ");
17✔
62
      to_string(tb, type, low);
17✔
63
   }
64
   else {
65
      to_string(tb, type, low);
61✔
66
      tb_cat(tb, " to ");
61✔
67
      to_string(tb, type, high);
61✔
68
   }
69
}
78✔
70

71
static void add_hint_string(diag_t *d, tree_t where)
31✔
72
{
73
   const char *what = "";
31✔
74
   switch (tree_kind(where)) {
31✔
75
   case T_VAR_DECL:
17✔
76
   case T_SIGNAL_DECL:
77
   case T_CONST_DECL:
78
   case T_REF:          what = class_str(class_of(where)); break;
17✔
79
   case T_PARAM_DECL:   what = "parameter"; break;
80
   case T_PORT_DECL:    what = "port"; break;
1✔
81
   case T_GENERIC_DECL: what = "generic"; break;
1✔
82
   case T_ALIAS:        what = "alias"; break;
1✔
83
   default: return;
84
   }
85

86
   diag_printf(d, " for %s %s", what, istr(tree_ident(where)));
30✔
87
}
88

89
static void bounds_check_scalar(tree_t value, type_t type, tree_t hint)
195,037✔
90
{
91
   if (type_is_generic(type))
195,037✔
92
      return;   // Cannot check yet
24✔
93

94
   tree_t r = range_of(type, 0);
195,013✔
95

96
   bool error = false;
195,013✔
97
   int64_t low, high, folded;
195,013✔
98
   double rlow, rhigh;
195,013✔
99
   if (folded_bounds(r, &low, &high)) {
195,013✔
100
      if (folded_int(value, &folded))
169,972✔
101
         error = (folded < low || folded > high);
136,834✔
102
   }
103
   else if (folded_bounds_real(r, &rlow, &rhigh)) {
25,041✔
104
      double folded_f;
24,959✔
105
      if (folded_real(value, &folded_f)) {
24,959✔
106
         error  = (folded_f < rlow || folded_f > rhigh);
17,463✔
107
         folded = FLOAT_BITS(folded_f);
17,463✔
108
         low    = FLOAT_BITS(rlow);
17,463✔
109
         high   = FLOAT_BITS(rhigh);
17,463✔
110
      }
111
   }
112

113
   if (error) {
93,387✔
114
      diag_t *d = diag_new(DIAG_ERROR, tree_loc(value));
25✔
115
      diag_printf(d, "value ");
25✔
116
      to_string(diag_text_buf(d), type, folded);
25✔
117
      diag_printf(d, " outside of %s range ", type_pp(type));
25✔
118
      format_type_range(d, type, tree_subkind(r), low, high);
25✔
119

120
      if (hint != NULL)
25✔
121
         add_hint_string(d, hint);
24✔
122

123
      diag_emit(d);
25✔
124
   }
125
}
126

127
static void bounds_check_array(tree_t value, type_t type, tree_t hint)
18,257✔
128
{
129
   if (type_is_unconstrained(type))
18,257✔
130
      return;
131

132
   type_t value_type = tree_type(value);
16,876✔
133
   if (type_is_unconstrained(value_type))
16,876✔
134
      return;
135

136
   const int ndims = dimension_of(type);
9,635✔
137
   for (int i = 0; i < ndims; i++) {
20,032✔
138
      int64_t target_w, value_w;
10,397✔
139
      if (!folded_length(range_of(type, i), &target_w))
10,397✔
140
         continue;
2,299✔
141
      else if (!folded_length(range_of(value_type, i), &value_w))
8,139✔
142
         continue;
41✔
143
      else if (target_w != value_w) {
8,098✔
144
         diag_t *d = diag_new(DIAG_ERROR, tree_loc(value));
8✔
145
         diag_printf(d, "length of ");
8✔
146
         if (i > 0)
8✔
147
            diag_printf(d, "dimension %d of ", i + 1);
×
148
         diag_printf(d, "value %"PRIi64" does not match length of target %"
8✔
149
                     PRIi64, value_w, target_w);
150
         if (hint != NULL)
8✔
151
            add_hint_string(d, hint);
7✔
152

153
         diag_emit(d);
8✔
154
      }
155
   }
156
}
157

158
static tree_t bounds_check_call_args(tree_t t)
95,847✔
159
{
160
   tree_t decl = tree_ref(t);
95,847✔
161

162
   const int nparams = tree_params(t);
95,847✔
163
   const int nports  = tree_ports(decl);
95,847✔
164

165
   bool known_arg_length = true;
95,847✔
166

167
   for (int i = 0; (i < nparams) && (i < nports); i++) {
293,247✔
168
      tree_t param = tree_param(t, i);
197,400✔
169
      assert(tree_subkind(param) == P_POS);
197,400✔
170

171
      tree_t value = tree_value(param);
197,400✔
172
      tree_t port  = tree_port(decl, tree_pos(param));
197,400✔
173

174
      type_t ftype = tree_type(port);
197,400✔
175
      type_t atype = tree_type(tree_value(param));
197,400✔
176

177
      if (type_is_array(ftype)) {
197,400✔
178
         // Check bounds of constrained array parameters
179

180
         if (type_is_unconstrained(atype)) {
50,546✔
181
            known_arg_length = false;
22,011✔
182
            continue;
22,011✔
183
         }
184
         else if (type_is_unconstrained(ftype))
28,535✔
185
            continue;
27,476✔
186

187
         const int ndims = dimension_of(ftype);
1,059✔
188

189
         for (int j = 0; j < ndims; j++) {
2,198✔
190
            tree_t formal_r = range_of(ftype, j);
1,139✔
191
            tree_t actual_r = range_of(atype, j);
1,139✔
192

193
            int64_t f_len, a_len;
1,139✔
194
            if (!folded_length(formal_r, &f_len))
1,139✔
195
               continue;
28✔
196
            else if (!folded_length(actual_r, &a_len)) {
1,136✔
197
               known_arg_length = false;
25✔
198
               continue;
25✔
199
            }
200

201
            if (f_len != a_len) {
1,111✔
202
               diag_t *d = diag_new(DIAG_ERROR, tree_loc(param));
3✔
203
               diag_printf(d, "actual length %"PRIi64, a_len);
3✔
204
               if (ndims > 1)
3✔
205
                  diag_printf(d, " for dimension %d", j + 1);
1✔
206
               diag_printf(d, " does not match formal length %"PRIi64
3✔
207
                           " for parameter %s", f_len, istr(tree_ident(port)));
208
               diag_emit(d);
3✔
209
            }
210
         }
211
      }
212
      else if (type_is_scalar(ftype))
146,854✔
213
         bounds_check_scalar(value, ftype, port);
138,997✔
214
   }
215

216
   if (tree_kind(decl) == T_GENERIC_DECL)
95,847✔
217
      return t;
218

219
   const subprogram_kind_t kind = tree_subkind(decl);
95,533✔
220
   if (known_arg_length && (kind == S_ARRAY_EQ || kind == S_ARRAY_NEQ)) {
95,533✔
221
      // Warn if calling the predefined array equality operators and the
222
      // left and right hand sides have different lengths as this always
223
      // returns FALSE
224

225
      type_t ltype = tree_type(tree_value(tree_param(t, 0)));
3,416✔
226
      type_t rtype = tree_type(tree_value(tree_param(t, 1)));
3,416✔
227

228
      const int ndims = dimension_of(ltype);
3,416✔
229
      for (int i = 0; i < ndims; i++) {
7,324✔
230
         tree_t left_r = range_of(ltype, i);
3,920✔
231
         tree_t right_r = range_of(rtype, i);
3,920✔
232

233
         int64_t left_len;
3,920✔
234
         if (!folded_length(left_r, &left_len))
3,920✔
235
            continue;
435✔
236

237
         int64_t right_len;
3,485✔
238
         if (!folded_length(right_r, &right_len))
3,485✔
239
            continue;
×
240

241
         if (left_len != right_len) {
3,485✔
242
            diag_t *d = diag_new(DIAG_WARN, tree_loc(t));
12✔
243
            diag_printf(d, "call to predefined operator %s always returns "
12✔
244
                        "FALSE", istr(tree_ident(t)));
245
            diag_hint(d, tree_loc(t), "left length is %"PRIi64" but right "
12✔
246
                      "length is %"PRIi64, left_len, right_len);
247
            diag_emit(d);
12✔
248
            break;
12✔
249
         }
250
      }
251
   }
252

253
   return t;
254
}
255

256
static bool index_in_range(tree_t index, int64_t low, int64_t high,
6,464✔
257
                           int64_t *value)
258
{
259
   int64_t folded;
6,464✔
260
   if (folded_int(index, &folded)) {
6,464✔
261
      *value = folded;
6,461✔
262
      return folded >= low && folded <= high;
6,476✔
263
   }
264

265
   return true;
266
}
267

268
static bool bounds_check_index(tree_t index, type_t type, range_kind_t kind,
4,943✔
269
                               const char *what, int64_t low, int64_t high)
270
{
271
   int64_t folded;
4,943✔
272
   if (!index_in_range(index, low, high, &folded) && low <= high) {
4,943✔
273
      diag_t *d = diag_new(DIAG_ERROR, tree_loc(index));
10✔
274
      diag_printf(d, "%s index ", what);
10✔
275
      to_string(diag_text_buf(d), type, folded);
10✔
276
      diag_printf(d, " outside of %s range ", type_pp(type));
10✔
277
      format_type_range(d, type, kind, low, high);
10✔
278
      diag_emit(d);
10✔
279

280
      return false;
10✔
281
   }
282

283
   return true;
284
}
285

286
static void bounds_check_array_ref(tree_t t)
15,842✔
287
{
288
   tree_t value = tree_value(t);
15,842✔
289

290
   if (!tree_has_type(value))
15,842✔
291
      return;
292
   else if (tree_flags(t) & TREE_F_ELIDE_BOUNDS)
15,842✔
293
      return;
294

295
   type_t value_type = tree_type(value);
15,579✔
296

297
   const bool unconstrained = type_is_unconstrained(value_type);
15,579✔
298
   const bool value_is_ref = tree_kind(value) == T_REF;
15,579✔
299

300
   int nstatic = 0;
15,579✔
301
   const int nparams = tree_params(t);
15,579✔
302
   for (int i = 0; i < nparams; i++) {
32,789✔
303
      tree_t p = tree_param(t, i);
17,210✔
304
      tree_t pvalue = tree_value(p);
17,210✔
305
      bool checked = false;
17,210✔
306

307
      if (!unconstrained) {
17,210✔
308
         tree_t r = range_of(value_type, i);
13,730✔
309
         type_t index_type = index_type_of(value_type, i);
13,730✔
310
         const range_kind_t dir = tree_subkind(r);
13,730✔
311

312
         int64_t ivalue, low, high;
13,730✔
313
         if (folded_int(pvalue, &ivalue) && folded_bounds(r, &low, &high)) {
13,730✔
314
            checked = true;
5,643✔
315

316
            if (ivalue < low || ivalue > high) {
5,643✔
317
               diag_t *d = diag_new(DIAG_ERROR, tree_loc(pvalue));
11✔
318
               diag_printf(d, "array");
11✔
319
               if (tree_kind(value) == T_REF)
11✔
320
                  diag_printf(d, " %s", istr(tree_ident(value)));
10✔
321
               diag_printf(d, " index ");
11✔
322
               to_string(diag_text_buf(d), index_type, ivalue);
11✔
323
               diag_printf(d, " outside of %s range ", type_pp(index_type));
11✔
324
               format_type_range(d, index_type, dir, low, high);
11✔
325

326
               diag_emit(d);
11✔
327
            }
328
         }
329
      }
330

331
      if (value_is_ref && nparams == 1 && tree_kind(pvalue) == T_REF) {
17,210✔
332
         // Automatically elide bounds check in cases like
333
         //
334
         //   for i in x'range loop
335
         //     y := a(x);  -- Always in bounds
336

337
         type_t ptype = tree_type(pvalue);
7,131✔
338
         if (type_kind(ptype) == T_SUBTYPE && type_has_constraint(ptype)) {
7,131✔
339
            tree_t c = type_constraint(ptype);
5,556✔
340
            if (tree_subkind(c) == C_RANGE) {
5,556✔
341
               tree_t r = tree_range(c, 0);
5,556✔
342
               if (tree_subkind(r) == RANGE_EXPR) {
5,556✔
343
                  tree_t r_attr = tree_value(r);
2,119✔
344
                  assert(tree_kind(r_attr) == T_ATTR_REF);
2,119✔
345
                  tree_t r_base = tree_name(r_attr);
2,119✔
346
                  checked |= (tree_kind(r_base) == T_REF &&
5,165✔
347
                              tree_ref(r_base) == tree_ref(value));
2,118✔
348
               }
349
            }
350
         }
351
      }
352

353
      if (checked)
17,210✔
354
         nstatic++;
6,833✔
355
   }
356

357
   if (nstatic == nparams)
15,579✔
358
      tree_set_flag(t, TREE_F_ELIDE_BOUNDS);
5,700✔
359
}
360

361
static void bounds_check_array_slice(tree_t t)
2,885✔
362
{
363
   tree_t value = tree_value(t);
2,885✔
364

365
   if (!tree_has_type(value))
2,885✔
366
      return;
2,199✔
367

368
   type_t value_type = tree_type(value);
2,885✔
369

370
   if (type_is_unconstrained(value_type))
2,885✔
371
      return;
372

373
   tree_t b = range_of(value_type, 0);
2,629✔
374
   tree_t r = tree_range(t, 0);
2,629✔
375

376
   int64_t blow, bhigh;
2,629✔
377
   if (!folded_bounds(b, &blow, &bhigh))
2,629✔
378
      return;
379

380
   int64_t rlow, rhigh;
859✔
381
   if (!folded_bounds(r, &rlow, &rhigh))
859✔
382
      return;
383

384
   if (rlow > rhigh)
719✔
385
      return;  // Null range
386

387
   type_t index_type = index_type_of(value_type, 0);
686✔
388
   const range_kind_t dir = tree_subkind(b);
686✔
389

390
   int64_t folded;
686✔
391
   const char *error = NULL;
686✔
392
   if (!index_in_range(tree_left(r), blow, bhigh, &folded))
686✔
393
      error = "left";
394
   else if (!index_in_range(tree_right(r), blow, bhigh, &folded))
683✔
395
      error = "right";
396

397
   if (error) {
4✔
398
      diag_t *d = diag_new(DIAG_ERROR, tree_loc(r));
4✔
399
      diag_printf(d, "array");
4✔
400
      if (tree_kind(value) == T_REF)
4✔
401
         diag_printf(d, " %s", istr(tree_ident(value)));
4✔
402
      diag_printf(d, " slice %s index ", error);
4✔
403
      to_string(diag_text_buf(d), index_type, folded);
4✔
404
      diag_printf(d, " outside of %s range ", type_pp(index_type));
4✔
405
      format_type_range(d, index_type, dir, blow, bhigh);
4✔
406

407
      diag_emit(d);
4✔
408
   }
409
}
410

411
static void bounds_cover_choice(interval_t **isp, tree_t t, type_t type,
31,755✔
412
                                int64_t low, int64_t high)
413
{
414
   interval_t *it, *prev;
31,755✔
415
   for (it = *isp, prev = NULL;
31,755✔
416
        (it != NULL) && (it->low <= high);
34,754✔
417
        prev = it, it = it->next) {
2,999✔
418

419
      if ((low <= it->high) && (it->low <= high)) {
28,602✔
420
         const int64_t rlow  = MAX(low, it->low);
5✔
421
         const int64_t rhigh = MIN(high, it->high);
5✔
422
         if (type_is_integer(type)) {
5✔
423
            if (rlow == rhigh)
3✔
424
               bounds_error(t, "value %"PRIi64" is already covered", rlow);
2✔
425
            else
426
               bounds_error(t, "range %"PRIi64" to %"PRIi64" is already covered",
1✔
427
                            rlow, rhigh);
428
         }
429
         else if (type_is_enum(type)) {
2✔
430
            type_t base = type_base_recur(type);
2✔
431
            if (rlow == rhigh)
2✔
432
               bounds_error(t, "duplicate choice for %s",
2✔
433
                            istr(tree_ident(type_enum_literal(base, rlow))));
434
            else
435
               bounds_error(t, "duplicate choices for range %s to %s",
×
436
                            istr(tree_ident(type_enum_literal(base, rlow))),
437
                            istr(tree_ident(type_enum_literal(base, rhigh))));
438
         }
439
         it->low = MIN(low, it->low);
5✔
440
         it->high = MAX(high, it->high);
5✔
441
         return;
5✔
442
      }
443
      else if (high == it->low - 1) {
28,597✔
444
         it->low = low;
×
445
         return;
×
446
      }
447
      else if (low == it->high + 1) {
28,597✔
448
         it->high = high;
25,598✔
449
         return;
25,598✔
450
      }
451
   }
452

453
   interval_t *new = xmalloc(sizeof(interval_t));
6,152✔
454
   new->low  = low;
6,152✔
455
   new->high = high;
6,152✔
456

457
   if ((*isp == NULL) || (prev == NULL)) {
6,152✔
458
      new->next = *isp;
5,160✔
459
      *isp = new;
5,160✔
460
   }
461
   else {
462
      new->next = prev->next;
992✔
463
      prev->next = new;
992✔
464
   }
465
}
466

467
static void report_interval(diag_t *d, type_t type, range_kind_t dir,
33✔
468
                            int64_t low, int64_t high)
469
{
470
   if (low == high) {
33✔
471
      if (type_is_integer(type))
13✔
472
         diag_printf(d, "%"PRIi64, low);
6✔
473
      else if (type_is_enum(type)) {
7✔
474
         type_t base = type_base_recur(type);
7✔
475
         diag_printf(d, "%s", istr(tree_ident(type_enum_literal(base, low))));
7✔
476
      }
477
   }
478
   else
479
      format_type_range(d, type, dir, low, high);
20✔
480
}
33✔
481

482
static void bounds_check_missing_choices(tree_t t, type_t type,
3,702✔
483
                                         type_t index_type, range_kind_t dir,
484
                                         int64_t tlow, int64_t thigh,
485
                                         interval_t *covered)
486
{
487
   int missing = 0;
3,702✔
488
   interval_t *it;
3,702✔
489
   int64_t walk;
3,702✔
490

491
   for (it = covered, walk = tlow; it != NULL; it = it->next) {
8,053✔
492
      if (it->low != walk)
4,351✔
493
         missing += it->low - walk;
9✔
494
      walk = it->high + 1;
4,351✔
495
   }
496

497
   if (walk != thigh + 1)
3,702✔
498
      missing += (thigh + 1 - walk);
16✔
499

500
   if (missing == 0)
3,702✔
501
      return;
3,681✔
502

503
   // Allow downgrade to warning for case statement but not aggregates
504
   diag_t *d;
21✔
505
   if (index_type == NULL) {
21✔
506
      if ((d = pedantic_diag(tree_loc(t))) == NULL)
9✔
507
         return;
508
   }
509
   else
510
      d = diag_new(DIAG_ERROR, tree_loc(t));
12✔
511

512
   diag_printf(d, "missing choice%s for element%s ",
21✔
513
               missing > 1 ? "s" : "", missing > 1 ? "s" : "");
514

515
   int printed = 0;
21✔
516
   for (it = covered, walk = tlow; it != NULL; it = it->next) {
66✔
517
      if (it->low != walk) {
24✔
518
         if (printed++) diag_printf(d, ", ");
9✔
519
         report_interval(d, index_type ?: type, dir, walk, it->low - 1);
14✔
520
      }
521

522
      walk = it->high + 1;
24✔
523
   }
524

525
   if (walk != thigh + 1) {
21✔
526
      if (printed++) diag_printf(d, ", ");
16✔
527
      report_interval(d, index_type ?: type, dir, walk, thigh);
23✔
528
   }
529

530
   if (index_type == NULL)
21✔
531
      diag_printf(d, " of type %s", type_pp(type));
9✔
532
   else
533
      diag_printf(d, " of %s with index type %s", type_pp(type),
12✔
534
                  type_pp(index_type));
535

536
   type_t base = index_type ?: type;
21✔
537
   while (is_anonymous_subtype(base))
22✔
538
      base = type_base(base);
1✔
539

540
   int64_t rlow, rhigh;
21✔
541
   if (!folded_bounds(range_of(index_type ?: type, 0), &rlow, &rhigh))
21✔
542
      return;
543

544
   if (rlow != tlow || rhigh != thigh || !type_has_ident(index_type ?: type)) {
21✔
545
      diag_printf(d, " range ");
8✔
546
      report_interval(d, index_type ?: type, dir, tlow, thigh);
8✔
547
   }
548

549
   diag_emit(d);
21✔
550
}
551

552
static void bounds_free_intervals(interval_t **list)
5,772✔
553
{
554
   for (interval_t *it = *list, *tmp; it != NULL; it = tmp) {
11,924✔
555
      tmp = it->next;
6,152✔
556
      free(it);
6,152✔
557
   }
558
   *list = NULL;
5,772✔
559
}
5,772✔
560

561
static void bounds_check_aggregate(tree_t t)
9,220✔
562
{
563
   type_t type = tree_type(t);
9,220✔
564
   if (!type_is_array(type))
9,220✔
565
      return;
3,943✔
566

567
   // Find the tightest bounds for the index
568

569
   int64_t low, high, clow = 0, chigh = 0;
6,787✔
570
   type_t index_type = index_type_of(type, 0);
6,787✔
571
   range_kind_t dir;
6,787✔
572

573
   const bool unconstrained = type_is_unconstrained(type);
6,787✔
574

575
   if (unconstrained) {
6,787✔
576
      // Aggregate of unconstrained array type
577
      tree_t base_r = range_of(index_type, 0);
357✔
578
      if (!folded_bounds(base_r, &low, &high))
357✔
579
         return;
580

581
      clow = high, chigh = low;  // Actual bounds computed below
351✔
582
      dir = tree_subkind(base_r);
351✔
583
   }
584
   else {
585
      tree_t type_r = range_of(type, 0);
6,430✔
586
      if (!folded_bounds(type_r, &low, &high))
6,430✔
587
         return;
588

589
      clow = low, chigh = high;
4,926✔
590
      dir = tree_subkind(type_r);
4,926✔
591
   }
592

593
   const int ndims = dimension_of(type);
5,277✔
594
   type_t elem = type_elem(type);
5,277✔
595

596
   interval_t *covered = NULL;
5,277✔
597
   bool known_elem_count = true;
5,277✔
598
   int next_pos = 0;
5,277✔
599
   const int nassocs = tree_assocs(t);
5,277✔
600
   for (int i = 0; i < nassocs; i++) {
35,902✔
601
      tree_t a = tree_assoc(t, i), value = tree_value(a);
30,625✔
602
      int64_t ilow = 0, ihigh = 0, count = 1;
30,625✔
603
      const assoc_kind_t akind = tree_subkind(a);
30,625✔
604

605
      if (akind == A_SLICE || akind == A_CONCAT) {
30,625✔
606
         type_t value_type = tree_type(value);
189✔
607
         if (type_is_unconstrained(value_type))
189✔
608
            known_elem_count = false;
609
         else if (!folded_length(range_of(value_type, 0), &count))
162✔
610
            known_elem_count = false;
6✔
611
      }
612
      else if (type_is_scalar(elem))
30,436✔
613
         bounds_check_scalar(value, elem, NULL);
28,061✔
614
      else if (ndims == 1 && type_is_array(elem))
2,375✔
615
         bounds_check_array(value, elem, NULL);
1,644✔
616

617
      switch (akind) {
30,625✔
618
      case A_NAMED:
1,376✔
619
         {
620
            tree_t name = tree_name(a);
1,376✔
621
            if (!bounds_check_index(name, index_type, dir,
1,376✔
622
                                    "aggregate choice", low, high))
623
               known_elem_count = false;
4✔
624
            if (folded_int(name, &ilow))
1,376✔
625
               ihigh = ilow;
1,373✔
626
            else
627
               known_elem_count = false;
628
         }
629
         break;
630

631
      case A_RANGE:
672✔
632
      case A_SLICE:
633
         {
634
            tree_t r = tree_range(a, 0);
672✔
635
            const range_kind_t rkind = tree_subkind(r);
672✔
636
            if (rkind == RANGE_TO || rkind == RANGE_DOWNTO) {
672✔
637
               tree_t left = tree_left(r), right = tree_right(r);
507✔
638

639
               int64_t ileft, iright;
507✔
640
               if (folded_int(left, &ileft) && folded_int(right, &iright)) {
507✔
641
                  ilow = (rkind == RANGE_TO ? ileft : iright);
352✔
642
                  ihigh = (rkind == RANGE_TO ? iright : ileft);
352✔
643

644
                  // Cannot check either index unless both are known
645
                  // since the range may be null
646
                  if (ilow <= ihigh) {
352✔
647
                     if (!bounds_check_index(left, index_type, rkind,
335✔
648
                                             "aggregate choice", low, high))
649
                        known_elem_count = false;
2✔
650
                     if (!bounds_check_index(right, index_type, rkind,
335✔
651
                                             "aggregate choice", low, high))
652
                        known_elem_count = false;
2✔
653
                  }
654
                  else
655
                     known_elem_count = false;
656
               }
657
               else
658
                  known_elem_count = false;
659

660
               if (count > 1 && known_elem_count && ihigh - ilow + 1 != count)
507✔
661
                  bounds_error(a, "discrete range has %"PRIi64" elements but "
2✔
662
                               "length of expression is %"PRIi64,
663
                               ihigh - ilow + 1, count);
664
               else if (unconstrained && akind == A_SLICE && count > 1) {
505✔
665
                  // VHDL-2008 range association determines index
666
                  // direction for unconstrained aggregate
UNCOV
667
                  assert(standard() >= STD_08);
×
668
                  dir = rkind;
669
               }
670
            }
671
            else
672
               known_elem_count = false;
673
         }
674
         break;
675

676
      case A_OTHERS:
1,327✔
677
         known_elem_count = false;
1,327✔
678
         break;
1,327✔
679

680
      case A_POS:
27,250✔
681
      case A_CONCAT:
682
         if (dir == RANGE_TO) {
27,250✔
683
            ilow = low + next_pos;
26,571✔
684
            ihigh = ilow + count - 1;
26,571✔
685
         }
686
         else {
687
            ihigh = high - next_pos;
679✔
688
            ilow = ihigh - count + 1;
679✔
689
         }
690

691
         next_pos += count;
27,250✔
692

693
         if ((ilow < low || ihigh > high) && known_elem_count) {
27,250✔
694
            diag_t *d = diag_new(DIAG_ERROR, tree_loc(t));
7✔
695
            diag_printf(d, "expected at most %"PRIi64" positional "
7✔
696
                        "associations in %s aggregate with index type %s "
697
                        "range ", MAX(0, high - low + 1), type_pp(type),
7✔
698
                        type_pp(index_type));
699
            format_type_range(d, index_type, dir, low, high);
7✔
700
            diag_emit(d);
7✔
701

702
            known_elem_count = false;
7✔
703
         }
704
         break;
705
      }
706

707
      if (unconstrained) {
30,625✔
708
         clow = MIN(clow, ilow);
383✔
709
         chigh = MAX(chigh, ihigh);
383✔
710
      }
711

712
      if (known_elem_count)
30,625✔
713
         bounds_cover_choice(&covered, a, index_type, ilow, ihigh);
28,903✔
714
   }
715

716
   if (known_elem_count)
5,277✔
717
      bounds_check_missing_choices(t, type, index_type, dir, clow, chigh,
3,578✔
718
                                   covered);
719

720
   bounds_free_intervals(&covered);
5,277✔
721

722
   // Check each sub-aggregate has the same length for an unconstrained
723
   // array aggregate
724

725
   if (ndims > 1) {
5,277✔
726
      int64_t length = -1;
727
      for (int i = 0; i < nassocs; i++) {
1,194✔
728
         tree_t a = tree_assoc(t, i);
925✔
729
         type_t value_type = tree_type(tree_value(a));
925✔
730

731
         if (type_is_unconstrained(value_type))
925✔
732
            continue;
3✔
733

734
         int64_t this_length;
925✔
735
         if (!folded_length(range_of(value_type, 0), &this_length))
925✔
736
            continue;
3✔
737

738
         if (length == -1)
922✔
739
            length = this_length;
266✔
740
         else if (length != this_length)
656✔
741
            bounds_error(a, "length of sub-aggregate %"PRIi64" does not match "
922✔
742
                         "expected length %"PRIi64, this_length, length);
743
      }
744
   }
745
}
746

747
static void bounds_check_index_contraints(type_t type)
21,176✔
748
{
749
   if (type_kind(type) != T_SUBTYPE || !type_has_constraint(type))
21,176✔
750
      return;
2,104✔
751

752
   tree_t c0 = type_constraint(type);
19,072✔
753

754
   const constraint_kind_t kind = tree_subkind(c0);
19,072✔
755
   if (kind != C_INDEX && kind != C_RANGE)
19,072✔
756
      return;
757

758
   // Check folded range does not violate index constraints of base type
759

760
   const int ndims = dimension_of(type);
18,810✔
761
   for (int i = 0; i < ndims; i++) {
37,961✔
762
      tree_t dim = tree_range(c0, i);
19,151✔
763

764
      const range_kind_t dir = tree_subkind(dim);
19,151✔
765
      if (dir != RANGE_TO && dir != RANGE_DOWNTO)
19,151✔
766
         continue;
2,503✔
767

768
      type_t cons = kind == C_INDEX ? index_type_of(type, i) : type_base(type);
16,648✔
769
      if (type_kind(cons) == T_GENERIC)
16,648✔
770
         continue;   // Cannot check
3✔
771

772
      tree_t bounds = range_of(cons, 0);
16,645✔
773

774
      // Only check here if range can be determined to be non-null
775

776
      if (kind == C_RANGE && type_is_real(type)) {
16,645✔
777
         double dim_low, bounds_low;
34✔
778
         double dim_high, bounds_high;
34✔
779

780
         const bool is_static =
68✔
781
            folded_bounds_real(dim, &dim_low, &dim_high)
34✔
782
            && folded_bounds_real(bounds, &bounds_low, &bounds_high);
34✔
783

784
         if (!is_static)
34✔
785
            continue;
5✔
786

787
         const bool is_null =
58✔
788
            dim_low > dim_high || bounds_low > bounds_high;
29✔
789

790
         if (is_null)
29✔
UNCOV
791
            continue;
×
792

793
         if (dim_low < bounds_low)
29✔
794
            bounds_error(dir == RANGE_TO ? tree_left(dim) : tree_right(dim),
1✔
795
                         "%s index %g violates constraint %s",
796
                         dir == RANGE_TO ? "left" : "right",
797
                         dim_low, type_pp(cons));
798

799
         if (dim_high > bounds_high)
29✔
800
            bounds_error(dir == RANGE_TO ? tree_right(dim) : tree_left(dim),
29✔
801
                         "%s index %g violates constraint %s",
802
                         dir == RANGE_TO ? "right" : "left",
803
                         dim_high, type_pp(cons));
804

805
      }
806
      else {
807
         int64_t dim_low, bounds_low;
16,611✔
808
         int64_t dim_high, bounds_high;
16,611✔
809

810
         const bool is_static =
33,222✔
811
            folded_bounds(dim, &dim_low, &dim_high)
16,611✔
812
            && folded_bounds(bounds, &bounds_low, &bounds_high);
16,611✔
813

814
         if (!is_static)
16,611✔
815
            continue;
7,559✔
816

817
         const bool is_null =
18,538✔
818
            dim_low > dim_high || bounds_low > bounds_high;
9,269✔
819

820
         if (is_null)
9,269✔
821
            continue;
217✔
822

823
         if (type_is_enum(cons)) {
9,052✔
824
            if (dim_low < bounds_low) {
544✔
825
               type_t cons_base = type_base_recur(cons);
1✔
826
               tree_t lit = type_enum_literal(cons_base, (unsigned)dim_low);
1✔
827
               bounds_error(dir == RANGE_TO ? tree_left(dim) : tree_right(dim),
1✔
828
                            "%s index %s violates constraint %s",
829
                            dir == RANGE_TO ? "left" : "right",
830
                            istr(tree_ident(lit)), type_pp(cons));
831
            }
832

833
            if (dim_high > bounds_high) {
544✔
834
               type_t cons_base = type_base_recur(cons);
2✔
835
               tree_t lit = type_enum_literal(cons_base, (unsigned)dim_high);
2✔
836
               bounds_error(dir == RANGE_TO ? tree_right(dim) : tree_left(dim),
2✔
837
                            "%s index %s violates constraint %s",
838
                            dir == RANGE_TO ? "right" : "left",
839
                            istr(tree_ident(lit)), type_pp(cons));
840
            }
841
         }
842
         else if (dim_high > bounds_high)
8,508✔
843
            bounds_error(dir == RANGE_TO ? tree_right(dim) : tree_left(dim),
2✔
844
                         "%s index %"PRIi64" violates constraint %s",
845
                         dir == RANGE_TO ? "right" : "left",
846
                         dim_high, type_pp(cons));
847
         else if (dim_low < bounds_low)
8,506✔
848
            bounds_error(dir == RANGE_TO ? tree_left(dim) : tree_right(dim),
9,053✔
849
                         "%s index %"PRIi64" violates constraint %s",
850
                         dir == RANGE_TO ? "left" : "right",
851
                         dim_low, type_pp(cons));
852
      }
853
   }
854
}
855

856
static void bounds_check_assignment(tree_t target, tree_t value)
48,591✔
857
{
858
   type_t target_type = tree_type(target);
48,591✔
859

860
   if (type_is_scalar(target_type))
48,591✔
861
      bounds_check_scalar(value, target_type, target);
27,979✔
862
   else if (type_is_array(target_type))
20,612✔
863
      bounds_check_array(value, target_type, target);
16,613✔
864
}
48,591✔
865

866
static void bounds_check_object_decl(tree_t t)
26,761✔
867
{
868
   if (tree_has_value(t))
26,761✔
869
      bounds_check_assignment(t, tree_value(t));
10,857✔
870

871
   type_t type = tree_type(t);
26,761✔
872
   if (is_anonymous_subtype(type))
26,761✔
873
      bounds_check_index_contraints(type);
10,652✔
874
}
26,761✔
875

876
static void bounds_check_alias_decl(tree_t t)
2,969✔
877
{
878
   if (!tree_has_type(t))
2,969✔
879
      return;   // Alias declaration without subtype indication
880

881
   if (tree_has_value(t))
2,813✔
882
      bounds_check_assignment(t, tree_value(t));
2,813✔
883

884
   type_t type = tree_type(t);
2,813✔
885
   if (is_anonymous_subtype(type))
2,813✔
886
      bounds_check_index_contraints(type);
781✔
887
}
888

889
static void bounds_check_elem_constraint(tree_t t)
547✔
890
{
891
   type_t type = tree_type(t);
547✔
892
   if (is_anonymous_subtype(type))
547✔
893
      bounds_check_index_contraints(type);
547✔
894
}
547✔
895

896
static void bounds_check_type_decl(tree_t t)
4,362✔
897
{
898
   type_t type = tree_type(t);
4,362✔
899

900
   if (type_is_record(type)) {
4,362✔
901
      const int nfields = type_fields(type);
1,142✔
902
      for (int i = 0; i < nfields; i++) {
4,656✔
903
         type_t ft = tree_type(type_field(type, i));
3,514✔
904
         if (is_anonymous_subtype(ft))
3,514✔
905
            bounds_check_index_contraints(ft);
695✔
906
      }
907
   }
908
   else if (type_is_array(type)) {
3,220✔
909
      bounds_check_index_contraints(type);
2,334✔
910

911
      type_t elem = type_elem(type);
2,334✔
912
      if (is_anonymous_subtype(elem))
2,334✔
913
         bounds_check_index_contraints(elem);
159✔
914
   }
915
   else if (type_is_scalar(type)) {
886✔
916
      int64_t low, high;
522✔
917
      if (folded_bounds(range_of(type, 0), &low, &high) && low > high)
522✔
918
         warn_at(tree_loc(t), "type %s has null range", type_pp(type));
1✔
919
   }
920
}
4,362✔
921

922
static void bounds_check_subtype_decl(tree_t t)
1,378✔
923
{
924
   bounds_check_index_contraints(tree_type(t));
1,378✔
925
}
1,378✔
926

927
static void bounds_check_interface_decl(tree_t t)
109,791✔
928
{
929
   const class_t class = tree_class(t);
109,791✔
930
   if (class == C_FUNCTION || class == C_PROCEDURE || class == C_PACKAGE)
109,791✔
931
      return;
932

933
   const port_mode_t mode = tree_subkind(t);
108,065✔
934
   if (mode != PORT_ARRAY_VIEW && mode != PORT_RECORD_VIEW && tree_has_value(t))
108,065✔
935
      bounds_check_assignment(t, tree_value(t));
7,099✔
936

937
   type_t type = tree_type(t);
108,065✔
938
   if (is_anonymous_subtype(type))
108,065✔
939
      bounds_check_index_contraints(type);
4,630✔
940
}
941

942
static void bounds_check_signal_assign(tree_t t)
7,266✔
943
{
944
   int64_t last_delay = 0;
7,266✔
945
   tree_t target = tree_target(t);
7,266✔
946

947
   const int nwaves = tree_waveforms(t);
7,266✔
948
   for (int i = 0; i < nwaves; i++) {
14,752✔
949
      tree_t w = tree_waveform(t, i);
7,486✔
950

951
      if (tree_has_value(w))
7,486✔
952
         bounds_check_assignment(target, tree_value(w));
7,462✔
953

954
      int64_t delay = 0;
7,486✔
955
      bool delay_is_known = true;
7,486✔
956
      const bool has_delay = tree_has_delay(w);
7,486✔
957

958
      if (has_delay) {
7,486✔
959
         delay_is_known = folded_int(tree_delay(w), &delay);
863✔
960
         if (delay_is_known && delay < 0)
863✔
961
            bounds_error(tree_delay(w), "assignment delay may not be "
4✔
962
                         "negative");
963
      }
964

965
      if (i == 0) {
7,486✔
966
         int64_t rlimit;
7,260✔
967
         if (tree_has_reject(t) && folded_int(tree_reject(t), &rlimit)) {
7,260✔
968
            if ((rlimit < 0) && (delay >= 0))
584✔
969
               bounds_error(tree_reject(t), "rejection limit may not be "
1✔
970
                            "negative");
971

972
            if (rlimit > delay)
584✔
973
               bounds_error(tree_reject(t), "rejection limit may not be "
7,260✔
974
                            "greater than first assignment delay");
975
         }
976
      } else if (delay_is_known && delay <= last_delay)
226✔
977
         bounds_error(has_delay ? tree_delay(w) : w, "assignment delays "
5✔
978
                      "must be in ascending time order");
979

980
      // even if the delay isn't known, it has to be at least zero
981
      last_delay = delay;
7,486✔
982
   }
983
}
7,266✔
984

985
static void bounds_check_var_assign(tree_t t)
20,360✔
986
{
987
   bounds_check_assignment(tree_target(t), tree_value(t));
20,360✔
988
}
20,360✔
989

990
static void bounds_check_scalar_case(tree_t t, type_t type, bool matching)
495✔
991
{
992
   // Check that the full range of the type is covered
993

994
   tree_t type_r = range_of(type, 0);
495✔
995

996
   int64_t tlow = INT64_MIN, thigh = INT64_MAX;
495✔
997
   while (!folded_bounds(type_r, &tlow, &thigh)
495✔
998
          && type_kind(type) == T_SUBTYPE) {
496✔
999
      // LRM 08 section 10.9: if the case expression does not have a
1000
      // locally static subtype then the choices must cover every value
1001
      // of the base type
1002
      type = type_base(type);
1✔
1003
      type_r = range_of(type, 0);
1✔
1004
   }
1005

1006
   const range_kind_t tdir = tree_subkind(type_r);
495✔
1007

1008
   bool have_others = false;
495✔
1009
   interval_t *covered = NULL;
495✔
1010

1011
   const int nstmts = tree_stmts(t);
495✔
1012
   for (int i = 0; i < nstmts; i++) {
2,894✔
1013
      tree_t alt = tree_stmt(t, i);
2,399✔
1014

1015
      const int nassocs = tree_assocs(alt);
2,399✔
1016
      for (int j = 0; j < nassocs; j++) {
5,623✔
1017
         tree_t a = tree_assoc(alt, j);
3,224✔
1018

1019
         int64_t low = INT64_MIN, high = INT64_MAX;
3,224✔
1020
         switch (tree_subkind(a)) {
3,224✔
1021
         case A_OTHERS:
363✔
1022
            have_others = true;
363✔
1023
            continue;
363✔
1024

1025
         case A_NAMED:
2,825✔
1026
            {
1027
               int64_t pos;
2,825✔
1028
               tree_t name = tree_name(a);
2,825✔
1029
               if (!bounds_check_index(name, type, tdir, "case choice",
2,825✔
1030
                                       tlow, thigh))
1031
                  have_others = true;
1032
               else if (matching && folded_int(name, &pos) && pos == 8)
2,824✔
1033
                  have_others = true;    // Has a '-' choice
1034
               else
1035
                  low = high = assume_int(tree_name(a));
2,818✔
1036
            }
1037
            break;
2,825✔
1038

1039
         case A_RANGE:
36✔
1040
            {
1041
               tree_t r = tree_range(a, 0);
36✔
1042
               const range_kind_t dir = tree_subkind(r);
36✔
1043

1044
               if (dir == RANGE_EXPR)
36✔
UNCOV
1045
                  fatal_at(tree_loc(r), "locally static range not folded");
×
1046

1047
               tree_t left = tree_left(r);
36✔
1048
               tree_t right = tree_right(r);
36✔
1049

1050
               if (!bounds_check_index(left, type, dir, "case choice",
36✔
1051
                                       tlow, thigh))
1052
                  have_others = true;
1✔
1053
               if (!bounds_check_index(right, type, dir, "case choice",
36✔
1054
                                       tlow, thigh))
UNCOV
1055
                  have_others = true;
×
1056

1057
               low = assume_int(dir == RANGE_TO ? left : right);
39✔
1058
               high = assume_int(dir == RANGE_TO ? right : left);
36✔
1059
            }
1060
            break;
36✔
1061
         }
1062

1063
         if (!have_others)
2,861✔
1064
            bounds_cover_choice(&covered, a, type, low, high);
2,852✔
1065
      }
1066
   }
1067

1068
   if (!have_others)
495✔
1069
      bounds_check_missing_choices(t, type, NULL, direction_of(type, 0),
124✔
1070
                                   tlow, thigh, covered);
1071

1072
   bounds_free_intervals(&covered);
495✔
1073
}
495✔
1074

1075
static void bounds_check_duplicate_choice(tree_t old, tree_t new, int length)
2✔
1076
{
1077
   for (int i = 0; i < length; i++) {
13✔
1078
      if (get_case_choice_char(old, i) != get_case_choice_char(new, i))
11✔
1079
         return;
1080
   }
1081

1082
   diag_t *d = diag_new(DIAG_ERROR, tree_loc(new));
2✔
1083
   diag_printf(d, "duplicate choice in case statement");
2✔
1084
   diag_hint(d, tree_loc(new), "repeated here");
2✔
1085
   diag_hint(d, tree_loc(old), "previous choice for this value");
2✔
1086
   diag_hint(d, NULL, "each value of the subtype of the expression must be "
2✔
1087
             "represented once and only once in the set of choices");
1088
   diag_lrm(d, STD_93, "8.8");
2✔
1089
   diag_emit(d);
2✔
1090
}
1091

1092
static void bounds_check_array_case(tree_t t, type_t type, bool matching)
129✔
1093
{
1094
   type_t elem = type_elem(type);
129✔
1095
   assert(type_is_enum(elem));
129✔
1096

1097
   // Calculate how many values each element has
1098
   int64_t elemsz = INT64_MAX;
129✔
1099
   while (!folded_length(range_of(elem, 0), &elemsz)
258✔
1100
          && type_kind(elem) == T_SUBTYPE)
258✔
UNCOV
1101
      elem = type_base(elem);
×
1102

1103
   int64_t expect = -1, length = -1;
129✔
1104

1105
   const bool known_length =
258✔
1106
      !type_is_unconstrained(type) && folded_length(range_of(type, 0), &length);
129✔
1107

1108
   if (known_length && !ipow_safe(elemsz, length, &expect))
129✔
1109
      expect = INT64_MAX;   // Overflow
4✔
1110

1111
   int nchoices = 0;
129✔
1112
   const int nstmts = tree_stmts(t);
129✔
1113
   for (int i = 0; i < nstmts; i++)
872✔
1114
      nchoices += tree_assocs(tree_stmt(t, i));
743✔
1115

1116
   int64_t have = 0;
129✔
1117
   int64_t *hashes LOCAL = xmalloc_array(nchoices, sizeof(int64_t));
258✔
1118
   tree_t *choices LOCAL = xmalloc_array(nchoices, sizeof(tree_t));
258✔
1119
   int hptr = 0;
129✔
1120

1121
   for (int i = 0; i < nstmts; i++) {
869✔
1122
      tree_t alt = tree_stmt(t, i);
741✔
1123

1124
      const int nassocs = tree_assocs(alt);
741✔
1125
      for (int j = 0; j < nassocs; j++, hptr++) {
1,515✔
1126
         tree_t a = tree_assoc(alt, j);
775✔
1127
         hashes[hptr] = INT64_MAX;
775✔
1128
         choices[hptr] = NULL;
775✔
1129

1130
         if (tree_subkind(a) == A_OTHERS) {
775✔
1131
            have = expect;
110✔
1132
            continue;
123✔
1133
         }
1134

1135
         assert(tree_subkind(a) == A_NAMED);
665✔
1136
         tree_t name = choices[hptr] = tree_name(a);
665✔
1137

1138
         int64_t covered = 1, pos;
665✔
1139
         if (matching && tree_kind(name) == T_STRING) {
665✔
1140
            const int nchars = tree_chars(name);
83✔
1141
            for (int i = 0; i < nchars; i++) {
368✔
1142
               if (folded_int(tree_char(name, i), &pos) && pos == 8)
285✔
1143
                  covered *= 9;    // Has a '-' choice
110✔
1144
            }
1145
         }
1146
         have += covered;
665✔
1147

1148
         type_t choice_type = tree_type(name);
665✔
1149
         if (type_is_unconstrained(choice_type))
665✔
1150
            continue;
13✔
1151

1152
         int64_t choice_length;
652✔
1153
         if (folded_length(range_of(choice_type, 0), &choice_length)) {
652✔
1154
            if (length == -1) {
652✔
1155
               length = choice_length;
20✔
1156
               if (!ipow_safe(elemsz, length, &expect))
20✔
1157
                  expect = INT64_MAX;
3✔
1158
            }
1159
            else if (choice_length != length) {
632✔
1160
               diag_t *d = diag_new(DIAG_ERROR, tree_loc(name));
1✔
1161
               diag_printf(d, "expected case choice to have length %"PRIi64
1✔
1162
                           " but is %"PRIi64, length, choice_length);
1163
               diag_hint(d, NULL, "the values of all choices for a case "
1✔
1164
                         "expression with one-dimensional character array "
1165
                         "type must have the same length");
1166
               diag_lrm(d, STD_08, "10.9");
1✔
1167
               diag_emit(d);
1✔
1168
               return;
1✔
1169
            }
1170

1171
            hashes[hptr] = encode_case_choice(name, choice_length, 0);
651✔
1172

1173
            for (int k = 0; k < hptr; k++) {
3,773✔
1174
               if (hashes[k] == INT64_MAX)
3,122✔
1175
                  continue;
18✔
1176
               else if (hashes[hptr] == hashes[k]) {
3,104✔
1177
                  tree_t old = choices[k];
2✔
1178
                  bounds_check_duplicate_choice(old, name, choice_length);
2✔
1179
               }
1180
            }
1181
         }
1182
      }
1183
   }
1184

1185
   if (have < expect && expect != -1) {
128✔
1186
      const loc_t *loc = tree_loc(tree_value(t));
6✔
1187
      diag_t *d = pedantic_diag(loc);
6✔
1188
      if (d != NULL) {
6✔
1189
         diag_printf(d, "choices cover only %"PRIi64" of ", have);
6✔
1190
         if (expect > 100000)
6✔
1191
            diag_printf(d, "%"PRIi64" ** %"PRIi64, elemsz, length);
3✔
1192
         else
1193
            diag_printf(d, "%"PRIi64, expect);
3✔
1194
         diag_printf(d, " possible values");
6✔
1195

1196
         diag_hint(d, loc, "expression has %"PRIi64" elements of type %s, "
6✔
1197
                   "each of which has %"PRIi64" possible values",
1198
                   length, type_pp(type_elem(type)), elemsz);
1199

1200
         if (!known_length)
6✔
1201
            diag_hint(d, NULL, "the case expression subtype is not locally "
2✔
1202
                      "static so the length was derived from the choices");
1203

1204
         diag_emit(d);
6✔
1205
      }
1206
   }
1207
}
1208

1209
static void bounds_check_case(tree_t t)
585✔
1210
{
1211
   type_t type = tree_type(tree_value(t));
585✔
1212

1213
   if (type_is_scalar(type))
585✔
1214
      bounds_check_scalar_case(t, type, false);
489✔
1215
   else if (type_is_array(type))
96✔
1216
      bounds_check_array_case(t, type, false);
96✔
1217
}
585✔
1218

1219
static void bounds_check_match_case(tree_t t)
39✔
1220
{
1221
   type_t type = tree_type(tree_value(t)), elem = type_elem_recur(type);
39✔
1222

1223
   const bool matching = type_eq(elem, ieee_type(IEEE_STD_ULOGIC));
39✔
1224

1225
   if (type_is_scalar(type))
39✔
1226
      bounds_check_scalar_case(t, type, matching);
6✔
1227
   else if (type_is_array(type))
33✔
1228
      bounds_check_array_case(t, type, matching);
33✔
1229
}
39✔
1230

1231
static void bounds_check_conv_integer(tree_t value, type_t from, type_t to)
154✔
1232
{
1233
   int64_t ival = 0;
154✔
1234
   double rval = 0.0;
154✔
1235
   bool folded = false;
154✔
1236
   if (type_is_real(from)) {
154✔
1237
      folded = folded_real(value, &rval);
100✔
1238
      ival = (int64_t)(rval + 0.5);
100✔
1239
   }
1240
   else if (type_is_integer(from))
54✔
1241
      folded = folded_int(value, &ival);
54✔
1242

1243
   if (folded) {
154✔
1244
      int64_t b_low, b_high;
2✔
1245
      if (folded_bounds(range_of(to, 0), &b_low, &b_high)
2✔
1246
          && (ival < b_low || ival > b_high)) {
2✔
1247
         char *argstr LOCAL = type_is_real(from)
2✔
1248
            ? xasprintf("%lg", rval) : xasprintf("%"PRIi64, ival);
2✔
1249
         bounds_error(value, "type conversion argument %s out of "
2✔
1250
                      "bounds %"PRIi64" to %"PRIi64, argstr, b_low, b_high);
1251
      }
1252
   }
1253
}
154✔
1254

1255
static void bounds_check_conv_array(tree_t value, type_t from, type_t to)
2,658✔
1256
{
1257
   const int ndims = dimension_of(to);
2,658✔
1258
   assert(ndims == dimension_of(from));
2,658✔
1259

1260
   const bool to_constrained = !type_is_unconstrained(to);
2,658✔
1261
   const bool from_constrained = !type_is_unconstrained(from);
2,658✔
1262

1263
   if (to_constrained && from_constrained) {
2,658✔
1264
      for (int i = 0; i < ndims; i++) {
46✔
1265
         tree_t r_to = range_of(to, i);
23✔
1266
         tree_t r_from = range_of(from, i);
23✔
1267

1268
         int64_t to_length;
23✔
1269
         if (!folded_length(r_to, &to_length))
23✔
1270
            continue;
6✔
1271

1272
         int64_t from_length;
20✔
1273
         if (!folded_length(r_from, &from_length))
20✔
1274
            continue;
3✔
1275

1276
         if (to_length != from_length)
17✔
1277
            bounds_error(value, "length of type conversion argument %"PRIi64
17✔
1278
                         " does not match expected length %"PRIi64
1279
                         " for constrained array subtype %s",
1280
                         from_length, to_length, type_pp(to));
1281
      }
1282
   }
1283
   else if (!to_constrained && from_constrained) {
2,635✔
1284
      for (int i = 0; i < ndims; i++) {
1,118✔
1285
         type_t index_type = index_type_of(to, i);
559✔
1286
         tree_t r_to = range_of(index_type, i);
559✔
1287
         tree_t r_from = range_of(from, i);
559✔
1288

1289
         if (tree_subkind(r_from) == RANGE_EXPR)
559✔
1290
            continue;
483✔
1291

1292
         int64_t low, high;
444✔
1293
         if (!folded_bounds(r_to, &low, &high))
444✔
UNCOV
1294
            continue;
×
1295

1296
         int64_t f_low, f_high;
444✔
1297
         if (!folded_bounds(r_from, &f_low, &f_high))
444✔
1298
            continue;
367✔
1299
         else if (f_low > f_high)
77✔
1300
            continue;  // Null range
1✔
1301

1302
         int64_t folded = 0;
76✔
1303
         const char *error = NULL;
76✔
1304
         if (!index_in_range(tree_left(r_from), low, high, &folded))
76✔
1305
            error = "left";
1306
         else if (!index_in_range(tree_right(r_from), low, high, &folded))
76✔
1307
            error = "right";
1308

1309
         if (error) {
1✔
1310
            diag_t *d = diag_new(DIAG_ERROR, tree_loc(value));
1✔
1311
            diag_printf(d, "array ");
1✔
1312
            if (tree_kind(value) == T_REF)
1✔
1313
               diag_printf(d, "%s ", istr(tree_ident(value)));
1✔
1314
            diag_printf(d, "%s bound ", error);
1✔
1315
            to_string(diag_text_buf(d), index_type, folded);
1✔
1316
            diag_printf(d, " violates %s index constraint ", type_pp(to));
1✔
1317
            format_type_range(d, index_type, tree_subkind(r_to), low, high);
1✔
1318
            diag_emit(d);
1✔
1319
         }
1320
      }
1321
   }
1322
}
2,658✔
1323

1324
static void bounds_check_type_conv(tree_t t)
3,011✔
1325
{
1326
   tree_t value = tree_value(t);
3,011✔
1327

1328
   type_t from = tree_type(value);
3,011✔
1329
   type_t to   = tree_type(t);
3,011✔
1330

1331
   if (type_is_integer(to))
3,011✔
1332
      bounds_check_conv_integer(value, from, to);
154✔
1333
   else if (type_is_array(to))
2,857✔
1334
      bounds_check_conv_array(value, from, to);
2,658✔
1335
}
3,011✔
1336

1337
static void bounds_check_attr_ref(tree_t t)
26,761✔
1338
{
1339
   const attr_kind_t predef = tree_subkind(t);
26,761✔
1340
   switch (predef) {
26,761✔
1341
   case ATTR_LENGTH:
22,881✔
1342
   case ATTR_LOW:
1343
   case ATTR_HIGH:
1344
   case ATTR_LEFT:
1345
   case ATTR_RIGHT:
1346
   case ATTR_RANGE:
1347
   case ATTR_REVERSE_RANGE:
1348
      if (tree_params(t) > 0) {
22,881✔
1349
         type_t type = tree_type(tree_name(t));
94✔
1350
         if (type_is_array(type)) {
94✔
1351
            tree_t dim_tree = tree_value(tree_param(t, 0));
94✔
1352

1353
            int64_t dim;
94✔
1354
            if (!folded_int(dim_tree, &dim))
94✔
UNCOV
1355
               bounds_error(dim_tree, "dimension is not constant");
×
1356
            else if (dim < 1 || dim > dimension_of(type))
94✔
1357
               bounds_error(dim_tree, "invalid dimension %"PRIi64" for type %s",
94✔
1358
                            dim, type_pp(type));
1359
         }
1360
      }
1361
      break;
1362

1363
   default:
1364
      break;
1365
   }
1366
}
26,761✔
1367

1368
static void bounds_check_wait(tree_t t)
12,193✔
1369
{
1370
   int64_t delay = 0;
12,193✔
1371
   if (tree_has_delay(t) && folded_int(tree_delay(t), &delay) && delay < 0)
12,193✔
1372
      bounds_error(tree_delay(t), "wait timeout may not be negative");
12,193✔
1373
}
12,193✔
1374

1375
static tree_t bounds_visit_fn(tree_t t, void *context)
1,538,769✔
1376
{
1377
   switch (tree_kind(t)) {
1,538,769✔
1378
   case T_PCALL:
95,847✔
1379
   case T_FCALL:
1380
      bounds_check_call_args(t);
95,847✔
1381
      break;
95,847✔
1382
   case T_ARRAY_REF:
15,842✔
1383
      bounds_check_array_ref(t);
15,842✔
1384
      break;
15,842✔
1385
   case T_ARRAY_SLICE:
2,885✔
1386
      bounds_check_array_slice(t);
2,885✔
1387
      break;
2,885✔
1388
   case T_AGGREGATE:
9,220✔
1389
      bounds_check_aggregate(t);
9,220✔
1390
      break;
9,220✔
1391
   case T_SIGNAL_DECL:
26,761✔
1392
   case T_CONST_DECL:
1393
   case T_VAR_DECL:
1394
      bounds_check_object_decl(t);
26,761✔
1395
      break;
26,761✔
1396
   case T_PORT_DECL:
109,791✔
1397
   case T_PARAM_DECL:
1398
   case T_GENERIC_DECL:
1399
      bounds_check_interface_decl(t);
109,791✔
1400
      break;
109,791✔
1401
   case T_ALIAS:
2,969✔
1402
      bounds_check_alias_decl(t);
2,969✔
1403
      break;
2,969✔
1404
   case T_SIGNAL_ASSIGN:
7,266✔
1405
      bounds_check_signal_assign(t);
7,266✔
1406
      break;
7,266✔
1407
   case T_VAR_ASSIGN:
20,360✔
1408
      bounds_check_var_assign(t);
20,360✔
1409
      break;
20,360✔
1410
   case T_CASE:
585✔
1411
      bounds_check_case(t);
585✔
1412
      break;
585✔
1413
   case T_MATCH_CASE:
39✔
1414
      bounds_check_match_case(t);
39✔
1415
      break;
39✔
1416
   case T_STRING:
23,969✔
1417
      bounds_check_string_literal(t);
23,969✔
1418
      break;
23,969✔
1419
   case T_TYPE_CONV:
3,011✔
1420
      bounds_check_type_conv(t);
3,011✔
1421
      break;
3,011✔
1422
   case T_ATTR_REF:
26,761✔
1423
      bounds_check_attr_ref(t);
26,761✔
1424
      break;
26,761✔
1425
   case T_WAIT:
12,193✔
1426
      bounds_check_wait(t);
12,193✔
1427
      break;
12,193✔
1428
   case T_ELEM_CONSTRAINT:
547✔
1429
      bounds_check_elem_constraint(t);
547✔
1430
      break;
547✔
1431
   case T_TYPE_DECL:
4,362✔
1432
      bounds_check_type_decl(t);
4,362✔
1433
      break;
4,362✔
1434
   case T_SUBTYPE_DECL:
1,378✔
1435
      bounds_check_subtype_decl(t);
1,378✔
1436
      break;
1,378✔
1437
   default:
1438
      break;
1439
   }
1440

1441
   return t;
1,538,769✔
1442
}
1443

1444
void bounds_check(tree_t top)
11,259✔
1445
{
1446
   tree_rewrite(top, NULL, bounds_visit_fn, NULL, NULL);
11,259✔
1447
}
11,259✔
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