Skip to content

Commit 8b3cc17

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 313c1ac commit 8b3cc17

File tree

4 files changed

+54
-48
lines changed

4 files changed

+54
-48
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(write_bin_object_file(output_file_executable, goto_model))
@@ -352,11 +354,13 @@ bool compilet::link()
352354
return add_written_cprover_symbols(goto_model.symbol_table);
353355
}
354356

355-
/// parses source files and writes object files, or keeps the symbols in the
356-
/// symbol_table depending on the doLink flag.
357-
/// \return true on error, false otherwise
358-
bool compilet::compile()
357+
/// Parses source files and writes object files, or keeps the symbols in the
358+
/// symbol_table if not compiling/assembling only.
359+
/// \return Symbol table, if parsing and type checking succeeded, else empty
360+
optionalt<symbol_tablet> compilet::compile()
359361
{
362+
symbol_tablet symbol_table;
363+
360364
while(!source_files.empty())
361365
{
362366
std::string file_name=source_files.front();
@@ -367,9 +371,9 @@ bool compilet::compile()
367371
if(echo_file_name)
368372
std::cout << get_base_name(file_name, false) << '\n' << std::flush;
369373

370-
bool r=parse_source(file_name); // don't break the program!
374+
auto file_symbol_table = parse_source(file_name);
371375

372-
if(r)
376+
if(!file_symbol_table.has_value())
373377
{
374378
const std::string &debug_outfile=
375379
cmdline.get_value("print-rejected-preprocessed-source");
@@ -381,15 +385,17 @@ bool compilet::compile()
381385
warning() << "Failed sources in " << debug_outfile << eom;
382386
}
383387

384-
return true; // parser/typecheck error
388+
return {}; // parser/typecheck error
385389
}
386390

387391
if(mode==COMPILE_ONLY || mode==ASSEMBLE_ONLY)
388392
{
389393
// output an object file for every source file
390394

391395
// "compile" functions
392-
convert_symbols(goto_model.goto_functions);
396+
goto_modelt file_goto_model;
397+
file_goto_model.symbol_table = std::move(*file_symbol_table);
398+
convert_symbols(file_goto_model);
393399

394400
std::string cfn;
395401

@@ -409,21 +415,26 @@ bool compilet::compile()
409415
if(keep_file_local)
410416
{
411417
function_name_manglert<file_name_manglert> mangler(
412-
get_message_handler(), goto_model, file_local_mangle_suffix);
418+
get_message_handler(), file_goto_model, file_local_mangle_suffix);
413419
mangler.mangle();
414420
}
415421

416-
if(write_bin_object_file(cfn, goto_model))
417-
return true;
418-
419-
if(add_written_cprover_symbols(goto_model.symbol_table))
420-
return true;
422+
if(write_bin_object_file(cfn, file_goto_model))
423+
return {};
421424

422-
goto_model.clear(); // clean symbol table for next source file.
425+
if(add_written_cprover_symbols(file_goto_model.symbol_table))
426+
return {};
427+
}
428+
else
429+
{
430+
if(linking(symbol_table, *file_symbol_table, get_message_handler()))
431+
{
432+
return {};
433+
}
423434
}
424435
}
425436

426-
return false;
437+
return std::move(symbol_table);
427438
}
428439

429440
/// parses a source file (low-level parsing)
@@ -593,37 +604,37 @@ bool compilet::write_bin_object_file(
593604
return false;
594605
}
595606

596-
/// parses a source file
597-
/// \return true on error, false otherwise
598-
bool compilet::parse_source(const std::string &file_name)
607+
/// Parses and type checks a source file located at \p file_name.
608+
/// \return A symbol table if, and only if, parsing and type checking succeeded.
609+
optionalt<symbol_tablet> compilet::parse_source(const std::string &file_name)
599610
{
600611
language_filest language_files;
601612
language_files.set_message_handler(get_message_handler());
602613

603614
if(parse(file_name, language_files))
604-
return true;
615+
return {};
605616

606617
// we just typecheck one file here
607-
if(language_files.typecheck(goto_model.symbol_table, keep_file_local))
618+
symbol_tablet file_symbol_table;
619+
if(language_files.typecheck(file_symbol_table, keep_file_local))
608620
{
609621
error() << "CONVERSION ERROR" << eom;
610-
return true;
622+
return {};
611623
}
612624

613-
if(language_files.final(goto_model.symbol_table))
625+
if(language_files.final(file_symbol_table))
614626
{
615627
error() << "CONVERSION ERROR" << eom;
616-
return true;
628+
return {};
617629
}
618630

619-
return false;
631+
return std::move(file_symbol_table);
620632
}
621633

622634
/// constructor
623635
/// \return nothing
624636
compilet::compilet(cmdlinet &_cmdline, message_handlert &mh, bool Werror)
625637
: messaget(mh),
626-
ns(goto_model.symbol_table),
627638
cmdline(_cmdline),
628639
warning_is_fatal(Werror),
629640
keep_file_local(cmdline.isset("export-function-local-symbols")),
@@ -663,7 +674,7 @@ void compilet::add_compiler_specific_defines() const
663674
std::string("__GOTO_CC_VERSION__=") + CBMC_VERSION);
664675
}
665676

666-
void compilet::convert_symbols(goto_functionst &dest)
677+
void compilet::convert_symbols(goto_modelt &goto_model)
667678
{
668679
symbol_table_buildert symbol_table_builder =
669680
symbol_table_buildert::wrap(goto_model.symbol_table);
@@ -697,7 +708,8 @@ void compilet::convert_symbols(goto_functionst &dest)
697708
s_it->second.value.is_not_nil())
698709
{
699710
debug() << "Compiling " << s_it->first << eom;
700-
converter.convert_function(s_it->first, dest.function_map[s_it->first]);
711+
converter.convert_function(
712+
s_it->first, goto_model.goto_functions.function_map[s_it->first]);
701713
symbol_table_builder.get_writeable_ref(symbol).set_compiled();
702714
}
703715
}

src/goto-cc/compile.h

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,6 @@ class languaget;
2626
class compilet : public messaget
2727
{
2828
public:
29-
// compilation results
30-
namespacet ns;
31-
goto_modelt goto_model;
32-
3329
// configuration
3430
bool echo_file_name;
3531
std::string working_directory;
@@ -68,10 +64,10 @@ class compilet : public messaget
6864
bool parse(const std::string &filename, language_filest &);
6965
bool parse_stdin(languaget &);
7066
bool doit();
71-
bool compile();
72-
bool link();
67+
optionalt<symbol_tablet> compile();
68+
bool link(optionalt<symbol_tablet> &&symbol_table);
7369

74-
bool parse_source(const std::string &);
70+
optionalt<symbol_tablet> parse_source(const std::string &);
7571

7672
/// Writes the goto functions of \p src_goto_model to a binary format object
7773
/// file.
@@ -132,7 +128,7 @@ class compilet : public messaget
132128

133129
void add_compiler_specific_defines() const;
134130

135-
void convert_symbols(goto_functionst &dest);
131+
void convert_symbols(goto_modelt &);
136132

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

0 commit comments

Comments
 (0)