Skip to content

Commit 388591b

Browse files
committed
Re-use known declarations when parsing the built-in library
When doing cross-platform verification we should not rely on 1) system headers being present and 2) system headers matching the declarations that were used while compiling the program to be verified. Thus re-use the symbol table that has been generated from the input program when compiling functions of the built-in library. This will address a number of SV-COMP benchmarks that CBMC currently fails on for they use augmented standard-library types.
1 parent 768e8a6 commit 388591b

File tree

10 files changed

+107
-16
lines changed

10 files changed

+107
-16
lines changed

regression/cbmc/library1/main.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
struct _IO_FILE;
2+
typedef struct _IO_FILE FILE;
3+
struct _IO_FILE
4+
{
5+
char dummy;
6+
};
7+
8+
extern FILE *fopen(char const* fname, char const* mode);
9+
10+
int main()
11+
{
12+
FILE *f;
13+
f = fopen("some_file", "r");
14+
__CPROVER_assert(f == 0, "");
15+
return 0;
16+
}

regression/cbmc/library1/test.desc

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
CORE
2+
main.c
3+
4+
^EXIT=10$
5+
^SIGNAL=0$
6+
^VERIFICATION FAILED$
7+
--
8+
^warning: ignoring
9+
implicit function declaration
10+
syntax error

src/ansi-c/ansi_c_language.cpp

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ Author: Daniel Kroening, [email protected]
1414

1515
#include <util/config.h>
1616
#include <util/get_base_name.h>
17+
#include <util/find_symbols.h>
1718

1819
#include <linking/linking.h>
1920
#include <linking/remove_internal_symbols.h>
@@ -52,6 +53,15 @@ bool ansi_c_languaget::preprocess(
5253
bool ansi_c_languaget::parse(
5354
std::istream &instream,
5455
const std::string &path)
56+
{
57+
symbol_tablet st;
58+
return parse(instream, path, st);
59+
}
60+
61+
bool ansi_c_languaget::parse(
62+
std::istream &instream,
63+
const std::string &path,
64+
const symbol_tablet &symbol_table)
5565
{
5666
// store the path
5767
parse_path=path;
@@ -78,6 +88,7 @@ bool ansi_c_languaget::parse(
7888
ansi_c_parser.cpp98=false; // it's not C++
7989
ansi_c_parser.cpp11=false; // it's not C++
8090
ansi_c_parser.mode=config.ansi_c.mode;
91+
ansi_c_parser.set_symbol_table(symbol_table);
8192

8293
ansi_c_scanner_init();
8394

@@ -95,6 +106,27 @@ bool ansi_c_languaget::parse(
95106
// save result
96107
parse_tree.swap(ansi_c_parser.parse_tree);
97108

109+
// copy depended-on symbols from the existing symbol table
110+
std::list<irep_idt> needed_syms;
111+
for(const auto &scope_syms : ansi_c_parser.root_scope().name_map)
112+
{
113+
if(scope_syms.second.from_symbol_table)
114+
needed_syms.push_back(scope_syms.second.prefixed_name);
115+
}
116+
while(!needed_syms.empty())
117+
{
118+
const irep_idt id = needed_syms.front();
119+
needed_syms.pop_front();
120+
const symbolt &symbol = symbol_table.lookup_ref(id);
121+
122+
if(symbol.is_type && !new_symbol_table.add(symbol))
123+
{
124+
find_symbols_sett deps;
125+
find_type_symbols(symbol.type, deps);
126+
needed_syms.insert(needed_syms.end(), deps.begin(), deps.end());
127+
}
128+
}
129+
98130
// save some memory
99131
ansi_c_parser.clear();
100132

@@ -105,8 +137,6 @@ bool ansi_c_languaget::typecheck(
105137
symbol_tablet &symbol_table,
106138
const std::string &module)
107139
{
108-
symbol_tablet new_symbol_table;
109-
110140
if(ansi_c_typecheck(
111141
parse_tree,
112142
new_symbol_table,
@@ -118,10 +148,10 @@ bool ansi_c_languaget::typecheck(
118148

119149
remove_internal_symbols(new_symbol_table);
120150

121-
if(linking(symbol_table, new_symbol_table, get_message_handler()))
122-
return true;
151+
bool retval = linking(symbol_table, new_symbol_table, get_message_handler());
152+
new_symbol_table.clear();
123153

124-
return false;
154+
return retval;
125155
}
126156

127157
bool ansi_c_languaget::generate_support_functions(
@@ -196,6 +226,7 @@ bool ansi_c_languaget::to_expr(
196226
ansi_c_parser.in=&i_preprocessed;
197227
ansi_c_parser.set_message_handler(get_message_handler());
198228
ansi_c_parser.mode=config.ansi_c.mode;
229+
ansi_c_parser.set_symbol_table(ns.get_symbol_table());
199230
ansi_c_scanner_init();
200231

201232
bool result=ansi_c_parser.parse();

src/ansi-c/ansi_c_language.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ Author: Daniel Kroening, [email protected]
1313
#include <memory>
1414

1515
#include <util/make_unique.h>
16+
#include <util/symbol_table.h>
1617

1718
#include <langapi/language.h>
1819

@@ -30,6 +31,9 @@ class ansi_c_languaget:public languaget
3031
std::istream &instream,
3132
const std::string &path) override;
3233

34+
bool
35+
parse(std::istream &instream, const std::string &path, const symbol_tablet &);
36+
3337
bool generate_support_functions(
3438
symbol_tablet &symbol_table) override;
3539

@@ -75,6 +79,7 @@ class ansi_c_languaget:public languaget
7579
protected:
7680
ansi_c_parse_treet parse_tree;
7781
std::string parse_path;
82+
symbol_tablet new_symbol_table;
7883
};
7984

8085
std::unique_ptr<languaget> new_ansi_c_language();

src/ansi-c/ansi_c_parser.cpp

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ Author: Daniel Kroening, [email protected]
88

99
#include "ansi_c_parser.h"
1010

11-
#include <iostream>
11+
#include <util/symbol_table.h>
1212

1313
#include "c_storage_spec.h"
1414

@@ -42,6 +42,24 @@ ansi_c_id_classt ansi_c_parsert::lookup(
4242
}
4343
}
4444

45+
// if a symbol table has been provided, try to resolve global-scoped symbols
46+
if(!tag && !label && symbol_table)
47+
{
48+
const symbolt *symbol = symbol_table->lookup(scope_name);
49+
if(symbol)
50+
{
51+
ansi_c_identifiert &i = root_scope().name_map[scope_name];
52+
i.from_symbol_table = true;
53+
i.id_class = symbol->is_type && symbol->is_macro
54+
? ansi_c_id_classt::ANSI_C_TYPEDEF
55+
: ansi_c_id_classt::ANSI_C_SYMBOL;
56+
i.prefixed_name = symbol->name;
57+
i.base_name = symbol->base_name;
58+
identifier = i.prefixed_name;
59+
return i.id_class;
60+
}
61+
}
62+
4563
// Not found.
4664
// If it's a tag, we will add to current scope.
4765
if(tag)

src/ansi-c/ansi_c_parser.h

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ class ansi_c_parsert:public parsert
3535
mode(modet::NONE),
3636
cpp98(false),
3737
cpp11(false),
38-
for_has_scope(false)
38+
for_has_scope(false),
39+
symbol_table(nullptr)
3940
{
4041
}
4142

@@ -59,6 +60,8 @@ class ansi_c_parsert:public parsert
5960
// set up global scope
6061
scopes.clear();
6162
scopes.push_back(scopet());
63+
64+
symbol_table = nullptr;
6265
}
6366

6467
// internal state of the scanner
@@ -139,6 +142,14 @@ class ansi_c_parsert:public parsert
139142
lookup(base_name, identifier, false, true);
140143
return identifier;
141144
}
145+
146+
void set_symbol_table(const symbol_tablet &st)
147+
{
148+
symbol_table = &st;
149+
}
150+
151+
private:
152+
const symbol_tablet *symbol_table;
142153
};
143154

144155
extern ansi_c_parsert ansi_c_parser;

src/ansi-c/ansi_c_scope.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,11 @@ class ansi_c_identifiert
2929
{
3030
public:
3131
ansi_c_id_classt id_class;
32+
bool from_symbol_table;
3233
irep_idt base_name, prefixed_name;
3334

34-
ansi_c_identifiert():id_class(ansi_c_id_classt::ANSI_C_UNKNOWN)
35+
ansi_c_identifiert()
36+
: id_class(ansi_c_id_classt::ANSI_C_UNKNOWN), from_symbol_table(false)
3537
{
3638
}
3739
};

src/ansi-c/c_typecheck_type.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -785,7 +785,7 @@ void c_typecheck_baset::typecheck_compound_type(struct_union_typet &type)
785785
symbol_table.get_writeable_ref(s_it->first).type.swap(type);
786786
}
787787
}
788-
else if(have_body)
788+
else if(have_body && type != s_it->second.type)
789789
{
790790
error().source_location=type.source_location();
791791
error() << "redefinition of body of `"

src/ansi-c/cprover_library.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ Author: Daniel Kroening, [email protected]
1414

1515
#include "ansi_c_language.h"
1616

17+
static void
18+
add_library(const std::string &src, symbol_tablet &, message_handlert &);
19+
1720
struct cprover_library_entryt
1821
{
1922
const char *function;
@@ -78,7 +81,7 @@ void add_cprover_library(
7881
add_library(library_text, symbol_table, message_handler);
7982
}
8083

81-
void add_library(
84+
static void add_library(
8285
const std::string &src,
8386
symbol_tablet &symbol_table,
8487
message_handlert &message_handler)
@@ -90,7 +93,7 @@ void add_library(
9093

9194
ansi_c_languaget ansi_c_language;
9295
ansi_c_language.set_message_handler(message_handler);
93-
ansi_c_language.parse(in, "");
96+
ansi_c_language.parse(in, "", symbol_table);
9497

9598
ansi_c_language.typecheck(symbol_table, "<built-in-library>");
9699
}

src/ansi-c/cprover_library.h

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,6 @@ std::string get_cprover_library_text(
1919
const std::set<irep_idt> &functions,
2020
const symbol_tablet &);
2121

22-
void add_library(
23-
const std::string &src,
24-
symbol_tablet &,
25-
message_handlert &);
26-
2722
void add_cprover_library(
2823
const std::set<irep_idt> &functions,
2924
symbol_tablet &,

0 commit comments

Comments
 (0)