Skip to content

Commit 26df513

Browse files
authored
Merge pull request #3227 from antlechner/load-annotation-classes
Include annotations in Java class loading [TG-3831]
2 parents 20c5857 + 48d9e44 commit 26df513

33 files changed

+159
-3
lines changed
Binary file not shown.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
public @interface AnnotationWithArrayValue {
2+
3+
Class<?>[] value();
4+
5+
}
Binary file not shown.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
public @interface AnnotationWithClassValue {
2+
3+
Class<?> value();
4+
5+
}
Binary file not shown.
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
@AnnotationWithArrayValue({MyClassA.class, MyClassB.class})
2+
public class ArrayValueAnnotationOnClass {
3+
}
Binary file not shown.
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
public class ArrayValueAnnotationOnField {
2+
@AnnotationWithArrayValue({MyClassA.class, MyClassB.class})
3+
int arrayValueAnnotatedField;
4+
}
Binary file not shown.
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
public class ArrayValueAnnotationOnMethod {
2+
@AnnotationWithArrayValue({MyClassA.class, MyClassB.class})
3+
public void arrayValueAnnotatedMethod() {}
4+
}
Binary file not shown.
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
public class ArrayValueAnnotationOnParameter {
2+
public void classValueAnnotatedParameter(
3+
@AnnotationWithArrayValue({MyClassA.class, MyClassB.class}) int param) {}
4+
}
Binary file not shown.
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
@AnnotationWithClassValue(MyClassA.class)
2+
public class ClassValueAnnotationOnClass {
3+
}
Binary file not shown.
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
public class ClassValueAnnotationOnField {
2+
@AnnotationWithClassValue(MyClassA.class)
3+
int classValueAnnotatedField;
4+
}
Binary file not shown.
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
public class ClassValueAnnotationOnMethod {
2+
@AnnotationWithClassValue(MyClassA.class)
3+
public void classValueAnnotatedMethod() {}
4+
}
Binary file not shown.
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
public class ClassValueAnnotationOnParameter {
2+
public void classValueAnnotatedParameter(
3+
@AnnotationWithClassValue(MyClassA.class) int param) {}
4+
}
Binary file not shown.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
public class MyClassA {}
Binary file not shown.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
public class MyClassB {}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
CORE
2+
ArrayValueAnnotationOnClass.class
3+
--verbosity 10
4+
Getting class `MyClassA' from file \.[\\/]MyClassA\.class
5+
Getting class `MyClassB' from file \.[\\/]MyClassB\.class
6+
--
7+
--
8+
This test checks that element classes of arrays that are given as values of a class-level annotation
9+
are loaded by java_class_loadert.
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
CORE
2+
ArrayValueAnnotationOnField.class
3+
--verbosity 10
4+
Getting class `MyClassA' from file \.[\\/]MyClassA\.class
5+
Getting class `MyClassB' from file \.[\\/]MyClassB\.class
6+
--
7+
--
8+
This test checks that element classes of arrays that are given as values of a field-level annotation
9+
are loaded by java_class_loadert.
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
CORE
2+
ArrayValueAnnotationOnMethod.class
3+
--verbosity 10
4+
Getting class `MyClassA' from file \.[\\/]MyClassA\.class
5+
Getting class `MyClassB' from file \.[\\/]MyClassB\.class
6+
--
7+
--
8+
This test checks that element classes of arrays that are given as values of a method-level
9+
annotation are loaded by java_class_loadert.
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
CORE
2+
ArrayValueAnnotationOnParameter.class
3+
--verbosity 10
4+
Getting class `MyClassA' from file \.[\\/]MyClassA\.class
5+
Getting class `MyClassB' from file \.[\\/]MyClassB\.class
6+
--
7+
--
8+
This test checks that element classes of arrays that are given as values of an annotation at method
9+
parameter level are loaded by java_class_loadert.
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
CORE
2+
ClassValueAnnotationOnClass.class
3+
--verbosity 10
4+
Getting class `MyClassA' from file \.[\\/]MyClassA\.class
5+
--
6+
MyClassB
7+
--
8+
This test checks that classes that are given as values of a class-level annotation are loaded by
9+
java_class_loadert.
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
CORE
2+
ClassValueAnnotationOnField.class
3+
--verbosity 10
4+
Getting class `MyClassA' from file \.[\\/]MyClassA\.class
5+
--
6+
MyClassB
7+
--
8+
This test checks that classes that are given as values of a field-level annotation are loaded by
9+
java_class_loadert.
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
CORE
2+
ClassValueAnnotationOnMethod.class
3+
--verbosity 10
4+
Getting class `MyClassA' from file \.[\\/]MyClassA\.class
5+
--
6+
MyClassB
7+
--
8+
This test checks that classes that are given as values of a method-level annotation are loaded by
9+
java_class_loadert.
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
CORE
2+
ClassValueAnnotationOnParameter.class
3+
--verbosity 10
4+
Getting class `MyClassA' from file \.[\\/]MyClassA\.class
5+
--
6+
MyClassB
7+
--
8+
This test checks that classes that are given as values of an annotation at method parameter level
9+
are loaded by java_class_loadert.

jbmc/src/java_bytecode/java_bytecode_parser.cpp

Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,9 @@ class java_bytecode_parsert:public parsert
134134
void rbytecode(methodt::instructionst &);
135135
void get_class_refs();
136136
void get_class_refs_rec(const typet &);
137+
void get_annotation_class_refs(
138+
const java_bytecode_parse_treet::annotationst &annotations);
139+
void get_annotation_value_class_refs(const exprt &value);
137140
void parse_local_variable_type_table(methodt &method);
138141
optionalt<lambda_method_handlet>
139142
parse_method_handle(const class method_handle_infot &entry);
@@ -525,11 +528,9 @@ void java_bytecode_parsert::rClassFile()
525528
parse_tree.loading_successful=true;
526529
}
527530

531+
/// Get the class references for the benefit of a dependency analysis.
528532
void java_bytecode_parsert::get_class_refs()
529533
{
530-
// Get the class references for the benefit of a dependency
531-
// analysis.
532-
533534
for(const auto &c : constant_pool)
534535
{
535536
switch(c.tag)
@@ -549,8 +550,11 @@ void java_bytecode_parsert::get_class_refs()
549550
}
550551
}
551552

553+
get_annotation_class_refs(parse_tree.parsed_class.annotations);
554+
552555
for(const auto &field : parse_tree.parsed_class.fields)
553556
{
557+
get_annotation_class_refs(field.annotations);
554558
typet field_type;
555559
if(field.signature.has_value())
556560
{
@@ -572,6 +576,9 @@ void java_bytecode_parsert::get_class_refs()
572576

573577
for(const auto &method : parse_tree.parsed_class.methods)
574578
{
579+
get_annotation_class_refs(method.annotations);
580+
for(const auto &parameter_annotations : method.parameter_annotations)
581+
get_annotation_class_refs(parameter_annotations);
575582
typet method_type;
576583
if(method.signature.has_value())
577584
{
@@ -637,6 +644,41 @@ void java_bytecode_parsert::get_class_refs_rec(const typet &src)
637644
get_class_refs_rec(src.subtype());
638645
}
639646

647+
/// For each of the given annotations, get a reference to its class and
648+
/// recursively get class references of the values it stores.
649+
void java_bytecode_parsert::get_annotation_class_refs(
650+
const java_bytecode_parse_treet::annotationst &annotations)
651+
{
652+
for(const auto &annotation : annotations)
653+
{
654+
get_class_refs_rec(annotation.type);
655+
for(const auto &element_value_pair : annotation.element_value_pairs)
656+
get_annotation_value_class_refs(element_value_pair.value);
657+
}
658+
}
659+
660+
/// See \ref java_bytecode_parsert::get_annotation_class_refs.
661+
/// For the different cases of `exprt`, see \ref
662+
/// java_bytecode_parsert::get_relement_value.
663+
void java_bytecode_parsert::get_annotation_value_class_refs(const exprt &value)
664+
{
665+
if(const auto &symbol_expr = expr_try_dynamic_cast<symbol_exprt>(value))
666+
{
667+
const irep_idt &value_id = symbol_expr->get_identifier();
668+
const typet value_type = java_type_from_string(id2string(value_id));
669+
get_class_refs_rec(value_type);
670+
}
671+
else if(const auto &array_expr = expr_try_dynamic_cast<array_exprt>(value))
672+
{
673+
for(const exprt &operand : array_expr->operands())
674+
get_annotation_value_class_refs(operand);
675+
}
676+
// TODO: enum and nested annotation cases (once these are correctly parsed by
677+
// get_relement_value).
678+
// Note that in the cases where expr is a string or primitive type, no
679+
// additional class references are needed.
680+
}
681+
640682
void java_bytecode_parsert::rconstant_pool()
641683
{
642684
u2 constant_pool_count=read_u2();

0 commit comments

Comments
 (0)