Skip to content

Commit 8412bdf

Browse files
committed
Move disjunction construction to goto conversion
This moves the construction of the disjunction that does the actual enum_is_in_range checks into the goto conversion part of the code (and correctly removes it from the type checking).
1 parent e51d2df commit 8412bdf

File tree

3 files changed

+42
-20
lines changed

3 files changed

+42
-20
lines changed

src/ansi-c/c_typecheck_expr.cpp

Lines changed: 5 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2852,28 +2852,9 @@ exprt c_typecheck_baset::do_special_functions(
28522852
<< expr.arguments().size() << " were provided";
28532853
throw invalid_source_file_exceptiont{error_message.str()};
28542854
}
2855-
// Replace expr with giant boolean that checks all the values
2856-
// of the enumeration as disjunction
2857-
// This code is similar to goto_checkt::enum_range_check
28582855
auto arg1 = expr.arguments()[0];
28592856
typecheck_expr(arg1);
2860-
if(
2861-
auto c_enum_tag_type =
2862-
type_try_dynamic_cast<c_enum_tag_typet>(arg1.type()))
2863-
{
2864-
const c_enum_typet &c_enum_type = follow_tag(*c_enum_tag_type);
2865-
const c_enum_typet::memberst enum_values = c_enum_type.members();
2866-
2867-
std::vector<exprt> disjuncts;
2868-
for(const auto &enum_value : enum_values)
2869-
{
2870-
constant_exprt val{enum_value.get_value(), *c_enum_tag_type};
2871-
disjuncts.push_back(equal_exprt(arg1, std::move(val)));
2872-
}
2873-
2874-
return disjunction(disjuncts);
2875-
}
2876-
else
2857+
if(!can_cast_type<c_enum_tag_typet>(arg1.type()))
28772858
{
28782859
// Can't enum range check a non-enum
28792860
std::ostringstream error_message;
@@ -2882,6 +2863,10 @@ exprt c_typecheck_baset::do_special_functions(
28822863
<< ") has type `" << type2c(arg1.type(), *this) << '`';
28832864
throw invalid_source_file_exceptiont{error_message.str()};
28842865
}
2866+
else
2867+
{
2868+
return expr;
2869+
}
28852870
}
28862871
else if(
28872872
identifier == "__builtin_add_overflow" ||

src/goto-programs/builtin_functions.cpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -610,6 +610,34 @@ exprt make_va_list(const exprt &expr)
610610
return result;
611611
}
612612

613+
void goto_convertt::do_enum_is_in_range(
614+
const exprt &lhs,
615+
const symbol_exprt &function,
616+
const exprt::operandst &arguments,
617+
goto_programt &dest)
618+
{
619+
PRECONDITION(arguments.size() == 1);
620+
const auto enum_expr = arguments.front();
621+
const auto enum_type =
622+
type_try_dynamic_cast<c_enum_tag_typet>(enum_expr.type());
623+
PRECONDITION(enum_type);
624+
const c_enum_typet &c_enum_type = ns.follow_tag(*enum_type);
625+
const c_enum_typet::memberst enum_values = c_enum_type.members();
626+
627+
std::vector<exprt> disjuncts;
628+
for(const auto &enum_value : enum_values)
629+
{
630+
constant_exprt val{enum_value.get_value(), *enum_type};
631+
disjuncts.push_back(equal_exprt(enum_expr, std::move(val)));
632+
}
633+
634+
const auto disjunction = ::disjunction(disjuncts);
635+
636+
code_assignt assignment(lhs, disjunction);
637+
assignment.add_source_location() = function.source_location();
638+
copy(assignment, ASSIGN, dest);
639+
}
640+
613641
/// add function calls to function queue for later processing
614642
void goto_convertt::do_function_call_symbol(
615643
const exprt &lhs,
@@ -734,6 +762,10 @@ void goto_convertt::do_function_call_symbol(
734762
throw 0;
735763
}
736764
}
765+
else if(identifier == CPROVER_PREFIX "enum_is_in_range")
766+
{
767+
do_enum_is_in_range(lhs, function, arguments, dest);
768+
}
737769
else if(
738770
identifier == CPROVER_PREFIX "assert" ||
739771
identifier == CPROVER_PREFIX "precondition" ||

src/goto-programs/goto_convert_class.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -589,6 +589,11 @@ class goto_convertt:public messaget
589589
exprt get_constant(const exprt &expr);
590590

591591
// some built-in functions
592+
void do_enum_is_in_range(
593+
const exprt &lhs,
594+
const symbol_exprt &function,
595+
const exprt::operandst &arguments,
596+
goto_programt &dest);
592597
void do_atomic_begin(
593598
const exprt &lhs,
594599
const symbol_exprt &function,

0 commit comments

Comments
 (0)