Skip to content

Commit c57a132

Browse files
authored
Merge pull request diffblue#2318 from tautschnig/c++-template-resolution
C++ function disambiguation and template scope cleanup [blocks: diffblue#1260]
2 parents 627afcf + aa40d59 commit c57a132

25 files changed

+179
-170
lines changed

regression/systemc/BitvectorSc1/main.cpp

+2-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
#include <cassert>
2-
31
template <int W>
42
class sc_uint {
53
public:
@@ -41,8 +39,8 @@ int main(int argc, char** argv)
4139
x.test1();
4240
x.test2();
4341

44-
assert(x.to_uint() == 1);
45-
assert(x.to_uint() == 2);
42+
__CPROVER_assert(x.to_uint() == 1, "");
43+
__CPROVER_assert(x.to_uint() == 2, "");
4644

4745
return 0;
4846
}

regression/systemc/BitvectorSc2/main.cpp

+1-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
#include <cassert>
2-
31
template <int W>
42
class sc_uint {
53
public:
@@ -56,7 +54,7 @@ int main(int argc, char** argv)
5654
z += y;
5755

5856
sc_uint<10> w(3);
59-
assert(z == w);
57+
__CPROVER_assert(z == w, "");
6058

6159
return 0;
6260
}

regression/systemc/BitvectorSc3/test.desc

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
KNOWNBUG
1+
CORE
22
main.cpp
33

44
^EXIT=0$

regression/systemc/EqualOp1/main.cpp

+1-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
#include <cassert>
2-
31
template<class T>
42
class myclass
53
{
@@ -20,5 +18,5 @@ int main(int argc, char** argv)
2018
myclass<int> x(0);
2119
myclass<int> y(1);
2220
x = y;
23-
assert(x == y);
21+
__CPROVER_assert(x == y, "");
2422
}

regression/systemc/EqualOp2/main.cpp

+1-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
#include <cassert>
2-
31
template<class T>
42
class myclass
53
{
@@ -26,5 +24,5 @@ int main(int argc, char** argv)
2624
myclass<int> y(1);
2725
//x = y;
2826
x += 1;
29-
assert(x == y);
27+
__CPROVER_assert(x == y, "");
3028
}

regression/systemc/EqualOp3/main.cpp

+1-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
#include <cassert>
2-
31
template<class T>
42
class myclass2;
53

@@ -38,6 +36,6 @@ int main(int argc, char** argv)
3836
myclass2<int> x(0);
3937
myclass<int> y(1);
4038
x = y;
41-
assert(x == y);
39+
__CPROVER_assert(x == y, "");
4240
return 0;
4341
}

regression/systemc/ForwardDecl1/test.desc

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
KNOWNBUG
1+
CORE
22
main.cpp
33

44
^EXIT=0$

regression/systemc/FunTempl1/main.cpp

+1-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
#include <cassert>
2-
31
template<class T>
42
T inc(T x)
53
{
@@ -15,5 +13,5 @@ int main(int argc, char** argv)
1513
x = inc<int>(x);
1614
y = inc<unsigned char>(y);
1715

18-
assert(x == y);
16+
__CPROVER_assert(x == y, "");
1917
}

regression/systemc/Mult1/test.desc

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
KNOWNBUG
22
main.cpp
3-
3+
--object-bits 10
44
^EXIT=0$
55
^SIGNAL=0$
66
^VERIFICATION SUCCESSFUL$

regression/systemc/SimpleSc1/main.cpp

+1-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
#include <cassert>
2-
31
template <int W>
42
class sc_uint {
53
public:
@@ -54,7 +52,7 @@ int main(int argc, char** argv)
5452
z += y;
5553

5654
sc_uint<10> w(3);
57-
assert(z == w);
55+
__CPROVER_assert(z == w, "");
5856

5957
return 0;
6058
}

regression/systemc/Template1/main.cpp

+2-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
#include <cassert>
2-
31
#define DEF_INSIDE
42

53
template<class T>
@@ -35,8 +33,8 @@ int main (int argc, char *argv[])
3533
my_template<int> x;
3634
x.set(5);
3735
int y = x.get();
38-
assert(y==5);
39-
assert(z.get()==3);
36+
__CPROVER_assert(y == 5, "");
37+
__CPROVER_assert(z.get() == 3, "");
4038

4139
return 0;
4240
}

regression/systemc/Tuple1/test.desc

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
KNOWNBUG
1+
CORE
22
main.cpp
33
-DNO_IO -DNO_STRING
44
^EXIT=0$

regression/systemc/Tuple2/test.desc

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
KNOWNBUG
1+
CORE
22
main.cpp
33
-DNO_IO -DNO_STRING
44
^EXIT=0$

src/cpp/cpp_declarator_converter.cpp

+24-7
Original file line numberDiff line numberDiff line change
@@ -64,11 +64,22 @@ symbolt &cpp_declarator_convertert::convert(
6464
cpp_typecheck_resolve.resolve_scope(
6565
declarator.name(), base_name, template_args);
6666

67+
cpp_scopet *friend_scope = nullptr;
68+
69+
if(is_friend)
70+
{
71+
friend_scope = &cpp_typecheck.cpp_scopes.current_scope();
72+
save_scope.restore();
73+
}
74+
6775
scope=&cpp_typecheck.cpp_scopes.current_scope();
6876

69-
// check the declarator-part of the type, in that scope
77+
// check the declarator-part of the type, in the current scope
7078
if(declarator.value().is_nil() || !cpp_typecheck.has_auto(final_type))
7179
cpp_typecheck.typecheck_type(final_type);
80+
81+
if(friend_scope)
82+
scope = friend_scope;
7283
}
7384

7485
is_code=is_code_type(final_type);
@@ -80,9 +91,9 @@ symbolt &cpp_declarator_convertert::convert(
8091
get_final_identifier();
8192

8293
// first see if it is a member
83-
if(scope->id_class==cpp_idt::id_classt::CLASS && !is_friend)
94+
if(scope->id_class == cpp_idt::id_classt::CLASS)
8495
{
85-
// it's a member! it must be declared already
96+
// it's a member! it must be declared already, unless it's a friend
8697

8798
typet &method_qualifier=
8899
static_cast<typet &>(declarator.method_qualifier());
@@ -118,7 +129,15 @@ symbolt &cpp_declarator_convertert::convert(
118129

119130
// try again
120131
maybe_symbol=cpp_typecheck.symbol_table.get_writeable(final_identifier);
121-
if(!maybe_symbol)
132+
if(!maybe_symbol && is_friend)
133+
{
134+
symbolt &friend_symbol =
135+
convert_new_symbol(storage_spec, member_spec, declarator);
136+
// mark it as weak so that the full declaration can replace the symbol
137+
friend_symbol.is_weak = true;
138+
return friend_symbol;
139+
}
140+
else if(!maybe_symbol)
122141
{
123142
cpp_typecheck.error().source_location=
124143
declarator.name().source_location();
@@ -411,9 +430,7 @@ void cpp_declarator_convertert::get_final_identifier()
411430
}
412431
}
413432

414-
final_identifier=
415-
scope->prefix+
416-
identifier;
433+
final_identifier = scope->prefix + identifier;
417434
}
418435

419436
symbolt &cpp_declarator_convertert::convert_new_symbol(

src/cpp/cpp_id.h

+5
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,11 @@ class cpp_idt
7070
return id_class==id_classt::TYPEDEF;
7171
}
7272

73+
bool is_template_scope() const
74+
{
75+
return id_class == id_classt::TEMPLATE_SCOPE;
76+
}
77+
7378
irep_idt identifier, base_name;
7479

7580
// if it is a member or method, what class is it in?

src/cpp/cpp_instantiate_template.cpp

+42-29
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,40 @@ void cpp_typecheckt::show_instantiation_stack(std::ostream &out)
103103
}
104104
}
105105

106+
/// Set up a scope as subscope of the template scope
107+
cpp_scopet &cpp_typecheckt::sub_scope_for_instantiation(
108+
cpp_scopet &template_scope,
109+
const std::string &suffix)
110+
{
111+
cpp_scopet::id_sett id_set =
112+
template_scope.lookup(suffix, cpp_scopet::SCOPE_ONLY);
113+
114+
CHECK_RETURN(id_set.size() <= 1);
115+
116+
if(id_set.size() == 1)
117+
{
118+
cpp_idt &cpp_id = **id_set.begin();
119+
CHECK_RETURN(cpp_id.is_template_scope());
120+
121+
return static_cast<cpp_scopet &>(cpp_id);
122+
}
123+
else
124+
{
125+
cpp_scopet &sub_scope = template_scope.new_scope(suffix);
126+
sub_scope.id_class = cpp_idt::id_classt::TEMPLATE_SCOPE;
127+
sub_scope.prefix = template_scope.get_parent().prefix;
128+
sub_scope.suffix = suffix;
129+
sub_scope.add_using_scope(template_scope.get_parent());
130+
131+
const std::string subscope_name =
132+
id2string(template_scope.identifier) + suffix;
133+
cpp_scopes.id_map.insert(
134+
cpp_scopest::id_mapt::value_type(subscope_name, &sub_scope));
135+
136+
return sub_scope;
137+
}
138+
}
139+
106140
const symbolt &cpp_typecheckt::class_template_symbol(
107141
const source_locationt &source_location,
108142
const symbolt &template_symbol,
@@ -131,10 +165,9 @@ const symbolt &cpp_typecheckt::class_template_symbol(
131165
INVARIANT_STRUCTURED(
132166
template_scope!=nullptr, nullptr_exceptiont, "template_scope is null");
133167

134-
irep_idt identifier=
135-
id2string(template_scope->prefix)+
136-
"tag-"+id2string(template_symbol.base_name)+
137-
id2string(suffix);
168+
irep_idt identifier = id2string(template_scope->get_parent().prefix) +
169+
"tag-" + id2string(template_symbol.base_name) +
170+
id2string(suffix);
138171

139172
// already there?
140173
symbol_tablet::symbolst::const_iterator s_it=
@@ -171,9 +204,8 @@ const symbolt &cpp_typecheckt::class_template_symbol(
171204

172205
id.id_class=cpp_idt::id_classt::CLASS;
173206
id.is_scope=true;
174-
id.prefix=template_scope->prefix+
175-
id2string(s_ptr->base_name)+
176-
id2string(suffix)+"::";
207+
id.prefix = template_scope->get_parent().prefix +
208+
id2string(s_ptr->base_name) + id2string(suffix) + "::";
177209
id.class_identifier=s_ptr->name;
178210
id.id_class=cpp_idt::id_classt::CLASS;
179211

@@ -318,18 +350,12 @@ const symbolt &cpp_typecheckt::instantiate_template(
318350
class_name=cpp_scopes.current_scope().get_parent().identifier;
319351

320352
// sub-scope for fixing the prefix
321-
std::string subscope_name=id2string(template_scope->identifier)+suffix;
353+
cpp_scopet &sub_scope = sub_scope_for_instantiation(*template_scope, suffix);
322354

323355
// let's see if we have the instance already
324-
cpp_scopest::id_mapt::iterator scope_it=
325-
cpp_scopes.id_map.find(subscope_name);
326-
327-
if(scope_it!=cpp_scopes.id_map.end())
328356
{
329-
cpp_scopet &scope=cpp_scopes.get_scope(subscope_name);
330-
331-
const auto id_set =
332-
scope.lookup(template_symbol.base_name, cpp_scopet::SCOPE_ONLY);
357+
cpp_scopet::id_sett id_set =
358+
sub_scope.lookup(template_symbol.base_name, cpp_scopet::SCOPE_ONLY);
333359

334360
if(id_set.size()==1)
335361
{
@@ -349,20 +375,7 @@ const symbolt &cpp_typecheckt::instantiate_template(
349375
return symb;
350376
}
351377

352-
cpp_scopes.go_to(scope);
353-
}
354-
else
355-
{
356-
// set up a scope as subscope of the template scope
357-
cpp_scopet &sub_scope=
358-
cpp_scopes.current_scope().new_scope(subscope_name);
359-
sub_scope.id_class=cpp_idt::id_classt::TEMPLATE_SCOPE;
360-
sub_scope.prefix=template_scope->get_parent().prefix;
361-
sub_scope.suffix=suffix;
362-
sub_scope.add_using_scope(template_scope->get_parent());
363378
cpp_scopes.go_to(sub_scope);
364-
cpp_scopes.id_map.insert(
365-
cpp_scopest::id_mapt::value_type(subscope_name, &sub_scope));
366379
}
367380

368381
// store the information that the template has

src/cpp/cpp_scope.h

-5
Original file line numberDiff line numberDiff line change
@@ -85,11 +85,6 @@ class cpp_scopet:public cpp_idt
8585
id_class==id_classt::NAMESPACE;
8686
}
8787

88-
bool is_template_scope() const
89-
{
90-
return id_class==id_classt::TEMPLATE_SCOPE;
91-
}
92-
9388
cpp_scopet &get_parent() const
9489
{
9590
return static_cast<cpp_scopet &>(cpp_idt::get_parent());

src/cpp/cpp_scopes.cpp

-1
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,6 @@ cpp_idt &cpp_scopest::put_into_scope(
4848
{
4949
cpp_save_scopet saved_scope(*this);
5050
go_to(scope);
51-
go_to_global_scope();
5251

5352
cpp_idt &id=current_scope().insert(symbol.base_name);
5453
id.identifier=symbol.name;

src/cpp/cpp_typecheck.h

+4
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,10 @@ class cpp_typecheckt:public c_typecheck_baset
230230
std::string template_suffix(
231231
const cpp_template_args_tct &template_args);
232232

233+
cpp_scopet &sub_scope_for_instantiation(
234+
cpp_scopet &template_scope,
235+
const std::string &suffix);
236+
233237
void
234238
convert_parameters(const irep_idt &current_mode, code_typet &function_type);
235239

0 commit comments

Comments
 (0)