Skip to content

Commit 8e72373

Browse files
committed
Add source location to invalid_source_file_exceptiont
This enables proper use in the C front-end in a way that is compatible with the compiler-specific message handlers in goto-cc: those message handlers generate source-location output that mimics that of the compiler being emulated. As future work it is thus possible to remove all "throw 0" instances from the C front-end.
1 parent 7072829 commit 8e72373

17 files changed

+118
-71
lines changed

regression/ansi-c/enum_is_in_range/enum_test10.desc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
CORE
22
enum_test10.c
33

4-
^EXIT=(6|70)$
4+
^EXIT=(1|64)$
55
^SIGNAL=0$
6-
^file enum_test10.c line \d+ function main: __CPROVER_enum_is_in_range expects enum, but \(i\) has type `signed int`$
6+
__CPROVER_enum_is_in_range expects enum, but \(i\) has type `signed int`$
77
--
88
^\[main.assertion.1\] line \d+ assertion __CPROVER_enum_is_in_range\(i\): SUCCESS$
99
^\[main.assertion.1\] line \d+ assertion __CPROVER_enum_is_in_range\(i\): FAILURE$

regression/ansi-c/enum_is_in_range/enum_test12.desc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
CORE
22
enum_test12.c
33

4-
^EXIT=(6|70)$
4+
^EXIT=(1|64)$
55
^SIGNAL=0$
6-
^file enum_test12.c line \d+ function main: __CPROVER_enum_is_in_range takes exactly 1 argument, but 2 were provided$
6+
__CPROVER_enum_is_in_range takes exactly 1 argument, but 2 were provided$
77
--
88
^\[main.assertion.1\] line \d+ assertion __CPROVER_enum_is_in_range\(.*\): SUCCESS$
99
^\[main.assertion.1\] line \d+ assertion __CPROVER_enum_is_in_range\(.*\): FAILURE$

src/ansi-c/ansi_c_typecheck.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,5 +67,11 @@ bool ansi_c_typecheck(
6767
ansi_c_typecheck.error() << e << messaget::eom;
6868
}
6969

70+
catch(const invalid_source_file_exceptiont &e)
71+
{
72+
ansi_c_typecheck.error().source_location = e.get_source_location();
73+
ansi_c_typecheck.error() << e.get_reason() << messaget::eom;
74+
}
75+
7076
return message_handler.get_message_count(messaget::M_ERROR)!=errors_before;
7177
}

src/ansi-c/c_typecheck_expr.cpp

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3147,21 +3147,22 @@ exprt c_typecheck_baset::do_special_functions(
31473147
if(expr.arguments().size() != 1)
31483148
{
31493149
std::ostringstream error_message;
3150-
error_message << expr.source_location().as_string() << ": " << identifier
3151-
<< " takes exactly 1 argument, but "
3150+
error_message << identifier << " takes exactly 1 argument, but "
31523151
<< expr.arguments().size() << " were provided";
3153-
throw invalid_source_file_exceptiont{error_message.str()};
3152+
throw invalid_source_file_exceptiont{error_message.str(),
3153+
expr.source_location()};
31543154
}
31553155
auto arg1 = expr.arguments()[0];
31563156
typecheck_expr(arg1);
31573157
if(!can_cast_type<c_enum_tag_typet>(arg1.type()))
31583158
{
31593159
// Can't enum range check a non-enum
31603160
std::ostringstream error_message;
3161-
error_message << expr.source_location().as_string() << ": " << identifier
3162-
<< " expects enum, but (" << expr2c(arg1, *this)
3163-
<< ") has type `" << type2c(arg1.type(), *this) << '`';
3164-
throw invalid_source_file_exceptiont{error_message.str()};
3161+
error_message << identifier << " expects enum, but ("
3162+
<< expr2c(arg1, *this) << ") has type `"
3163+
<< type2c(arg1.type(), *this) << '`';
3164+
throw invalid_source_file_exceptiont{error_message.str(),
3165+
expr.source_location()};
31653166
}
31663167
else
31673168
{
@@ -3180,10 +3181,10 @@ exprt c_typecheck_baset::do_special_functions(
31803181
if(expr.arguments().size() != 3)
31813182
{
31823183
std::ostringstream error_message;
3183-
error_message << expr.source_location().as_string() << ": " << identifier
3184-
<< " takes exactly 3 arguments, but "
3184+
error_message << identifier << " takes exactly 3 arguments, but "
31853185
<< expr.arguments().size() << " were provided";
3186-
throw invalid_source_file_exceptiont{error_message.str()};
3186+
throw invalid_source_file_exceptiont{error_message.str(),
3187+
expr.source_location()};
31873188
}
31883189

31893190
typecheck_function_call_arguments(expr);
@@ -3199,14 +3200,14 @@ exprt c_typecheck_baset::do_special_functions(
31993200
[this, identifier](
32003201
const exprt &wrong_argument, std::size_t argument_number, bool _p) {
32013202
std::ostringstream error_message;
3202-
error_message << wrong_argument.source_location().as_string() << ": "
3203-
<< identifier << " has signature " << identifier
3203+
error_message << identifier << " has signature " << identifier
32043204
<< "(integral, integral, integral" << (_p ? "" : "*")
32053205
<< "), "
32063206
<< "but argument " << argument_number << " ("
32073207
<< expr2c(wrong_argument, *this) << ") has type `"
32083208
<< type2c(wrong_argument.type(), *this) << '`';
3209-
throw invalid_source_file_exceptiont{error_message.str()};
3209+
throw invalid_source_file_exceptiont{
3210+
error_message.str(), wrong_argument.source_location()};
32103211
};
32113212
for(int arg_index = 0; arg_index <= (!is__p_variant ? 1 : 2); ++arg_index)
32123213
{

src/ansi-c/c_typecheck_type.cpp

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1198,10 +1198,9 @@ void c_typecheck_baset::typecheck_c_enum_type(typet &type)
11981198
if(!is_signed_or_unsigned_bitvector(underlying_type))
11991199
{
12001200
std::ostringstream msg;
1201-
msg << source_location << ": non-integral type '"
1202-
<< underlying_type.get(ID_C_c_type)
1201+
msg << "non-integral type '" << underlying_type.get(ID_C_c_type)
12031202
<< "' is an invalid underlying type";
1204-
throw invalid_source_file_exceptiont{msg.str()};
1203+
throw invalid_source_file_exceptiont{msg.str(), source_location};
12051204
}
12061205
}
12071206

@@ -1260,11 +1259,9 @@ void c_typecheck_baset::typecheck_c_enum_type(typet &type)
12601259
if(value < tmp.smallest() || value > tmp.largest())
12611260
{
12621261
std::ostringstream msg;
1263-
msg
1264-
<< v.source_location()
1265-
<< ": enumerator value is not representable in the underlying type '"
1266-
<< constant_type.get(ID_C_c_type) << "'";
1267-
throw invalid_source_file_exceptiont{msg.str()};
1262+
msg << "enumerator value is not representable in the underlying type '"
1263+
<< constant_type.get(ID_C_c_type) << "'";
1264+
throw invalid_source_file_exceptiont{msg.str(), v.source_location()};
12681265
}
12691266
}
12701267
else

src/ansi-c/literals/convert_character_literal.cpp

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ Author: Daniel Kroening, [email protected]
2020

2121
exprt convert_character_literal(
2222
const std::string &src,
23-
bool force_integer_type)
23+
bool force_integer_type,
24+
const source_locationt &source_location)
2425
{
2526
assert(src.size()>=2);
2627

@@ -60,8 +61,10 @@ exprt convert_character_literal(
6061
result=from_integer(x, type);
6162
}
6263
else
63-
throw "wide literals with "+std::to_string(value.size())+
64-
" characters are not supported";
64+
throw invalid_source_file_exceptiont{"wide literals with " +
65+
std::to_string(value.size()) +
66+
" characters are not supported",
67+
source_location};
6568
}
6669
else
6770
{
@@ -93,9 +96,12 @@ exprt convert_character_literal(
9396
result=from_integer(x, signed_int_type());
9497
}
9598
else
96-
throw "literals with "+std::to_string(value.size())+
97-
" characters are not supported";
99+
throw invalid_source_file_exceptiont{"literals with " +
100+
std::to_string(value.size()) +
101+
" characters are not supported",
102+
source_location};
98103
}
99104

105+
result.add_source_location() = source_location;
100106
return result;
101107
}

src/ansi-c/literals/convert_character_literal.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ Author: Daniel Kroening, [email protected]
2121

2222
exprt convert_character_literal(
2323
const std::string &src,
24-
bool force_integer_type);
24+
bool force_integer_type,
25+
const source_locationt &source_location);
2526

2627
#endif // CPROVER_ANSI_C_LITERALS_CONVERT_CHARACTER_LITERAL_H

src/ansi-c/scanner.l

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -308,8 +308,8 @@ void ansi_c_scanner_init()
308308

309309
<GRAMMAR>{char_lit} {
310310
newstack(yyansi_clval);
311-
parser_stack(yyansi_clval)=convert_character_literal(yytext, true);
312-
PARSER.set_source_location(parser_stack(yyansi_clval));
311+
source_locationt l=parser_stack(yyansi_clval).source_location();
312+
parser_stack(yyansi_clval)=convert_character_literal(yytext, true, l);
313313
return TOK_CHARACTER;
314314
}
315315

src/cpp/cpp_typecheck.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,12 @@ bool cpp_typecheck(
128128
cpp_typecheck.error() << e << messaget::eom;
129129
}
130130

131+
catch(const invalid_source_file_exceptiont &e)
132+
{
133+
cpp_typecheck.error().source_location = e.get_source_location();
134+
cpp_typecheck.error() << e.get_reason() << messaget::eom;
135+
}
136+
131137
return message_handler.get_message_count(messaget::M_ERROR)!=errors_before;
132138
}
133139

src/crangler/mini_c_parser.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -236,8 +236,12 @@ mini_c_parsert::tokenst mini_c_parsert::parse_pre_declarator()
236236
else if(token == '(') // function type, part of declarator
237237
return result;
238238
else
239+
{
240+
source_locationt loc;
241+
loc.set_line(token.line_number);
239242
throw invalid_source_file_exceptiont(
240-
"expected a declaration but got '" + token.text + "'");
243+
"expected a declaration but got '" + token.text + "'", loc);
244+
}
241245
}
242246
}
243247

@@ -263,7 +267,11 @@ mini_c_parsert::tokenst mini_c_parsert::parse_declarator()
263267
return {consume_token()};
264268
}
265269
else
266-
throw invalid_source_file_exceptiont("expected an identifier");
270+
{
271+
source_locationt loc;
272+
loc.set_line(peek().line_number);
273+
throw invalid_source_file_exceptiont("expected an identifier", loc);
274+
}
267275
}
268276

269277
mini_c_parsert::tokenst mini_c_parsert::parse_post_declarator()

src/goto-cc/goto_cc_mode.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,15 @@ int goto_cc_modet::main(int argc, const char **argv)
111111
log.error() << "Out of memory" << messaget::eom;
112112
return EX_SOFTWARE;
113113
}
114+
115+
catch(const invalid_source_file_exceptiont &e)
116+
{
117+
messaget log{message_handler};
118+
log.error().source_location = e.get_source_location();
119+
log.error() << e.get_reason() << messaget::eom;
120+
return EX_SOFTWARE;
121+
}
122+
114123
catch(const cprover_exception_baset &e)
115124
{
116125
messaget log{message_handler};

src/goto-programs/string_instrumentation.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,7 @@ void string_instrumentationt::do_sprintf(
265265
{
266266
if(arguments.size()<2)
267267
{
268-
throw incorrect_source_program_exceptiont(
268+
throw invalid_source_file_exceptiont(
269269
"sprintf expected to have two or more arguments",
270270
target->source_location());
271271
}
@@ -301,7 +301,7 @@ void string_instrumentationt::do_snprintf(
301301
{
302302
if(arguments.size()<3)
303303
{
304-
throw incorrect_source_program_exceptiont(
304+
throw invalid_source_file_exceptiont(
305305
"snprintf expected to have three or more arguments",
306306
target->source_location());
307307
}
@@ -338,7 +338,7 @@ void string_instrumentationt::do_fscanf(
338338
{
339339
if(arguments.size()<2)
340340
{
341-
throw incorrect_source_program_exceptiont(
341+
throw invalid_source_file_exceptiont(
342342
"fscanf expected to have two or more arguments",
343343
target->source_location());
344344
}
@@ -614,7 +614,7 @@ void string_instrumentationt::do_strchr(
614614
{
615615
if(arguments.size()!=2)
616616
{
617-
throw incorrect_source_program_exceptiont(
617+
throw invalid_source_file_exceptiont(
618618
"strchr expected to have two arguments", target->source_location());
619619
}
620620

@@ -638,7 +638,7 @@ void string_instrumentationt::do_strrchr(
638638
{
639639
if(arguments.size()!=2)
640640
{
641-
throw incorrect_source_program_exceptiont(
641+
throw invalid_source_file_exceptiont(
642642
"strrchr expected to have two arguments", target->source_location());
643643
}
644644

@@ -662,7 +662,7 @@ void string_instrumentationt::do_strstr(
662662
{
663663
if(arguments.size()!=2)
664664
{
665-
throw incorrect_source_program_exceptiont(
665+
throw invalid_source_file_exceptiont(
666666
"strstr expected to have two arguments", target->source_location());
667667
}
668668

@@ -692,7 +692,7 @@ void string_instrumentationt::do_strtok(
692692
{
693693
if(arguments.size()!=2)
694694
{
695-
throw incorrect_source_program_exceptiont(
695+
throw invalid_source_file_exceptiont(
696696
"strtok expected to have two arguments", target->source_location());
697697
}
698698

src/goto-programs/string_instrumentation.h

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -12,33 +12,12 @@ Author: Daniel Kroening, [email protected]
1212
#ifndef CPROVER_GOTO_PROGRAMS_STRING_INSTRUMENTATION_H
1313
#define CPROVER_GOTO_PROGRAMS_STRING_INSTRUMENTATION_H
1414

15-
#include <util/exception_utils.h>
16-
1715
class exprt;
1816
class goto_functionst;
1917
class goto_modelt;
2018
class goto_programt;
2119
class symbol_tablet;
2220

23-
class incorrect_source_program_exceptiont : public cprover_exception_baset
24-
{
25-
public:
26-
incorrect_source_program_exceptiont(
27-
std::string message,
28-
source_locationt source_location)
29-
: cprover_exception_baset(std::move(message)),
30-
source_location(std::move(source_location))
31-
{
32-
}
33-
std::string what() const override
34-
{
35-
return reason + " (at: " + source_location.as_string() + ")";
36-
}
37-
38-
private:
39-
source_locationt source_location;
40-
};
41-
4221
void string_instrumentation(
4322
symbol_tablet &,
4423
goto_programt &);

src/symtab2gb/symtab2gb_parse_options.cpp

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -77,14 +77,18 @@ static void run_symtab2gb(
7777
auto &symtab_file = symtab_files[ix];
7878
if(failed(symtab_language->parse(symtab_file, symtab_filename)))
7979
{
80-
throw invalid_source_file_exceptiont{
81-
"failed to parse symbol table from file '" + symtab_filename + "'"};
80+
source_locationt source_location;
81+
source_location.set_file(symtab_filename);
82+
throw invalid_source_file_exceptiont{"failed to parse symbol table",
83+
source_location};
8284
}
8385
symbol_tablet symtab{};
8486
if(failed(symtab_language->typecheck(symtab, "<unused>")))
8587
{
86-
throw invalid_source_file_exceptiont{
87-
"failed to typecheck symbol table from file '" + symtab_filename + "'"};
88+
source_locationt source_location;
89+
source_location.set_file(symtab_filename);
90+
throw invalid_source_file_exceptiont{"failed to typecheck symbol table",
91+
source_location};
8892
}
8993
config.set_from_symbol_table(symtab);
9094

src/util/exception_utils.cpp

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,14 @@ invalid_input_exceptiont::invalid_input_exceptiont(std::string reason)
8686
}
8787

8888
invalid_source_file_exceptiont::invalid_source_file_exceptiont(
89-
std::string reason)
90-
: cprover_exception_baset(std::move(reason))
89+
std::string reason,
90+
source_locationt source_location)
91+
: invalid_input_exceptiont(std::move(reason)),
92+
source_location(std::move(source_location))
93+
{
94+
}
95+
96+
std::string invalid_source_file_exceptiont::what() const
9197
{
98+
return source_location.as_string() + ": " + reason;
9299
}

0 commit comments

Comments
 (0)