From f3bbb12e920680c314c8b31faf7d8f62cf319c81 Mon Sep 17 00:00:00 2001 From: Michael Tautschnig Date: Sat, 10 Mar 2018 18:42:17 +0000 Subject: [PATCH] Linking: report multiple conflicts Previously, linking would fail with an exception upon the first symbol with conflicting types. As there may be multiple problems found in the same linking run, display all conflicts to the user so that they can fix all of them at once. --- regression/ansi-c/linking_conflicts1/main.c | 14 +++++++ regression/ansi-c/linking_conflicts1/other.c | 12 ++++++ .../ansi-c/linking_conflicts1/test.desc | 10 +++++ src/linking/linking.cpp | 38 ++++++++++++++++++- 4 files changed, 72 insertions(+), 2 deletions(-) create mode 100644 regression/ansi-c/linking_conflicts1/main.c create mode 100644 regression/ansi-c/linking_conflicts1/other.c create mode 100644 regression/ansi-c/linking_conflicts1/test.desc diff --git a/regression/ansi-c/linking_conflicts1/main.c b/regression/ansi-c/linking_conflicts1/main.c new file mode 100644 index 00000000000..9494fc68762 --- /dev/null +++ b/regression/ansi-c/linking_conflicts1/main.c @@ -0,0 +1,14 @@ +int bar() +{ + return 0; +} + +int bar2() +{ + return 0; +} + +int main() +{ + unsigned x = foo(); +} diff --git a/regression/ansi-c/linking_conflicts1/other.c b/regression/ansi-c/linking_conflicts1/other.c new file mode 100644 index 00000000000..6f27ef784e4 --- /dev/null +++ b/regression/ansi-c/linking_conflicts1/other.c @@ -0,0 +1,12 @@ +void bar() +{ +} + +void bar2() +{ +} + +unsigned foo() +{ + return 0; +} diff --git a/regression/ansi-c/linking_conflicts1/test.desc b/regression/ansi-c/linking_conflicts1/test.desc new file mode 100644 index 00000000000..92ed8df59a9 --- /dev/null +++ b/regression/ansi-c/linking_conflicts1/test.desc @@ -0,0 +1,10 @@ +CORE +main.c +other.c +^EXIT=(64|1)$ +^SIGNAL=0$ +^CONVERSION ERROR$ +error: conflicting function declarations `bar' +error: conflicting function declarations `bar2' +-- +^warning: ignoring diff --git a/src/linking/linking.cpp b/src/linking/linking.cpp index e956867ebb0..c4efe0b773e 100644 --- a/src/linking/linking.cpp +++ b/src/linking/linking.cpp @@ -382,8 +382,6 @@ void linkingt::link_error( error() << "new definition in module `" << new_symbol.module << "' " << new_symbol.location << '\n' << type_to_string_verbose(ns, new_symbol) << eom; - - throw 0; } void linkingt::link_warning( @@ -573,6 +571,9 @@ void linkingt::duplicate_code_symbol( old_symbol, new_symbol, "conflicting parameter counts of function declarations"); + + // error logged, continue typechecking other symbols + return; } else { @@ -602,19 +603,31 @@ void linkingt::duplicate_code_symbol( if(o_it!=old_t.parameters().end()) { if(!new_t.has_ellipsis() && old_symbol.value.is_not_nil()) + { link_error( old_symbol, new_symbol, "conflicting parameter counts of function declarations"); + + // error logged, continue typechecking other symbols + return; + } + replace=new_symbol.value.is_not_nil(); } else if(n_it!=new_t.parameters().end()) { if(!old_t.has_ellipsis() && new_symbol.value.is_not_nil()) + { link_error( old_symbol, new_symbol, "conflicting parameter counts of function declarations"); + + // error logged, continue typechecking other symbols + return; + } + replace=new_symbol.value.is_not_nil(); } @@ -708,6 +721,9 @@ void linkingt::duplicate_code_symbol( old_symbol, new_symbol, "conflicting function declarations"); + + // error logged, continue typechecking other symbols + return; } else { @@ -876,10 +892,15 @@ bool linkingt::adjust_object_type_rec( equal_exprt eq(old_size, new_size); if(!simplify_expr(eq, ns).is_true()) + { link_error( info.old_symbol, info.new_symbol, "conflicting array sizes for variable"); + + // error logged, continue typechecking other symbols + return true; + } } return false; @@ -958,6 +979,9 @@ void linkingt::duplicate_object_symbol( old_symbol, new_symbol, "conflicting types for variable"); + + // error logged, continue typechecking other symbols + return; } else if(set_to_new) old_symbol.type=new_symbol.type; @@ -1022,11 +1046,16 @@ void linkingt::duplicate_non_type_symbol( bool is_code_new_symbol=new_symbol.type.id()==ID_code; if(is_code_old_symbol!=is_code_new_symbol) + { link_error( old_symbol, new_symbol, "conflicting definition for symbol"); + // error logged, continue typechecking other symbols + return; + } + if(is_code_old_symbol) duplicate_code_symbol(old_symbol, new_symbol); else @@ -1048,11 +1077,16 @@ void linkingt::duplicate_type_symbol( assert(new_symbol.is_type); if(!old_symbol.is_type) + { link_error( old_symbol, new_symbol, "conflicting definition for symbol"); + // error logged, continue typechecking other symbols + return; + } + if(old_symbol.type==new_symbol.type) return;