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

nickg / nvc / 14430972582

13 Apr 2025 03:46PM UTC coverage: 92.302% (-0.008%) from 92.31%
14430972582

push

github

nickg
Add a test for errors in default value

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

144 existing lines in 4 files now uncovered.

68983 of 74736 relevant lines covered (92.3%)

417996.71 hits per line

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

98.02
/src/bounds.c
1
//
2
//  Copyright (C) 2011-2025  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,934✔
44
{
45
   type_t type = tree_type(t);
23,934✔
46
   assert(!type_is_unconstrained(type));
23,934✔
47

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

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

59
   if (dir == RANGE_DOWNTO) {
79✔
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);
62✔
66
      tb_cat(tb, " to ");
62✔
67
      to_string(tb, type, high);
62✔
68
   }
69
}
79✔
70

71
static void add_hint_string(diag_t *d, tree_t where)
38✔
72
{
73
   const char *what = "";
38✔
74
   switch (tree_kind(where)) {
38✔
75
   case T_VAR_DECL:
19✔
76
   case T_SIGNAL_DECL:
77
   case T_CONST_DECL:
78
   case T_REF:          what = class_str(class_of(where)); break;
19✔
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;
4✔
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)));
35✔
87
}
88

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

94
   tree_t r = range_of(type, 0);
204,694✔
95

96
   bool error = false;
204,694✔
97
   int64_t low, high, folded;
204,694✔
98
   double rlow, rhigh;
204,694✔
99
   if (folded_bounds(r, &low, &high)) {
204,694✔
100
      if (folded_int(value, &folded))
178,890✔
101
         error = (folded < low || folded > high);
132,017✔
102
   }
103
   else if (folded_bounds_real(r, &rlow, &rhigh)) {
25,804✔
104
      double folded_f;
25,712✔
105
      if (folded_real(value, &folded_f)) {
25,712✔
106
         error  = (folded_f < rlow || folded_f > rhigh);
17,591✔
107
         folded = FLOAT_BITS(folded_f);
17,591✔
108
         low    = FLOAT_BITS(rlow);
17,591✔
109
         high   = FLOAT_BITS(rhigh);
17,591✔
110
      }
111
   }
112

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

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

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

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

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

136
   const int ndims = dimension_of(type);
11,562✔
137
   for (int i = 0; i < ndims; i++) {
24,460✔
138
      int64_t target_w, value_w;
12,898✔
139
      if (!folded_length(range_of(type, i), &target_w))
12,898✔
140
         continue;
2,596✔
141
      else if (!folded_length(range_of(value_type, i), &value_w))
10,344✔
142
         continue;
42✔
143
      else if (target_w != value_w) {
10,302✔
144
         diag_t *d = diag_new(DIAG_ERROR, tree_loc(value));
15✔
145
         diag_printf(d, "length of ");
15✔
146
         if (i > 0)
15✔
147
            diag_printf(d, "dimension %d of ", i + 1);
×
148
         diag_printf(d, "value %"PRIi64" does not match length of target %"
15✔
149
                     PRIi64, value_w, target_w);
150
         if (hint != NULL)
15✔
151
            add_hint_string(d, hint);
13✔
152

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

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

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

165
   bool known_arg_length = true;
92,028✔
166

167
   for (int i = 0; (i < nparams) && (i < nports); i++) {
281,783✔
168
      tree_t param = tree_param(t, i), port;
189,755✔
169
      switch (tree_subkind(param)) {
189,755✔
170
      case P_POS:
189,755✔
171
         port = tree_port(decl, tree_pos(param));
189,755✔
172
         break;
189,755✔
UNCOV
173
      case P_NAMED:
×
UNCOV
174
         port = tree_ref(name_to_ref(tree_name(param)));
×
UNCOV
175
         break;
×
UNCOV
176
      default:
×
177
         should_not_reach_here();
178
      }
179
      assert(tree_kind(port) == T_PARAM_DECL);
189,755✔
180

181
      tree_t value = tree_value(param);
189,755✔
182

183
      type_t ftype = tree_type(port);
189,755✔
184
      type_t atype = tree_type(value);
189,755✔
185

186
      if (type_is_array(ftype)) {
189,755✔
187
         // Check bounds of constrained array parameters
188

189
         if (type_is_unconstrained(atype)) {
43,506✔
190
            known_arg_length = false;
18,051✔
191
            continue;
18,051✔
192
         }
193
         else if (type_is_unconstrained(ftype))
25,455✔
194
            continue;
24,399✔
195

196
         const int ndims = dimension_of(ftype);
1,056✔
197

198
         for (int j = 0; j < ndims; j++) {
2,192✔
199
            tree_t formal_r = range_of(ftype, j);
1,136✔
200
            tree_t actual_r = range_of(atype, j);
1,136✔
201

202
            int64_t f_len, a_len;
1,136✔
203
            if (!folded_length(formal_r, &f_len))
1,136✔
204
               continue;
28✔
205
            else if (!folded_length(actual_r, &a_len)) {
1,133✔
206
               known_arg_length = false;
25✔
207
               continue;
25✔
208
            }
209

210
            if (f_len != a_len) {
1,108✔
211
               diag_t *d = diag_new(DIAG_ERROR, tree_loc(param));
3✔
212
               diag_printf(d, "actual length %"PRIi64, a_len);
3✔
213
               if (ndims > 1)
3✔
214
                  diag_printf(d, " for dimension %d", j + 1);
1✔
215
               diag_printf(d, " does not match formal length %"PRIi64
3✔
216
                           " for parameter %s", f_len, istr(tree_ident(port)));
217
               diag_emit(d);
3✔
218
            }
219
         }
220
      }
221
      else if (type_is_scalar(ftype))
146,249✔
222
         bounds_check_scalar(value, ftype, port);
138,404✔
223
   }
224

225
   if (tree_kind(decl) == T_GENERIC_DECL)
92,028✔
226
      return t;
227

228
   const subprogram_kind_t kind = tree_subkind(decl);
91,714✔
229
   if (known_arg_length && (kind == S_ARRAY_EQ || kind == S_ARRAY_NEQ)) {
91,714✔
230
      // Warn if calling the predefined array equality operators and the
231
      // left and right hand sides have different lengths as this always
232
      // returns FALSE
233

234
      type_t ltype = tree_type(tree_value(tree_param(t, 0)));
3,432✔
235
      type_t rtype = tree_type(tree_value(tree_param(t, 1)));
3,432✔
236

237
      const int ndims = dimension_of(ltype);
3,432✔
238
      for (int i = 0; i < ndims; i++) {
7,356✔
239
         tree_t left_r = range_of(ltype, i);
3,936✔
240
         tree_t right_r = range_of(rtype, i);
3,936✔
241

242
         int64_t left_len;
3,936✔
243
         if (!folded_length(left_r, &left_len))
3,936✔
244
            continue;
435✔
245

246
         int64_t right_len;
3,501✔
247
         if (!folded_length(right_r, &right_len))
3,501✔
UNCOV
248
            continue;
×
249

250
         if (left_len != right_len) {
3,501✔
251
            diag_t *d = diag_new(DIAG_WARN, tree_loc(t));
12✔
252
            diag_printf(d, "call to predefined operator %s always returns "
12✔
253
                        "FALSE", istr(tree_ident(t)));
254
            diag_hint(d, tree_loc(t), "left length is %"PRIi64" but right "
12✔
255
                      "length is %"PRIi64, left_len, right_len);
256
            diag_emit(d);
12✔
257
            break;
12✔
258
         }
259
      }
260
   }
261

262
   return t;
263
}
264

265
static bool index_in_range(tree_t index, int64_t low, int64_t high,
6,480✔
266
                           int64_t *value)
267
{
268
   int64_t folded;
6,480✔
269
   if (folded_int(index, &folded)) {
6,480✔
270
      *value = folded;
6,477✔
271
      return folded >= low && folded <= high;
6,492✔
272
   }
273

274
   return true;
275
}
276

277
static bool bounds_check_index(tree_t index, type_t type, range_kind_t kind,
4,943✔
278
                               const char *what, int64_t low, int64_t high)
279
{
280
   int64_t folded;
4,943✔
281
   if (!index_in_range(index, low, high, &folded) && low <= high) {
4,943✔
282
      diag_t *d = diag_new(DIAG_ERROR, tree_loc(index));
10✔
283
      diag_printf(d, "%s index ", what);
10✔
284
      to_string(diag_text_buf(d), type, folded);
10✔
285
      diag_printf(d, " outside of %s range ", type_pp(type));
10✔
286
      format_type_range(d, type, kind, low, high);
10✔
287
      diag_emit(d);
10✔
288

289
      return false;
10✔
290
   }
291

292
   return true;
293
}
294

295
static void bounds_check_array_ref(tree_t t)
15,807✔
296
{
297
   tree_t value = tree_value(t);
15,807✔
298

299
   if (!tree_has_type(value))
15,807✔
300
      return;
301
   else if (tree_flags(t) & TREE_F_ELIDE_BOUNDS)
15,807✔
302
      return;
303

304
   type_t value_type = tree_type(value);
15,548✔
305

306
   const bool unconstrained = type_is_unconstrained(value_type);
15,548✔
307
   const bool value_is_ref = tree_kind(value) == T_REF;
15,548✔
308

309
   int nstatic = 0;
15,548✔
310
   const int nparams = tree_params(t);
15,548✔
311
   for (int i = 0; i < nparams; i++) {
32,719✔
312
      tree_t p = tree_param(t, i);
17,171✔
313
      tree_t pvalue = tree_value(p);
17,171✔
314
      bool checked = false;
17,171✔
315

316
      if (!unconstrained) {
17,171✔
317
         tree_t r = range_of(value_type, i);
13,693✔
318
         type_t index_type = index_type_of(value_type, i);
13,693✔
319
         const range_kind_t dir = tree_subkind(r);
13,693✔
320

321
         int64_t ivalue, low, high;
13,693✔
322
         if (folded_int(pvalue, &ivalue) && folded_bounds(r, &low, &high)) {
13,693✔
323
            checked = true;
5,625✔
324

325
            if (ivalue < low || ivalue > high) {
5,625✔
326
               diag_t *d = diag_new(DIAG_ERROR, tree_loc(pvalue));
11✔
327
               diag_printf(d, "array");
11✔
328
               if (tree_kind(value) == T_REF)
11✔
329
                  diag_printf(d, " %s", istr(tree_ident(value)));
10✔
330
               diag_printf(d, " index ");
11✔
331
               to_string(diag_text_buf(d), index_type, ivalue);
11✔
332
               diag_printf(d, " outside of %s range ", type_pp(index_type));
11✔
333
               format_type_range(d, index_type, dir, low, high);
11✔
334

335
               diag_emit(d);
11✔
336
            }
337
         }
338
      }
339

340
      if (value_is_ref && nparams == 1 && tree_kind(pvalue) == T_REF) {
17,171✔
341
         // Automatically elide bounds check in cases like
342
         //
343
         //   for i in x'range loop
344
         //     y := a(x);  -- Always in bounds
345

346
         type_t ptype = tree_type(pvalue);
7,129✔
347
         if (type_kind(ptype) == T_SUBTYPE && type_has_constraint(ptype)) {
7,129✔
348
            tree_t c = type_constraint(ptype);
5,554✔
349
            if (tree_subkind(c) == C_RANGE) {
5,554✔
350
               tree_t r = tree_range(c, 0);
5,554✔
351
               if (tree_subkind(r) == RANGE_EXPR) {
5,554✔
352
                  tree_t r_attr = tree_value(r);
2,117✔
353
                  assert(tree_kind(r_attr) == T_ATTR_REF);
2,117✔
354
                  tree_t r_base = tree_name(r_attr);
2,117✔
355
                  checked |= (tree_kind(r_base) == T_REF &&
5,161✔
356
                              tree_ref(r_base) == tree_ref(value));
2,116✔
357
               }
358
            }
359
         }
360
      }
361

362
      if (checked)
17,171✔
363
         nstatic++;
6,813✔
364
   }
365

366
   if (nstatic == nparams)
15,548✔
367
      tree_set_flag(t, TREE_F_ELIDE_BOUNDS);
5,680✔
368
}
369

370
static void bounds_check_array_slice(tree_t t)
2,890✔
371
{
372
   tree_t value = tree_value(t);
2,890✔
373

374
   if (!tree_has_type(value))
2,890✔
375
      return;
2,199✔
376

377
   type_t value_type = tree_type(value);
2,890✔
378

379
   if (type_is_unconstrained(value_type))
2,890✔
380
      return;
381

382
   tree_t b = range_of(value_type, 0);
2,634✔
383
   tree_t r = tree_range(t, 0);
2,634✔
384

385
   int64_t blow, bhigh;
2,634✔
386
   if (!folded_bounds(b, &blow, &bhigh))
2,634✔
387
      return;
388

389
   int64_t rlow, rhigh;
864✔
390
   if (!folded_bounds(r, &rlow, &rhigh))
864✔
391
      return;
392

393
   if (rlow > rhigh)
724✔
394
      return;  // Null range
395

396
   type_t index_type = index_type_of(value_type, 0);
691✔
397
   const range_kind_t dir = tree_subkind(b);
691✔
398

399
   int64_t folded;
691✔
400
   const char *error = NULL;
691✔
401
   if (!index_in_range(tree_left(r), blow, bhigh, &folded))
691✔
402
      error = "left";
403
   else if (!index_in_range(tree_right(r), blow, bhigh, &folded))
688✔
404
      error = "right";
405

406
   if (error) {
4✔
407
      diag_t *d = diag_new(DIAG_ERROR, tree_loc(r));
4✔
408
      diag_printf(d, "array");
4✔
409
      if (tree_kind(value) == T_REF)
4✔
410
         diag_printf(d, " %s", istr(tree_ident(value)));
4✔
411
      diag_printf(d, " slice %s index ", error);
4✔
412
      to_string(diag_text_buf(d), index_type, folded);
4✔
413
      diag_printf(d, " outside of %s range ", type_pp(index_type));
4✔
414
      format_type_range(d, index_type, dir, blow, bhigh);
4✔
415

416
      diag_emit(d);
4✔
417
   }
418
}
419

420
static void bounds_cover_choice(interval_t **isp, tree_t t, type_t type,
32,467✔
421
                                int64_t low, int64_t high)
422
{
423
   interval_t *it, *prev;
32,467✔
424
   for (it = *isp, prev = NULL;
32,467✔
425
        (it != NULL) && (it->low <= high);
35,466✔
426
        prev = it, it = it->next) {
2,999✔
427

428
      if ((low <= it->high) && (it->low <= high)) {
28,654✔
429
         const int64_t rlow  = MAX(low, it->low);
5✔
430
         const int64_t rhigh = MIN(high, it->high);
5✔
431
         if (type_is_integer(type)) {
5✔
432
            if (rlow == rhigh)
3✔
433
               bounds_error(t, "value %"PRIi64" is already covered", rlow);
2✔
434
            else
435
               bounds_error(t, "range %"PRIi64" to %"PRIi64" is already covered",
1✔
436
                            rlow, rhigh);
437
         }
438
         else if (type_is_enum(type)) {
2✔
439
            type_t base = type_base_recur(type);
2✔
440
            if (rlow == rhigh)
2✔
441
               bounds_error(t, "duplicate choice for %s",
2✔
442
                            istr(tree_ident(type_enum_literal(base, rlow))));
443
            else
UNCOV
444
               bounds_error(t, "duplicate choices for range %s to %s",
×
445
                            istr(tree_ident(type_enum_literal(base, rlow))),
446
                            istr(tree_ident(type_enum_literal(base, rhigh))));
447
         }
448
         it->low = MIN(low, it->low);
5✔
449
         it->high = MAX(high, it->high);
5✔
450
         return;
5✔
451
      }
452
      else if (high == it->low - 1) {
28,649✔
UNCOV
453
         it->low = low;
×
UNCOV
454
         return;
×
455
      }
456
      else if (low == it->high + 1) {
28,649✔
457
         it->high = high;
25,650✔
458
         return;
25,650✔
459
      }
460
   }
461

462
   interval_t *new = xmalloc(sizeof(interval_t));
6,812✔
463
   new->low  = low;
6,812✔
464
   new->high = high;
6,812✔
465

466
   if ((*isp == NULL) || (prev == NULL)) {
6,812✔
467
      new->next = *isp;
5,820✔
468
      *isp = new;
5,820✔
469
   }
470
   else {
471
      new->next = prev->next;
992✔
472
      prev->next = new;
992✔
473
   }
474
}
475

476
static void report_interval(diag_t *d, type_t type, range_kind_t dir,
33✔
477
                            int64_t low, int64_t high)
478
{
479
   if (low == high) {
33✔
480
      if (type_is_integer(type))
13✔
481
         diag_printf(d, "%"PRIi64, low);
6✔
482
      else if (type_is_enum(type)) {
7✔
483
         type_t base = type_base_recur(type);
7✔
484
         diag_printf(d, "%s", istr(tree_ident(type_enum_literal(base, low))));
7✔
485
      }
486
   }
487
   else
488
      format_type_range(d, type, dir, low, high);
20✔
489
}
33✔
490

491
static void bounds_check_missing_choices(tree_t t, type_t type,
3,844✔
492
                                         type_t index_type, range_kind_t dir,
493
                                         int64_t tlow, int64_t thigh,
494
                                         interval_t *covered)
495
{
496
   int missing = 0;
3,844✔
497
   interval_t *it;
3,844✔
498
   int64_t walk;
3,844✔
499

500
   for (it = covered, walk = tlow; it != NULL; it = it->next) {
8,346✔
501
      if (it->low != walk)
4,502✔
502
         missing += it->low - walk;
9✔
503
      walk = it->high + 1;
4,502✔
504
   }
505

506
   if (walk != thigh + 1)
3,844✔
507
      missing += (thigh + 1 - walk);
16✔
508

509
   if (missing == 0)
3,844✔
510
      return;
3,823✔
511

512
   // Allow downgrade to warning for case statement but not aggregates
513
   diag_t *d;
21✔
514
   if (index_type == NULL) {
21✔
515
      if ((d = pedantic_diag(tree_loc(t))) == NULL)
9✔
516
         return;
517
   }
518
   else
519
      d = diag_new(DIAG_ERROR, tree_loc(t));
12✔
520

521
   diag_printf(d, "missing choice%s for element%s ",
21✔
522
               missing > 1 ? "s" : "", missing > 1 ? "s" : "");
523

524
   int printed = 0;
21✔
525
   for (it = covered, walk = tlow; it != NULL; it = it->next) {
66✔
526
      if (it->low != walk) {
24✔
527
         if (printed++) diag_printf(d, ", ");
9✔
528
         report_interval(d, index_type ?: type, dir, walk, it->low - 1);
14✔
529
      }
530

531
      walk = it->high + 1;
24✔
532
   }
533

534
   if (walk != thigh + 1) {
21✔
535
      if (printed++) diag_printf(d, ", ");
16✔
536
      report_interval(d, index_type ?: type, dir, walk, thigh);
23✔
537
   }
538

539
   if (index_type == NULL)
21✔
540
      diag_printf(d, " of type %s", type_pp(type));
9✔
541
   else
542
      diag_printf(d, " of %s with index type %s", type_pp(type),
12✔
543
                  type_pp(index_type));
544

545
   type_t base = index_type ?: type;
21✔
546
   while (is_anonymous_subtype(base))
22✔
547
      base = type_base(base);
1✔
548

549
   int64_t rlow, rhigh;
21✔
550
   if (!folded_bounds(range_of(index_type ?: type, 0), &rlow, &rhigh))
21✔
551
      return;
552

553
   if (rlow != tlow || rhigh != thigh || !type_has_ident(index_type ?: type)) {
21✔
554
      diag_printf(d, " range ");
8✔
555
      report_interval(d, index_type ?: type, dir, tlow, thigh);
8✔
556
   }
557

558
   diag_emit(d);
21✔
559
}
560

561
static void bounds_free_intervals(interval_t **list)
7,840✔
562
{
563
   for (interval_t *it = *list, *tmp; it != NULL; it = tmp) {
14,652✔
564
      tmp = it->next;
6,812✔
565
      free(it);
6,812✔
566
   }
567
   *list = NULL;
7,840✔
568
}
7,840✔
569

570
static void bounds_check_aggregate(tree_t t)
11,290✔
571
{
572
   type_t type = tree_type(t);
11,290✔
573
   if (!type_is_array(type))
11,290✔
574
      return;
3,945✔
575

576
   // Find the tightest bounds for the index
577

578
   int64_t low, high, clow = 0, chigh = 0;
8,856✔
579
   type_t index_type = index_type_of(type, 0);
8,856✔
580
   range_kind_t dir;
8,856✔
581

582
   const bool unconstrained = type_is_unconstrained(type);
8,856✔
583

584
   if (unconstrained) {
8,856✔
585
      // Aggregate of unconstrained array type
586
      tree_t base_r = range_of(index_type, 0);
2,281✔
587
      if (!folded_bounds(base_r, &low, &high))
2,281✔
588
         return;
589

590
      clow = high, chigh = low;  // Actual bounds computed below
2,275✔
591
      dir = tree_subkind(base_r);
2,275✔
592
   }
593
   else {
594
      tree_t type_r = range_of(type, 0);
6,575✔
595
      if (!folded_bounds(type_r, &low, &high))
6,575✔
596
         return;
597

598
      clow = low, chigh = high;
5,070✔
599
      dir = tree_subkind(type_r);
5,070✔
600
   }
601

602
   const int ndims = dimension_of(type);
7,345✔
603
   type_t elem = type_elem(type);
7,345✔
604

605
   interval_t *covered = NULL;
7,345✔
606
   bool known_elem_count = true;
7,345✔
607
   int next_pos = 0;
7,345✔
608
   const int nassocs = tree_assocs(t);
7,345✔
609
   for (int i = 0; i < nassocs; i++) {
43,347✔
610
      tree_t a = tree_assoc(t, i), value = tree_value(a);
36,002✔
611
      int64_t ilow = 0, ihigh = 0, count = 1;
36,002✔
612
      const assoc_kind_t akind = tree_subkind(a);
36,002✔
613

614
      if (akind == A_SLICE || akind == A_CONCAT) {
36,002✔
615
         type_t value_type = tree_type(value);
5,462✔
616
         if (type_is_unconstrained(value_type))
5,462✔
617
            known_elem_count = false;
618
         else if (!folded_length(range_of(value_type, 0), &count))
3,046✔
619
            known_elem_count = false;
260✔
620
      }
621
      else if (type_is_scalar(elem))
30,540✔
622
         bounds_check_scalar(value, elem, NULL);
28,144✔
623
      else if (ndims == 1 && type_is_array(elem))
2,396✔
624
         bounds_check_array(value, elem, NULL);
1,650✔
625

626
      switch (akind) {
36,002✔
627
      case A_NAMED:
1,376✔
628
         {
629
            tree_t name = tree_name(a);
1,376✔
630
            if (!bounds_check_index(name, index_type, dir,
1,376✔
631
                                    "aggregate choice", low, high))
632
               known_elem_count = false;
4✔
633
            if (folded_int(name, &ilow))
1,376✔
634
               ihigh = ilow;
1,373✔
635
            else
636
               known_elem_count = false;
637
         }
638
         break;
639

640
      case A_RANGE:
672✔
641
      case A_SLICE:
642
         {
643
            tree_t r = tree_range(a, 0);
672✔
644
            const range_kind_t rkind = tree_subkind(r);
672✔
645
            if (rkind == RANGE_TO || rkind == RANGE_DOWNTO) {
672✔
646
               tree_t left = tree_left(r), right = tree_right(r);
507✔
647

648
               int64_t ileft, iright;
507✔
649
               if (folded_int(left, &ileft) && folded_int(right, &iright)) {
507✔
650
                  ilow = (rkind == RANGE_TO ? ileft : iright);
352✔
651
                  ihigh = (rkind == RANGE_TO ? iright : ileft);
352✔
652

653
                  // Cannot check either index unless both are known
654
                  // since the range may be null
655
                  if (ilow <= ihigh) {
352✔
656
                     if (!bounds_check_index(left, index_type, rkind,
335✔
657
                                             "aggregate choice", low, high))
658
                        known_elem_count = false;
2✔
659
                     if (!bounds_check_index(right, index_type, rkind,
335✔
660
                                             "aggregate choice", low, high))
661
                        known_elem_count = false;
2✔
662
                  }
663
                  else
664
                     known_elem_count = false;
665
               }
666
               else
667
                  known_elem_count = false;
668

669
               if (count > 1 && known_elem_count && ihigh - ilow + 1 != count)
507✔
670
                  bounds_error(a, "discrete range has %"PRIi64" elements but "
2✔
671
                               "length of expression is %"PRIi64,
672
                               ihigh - ilow + 1, count);
673
               else if (unconstrained && akind == A_SLICE && count > 1) {
505✔
674
                  // VHDL-2008 range association determines index
675
                  // direction for unconstrained aggregate
UNCOV
676
                  assert(standard() >= STD_08);
×
677
                  dir = rkind;
678
               }
679
            }
680
            else
681
               known_elem_count = false;
682
         }
683
         break;
684

685
      case A_OTHERS:
1,329✔
686
         known_elem_count = false;
1,329✔
687
         break;
1,329✔
688

689
      case A_POS:
32,625✔
690
      case A_CONCAT:
691
         if (dir == RANGE_TO) {
32,625✔
692
            ilow = low + next_pos;
31,928✔
693
            ihigh = ilow + count - 1;
31,928✔
694
         }
695
         else {
696
            ihigh = high - next_pos;
697✔
697
            ilow = ihigh - count + 1;
697✔
698
         }
699

700
         next_pos += count;
32,625✔
701

702
         if ((ilow < low || ihigh > high) && known_elem_count) {
32,625✔
703
            diag_t *d = diag_new(DIAG_ERROR, tree_loc(t));
7✔
704
            diag_printf(d, "expected at most %"PRIi64" positional "
7✔
705
                        "associations in %s aggregate with index type %s "
706
                        "range ", MAX(0, high - low + 1), type_pp(type),
7✔
707
                        type_pp(index_type));
708
            format_type_range(d, index_type, dir, low, high);
7✔
709
            diag_emit(d);
7✔
710

711
            known_elem_count = false;
7✔
712
         }
713
         break;
714
      }
715

716
      if (unconstrained) {
36,002✔
717
         clow = MIN(clow, ilow);
5,558✔
718
         chigh = MAX(chigh, ihigh);
5,558✔
719
      }
720

721
      if (known_elem_count)
36,002✔
722
         bounds_cover_choice(&covered, a, index_type, ilow, ihigh);
29,615✔
723
   }
724

725
   if (known_elem_count)
7,345✔
726
      bounds_check_missing_choices(t, type, index_type, dir, clow, chigh,
3,720✔
727
                                   covered);
728

729
   bounds_free_intervals(&covered);
7,345✔
730

731
   // Check each sub-aggregate has the same length for an unconstrained
732
   // array aggregate
733

734
   if (ndims > 1) {
7,345✔
735
      int64_t length = -1;
736
      for (int i = 0; i < nassocs; i++) {
1,154✔
737
         tree_t a = tree_assoc(t, i);
889✔
738
         type_t value_type = tree_type(tree_value(a));
889✔
739

740
         if (type_is_unconstrained(value_type))
889✔
741
            continue;
3✔
742

743
         int64_t this_length;
889✔
744
         if (!folded_length(range_of(value_type, 0), &this_length))
889✔
745
            continue;
3✔
746

747
         if (length == -1)
886✔
748
            length = this_length;
262✔
749
         else if (length != this_length)
624✔
750
            bounds_error(a, "length of sub-aggregate %"PRIi64" does not match "
886✔
751
                         "expected length %"PRIi64, this_length, length);
752
      }
753
   }
754
}
755

756
static void bounds_check_index_contraints(type_t type)
21,190✔
757
{
758
   if (type_kind(type) != T_SUBTYPE || !type_has_constraint(type))
21,190✔
759
      return;
2,108✔
760

761
   tree_t c0 = type_constraint(type);
19,082✔
762

763
   const constraint_kind_t kind = tree_subkind(c0);
19,082✔
764
   if (kind != C_INDEX && kind != C_RANGE)
19,082✔
765
      return;
766

767
   // Check folded range does not violate index constraints of base type
768

769
   const int ndims = dimension_of(type);
18,820✔
770
   for (int i = 0; i < ndims; i++) {
37,979✔
771
      tree_t dim = tree_range(c0, i);
19,159✔
772

773
      const range_kind_t dir = tree_subkind(dim);
19,159✔
774
      if (dir != RANGE_TO && dir != RANGE_DOWNTO)
19,159✔
775
         continue;
2,516✔
776

777
      type_t cons = kind == C_INDEX ? index_type_of(type, i) : type_base(type);
16,643✔
778
      if (type_kind(cons) == T_GENERIC)
16,643✔
779
         continue;   // Cannot check
3✔
780

781
      tree_t bounds = range_of(cons, 0);
16,640✔
782

783
      // Only check here if range can be determined to be non-null
784

785
      if (kind == C_RANGE && type_is_real(type)) {
16,640✔
786
         double dim_low, bounds_low;
34✔
787
         double dim_high, bounds_high;
34✔
788

789
         const bool is_static =
68✔
790
            folded_bounds_real(dim, &dim_low, &dim_high)
34✔
791
            && folded_bounds_real(bounds, &bounds_low, &bounds_high);
34✔
792

793
         if (!is_static)
34✔
794
            continue;
5✔
795

796
         const bool is_null =
58✔
797
            dim_low > dim_high || bounds_low > bounds_high;
29✔
798

799
         if (is_null)
29✔
UNCOV
800
            continue;
×
801

802
         if (dim_low < bounds_low)
29✔
803
            bounds_error(dir == RANGE_TO ? tree_left(dim) : tree_right(dim),
1✔
804
                         "%s index %g violates constraint %s",
805
                         dir == RANGE_TO ? "left" : "right",
806
                         dim_low, type_pp(cons));
807

808
         if (dim_high > bounds_high)
29✔
809
            bounds_error(dir == RANGE_TO ? tree_right(dim) : tree_left(dim),
29✔
810
                         "%s index %g violates constraint %s",
811
                         dir == RANGE_TO ? "right" : "left",
812
                         dim_high, type_pp(cons));
813

814
      }
815
      else {
816
         int64_t dim_low, bounds_low;
16,606✔
817
         int64_t dim_high, bounds_high;
16,606✔
818

819
         const bool is_static =
33,212✔
820
            folded_bounds(dim, &dim_low, &dim_high)
16,606✔
821
            && folded_bounds(bounds, &bounds_low, &bounds_high);
16,606✔
822

823
         if (!is_static)
16,606✔
824
            continue;
7,555✔
825

826
         const bool is_null =
18,538✔
827
            dim_low > dim_high || bounds_low > bounds_high;
9,269✔
828

829
         if (is_null)
9,269✔
830
            continue;
218✔
831

832
         if (type_is_enum(cons)) {
9,051✔
833
            if (dim_low < bounds_low) {
540✔
834
               type_t cons_base = type_base_recur(cons);
1✔
835
               tree_t lit = type_enum_literal(cons_base, (unsigned)dim_low);
1✔
836
               bounds_error(dir == RANGE_TO ? tree_left(dim) : tree_right(dim),
1✔
837
                            "%s index %s violates constraint %s",
838
                            dir == RANGE_TO ? "left" : "right",
839
                            istr(tree_ident(lit)), type_pp(cons));
840
            }
841

842
            if (dim_high > bounds_high) {
540✔
843
               type_t cons_base = type_base_recur(cons);
2✔
844
               tree_t lit = type_enum_literal(cons_base, (unsigned)dim_high);
2✔
845
               bounds_error(dir == RANGE_TO ? tree_right(dim) : tree_left(dim),
2✔
846
                            "%s index %s violates constraint %s",
847
                            dir == RANGE_TO ? "right" : "left",
848
                            istr(tree_ident(lit)), type_pp(cons));
849
            }
850
         }
851
         else if (dim_high > bounds_high)
8,511✔
852
            bounds_error(dir == RANGE_TO ? tree_right(dim) : tree_left(dim),
2✔
853
                         "%s index %"PRIi64" violates constraint %s",
854
                         dir == RANGE_TO ? "right" : "left",
855
                         dim_high, type_pp(cons));
856
         else if (dim_low < bounds_low)
8,509✔
857
            bounds_error(dir == RANGE_TO ? tree_left(dim) : tree_right(dim),
9,052✔
858
                         "%s index %"PRIi64" violates constraint %s",
859
                         dir == RANGE_TO ? "left" : "right",
860
                         dim_low, type_pp(cons));
861
      }
862
   }
863
}
864

865
static void bounds_check_assignment(tree_t target, tree_t value)
53,034✔
866
{
867
   type_t target_type = tree_type(target);
53,034✔
868

869
   if (type_is_scalar(target_type))
53,034✔
870
      bounds_check_scalar(value, target_type, target);
30,907✔
871
   else if (type_is_array(target_type))
22,127✔
872
      bounds_check_array(value, target_type, target);
17,772✔
873
}
53,034✔
874

875
static void bounds_check_object_decl(tree_t t)
26,768✔
876
{
877
   if (tree_has_value(t))
26,768✔
878
      bounds_check_assignment(t, tree_value(t));
10,866✔
879

880
   type_t type = tree_type(t);
26,768✔
881
   if (is_anonymous_subtype(type))
26,768✔
882
      bounds_check_index_contraints(type);
10,655✔
883
}
26,768✔
884

885
static void bounds_check_alias_decl(tree_t t)
2,969✔
886
{
887
   if (!tree_has_type(t))
2,969✔
888
      return;   // Alias declaration without subtype indication
889

890
   if (tree_has_value(t))
2,813✔
891
      bounds_check_assignment(t, tree_value(t));
2,813✔
892

893
   type_t type = tree_type(t);
2,813✔
894
   if (is_anonymous_subtype(type))
2,813✔
895
      bounds_check_index_contraints(type);
781✔
896
}
897

898
static void bounds_check_elem_constraint(tree_t t)
548✔
899
{
900
   type_t type = tree_type(t);
548✔
901
   if (is_anonymous_subtype(type))
548✔
902
      bounds_check_index_contraints(type);
548✔
903
}
548✔
904

905
static void bounds_check_type_decl(tree_t t)
4,366✔
906
{
907
   type_t type = tree_type(t);
4,366✔
908

909
   if (type_is_record(type)) {
4,366✔
910
      const int nfields = type_fields(type);
1,143✔
911
      for (int i = 0; i < nfields; i++) {
4,658✔
912
         type_t ft = tree_type(type_field(type, i));
3,515✔
913
         if (is_anonymous_subtype(ft))
3,515✔
914
            bounds_check_index_contraints(ft);
695✔
915
      }
916
   }
917
   else if (type_is_array(type)) {
3,223✔
918
      bounds_check_index_contraints(type);
2,337✔
919

920
      type_t elem = type_elem(type);
2,337✔
921
      if (is_anonymous_subtype(elem))
2,337✔
922
         bounds_check_index_contraints(elem);
160✔
923
   }
924
   else if (type_is_scalar(type)) {
886✔
925
      int64_t low, high;
522✔
926
      if (folded_bounds(range_of(type, 0), &low, &high) && low > high)
522✔
927
         warn_at(tree_loc(t), "type %s has null range", type_pp(type));
1✔
928
   }
929
}
4,366✔
930

931
static void bounds_check_subtype_decl(tree_t t)
1,379✔
932
{
933
   bounds_check_index_contraints(tree_type(t));
1,379✔
934
}
1,379✔
935

936
static void bounds_check_interface_decl(tree_t t)
109,915✔
937
{
938
   const class_t class = tree_class(t);
109,915✔
939
   if (class == C_FUNCTION || class == C_PROCEDURE || class == C_PACKAGE)
109,915✔
940
      return;
941

942
   const port_mode_t mode = tree_subkind(t);
108,189✔
943
   if (mode != PORT_ARRAY_VIEW && mode != PORT_RECORD_VIEW && tree_has_value(t))
108,189✔
944
      bounds_check_assignment(t, tree_value(t));
7,102✔
945

946
   type_t type = tree_type(t);
108,189✔
947
   if (is_anonymous_subtype(type))
108,189✔
948
      bounds_check_index_contraints(type);
4,635✔
949
}
950

951
static void bounds_check_signal_assign(tree_t t)
7,248✔
952
{
953
   int64_t last_delay = 0;
7,248✔
954
   tree_t target = tree_target(t);
7,248✔
955

956
   const int nwaves = tree_waveforms(t);
7,248✔
957
   for (int i = 0; i < nwaves; i++) {
14,716✔
958
      tree_t w = tree_waveform(t, i);
7,468✔
959

960
      if (tree_has_value(w))
7,468✔
961
         bounds_check_assignment(target, tree_value(w));
7,444✔
962

963
      int64_t delay = 0;
7,468✔
964
      bool delay_is_known = true;
7,468✔
965
      const bool has_delay = tree_has_delay(w);
7,468✔
966

967
      if (has_delay) {
7,468✔
968
         delay_is_known = folded_int(tree_delay(w), &delay);
863✔
969
         if (delay_is_known && delay < 0)
863✔
970
            bounds_error(tree_delay(w), "assignment delay may not be "
4✔
971
                         "negative");
972
      }
973

974
      if (i == 0) {
7,468✔
975
         int64_t rlimit;
7,242✔
976
         if (tree_has_reject(t) && folded_int(tree_reject(t), &rlimit)) {
7,242✔
977
            if ((rlimit < 0) && (delay >= 0))
584✔
978
               bounds_error(tree_reject(t), "rejection limit may not be "
1✔
979
                            "negative");
980

981
            if (rlimit > delay)
584✔
982
               bounds_error(tree_reject(t), "rejection limit may not be "
7,242✔
983
                            "greater than first assignment delay");
984
         }
985
      } else if (delay_is_known && delay <= last_delay)
226✔
986
         bounds_error(has_delay ? tree_delay(w) : w, "assignment delays "
5✔
987
                      "must be in ascending time order");
988

989
      // even if the delay isn't known, it has to be at least zero
990
      last_delay = delay;
7,468✔
991
   }
992
}
7,248✔
993

994
static void bounds_check_var_assign(tree_t t)
20,360✔
995
{
996
   bounds_check_assignment(tree_target(t), tree_value(t));
20,360✔
997
}
20,360✔
998

999
static void bounds_check_scalar_case(tree_t t, type_t type, bool matching)
495✔
1000
{
1001
   // Check that the full range of the type is covered
1002

1003
   tree_t type_r = range_of(type, 0);
495✔
1004

1005
   int64_t tlow = INT64_MIN, thigh = INT64_MAX;
495✔
1006
   while (!folded_bounds(type_r, &tlow, &thigh)
495✔
1007
          && type_kind(type) == T_SUBTYPE) {
496✔
1008
      // LRM 08 section 10.9: if the case expression does not have a
1009
      // locally static subtype then the choices must cover every value
1010
      // of the base type
1011
      type = type_base(type);
1✔
1012
      type_r = range_of(type, 0);
1✔
1013
   }
1014

1015
   const range_kind_t tdir = tree_subkind(type_r);
495✔
1016

1017
   bool have_others = false;
495✔
1018
   interval_t *covered = NULL;
495✔
1019

1020
   const int nstmts = tree_stmts(t);
495✔
1021
   for (int i = 0; i < nstmts; i++) {
2,894✔
1022
      tree_t alt = tree_stmt(t, i);
2,399✔
1023

1024
      const int nassocs = tree_assocs(alt);
2,399✔
1025
      for (int j = 0; j < nassocs; j++) {
5,623✔
1026
         tree_t a = tree_assoc(alt, j);
3,224✔
1027

1028
         int64_t low = INT64_MIN, high = INT64_MAX;
3,224✔
1029
         switch (tree_subkind(a)) {
3,224✔
1030
         case A_OTHERS:
363✔
1031
            have_others = true;
363✔
1032
            continue;
363✔
1033

1034
         case A_NAMED:
2,825✔
1035
            {
1036
               int64_t pos;
2,825✔
1037
               tree_t name = tree_name(a);
2,825✔
1038
               if (!bounds_check_index(name, type, tdir, "case choice",
2,825✔
1039
                                       tlow, thigh))
1040
                  have_others = true;
1041
               else if (matching && folded_int(name, &pos) && pos == 8)
2,824✔
1042
                  have_others = true;    // Has a '-' choice
1043
               else
1044
                  low = high = assume_int(tree_name(a));
2,818✔
1045
            }
1046
            break;
2,825✔
1047

1048
         case A_RANGE:
36✔
1049
            {
1050
               tree_t r = tree_range(a, 0);
36✔
1051
               const range_kind_t dir = tree_subkind(r);
36✔
1052

1053
               if (dir == RANGE_EXPR)
36✔
UNCOV
1054
                  fatal_at(tree_loc(r), "locally static range not folded");
×
1055

1056
               tree_t left = tree_left(r);
36✔
1057
               tree_t right = tree_right(r);
36✔
1058

1059
               if (!bounds_check_index(left, type, dir, "case choice",
36✔
1060
                                       tlow, thigh))
1061
                  have_others = true;
1✔
1062
               if (!bounds_check_index(right, type, dir, "case choice",
36✔
1063
                                       tlow, thigh))
UNCOV
1064
                  have_others = true;
×
1065

1066
               low = assume_int(dir == RANGE_TO ? left : right);
39✔
1067
               high = assume_int(dir == RANGE_TO ? right : left);
36✔
1068
            }
1069
            break;
36✔
1070
         }
1071

1072
         if (!have_others)
2,861✔
1073
            bounds_cover_choice(&covered, a, type, low, high);
2,852✔
1074
      }
1075
   }
1076

1077
   if (!have_others)
495✔
1078
      bounds_check_missing_choices(t, type, NULL, direction_of(type, 0),
124✔
1079
                                   tlow, thigh, covered);
1080

1081
   bounds_free_intervals(&covered);
495✔
1082
}
495✔
1083

1084
static void bounds_check_duplicate_choice(tree_t old, tree_t new, int length)
2✔
1085
{
1086
   for (int i = 0; i < length; i++) {
13✔
1087
      if (get_case_choice_char(old, i) != get_case_choice_char(new, i))
11✔
1088
         return;
1089
   }
1090

1091
   diag_t *d = diag_new(DIAG_ERROR, tree_loc(new));
2✔
1092
   diag_printf(d, "duplicate choice in case statement");
2✔
1093
   diag_hint(d, tree_loc(new), "repeated here");
2✔
1094
   diag_hint(d, tree_loc(old), "previous choice for this value");
2✔
1095
   diag_hint(d, NULL, "each value of the subtype of the expression must be "
2✔
1096
             "represented once and only once in the set of choices");
1097
   diag_lrm(d, STD_93, "8.8");
2✔
1098
   diag_emit(d);
2✔
1099
}
1100

1101
static void bounds_check_array_case(tree_t t, type_t type, bool matching)
126✔
1102
{
1103
   type_t elem = type_elem(type);
126✔
1104
   assert(type_is_enum(elem));
126✔
1105

1106
   // Calculate how many values each element has
1107
   int64_t elemsz = INT64_MAX;
126✔
1108
   while (!folded_length(range_of(elem, 0), &elemsz)
252✔
1109
          && type_kind(elem) == T_SUBTYPE)
252✔
UNCOV
1110
      elem = type_base(elem);
×
1111

1112
   int64_t expect = -1, length = -1;
126✔
1113

1114
   const bool known_length =
252✔
1115
      !type_is_unconstrained(type) && folded_length(range_of(type, 0), &length);
126✔
1116

1117
   if (known_length && !ipow_safe(elemsz, length, &expect))
126✔
1118
      expect = INT64_MAX;   // Overflow
4✔
1119

1120
   int nchoices = 0;
126✔
1121
   const int nstmts = tree_stmts(t);
126✔
1122
   for (int i = 0; i < nstmts; i++)
851✔
1123
      nchoices += tree_assocs(tree_stmt(t, i));
725✔
1124

1125
   int64_t have = 0;
126✔
1126
   int64_t *hashes LOCAL = xmalloc_array(nchoices, sizeof(int64_t));
252✔
1127
   tree_t *choices LOCAL = xmalloc_array(nchoices, sizeof(tree_t));
252✔
1128
   int hptr = 0;
126✔
1129

1130
   for (int i = 0; i < nstmts; i++) {
848✔
1131
      tree_t alt = tree_stmt(t, i);
723✔
1132

1133
      const int nassocs = tree_assocs(alt);
723✔
1134
      for (int j = 0; j < nassocs; j++, hptr++) {
1,479✔
1135
         tree_t a = tree_assoc(alt, j);
757✔
1136
         hashes[hptr] = INT64_MAX;
757✔
1137
         choices[hptr] = NULL;
757✔
1138

1139
         if (tree_subkind(a) == A_OTHERS) {
757✔
1140
            have = expect;
107✔
1141
            continue;
107✔
1142
         }
1143

1144
         assert(tree_subkind(a) == A_NAMED);
650✔
1145
         tree_t name = choices[hptr] = tree_name(a);
650✔
1146

1147
         int64_t covered = 1, pos;
650✔
1148
         if (matching && tree_kind(name) == T_STRING) {
650✔
1149
            const int nchars = tree_chars(name);
68✔
1150
            for (int i = 0; i < nchars; i++) {
308✔
1151
               if (folded_int(tree_char(name, i), &pos) && pos == 8)
240✔
1152
                  covered *= 9;    // Has a '-' choice
92✔
1153
            }
1154
         }
1155
         have += covered;
650✔
1156

1157
         type_t choice_type = tree_type(name);
650✔
1158
         if (type_is_unconstrained(choice_type))
650✔
UNCOV
1159
            continue;
×
1160

1161
         int64_t choice_length;
650✔
1162
         if (folded_length(range_of(choice_type, 0), &choice_length)) {
650✔
1163
            if (length == -1) {
650✔
1164
               length = choice_length;
20✔
1165
               if (!ipow_safe(elemsz, length, &expect))
20✔
1166
                  expect = INT64_MAX;
3✔
1167
            }
1168
            else if (choice_length != length) {
630✔
1169
               diag_t *d = diag_new(DIAG_ERROR, tree_loc(name));
1✔
1170
               diag_printf(d, "expected case choice to have length %"PRIi64
1✔
1171
                           " but is %"PRIi64, length, choice_length);
1172
               diag_hint(d, NULL, "the values of all choices for a case "
1✔
1173
                         "expression with one-dimensional character array "
1174
                         "type must have the same length");
1175
               diag_lrm(d, STD_08, "10.9");
1✔
1176
               diag_emit(d);
1✔
1177
               return;
1✔
1178
            }
1179

1180
            hashes[hptr] = encode_case_choice(name, choice_length, 0);
649✔
1181

1182
            for (int k = 0; k < hptr; k++) {
3,756✔
1183
               if (hashes[k] == INT64_MAX)
3,107✔
UNCOV
1184
                  continue;
×
1185
               else if (hashes[hptr] == hashes[k]) {
3,107✔
1186
                  tree_t old = choices[k];
2✔
1187
                  bounds_check_duplicate_choice(old, name, choice_length);
2✔
1188
               }
1189
            }
1190
         }
1191
      }
1192
   }
1193

1194
   if (have < expect && expect != -1) {
125✔
1195
      const loc_t *loc = tree_loc(tree_value(t));
6✔
1196
      diag_t *d = pedantic_diag(loc);
6✔
1197
      if (d != NULL) {
6✔
1198
         diag_printf(d, "choices cover only %"PRIi64" of ", have);
6✔
1199
         if (expect > 100000)
6✔
1200
            diag_printf(d, "%"PRIi64" ** %"PRIi64, elemsz, length);
3✔
1201
         else
1202
            diag_printf(d, "%"PRIi64, expect);
3✔
1203
         diag_printf(d, " possible values");
6✔
1204

1205
         diag_hint(d, loc, "expression has %"PRIi64" elements of type %s, "
6✔
1206
                   "each of which has %"PRIi64" possible values",
1207
                   length, type_pp(type_elem(type)), elemsz);
1208

1209
         if (!known_length)
6✔
1210
            diag_hint(d, NULL, "the case expression subtype is not locally "
2✔
1211
                      "static so the length was derived from the choices");
1212

1213
         diag_emit(d);
6✔
1214
      }
1215
   }
1216
}
1217

1218
static void bounds_check_case(tree_t t)
585✔
1219
{
1220
   type_t type = tree_type(tree_value(t));
585✔
1221

1222
   if (type_is_scalar(type))
585✔
1223
      bounds_check_scalar_case(t, type, false);
489✔
1224
   else if (type_is_array(type))
96✔
1225
      bounds_check_array_case(t, type, false);
96✔
1226
}
585✔
1227

1228
static void bounds_check_match_case(tree_t t)
36✔
1229
{
1230
   type_t type = tree_type(tree_value(t)), elem = type_elem_recur(type);
36✔
1231

1232
   const bool matching = type_eq(elem, ieee_type(IEEE_STD_ULOGIC));
36✔
1233

1234
   if (type_is_scalar(type))
36✔
1235
      bounds_check_scalar_case(t, type, matching);
6✔
1236
   else if (type_is_array(type))
30✔
1237
      bounds_check_array_case(t, type, matching);
30✔
1238
}
36✔
1239

1240
static void bounds_check_conv_integer(tree_t value, type_t from, type_t to)
154✔
1241
{
1242
   int64_t ival = 0;
154✔
1243
   double rval = 0.0;
154✔
1244
   bool folded = false;
154✔
1245
   if (type_is_real(from)) {
154✔
1246
      folded = folded_real(value, &rval);
100✔
1247
      ival = (int64_t)(rval + 0.5);
100✔
1248
   }
1249
   else if (type_is_integer(from))
54✔
1250
      folded = folded_int(value, &ival);
54✔
1251

1252
   if (folded) {
154✔
1253
      int64_t b_low, b_high;
2✔
1254
      if (folded_bounds(range_of(to, 0), &b_low, &b_high)
2✔
1255
          && (ival < b_low || ival > b_high)) {
2✔
1256
         char *argstr LOCAL = type_is_real(from)
2✔
1257
            ? xasprintf("%lg", rval) : xasprintf("%"PRIi64, ival);
2✔
1258
         bounds_error(value, "type conversion argument %s out of "
2✔
1259
                      "bounds %"PRIi64" to %"PRIi64, argstr, b_low, b_high);
1260
      }
1261
   }
1262
}
154✔
1263

1264
static void bounds_check_conv_array(tree_t value, type_t from, type_t to)
2,659✔
1265
{
1266
   const int ndims = dimension_of(to);
2,659✔
1267
   assert(ndims == dimension_of(from));
2,659✔
1268

1269
   const bool to_constrained = !type_is_unconstrained(to);
2,659✔
1270
   const bool from_constrained = !type_is_unconstrained(from);
2,659✔
1271

1272
   if (to_constrained && from_constrained) {
2,659✔
1273
      for (int i = 0; i < ndims; i++) {
46✔
1274
         tree_t r_to = range_of(to, i);
23✔
1275
         tree_t r_from = range_of(from, i);
23✔
1276

1277
         int64_t to_length;
23✔
1278
         if (!folded_length(r_to, &to_length))
23✔
1279
            continue;
6✔
1280

1281
         int64_t from_length;
20✔
1282
         if (!folded_length(r_from, &from_length))
20✔
1283
            continue;
3✔
1284

1285
         if (to_length != from_length)
17✔
1286
            bounds_error(value, "length of type conversion argument %"PRIi64
17✔
1287
                         " does not match expected length %"PRIi64
1288
                         " for constrained array subtype %s",
1289
                         from_length, to_length, type_pp(to));
1290
      }
1291
   }
1292
   else if (!to_constrained && from_constrained) {
2,636✔
1293
      for (int i = 0; i < ndims; i++) {
1,126✔
1294
         type_t index_type = index_type_of(to, i);
563✔
1295
         tree_t r_to = range_of(index_type, i);
563✔
1296
         tree_t r_from = range_of(from, i);
563✔
1297

1298
         if (tree_subkind(r_from) == RANGE_EXPR)
563✔
1299
            continue;
484✔
1300

1301
         int64_t low, high;
448✔
1302
         if (!folded_bounds(r_to, &low, &high))
448✔
UNCOV
1303
            continue;
×
1304

1305
         int64_t f_low, f_high;
448✔
1306
         if (!folded_bounds(r_from, &f_low, &f_high))
448✔
1307
            continue;
368✔
1308
         else if (f_low > f_high)
80✔
1309
            continue;  // Null range
1✔
1310

1311
         int64_t folded = 0;
79✔
1312
         const char *error = NULL;
79✔
1313
         if (!index_in_range(tree_left(r_from), low, high, &folded))
79✔
1314
            error = "left";
1315
         else if (!index_in_range(tree_right(r_from), low, high, &folded))
79✔
1316
            error = "right";
1317

1318
         if (error) {
1✔
1319
            diag_t *d = diag_new(DIAG_ERROR, tree_loc(value));
1✔
1320
            diag_printf(d, "array ");
1✔
1321
            if (tree_kind(value) == T_REF)
1✔
1322
               diag_printf(d, "%s ", istr(tree_ident(value)));
1✔
1323
            diag_printf(d, "%s bound ", error);
1✔
1324
            to_string(diag_text_buf(d), index_type, folded);
1✔
1325
            diag_printf(d, " violates %s index constraint ", type_pp(to));
1✔
1326
            format_type_range(d, index_type, tree_subkind(r_to), low, high);
1✔
1327
            diag_emit(d);
1✔
1328
         }
1329
      }
1330
   }
1331
}
2,659✔
1332

1333
static void bounds_check_type_conv(tree_t t)
3,012✔
1334
{
1335
   tree_t value = tree_value(t);
3,012✔
1336

1337
   type_t from = tree_type(value);
3,012✔
1338
   type_t to   = tree_type(t);
3,012✔
1339

1340
   if (type_is_integer(to))
3,012✔
1341
      bounds_check_conv_integer(value, from, to);
154✔
1342
   else if (type_is_array(to))
2,858✔
1343
      bounds_check_conv_array(value, from, to);
2,659✔
1344
}
3,012✔
1345

1346
static void bounds_check_attr_ref(tree_t t)
26,774✔
1347
{
1348
   switch (tree_subkind(t)) {
26,774✔
1349
   case ATTR_LENGTH:
22,885✔
1350
   case ATTR_LOW:
1351
   case ATTR_HIGH:
1352
   case ATTR_LEFT:
1353
   case ATTR_RIGHT:
1354
   case ATTR_RANGE:
1355
   case ATTR_REVERSE_RANGE:
1356
      if (tree_params(t) > 0) {
22,885✔
1357
         type_t type = tree_type(tree_name(t));
94✔
1358
         if (type_is_array(type)) {
94✔
1359
            tree_t dim_tree = tree_value(tree_param(t, 0));
94✔
1360

1361
            int64_t dim;
94✔
1362
            if (!folded_int(dim_tree, &dim))
94✔
UNCOV
1363
               bounds_error(dim_tree, "dimension is not constant");
×
1364
            else if (dim < 1 || dim > dimension_of(type))
94✔
1365
               bounds_error(dim_tree, "invalid dimension %"PRIi64" for type %s",
94✔
1366
                            dim, type_pp(type));
1367
         }
1368
      }
1369
      break;
1370

1371
   default:
1372
      break;
1373
   }
1374
}
26,774✔
1375

1376
static void bounds_check_wait(tree_t t)
12,215✔
1377
{
1378
   int64_t delay = 0;
12,215✔
1379
   if (tree_has_delay(t) && folded_int(tree_delay(t), &delay) && delay < 0)
12,215✔
1380
      bounds_error(tree_delay(t), "wait timeout may not be negative");
12,215✔
1381
}
12,215✔
1382

1383
static void bounds_check_return(tree_t t)
16,513✔
1384
{
1385
   if (!tree_has_value(t))
16,513✔
1386
      return;
1387

1388
   tree_t value = tree_value(t);
16,170✔
1389

1390
   type_t type = tree_type(t);
16,170✔
1391
   if (type_is_scalar(type))
16,170✔
1392
      bounds_check_scalar(value, type, NULL);
7,269✔
1393
   else if (type_is_array(type))
8,901✔
1394
      bounds_check_array(value, type, NULL);
7,721✔
1395
}
1396

1397
static void bounds_check_generic_map(tree_t t, tree_t unit)
1,836✔
1398
{
1399
   const int ngenmaps = tree_genmaps(t);
1,836✔
1400
   for (int i = 0; i < ngenmaps; i++) {
3,893✔
1401
      tree_t m = tree_genmap(t, i);
2,057✔
1402
      assert(tree_subkind(m) == P_POS);
2,057✔
1403

1404
      tree_t g = tree_generic(unit, i);
2,057✔
1405
      if (tree_class(g) == C_CONSTANT)
2,057✔
1406
         bounds_check_assignment(g, tree_value(m));
1,238✔
1407
   }
1408
}
1,836✔
1409

1410
static void bounds_check_port_map(tree_t t, tree_t unit)
1,578✔
1411
{
1412
   const int nparams = tree_params(t);
1,578✔
1413
   for (int i = 0; i < nparams; i++) {
4,907✔
1414
      tree_t m = tree_param(t, i);
3,329✔
1415

1416
      tree_t value = tree_value(m);
3,329✔
1417
      switch (tree_kind(value)) {
3,329✔
1418
      case T_OPEN:
35✔
1419
         continue;
35✔
1420
      case T_INERTIAL:
26✔
1421
         value = tree_value(value);
26✔
1422
         break;
26✔
1423
      default:
1424
         break;
1425
      }
1426

1427
      tree_t formal = NULL;
3,294✔
1428
      switch (tree_subkind(m)) {
3,294✔
1429
      case P_POS:
1,296✔
1430
         formal = tree_port(unit, tree_pos(m));
1,296✔
1431
         break;
1,296✔
1432
      case P_NAMED:
1,998✔
1433
         formal = tree_name(m);
1,998✔
1434
         break;
1,998✔
1435
      }
1436

1437
      switch (tree_kind(formal)) {
3,294✔
1438
      case T_TYPE_CONV:
83✔
1439
      case T_CONV_FUNC:
1440
         continue;   // Ignore for now
83✔
1441
      default:
3,211✔
1442
         bounds_check_assignment(formal, value);
3,211✔
1443
         break;
3,211✔
1444
      }
1445
   }
1446
}
1,578✔
1447

1448
static tree_t bounds_visit_fn(tree_t t, void *context)
1,534,673✔
1449
{
1450
   switch (tree_kind(t)) {
1,534,673✔
1451
   case T_PCALL:
92,028✔
1452
   case T_FCALL:
1453
      bounds_check_call_args(t);
92,028✔
1454
      break;
92,028✔
1455
   case T_ARRAY_REF:
15,807✔
1456
      bounds_check_array_ref(t);
15,807✔
1457
      break;
15,807✔
1458
   case T_ARRAY_SLICE:
2,890✔
1459
      bounds_check_array_slice(t);
2,890✔
1460
      break;
2,890✔
1461
   case T_AGGREGATE:
11,290✔
1462
      bounds_check_aggregate(t);
11,290✔
1463
      break;
11,290✔
1464
   case T_SIGNAL_DECL:
26,768✔
1465
   case T_CONST_DECL:
1466
   case T_VAR_DECL:
1467
      bounds_check_object_decl(t);
26,768✔
1468
      break;
26,768✔
1469
   case T_PORT_DECL:
109,915✔
1470
   case T_PARAM_DECL:
1471
   case T_GENERIC_DECL:
1472
      bounds_check_interface_decl(t);
109,915✔
1473
      break;
109,915✔
1474
   case T_ALIAS:
2,969✔
1475
      bounds_check_alias_decl(t);
2,969✔
1476
      break;
2,969✔
1477
   case T_SIGNAL_ASSIGN:
7,248✔
1478
      bounds_check_signal_assign(t);
7,248✔
1479
      break;
7,248✔
1480
   case T_VAR_ASSIGN:
20,360✔
1481
      bounds_check_var_assign(t);
20,360✔
1482
      break;
20,360✔
1483
   case T_CASE:
585✔
1484
      bounds_check_case(t);
585✔
1485
      break;
585✔
1486
   case T_MATCH_CASE:
36✔
1487
      bounds_check_match_case(t);
36✔
1488
      break;
36✔
1489
   case T_STRING:
23,934✔
1490
      bounds_check_string_literal(t);
23,934✔
1491
      break;
23,934✔
1492
   case T_TYPE_CONV:
3,012✔
1493
      bounds_check_type_conv(t);
3,012✔
1494
      break;
3,012✔
1495
   case T_ATTR_REF:
26,774✔
1496
      bounds_check_attr_ref(t);
26,774✔
1497
      break;
26,774✔
1498
   case T_WAIT:
12,215✔
1499
      bounds_check_wait(t);
12,215✔
1500
      break;
12,215✔
1501
   case T_RETURN:
16,513✔
1502
      bounds_check_return(t);
16,513✔
1503
      break;
16,513✔
1504
   case T_ELEM_CONSTRAINT:
548✔
1505
      bounds_check_elem_constraint(t);
548✔
1506
      break;
548✔
1507
   case T_TYPE_DECL:
4,366✔
1508
      bounds_check_type_decl(t);
4,366✔
1509
      break;
4,366✔
1510
   case T_SUBTYPE_DECL:
1,379✔
1511
      bounds_check_subtype_decl(t);
1,379✔
1512
      break;
1,379✔
1513
   case T_BLOCK:
297✔
1514
      bounds_check_generic_map(t, t);
297✔
1515
      bounds_check_port_map(t, t);
297✔
1516
      break;
297✔
1517
   case T_INSTANCE:
1,281✔
1518
      {
1519
         tree_t primary = primary_unit_of(tree_ref(t));
1,281✔
1520
         bounds_check_generic_map(t, primary);
1,281✔
1521
         bounds_check_port_map(t, primary);
1,281✔
1522
      }
1523
      break;
1,281✔
1524
   case T_PACK_INST:
258✔
1525
      bounds_check_generic_map(t, tree_ref(t));
258✔
1526
      break;
258✔
1527
   default:
1528
      break;
1529
   }
1530

1531
   return t;
1,534,673✔
1532
}
1533

1534
void bounds_check(tree_t top)
11,251✔
1535
{
1536
   tree_rewrite(top, NULL, bounds_visit_fn, NULL, NULL);
11,251✔
1537
}
11,251✔
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