Skip to content

Commit 21d3ee8

Browse files
authored
Merge pull request #4297 from tautschnig/linking-fix-2
goto-cc: also use the linker when processing multiple source files [blocks: #4056]
2 parents 4c51ce9 + adaefcf commit 21d3ee8

File tree

10 files changed

+136
-97
lines changed

10 files changed

+136
-97
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

scripts/expected_doxygen_warnings.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,11 +91,11 @@ warning: Included by graph for 'expr.h' not generated, too many nodes (88), thre
9191
warning: Included by graph for 'expr_util.h' not generated, too many nodes (60), threshold is 60. Consider increasing DOT_GRAPH_MAX_NODES.
9292
warning: Included by graph for 'invariant.h' not generated, too many nodes (187), threshold is 60. Consider increasing DOT_GRAPH_MAX_NODES.
9393
warning: Included by graph for 'irep.h' not generated, too many nodes (62), threshold is 60. Consider increasing DOT_GRAPH_MAX_NODES.
94-
warning: Included by graph for 'message.h' not generated, too many nodes (115), threshold is 60. Consider increasing DOT_GRAPH_MAX_NODES.
94+
warning: Included by graph for 'message.h' not generated, too many nodes (116), threshold is 60. Consider increasing DOT_GRAPH_MAX_NODES.
9595
warning: Included by graph for 'namespace.h' not generated, too many nodes (111), threshold is 60. Consider increasing DOT_GRAPH_MAX_NODES.
9696
warning: Included by graph for 'prefix.h' not generated, too many nodes (86), threshold is 60. Consider increasing DOT_GRAPH_MAX_NODES.
9797
warning: Included by graph for 'simplify_expr.h' not generated, too many nodes (76), threshold is 60. Consider increasing DOT_GRAPH_MAX_NODES.
9898
warning: Included by graph for 'std_code.h' not generated, too many nodes (78), threshold is 60. Consider increasing DOT_GRAPH_MAX_NODES.
99-
warning: Included by graph for 'std_expr.h' not generated, too many nodes (245), threshold is 60. Consider increasing DOT_GRAPH_MAX_NODES.
99+
warning: Included by graph for 'std_expr.h' not generated, too many nodes (246), threshold is 60. Consider increasing DOT_GRAPH_MAX_NODES.
100100
warning: Included by graph for 'std_types.h' not generated, too many nodes (124), threshold is 60. Consider increasing DOT_GRAPH_MAX_NODES.
101101
warning: Included by graph for 'symbol_table.h' not generated, too many nodes (95), threshold is 60. Consider increasing DOT_GRAPH_MAX_NODES.

src/goto-cc/compile.cpp

Lines changed: 65 additions & 54 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;
429+
if(write_bin_object_file(cfn, file_goto_model))
430+
return {};
425431

426-
if(add_written_cprover_symbols(goto_model.symbol_table))
427-
return true;
428-
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)
@@ -556,32 +567,33 @@ bool compilet::parse_stdin(languaget &language)
556567
return false;
557568
}
558569

559-
/// Writes the goto functions of \p src_goto_model to a binary format object
560-
/// file.
561-
/// \param file_name: Target file to serialize \p src_goto_model to
562-
/// \param src_goto_model: goto model to serialize
563-
/// \return true on error, false otherwise
564570
bool compilet::write_bin_object_file(
565571
const std::string &file_name,
566-
const goto_modelt &src_goto_model)
572+
const goto_modelt &src_goto_model,
573+
bool validate_goto_model,
574+
message_handlert &message_handler)
567575
{
576+
messaget log(message_handler);
577+
568578
if(validate_goto_model)
569579
{
570-
status() << "Validating goto model" << eom;
580+
log.status() << "Validating goto model" << messaget::eom;
571581
src_goto_model.validate();
572582
}
573583

574-
statistics() << "Writing binary format object '" << file_name << "'" << eom;
584+
log.statistics() << "Writing binary format object '" << file_name << "'"
585+
<< messaget::eom;
575586

576587
// symbols
577-
statistics() << "Symbols in table: "
578-
<< src_goto_model.symbol_table.symbols.size() << eom;
588+
log.statistics() << "Symbols in table: "
589+
<< src_goto_model.symbol_table.symbols.size()
590+
<< messaget::eom;
579591

580592
std::ofstream outfile(file_name, std::ios::binary);
581593

582594
if(!outfile.is_open())
583595
{
584-
error() << "Error opening file '" << file_name << "'" << eom;
596+
log.error() << "Error opening file '" << file_name << "'" << messaget::eom;
585597
return true;
586598
}
587599

@@ -590,47 +602,46 @@ bool compilet::write_bin_object_file(
590602

591603
const auto cnt = function_body_count(src_goto_model.goto_functions);
592604

593-
statistics() << "Functions: "
594-
<< src_goto_model.goto_functions.function_map.size() << "; "
595-
<< cnt << " have a body." << eom;
605+
log.statistics() << "Functions: "
606+
<< src_goto_model.goto_functions.function_map.size() << "; "
607+
<< cnt << " have a body." << messaget::eom;
596608

597609
outfile.close();
598-
wrote_object=true;
599610

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(
@@ -661,8 +672,7 @@ compilet::~compilet()
661672
delete_directory(dir);
662673
}
663674

664-
std::size_t
665-
compilet::function_body_count(const goto_functionst &functions) const
675+
std::size_t compilet::function_body_count(const goto_functionst &functions)
666676
{
667677
std::size_t count = 0;
668678

@@ -679,7 +689,7 @@ void compilet::add_compiler_specific_defines() const
679689
std::string("__GOTO_CC_VERSION__=") + CBMC_VERSION);
680690
}
681691

682-
void compilet::convert_symbols(goto_functionst &dest)
692+
void compilet::convert_symbols(goto_modelt &goto_model)
683693
{
684694
symbol_table_buildert symbol_table_builder =
685695
symbol_table_buildert::wrap(goto_model.symbol_table);
@@ -713,7 +723,8 @@ void compilet::convert_symbols(goto_functionst &dest)
713723
s_it->second.value.is_not_nil())
714724
{
715725
debug() << "Compiling " << s_it->first << eom;
716-
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]);
717728
symbol_table_builder.get_writeable_ref(symbol).set_compiled();
718729
}
719730
}

src/goto-cc/compile.h

Lines changed: 34 additions & 13 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,12 +60,23 @@ 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();
68-
69-
bool parse_source(const std::string &);
70-
71-
bool write_bin_object_file(const std::string &, const goto_modelt &);
63+
optionalt<symbol_tablet> compile();
64+
bool link(optionalt<symbol_tablet> &&symbol_table);
65+
66+
optionalt<symbol_tablet> parse_source(const std::string &);
67+
68+
/// Writes the goto functions of \p src_goto_model to a binary format object
69+
/// file.
70+
/// \param file_name: Target file to serialize \p src_goto_model to
71+
/// \param src_goto_model: goto model to serialize
72+
/// \param validate_goto_model: enable goto-model validation
73+
/// \param message_handler: message handler
74+
/// \return true on error, false otherwise
75+
static bool write_bin_object_file(
76+
const std::string &file_name,
77+
const goto_modelt &src_goto_model,
78+
bool validate_goto_model,
79+
message_handlert &message_handler);
7280

7381
/// \brief Has this compiler written any object files?
7482
bool wrote_object_files() const { return wrote_object; }
@@ -88,8 +96,6 @@ class compilet : public messaget
8896
}
8997

9098
protected:
91-
namespacet ns;
92-
9399
std::string working_directory;
94100
std::string override_language;
95101

@@ -105,11 +111,26 @@ class compilet : public messaget
105111
/// \brief String to include in all mangled names
106112
const std::string file_local_mangle_suffix;
107113

108-
std::size_t function_body_count(const goto_functionst &) const;
114+
static std::size_t function_body_count(const goto_functionst &);
115+
116+
bool write_bin_object_file(
117+
const std::string &file_name,
118+
const goto_modelt &src_goto_model)
119+
{
120+
if(write_bin_object_file(
121+
file_name, src_goto_model, validate_goto_model, get_message_handler()))
122+
{
123+
return true;
124+
}
125+
126+
wrote_object = true;
127+
128+
return false;
129+
}
109130

110131
void add_compiler_specific_defines() const;
111132

112-
void convert_symbols(goto_functionst &dest);
133+
void convert_symbols(goto_modelt &);
113134

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

0 commit comments

Comments
 (0)