Skip to content

Commit 03f65f9

Browse files
committed
export-file-local-symbol A,B: selective export of file-local symbols
Previously, --export-file-local-symbols would mark (and mangle) all file-local symbols. With --export-file-local-symbol A (or --export-file-local-symbol A,B), only A (or A and B) will be mangled and exported.
1 parent 66a80eb commit 03f65f9

File tree

20 files changed

+119
-33
lines changed

20 files changed

+119
-33
lines changed

doc/architectural/static-functions.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,8 @@ We should now also write a harness for `private_function`. However,
9292
since that function is marked `static`, it is not possible for functions
9393
in external files to call it. We can write and link a harness by
9494
stripping the `static` attribute from `private_function` using goto-cc's
95-
`--export-file-local-symbols` flag.
95+
`--export-file-local-symbols` or `--export-file-local-symbol private_function`
96+
flag.
9697

9798
\code{.sh}
9899
> goto-cc -c -o --export-file-local-symbols library_with_static.o library.c

regression/goto-cc-file-local/chain.sh

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,9 @@ fi
5050
export_flag=""
5151
if is_in old-flag "$ALL_ARGS"; then
5252
export_flag="--export-function-local-symbols"
53+
elif is_in "export-[a-zA-Z0-9_,]*-only" "$ALL_ARGS"; then
54+
suffix=${ALL_ARGS#*export-}
55+
export_flag="--export-file-local-symbol ${suffix%-only*}"
5356
else
5457
export_flag="--export-file-local-symbols"
5558
fi
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
static int foo(int x)
2+
{
3+
return x + 1;
4+
}
5+
6+
static int bar(int x)
7+
{
8+
return x + 2;
9+
}
10+
11+
static int baz(int x)
12+
{
13+
return x + 2;
14+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
CORE
2+
main.c
3+
export-foo,bar-only show-symbol-table
4+
^Symbol\.\.\.\.\.\.: __CPROVER_file_local_main_c_foo$
5+
^Symbol\.\.\.\.\.\.: __CPROVER_file_local_main_c_bar$
6+
^Symbol\.\.\.\.\.\.: baz$
7+
^EXIT=0$
8+
^SIGNAL=0$
9+
--
10+
^warning: ignoring
11+
^Symbol\.\.\.\.\.\.: __CPROVER_file_local_main_c_baz$

src/ansi-c/ansi_c_language.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ bool ansi_c_languaget::parse(
103103
bool ansi_c_languaget::typecheck(
104104
symbol_tablet &symbol_table,
105105
const std::string &module,
106-
const bool keep_file_local)
106+
const std::string &keep_file_local)
107107
{
108108
symbol_tablet new_symbol_table;
109109

src/ansi-c/ansi_c_language.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ class ansi_c_languaget:public languaget
5454
bool typecheck(
5555
symbol_tablet &symbol_table,
5656
const std::string &module,
57-
const bool keep_file_local) override;
57+
const std::string &keep_file_local) override;
5858

5959
bool can_keep_file_local() override
6060
{
@@ -64,7 +64,7 @@ class ansi_c_languaget:public languaget
6464
bool
6565
typecheck(symbol_tablet &symbol_table, const std::string &module) override
6666
{
67-
return typecheck(symbol_table, module, true);
67+
return typecheck(symbol_table, module, ".*");
6868
}
6969

7070
void show_parse(std::ostream &out) override;

src/cpp/cpp_language.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ bool cpp_languaget::typecheck(
131131
cpp_parse_tree, new_symbol_table, module, get_message_handler()))
132132
return true;
133133

134-
remove_internal_symbols(new_symbol_table, get_message_handler(), false);
134+
remove_internal_symbols(new_symbol_table, get_message_handler(), "");
135135

136136
return linking(symbol_table, new_symbol_table, get_message_handler());
137137
}

src/goto-cc/compile.cpp

Lines changed: 39 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ Date: June 2006
2323
#include <util/get_base_name.h>
2424
#include <util/prefix.h>
2525
#include <util/run.h>
26+
#include <util/string_utils.h>
2627
#include <util/symbol_table_builder.h>
2728
#include <util/tempdir.h>
2829
#include <util/tempfile.h>
@@ -353,10 +354,13 @@ bool compilet::link(optionalt<symbol_tablet> &&symbol_table)
353354
convert_symbols(goto_model);
354355
}
355356

356-
if(keep_file_local)
357+
if(!keep_file_local.empty())
357358
{
358359
function_name_manglert<file_name_manglert> mangler(
359-
log.get_message_handler(), goto_model, file_local_mangle_suffix);
360+
log.get_message_handler(),
361+
goto_model,
362+
file_local_mangle_suffix,
363+
keep_file_local);
360364
mangler.mangle();
361365
}
362366

@@ -424,10 +428,13 @@ optionalt<symbol_tablet> compilet::compile()
424428
else
425429
cfn = output_file_object;
426430

427-
if(keep_file_local)
431+
if(!keep_file_local.empty())
428432
{
429433
function_name_manglert<file_name_manglert> mangler(
430-
log.get_message_handler(), file_goto_model, file_local_mangle_suffix);
434+
log.get_message_handler(),
435+
file_goto_model,
436+
file_local_mangle_suffix,
437+
keep_file_local);
431438
mangler.mangle();
432439
}
433440

@@ -645,18 +652,44 @@ optionalt<symbol_tablet> compilet::parse_source(const std::string &file_name)
645652
return std::move(file_symbol_table);
646653
}
647654

655+
/// Combine the elements of \p values to a regular expression denoting
656+
/// alternatives. Each element of \p values may in turn be a sequence of
657+
/// comma-separated values, which are also expanded to contribute to the overall
658+
/// collection of alternatives.
659+
static std::string csv_to_pattern(const std::list<std::string> &values)
660+
{
661+
std::string result;
662+
663+
for(const auto& csv : values)
664+
{
665+
for(const auto &name : split_string(csv, ','))
666+
{
667+
if(!result.empty())
668+
result += '|';
669+
result += name;
670+
}
671+
}
672+
673+
return result;
674+
}
675+
648676
/// constructor
649677
compilet::compilet(cmdlinet &_cmdline, message_handlert &mh, bool Werror)
650678
: log(mh),
651679
cmdline(_cmdline),
652680
warning_is_fatal(Werror),
653681
keep_file_local(
654682
// function-local is the old name and is still in use, but is misleading
655-
cmdline.isset("export-function-local-symbols") ||
656-
cmdline.isset("export-file-local-symbols")),
683+
(cmdline.isset("export-function-local-symbols") ||
684+
cmdline.isset("export-file-local-symbols"))
685+
? ".*"
686+
: (cmdline.isset("export-file-local-symbol")
687+
? csv_to_pattern(cmdline.get_values("export-file-local-symbol"))
688+
: "")),
657689
file_local_mangle_suffix(
658690
cmdline.isset("mangle-suffix") ? cmdline.get_value("mangle-suffix") : "")
659691
{
692+
log.warning() << "file-local: " << keep_file_local << messaget::eom;
660693
mode=COMPILE_LINK_EXECUTABLE;
661694
echo_file_name=false;
662695
wrote_object=false;

src/goto-cc/compile.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ class compilet
111111
bool warning_is_fatal;
112112

113113
/// \brief Whether to keep implementations of file-local symbols
114-
const bool keep_file_local;
114+
const std::string keep_file_local;
115115

116116
/// \brief String to include in all mangled names
117117
const std::string file_local_mangle_suffix;

src/goto-cc/gcc_cmdline.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ const char *goto_cc_options_with_separated_argument[]=
2828
"--print-rejected-preprocessed-source",
2929
"--mangle-suffix",
3030
"--object-bits",
31+
"--export-file-local-symbol",
3132
nullptr
3233
};
3334

src/goto-cc/goto_cc_mode.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,9 @@ void goto_cc_modet::help()
6666
" --native-assembler cmd command to invoke as assembler (goto-as only)\n"
6767
" --export-file-local-symbols\n"
6868
" name-mangle and export file-local symbols\n"
69+
" --export-file-local-symbol A,B\n"
70+
" export file-local symbols as above, but\n"
71+
" restrict this operation to symbols A and B\n"
6972
" --mangle-suffix suffix append suffix to exported file-local symbols\n"
7073
" --print-rejected-preprocessed-source file\n"
7174
" copy failing (preprocessed) source to file\n"

src/goto-cc/ms_cl_cmdline.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ const char *non_ms_cl_options[]=
4747
"--validate-goto-model",
4848
"--export-file-local-symbols",
4949
"--mangle-suffix",
50+
"--export-file-local-symbol",
5051
nullptr
5152
};
5253
// clang-format on
@@ -62,7 +63,8 @@ bool ms_cl_cmdlinet::parse(const std::vector<std::string> &arguments)
6263

6364
if(
6465
arguments[i] == "--verbosity" || arguments[i] == "--function" ||
65-
arguments[i] == "--mangle-suffix")
66+
arguments[i] == "--mangle-suffix" ||
67+
arguments[i] == "--export-file-local-symbol")
6668
{
6769
if(i < arguments.size() - 1)
6870
{

src/goto-programs/name_mangler.h

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,20 @@ class function_name_manglert
3131
{
3232
public:
3333
/// \param mh: handler to construct a log from
34-
/// \param gm: mangle all names in gm's symbol table and goto program
34+
/// \param gm: mangle names in gm's symbol table and goto program
3535
/// \param extra_info: a string to be included in each mangled name
36+
/// \param needs_mangling: a regular expression describing names that need to
37+
/// be mangled.
3638
function_name_manglert(
3739
message_handlert &mh,
3840
goto_modelt &gm,
39-
const std::string &extra_info)
40-
: log(mh), model(gm), mangle_fun(), extra_info(extra_info)
41+
const std::string &extra_info,
42+
const std::string &needs_mangling)
43+
: log(mh),
44+
model(gm),
45+
mangle_fun(),
46+
extra_info(extra_info),
47+
needs_mangling(needs_mangling)
4148
{
4249
}
4350

@@ -65,6 +72,8 @@ class function_name_manglert
6572
continue;
6673
if(!sym.is_file_local)
6774
continue;
75+
if(!std::regex_match(id2string(sym.name), needs_mangling))
76+
continue;
6877

6978
const irep_idt mangled = mangle_fun(sym, extra_info);
7079
symbolt new_sym;
@@ -136,6 +145,7 @@ class function_name_manglert
136145
goto_modelt &model;
137146
MangleFun mangle_fun;
138147
const std::string &extra_info;
148+
const std::regex needs_mangling;
139149
};
140150

141151
/// \brief Mangle identifiers by including their filename

src/langapi/language.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ class languaget:public messaget
140140
virtual bool typecheck(
141141
symbol_tablet &symbol_table,
142142
const std::string &module,
143-
const bool keep_file_local)
143+
const std::string &keep_file_local)
144144
{
145145
INVARIANT(
146146
false,

src/langapi/language_file.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ bool language_filest::parse()
8282

8383
bool language_filest::typecheck(
8484
symbol_tablet &symbol_table,
85-
const bool keep_file_local)
85+
const std::string &keep_file_local)
8686
{
8787
// typecheck interfaces
8888

@@ -204,7 +204,7 @@ bool language_filest::interfaces(
204204
bool language_filest::typecheck_module(
205205
symbol_tablet &symbol_table,
206206
const std::string &module,
207-
const bool keep_file_local)
207+
const std::string &keep_file_local)
208208
{
209209
// check module map
210210

@@ -222,7 +222,7 @@ bool language_filest::typecheck_module(
222222
bool language_filest::typecheck_module(
223223
symbol_tablet &symbol_table,
224224
language_modulet &module,
225-
const bool keep_file_local)
225+
const std::string &keep_file_local)
226226
{
227227
// already typechecked?
228228

src/langapi/language_file.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -108,8 +108,9 @@ class language_filest:public messaget
108108

109109
bool generate_support_functions(symbol_tablet &symbol_table);
110110

111-
bool
112-
typecheck(symbol_tablet &symbol_table, const bool keep_file_local = false);
111+
bool typecheck(
112+
symbol_tablet &symbol_table,
113+
const std::string &keep_file_local = "");
113114

114115
bool final(symbol_table_baset &symbol_table);
115116

@@ -144,12 +145,12 @@ class language_filest:public messaget
144145
bool typecheck_module(
145146
symbol_tablet &symbol_table,
146147
language_modulet &module,
147-
const bool keep_file_local);
148+
const std::string &keep_file_local);
148149

149150
bool typecheck_module(
150151
symbol_tablet &symbol_table,
151152
const std::string &module,
152-
const bool keep_file_local);
153+
const std::string &keep_file_local);
153154
};
154155

155156
#endif // CPROVER_UTIL_LANGUAGE_FILE_H

src/linking/remove_internal_symbols.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ Author: Daniel Kroening
2222

2323
#include "static_lifetime_init.h"
2424

25+
#include <regex>
26+
2527
static void get_symbols(
2628
const namespacet &ns,
2729
const symbolt &in_symbol,
@@ -99,12 +101,12 @@ static void get_symbols(
99101
/// on "extern inline"
100102
/// \param symbol_table: symbol table to clean up
101103
/// \param mh: log handler
102-
/// \param keep_file_local: keep file-local functions with bodies even if we
104+
/// \param keep_file_local: regular expression over symbols to keep even if we
103105
/// would otherwise remove them
104106
void remove_internal_symbols(
105107
symbol_tablet &symbol_table,
106108
message_handlert &mh,
107-
const bool keep_file_local)
109+
const std::string &keep_file_local)
108110
{
109111
namespacet ns(symbol_table);
110112
find_symbols_sett exported;
@@ -176,7 +178,9 @@ void remove_internal_symbols(
176178
{
177179
get_symbols(ns, symbol, exported);
178180
}
179-
else if(has_body && is_file_local && keep_file_local)
181+
else if(
182+
has_body && is_file_local && !keep_file_local.empty() &&
183+
std::regex_match(id2string(symbol.name), std::regex(keep_file_local)))
180184
{
181185
get_symbols(ns, symbol, exported);
182186
}

src/linking/remove_internal_symbols.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,13 @@ Author: Daniel Kroening
1212
#ifndef CPROVER_LINKING_REMOVE_INTERNAL_SYMBOLS_H
1313
#define CPROVER_LINKING_REMOVE_INTERNAL_SYMBOLS_H
1414

15+
#include <string>
16+
1517
class message_handlert;
1618

1719
void remove_internal_symbols(
1820
class symbol_tablet &symbol_table,
1921
message_handlert &,
20-
const bool);
22+
const std::string &);
2123

2224
#endif // CPROVER_LINKING_REMOVE_INTERNAL_SYMBOLS_H

src/statement-list/statement_list_language.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ bool statement_list_languaget::generate_support_functions(
3636
bool statement_list_languaget::typecheck(
3737
symbol_tablet &symbol_table,
3838
const std::string &module,
39-
const bool keep_file_local)
39+
const std::string &keep_file_local)
4040
{
4141
symbol_tablet new_symbol_table;
4242

@@ -85,7 +85,7 @@ bool statement_list_languaget::typecheck(
8585
symbol_tablet &symbol_table,
8686
const std::string &module)
8787
{
88-
return typecheck(symbol_table, module, true);
88+
return typecheck(symbol_table, module, ".*");
8989
}
9090

9191
bool statement_list_languaget::from_expr(

0 commit comments

Comments
 (0)