6
6
7
7
\*******************************************************************/
8
8
9
-
10
9
#include " type.h"
11
10
#include " std_types.h"
12
11
#include " namespace.h"
@@ -48,26 +47,24 @@ bool is_number(const typet &type)
48
47
bool is_constant_or_has_constant_components (
49
48
const typet &type, const namespacet &ns)
50
49
{
51
- // Helper function to avoid the code duplication
52
- // in the branches below.
50
+ // Helper function to avoid the code duplication in the branches
51
+ // below.
53
52
const auto has_constant_components =
54
- [](const typet &subtype) -> bool
55
- {
56
- if (subtype.id () == ID_struct || subtype.id () == ID_union)
53
+ [&ns](const typet &subtype) -> bool
57
54
{
58
- const auto &struct_union_type = to_struct_union_type (subtype);
59
- for (const auto &component : struct_union_type.components ())
55
+ if (subtype.id () == ID_struct || subtype.id () == ID_union)
60
56
{
61
- if (component.type ().id () == ID_pointer)
62
- return component.type ().get_bool (ID_C_constant);
63
- if (component.type ().get_bool (ID_C_constant))
64
- return true ;
57
+ const auto &struct_union_type = to_struct_union_type (subtype);
58
+ for (const auto &component : struct_union_type.components ())
59
+ {
60
+ if (is_constant_or_has_constant_components (component.type (), ns))
61
+ return true ;
62
+ }
65
63
}
66
- }
67
- return false ;
68
- };
64
+ return false ;
65
+ };
69
66
70
- // There are 3 possibilities the code below is handling.
67
+ // There are 4 possibilities the code below is handling.
71
68
// The possibilities are enumerated as comments, to show
72
69
// what each code is supposed to be handling. For more
73
70
// comprehensive test case for this, take a look at
@@ -77,30 +74,34 @@ bool is_constant_or_has_constant_components(
77
74
if (type.get_bool (ID_C_constant))
78
75
return true ;
79
76
77
+ // This is a termination condition to break the recursion
78
+ // for recursive types such as the following:
79
+ // struct list { const int datum; struct list * next; };
80
+ // NOTE: the difference between this condition and the previous
81
+ // one is that this one always returns.
82
+ if (type.id ()==ID_pointer)
83
+ return type.get_bool (ID_C_constant);
84
+
80
85
// When we have a case like the following, we don't immediately
81
86
// see the struct t. Instead, we only get to see symbol t1, which
82
87
// we have to use the namespace to resolve to its definition:
83
88
// struct t { const int a; };
84
89
// struct t t1;
85
90
if (type.id () == ID_symbol)
86
91
{
87
- const auto &subtype = ns.follow (type);
88
- return has_constant_components (subtype );
92
+ const auto &resolved_type = ns.follow (type);
93
+ return has_constant_components (resolved_type );
89
94
}
90
95
91
- // In a case like this, were we see an array (b[3] here), we know that
96
+ // In a case like this, where we see an array (b[3] here), we know that
92
97
// the array contains subtypes. We get the first one, and
93
98
// then resolve it to its definition through the usage of the namespace.
94
99
// struct contains_constant_pointer { int x; int * const p; };
95
100
// struct contains_constant_pointer b[3] = { {23, &y}, {23, &y}, {23, &y} };
96
101
if (type.has_subtype ())
97
102
{
98
103
const auto &subtype = type.subtype ();
99
- if (subtype.id () == ID_symbol)
100
- {
101
- const auto &new_subtype = ns.follow (to_symbol_type (subtype));
102
- return has_constant_components (new_subtype);
103
- }
104
+ return is_constant_or_has_constant_components (subtype, ns);
104
105
}
105
106
106
107
return false ;
0 commit comments