@@ -142,9 +142,9 @@ exprt value_set_dereferencet::dereference(
142142 const exprt &pointer,
143143 bool display_points_to_sets)
144144{
145- if (pointer. type (). id ()!=ID_pointer)
146- throw " dereference expected pointer type, but got " +
147- pointer.type ().pretty ();
145+ PRECONDITION_WITH_DIAGNOSTICS (
146+ pointer. type (). id () == ID_pointer,
147+ " dereference expected pointer type, but got " + pointer.type ().pretty () );
148148
149149 // we may get ifs due to recursive calls
150150 if (pointer.id ()==ID_if)
@@ -465,8 +465,9 @@ value_set_dereferencet::valuet value_set_dereferencet::build_reference_to(
465465 return valuet ();
466466 }
467467
468- if (what.id ()!=ID_object_descriptor)
469- throw " unknown points-to: " +what.id_string ();
468+ PRECONDITION_WITH_DIAGNOSTICS (
469+ what.id () == ID_object_descriptor,
470+ " unknown points-to: " + what.id_string ());
470471
471472 const object_descriptor_exprt &o=to_object_descriptor_expr (what);
472473
@@ -477,24 +478,28 @@ value_set_dereferencet::valuet value_set_dereferencet::build_reference_to(
477478 std::cout << "O: " << format(root_object) << '\n';
478479 #endif
479480
480- valuet result;
481-
482481 if (root_object.id () == ID_null_object)
483482 {
484- if (o.offset ().is_zero ())
485- result.pointer = null_pointer_exprt{pointer_type};
486- else
487- return valuet{};
483+ if (!o.offset ().is_zero ())
484+ return {};
485+
486+ valuet result;
487+ result.pointer = null_pointer_exprt{pointer_type};
488+ return result;
488489 }
489490 else if (root_object.id ()==ID_dynamic_object)
490491 {
492+ valuet result;
493+
491494 // constraint that it actually is a dynamic object
492495 // this is also our guard
493496 result.pointer_guard = is_dynamic_object_exprt (pointer_expr);
494497
495498 // can't remove here, turn into *p
496499 result.value = dereference_exprt{pointer_expr};
497500 result.pointer = pointer_expr;
501+
502+ return result;
498503 }
499504 else if (root_object.id ()==ID_integer_address)
500505 {
@@ -514,8 +519,10 @@ value_set_dereferencet::valuet value_set_dereferencet::build_reference_to(
514519 pointer_offset (pointer_expr),
515520 to_array_type (memory_symbol.type ).element_type ());
516521
522+ valuet result;
517523 result.value =index_expr;
518524 result.pointer = address_of_exprt{index_expr};
525+ return result;
519526 }
520527 else if (dereference_type_compare (
521528 to_array_type (memory_symbol.type ).element_type (),
@@ -526,28 +533,32 @@ value_set_dereferencet::valuet value_set_dereferencet::build_reference_to(
526533 symbol_expr,
527534 pointer_offset (pointer_expr),
528535 to_array_type (memory_symbol.type ).element_type ());
536+
537+ valuet result;
529538 result.value =typecast_exprt (index_expr, dereference_type);
530539 result.pointer =
531540 typecast_exprt{address_of_exprt{index_expr}, pointer_type};
541+ return result;
532542 }
533543 else
534544 {
535545 // We need to use byte_extract.
536546 // Won't do this without a commitment to an endianness.
537547
538548 if (config.ansi_c .endianness ==configt::ansi_ct::endiannesst::NO_ENDIANNESS)
539- {
540- }
541- else
542- {
543- result.value = make_byte_extract (
544- symbol_expr, pointer_offset (pointer_expr), dereference_type);
545- result.pointer = address_of_exprt{result.value };
546- }
549+ return {};
550+
551+ valuet result;
552+ result.value = make_byte_extract (
553+ symbol_expr, pointer_offset (pointer_expr), dereference_type);
554+ result.pointer = address_of_exprt{result.value };
555+ return result;
547556 }
548557 }
549558 else
550559 {
560+ valuet result;
561+
551562 // something generic -- really has to be a symbol
552563 address_of_exprt object_pointer (object);
553564
@@ -565,8 +576,6 @@ value_set_dereferencet::valuet value_set_dereferencet::build_reference_to(
565576 const typet &object_type = object.type ();
566577 const typet &root_object_type = root_object.type ();
567578
568- exprt root_object_subexpression=root_object;
569-
570579 if (
571580 dereference_type_compare (object_type, dereference_type, ns) &&
572581 o.offset ().is_zero ())
@@ -577,89 +586,81 @@ value_set_dereferencet::valuet value_set_dereferencet::build_reference_to(
577586 result.value = typecast_exprt::conditional_cast (object, dereference_type);
578587 result.pointer =
579588 typecast_exprt::conditional_cast (object_pointer, pointer_type);
589+
590+ return result;
580591 }
581- else if (
592+
593+ // this is relative to the root object
594+ exprt offset;
595+ if (o.offset ().is_constant ())
596+ offset = o.offset ();
597+ else
598+ offset = simplify_expr (pointer_offset (pointer_expr), ns);
599+
600+ if (
582601 root_object_type.id () == ID_array &&
583602 dereference_type_compare (
584603 to_array_type (root_object_type).element_type (), dereference_type, ns) &&
585604 pointer_offset_bits (to_array_type (root_object_type).element_type (), ns) ==
586- pointer_offset_bits (dereference_type, ns))
605+ pointer_offset_bits (dereference_type, ns) &&
606+ offset.is_constant ())
587607 {
588608 // We have an array with a subtype that matches
589609 // the dereferencing type.
590- exprt offset;
591-
592- // this should work as the object is essentially the root object
593- if (o.offset ().is_constant ())
594- offset=o.offset ();
595- else
596- offset=pointer_offset (pointer_expr);
597610
598611 // are we doing a byte?
599612 auto element_size =
600613 pointer_offset_size (to_array_type (root_object_type).element_type (), ns);
614+ CHECK_RETURN (element_size.has_value ());
615+ CHECK_RETURN (*element_size > 0 );
601616
602- if (!element_size.has_value () || *element_size == 0 )
603- {
604- throw " unknown or invalid type size of:\n " +
605- to_array_type (root_object_type).element_type ().pretty ();
606- }
607-
608- exprt element_size_expr = from_integer (*element_size, offset.type ());
609-
610- exprt adjusted_offset =
611- simplify_expr (div_exprt{offset, element_size_expr}, ns);
617+ const auto offset_int =
618+ numeric_cast_v<mp_integer>(to_constant_expr (offset));
612619
613- index_exprt index_expr{root_object, adjusted_offset};
614- result.value =
615- typecast_exprt::conditional_cast (index_expr, dereference_type);
616- result.pointer = typecast_exprt::conditional_cast (
617- address_of_exprt{index_expr}, pointer_type);
618- }
619- else
620- {
621- // try to build a member/index expression - do not use byte_extract
622- auto subexpr = get_subexpression_at_offset (
623- root_object_subexpression, o.offset (), dereference_type, ns);
624- if (subexpr.has_value ())
625- simplify (subexpr.value (), ns);
626- if (
627- subexpr.has_value () &&
628- subexpr.value ().id () != ID_byte_extract_little_endian &&
629- subexpr.value ().id () != ID_byte_extract_big_endian)
620+ if (offset_int % *element_size == 0 )
630621 {
631- // Successfully found a member, array index, or combination thereof
632- // that matches the desired type and offset:
633- result.value = subexpr.value ();
622+ index_exprt index_expr{
623+ root_object,
624+ from_integer (
625+ offset_int / *element_size,
626+ to_array_type (root_object_type).index_type ())};
627+ result.value =
628+ typecast_exprt::conditional_cast (index_expr, dereference_type);
634629 result.pointer = typecast_exprt::conditional_cast (
635- address_of_exprt{skip_typecast (subexpr.value ())}, pointer_type);
630+ address_of_exprt{index_expr}, pointer_type);
631+
636632 return result;
637633 }
634+ }
638635
639- // we extract something from the root object
640- result.value =o.root_object ();
636+ // try to build a member/index expression - do not use byte_extract
637+ auto subexpr = get_subexpression_at_offset (
638+ root_object, o.offset (), dereference_type, ns);
639+ if (subexpr.has_value ())
640+ simplify (subexpr.value (), ns);
641+ if (
642+ subexpr.has_value () &&
643+ subexpr.value ().id () != ID_byte_extract_little_endian &&
644+ subexpr.value ().id () != ID_byte_extract_big_endian)
645+ {
646+ // Successfully found a member, array index, or combination thereof
647+ // that matches the desired type and offset:
648+ result.value = subexpr.value ();
641649 result.pointer = typecast_exprt::conditional_cast (
642- address_of_exprt{skip_typecast (o.root_object ())}, pointer_type);
650+ address_of_exprt{skip_typecast (subexpr.value ())}, pointer_type);
651+ return result;
652+ }
643653
644- // this is relative to the root object
645- exprt offset;
646- if (o.offset ().id ()==ID_unknown)
647- offset=pointer_offset (pointer_expr);
648- else
649- offset=o.offset ();
654+ // we extract something from the root object
655+ result.value = o.root_object ();
656+ result.pointer = typecast_exprt::conditional_cast (
657+ address_of_exprt{skip_typecast (o.root_object ())}, pointer_type);
650658
651- if (memory_model (result.value , dereference_type, offset, ns))
652- {
653- // ok, done
654- }
655- else
656- {
657- return valuet (); // give up, no way that this is ok
658- }
659- }
660- }
659+ if (!memory_model (result.value , dereference_type, offset, ns))
660+ return {}; // give up, no way that this is ok
661661
662- return result;
662+ return result;
663+ }
663664}
664665
665666static bool is_a_bv_type (const typet &type)
0 commit comments