From fe5c1a10d505852eb9a70c19e20c727e05cdea48 Mon Sep 17 00:00:00 2001 From: Michael Tautschnig Date: Tue, 7 Mar 2023 12:19:37 +0000 Subject: [PATCH] Linking: fix up all types before handling functions or objects Function parameters may require application of type fixes: our linking ensures that all types have a unique tag, and some parameter's types may require such tag updates. We used to do this for objects already, but need to apply it to parameters as well. Also, the order matters: all types need to be sorted out first before attempting objects or functions. Spotted while trying to compile a particular version of Xen 4.11. --- .../ansi-c/linking_conflicts2/test.desc | 2 +- src/linking/linking.cpp | 49 ++++++++++++------- 2 files changed, 32 insertions(+), 19 deletions(-) diff --git a/regression/ansi-c/linking_conflicts2/test.desc b/regression/ansi-c/linking_conflicts2/test.desc index aa958cb6476..3d3eb99c6b5 100644 --- a/regression/ansi-c/linking_conflicts2/test.desc +++ b/regression/ansi-c/linking_conflicts2/test.desc @@ -3,6 +3,6 @@ main.c other.c ^EXIT=(64|1)$ ^SIGNAL=0$ -^\S+\.c(:\d+:\d+|\(\d+\)): error: conflicting function declarations 'foo'$ +^\S+\.c(:\d+:\d+|\(\d+\)): error: duplicate definition of function 'foo'$ -- ^warning: ignoring diff --git a/src/linking/linking.cpp b/src/linking/linking.cpp index a5c11955b1e..def12b6ca68 100644 --- a/src/linking/linking.cpp +++ b/src/linking/linking.cpp @@ -692,9 +692,18 @@ void linkingt::duplicate_code_symbol( n_it!=new_t.parameters().end(); ++o_it, ++n_it) { - if(o_it->type() != n_it->type()) + if(o_it->type() == n_it->type()) + continue; + + adjust_type_infot info(old_symbol, new_symbol); + bool failed = adjust_object_type_rec(o_it->type(), n_it->type(), info); + replace = info.set_to_new; + + if(failed) + { conflicts.push_back( std::make_pair(o_it->type(), n_it->type())); + } } if(o_it!=old_t.parameters().end()) { @@ -970,22 +979,20 @@ bool linkingt::adjust_object_type_rec( if(t1.id()==ID_pointer) { - #if 0 - bool s=info.set_to_new; - if(adjust_object_type_rec(t1.subtype(), t2.subtype(), info)) + if(info.old_symbol.type.id() == ID_code) + { + link_warning( + info.old_symbol, + info.new_symbol, + "pointer parameter types differ between declaration and definition"); + } + else { link_warning( info.old_symbol, info.new_symbol, "conflicting pointer types for variable"); - info.set_to_new=s; } - #else - link_warning( - info.old_symbol, - info.new_symbol, - "conflicting pointer types for variable"); - #endif if(info.old_symbol.is_extern && !info.new_symbol.is_extern) { @@ -1490,7 +1497,7 @@ void linkingt::copy_symbols( } // Move over all the non-colliding ones - std::unordered_set collisions; + std::unordered_set type_collisions, non_type_collisions; for(const auto &named_symbol : src_symbols) { @@ -1507,21 +1514,27 @@ void linkingt::copy_symbols( // new main_symbol_table.add(named_symbol.second); } + else if(named_symbol.second.is_type) + type_collisions.insert(named_symbol.first); else - collisions.insert(named_symbol.first); + non_type_collisions.insert(named_symbol.first); } } // Now do the collisions - for(const irep_idt &collision : collisions) + for(const irep_idt &collision : type_collisions) { symbolt &old_symbol = main_symbol_table.get_writeable_ref(collision); symbolt &new_symbol=src_symbols.at(collision); - if(new_symbol.is_type) - duplicate_type_symbol(old_symbol, new_symbol); - else - duplicate_non_type_symbol(old_symbol, new_symbol); + duplicate_type_symbol(old_symbol, new_symbol); + } + for(const irep_idt &collision : non_type_collisions) + { + symbolt &old_symbol = main_symbol_table.get_writeable_ref(collision); + symbolt &new_symbol = src_symbols.at(collision); + + duplicate_non_type_symbol(old_symbol, new_symbol); } // Apply type updates to initializers