Skip to content

Commit d590932

Browse files
committed
Improving linker warning diagnostics
We previously just reported pointer type conflicts without elaborating what the exact difference was. To produce type-consistent goto programs, we chose to use the type that the definition had, but lacked any test that doing so would actually result in a program that can be analysed successfully. This commit fixes bugs in the code producing diagnostics, enables diagnostics for the case of pointer type conflicts, and adds a test to demonstrate that we successfully analyse programs after type conflict resolution. Despite this, however, inconsistencies in the goto program remain: the call types still need fixing up. Fixes: #198
1 parent 9720295 commit d590932

File tree

7 files changed

+150
-43
lines changed

7 files changed

+150
-43
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
CORE
2+
typesmain.c
3+
types1.c types2.c types3.c --verbosity 2
4+
reason for conflict at \*#this.u: number of members is different \(3/0\)
5+
reason for conflict at \*#this.u: number of members is different \(0/3\)
6+
struct U \(incomplete\)
7+
warning: pointer parameter types differ between declaration and definition "bar"
8+
warning: pointer parameter types differ between declaration and definition "foo"
9+
^EXIT=0$
10+
^SIGNAL=0$
11+
--
12+
^warning: ignoring
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
struct S
2+
{
3+
int s;
4+
} s_object;
5+
6+
int foobar()
7+
{
8+
return s_object.s;
9+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
struct S
2+
{
3+
struct T *t;
4+
struct U *u;
5+
};
6+
7+
struct U
8+
{
9+
struct S *s;
10+
int j;
11+
};
12+
13+
int bar(struct S *s)
14+
{
15+
return s->u->j;
16+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
struct T
2+
{
3+
int i;
4+
};
5+
6+
struct S
7+
{
8+
struct T *t;
9+
struct U *u;
10+
};
11+
12+
int bar(struct S *);
13+
14+
int foo(struct S *s)
15+
{
16+
return bar(s) + s->t->i;
17+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#include <assert.h>
2+
3+
struct T
4+
{
5+
int i;
6+
};
7+
8+
struct U
9+
{
10+
struct S *s;
11+
int j;
12+
};
13+
14+
struct S
15+
{
16+
struct T *t;
17+
struct U *u;
18+
};
19+
20+
int foo(struct S *s);
21+
22+
int main()
23+
{
24+
struct T t = {10};
25+
struct U u = {0, 32};
26+
struct S s = {&t, &u};
27+
int res = foo(&s);
28+
assert(res == 42);
29+
}

src/linking/linking.cpp

+63-42
Original file line numberDiff line numberDiff line change
@@ -126,25 +126,30 @@ std::string linkingt::type_to_string_verbose(
126126
return type_to_string(symbol.name, type);
127127
}
128128

129-
void linkingt::detailed_conflict_report_rec(
129+
bool linkingt::detailed_conflict_report_rec(
130130
const symbolt &old_symbol,
131131
const symbolt &new_symbol,
132132
const typet &type1,
133133
const typet &type2,
134134
unsigned depth,
135135
exprt &conflict_path)
136136
{
137-
#ifdef DEBUG
137+
bool conclusive = false;
138+
139+
#ifdef DEBUG
138140
debug() << "<BEGIN DEPTH " << depth << ">" << eom;
139-
#endif
141+
#endif
140142

141143
std::string msg;
142144

143145
const typet &t1=follow_tags_symbols(ns, type1);
144146
const typet &t2=follow_tags_symbols(ns, type2);
145147

146148
if(t1.id()!=t2.id())
149+
{
147150
msg="type classes differ";
151+
conclusive = true;
152+
}
148153
else if(t1.id()==ID_pointer ||
149154
t1.id()==ID_array)
150155
{
@@ -155,7 +160,7 @@ void linkingt::detailed_conflict_report_rec(
155160
if(conflict_path.type().id() == ID_pointer)
156161
conflict_path = dereference_exprt(conflict_path);
157162

158-
detailed_conflict_report_rec(
163+
conclusive = detailed_conflict_report_rec(
159164
old_symbol,
160165
new_symbol,
161166
to_type_with_subtype(t1).subtype(),
@@ -184,6 +189,7 @@ void linkingt::detailed_conflict_report_rec(
184189
msg="number of members is different (";
185190
msg+=std::to_string(components1.size())+'/';
186191
msg+=std::to_string(components2.size())+')';
192+
conclusive = true;
187193
}
188194
else
189195
{
@@ -197,7 +203,7 @@ void linkingt::detailed_conflict_report_rec(
197203
msg="names of member "+std::to_string(i)+" differ (";
198204
msg+=id2string(components1[i].get_name())+'/';
199205
msg+=id2string(components2[i].get_name())+')';
200-
break;
206+
conclusive = true;
201207
}
202208
else if(subtype1 != subtype2)
203209
{
@@ -210,6 +216,7 @@ void linkingt::detailed_conflict_report_rec(
210216
e.id()==ID_index)
211217
{
212218
parent_types.insert(e.type());
219+
parent_types.insert(follow_tags_symbols(ns, e.type()));
213220
if(e.id() == ID_dereference)
214221
e = to_dereference_expr(e).pointer();
215222
else if(e.id() == ID_member)
@@ -220,44 +227,32 @@ void linkingt::detailed_conflict_report_rec(
220227
UNREACHABLE;
221228
}
222229

223-
conflict_path=conflict_path_before;
224-
conflict_path.type()=t1;
225-
conflict_path=
226-
member_exprt(conflict_path, components1[i]);
227-
228-
if(depth>0 &&
229-
parent_types.find(t1)==parent_types.end())
230-
detailed_conflict_report_rec(
231-
old_symbol,
232-
new_symbol,
233-
subtype1,
234-
subtype2,
235-
depth-1,
236-
conflict_path);
237-
else
230+
if(parent_types.find(subtype1) == parent_types.end())
238231
{
239-
msg="type of member "+
240-
id2string(components1[i].get_name())+
241-
" differs";
242-
if(depth>0)
232+
conflict_path = conflict_path_before;
233+
conflict_path.type() = t1;
234+
conflict_path = member_exprt(conflict_path, components1[i]);
235+
236+
if(depth > 0)
243237
{
244-
std::string msg_bak;
245-
msg_bak.swap(msg);
246-
symbol_exprt c = symbol_exprt::typeless(ID_C_this);
247-
detailed_conflict_report_rec(
238+
conclusive = detailed_conflict_report_rec(
248239
old_symbol,
249240
new_symbol,
250241
subtype1,
251242
subtype2,
252-
depth-1,
253-
c);
254-
msg.swap(msg_bak);
243+
depth - 1,
244+
conflict_path);
255245
}
256246
}
257-
258-
if(parent_types.find(t1)==parent_types.end())
259-
break;
247+
else
248+
{
249+
msg = "type of member " + id2string(components1[i].get_name()) +
250+
" differs (recursive)";
251+
}
260252
}
253+
254+
if(conclusive)
255+
break;
261256
}
262257
}
263258
}
@@ -280,12 +275,14 @@ void linkingt::detailed_conflict_report_rec(
280275
msg +=
281276
type_to_string(new_symbol.name, to_c_enum_type(t2).underlying_type()) +
282277
')';
278+
conclusive = true;
283279
}
284280
else if(members1.size()!=members2.size())
285281
{
286282
msg="number of enum members is different (";
287283
msg+=std::to_string(members1.size())+'/';
288284
msg+=std::to_string(members2.size())+')';
285+
conclusive = true;
289286
}
290287
else
291288
{
@@ -296,15 +293,18 @@ void linkingt::detailed_conflict_report_rec(
296293
msg="names of member "+std::to_string(i)+" differ (";
297294
msg+=id2string(members1[i].get_base_name())+'/';
298295
msg+=id2string(members2[i].get_base_name())+')';
299-
break;
296+
conclusive = true;
300297
}
301298
else if(members1[i].get_value()!=members2[i].get_value())
302299
{
303300
msg="values of member "+std::to_string(i)+" differ (";
304301
msg+=id2string(members1[i].get_value())+'/';
305302
msg+=id2string(members2[i].get_value())+')';
306-
break;
303+
conclusive = true;
307304
}
305+
306+
if(conclusive)
307+
break;
308308
}
309309
}
310310

@@ -328,21 +328,25 @@ void linkingt::detailed_conflict_report_rec(
328328
msg="parameter counts differ (";
329329
msg+=std::to_string(parameters1.size())+'/';
330330
msg+=std::to_string(parameters2.size())+')';
331+
conclusive = true;
331332
}
332333
else if(return_type1 != return_type2)
333334
{
335+
conflict_path.type() = array_typet{void_type(), nil_exprt{}};
334336
conflict_path=
335337
index_exprt(conflict_path,
336338
constant_exprt(std::to_string(-1), integer_typet()));
337339

338340
if(depth>0)
339-
detailed_conflict_report_rec(
341+
{
342+
conclusive = detailed_conflict_report_rec(
340343
old_symbol,
341344
new_symbol,
342345
return_type1,
343346
return_type2,
344-
depth-1,
347+
depth - 1,
345348
conflict_path);
349+
}
346350
else
347351
msg="return types differ";
348352
}
@@ -355,30 +359,37 @@ void linkingt::detailed_conflict_report_rec(
355359

356360
if(subtype1 != subtype2)
357361
{
362+
conflict_path.type() = array_typet{void_type(), nil_exprt{}};
358363
conflict_path=
359364
index_exprt(conflict_path,
360365
constant_exprt(std::to_string(i), integer_typet()));
361366

362367
if(depth>0)
363-
detailed_conflict_report_rec(
368+
{
369+
conclusive = detailed_conflict_report_rec(
364370
old_symbol,
365371
new_symbol,
366372
subtype1,
367373
subtype2,
368-
depth-1,
374+
depth - 1,
369375
conflict_path);
376+
}
370377
else
371378
msg="parameter types differ";
379+
}
372380

381+
if(conclusive)
373382
break;
374-
}
375383
}
376384
}
377385
}
378386
else
387+
{
379388
msg="conflict on POD";
389+
conclusive = true;
390+
}
380391

381-
if(!msg.empty())
392+
if(conclusive && !msg.empty())
382393
{
383394
error() << '\n';
384395
error() << "reason for conflict at "
@@ -392,6 +403,8 @@ void linkingt::detailed_conflict_report_rec(
392403
#ifdef DEBUG
393404
debug() << "<END DEPTH " << depth << ">" << eom;
394405
#endif
406+
407+
return conclusive;
395408
}
396409

397410
void linkingt::link_error(
@@ -685,8 +698,16 @@ void linkingt::duplicate_code_symbol(
685698
old_symbol.value.is_nil()!=new_symbol.value.is_nil())
686699
{
687700
if(warn_msg.empty())
701+
{
688702
warn_msg="pointer parameter types differ between "
689703
"declaration and definition";
704+
detailed_conflict_report(
705+
old_symbol,
706+
new_symbol,
707+
conflicts.front().first,
708+
conflicts.front().second);
709+
}
710+
690711
replace=new_symbol.value.is_not_nil();
691712
}
692713
// transparent union with (or entirely without) implementation is

src/linking/linking_class.h

+4-1
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,10 @@ class linkingt:public typecheckt
131131
return type_to_string_verbose(symbol, symbol.type);
132132
}
133133

134-
void detailed_conflict_report_rec(
134+
/// Returns true iff the conflict report on a particular branch of the tree of
135+
/// types was a definitive result, and not contingent on conflicts within a
136+
/// tag type.
137+
bool detailed_conflict_report_rec(
135138
const symbolt &old_symbol,
136139
const symbolt &new_symbol,
137140
const typet &type1,

0 commit comments

Comments
 (0)