@@ -34,6 +34,8 @@ Author: Daniel Kroening, kroening@kroening.com
3434#include < util/simplify_expr.h>
3535#include < util/ssa_expr.h>
3636
37+ #include < deque>
38+
3739// / Returns true if \p expr is complicated enough that a local definition (using
3840// / a let expression) is preferable to repeating it, potentially many times.
3941// / Of course this is just a heuristic -- currently we allow any expression that
@@ -139,7 +141,13 @@ exprt value_set_dereferencet::dereference(
139141 }
140142 }
141143
142- // type of the object
144+ return handle_dereference_base_case (pointer, display_points_to_sets);
145+ }
146+
147+ exprt value_set_dereferencet::handle_dereference_base_case (
148+ const exprt &pointer,
149+ bool display_points_to_sets)
150+ { // type of the object
143151 const typet &type=pointer.type ().subtype ();
144152
145153 // collect objects the pointer may point to
@@ -167,95 +175,89 @@ exprt value_set_dereferencet::dereference(
167175 compare_against_pointer = fresh_binder.symbol_expr ();
168176 }
169177
170- std::list<valuet> values =
171- make_range (retained_values).map ([&](const exprt &value) {
172- return build_reference_to (value, compare_against_pointer, ns);
178+ auto values =
179+ make_range (retained_values)
180+ .map ([&](const exprt &value) {
181+ return build_reference_to (value, compare_against_pointer, ns);
182+ })
183+ .collect <std::deque<valuet>>();
184+
185+ const bool may_fail =
186+ values.empty () ||
187+ std::any_of (values.begin (), values.end (), [](const valuet &value) {
188+ return value.value .is_nil ();
173189 });
174190
175- // can this fail?
176- bool may_fail;
177-
178- if (values.empty ())
179- {
180- may_fail=true ;
181- }
182- else
183- {
184- may_fail=false ;
185- for (std::list<valuet>::const_iterator
186- it=values.begin ();
187- it!=values.end ();
188- it++)
189- if (it->value .is_nil ())
190- may_fail=true ;
191- }
192-
193191 if (may_fail)
194192 {
195- // first see if we have a "failed object" for this pointer
196-
197- exprt failure_value;
198-
199- if (
200- const symbolt *failed_symbol =
201- dereference_callback.get_or_create_failed_symbol (pointer))
202- {
203- // yes!
204- failure_value=failed_symbol->symbol_expr ();
205- failure_value.set (ID_C_invalid_object, true );
206- }
207- else
208- {
209- // else: produce new symbol
210- symbolt &symbol = get_fresh_aux_symbol (
211- type,
212- " symex" ,
213- " invalid_object" ,
214- pointer.source_location (),
215- language_mode,
216- new_symbol_table);
217-
218- // make it a lvalue, so we can assign to it
219- symbol.is_lvalue =true ;
220-
221- failure_value=symbol.symbol_expr ();
222- failure_value.set (ID_C_invalid_object, true );
223- }
224-
225- valuet value;
226- value.value =failure_value;
227- value.pointer_guard =true_exprt ();
228- values.push_front (value);
193+ values.push_front (get_failure_value (pointer, type));
229194 }
230195
231196 // now build big case split, but we only do "good" objects
232197
233- exprt value= nil_exprt () ;
198+ exprt result_value = nil_exprt{} ;
234199
235- for (std::list<valuet>::const_iterator
236- it=values.begin ();
237- it!=values.end ();
238- it++)
200+ for (const auto &value : values)
239201 {
240- if (it-> value .is_not_nil ())
202+ if (value. value .is_not_nil ())
241203 {
242- if (value .is_nil ()) // first?
243- value=it-> value ;
204+ if (result_value .is_nil ()) // first?
205+ result_value = value. value ;
244206 else
245- value= if_exprt (it-> pointer_guard , it-> value , value );
207+ result_value = if_exprt (value. pointer_guard , value. value , result_value );
246208 }
247209 }
248210
249211 if (compare_against_pointer != pointer)
250- value = let_exprt (to_symbol_expr (compare_against_pointer), pointer, value);
212+ result_value =
213+ let_exprt (to_symbol_expr (compare_against_pointer), pointer, result_value);
251214
252215 if (display_points_to_sets)
253216 {
254217 log.status () << value_set_dereference_stats_to_json (
255- pointer, points_to_set, retained_values, value );
218+ pointer, points_to_set, retained_values, result_value );
256219 }
257220
258- return value;
221+ return result_value;
222+ }
223+
224+ value_set_dereferencet::valuet value_set_dereferencet::get_failure_value (
225+ const exprt &pointer,
226+ const typet &type)
227+ {
228+ // first see if we have a "failed object" for this pointer
229+ exprt failure_value;
230+
231+ if (
232+ const symbolt *failed_symbol =
233+ dereference_callback.get_or_create_failed_symbol (pointer))
234+ {
235+ // yes!
236+ failure_value = failed_symbol->symbol_expr ();
237+ failure_value.set (ID_C_invalid_object, true );
238+ }
239+ else
240+ {
241+ // else: produce new symbol
242+ symbolt &symbol = get_fresh_aux_symbol (
243+ type,
244+ " symex" ,
245+ " invalid_object" ,
246+ pointer.source_location (),
247+ language_mode,
248+ new_symbol_table);
249+
250+ // make it a lvalue, so we can assign to it
251+ symbol.is_lvalue = true ;
252+
253+ failure_value = symbol.symbol_expr ();
254+ failure_value.set (ID_C_invalid_object, true );
255+ }
256+
257+ valuet result{};
258+ result.value = failure_value;
259+ result.pointer_guard = true_exprt ();
260+ return result;
259261}
260262
261263// / Check if the two types have matching number of ID_pointer levels, with
0 commit comments