Skip to content

Commit 2f60e13

Browse files
committed
Linking: replace conflicting pointer types when one declaration is extern
1 parent 32afaaa commit 2f60e13

File tree

7 files changed

+87
-2
lines changed

7 files changed

+87
-2
lines changed

regression/cbmc/Linking8/a.c

+11
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/Linking8/b.c

+6
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/Linking8/test.desc

+8
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

+9
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,15 @@ 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+
// According to the C standard this should be an error, but at least some
74+
// versions of Visual Studio insist to use this in their C library, and
75+
// GCC just warns as well.
76+
warning().source_location = symbol.value.find_source_location();
77+
warning() << "`extern' symbol should not have an initializer" << eom;
78+
}
7079
}
7180
else if(!is_function && symbol.value.id()==ID_code)
7281
{

src/goto-symex/symex_dereference.cpp

+17
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,23 @@ exprt goto_symext::address_arithmetic(
216216
else
217217
result=address_of_exprt(result);
218218
}
219+
else if(expr.id() == ID_typecast)
220+
{
221+
const typecast_exprt &tc_expr = to_typecast_expr(expr);
222+
223+
result = address_arithmetic(tc_expr.op(), state, guard, keep_array);
224+
225+
// treat &array as &array[0]
226+
const typet &expr_type = ns.follow(expr.type());
227+
typet dest_type_subtype;
228+
229+
if(expr_type.id() == ID_array && !keep_array)
230+
dest_type_subtype = expr_type.subtype();
231+
else
232+
dest_type_subtype = expr_type;
233+
234+
result = typecast_exprt(result, pointer_type(dest_type_subtype));
235+
}
219236
else
220237
throw unsupported_operation_exceptiont(
221238
"goto_symext::address_arithmetic does not handle " + expr.id_string());

src/linking/linking.cpp

+29-1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,21 @@ Author: Daniel Kroening, [email protected]
2424

2525
#include "linking_class.h"
2626

27+
bool casting_replace_symbolt::replace_symbol_expr(symbol_exprt &s) const
28+
{
29+
expr_mapt::const_iterator it = expr_map.find(s.get_identifier());
30+
31+
if(it == expr_map.end())
32+
return true;
33+
34+
const exprt &e = it->second;
35+
36+
typet type = s.type();
37+
static_cast<exprt &>(s) = typecast_exprt::conditional_cast(e, type);
38+
39+
return false;
40+
}
41+
2742
std::string linkingt::expr_to_string(
2843
const namespacet &ns,
2944
const irep_idt &identifier,
@@ -864,6 +879,11 @@ bool linkingt::adjust_object_type_rec(
864879
"conflicting pointer types for variable");
865880
#endif
866881

882+
if(info.old_symbol.is_extern && !info.new_symbol.is_extern)
883+
{
884+
info.set_to_new = true; // store new type
885+
}
886+
867887
return false;
868888
}
869889
else if(t1.id()==ID_array &&
@@ -950,10 +970,10 @@ void linkingt::duplicate_object_symbol(
950970
symbolt &new_symbol)
951971
{
952972
// both are variables
973+
bool set_to_new = false;
953974

954975
if(!base_type_eq(old_symbol.type, new_symbol.type, ns))
955976
{
956-
bool set_to_new=false;
957977
bool failed=
958978
adjust_object_type(old_symbol, new_symbol, set_to_new);
959979

@@ -1033,6 +1053,14 @@ void linkingt::duplicate_object_symbol(
10331053
}
10341054
}
10351055
}
1056+
else if(
1057+
set_to_new && !old_symbol.value.is_nil() &&
1058+
!old_symbol.value.get_bool(ID_C_zero_initializer))
1059+
{
1060+
// the type has been updated, now make sure that the initialising assignment
1061+
// will have matching types
1062+
old_symbol.value.make_typecast(old_symbol.type);
1063+
}
10361064
}
10371065

10381066
void linkingt::duplicate_non_type_symbol(

src/linking/linking_class.h

+7-1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,12 @@ Author: Daniel Kroening, [email protected]
1818
#include <util/typecheck.h>
1919
#include <util/std_expr.h>
2020

21+
class casting_replace_symbolt : public replace_symbolt
22+
{
23+
private:
24+
bool replace_symbol_expr(symbol_exprt &dest) const override;
25+
};
26+
2127
class linkingt:public typecheckt
2228
{
2329
public:
@@ -35,7 +41,7 @@ class linkingt:public typecheckt
3541
virtual void typecheck();
3642

3743
rename_symbolt rename_symbol;
38-
unchecked_replace_symbolt object_type_updates;
44+
casting_replace_symbolt object_type_updates;
3945

4046
protected:
4147
bool needs_renaming_type(

0 commit comments

Comments
 (0)