Skip to content

Commit 7ebc1de

Browse files
committed
goto-cc: also use the linker when processing multiple source files
The linker is able to do some type sanitisation across translation units, and there is no reason behaviour should be different whether we link previously compiled object files or a set of source files.
1 parent 34faef6 commit 7ebc1de

File tree

4 files changed

+54
-47
lines changed

4 files changed

+54
-47
lines changed

regression/ansi-c/linking_conflicts1/test.desc

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ main.c
33
other.c
44
^EXIT=(64|1)$
55
^SIGNAL=0$
6-
^CONVERSION ERROR$
76
error: conflicting function declarations 'bar'
87
error: conflicting function declarations 'bar2'
98
--
Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
1-
CORE broken-test-c++-front-end
1+
CORE
22
main.c
33
other.c
44
^EXIT=(64|1)$
55
^SIGNAL=0$
6-
^CONVERSION ERROR$
76
error: conflicting function declarations 'foo'
87
--
98
^warning: ignoring

src/goto-cc/compile.cpp

Lines changed: 49 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ Date: June 2006
4242
#include <langapi/language_file.h>
4343
#include <langapi/mode.h>
4444

45+
#include <linking/linking.h>
4546
#include <linking/static_lifetime_init.h>
4647

4748
#define DOTGRAPHSETTINGS "color=black;" \
@@ -56,8 +57,6 @@ Date: June 2006
5657
/// \return true on error, false otherwise
5758
bool compilet::doit()
5859
{
59-
goto_model.goto_functions.clear();
60-
6160
add_compiler_specific_defines();
6261

6362
// Parse command line for source and object file names
@@ -98,15 +97,15 @@ bool compilet::doit()
9897
const unsigned warnings_before=
9998
get_message_handler().get_message_count(messaget::M_WARNING);
10099

101-
if(!source_files.empty())
102-
if(compile())
103-
return true;
100+
auto symbol_table_opt = compile();
101+
if(!symbol_table_opt.has_value())
102+
return true;
104103

105104
if(mode==LINK_LIBRARY ||
106105
mode==COMPILE_LINK ||
107106
mode==COMPILE_LINK_EXECUTABLE)
108107
{
109-
if(link())
108+
if(link(*symbol_table_opt))
110109
return true;
111110
}
112111

@@ -308,11 +307,14 @@ bool compilet::find_library(const std::string &name)
308307

309308
/// parses object files and links them
310309
/// \return true on error, false otherwise
311-
bool compilet::link()
310+
bool compilet::link(optionalt<symbol_tablet> &&symbol_table)
312311
{
313312
// "compile" hitherto uncompiled functions
314313
statistics() << "Compiling functions" << eom;
315-
convert_symbols(goto_model.goto_functions);
314+
goto_modelt goto_model;
315+
if(symbol_table.has_value())
316+
goto_model.symbol_table = std::move(*symbol_table);
317+
convert_symbols(goto_model);
316318

317319
// parse object files
318320
for(const auto &file_name : object_files)
@@ -343,7 +345,7 @@ bool compilet::link()
343345
return true;
344346

345347
// entry_point may (should) add some more functions.
346-
convert_symbols(goto_model.goto_functions);
348+
convert_symbols(goto_model);
347349
}
348350

349351
if(keep_file_local)
@@ -359,11 +361,13 @@ bool compilet::link()
359361
return add_written_cprover_symbols(goto_model.symbol_table);
360362
}
361363

362-
/// parses source files and writes object files, or keeps the symbols in the
363-
/// symbol_table depending on the doLink flag.
364-
/// \return true on error, false otherwise
365-
bool compilet::compile()
364+
/// Parses source files and writes object files, or keeps the symbols in the
365+
/// symbol_table if not compiling/assembling only.
366+
/// \return Symbol table, if parsing and type checking succeeded, else empty
367+
optionalt<symbol_tablet> compilet::compile()
366368
{
369+
symbol_tablet symbol_table;
370+
367371
while(!source_files.empty())
368372
{
369373
std::string file_name=source_files.front();
@@ -374,9 +378,9 @@ bool compilet::compile()
374378
if(echo_file_name)
375379
std::cout << get_base_name(file_name, false) << '\n' << std::flush;
376380

377-
bool r=parse_source(file_name); // don't break the program!
381+
auto file_symbol_table = parse_source(file_name);
378382

379-
if(r)
383+
if(!file_symbol_table.has_value())
380384
{
381385
const std::string &debug_outfile=
382386
cmdline.get_value("print-rejected-preprocessed-source");
@@ -388,15 +392,17 @@ bool compilet::compile()
388392
warning() << "Failed sources in " << debug_outfile << eom;
389393
}
390394

391-
return true; // parser/typecheck error
395+
return {}; // parser/typecheck error
392396
}
393397

394398
if(mode==COMPILE_ONLY || mode==ASSEMBLE_ONLY)
395399
{
396400
// output an object file for every source file
397401

398402
// "compile" functions
399-
convert_symbols(goto_model.goto_functions);
403+
goto_modelt file_goto_model;
404+
file_goto_model.symbol_table = std::move(*file_symbol_table);
405+
convert_symbols(file_goto_model);
400406

401407
std::string cfn;
402408

@@ -416,21 +422,26 @@ bool compilet::compile()
416422
if(keep_file_local)
417423
{
418424
function_name_manglert<file_name_manglert> mangler(
419-
get_message_handler(), goto_model, file_local_mangle_suffix);
425+
get_message_handler(), file_goto_model, file_local_mangle_suffix);
420426
mangler.mangle();
421427
}
422428

423-
if(write_bin_object_file(cfn, goto_model))
424-
return true;
425-
426-
if(add_written_cprover_symbols(goto_model.symbol_table))
427-
return true;
429+
if(write_bin_object_file(cfn, file_goto_model))
430+
return {};
428431

429-
goto_model.clear(); // clean symbol table for next source file.
432+
if(add_written_cprover_symbols(file_goto_model.symbol_table))
433+
return {};
434+
}
435+
else
436+
{
437+
if(linking(symbol_table, *file_symbol_table, get_message_handler()))
438+
{
439+
return {};
440+
}
430441
}
431442
}
432443

433-
return false;
444+
return std::move(symbol_table);
434445
}
435446

436447
/// parses a source file (low-level parsing)
@@ -600,37 +611,37 @@ bool compilet::write_bin_object_file(
600611
return false;
601612
}
602613

603-
/// parses a source file
604-
/// \return true on error, false otherwise
605-
bool compilet::parse_source(const std::string &file_name)
614+
/// Parses and type checks a source file located at \p file_name.
615+
/// \return A symbol table if, and only if, parsing and type checking succeeded.
616+
optionalt<symbol_tablet> compilet::parse_source(const std::string &file_name)
606617
{
607618
language_filest language_files;
608619
language_files.set_message_handler(get_message_handler());
609620

610621
if(parse(file_name, language_files))
611-
return true;
622+
return {};
612623

613624
// we just typecheck one file here
614-
if(language_files.typecheck(goto_model.symbol_table, keep_file_local))
625+
symbol_tablet file_symbol_table;
626+
if(language_files.typecheck(file_symbol_table, keep_file_local))
615627
{
616628
error() << "CONVERSION ERROR" << eom;
617-
return true;
629+
return {};
618630
}
619631

620-
if(language_files.final(goto_model.symbol_table))
632+
if(language_files.final(file_symbol_table))
621633
{
622634
error() << "CONVERSION ERROR" << eom;
623-
return true;
635+
return {};
624636
}
625637

626-
return false;
638+
return std::move(file_symbol_table);
627639
}
628640

629641
/// constructor
630642
/// \return nothing
631643
compilet::compilet(cmdlinet &_cmdline, message_handlert &mh, bool Werror)
632644
: messaget(mh),
633-
ns(goto_model.symbol_table),
634645
cmdline(_cmdline),
635646
warning_is_fatal(Werror),
636647
keep_file_local(
@@ -678,7 +689,7 @@ void compilet::add_compiler_specific_defines() const
678689
std::string("__GOTO_CC_VERSION__=") + CBMC_VERSION);
679690
}
680691

681-
void compilet::convert_symbols(goto_functionst &dest)
692+
void compilet::convert_symbols(goto_modelt &goto_model)
682693
{
683694
symbol_table_buildert symbol_table_builder =
684695
symbol_table_buildert::wrap(goto_model.symbol_table);
@@ -712,7 +723,8 @@ void compilet::convert_symbols(goto_functionst &dest)
712723
s_it->second.value.is_not_nil())
713724
{
714725
debug() << "Compiling " << s_it->first << eom;
715-
converter.convert_function(s_it->first, dest.function_map[s_it->first]);
726+
converter.convert_function(
727+
s_it->first, goto_model.goto_functions.function_map[s_it->first]);
716728
symbol_table_builder.get_writeable_ref(symbol).set_compiled();
717729
}
718730
}

src/goto-cc/compile.h

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,6 @@ class languaget;
2626
class compilet : public messaget
2727
{
2828
public:
29-
// compilation results
30-
goto_modelt goto_model;
31-
3229
// configuration
3330
bool echo_file_name;
3431
bool validate_goto_model = false;
@@ -63,10 +60,10 @@ class compilet : public messaget
6360
bool parse(const std::string &filename, language_filest &);
6461
bool parse_stdin(languaget &);
6562
bool doit();
66-
bool compile();
67-
bool link();
63+
optionalt<symbol_tablet> compile();
64+
bool link(optionalt<symbol_tablet> &&symbol_table);
6865

69-
bool parse_source(const std::string &);
66+
optionalt<symbol_tablet> parse_source(const std::string &);
7067

7168
/// Writes the goto functions of \p src_goto_model to a binary format object
7269
/// file.
@@ -133,7 +130,7 @@ class compilet : public messaget
133130

134131
void add_compiler_specific_defines() const;
135132

136-
void convert_symbols(goto_functionst &dest);
133+
void convert_symbols(goto_modelt &);
137134

138135
bool add_written_cprover_symbols(const symbol_tablet &symbol_table);
139136
std::map<irep_idt, symbolt> written_macros;

0 commit comments

Comments
 (0)