@@ -8,6 +8,73 @@ Author: Chris Smowton, chris.smowton@diffblue.com
8
8
9
9
/// \file
10
10
/// Remove Instance-of Operators
11
+ ///
12
+ /// Java has an operator called `instanceof`, which is used to check if an
13
+ /// instance of a class is of a particular type. For example given that `A` and
14
+ /// `B` are the identifiers of classes, which directly extend Object. If the
15
+ /// following example java code is executed -
16
+ /// ```java
17
+ /// Object a = new A();
18
+ /// boolean x = a instanceof A; // true
19
+ /// boolean y = a instanceof B; // false
20
+ /// ```
21
+ /// Then, `x` will be set to `true` and `y` will be set to `false`.
22
+ ///
23
+ /// `instanceof` also works with inheritance. Given classes `C` and `D`, where
24
+ /// `C` extends from `Object` and `D` extends `C`. If the following example java
25
+ /// code is executed -
26
+ /// ```java
27
+ /// Object c = new C();
28
+ /// Object d = new D();
29
+ /// boolean b1 = c instanceof C; // true
30
+ /// boolean b2 = c instanceof D; // false
31
+ /// boolean b3 = d instanceof C; // true
32
+ /// boolean b4 = d instanceof D; // true
33
+ /// ```
34
+ /// Then, `b1` will be `true`, `b2` will be `false`, `b3` will be `true` and
35
+ /// `b4` will be `true`.
36
+ ///
37
+ /// `instanceof` has its own instruction type in the java bytecode. We need to
38
+ /// rewrite it in terms of other, more fundamental operations in order to
39
+ /// analyse it. This operation is referred to as "lowering" or in this
40
+ /// specific case - `remove_instanceof`.
41
+ ///
42
+ /// For a simple example where class `A` extends `Object` and no classes extend
43
+ /// `A`, the expression `e instanceof A` needs to be lowered to an expression
44
+ /// equivalent to `e == null ? false : e->@class_identifier == "A"`. The null
45
+ /// case needs to be taken into account first, as we can't lookup the value of
46
+ /// a `@class_identifier` field in a null pointer. Note that according to the
47
+ /// Java specification, `null` is not an instance of any type.
48
+ ///
49
+ /// For an example with inheritance where class `D` extends `C` and `C` extends
50
+ /// `Object`, then `e instanceof C` needs to be lowered to an expression
51
+ /// equivalent to `e == null ? false : (e->@class_identifier == "C" ||
52
+ /// e->@class_identifier == "D")`. To lower `e instanceof C` correctly, we need
53
+ /// to take into account each of the classes extends from `C`. Working out what
54
+ /// classes extend a given class type is performed using an instance of the
55
+ /// `class_hierarchyt` class.
56
+ ///
57
+ /// In terms of the goto program, the `instanceof` operator is identified in the
58
+ /// expression tree, based on the `exprt.id()` being `ID_java_instance_of`. The
59
+ /// left hand side of the operator must be a pointer and the right hand side
60
+ /// must be a type.
61
+ ///
62
+ /// The lowered form has a refinement to help with null pointer analysis later
63
+ /// on. Instead of dereferencing the pointer to get `@class_identifier` in each
64
+ /// comparision, it is dereferenced a single time and the result is reused. This
65
+ /// is easier to analyse for null pointers, because there is only a single
66
+ /// dereference to consider. So the constructed program takes the form -
67
+ /// ```cpp
68
+ /// if(expr == null)
69
+ /// instanceof_result = false;
70
+ /// else
71
+ /// string class_identifier_tmpX = expr->@class_identifier;
72
+ /// instanceof_result =
73
+ /// class_identifier_tmpX == "C" ||
74
+ /// class_identifier_tmpX == "D";
75
+ /// ```
76
+ /// Where the `X` in `class_identifier_tmp` is a number which makes the
77
+ /// identifier unique.
11
78
12
79
#ifndef CPROVER_JAVA_BYTECODE_REMOVE_INSTANCEOF_H
13
80
#define CPROVER_JAVA_BYTECODE_REMOVE_INSTANCEOF_H
0 commit comments