@@ -47,7 +47,7 @@ bool does_remove_constt::operator()() const
47
47
48
48
// Compare the types recursively for a point where the rhs is more
49
49
// const that the lhs
50
- if (!is_type_at_least_as_const_as (&lhs_type, &rhs_type))
50
+ if (!does_type_preserve_const_correctness (&lhs_type, &rhs_type))
51
51
{
52
52
return true ;
53
53
}
@@ -78,7 +78,7 @@ bool does_remove_constt::does_expr_lose_const(const exprt &expr) const
78
78
if (base_type_eq (op_type, root_type, ns))
79
79
{
80
80
// Is this child more const-qualified than the root
81
- if (!is_type_at_least_as_const_as (&root_type, &op_type))
81
+ if (!does_type_preserve_const_correctness (&root_type, &op_type))
82
82
{
83
83
return true ;
84
84
}
@@ -93,37 +93,78 @@ bool does_remove_constt::does_expr_lose_const(const exprt &expr) const
93
93
return false ;
94
94
}
95
95
96
- // / A recursive check to check the type_more_const is at least as const as type
97
- // / compare .
96
+ // / A recursive check that handles when assigning a source value to a target, is
97
+ // / the assignment a loss of const-correctness .
98
98
// /
99
- // / type_more_const | type_compare || result
100
- // / ----------------------------------------
101
- // / const int * | const int * -> true
102
- // / int * | const int * -> false
103
- // / const int * | int * -> true
104
- // / int * | int * const -> false
99
+ // / For primitive types, it always returns true since these are copied
100
+ // /
101
+ // / For pointers we requires that if in the source it's value couldn't
102
+ // / be modified, then it still can't be modified in the target
103
+ // /
104
+ // / target_type | source_type || result
105
+ // / ----------------------------------------
106
+ // / const int | int -> true
107
+ // / int | const int -> true
108
+ // / const int | const int -> true
109
+ // / int | int -> true
110
+ // /
111
+ // / int * | int * const -> true
112
+ // / int * | const int * -> false
113
+ // / const int * | int * -> true
114
+ // / const int * | const int * -> true
115
+ // / int * const | int * -> true
116
+ // /
117
+ // / See unit/analyses/does_type_preserve_const_correcness for
118
+ // / comprehensive list
119
+ // / \param target_type: the resulting type
120
+ // / \param source_type: the starting type
121
+ // / \return Returns true if a value of type source_type could be assigned into a
122
+ // / a value of target_type without losing const-correctness
123
+ bool does_remove_constt::does_type_preserve_const_correctness (
124
+ const typet *target_type, const typet *source_type) const
125
+ {
126
+ while (target_type->id ()==ID_pointer)
127
+ {
128
+ bool direct_subtypes_at_least_as_const=
129
+ is_type_at_least_as_const_as (
130
+ target_type->subtype (), source_type->subtype ());
131
+ // We have a pointer to something, but the thing it is pointing to can't be
132
+ // modified normally, but can through this pointer
133
+ if (!direct_subtypes_at_least_as_const)
134
+ return false ;
135
+ // Check the subtypes if they are pointers
136
+ target_type=&target_type->subtype ();
137
+ source_type=&source_type->subtype ();
138
+ }
139
+ return true ;
140
+ }
141
+
142
+ // / A simple check to check the type_more_const is at least as const as type
143
+ // / compare. This only checks the exact type, use
144
+ // / `is_pointer_at_least_as_constant_as` for dealing with nested types
145
+ // /
146
+ // / type_more_const | type_compare || result
147
+ // / ----------------------------------------
148
+ // / const int | int -> true
149
+ // / int | const int -> false
150
+ // / const int | const int -> true
151
+ // / int | int -> true
152
+ // / int * | int * const -> false
153
+ // / int * | const int * -> true
154
+ // / const int * | int * -> true
155
+ // / int * const | int * -> true
156
+ // /
157
+ // / See unit/analyses/is_type_as_least_as_const_as for comprehensive list
105
158
// / \param type_more_const: the type we are expecting to be at least as const
106
159
// / qualified
107
160
// / \param type_compare: the type we are comparing against which may be less
108
161
// / const qualified
109
162
// / \return Returns true if type_more_const is at least as const as type_compare
110
163
bool does_remove_constt::is_type_at_least_as_const_as (
111
- const typet * type_more_const, const typet * type_compare) const
164
+ const typet & type_more_const, const typet & type_compare) const
112
165
{
113
- while (type_compare->id ()!=ID_nil && type_more_const->id ()!=ID_nil)
114
- {
115
- const c_qualifierst rhs_qualifiers (*type_compare);
116
- const c_qualifierst lhs_qualifiers (*type_more_const);
117
- if (rhs_qualifiers.is_constant && !lhs_qualifiers.is_constant )
118
- {
119
- return false ;
120
- }
121
-
122
- type_compare=&type_compare->subtype ();
123
- type_more_const=&type_more_const->subtype ();
124
- }
125
-
126
- // Both the types should have the same number of subtypes
127
- assert (type_compare->id ()==ID_nil && type_more_const->id ()==ID_nil);
128
- return true ;
166
+ const c_qualifierst type_compare_qualifiers (type_compare);
167
+ const c_qualifierst more_constant_qualifiers (type_more_const);
168
+ return !type_compare_qualifiers.is_constant ||
169
+ more_constant_qualifiers.is_constant ;
129
170
}
0 commit comments