Skip to content

Commit cbd5d9f

Browse files
committed
Linking: replace conflicting pointer types when one declaration is extern
1 parent 401a46c commit cbd5d9f

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
@@ -214,6 +214,23 @@ exprt goto_symext::address_arithmetic(
214214
else
215215
result=address_of_exprt(result);
216216
}
217+
else if(expr.id() == ID_typecast)
218+
{
219+
const typecast_exprt &tc_expr = to_typecast_expr(expr);
220+
221+
result = address_arithmetic(tc_expr.op(), state, guard, keep_array);
222+
223+
// treat &array as &array[0]
224+
const typet &expr_type = ns.follow(expr.type());
225+
typet dest_type_subtype;
226+
227+
if(expr_type.id() == ID_array && !keep_array)
228+
dest_type_subtype = expr_type.subtype();
229+
else
230+
dest_type_subtype = expr_type;
231+
232+
result = typecast_exprt(result, pointer_type(dest_type_subtype));
233+
}
217234
else
218235
throw "goto_symext::address_arithmetic does not handle "+expr.id_string();
219236

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,
@@ -873,6 +888,11 @@ bool linkingt::adjust_object_type_rec(
873888
"conflicting pointer types for variable");
874889
#endif
875890

891+
if(info.old_symbol.is_extern && !info.new_symbol.is_extern)
892+
{
893+
info.set_to_new = true; // store new type
894+
}
895+
876896
return false;
877897
}
878898
else if(t1.id()==ID_array &&
@@ -959,10 +979,10 @@ void linkingt::duplicate_object_symbol(
959979
symbolt &new_symbol)
960980
{
961981
// both are variables
982+
bool set_to_new = false;
962983

963984
if(!base_type_eq(old_symbol.type, new_symbol.type, ns))
964985
{
965-
bool set_to_new=false;
966986
bool failed=
967987
adjust_object_type(old_symbol, new_symbol, set_to_new);
968988

@@ -1042,6 +1062,14 @@ void linkingt::duplicate_object_symbol(
10421062
}
10431063
}
10441064
}
1065+
else if(
1066+
set_to_new && !old_symbol.value.is_nil() &&
1067+
!old_symbol.value.get_bool(ID_C_zero_initializer))
1068+
{
1069+
// the type has been updated, now make sure that the initialising assignment
1070+
// will have matching types
1071+
old_symbol.value.make_typecast(old_symbol.type);
1072+
}
10451073
}
10461074

10471075
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)