@@ -47,7 +47,7 @@ bool does_remove_constt::operator()() const
4747
4848 // Compare the types recursively for a point where the rhs is more
4949 // 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))
5151 {
5252 return true ;
5353 }
@@ -78,7 +78,7 @@ bool does_remove_constt::does_expr_lose_const(const exprt &expr) const
7878 if (base_type_eq (op_type, root_type, ns))
7979 {
8080 // 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))
8282 {
8383 return true ;
8484 }
@@ -93,37 +93,78 @@ bool does_remove_constt::does_expr_lose_const(const exprt &expr) const
9393 return false ;
9494}
9595
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 .
9898// /
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
105158// / \param type_more_const: the type we are expecting to be at least as const
106159// / qualified
107160// / \param type_compare: the type we are comparing against which may be less
108161// / const qualified
109162// / \return Returns true if type_more_const is at least as const as type_compare
110163bool 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
112165{
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 ;
129170}
0 commit comments