Skip to content

Commit d77f6a2

Browse files
authoredApr 13, 2018
Merge pull request #1831 from NathanJPhillips/feature/class-annotations
[SEC-179] Add annotations to java_class_typet
2 parents f84753d + 9a8d937 commit d77f6a2

22 files changed

+525
-77
lines changed
 
Binary file not shown.
Binary file not shown.
Binary file not shown.
409 Bytes
Binary file not shown.
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
@interface ClassAnnotation {
2+
}
3+
4+
@interface MethodAnnotation {
5+
}
6+
7+
@interface FieldAnnotation {
8+
}
9+
10+
@ClassAnnotation
11+
public class annotations
12+
{
13+
@FieldAnnotation
14+
public int x;
15+
16+
@FieldAnnotation
17+
public static int y;
18+
19+
@MethodAnnotation
20+
public void main()
21+
{
22+
}
23+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
CORE
2+
annotations.class
3+
--verbosity 10 --show-symbol-table
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^Type\.\.\.\.\.\.\.\.: @java::ClassAnnotation struct annotations
7+
^Type\.\.\.\.\.\.\.\.: @java::MethodAnnotation \(struct annotations \*\) -> void$
8+
^Type\.\.\.\.\.\.\.\.: @java::FieldAnnotation int$
9+
--
10+
--
11+
The purpose of the test is ensuring that annotations can be shown in the symbol
12+
table.

‎src/ansi-c/c_qualifiers.cpp

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,27 @@ Author: Daniel Kroening, kroening@kroening.com
99
#include "c_qualifiers.h"
1010

1111
#include <ostream>
12+
#include <util/make_unique.h>
13+
14+
c_qualifierst &c_qualifierst::operator=(const c_qualifierst &other)
15+
{
16+
is_constant = other.is_constant;
17+
is_volatile = other.is_volatile;
18+
is_restricted = other.is_restricted;
19+
is_atomic = other.is_atomic;
20+
is_noreturn = other.is_noreturn;
21+
is_ptr32 = other.is_ptr32;
22+
is_ptr64 = other.is_ptr64;
23+
is_transparent_union = other.is_transparent_union;
24+
return *this;
25+
}
26+
27+
std::unique_ptr<qualifierst> c_qualifierst::clone() const
28+
{
29+
auto other = util_make_unique<c_qualifierst>();
30+
*other = *this;
31+
return std::move(other);
32+
}
1233

1334
std::string c_qualifierst::as_string() const
1435
{
@@ -120,9 +141,7 @@ void c_qualifierst::clear(typet &dest)
120141
}
121142

122143
/// pretty-print the qualifiers
123-
std::ostream &operator << (
124-
std::ostream &out,
125-
const c_qualifierst &c_qualifiers)
144+
std::ostream &operator<<(std::ostream &out, const qualifierst &qualifiers)
126145
{
127-
return out << c_qualifiers.as_string();
146+
return out << qualifiers.as_string();
128147
}

‎src/ansi-c/c_qualifiers.h

Lines changed: 85 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,53 @@ Author: Daniel Kroening, kroening@kroening.com
1111
#define CPROVER_ANSI_C_C_QUALIFIERS_H
1212

1313
#include <iosfwd>
14+
#include <memory>
1415

1516
#include <util/expr.h>
1617

17-
class c_qualifierst
18+
class qualifierst
19+
{
20+
protected:
21+
// Only derived classes can construct
22+
qualifierst() = default;
23+
24+
public:
25+
// Copy/move construction/assignment is deleted here and in derived classes
26+
qualifierst(const qualifierst &) = delete;
27+
qualifierst(qualifierst &&) = delete;
28+
qualifierst &operator=(const qualifierst &) = delete;
29+
qualifierst &operator=(qualifierst &&) = delete;
30+
31+
// Destruction is virtual
32+
virtual ~qualifierst() = default;
33+
34+
public:
35+
virtual std::unique_ptr<qualifierst> clone() const = 0;
36+
37+
virtual qualifierst &operator+=(const qualifierst &b) = 0;
38+
39+
virtual std::size_t count() const = 0;
40+
41+
virtual void clear() = 0;
42+
43+
virtual void read(const typet &src) = 0;
44+
virtual void write(typet &src) const = 0;
45+
46+
// Comparisons
47+
virtual bool is_subset_of(const qualifierst &q) const = 0;
48+
virtual bool operator==(const qualifierst &other) const = 0;
49+
bool operator!=(const qualifierst &other) const
50+
{
51+
return !(*this == other);
52+
}
53+
54+
// String conversion
55+
virtual std::string as_string() const = 0;
56+
friend std::ostream &operator<<(std::ostream &, const qualifierst &);
57+
};
58+
59+
60+
class c_qualifierst : public qualifierst
1861
{
1962
public:
2063
c_qualifierst()
@@ -28,7 +71,12 @@ class c_qualifierst
2871
read(src);
2972
}
3073

31-
void clear()
74+
protected:
75+
c_qualifierst &operator=(const c_qualifierst &other);
76+
public:
77+
virtual std::unique_ptr<qualifierst> clone() const override;
78+
79+
virtual void clear() override
3280
{
3381
is_constant=false;
3482
is_volatile=false;
@@ -50,62 +98,60 @@ class c_qualifierst
5098

5199
// will likely add alignment here as well
52100

53-
std::string as_string() const;
54-
void read(const typet &src);
55-
void write(typet &src) const;
101+
virtual std::string as_string() const override;
102+
virtual void read(const typet &src) override;
103+
virtual void write(typet &src) const override;
56104

57105
static void clear(typet &dest);
58106

59-
bool is_subset_of(const c_qualifierst &q) const
107+
virtual bool is_subset_of(const qualifierst &other) const override
60108
{
61-
return (!is_constant || q.is_constant) &&
62-
(!is_volatile || q.is_volatile) &&
63-
(!is_restricted || q.is_restricted) &&
64-
(!is_atomic || q.is_atomic) &&
65-
(!is_ptr32 || q.is_ptr32) &&
66-
(!is_ptr64 || q.is_ptr64) &&
67-
(!is_noreturn || q.is_noreturn);
109+
const c_qualifierst *cq = dynamic_cast<const c_qualifierst *>(&other);
110+
return
111+
(!is_constant || cq->is_constant) &&
112+
(!is_volatile || cq->is_volatile) &&
113+
(!is_restricted || cq->is_restricted) &&
114+
(!is_atomic || cq->is_atomic) &&
115+
(!is_ptr32 || cq->is_ptr32) &&
116+
(!is_ptr64 || cq->is_ptr64) &&
117+
(!is_noreturn || cq->is_noreturn);
68118

69119
// is_transparent_union isn't checked
70120
}
71121

72-
bool operator==(const c_qualifierst &other) const
122+
virtual bool operator==(const qualifierst &other) const override
73123
{
74-
return is_constant==other.is_constant &&
75-
is_volatile==other.is_volatile &&
76-
is_restricted==other.is_restricted &&
77-
is_atomic==other.is_atomic &&
78-
is_ptr32==other.is_ptr32 &&
79-
is_ptr64==other.is_ptr64 &&
80-
is_transparent_union==other.is_transparent_union &&
81-
is_noreturn==other.is_noreturn;
124+
const c_qualifierst *cq = dynamic_cast<const c_qualifierst *>(&other);
125+
return
126+
is_constant == cq->is_constant &&
127+
is_volatile == cq->is_volatile &&
128+
is_restricted == cq->is_restricted &&
129+
is_atomic == cq->is_atomic &&
130+
is_ptr32 == cq->is_ptr32 &&
131+
is_ptr64 == cq->is_ptr64 &&
132+
is_transparent_union == cq->is_transparent_union &&
133+
is_noreturn == cq->is_noreturn;
82134
}
83135

84-
bool operator!=(const c_qualifierst &other) const
136+
virtual qualifierst &operator+=(const qualifierst &other) override
85137
{
86-
return !(*this==other);
87-
}
88-
89-
c_qualifierst &operator+=(const c_qualifierst &b)
90-
{
91-
is_constant|=b.is_constant;
92-
is_volatile|=b.is_volatile;
93-
is_restricted|=b.is_restricted;
94-
is_atomic|=b.is_atomic;
95-
is_ptr32|=b.is_ptr32;
96-
is_ptr64|=b.is_ptr64;
97-
is_transparent_union|=b.is_transparent_union;
98-
is_noreturn|=b.is_noreturn;
138+
const c_qualifierst *cq = dynamic_cast<const c_qualifierst *>(&other);
139+
is_constant |= cq->is_constant;
140+
is_volatile |= cq->is_volatile;
141+
is_restricted |= cq->is_restricted;
142+
is_atomic |= cq->is_atomic;
143+
is_ptr32 |= cq->is_ptr32;
144+
is_ptr64 |= cq->is_ptr64;
145+
is_transparent_union |= cq->is_transparent_union;
146+
is_noreturn |= cq->is_noreturn;
99147
return *this;
100148
}
101149

102-
unsigned count() const
150+
virtual std::size_t count() const override
103151
{
104152
return is_constant+is_volatile+is_restricted+is_atomic+
105153
is_ptr32+is_ptr64+is_noreturn;
106154
}
107155
};
108156

109-
std::ostream &operator << (std::ostream &, const c_qualifierst &);
110-
111157
#endif // CPROVER_ANSI_C_C_QUALIFIERS_H

‎src/ansi-c/expr2c.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -162,10 +162,11 @@ std::string expr2ct::convert(const typet &src)
162162

163163
std::string expr2ct::convert_rec(
164164
const typet &src,
165-
const c_qualifierst &qualifiers,
165+
const qualifierst &qualifiers,
166166
const std::string &declarator)
167167
{
168-
c_qualifierst new_qualifiers(qualifiers);
168+
std::unique_ptr<qualifierst> clone = qualifiers.clone();
169+
c_qualifierst &new_qualifiers = dynamic_cast<c_qualifierst &>(*clone);
169170
new_qualifiers.read(src);
170171

171172
std::string q=new_qualifiers.as_string();
@@ -736,7 +737,7 @@ std::string expr2ct::convert_struct_type(
736737
/// \return A C-like type declaration of an array
737738
std::string expr2ct::convert_array_type(
738739
const typet &src,
739-
const c_qualifierst &qualifiers,
740+
const qualifierst &qualifiers,
740741
const std::string &declarator_str)
741742
{
742743
return convert_array_type(src, qualifiers, declarator_str, true);
@@ -752,7 +753,7 @@ std::string expr2ct::convert_array_type(
752753
/// \return A C-like type declaration of an array
753754
std::string expr2ct::convert_array_type(
754755
const typet &src,
755-
const c_qualifierst &qualifiers,
756+
const qualifierst &qualifiers,
756757
const std::string &declarator_str,
757758
bool inc_size_if_possible)
758759
{

‎src/ansi-c/expr2c_class.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ Author: Daniel Kroening, kroening@kroening.com
1717
#include <util/std_code.h>
1818
#include <util/std_expr.h>
1919

20-
class c_qualifierst;
20+
class qualifierst;
2121
class namespacet;
2222

2323
class expr2ct
@@ -36,7 +36,7 @@ class expr2ct
3636

3737
virtual std::string convert_rec(
3838
const typet &src,
39-
const c_qualifierst &qualifiers,
39+
const qualifierst &qualifiers,
4040
const std::string &declarator);
4141

4242
virtual std::string convert_struct_type(
@@ -53,12 +53,12 @@ class expr2ct
5353

5454
virtual std::string convert_array_type(
5555
const typet &src,
56-
const c_qualifierst &qualifiers,
56+
const qualifierst &qualifiers,
5757
const std::string &declarator_str);
5858

5959
std::string convert_array_type(
6060
const typet &src,
61-
const c_qualifierst &qualifiers,
61+
const qualifierst &qualifiers,
6262
const std::string &declarator_str,
6363
bool inc_size_if_possible);
6464

‎src/cpp/expr2cpp.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ class expr2cppt:public expr2ct
4141

4242
std::string convert_rec(
4343
const typet &src,
44-
const c_qualifierst &qualifiers,
44+
const qualifierst &qualifiers,
4545
const std::string &declarator) override;
4646

4747
typedef std::unordered_set<std::string, string_hash> id_sett;
@@ -129,10 +129,11 @@ std::string expr2cppt::convert_constant(
129129

130130
std::string expr2cppt::convert_rec(
131131
const typet &src,
132-
const c_qualifierst &qualifiers,
132+
const qualifierst &qualifiers,
133133
const std::string &declarator)
134134
{
135-
c_qualifierst new_qualifiers(qualifiers);
135+
std::unique_ptr<qualifierst> clone = qualifiers.clone();
136+
qualifierst &new_qualifiers = *clone;
136137
new_qualifiers.read(src);
137138

138139
const std::string d=

‎src/java_bytecode/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ SRC = bytecode_info.cpp \
2323
java_local_variable_table.cpp \
2424
java_object_factory.cpp \
2525
java_pointer_casts.cpp \
26+
java_qualifiers.cpp \
2627
java_root_class.cpp \
2728
java_static_initializers.cpp \
2829
java_string_library_preprocess.cpp \

‎src/java_bytecode/expr2java.cpp

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,22 @@ Author: Daniel Kroening, kroening@cs.cmu.edu
1919
#include <util/arith_tools.h>
2020
#include <util/ieee_float.h>
2121

22-
#include <ansi-c/c_qualifiers.h>
2322
#include <ansi-c/c_misc.h>
2423
#include <ansi-c/expr2c_class.h>
2524

25+
#include "java_qualifiers.h"
2626
#include "java_types.h"
2727

28+
std::string expr2javat::convert(const typet &src)
29+
{
30+
return convert_rec(src, java_qualifierst(ns), "");
31+
}
32+
33+
std::string expr2javat::convert(const exprt &src)
34+
{
35+
return expr2ct::convert(src);
36+
}
37+
2838
std::string expr2javat::convert_code_function_call(
2939
const code_function_callt &src,
3040
unsigned indent)
@@ -241,10 +251,11 @@ std::string expr2javat::convert_constant(
241251

242252
std::string expr2javat::convert_rec(
243253
const typet &src,
244-
const c_qualifierst &qualifiers,
254+
const qualifierst &qualifiers,
245255
const std::string &declarator)
246256
{
247-
c_qualifierst new_qualifiers(qualifiers);
257+
std::unique_ptr<qualifierst> clone = qualifiers.clone();
258+
qualifierst &new_qualifiers = *clone;
248259
new_qualifiers.read(src);
249260

250261
const std::string d=
@@ -307,7 +318,7 @@ std::string expr2javat::convert_rec(
307318
const typet &return_type=code_type.return_type();
308319
dest+=" -> "+convert(return_type);
309320

310-
return dest;
321+
return q + dest;
311322
}
312323
else
313324
return expr2ct::convert_rec(src, qualifiers, declarator);

‎src/java_bytecode/expr2java.h

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -20,30 +20,29 @@ class expr2javat:public expr2ct
2020
{
2121
public:
2222
explicit expr2javat(const namespacet &_ns):expr2ct(_ns) { }
23+
virtual std::string convert(const typet &src) override;
24+
virtual std::string convert(const exprt &src) override;
25+
2326
protected:
2427
virtual std::string convert_with_precedence(
25-
const exprt &src, unsigned &precedence);
26-
virtual std::string convert_java_this(const exprt &src, unsigned precedence);
27-
virtual std::string convert_java_instanceof(
28-
const exprt &src,
29-
unsigned precedence);
30-
virtual std::string convert_java_new(const exprt &src, unsigned precedence);
31-
virtual std::string convert_code_java_delete(
32-
const exprt &src,
33-
unsigned precedence);
34-
virtual std::string convert_struct(const exprt &src, unsigned &precedence);
35-
virtual std::string convert_code(const codet &src, unsigned indent);
28+
const exprt &src, unsigned &precedence) override;
29+
std::string convert_java_this(const exprt &src, unsigned precedence);
30+
std::string convert_java_instanceof(const exprt &src, unsigned precedence);
31+
std::string convert_java_new(const exprt &src, unsigned precedence);
32+
std::string convert_code_java_delete(const exprt &src, unsigned precedence);
33+
virtual std::string convert_struct(
34+
const exprt &src, unsigned &precedence) override;
35+
virtual std::string convert_code(const codet &src, unsigned indent) override;
3636
virtual std::string convert_constant(
37-
const constant_exprt &src,
38-
unsigned &precedence);
39-
virtual std::string convert_code_function_call(
40-
const code_function_callt &src,
41-
unsigned indent);
37+
const constant_exprt &src, unsigned &precedence) override;
38+
// Hides base class version
39+
std::string convert_code_function_call(
40+
const code_function_callt &src, unsigned indent);
4241

4342
virtual std::string convert_rec(
4443
const typet &src,
45-
const c_qualifierst &qualifiers,
46-
const std::string &declarator);
44+
const qualifierst &qualifiers,
45+
const std::string &declarator) override;
4746

4847
// length of string representation of Java Char
4948
// representation is '\u0000'

‎src/java_bytecode/java_bytecode_convert_class.cpp

Lines changed: 45 additions & 1 deletion
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+
type_checked_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

Lines changed: 4 additions & 0 deletions
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

Lines changed: 9 additions & 0 deletions
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+
type_checked_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_qualifiers.cpp

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
// Author: Diffblue Ltd.
2+
3+
/// \file
4+
/// Java-specific type qualifiers
5+
6+
#include "java_qualifiers.h"
7+
#include <sstream>
8+
#include <util/make_unique.h>
9+
#include "expr2java.h"
10+
11+
12+
java_qualifierst &java_qualifierst::operator=(const java_qualifierst &other)
13+
{
14+
INVARIANT(
15+
&other.ns == &ns,
16+
"Can only assign from a java_qualifierst using the same namespace");
17+
annotations = other.annotations;
18+
c_qualifierst::operator=(other);
19+
return *this;
20+
}
21+
22+
std::unique_ptr<qualifierst> java_qualifierst::clone() const
23+
{
24+
auto other = util_make_unique<java_qualifierst>(ns);
25+
*other = *this;
26+
return std::move(other);
27+
}
28+
29+
std::size_t java_qualifierst::count() const
30+
{
31+
return c_qualifierst::count() + annotations.size();
32+
}
33+
34+
void java_qualifierst::clear()
35+
{
36+
c_qualifierst::clear();
37+
annotations.clear();
38+
}
39+
40+
void java_qualifierst::read(const typet &src)
41+
{
42+
c_qualifierst::read(src);
43+
auto &annotated_type = static_cast<const annotated_typet &>(src);
44+
annotations = annotated_type.get_annotations();
45+
}
46+
47+
void java_qualifierst::write(typet &src) const
48+
{
49+
c_qualifierst::write(src);
50+
type_checked_cast<annotated_typet>(src).get_annotations() = annotations;
51+
}
52+
53+
qualifierst &java_qualifierst::operator+=(const qualifierst &other)
54+
{
55+
c_qualifierst::operator+=(other);
56+
auto jq = dynamic_cast<const java_qualifierst *>(&other);
57+
if(jq != nullptr)
58+
{
59+
std::copy(
60+
jq->annotations.begin(),
61+
jq->annotations.end(),
62+
std::back_inserter(annotations));
63+
}
64+
return *this;
65+
}
66+
67+
bool java_qualifierst::operator==(const qualifierst &other) const
68+
{
69+
auto jq = dynamic_cast<const java_qualifierst *>(&other);
70+
if(jq == nullptr)
71+
return false;
72+
return c_qualifierst::operator==(other) && annotations == jq->annotations;
73+
}
74+
75+
bool java_qualifierst::is_subset_of(const qualifierst &other) const
76+
{
77+
if(!c_qualifierst::is_subset_of(other))
78+
return false;
79+
auto jq = dynamic_cast<const java_qualifierst *>(&other);
80+
if(jq == nullptr)
81+
return annotations.empty();
82+
auto &other_a = jq->annotations;
83+
for(const auto &annotation : annotations)
84+
{
85+
if(std::find(other_a.begin(), other_a.end(), annotation) == other_a.end())
86+
return false;
87+
}
88+
return true;
89+
}
90+
91+
std::string java_qualifierst::as_string() const
92+
{
93+
std::stringstream out;
94+
for(const java_annotationt &annotation : annotations)
95+
{
96+
out << '@';
97+
out << annotation.get_type().subtype().get(ID_identifier);
98+
99+
if(!annotation.get_values().empty())
100+
{
101+
out << '(';
102+
103+
bool first = true;
104+
for(const java_annotationt::valuet &value : annotation.get_values())
105+
{
106+
if(first)
107+
first = false;
108+
else
109+
out << ", ";
110+
111+
out << '"' << value.get_name() << '"' << '=';
112+
out << expr2java(value.get_value(), ns);
113+
}
114+
115+
out << ')';
116+
}
117+
out << ' ';
118+
}
119+
out << c_qualifierst::as_string();
120+
return out.str();
121+
}

‎src/java_bytecode/java_qualifiers.h

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// Author: Diffblue Ltd.
2+
3+
/// \file
4+
/// Java-specific type qualifiers
5+
6+
#ifndef CPROVER_JAVA_BYTECODE_JAVA_QUALIFIERS_H
7+
#define CPROVER_JAVA_BYTECODE_JAVA_QUALIFIERS_H
8+
9+
#include "java_types.h"
10+
#include <ansi-c/c_qualifiers.h>
11+
12+
class java_qualifierst : public c_qualifierst
13+
{
14+
private:
15+
const namespacet &ns;
16+
std::vector<java_annotationt> annotations;
17+
18+
public:
19+
explicit java_qualifierst(const namespacet &ns)
20+
: ns(ns)
21+
{}
22+
23+
protected:
24+
java_qualifierst &operator=(const java_qualifierst &other);
25+
public:
26+
virtual std::unique_ptr<qualifierst> clone() const override;
27+
28+
virtual qualifierst &operator+=(const qualifierst &other) override;
29+
30+
const std::vector<java_annotationt> &get_annotations() const
31+
{
32+
return annotations;
33+
}
34+
virtual std::size_t count() const override;
35+
36+
virtual void clear() override;
37+
38+
virtual void read(const typet &src) override;
39+
virtual void write(typet &src) const override;
40+
41+
virtual bool is_subset_of(const qualifierst &other) const override;
42+
virtual bool operator==(const qualifierst &other) const override;
43+
44+
virtual std::string as_string() const override;
45+
};
46+
47+
#endif // CPROVER_JAVA_BYTECODE_JAVA_QUALIFIERS_H

‎src/java_bytecode/java_types.h

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,85 @@ Author: Daniel Kroening, kroening@kroening.com
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+
85+
inline const annotated_typet &to_annotated_type(const typet &type)
86+
{
87+
return static_cast<const annotated_typet &>(type);
88+
}
89+
90+
inline annotated_typet &to_annotated_type(typet &type)
91+
{
92+
return static_cast<annotated_typet &>(type);
93+
}
94+
95+
template <>
96+
inline bool can_cast_type<annotated_typet>(const typet &type)
97+
{
98+
return true;
99+
}
100+
22101
class java_class_typet:public class_typet
23102
{
24103
public:
@@ -57,6 +136,18 @@ class java_class_typet:public class_typet
57136
// creates empty symbol_exprt and pushes it in the vector
58137
lambda_method_handles().emplace_back();
59138
}
139+
140+
const std::vector<java_annotationt> &get_annotations() const
141+
{
142+
return static_cast<const annotated_typet &>(
143+
static_cast<const typet &>(*this)).get_annotations();
144+
}
145+
146+
std::vector<java_annotationt> &get_annotations()
147+
{
148+
return type_checked_cast<annotated_typet>(
149+
static_cast<typet &>(*this)).get_annotations();
150+
}
60151
};
61152

62153
inline const java_class_typet &to_java_class_type(const typet &type)
@@ -71,6 +162,12 @@ inline java_class_typet &to_java_class_type(typet &type)
71162
return static_cast<java_class_typet &>(type);
72163
}
73164

165+
template <>
166+
inline bool can_cast_type<java_class_typet>(const typet &type)
167+
{
168+
return can_cast_type<class_typet>(type);
169+
}
170+
74171
typet java_int_type();
75172
typet java_long_type();
76173
typet java_short_type();

‎src/util/irep_ids.def

Lines changed: 1 addition & 0 deletions
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

‎src/util/std_types.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,12 @@ inline struct_typet &to_struct_type(typet &type)
328328
return static_cast<struct_typet &>(type);
329329
}
330330

331+
template <>
332+
inline bool can_cast_type<struct_typet>(const typet &type)
333+
{
334+
return type.id() == ID_struct;
335+
}
336+
331337
/*! \brief C++ class type
332338
*/
333339
class class_typet:public struct_typet
@@ -432,6 +438,12 @@ inline class_typet &to_class_type(typet &type)
432438
return static_cast<class_typet &>(type);
433439
}
434440

441+
template <>
442+
inline bool can_cast_type<class_typet>(const typet &type)
443+
{
444+
return can_cast_type<struct_typet>(type) && type.get_bool(ID_C_class);
445+
}
446+
435447
/*! \brief The union type
436448
*/
437449
class union_typet:public struct_union_typet

0 commit comments

Comments
 (0)
Please sign in to comment.