Skip to content

Commit d34b1a9

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 0a09814 commit d34b1a9

File tree

9 files changed

+99
-18
lines changed

9 files changed

+99
-18
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
@@ -48,15 +48,45 @@ static bool link_functions(
4848
goto_functionst &dest_functions,
4949
const symbol_tablet &src_symbol_table,
5050
goto_functionst &src_functions,
51-
const rename_symbolt &rename_symbol,
51+
rename_symbolt &rename_symbol,
5252
const std::unordered_set<irep_idt> &weak_symbols)
5353
{
5454
namespacet ns(dest_symbol_table);
5555
namespacet src_ns(src_symbol_table);
5656

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

src/linking/linking.cpp

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -537,11 +537,9 @@ bool linkingt::needs_renaming_non_type(
537537
// We first take care of file-local non-type symbols.
538538
// These are static functions, or static variables
539539
// inside static function bodies.
540-
if(new_symbol.is_file_local ||
541-
old_symbol.is_file_local)
542-
return true;
543-
544-
return false;
540+
return (new_symbol.is_file_local || old_symbol.is_file_local) &&
541+
(new_symbol.type.id() != ID_code || new_symbol.is_compiled() ||
542+
new_symbol.value != old_symbol.value);
545543
}
546544

547545
void linkingt::duplicate_code_symbol(
@@ -848,19 +846,18 @@ void linkingt::duplicate_code_symbol(
848846
object_type_updates.insert(
849847
old_symbol.symbol_expr(), old_symbol.symbol_expr());
850848
}
851-
else if(to_code_type(old_symbol.type).get_inlined())
852-
{
853-
// ok, silently ignore
854-
}
855849
else if(old_symbol.type == new_symbol.type)
856850
{
857-
// keep the one in old_symbol -- libraries come last!
858-
debug().source_location = new_symbol.location;
851+
if(!new_symbol.is_file_local || !old_symbol.is_file_local)
852+
{
853+
// keep the one in old_symbol -- libraries come last!
854+
debug().source_location = new_symbol.location;
859855

860-
debug() << "function '" << old_symbol.name << "' in module '"
861-
<< new_symbol.module
862-
<< "' is shadowed by a definition in module '"
863-
<< old_symbol.module << "'" << eom;
856+
debug() << "function '" << old_symbol.name << "' in module '"
857+
<< new_symbol.module
858+
<< "' is shadowed by a definition in module '"
859+
<< old_symbol.module << "'" << eom;
860+
}
864861
}
865862
else
866863
link_error(

0 commit comments

Comments
 (0)