Skip to content

Commit c390aa7

Browse files
committed
Add a highlevel api to test types on exprt and typet
The CBMC code base normaly checks the id of an irept subtype against some magic id. But for some tests, it is necessary to check against more than one id. So this functions are use do the checks. This should further support code readability as a combination of different ids gets a name.
1 parent e0135ec commit c390aa7

File tree

3 files changed

+158
-8
lines changed

3 files changed

+158
-8
lines changed

src/ansi-c/c_typecast.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -55,14 +55,14 @@ bool c_implicit_typecast_arithmetic(
5555
return !c_typecast.errors.empty();
5656
}
5757

58-
bool is_void_pointer(const typet &type)
58+
bool has_a_void_pointer(const typet &type)
5959
{
6060
if(type.id()==ID_pointer)
6161
{
6262
if(type.subtype().id()==ID_empty)
6363
return true;
6464

65-
return is_void_pointer(type.subtype());
65+
return has_a_void_pointer(type.subtype());
6666
}
6767
else
6868
return false;
@@ -214,10 +214,11 @@ bool check_c_implicit_typecast(
214214
const irept &dest_subtype=dest_type.subtype();
215215
const irept &src_subtype =src_type.subtype();
216216

217-
if(src_subtype==dest_subtype)
217+
if(src_subtype == dest_subtype)
218218
return false;
219-
else if(is_void_pointer(src_type) || // from void to anything
220-
is_void_pointer(dest_type)) // to void from anything
219+
else if(
220+
has_a_void_pointer(src_type) || // from void to anything
221+
has_a_void_pointer(dest_type)) // to void from anything
221222
return false;
222223
}
223224

@@ -516,10 +517,9 @@ void c_typecastt::implicit_typecast_followed(
516517
// we are quite generous about pointers
517518

518519
const typet &src_sub=ns.follow(src_type.subtype());
519-
const typet &dest_sub=ns.follow(dest_type.subtype());
520+
const typet &dest_sub = ns.follow(dest_type.subtype());
520521

521-
if(is_void_pointer(src_type) ||
522-
is_void_pointer(dest_type))
522+
if(has_a_void_pointer(src_type) || has_a_void_pointer(dest_type))
523523
{
524524
// from/to void is always good
525525
}

src/util/c_types_util.h

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
// Copyright 2018 Author: Malte Mues <[email protected]>
2+
3+
/// \file
4+
/// This file contains functions, that should support test for underlying
5+
/// c types, in cases where this is required for anlysis purpose.
6+
#ifndef CPROVER_UTIL_C_TYPES_UTIL_H
7+
#define CPROVER_UTIL_C_TYPES_UTIL_H
8+
9+
#include "arith_tools.h"
10+
#include "invariant.h"
11+
#include "std_types.h"
12+
#include "type.h"
13+
14+
#include <algorithm>
15+
#include <string>
16+
17+
/// This function checks, whether this has been a char type in the c program.
18+
inline bool is_c_char(const typet &type)
19+
{
20+
const irep_idt &c_type = type.get(ID_C_c_type);
21+
return is_signed_or_unsigned_bitvector(type) &&
22+
(c_type == ID_char || c_type == ID_unsigned_char ||
23+
c_type == ID_signed_char);
24+
}
25+
26+
/// This function checks, whether the type
27+
/// has been a bool type in the c program.
28+
inline bool is_c_bool(const typet &type)
29+
{
30+
return type.id() == ID_c_bool;
31+
}
32+
33+
/// This function checks, whether the type is has been some kind of integer
34+
/// type in the c program.
35+
/// It considers the signed and unsigned verison of
36+
/// int, short, long and long long as integer types in c.
37+
inline bool is_c_int_derivate(const typet &type)
38+
{
39+
const irep_idt &c_type = type.get(ID_C_c_type);
40+
return is_signed_or_unsigned_bitvector(type) &&
41+
(c_type == ID_signed_int || c_type == ID_unsigned_int ||
42+
c_type == ID_signed_short_int || c_type == ID_unsigned_int ||
43+
c_type == ID_unsigned_short_int || c_type == ID_signed_long_int ||
44+
c_type == ID_signed_long_long_int || c_type == ID_unsigned_long_int ||
45+
c_type == ID_unsigned_long_long_int);
46+
}
47+
48+
/// This function checks, whether type is a pointer and the target type
49+
/// of the pointer has been a char type in the c program.
50+
inline bool is_c_char_pointer(const typet &type)
51+
{
52+
return is_pointer(type) && is_c_char(type.subtype());
53+
}
54+
55+
/// This function checks, whether type is a pointer and the target type
56+
/// has been some kind of int type in the c program.
57+
/// is_c_int_derivate answers is used for checking the int type.
58+
inline bool is_c_int_derivate_pointer(const typet &type)
59+
{
60+
return is_pointer(type) && is_c_int_derivate(type.subtype());
61+
}
62+
63+
/// This function checks, whether the type
64+
/// has been an enum type in the c program.
65+
inline bool is_c_enum(const typet &type)
66+
{
67+
return type.id() == ID_c_enum;
68+
}
69+
70+
/// This function creates a constant representing the
71+
/// bitvector encoded integer value of a string in the enum.
72+
/// \param member_name is a string that should be in the enum.
73+
/// \param c_enum the enum type memeber_name is supposed to be part of.
74+
/// \return value a constant, that could be assigned as value for an expression
75+
/// with type c_enum.
76+
constant_exprt convert_memeber_name_to_enum_value(
77+
const std::string &member_name,
78+
const c_enum_typet &c_enum)
79+
{
80+
for(const auto &enum_value : c_enum.members())
81+
{
82+
if(id2string(enum_value.get_identifier()) == member_name)
83+
{
84+
mp_integer int_value = string2integer(id2string(enum_value.get_value()));
85+
return from_integer(int_value, c_enum);
86+
}
87+
}
88+
INVARIANT(false, "member_name must be a valid value in the c_enum.");
89+
}
90+
91+
/// This function creates a constant representing either 0 or 1 as value of
92+
/// type type.
93+
/// \param bool_value: A string that is compared to "true" ignoring case.
94+
/// \param type: The type, the resulting constant is supposed to have.
95+
/// \return a constant of type \param type with either 0 or 1 as value.
96+
constant_exprt from_c_boolean_value(std::string bool_value, const typet &type)
97+
{
98+
std::transform(
99+
bool_value.begin(), bool_value.end(), bool_value.begin(), ::tolower);
100+
if(bool_value == "true")
101+
{
102+
return from_integer(mp_integer(1), type);
103+
}
104+
else
105+
{
106+
return from_integer(mp_integer(0), type);
107+
}
108+
}
109+
#endif // CPROVER_UTIL_C_TYPES_UTIL_H

src/util/std_types.h

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,13 @@ Author: Daniel Kroening, [email protected]
2525

2626
class constant_exprt;
2727

28+
/// This method tests,
29+
/// if the given typet is a constant
30+
inline bool is_constant(const typet &type)
31+
{
32+
return type.id() == ID_constant;
33+
}
34+
2835
/*!
2936
* Conversion to subclasses of @ref typet
3037
*/
@@ -305,6 +312,13 @@ class struct_typet:public struct_union_typet
305312
bool is_prefix_of(const struct_typet &other) const;
306313
};
307314

315+
/// This method tests,
316+
/// if the given typet is a struct
317+
inline bool is_struct(const typet &type)
318+
{
319+
return type.id() == ID_struct;
320+
}
321+
308322
/*! \brief Cast a generic typet to a \ref struct_typet
309323
*
310324
* This is an unchecked conversion. \a type must be known to be \ref
@@ -1040,6 +1054,12 @@ class array_typet:public type_with_subtypet
10401054
return size().is_nil();
10411055
}
10421056
};
1057+
/// This method tests,
1058+
/// if the given typet is an array_typet
1059+
inline bool is_array(const typet &type)
1060+
{
1061+
return type.id() == ID_array;
1062+
}
10431063

10441064
/*! \brief Cast a generic typet to an \ref array_typet
10451065
*
@@ -1146,6 +1166,13 @@ class bitvector_typet:public type_with_subtypet
11461166
}
11471167
};
11481168

1169+
/// This method tests,
1170+
/// if the given typet is a signed or unsigned bitvector.
1171+
inline bool is_signed_or_unsigned_bitvector(const typet &type)
1172+
{
1173+
return type.id() == ID_signedbv || type.id() == ID_unsignedbv;
1174+
}
1175+
11491176
/*! \brief Cast a generic typet to a \ref bitvector_typet
11501177
*
11511178
* This is an unchecked conversion. \a type must be known to be \ref
@@ -1487,6 +1514,20 @@ inline void validate_type(const pointer_typet &type)
14871514
DATA_INVARIANT(type.get_width() > 0, "pointer must have non-zero width");
14881515
}
14891516

1517+
/// This method tests,
1518+
/// if the given typet is a pointer.
1519+
inline bool is_pointer(const typet &type)
1520+
{
1521+
return type.id() == ID_pointer;
1522+
}
1523+
1524+
/// This method tests,
1525+
/// if the given typet is a pointer of type void.
1526+
inline bool is_void_pointer(const typet &type)
1527+
{
1528+
return is_pointer(type) && type.subtype().id() == ID_empty;
1529+
}
1530+
14901531
/*! \brief The reference type
14911532
*/
14921533
class reference_typet:public pointer_typet

0 commit comments

Comments
 (0)