Skip to content

Commit f5cadb0

Browse files
author
Nathan Wetzler
committed
Populate function name in source locations for function contracts
Added function to C type-checking class that will recursively set the function name in source locations of function contract declaration expressions. Previously, function contract declarations would not store an associated function name in the source location because the function name was not known during parsing. CBMC Viewer reports a failure when analyzing the incomplete coverage report, causing the CMBC Starter Kit to fail during a standard build. Also removed source location from "end function" command during contract checking and added proper source location to function contract instrumentation. Resolves issue #7032
1 parent 6766bc4 commit f5cadb0

File tree

3 files changed

+33
-6
lines changed

3 files changed

+33
-6
lines changed

src/ansi-c/c_typecheck_base.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -674,6 +674,28 @@ void c_typecheck_baset::apply_asm_label(
674674
}
675675
}
676676

677+
/// Recursively set function name in source locations of expression
678+
/// tree. The function is not fully defined during parsing of
679+
/// function contract declarations, so type-checking is the first
680+
/// point in time when we can populate the function name in source
681+
/// locations.
682+
/// \param [in,out] expr: An expression, with possible subexpressions
683+
/// as operands.
684+
/// \param function_name: The function name to add to source locations
685+
void c_typecheck_baset::populate_function_in_expr(
686+
exprt &expr,
687+
irep_idt function_name)
688+
{
689+
source_locationt source_location = expr.source_location();
690+
source_location.set_function(function_name);
691+
expr.add_source_location() = source_location;
692+
for(exprt &e : expr.operands())
693+
{
694+
populate_function_in_expr(e, function_name);
695+
}
696+
return;
697+
}
698+
677699
void c_typecheck_baset::typecheck_declaration(
678700
ansi_c_declarationt &declaration)
679701
{
@@ -833,6 +855,7 @@ void c_typecheck_baset::typecheck_declaration(
833855
typecheck_expr(requires);
834856
implicit_typecast_bool(requires);
835857
check_history_expr(requires);
858+
populate_function_in_expr(requires, identifier);
836859
lambda_exprt lambda{temporary_parameter_symbols, requires};
837860
lambda.add_source_location() = requires.source_location();
838861
requires.swap(lambda);
@@ -841,6 +864,7 @@ void c_typecheck_baset::typecheck_declaration(
841864
typecheck_spec_assigns(code_type.assigns());
842865
for(auto &assigns : code_type.assigns())
843866
{
867+
populate_function_in_expr(assigns, identifier);
844868
lambda_exprt lambda{temporary_parameter_symbols, assigns};
845869
lambda.add_source_location() = assigns.source_location();
846870
assigns.swap(lambda);
@@ -866,6 +890,7 @@ void c_typecheck_baset::typecheck_declaration(
866890
ensures,
867891
ID_loop_entry,
868892
CPROVER_PREFIX "loop_entry is not allowed in postconditions.");
893+
populate_function_in_expr(ensures, identifier);
869894
lambda_exprt lambda{temporary_parameter_symbols, ensures};
870895
lambda.add_source_location() = ensures.source_location();
871896
ensures.swap(lambda);

src/ansi-c/c_typecheck_base.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,9 @@ class c_typecheck_baset:
153153
virtual void typecheck_spec_loop_invariant(codet &code);
154154
virtual void typecheck_spec_decreases(codet &code);
155155

156+
// Recursively set function name in source locations of expression
157+
void populate_function_in_expr(exprt &expr, irep_idt function_name);
158+
156159
bool break_is_allowed;
157160
bool continue_is_allowed;
158161
bool case_is_allowed;

src/goto-instrument/contracts/contracts.cpp

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1382,15 +1382,12 @@ void code_contractst::enforce_contract(const irep_idt &function)
13821382
goto_functions.function_map.erase(old_function);
13831383

13841384
// Place a new symbol with the mangled name into the symbol table
1385-
source_locationt sl;
1386-
sl.set_file("instrumented for code contracts");
1387-
sl.set_line("0");
13881385
symbolt mangled_sym;
13891386
const symbolt *original_sym = symbol_table.lookup(original);
13901387
mangled_sym = *original_sym;
13911388
mangled_sym.name = mangled;
13921389
mangled_sym.base_name = mangled;
1393-
mangled_sym.location = sl;
1390+
mangled_sym.location = original_sym->location;
13941391
const auto mangled_found = symbol_table.insert(std::move(mangled_sym));
13951392
INVARIANT(
13961393
mangled_found.second,
@@ -1414,7 +1411,7 @@ void code_contractst::enforce_contract(const irep_idt &function)
14141411

14151412
goto_functiont &wrapper = goto_functions.function_map[original];
14161413
wrapper.parameter_identifiers = mangled_fun->second.parameter_identifiers;
1417-
wrapper.body.add(goto_programt::make_end_function(sl));
1414+
wrapper.body.add(goto_programt::make_end_function());
14181415
add_contract_check(original, mangled, wrapper.body);
14191416
}
14201417

@@ -1485,7 +1482,9 @@ void code_contractst::add_contract_check(
14851482
// with expressions from the call site (e.g. the return value).
14861483
exprt::operandst instantiation_values;
14871484

1488-
const auto &source_location = function_symbol.location;
1485+
source_locationt source_location = function_symbol.location;
1486+
// Set function in source location to original function
1487+
source_location.set_function(wrapper_function);
14891488

14901489
// decl ret
14911490
optionalt<code_returnt> return_stmt;

0 commit comments

Comments
 (0)