Skip to content

Commit ce1f4d2

Browse files
Add annotations to java_class_typet, its methods and fields
Add the annotations parsed from the byte code to classes/fields/methods and static fields (globals) in the symbol table
1 parent f84753d commit ce1f4d2

5 files changed

+134
-1
lines changed

src/java_bytecode/java_bytecode_convert_class.cpp

+45-1
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ class java_bytecode_convert_classt:public messaget
103103
typedef java_bytecode_parse_treet::classt classt;
104104
typedef java_bytecode_parse_treet::fieldt fieldt;
105105
typedef java_bytecode_parse_treet::methodt methodt;
106+
typedef java_bytecode_parse_treet::annotationt annotationt;
106107

107108
private:
108109
symbol_tablet &symbol_table;
@@ -372,6 +373,10 @@ void java_bytecode_convert_classt::convert(
372373
"java::" + id2string(lambda_entry.second.lambda_method_ref));
373374
}
374375

376+
// Load annotations
377+
if(!c.annotations.empty())
378+
convert_annotations(c.annotations, class_type.get_annotations());
379+
375380
// produce class symbol
376381
symbolt new_symbol;
377382
new_symbol.base_name=c.name;
@@ -638,6 +643,14 @@ void java_bytecode_convert_classt::convert(
638643
ns,
639644
get_message_handler());
640645

646+
// Load annotations
647+
if(!f.annotations.empty())
648+
{
649+
convert_annotations(
650+
f.annotations,
651+
static_cast<annotated_typet &>(new_symbol.type).get_annotations());
652+
}
653+
641654
// Do we have the static field symbol already?
642655
const auto s_it=symbol_table.symbols.find(new_symbol.name);
643656
if(s_it!=symbol_table.symbols.end())
@@ -650,7 +663,7 @@ void java_bytecode_convert_classt::convert(
650663
{
651664
class_typet &class_type=to_class_type(class_symbol.type);
652665

653-
class_type.components().push_back(class_typet::componentt());
666+
class_type.components().emplace_back();
654667
class_typet::componentt &component=class_type.components().back();
655668

656669
component.set_name(f.name);
@@ -666,6 +679,14 @@ void java_bytecode_convert_classt::convert(
666679
component.set_access(ID_public);
667680
else
668681
component.set_access(ID_default);
682+
683+
// Load annotations
684+
if(!f.annotations.empty())
685+
{
686+
convert_annotations(
687+
f.annotations,
688+
static_cast<annotated_typet &>(component.type()).get_annotations());
689+
}
669690
}
670691
}
671692

@@ -979,6 +1000,29 @@ static void find_and_replace_parameters(
9791000
}
9801001
}
9811002

1003+
/// Convert parsed annotations into the symbol table
1004+
/// \param parsed_annotations: The parsed annotations to convert
1005+
/// \param annotations: The java_annotationt collection to populate
1006+
void convert_annotations(
1007+
const java_bytecode_parse_treet::annotationst &parsed_annotations,
1008+
std::vector<java_annotationt> &annotations)
1009+
{
1010+
for(const auto &annotation : parsed_annotations)
1011+
{
1012+
annotations.emplace_back(annotation.type);
1013+
std::vector<java_annotationt::valuet> &values =
1014+
annotations.back().get_values();
1015+
std::transform(
1016+
annotation.element_value_pairs.begin(),
1017+
annotation.element_value_pairs.end(),
1018+
std::back_inserter(values),
1019+
[](const decltype(annotation.element_value_pairs)::value_type &value)
1020+
{
1021+
return java_annotationt::valuet(value.element_name, value.value);
1022+
});
1023+
}
1024+
}
1025+
9821026
/// Checks if the class is implicitly generic, i.e., it is an inner class of
9831027
/// any generic class. All uses of the implicit generic type parameters within
9841028
/// the inner class are updated to point to the type parameters of the

src/java_bytecode/java_bytecode_convert_class.h

+4
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@ bool java_bytecode_convert_class(
2929
java_string_library_preprocesst &string_preprocess,
3030
const std::unordered_set<std::string> &no_load_classes);
3131

32+
void convert_annotations(
33+
const java_bytecode_parse_treet::annotationst &parsed_annotations,
34+
std::vector<java_annotationt> &annotations);
35+
3236
void mark_java_implicitly_generic_class_type(
3337
const irep_idt &class_name,
3438
symbol_tablet &symbol_table);

src/java_bytecode/java_bytecode_convert_method.cpp

+9
Original file line numberDiff line numberDiff line change
@@ -387,6 +387,15 @@ void java_bytecode_convert_method_lazy(
387387
parameters.insert(parameters.begin(), this_p);
388388
}
389389

390+
// Load annotations
391+
if(!m.annotations.empty())
392+
{
393+
convert_annotations(
394+
m.annotations,
395+
static_cast<annotated_typet &>(static_cast<typet &>(member_type))
396+
.get_annotations());
397+
}
398+
390399
method_symbol.type=member_type;
391400
symbol_table.add(method_symbol);
392401
}

src/java_bytecode/java_types.h

+75
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,69 @@ Author: Daniel Kroening, [email protected]
1919
#include <util/optional.h>
2020
#include <util/std_expr.h>
2121

22+
class java_annotationt : public irept
23+
{
24+
public:
25+
class valuet : public irept
26+
{
27+
public:
28+
valuet(irep_idt name, const exprt &value) : irept(name)
29+
{
30+
get_sub().push_back(value);
31+
}
32+
33+
const irep_idt &get_name() const
34+
{
35+
return id();
36+
}
37+
38+
const exprt &get_value() const
39+
{
40+
return static_cast<const exprt &>(get_sub().front());
41+
}
42+
};
43+
44+
explicit java_annotationt(const typet &type)
45+
{
46+
set(ID_type, type);
47+
}
48+
49+
const typet &get_type() const
50+
{
51+
return static_cast<const typet &>(find(ID_type));
52+
}
53+
54+
const std::vector<valuet> &get_values() const
55+
{
56+
// This cast should be safe as valuet doesn't add data to irept
57+
return reinterpret_cast<const std::vector<valuet> &>(get_sub());
58+
}
59+
60+
std::vector<valuet> &get_values()
61+
{
62+
// This cast should be safe as valuet doesn't add data to irept
63+
return reinterpret_cast<std::vector<valuet> &>(get_sub());
64+
}
65+
};
66+
67+
class annotated_typet : public typet
68+
{
69+
public:
70+
const std::vector<java_annotationt> &get_annotations() const
71+
{
72+
// This cast should be safe as java_annotationt doesn't add data to irept
73+
return reinterpret_cast<const std::vector<java_annotationt> &>(
74+
find(ID_annotations).get_sub());
75+
}
76+
77+
std::vector<java_annotationt> &get_annotations()
78+
{
79+
// This cast should be safe as java_annotationt doesn't add data to irept
80+
return reinterpret_cast<std::vector<java_annotationt> &>(
81+
add(ID_annotations).get_sub());
82+
}
83+
};
84+
2285
class java_class_typet:public class_typet
2386
{
2487
public:
@@ -57,6 +120,18 @@ class java_class_typet:public class_typet
57120
// creates empty symbol_exprt and pushes it in the vector
58121
lambda_method_handles().emplace_back();
59122
}
123+
124+
const std::vector<java_annotationt> &get_annotations() const
125+
{
126+
return static_cast<const annotated_typet &>(
127+
static_cast<const typet &>(*this)).get_annotations();
128+
}
129+
130+
std::vector<java_annotationt> &get_annotations()
131+
{
132+
return static_cast<annotated_typet &>(
133+
static_cast<typet &>(*this)).get_annotations();
134+
}
60135
};
61136

62137
inline const java_class_typet &to_java_class_type(const typet &type)

src/util/irep_ids.def

+1
Original file line numberDiff line numberDiff line change
@@ -844,6 +844,7 @@ IREP_ID_TWO(overflow_shl, overflow-shl)
844844
IREP_ID_TWO(C_no_initialization_required, #no_initialization_required)
845845
IREP_ID_TWO(overlay_class, java::com.diffblue.OverlayClassImplementation)
846846
IREP_ID_TWO(overlay_method, java::com.diffblue.OverlayMethodImplementation)
847+
IREP_ID_ONE(annotations)
847848

848849
#undef IREP_ID_ONE
849850
#undef IREP_ID_TWO

0 commit comments

Comments
 (0)