CBMC
java_enum_static_init_unwind_handler.cpp
Go to the documentation of this file.
1 /*******************************************************************\
2 
3 Module: Unwind loops in static initializers
4 
5 Author: Chris Smowton, chris.smowton@diffblue.com
6 
7 \*******************************************************************/
8 
11 
13 
14 #include <util/invariant.h>
15 #include <util/ssa_expr.h> // IWYU pragma: keep
16 #include <util/suffix.h>
17 
18 #include <goto-symex/call_stack.h>
19 
20 #include "java_utils.h"
21 
33 {
34  static irep_idt reference_array_clone_id =
35  "java::array[reference].clone:()Ljava/lang/Object;";
36 
37  PRECONDITION(!context.empty());
38  const irep_idt &current_function = context.back().function_identifier;
39 
40  if(context.size() >= 2 && current_function == reference_array_clone_id)
41  {
42  const irep_idt &clone_caller =
43  context.at(context.size() - 2).function_identifier;
44  if(id2string(clone_caller).find(".values:()[L") != std::string::npos)
45  return clone_caller;
46  else
47  return irep_idt();
48  }
49  else if(has_suffix(id2string(current_function), ".<clinit>:()V"))
50  return current_function;
51  else
52  return irep_idt();
53 }
54 
71  const call_stackt &context,
72  unsigned loop_number,
73  unsigned unwind_count,
74  unsigned &unwind_max,
75  const symbol_tablet &symbol_table)
76 {
77  (void)loop_number; // unused parameter
78 
79  const irep_idt enum_function_id = find_enum_function_on_stack(context);
80  if(enum_function_id.empty())
81  return tvt::unknown();
82 
83  const symbolt &function_symbol = symbol_table.lookup_ref(enum_function_id);
84  const auto class_id = declaring_class(function_symbol);
85  INVARIANT(class_id, "Java methods should have a defining class.");
86 
87  const typet &class_type = symbol_table.lookup_ref(*class_id).type;
88  size_t unwinds = class_type.get_size_t(ID_java_enum_static_unwind);
89  if(unwinds != 0 && unwind_count < unwinds)
90  {
91  unwind_max = unwinds;
92  return tvt(false); // Must unwind
93  }
94  else
95  {
96  return tvt::unknown(); // Defer to other unwind handlers
97  }
98 }
dstringt has one field, an unsigned integer no which is an index into a static table of strings.
Definition: dstring.h:38
bool empty() const
Definition: dstring.h:89
std::size_t get_size_t(const irep_idt &name) const
Definition: irep.cpp:67
const symbolt & lookup_ref(const irep_idt &name) const
Find a symbol in the symbol table for read-only access.
The symbol table.
Definition: symbol_table.h:14
Symbol table entry.
Definition: symbol.h:28
typet type
Type of symbol.
Definition: symbol.h:31
Definition: threeval.h:20
static tvt unknown()
Definition: threeval.h:33
The type of an expression, extends irept.
Definition: type.h:29
const std::string & id2string(const irep_idt &d)
Definition: irep.h:40
static irep_idt find_enum_function_on_stack(const call_stackt &context)
Check if we may be in a function that loops over the cases of an enumeration (note we return a candid...
tvt java_enum_static_init_unwind_handler(const call_stackt &context, unsigned loop_number, unsigned unwind_count, unsigned &unwind_max, const symbol_tablet &symbol_table)
Unwind handler that special-cases the clinit (static initializer) functions of enumeration classes,...
Unwind loops in static initializers.
std::optional< irep_idt > declaring_class(const symbolt &symbol)
Gets the identifier of the class which declared a given symbol.
Definition: java_utils.cpp:568
#define PRECONDITION(CONDITION)
Definition: invariant.h:463
#define INVARIANT(CONDITION, REASON)
This macro uses the wrapper function 'invariant_violated_string'.
Definition: invariant.h:423
bool has_suffix(const std::string &s, const std::string &suffix)
Definition: suffix.h:17
dstringt irep_idt