Skip to content

Commit 77bc8f1

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 247380f commit 77bc8f1

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
@@ -53,16 +53,46 @@ static bool link_functions(
5353
goto_functionst &dest_functions,
5454
const symbol_tablet &src_symbol_table,
5555
goto_functionst &src_functions,
56-
const rename_symbolt &rename_symbol,
56+
rename_symbolt &rename_symbol,
5757
const std::unordered_set<irep_idt> &weak_symbols,
5858
const replace_symbolt &object_type_updates)
5959
{
6060
namespacet ns(dest_symbol_table);
6161
namespacet src_ns(src_symbol_table);
6262

63+
// remove any unnecessary duplicates
64+
std::unordered_set<irep_idt> duplicates;
65+
for(const auto &f_pair : src_functions.function_map)
66+
{
67+
rename_symbolt::expr_mapt::iterator rename_it =
68+
rename_symbol.expr_map.find(f_pair.first);
69+
if(rename_it == rename_symbol.expr_map.end())
70+
continue;
71+
72+
std::string new_name = id2string(rename_it->second);
73+
std::string::size_type suffix_pos = new_name.find("$link");
74+
if(suffix_pos == std::string::npos)
75+
continue;
76+
77+
irep_idt original_name = new_name.substr(0, suffix_pos);
78+
goto_functionst::function_mapt::iterator existing_func =
79+
dest_functions.function_map.find(original_name);
80+
if(existing_func == dest_functions.function_map.end())
81+
continue;
82+
83+
if(f_pair.second.body.equals(existing_func->second.body))
84+
{
85+
duplicates.insert(f_pair.first);
86+
rename_symbol.expr_map.erase(rename_it);
87+
}
88+
}
89+
6390
// merge functions
6491
for(auto &gf_entry : src_functions.function_map)
6592
{
93+
if(duplicates.find(gf_entry.first) != duplicates.end())
94+
continue;
95+
6696
// the function might have been renamed
6797
rename_symbolt::expr_mapt::const_iterator e_it =
6898
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
@@ -447,11 +447,9 @@ bool linkingt::needs_renaming_non_type(
447447
// We first take care of file-local non-type symbols.
448448
// These are static functions, or static variables
449449
// inside static function bodies.
450-
if(new_symbol.is_file_local ||
451-
old_symbol.is_file_local)
452-
return true;
453-
454-
return false;
450+
return (new_symbol.is_file_local || old_symbol.is_file_local) &&
451+
(new_symbol.type.id() != ID_code || new_symbol.is_compiled() ||
452+
new_symbol.value != old_symbol.value);
455453
}
456454

457455
void linkingt::duplicate_code_symbol(
@@ -773,19 +771,18 @@ void linkingt::duplicate_code_symbol(
773771
old_symbol.location=new_symbol.location;
774772
old_symbol.is_macro=new_symbol.is_macro;
775773
}
776-
else if(to_code_type(old_symbol.type).get_inlined())
777-
{
778-
// ok, silently ignore
779-
}
780774
else if(base_type_eq(old_symbol.type, new_symbol.type, ns))
781775
{
782-
// keep the one in old_symbol -- libraries come last!
783-
warning().source_location=new_symbol.location;
776+
if(!new_symbol.is_file_local || !old_symbol.is_file_local)
777+
{
778+
// keep the one in old_symbol -- libraries come last!
779+
warning().source_location = new_symbol.location;
784780

785-
warning() << "function '" << old_symbol.name << "' in module '"
786-
<< new_symbol.module
787-
<< "' is shadowed by a definition in module '"
788-
<< old_symbol.module << "'" << eom;
781+
warning() << "function '" << old_symbol.name << "' in module '"
782+
<< new_symbol.module
783+
<< "' is shadowed by a definition in module '"
784+
<< old_symbol.module << "'" << eom;
785+
}
789786
}
790787
else
791788
link_error(

0 commit comments

Comments
 (0)