svf-tools 1.0.937 → 1.0.939

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,656 @@
1
+ //===- NumericValue.h ----Numeric Value-------------------------//
2
+ //
3
+ // SVF: Static Value-Flow Analysis
4
+ //
5
+ // Copyright (C) <2013-2022> <Yulei Sui>
6
+ //
7
+
8
+ // This program is free software: you can redistribute it and/or modify
9
+ // it under the terms of the GNU Affero General Public License as published by
10
+ // the Free Software Foundation, either version 3 of the License, or
11
+ // (at your option) any later version.
12
+
13
+ // This program is distributed in the hope that it will be useful,
14
+ // but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
+ // GNU Affero General Public License for more details.
17
+
18
+ // You should have received a copy of the GNU Affero General Public License
19
+ // along with this program. If not, see <http://www.gnu.org/licenses/>.
20
+ //
21
+ //===----------------------------------------------------------------------===//
22
+ /*
23
+ * Numeri Value.h
24
+ *
25
+ * Created on: May 11, 2024
26
+ * Author: Xiao Cheng, Jiawei Ren
27
+ *
28
+ */
29
+
30
+ #ifndef SVF_NUMERICVALUE_H
31
+ #define SVF_NUMERICVALUE_H
32
+
33
+ #include "SVFIR/SVFType.h"
34
+ #include <cmath>
35
+ #include <cfloat> // For DBL_MAX
36
+ #include <utility>
37
+
38
+
39
+ #define epsilon std::numeric_limits<double>::epsilon();
40
+ namespace SVF
41
+ {
42
+
43
+ /*!
44
+ * Bounded double numeric value
45
+ */
46
+ class BoundedDouble
47
+ {
48
+ protected:
49
+
50
+ double _fVal;
51
+
52
+ BoundedDouble() = default;
53
+
54
+ public:
55
+ BoundedDouble(double fVal) : _fVal(fVal) {}
56
+
57
+ BoundedDouble(const BoundedDouble& rhs) : _fVal(rhs._fVal) {}
58
+
59
+ BoundedDouble& operator=(const BoundedDouble& rhs)
60
+ {
61
+ _fVal = rhs._fVal;
62
+ return *this;
63
+ }
64
+
65
+ BoundedDouble(BoundedDouble &&rhs) : _fVal(std::move(rhs._fVal)) {}
66
+
67
+ BoundedDouble& operator=(BoundedDouble&& rhs)
68
+ {
69
+ _fVal = std::move(rhs._fVal);
70
+ return *this;
71
+ }
72
+
73
+ virtual ~BoundedDouble() {}
74
+
75
+
76
+ static bool doubleEqual(double a, double b)
77
+ {
78
+ if (std::isinf(a) && std::isinf(b))
79
+ return a == b;
80
+ return std::fabs(a - b) < epsilon;
81
+ }
82
+
83
+ const double getFVal() const
84
+ {
85
+ return _fVal;
86
+ }
87
+
88
+ bool is_plus_infinity() const
89
+ {
90
+ return _fVal == std::numeric_limits<double>::infinity();
91
+ }
92
+
93
+ bool is_minus_infinity() const
94
+ {
95
+ return _fVal == -std::numeric_limits<double>::infinity();
96
+ }
97
+
98
+ bool is_infinity() const
99
+ {
100
+ return is_plus_infinity() || is_minus_infinity();
101
+ }
102
+
103
+ void set_plus_infinity()
104
+ {
105
+ *this = plus_infinity();
106
+ }
107
+
108
+ void set_minus_infinity()
109
+ {
110
+ *this = minus_infinity();
111
+ }
112
+
113
+ static BoundedDouble plus_infinity()
114
+ {
115
+ return std::numeric_limits<double>::infinity();
116
+ }
117
+
118
+ static BoundedDouble minus_infinity()
119
+ {
120
+ return -std::numeric_limits<double>::infinity();
121
+ }
122
+
123
+
124
+ bool is_zero() const
125
+ {
126
+ return doubleEqual(_fVal, 0.0f);
127
+ }
128
+
129
+ static bool isZero(const BoundedDouble &expr)
130
+ {
131
+ return doubleEqual(expr.getFVal(), 0.0f);
132
+ }
133
+
134
+ bool equal(const BoundedDouble &rhs) const
135
+ {
136
+ return doubleEqual(_fVal, rhs._fVal);
137
+ }
138
+
139
+ bool leq(const BoundedDouble &rhs) const
140
+ {
141
+ if (is_infinity() ^ rhs.is_infinity())
142
+ {
143
+ if (is_infinity())
144
+ {
145
+ return is_minus_infinity();
146
+ }
147
+ else
148
+ {
149
+ return rhs.is_plus_infinity();
150
+ }
151
+ }
152
+ if(is_infinity() && rhs.is_infinity())
153
+ {
154
+ if(is_minus_infinity()) return true;
155
+ else return rhs.is_plus_infinity();
156
+ }
157
+ else
158
+ return _fVal <= rhs._fVal;
159
+ }
160
+
161
+ bool geq(const BoundedDouble &rhs) const
162
+ {
163
+ if (is_infinity() ^ rhs.is_infinity())
164
+ {
165
+ if (is_infinity())
166
+ {
167
+ return is_plus_infinity();
168
+ }
169
+ else
170
+ {
171
+ return rhs.is_minus_infinity();
172
+ }
173
+ }
174
+ if(is_infinity() && rhs.is_infinity())
175
+ {
176
+ if(is_plus_infinity()) return true;
177
+ else return rhs.is_minus_infinity();
178
+ }
179
+ else
180
+ return _fVal >= rhs._fVal;
181
+ }
182
+
183
+ /// Reload operator
184
+ //{%
185
+ friend BoundedDouble operator==(const BoundedDouble &lhs, const BoundedDouble &rhs)
186
+ {
187
+ return lhs.equal(rhs);
188
+ }
189
+
190
+ friend BoundedDouble operator!=(const BoundedDouble &lhs, const BoundedDouble &rhs)
191
+ {
192
+ return !lhs.equal(rhs);
193
+ }
194
+
195
+ friend BoundedDouble operator>(const BoundedDouble &lhs, const BoundedDouble &rhs)
196
+ {
197
+ return !lhs.leq(rhs);
198
+ }
199
+
200
+ friend BoundedDouble operator<(const BoundedDouble &lhs, const BoundedDouble &rhs)
201
+ {
202
+ return !lhs.geq(rhs);
203
+ }
204
+
205
+ friend BoundedDouble operator<=(const BoundedDouble &lhs, const BoundedDouble &rhs)
206
+ {
207
+ return lhs.leq(rhs);
208
+ }
209
+
210
+ friend BoundedDouble operator>=(const BoundedDouble &lhs, const BoundedDouble &rhs)
211
+ {
212
+ return lhs.geq(rhs);
213
+ }
214
+
215
+ /**
216
+ * Adds two floating-point numbers safely, checking for overflow and
217
+ * underflow conditions.
218
+ *
219
+ * @param lhs Left-hand side operand of the addition.
220
+ * @param rhs Right-hand side operand of the addition.
221
+ * @return The sum of lhs and rhs. If overflow or underflow occurs, returns
222
+ * positive or negative infinity.
223
+ */
224
+ static double safeAdd(double lhs, double rhs)
225
+ {
226
+ if ((lhs == std::numeric_limits<double>::infinity() &&
227
+ rhs == -std::numeric_limits<double>::infinity()) ||
228
+ (lhs == -std::numeric_limits<double>::infinity() &&
229
+ rhs == std::numeric_limits<double>::infinity()))
230
+ {
231
+ assert(false && "invalid add");
232
+ }
233
+ double res =
234
+ lhs + rhs; // Perform the addition and store the result in 'res'
235
+
236
+ // Check if the result is positive infinity due to overflow
237
+ if (res == std::numeric_limits<double>::infinity())
238
+ {
239
+ return res; // Positive overflow has occurred, return positive
240
+ // infinity
241
+ }
242
+
243
+ // Check if the result is negative infinity, which can indicate a large
244
+ // negative overflow
245
+ if (res == -std::numeric_limits<double>::infinity())
246
+ {
247
+ return res; // Negative "overflow", effectively an underflow to
248
+ // negative infinity
249
+ }
250
+
251
+ // Check for positive overflow: verify if both operands are positive and
252
+ // their sum exceeds the maximum double value
253
+ if (lhs > 0 && rhs > 0 &&
254
+ (std::numeric_limits<double>::max() - lhs) < rhs)
255
+ {
256
+ res =
257
+ std::numeric_limits<double>::infinity(); // Set result to
258
+ // positive infinity to
259
+ // indicate overflow
260
+ return res;
261
+ }
262
+
263
+ // Check for an underflow scenario: both numbers are negative and their
264
+ // sum is more negative than what double can represent
265
+ if (lhs < 0 && rhs < 0 &&
266
+ (-std::numeric_limits<double>::max() - lhs) > rhs)
267
+ {
268
+ res = -std::numeric_limits<
269
+ double>::infinity(); // Set result to negative infinity to
270
+ // clarify extreme negative sum
271
+ return res;
272
+ }
273
+
274
+ // If none of the above conditions are met, return the result of the
275
+ // addition
276
+ return res;
277
+ }
278
+
279
+ friend BoundedDouble operator+(const BoundedDouble &lhs, const BoundedDouble &rhs)
280
+ {
281
+ return safeAdd(lhs._fVal, rhs._fVal);
282
+ }
283
+
284
+ friend BoundedDouble operator-(const BoundedDouble &lhs)
285
+ {
286
+ return -lhs._fVal;
287
+ }
288
+
289
+ friend BoundedDouble operator-(const BoundedDouble &lhs, const BoundedDouble &rhs)
290
+ {
291
+ return safeAdd(lhs._fVal, -rhs._fVal);
292
+ }
293
+
294
+ /**
295
+ * Safely multiplies two floating-point numbers, checking for overflow and
296
+ * underflow.
297
+ *
298
+ * @param lhs Left-hand side operand of the multiplication.
299
+ * @param rhs Right-hand side operand of the multiplication.
300
+ * @return The product of lhs and rhs. If overflow or underflow occurs,
301
+ * returns positive or negative infinity accordingly.
302
+ */
303
+ static double safeMul(double lhs, double rhs)
304
+ {
305
+ if (doubleEqual(lhs, 0.0f) || doubleEqual(rhs, 0.0f))
306
+ return 0.0f;
307
+ double res = lhs * rhs;
308
+ // Check if the result is positive infinity due to overflow
309
+ if (res == std::numeric_limits<double>::infinity())
310
+ {
311
+ return res; // Positive overflow has occurred, return positive
312
+ // infinity
313
+ }
314
+
315
+ // Check if the result is negative infinity, which can indicate a large
316
+ // negative overflow
317
+ if (res == -std::numeric_limits<double>::infinity())
318
+ {
319
+ return res; // Negative "overflow", effectively an underflow to
320
+ // negative infinity
321
+ }
322
+ // Check for overflow scenarios
323
+ if (lhs > 0 && rhs > 0 && lhs > std::numeric_limits<double>::max() / rhs)
324
+ {
325
+ return std::numeric_limits<double>::infinity();
326
+ }
327
+ if (lhs < 0 && rhs < 0 && lhs < std::numeric_limits<double>::max() / rhs)
328
+ {
329
+ return std::numeric_limits<double>::infinity();
330
+ }
331
+
332
+ // Check for "underflow" scenarios (negative overflow)
333
+ if (lhs > 0 && rhs < 0 &&
334
+ rhs < std::numeric_limits<double>::lowest() / lhs)
335
+ {
336
+ return -std::numeric_limits<double>::infinity();
337
+ }
338
+ if (lhs < 0 && rhs > 0 &&
339
+ lhs < std::numeric_limits<double>::lowest() / rhs)
340
+ {
341
+ return -std::numeric_limits<double>::infinity();
342
+ }
343
+
344
+ return res; // If no overflow or underflow, return the product
345
+ }
346
+
347
+ friend BoundedDouble operator*(const BoundedDouble &lhs, const BoundedDouble &rhs)
348
+ {
349
+ return safeMul(lhs._fVal, rhs._fVal);
350
+ }
351
+
352
+ /**
353
+ * Safely divides one floating-point number by another, checking for
354
+ * division by zero and overflow.
355
+ *
356
+ * @param lhs Left-hand side operand (numerator).
357
+ * @param rhs Right-hand side operand (denominator).
358
+ * @return The quotient of lhs and rhs. Returns positive or negative
359
+ * infinity for division by zero, or when overflow occurs.
360
+ */
361
+ static double safeDiv(double lhs, double rhs)
362
+ {
363
+ // Check for division by zero
364
+ if (doubleEqual(rhs, 0.0f))
365
+ {
366
+ return (lhs >= 0.0f) ? std::numeric_limits<double>::infinity()
367
+ : -std::numeric_limits<double>::infinity();
368
+ }
369
+ double res = lhs / rhs;
370
+ // Check if the result is positive infinity due to overflow
371
+ if (res == std::numeric_limits<double>::infinity())
372
+ {
373
+ return res; // Positive overflow has occurred, return positive
374
+ // infinity
375
+ }
376
+
377
+ // Check if the result is negative infinity, which can indicate a large
378
+ // negative overflow
379
+ if (res == -std::numeric_limits<double>::infinity())
380
+ {
381
+ return res; // Negative "overflow", effectively an underflow to
382
+ // negative infinity
383
+ }
384
+
385
+ // Check for overflow when dividing small numbers
386
+ if (rhs > 0 && rhs < std::numeric_limits<double>::min() &&
387
+ lhs > std::numeric_limits<double>::max() * rhs)
388
+ {
389
+ return std::numeric_limits<double>::infinity();
390
+ }
391
+ if (rhs < 0 && rhs > -std::numeric_limits<double>::min() &&
392
+ lhs > std::numeric_limits<double>::max() * rhs)
393
+ {
394
+ return -std::numeric_limits<double>::infinity();
395
+ }
396
+
397
+ return res; // If no special cases, return the quotient
398
+ }
399
+
400
+ friend BoundedDouble operator/(const BoundedDouble &lhs, const BoundedDouble &rhs)
401
+ {
402
+ return safeDiv(lhs._fVal, rhs._fVal);
403
+ }
404
+
405
+ friend BoundedDouble operator%(const BoundedDouble &lhs, const BoundedDouble &rhs)
406
+ {
407
+ if (rhs.is_zero()) assert(false && "divide by zero");
408
+ else if (!lhs.is_infinity() && !rhs.is_infinity())
409
+ return std::fmod(lhs._fVal, rhs._fVal);
410
+ else if (!lhs.is_infinity() && rhs.is_infinity())
411
+ return 0.0f;
412
+ // TODO: not sure
413
+ else if (lhs.is_infinity() && !rhs.is_infinity())
414
+ return ite(rhs._fVal > 0.0f, lhs, -lhs);
415
+ else
416
+ // TODO: +oo/-oo L'Hôpital's rule?
417
+ return eq(lhs, rhs) ? plus_infinity() : minus_infinity();
418
+ abort();
419
+ }
420
+
421
+ inline bool is_int() const
422
+ {
423
+ return _fVal == std::round(_fVal);
424
+ }
425
+ inline bool is_real() const
426
+ {
427
+ return !is_int();
428
+ }
429
+
430
+ friend BoundedDouble operator^(const BoundedDouble &lhs, const BoundedDouble &rhs)
431
+ {
432
+ int lInt = std::round(rhs._fVal), rInt = std::round(rhs._fVal);
433
+ return lInt ^ rInt;
434
+ }
435
+
436
+ friend BoundedDouble operator&(const BoundedDouble &lhs, const BoundedDouble &rhs)
437
+ {
438
+ int lInt = std::round(rhs._fVal), rInt = std::round(rhs._fVal);
439
+ return lInt & rInt;
440
+ }
441
+
442
+ friend BoundedDouble operator|(const BoundedDouble &lhs, const BoundedDouble &rhs)
443
+ {
444
+ int lInt = std::round(rhs._fVal), rInt = std::round(rhs._fVal);
445
+ return lInt | rInt;
446
+ }
447
+
448
+
449
+ friend BoundedDouble operator&&(const BoundedDouble &lhs, const BoundedDouble &rhs)
450
+ {
451
+ return lhs._fVal && rhs._fVal;
452
+ }
453
+
454
+ friend BoundedDouble operator||(const BoundedDouble &lhs, const BoundedDouble &rhs)
455
+ {
456
+ return lhs._fVal || rhs._fVal;
457
+ }
458
+
459
+ friend BoundedDouble operator!(const BoundedDouble &lhs)
460
+ {
461
+ return !lhs._fVal;
462
+ }
463
+
464
+ friend BoundedDouble operator>>(const BoundedDouble &lhs, const BoundedDouble &rhs)
465
+ {
466
+ assert(rhs.geq(0) && "rhs should be greater or equal than 0");
467
+ if (lhs.is_zero())
468
+ return lhs;
469
+ else if (lhs.is_infinity())
470
+ return lhs;
471
+ else if (rhs.is_infinity())
472
+ return lhs.geq(0) ? 0 : -1;
473
+ else
474
+ return (s32_t) lhs.getNumeral() >> (s32_t) rhs.getNumeral();
475
+ }
476
+
477
+ friend BoundedDouble operator<<(const BoundedDouble &lhs, const BoundedDouble &rhs)
478
+ {
479
+ assert(rhs.geq(0) && "rhs should be greater or equal than 0");
480
+ if (lhs.is_zero())
481
+ return lhs;
482
+ else if (lhs.is_infinity())
483
+ return lhs;
484
+ else if (rhs.is_infinity())
485
+ return lhs.geq(0) ? plus_infinity() : minus_infinity();
486
+ else
487
+ return (s32_t) lhs.getNumeral() << (s32_t) rhs.getNumeral();
488
+ }
489
+
490
+ friend BoundedDouble ite(const BoundedDouble& cond, const BoundedDouble& lhs,
491
+ const BoundedDouble& rhs)
492
+ {
493
+ return cond._fVal != 0.0f ? lhs._fVal : rhs._fVal;
494
+ }
495
+
496
+ friend std::ostream &operator<<(std::ostream &out, const BoundedDouble &expr)
497
+ {
498
+ out << expr._fVal;
499
+ return out;
500
+ }
501
+
502
+ friend bool eq(const BoundedDouble &lhs, const BoundedDouble &rhs)
503
+ {
504
+ return doubleEqual(lhs._fVal, rhs._fVal);
505
+ }
506
+
507
+ friend BoundedDouble min(const BoundedDouble &lhs, const BoundedDouble &rhs)
508
+ {
509
+ return std::min(lhs._fVal, rhs._fVal);
510
+ }
511
+
512
+ friend BoundedDouble max(const BoundedDouble &lhs, const BoundedDouble &rhs)
513
+ {
514
+ return std::max(lhs._fVal, rhs._fVal);
515
+ }
516
+
517
+ static BoundedDouble min(std::vector<BoundedDouble>& _l)
518
+ {
519
+ BoundedDouble ret(plus_infinity());
520
+ for (const auto &it: _l)
521
+ {
522
+ if (it.is_minus_infinity())
523
+ return minus_infinity();
524
+ else if (!it.geq(ret))
525
+ {
526
+ ret = it;
527
+ }
528
+ }
529
+ return ret;
530
+ }
531
+
532
+ static BoundedDouble max(std::vector<BoundedDouble>& _l)
533
+ {
534
+ BoundedDouble ret(minus_infinity());
535
+ for (const auto &it: _l)
536
+ {
537
+ if (it.is_plus_infinity())
538
+ return plus_infinity();
539
+ else if (!it.leq(ret))
540
+ {
541
+ ret = it;
542
+ }
543
+ }
544
+ return ret;
545
+ }
546
+
547
+ friend BoundedDouble abs(const BoundedDouble &lhs)
548
+ {
549
+ return lhs.leq(0) ? -lhs : lhs;
550
+ }
551
+
552
+ inline bool is_true() const
553
+ {
554
+ return _fVal != 0.0f;
555
+ }
556
+
557
+ /// Return Numeral
558
+ inline s64_t getNumeral() const
559
+ {
560
+ if (is_minus_infinity())
561
+ {
562
+ return INT64_MIN;
563
+ }
564
+ else if (is_plus_infinity())
565
+ {
566
+ return INT64_MAX;
567
+ }
568
+ else
569
+ {
570
+ return std::round(_fVal);
571
+ }
572
+ }
573
+
574
+ inline s64_t getIntNumeral() const
575
+ {
576
+ return getNumeral();
577
+ }
578
+
579
+ inline double getRealNumeral() const
580
+ {
581
+ return _fVal;
582
+ }
583
+
584
+ inline virtual const std::string to_string() const
585
+ {
586
+ return std::to_string(_fVal);
587
+ }
588
+
589
+ //%}
590
+ }; // end class BoundedDouble
591
+
592
+ class BoundedInt : public BoundedDouble
593
+ {
594
+ private:
595
+ BoundedInt() = default;
596
+
597
+ public:
598
+
599
+ BoundedInt(s32_t val)
600
+ {
601
+ _fVal = val;
602
+ }
603
+
604
+ BoundedInt(s64_t val)
605
+ {
606
+ _fVal = val;
607
+ }
608
+
609
+ BoundedInt(const BoundedInt& rhs)
610
+ {
611
+ _fVal = rhs._fVal;
612
+ }
613
+
614
+ BoundedInt& operator=(const BoundedInt& rhs)
615
+ {
616
+ _fVal = rhs._fVal;
617
+ return *this;
618
+ }
619
+
620
+ BoundedInt(BoundedInt&& rhs)
621
+ {
622
+ _fVal = rhs._fVal;
623
+ }
624
+
625
+ BoundedInt& operator=(const BoundedInt&& rhs)
626
+ {
627
+ _fVal = rhs._fVal;
628
+ return *this;
629
+ }
630
+
631
+ BoundedInt(double val)
632
+ {
633
+ _fVal = val;
634
+ }
635
+
636
+ BoundedInt(const BoundedDouble& f)
637
+ {
638
+ _fVal = f.getFVal();
639
+ }
640
+
641
+ virtual ~BoundedInt() {}
642
+
643
+ inline const std::string to_string() const override
644
+ {
645
+ if (is_minus_infinity())
646
+ return "-∞";
647
+ else if (is_plus_infinity())
648
+ return "∞";
649
+ else
650
+ return std::to_string(getIntNumeral());
651
+ }
652
+ };
653
+
654
+ } // end namespace SVF
655
+
656
+ #endif // SVF_NUMERICVALUE_H
@@ -58,24 +58,33 @@ public:
58
58
 
59
59
 
60
60
  /// Return Z3 expression lazily based on SVFVar ID
61
- virtual inline Z3Expr toZ3Expr(u32_t varId) const
61
+ virtual inline Z3Expr toIntZ3Expr(u32_t varId) const
62
62
  {
63
63
  return Z3Expr::getContext().int_const(std::to_string(varId).c_str());
64
64
  }
65
65
 
66
+ inline Z3Expr toIntVal(s32_t f) const
67
+ {
68
+ return Z3Expr::getContext().int_val(f);
69
+ }
70
+ inline Z3Expr toRealVal(BoundedDouble f) const
71
+ {
72
+ return Z3Expr::getContext().real_val(std::to_string(f.getFVal()).c_str());
73
+ }
74
+
66
75
  /* two optional solvers: RSY and bilateral */
67
76
 
68
77
  AbstractState bilateral(const AbstractState& domain, const Z3Expr &phi, u32_t descend_check = 0);
69
78
 
70
79
  AbstractState RSY(const AbstractState& domain, const Z3Expr &phi);
71
80
 
72
- Map<u32_t, NumericLiteral> BoxedOptSolver(const Z3Expr& phi, Map<u32_t, NumericLiteral>& ret, Map<u32_t, NumericLiteral>& low_values, Map<u32_t, NumericLiteral>& high_values);
81
+ Map<u32_t, s32_t> BoxedOptSolver(const Z3Expr& phi, Map<u32_t, s32_t>& ret, Map<u32_t, s32_t>& low_values, Map<u32_t, s32_t>& high_values);
73
82
 
74
83
  AbstractState BS(const AbstractState& domain, const Z3Expr &phi);
75
84
 
76
- void updateMap(Map<u32_t, NumericLiteral>& map, u32_t key, const NumericLiteral& value);
85
+ void updateMap(Map<u32_t, s32_t>& map, u32_t key, const s32_t& value);
77
86
 
78
- void decide_cpa_ext(const Z3Expr &phi, Map<u32_t, Z3Expr>&, Map<u32_t, NumericLiteral>&, Map<u32_t, NumericLiteral>&, Map<u32_t, NumericLiteral>&, Map<u32_t, NumericLiteral>&);
87
+ void decide_cpa_ext(const Z3Expr &phi, Map<u32_t, Z3Expr>&, Map<u32_t, s32_t>&, Map<u32_t, s32_t>&, Map<u32_t, s32_t>&, Map<u32_t, s32_t>&);
79
88
  };
80
89
  }
81
90