Skip to content

Commit 075d97a

Browse files
authored
Merge pull request #3147 from danpoe/refactor/use-validation-methods-in-std-types
Move existing type validation checks to new framework
2 parents 7026abc + f2dfd2e commit 075d97a

File tree

3 files changed

+95
-86
lines changed

3 files changed

+95
-86
lines changed

src/util/expr_cast.h

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -48,16 +48,6 @@ inline bool can_cast_type(const typet &base);
4848
/// validate objects in this way at any time.
4949
inline void validate_expr(const exprt &) {}
5050

51-
/// Called after casting. Provides a point to check data invariants on the
52-
/// structure of the typet. By default, this is a no-op, but you can provide an
53-
/// overload to validate particular types. Should always succeed unless the
54-
/// program has entered an invalid state. We validate objects at cast time as
55-
/// that is when these checks have been used historically, but it would be
56-
/// reasonable to validate objects in this way at any time.
57-
inline void validate_type(const typet &)
58-
{
59-
}
60-
6151
namespace detail // NOLINT
6252
{
6353

@@ -155,9 +145,8 @@ auto type_try_dynamic_cast(TType &base) ->
155145
"The template argument T must be derived from typet.");
156146
if(!can_cast_type<typename std::remove_const<T>::type>(base))
157147
return nullptr;
158-
const auto ret = static_cast<returnt>(&base);
159-
validate_type(*ret);
160-
return ret;
148+
TType::check(base);
149+
return static_cast<returnt>(&base);
161150
}
162151

163152
/// \brief Try to cast a generic typet to a specific derived class.

src/util/std_types.h

Lines changed: 71 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -968,15 +968,15 @@ inline bool can_cast_type<code_typet>(const typet &type)
968968
inline const code_typet &to_code_type(const typet &type)
969969
{
970970
PRECONDITION(can_cast_type<code_typet>(type));
971-
validate_type(type);
971+
code_typet::check(type);
972972
return static_cast<const code_typet &>(type);
973973
}
974974

975975
/// \copydoc to_code_type(const typet &)
976976
inline code_typet &to_code_type(typet &type)
977977
{
978978
PRECONDITION(can_cast_type<code_typet>(type));
979-
validate_type(type);
979+
code_typet::check(type);
980980
return static_cast<code_typet &>(type);
981981
}
982982

@@ -1125,6 +1125,13 @@ class bv_typet:public bitvector_typet
11251125
{
11261126
set_width(width);
11271127
}
1128+
1129+
static void check(
1130+
const typet &type,
1131+
const validation_modet vm = validation_modet::INVARIANT)
1132+
{
1133+
DATA_CHECK(!type.get(ID_width).empty(), "bitvector type must have width");
1134+
}
11281135
};
11291136

11301137
/// Check whether a reference to a typet is a \ref bv_typet.
@@ -1136,11 +1143,6 @@ inline bool can_cast_type<bv_typet>(const typet &type)
11361143
return type.id() == ID_bv;
11371144
}
11381145

1139-
inline void validate_type(const bv_typet &type)
1140-
{
1141-
DATA_INVARIANT(!type.get(ID_width).empty(), "bitvector type must have width");
1142-
}
1143-
11441146
/// \brief Cast a typet to a \ref bv_typet
11451147
///
11461148
/// This is an unchecked conversion. \a type must be known to be \ref
@@ -1152,18 +1154,16 @@ inline void validate_type(const bv_typet &type)
11521154
inline const bv_typet &to_bv_type(const typet &type)
11531155
{
11541156
PRECONDITION(can_cast_type<bv_typet>(type));
1155-
const bv_typet &ret = static_cast<const bv_typet &>(type);
1156-
validate_type(ret);
1157-
return ret;
1157+
bv_typet::check(type);
1158+
return static_cast<const bv_typet &>(type);
11581159
}
11591160

11601161
/// \copydoc to_bv_type(const typet &)
11611162
inline bv_typet &to_bv_type(typet &type)
11621163
{
11631164
PRECONDITION(can_cast_type<bv_typet>(type));
1164-
bv_typet &ret = static_cast<bv_typet &>(type);
1165-
validate_type(ret);
1166-
return ret;
1165+
bv_typet::check(type);
1166+
return static_cast<bv_typet &>(type);
11671167
}
11681168

11691169
/// Fixed-width bit-vector with unsigned binary interpretation
@@ -1235,6 +1235,14 @@ class signedbv_typet:public bitvector_typet
12351235
constant_exprt smallest_expr() const;
12361236
constant_exprt zero_expr() const;
12371237
constant_exprt largest_expr() const;
1238+
1239+
static void check(
1240+
const typet &type,
1241+
const validation_modet vm = validation_modet::INVARIANT)
1242+
{
1243+
DATA_CHECK(
1244+
!type.get(ID_width).empty(), "signed bitvector type must have width");
1245+
}
12381246
};
12391247

12401248
/// Check whether a reference to a typet is a \ref signedbv_typet.
@@ -1246,12 +1254,6 @@ inline bool can_cast_type<signedbv_typet>(const typet &type)
12461254
return type.id() == ID_signedbv;
12471255
}
12481256

1249-
inline void validate_type(const signedbv_typet &type)
1250-
{
1251-
DATA_INVARIANT(
1252-
!type.get(ID_width).empty(), "signed bitvector type must have width");
1253-
}
1254-
12551257
/// \brief Cast a typet to a \ref signedbv_typet
12561258
///
12571259
/// This is an unchecked conversion. \a type must be known to be \ref
@@ -1263,18 +1265,16 @@ inline void validate_type(const signedbv_typet &type)
12631265
inline const signedbv_typet &to_signedbv_type(const typet &type)
12641266
{
12651267
PRECONDITION(can_cast_type<signedbv_typet>(type));
1266-
const signedbv_typet &ret = static_cast<const signedbv_typet &>(type);
1267-
validate_type(ret);
1268-
return ret;
1268+
signedbv_typet::check(type);
1269+
return static_cast<const signedbv_typet &>(type);
12691270
}
12701271

12711272
/// \copydoc to_signedbv_type(const typet &)
12721273
inline signedbv_typet &to_signedbv_type(typet &type)
12731274
{
12741275
PRECONDITION(can_cast_type<signedbv_typet>(type));
1275-
signedbv_typet &ret = static_cast<signedbv_typet &>(type);
1276-
validate_type(ret);
1277-
return ret;
1276+
signedbv_typet::check(type);
1277+
return static_cast<signedbv_typet &>(type);
12781278
}
12791279

12801280
/// Fixed-width bit-vector with signed fixed-point interpretation
@@ -1299,6 +1299,14 @@ class fixedbv_typet:public bitvector_typet
12991299
{
13001300
set(ID_integer_bits, narrow_cast<long long>(b));
13011301
}
1302+
1303+
static void check(
1304+
const typet &type,
1305+
const validation_modet vm = validation_modet::INVARIANT)
1306+
{
1307+
DATA_CHECK(
1308+
!type.get(ID_width).empty(), "fixed bitvector type must have width");
1309+
}
13021310
};
13031311

13041312
/// Check whether a reference to a typet is a \ref fixedbv_typet.
@@ -1310,12 +1318,6 @@ inline bool can_cast_type<fixedbv_typet>(const typet &type)
13101318
return type.id() == ID_fixedbv;
13111319
}
13121320

1313-
inline void validate_type(const fixedbv_typet &type)
1314-
{
1315-
DATA_INVARIANT(
1316-
!type.get(ID_width).empty(), "fixed bitvector type must have width");
1317-
}
1318-
13191321
/// \brief Cast a typet to a \ref fixedbv_typet
13201322
///
13211323
/// This is an unchecked conversion. \a type must be known to be \ref
@@ -1327,18 +1329,16 @@ inline void validate_type(const fixedbv_typet &type)
13271329
inline const fixedbv_typet &to_fixedbv_type(const typet &type)
13281330
{
13291331
PRECONDITION(can_cast_type<fixedbv_typet>(type));
1330-
const fixedbv_typet &ret = static_cast<const fixedbv_typet &>(type);
1331-
validate_type(ret);
1332-
return ret;
1332+
fixedbv_typet::check(type);
1333+
return static_cast<const fixedbv_typet &>(type);
13331334
}
13341335

13351336
/// \copydoc to_fixedbv_type(const typet &)
13361337
inline fixedbv_typet &to_fixedbv_type(typet &type)
13371338
{
13381339
PRECONDITION(can_cast_type<fixedbv_typet>(type));
1339-
fixedbv_typet &ret = static_cast<fixedbv_typet &>(type);
1340-
validate_type(ret);
1341-
return ret;
1340+
fixedbv_typet::check(type);
1341+
return static_cast<fixedbv_typet &>(type);
13421342
}
13431343

13441344
/// Fixed-width bit-vector with IEEE floating-point interpretation
@@ -1361,6 +1361,14 @@ class floatbv_typet:public bitvector_typet
13611361
{
13621362
set(ID_f, narrow_cast<long long>(b));
13631363
}
1364+
1365+
static void check(
1366+
const typet &type,
1367+
const validation_modet vm = validation_modet::INVARIANT)
1368+
{
1369+
DATA_CHECK(
1370+
!type.get(ID_width).empty(), "float bitvector type must have width");
1371+
}
13641372
};
13651373

13661374
/// Check whether a reference to a typet is a \ref floatbv_typet.
@@ -1372,12 +1380,6 @@ inline bool can_cast_type<floatbv_typet>(const typet &type)
13721380
return type.id() == ID_floatbv;
13731381
}
13741382

1375-
inline void validate_type(const floatbv_typet &type)
1376-
{
1377-
DATA_INVARIANT(
1378-
!type.get(ID_width).empty(), "float bitvector type must have width");
1379-
}
1380-
13811383
/// \brief Cast a typet to a \ref floatbv_typet
13821384
///
13831385
/// This is an unchecked conversion. \a type must be known to be \ref
@@ -1389,18 +1391,16 @@ inline void validate_type(const floatbv_typet &type)
13891391
inline const floatbv_typet &to_floatbv_type(const typet &type)
13901392
{
13911393
PRECONDITION(can_cast_type<floatbv_typet>(type));
1392-
const floatbv_typet &ret = static_cast<const floatbv_typet &>(type);
1393-
validate_type(ret);
1394-
return ret;
1394+
floatbv_typet::check(type);
1395+
return static_cast<const floatbv_typet &>(type);
13951396
}
13961397

13971398
/// \copydoc to_floatbv_type(const typet &)
13981399
inline floatbv_typet &to_floatbv_type(typet &type)
13991400
{
14001401
PRECONDITION(can_cast_type<floatbv_typet>(type));
1401-
floatbv_typet &ret = static_cast<floatbv_typet &>(type);
1402-
validate_type(ret);
1403-
return ret;
1402+
floatbv_typet::check(type);
1403+
return static_cast<floatbv_typet &>(type);
14041404
}
14051405

14061406
/// Type for C bit fields
@@ -1464,6 +1464,13 @@ class pointer_typet:public bitvector_typet
14641464
{
14651465
return signedbv_typet(get_width());
14661466
}
1467+
1468+
static void check(
1469+
const typet &type,
1470+
const validation_modet vm = validation_modet::INVARIANT)
1471+
{
1472+
DATA_CHECK(!type.get(ID_width).empty(), "pointer must have width");
1473+
}
14671474
};
14681475

14691476
/// Check whether a reference to a typet is a \ref pointer_typet.
@@ -1475,11 +1482,6 @@ inline bool can_cast_type<pointer_typet>(const typet &type)
14751482
return type.id() == ID_pointer;
14761483
}
14771484

1478-
inline void validate_type(const pointer_typet &type)
1479-
{
1480-
DATA_INVARIANT(!type.get(ID_width).empty(), "pointer must have width");
1481-
}
1482-
14831485
/// \brief Cast a typet to a \ref pointer_typet
14841486
///
14851487
/// This is an unchecked conversion. \a type must be known to be \ref
@@ -1491,18 +1493,16 @@ inline void validate_type(const pointer_typet &type)
14911493
inline const pointer_typet &to_pointer_type(const typet &type)
14921494
{
14931495
PRECONDITION(can_cast_type<pointer_typet>(type));
1494-
const pointer_typet &ret = static_cast<const pointer_typet &>(type);
1495-
validate_type(ret);
1496-
return ret;
1496+
pointer_typet::check(type);
1497+
return static_cast<const pointer_typet &>(type);
14971498
}
14981499

14991500
/// \copydoc to_pointer_type(const typet &)
15001501
inline pointer_typet &to_pointer_type(typet &type)
15011502
{
15021503
PRECONDITION(can_cast_type<pointer_typet>(type));
1503-
pointer_typet &ret = static_cast<pointer_typet &>(type);
1504-
validate_type(ret);
1505-
return ret;
1504+
pointer_typet::check(type);
1505+
return static_cast<pointer_typet &>(type);
15061506
}
15071507

15081508
/// The reference type
@@ -1562,6 +1562,13 @@ class c_bool_typet:public bitvector_typet
15621562
bitvector_typet(ID_c_bool, width)
15631563
{
15641564
}
1565+
1566+
static void check(
1567+
const typet &type,
1568+
const validation_modet vm = validation_modet::INVARIANT)
1569+
{
1570+
DATA_CHECK(!type.get(ID_width).empty(), "C bool type must have width");
1571+
}
15651572
};
15661573

15671574
/// Check whether a reference to a typet is a \ref c_bool_typet.
@@ -1573,11 +1580,6 @@ inline bool can_cast_type<c_bool_typet>(const typet &type)
15731580
return type.id() == ID_c_bool;
15741581
}
15751582

1576-
inline void validate_type(const c_bool_typet &type)
1577-
{
1578-
DATA_INVARIANT(!type.get(ID_width).empty(), "C bool type must have width");
1579-
}
1580-
15811583
/// \brief Cast a typet to a \ref c_bool_typet
15821584
///
15831585
/// This is an unchecked conversion. \a type must be known to be \ref
@@ -1589,18 +1591,16 @@ inline void validate_type(const c_bool_typet &type)
15891591
inline const c_bool_typet &to_c_bool_type(const typet &type)
15901592
{
15911593
PRECONDITION(can_cast_type<c_bool_typet>(type));
1592-
const c_bool_typet &ret = static_cast<const c_bool_typet &>(type);
1593-
validate_type(ret);
1594-
return ret;
1594+
c_bool_typet::check(type);
1595+
return static_cast<const c_bool_typet &>(type);
15951596
}
15961597

15971598
/// \copydoc to_c_bool_type(const typet &)
15981599
inline c_bool_typet &to_c_bool_type(typet &type)
15991600
{
16001601
PRECONDITION(can_cast_type<c_bool_typet>(type));
1601-
c_bool_typet &ret = static_cast<c_bool_typet &>(type);
1602-
validate_type(ret);
1603-
return ret;
1602+
c_bool_typet::check(type);
1603+
return static_cast<c_bool_typet &>(type);
16041604
}
16051605

16061606
/// String type

src/util/validate_types.cpp

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,34 @@ Author: Daniel Poetzl
2424
template <template <typename, typename> class C, typename... Args>
2525
void call_on_type(const typet &type, Args &&... args)
2626
{
27-
if(type.id() == ID_signedbv)
27+
if(type.id() == ID_bv)
2828
{
29-
CALL_ON_TYPE(signedbv_typet);
29+
CALL_ON_TYPE(bv_typet);
3030
}
3131
else if(type.id() == ID_unsignedbv)
3232
{
3333
CALL_ON_TYPE(unsignedbv_typet);
3434
}
35+
else if(type.id() == ID_signedbv)
36+
{
37+
CALL_ON_TYPE(signedbv_typet);
38+
}
39+
else if(type.id() == ID_fixedbv)
40+
{
41+
CALL_ON_TYPE(fixedbv_typet);
42+
}
43+
else if(type.id() == ID_floatbv)
44+
{
45+
CALL_ON_TYPE(floatbv_typet);
46+
}
47+
else if(type.id() == ID_pointer)
48+
{
49+
CALL_ON_TYPE(pointer_typet);
50+
}
51+
else if(type.id() == ID_c_bool)
52+
{
53+
CALL_ON_TYPE(c_bool_typet);
54+
}
3555
else
3656
{
3757
#ifdef REPORT_UNIMPLEMENTED_TYPE_CHECKS

0 commit comments

Comments
 (0)