Skip to content

Commit fd9896f

Browse files
committed
Linking can safely clean up duplicates of static inline functions
This will avoid some occurrences of function$linkN names that are confusing to users, in particular when specifying loop unwinding limits.
1 parent 3705a60 commit fd9896f

File tree

9 files changed

+99
-17
lines changed

9 files changed

+99
-17
lines changed

regression/ansi-c/linking2/foo.h

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

regression/ansi-c/linking2/main.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#include "foo.h"
2+
3+
int main(int argc, char *argv[])
4+
{
5+
foo(argc);
6+
bar(argc);
7+
return 0;
8+
}

regression/ansi-c/linking2/other.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#ifndef TEST2
2+
#include "foo.h"
3+
#else
4+
inline void foo(int x)
5+
{
6+
x = 0;
7+
}
8+
#endif
9+
10+
void bar(int y)
11+
{
12+
foo(y);
13+
y = 2;
14+
}

regression/ansi-c/linking2/test1.desc

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
CORE
2+
main.c
3+
other.c --verbosity 10
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^Functions: 5; 5 have a body.$
7+
--
8+
^warning: ignoring
9+
^CONVERSION ERROR$
10+
--
11+
The implementation of a function named "foo" (static inline void foo(int x)) is
12+
the same in both translation units, thus linking can safely discard one of the
13+
copies and does not need to do any renaming.

regression/ansi-c/linking2/test2.desc

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
CORE
2+
main.c
3+
other.c --verbosity 10 -DTEST2
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^Functions: 6; 6 have a body.$
7+
--
8+
^warning: ignoring
9+
^CONVERSION ERROR$
10+
--
11+
The implementation of a function named "foo" (void foo(int x)) differs between
12+
translation units; as at least one of them is static this is acceptable at link
13+
time and can be resolved by renaming one of them.

regression/ansi-c/static2/main2.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
static int foo(int a)
22
{
3-
return a+1;
3+
return a + 2;
44
}

regression/ansi-c/static3/main2.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
static int foo(int a)
22
{
3-
return a+1;
3+
return a + 2;
44
}

src/goto-programs/link_goto_model.cpp

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,16 +46,46 @@ static bool link_functions(
4646
goto_functionst &dest_functions,
4747
const symbol_tablet &src_symbol_table,
4848
goto_functionst &src_functions,
49-
const rename_symbolt &rename_symbol,
49+
rename_symbolt &rename_symbol,
5050
const std::unordered_set<irep_idt> &weak_symbols,
5151
const replace_symbolt &object_type_updates)
5252
{
5353
namespacet ns(dest_symbol_table);
5454
namespacet src_ns(src_symbol_table);
5555

56+
// remove any unnecessary duplicates
57+
std::unordered_set<irep_idt> duplicates;
58+
for(const auto &f_pair : src_functions.function_map)
59+
{
60+
rename_symbolt::expr_mapt::iterator rename_it =
61+
rename_symbol.expr_map.find(f_pair.first);
62+
if(rename_it == rename_symbol.expr_map.end())
63+
continue;
64+
65+
std::string new_name = id2string(rename_it->second);
66+
std::string::size_type suffix_pos = new_name.find("$link");
67+
if(suffix_pos == std::string::npos)
68+
continue;
69+
70+
irep_idt original_name = new_name.substr(0, suffix_pos);
71+
goto_functionst::function_mapt::iterator existing_func =
72+
dest_functions.function_map.find(original_name);
73+
if(existing_func == dest_functions.function_map.end())
74+
continue;
75+
76+
if(f_pair.second.body.equals(existing_func->second.body))
77+
{
78+
duplicates.insert(f_pair.first);
79+
rename_symbol.expr_map.erase(rename_it);
80+
}
81+
}
82+
5683
// merge functions
5784
Forall_goto_functions(src_it, src_functions)
5885
{
86+
if(duplicates.find(src_it->first) != duplicates.end())
87+
continue;
88+
5989
// the function might have been renamed
6090
rename_symbolt::expr_mapt::const_iterator e_it=
6191
rename_symbol.expr_map.find(src_it->first);

src/linking/linking.cpp

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -425,11 +425,9 @@ bool linkingt::needs_renaming_non_type(
425425
// We first take care of file-local non-type symbols.
426426
// These are static functions, or static variables
427427
// inside static function bodies.
428-
if(new_symbol.is_file_local ||
429-
old_symbol.is_file_local)
430-
return true;
431-
432-
return false;
428+
return (new_symbol.is_file_local || old_symbol.is_file_local) &&
429+
(new_symbol.type.id() != ID_code || new_symbol.is_compiled() ||
430+
new_symbol.value != old_symbol.value);
433431
}
434432

435433
void linkingt::duplicate_code_symbol(
@@ -752,18 +750,18 @@ void linkingt::duplicate_code_symbol(
752750
old_symbol.location=new_symbol.location;
753751
old_symbol.is_macro=new_symbol.is_macro;
754752
}
755-
else if(to_code_type(old_symbol.type).get_inlined())
756-
{
757-
// ok, silently ignore
758-
}
759753
else if(base_type_eq(old_symbol.type, new_symbol.type, ns))
760754
{
761-
// keep the one in old_symbol -- libraries come last!
762-
warning().source_location=new_symbol.location;
755+
if(!new_symbol.is_file_local || !old_symbol.is_file_local)
756+
{
757+
// keep the one in old_symbol -- libraries come last!
758+
warning().source_location = new_symbol.location;
763759

764-
warning() << "function `" << old_symbol.name << "' in module `"
765-
<< new_symbol.module << "' is shadowed by a definition in module `"
766-
<< old_symbol.module << "'" << eom;
760+
warning() << "function `" << old_symbol.name << "' in module `"
761+
<< new_symbol.module
762+
<< "' is shadowed by a definition in module `"
763+
<< old_symbol.module << "'" << eom;
764+
}
767765
}
768766
else
769767
link_error(

0 commit comments

Comments
 (0)