Skip to content

Commit

Permalink
Merge pull request diffblue#2260 from antlechner/antonia/annotation-c…
Browse files Browse the repository at this point in the history
…lass-value

Add support for Java annotations with Class value
  • Loading branch information
romainbrenguier authored Jun 1, 2018
2 parents e0a5142 + e0ad069 commit 15dff7d
Show file tree
Hide file tree
Showing 11 changed files with 115 additions and 2 deletions.
7 changes: 5 additions & 2 deletions jbmc/src/java_bytecode/java_bytecode_parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1514,6 +1514,9 @@ void java_bytecode_parsert::relement_value_pairs(
}
}

/// Corresponds to the element_value structure
/// Described in Java 8 specification 4.7.16.1
/// https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.7.16.1
void java_bytecode_parsert::relement_value_pair(
annotationt::element_value_pairt &element_value_pair)
{
Expand All @@ -1531,8 +1534,8 @@ void java_bytecode_parsert::relement_value_pair(

case 'c':
{
UNUSED u2 class_info_index=read_u2();
// todo: class
u2 class_info_index = read_u2();
element_value_pair.value = symbol_exprt(pool_entry(class_info_index).s);
}
break;

Expand Down
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
public @interface AnnotationWithClassType {
Class<?> value();
}
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
@AnnotationWithClassType(java.lang.String.class)
public class ClassWithClassTypeAnnotation {
}
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
@AnnotationWithClassType(byte.class)
public class ClassWithPrimitiveTypeAnnotation {
}
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
@AnnotationWithClassType(void.class)
public class ClassWithVoidTypeAnnotation {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
java-testing-utils
testing-utils
java_bytecode
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/*******************************************************************\
Module: Unit tests for converting annotations
Author: Diffblue Ltd.
\*******************************************************************/

#include <java-testing-utils/load_java_class.h>
#include <java_bytecode/java_bytecode_convert_class.h>
#include <java_bytecode/java_bytecode_parse_tree.h>
#include <java_bytecode/java_types.h>
#include <testing-utils/catch.hpp>

// See
// https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.7.16.1
SCENARIO(
"java_bytecode_parse_annotations",
"[core][java_bytecode][java_bytecode_parser]")
{
GIVEN("Some class files in the class path")
{
WHEN(
"Parsing an annotation with Class value specified to non-primitive "
"(java.lang.String)")
{
const symbol_tablet &new_symbol_table = load_java_class(
"ClassWithClassTypeAnnotation", "./java_bytecode/java_bytecode_parser");

THEN("The annotation should store the correct type (String)")
{
const symbolt &class_symbol =
*new_symbol_table.lookup("java::ClassWithClassTypeAnnotation");
const std::vector<java_annotationt> &java_annotations =
to_annotated_type(class_symbol.type).get_annotations();
java_bytecode_parse_treet::annotationst annotations;
convert_java_annotations(java_annotations, annotations);
REQUIRE(annotations.size() == 1);
const auto &annotation = annotations.front();
const auto &element_value_pair = annotation.element_value_pairs.front();
const auto &id =
to_symbol_expr(element_value_pair.value).get_identifier();
const auto &java_type = java_type_from_string(id2string(id));
const std::string &class_name =
id2string(to_symbol_type(java_type.subtype()).get_identifier());
REQUIRE(id2string(class_name) == "java::java.lang.String");
}
}
WHEN("Parsing an annotation with Class value specified to primitive (byte)")
{
const symbol_tablet &new_symbol_table = load_java_class(
"ClassWithPrimitiveTypeAnnotation",
"./java_bytecode/java_bytecode_parser");

THEN("The annotation should store the correct type (byte)")
{
const symbolt &class_symbol =
*new_symbol_table.lookup("java::ClassWithPrimitiveTypeAnnotation");
const std::vector<java_annotationt> &java_annotations =
to_annotated_type(class_symbol.type).get_annotations();
java_bytecode_parse_treet::annotationst annotations;
convert_java_annotations(java_annotations, annotations);
REQUIRE(annotations.size() == 1);
const auto &annotation = annotations.front();
const auto &element_value_pair = annotation.element_value_pairs.front();
const auto &id =
to_symbol_expr(element_value_pair.value).get_identifier();
const auto &java_type = java_type_from_string(id2string(id));
REQUIRE(java_type == java_byte_type());
}
}
WHEN("Parsing an annotation with Class value specified to void")
{
const symbol_tablet &new_symbol_table = load_java_class(
"ClassWithVoidTypeAnnotation", "./java_bytecode/java_bytecode_parser");

THEN("The annotation should store the correct type (void)")
{
const symbolt &class_symbol =
*new_symbol_table.lookup("java::ClassWithVoidTypeAnnotation");
const std::vector<java_annotationt> &java_annotations =
to_annotated_type(class_symbol.type).get_annotations();
java_bytecode_parse_treet::annotationst annotations;
convert_java_annotations(java_annotations, annotations);
REQUIRE(annotations.size() == 1);
const auto &annotation = annotations.front();
const auto &element_value_pair = annotation.element_value_pairs.front();
const auto &id =
to_symbol_expr(element_value_pair.value).get_identifier();
const auto &java_type = java_type_from_string(id2string(id));
REQUIRE(java_type == void_type());
}
}
}
}

0 comments on commit 15dff7d

Please sign in to comment.