CBMC
java_pointer_casts.cpp
Go to the documentation of this file.
1 /*******************************************************************\
2 
3 Module: JAVA Pointer Casts
4 
5 Author: Daniel Kroening, kroening@kroening.com
6 
7 \*******************************************************************/
8 
11 
12 #include "java_pointer_casts.h"
13 
14 #include <util/expr_util.h>
15 #include <util/namespace.h>
16 #include <util/pointer_expr.h>
17 #include <util/std_expr.h>
18 
19 #include "java_types.h"
20 
23 static exprt clean_deref(const exprt &ptr)
24 {
25  return ptr.id() == ID_address_of ? to_address_of_expr(ptr).object()
26  : dereference_exprt{ptr};
27 }
28 
33  exprt &ptr,
34  const typet &target_type,
35  const namespacet &ns)
36 {
37  PRECONDITION(ptr.type().id() == ID_pointer);
38  while(true)
39  {
40  const typet &ptr_base = to_pointer_type(ptr.type()).base_type();
41  if(ptr_base.id() != ID_struct_tag)
42  return false;
43  const struct_typet &base_struct =
44  ns.follow_tag(to_struct_tag_type(ptr_base));
45 
46  if(base_struct.components().empty())
47  return false;
48 
49  const typet &first_field_type=base_struct.components()[0].type();
50  ptr=clean_deref(ptr);
51  // Careful not to use the followed type here, as stub types may be
52  // extended by later method conversion adding fields (e.g. an access
53  // against x->y might add a new field `y` to the type of `*x`)
54  ptr=member_exprt(
55  ptr,
56  base_struct.components()[0].get_name(),
57  first_field_type);
58  ptr=address_of_exprt(ptr);
59 
60  // Compare the real (underlying) type, as target_type is already a non-
61  // symbolic type.
62  const typet &underlying_type =
63  first_field_type.id() == ID_struct_tag
64  ? ns.follow_tag(to_struct_tag_type(first_field_type))
65  : first_field_type;
66  if(underlying_type == target_type)
67  return true;
68  }
69 }
70 
76  const exprt &rawptr,
77  const pointer_typet &target_type,
78  const namespacet &ns)
79 {
80  const exprt &ptr = skip_typecast(rawptr);
81 
82  PRECONDITION(ptr.type().id()==ID_pointer);
83 
84  if(ptr.type()==target_type)
85  return ptr;
86 
87  if(
89  target_type.base_type() == java_void_type())
90  {
91  return typecast_exprt(ptr, target_type);
92  }
93 
94  exprt bare_ptr=ptr;
95  while(bare_ptr.id()==ID_typecast)
96  {
97  INVARIANT(
98  bare_ptr.type().id() == ID_pointer,
99  "Non-pointer in make_clean_pointer_cast?");
100  if(to_pointer_type(bare_ptr.type()).base_type() == java_void_type())
101  bare_ptr = to_typecast_expr(bare_ptr).op();
102  }
103 
104  INVARIANT(
105  bare_ptr.type().id() == ID_pointer,
106  "Non-pointer in make_clean_pointer_cast?");
107 
108  if(bare_ptr.type()==target_type)
109  return bare_ptr;
110 
111  exprt superclass_ptr=bare_ptr;
112  // Looking at base types discards generic qualifiers (because those are
113  // recorded on the pointer, not the pointee), so it may still be necessary
114  // to use a cast to reintroduce the qualifier (for example, the base might
115  // be recorded as a List, when we're looking for a List<E>)
116  const typet &target_base =
117  target_type.base_type().id() == ID_struct_tag
118  ? ns.follow_tag(to_struct_tag_type(target_type.base_type()))
119  : target_type.base_type();
120  if(find_superclass_with_type(superclass_ptr, target_base, ns))
121  return typecast_exprt::conditional_cast(superclass_ptr, target_type);
122 
123  return typecast_exprt(bare_ptr, target_type);
124 }
Operator to return the address of an object.
Definition: pointer_expr.h:540
exprt & object()
Definition: pointer_expr.h:549
Operator to dereference a pointer.
Definition: pointer_expr.h:834
Base class for all expressions.
Definition: expr.h:56
typet & type()
Return the type of the expression.
Definition: expr.h:84
const irep_idt & id() const
Definition: irep.h:388
Extract member of struct or union.
Definition: std_expr.h:2844
const union_typet & follow_tag(const union_tag_typet &) const
Follow type tag of union type.
Definition: namespace.cpp:63
A namespacet is essentially one or two symbol tables bound together, to allow for symbol lookups in t...
Definition: namespace.h:94
The pointer type These are both 'bitvector_typet' (they have a width) and 'type_with_subtypet' (they ...
Definition: pointer_expr.h:24
const typet & base_type() const
The type of the data what we point to.
Definition: pointer_expr.h:35
Structure type, corresponds to C style structs.
Definition: std_types.h:231
const componentst & components() const
Definition: std_types.h:147
Semantic type conversion.
Definition: std_expr.h:2068
static exprt conditional_cast(const exprt &expr, const typet &type)
Definition: std_expr.h:2076
The type of an expression, extends irept.
Definition: type.h:29
const exprt & op() const
Definition: std_expr.h:391
const exprt & skip_typecast(const exprt &expr)
find the expression nested inside typecasts, if any
Definition: expr_util.cpp:193
Deprecated expression utility functions.
bool find_superclass_with_type(exprt &ptr, const typet &target_type, const namespacet &ns)
static exprt clean_deref(const exprt &ptr)
dereference pointer expression
exprt make_clean_pointer_cast(const exprt &rawptr, const pointer_typet &target_type, const namespacet &ns)
JAVA Pointer Casts.
empty_typet java_void_type()
Definition: java_types.cpp:37
API to expression classes for Pointers.
const pointer_typet & to_pointer_type(const typet &type)
Cast a typet to a pointer_typet.
Definition: pointer_expr.h:93
const address_of_exprt & to_address_of_expr(const exprt &expr)
Cast an exprt to an address_of_exprt.
Definition: pointer_expr.h:577
#define PRECONDITION(CONDITION)
Definition: invariant.h:463
#define INVARIANT(CONDITION, REASON)
This macro uses the wrapper function 'invariant_violated_string'.
Definition: invariant.h:423
API to expression classes.
const typecast_exprt & to_typecast_expr(const exprt &expr)
Cast an exprt to a typecast_exprt.
Definition: std_expr.h:2102
const struct_tag_typet & to_struct_tag_type(const typet &type)
Cast a typet to a struct_tag_typet.
Definition: std_types.h:518