Skip to content

Commit 760202c

Browse files
committed
Linking: replace conflicting pointer types when one declaration is extern
1 parent e6a9127 commit 760202c

File tree

10 files changed

+75
-9
lines changed

10 files changed

+75
-9
lines changed

regression/cbmc/Linking7/a.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#include <stdlib.h>
2+
3+
void foo();
4+
5+
int main()
6+
{
7+
extern void* p;
8+
p=malloc(sizeof(int));
9+
foo();
10+
return 0;
11+
}

regression/cbmc/Linking7/b.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
int *p;
2+
3+
void foo()
4+
{
5+
*p=42;
6+
}

regression/cbmc/Linking7/test.desc

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CORE
2+
b.c
3+
a.c --pointer-check
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^VERIFICATION SUCCESSFUL$
7+
--
8+
^warning: ignoring

src/ansi-c/c_typecheck_base.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,13 @@ void c_typecheck_baset::typecheck_symbol(symbolt &symbol)
6767
// and have static lifetime
6868
new_name=root_name;
6969
symbol.is_static_lifetime=true;
70+
71+
if(symbol.value.is_not_nil())
72+
{
73+
error().source_location=symbol.value.find_source_location();
74+
error() << "extern symbols cannot have an initializer" << eom;
75+
throw 0;
76+
}
7077
}
7178
else if(!is_function && symbol.value.id()==ID_code)
7279
{

src/goto-instrument/dump_c.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -962,7 +962,7 @@ void dump_ct::cleanup_harness(code_blockt &b)
962962
}
963963

964964
b.swap(decls);
965-
replace(b);
965+
replace.replace(b, true, true);
966966
}
967967

968968
void dump_ct::convert_function_declaration(

src/goto-instrument/model_argc_argv.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ bool model_argc_argv(
128128
replace_symbolt replace;
129129
replace.insert("ARGC", ns.lookup("argc'").symbol_expr());
130130
replace.insert("ARGV", ns.lookup("argv'").symbol_expr());
131-
replace(value);
131+
replace.replace(value, true, true);
132132
}
133133
else if(
134134
has_prefix(

src/goto-symex/symex_dereference.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,24 @@ exprt goto_symext::address_arithmetic(
218218
else
219219
result=address_of_exprt(result);
220220
}
221+
else if(expr.id()==ID_typecast)
222+
{
223+
typecast_exprt tc_expr=to_typecast_expr(expr);
224+
225+
result=
226+
address_arithmetic(tc_expr.op(), state, guard, keep_array);
227+
228+
// treat &array as &array[0]
229+
const typet &expr_type=ns.follow(expr.type());
230+
typet dest_type_subtype;
231+
232+
if(expr_type.id()==ID_array && !keep_array)
233+
dest_type_subtype=expr_type.subtype();
234+
else
235+
dest_type_subtype=expr_type;
236+
237+
result=typecast_exprt(result, pointer_type(dest_type_subtype));
238+
}
221239
else
222240
throw "goto_symext::address_arithmetic does not handle "+expr.id_string();
223241

src/linking/linking.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -850,6 +850,9 @@ bool linkingt::adjust_object_type_rec(
850850
"conflicting pointer types for variable");
851851
#endif
852852

853+
if(info.old_symbol.is_extern && !info.new_symbol.is_extern)
854+
info.set_to_new=true; // store new type
855+
853856
return false;
854857
}
855858
else if(t1.id()==ID_array &&

src/util/replace_symbol.cpp

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ void replace_symbolt::insert(
2929

3030
bool replace_symbolt::replace(
3131
exprt &dest,
32-
const bool replace_with_const) const
32+
const bool replace_with_const,
33+
const bool ignore_type_change) const
3334
{
3435
bool result=true; // unchanged
3536

@@ -48,14 +49,16 @@ bool replace_symbolt::replace(
4849
{
4950
member_exprt &me=to_member_expr(dest);
5051

51-
if(!replace(me.struct_op(), replace_with_const)) // Could give non l-value.
52+
// Could yield non l-value.
53+
if(!replace(me.struct_op(), replace_with_const, ignore_type_change))
5254
result=false;
5355
}
5456
else if(dest.id()==ID_index)
5557
{
5658
index_exprt &ie=to_index_expr(dest);
5759

58-
if(!replace(ie.array(), replace_with_const)) // Could give non l-value.
60+
// Could yield non l-value.
61+
if(!replace(ie.array(), replace_with_const, ignore_type_change))
5962
result=false;
6063

6164
if(!replace(ie.index()))
@@ -65,7 +68,7 @@ bool replace_symbolt::replace(
6568
{
6669
address_of_exprt &aoe=to_address_of_expr(dest);
6770

68-
if(!replace(aoe.object(), false))
71+
if(!replace(aoe.object(), false, ignore_type_change))
6972
result=false;
7073
}
7174
else if(dest.id()==ID_symbol)
@@ -82,15 +85,22 @@ bool replace_symbolt::replace(
8285
if(!replace_with_const && e.is_constant()) // Would give non l-value.
8386
return true;
8487

85-
dest=e;
88+
if(ignore_type_change || dest.type()==e.type())
89+
dest=e;
90+
else
91+
{
92+
typet type=dest.type();
93+
dest=e;
94+
dest.make_typecast(type);
95+
}
8696

8797
return false;
8898
}
8999
}
90100
else
91101
{
92102
Forall_operands(it, dest)
93-
if(!replace(*it))
103+
if(!replace(*it, true, ignore_type_change))
94104
result=false;
95105
}
96106

src/util/replace_symbol.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,10 +51,13 @@ class replace_symbolt
5151
/// \param dest The expression in which to do the replacement
5252
/// \param replace_with_const If false then it disables the rewrites that
5353
/// could result in something that is not an l-value.
54+
/// \param ignore_type_change If true, do not introduce type casts when the
55+
/// replacement would cause expression types to change.
5456
///
5557
virtual bool replace(
5658
exprt &dest,
57-
const bool replace_with_const=true) const;
59+
const bool replace_with_const=true,
60+
const bool ignore_type_change=false) const;
5861

5962
virtual bool replace(typet &dest) const;
6063

0 commit comments

Comments
 (0)