Skip to content

Commit 3b94bf0

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 47bdb15 commit 3b94bf0

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
@@ -57,16 +57,46 @@ static bool link_functions(
5757
goto_functionst &dest_functions,
5858
const symbol_tablet &src_symbol_table,
5959
goto_functionst &src_functions,
60-
const rename_symbolt &rename_symbol,
60+
rename_symbolt &rename_symbol,
6161
const std::unordered_set<irep_idt> &weak_symbols,
6262
const replace_symbolt &object_type_updates)
6363
{
6464
namespacet ns(dest_symbol_table);
6565
namespacet src_ns(src_symbol_table);
6666

67+
// remove any unnecessary duplicates
68+
std::unordered_set<irep_idt> duplicates;
69+
for(const auto &f_pair : src_functions.function_map)
70+
{
71+
rename_symbolt::expr_mapt::iterator rename_it =
72+
rename_symbol.expr_map.find(f_pair.first);
73+
if(rename_it == rename_symbol.expr_map.end())
74+
continue;
75+
76+
std::string new_name = id2string(rename_it->second);
77+
std::string::size_type suffix_pos = new_name.find("$link");
78+
if(suffix_pos == std::string::npos)
79+
continue;
80+
81+
irep_idt original_name = new_name.substr(0, suffix_pos);
82+
goto_functionst::function_mapt::iterator existing_func =
83+
dest_functions.function_map.find(original_name);
84+
if(existing_func == dest_functions.function_map.end())
85+
continue;
86+
87+
if(f_pair.second.body.equals(existing_func->second.body))
88+
{
89+
duplicates.insert(f_pair.first);
90+
rename_symbol.expr_map.erase(rename_it);
91+
}
92+
}
93+
6794
// merge functions
6895
Forall_goto_functions(src_it, src_functions)
6996
{
97+
if(duplicates.find(src_it->first) != duplicates.end())
98+
continue;
99+
70100
// the function might have been renamed
71101
rename_symbolt::expr_mapt::const_iterator e_it=
72102
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
@@ -438,11 +438,9 @@ bool linkingt::needs_renaming_non_type(
438438
// We first take care of file-local non-type symbols.
439439
// These are static functions, or static variables
440440
// inside static function bodies.
441-
if(new_symbol.is_file_local ||
442-
old_symbol.is_file_local)
443-
return true;
444-
445-
return false;
441+
return (new_symbol.is_file_local || old_symbol.is_file_local) &&
442+
(new_symbol.type.id() != ID_code || new_symbol.is_compiled() ||
443+
new_symbol.value != old_symbol.value);
446444
}
447445

448446
void linkingt::duplicate_code_symbol(
@@ -764,18 +762,18 @@ void linkingt::duplicate_code_symbol(
764762
old_symbol.location=new_symbol.location;
765763
old_symbol.is_macro=new_symbol.is_macro;
766764
}
767-
else if(to_code_type(old_symbol.type).get_inlined())
768-
{
769-
// ok, silently ignore
770-
}
771765
else if(base_type_eq(old_symbol.type, new_symbol.type, ns))
772766
{
773-
// keep the one in old_symbol -- libraries come last!
774-
warning().source_location=new_symbol.location;
767+
if(!new_symbol.is_file_local || !old_symbol.is_file_local)
768+
{
769+
// keep the one in old_symbol -- libraries come last!
770+
warning().source_location = new_symbol.location;
775771

776-
warning() << "function `" << old_symbol.name << "' in module `"
777-
<< new_symbol.module << "' is shadowed by a definition in module `"
778-
<< old_symbol.module << "'" << eom;
772+
warning() << "function `" << old_symbol.name << "' in module `"
773+
<< new_symbol.module
774+
<< "' is shadowed by a definition in module `"
775+
<< old_symbol.module << "'" << eom;
776+
}
779777
}
780778
else
781779
link_error(

0 commit comments

Comments
 (0)