Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 32 additions & 1 deletion src/solvers/smt2/smt2_conv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2707,8 +2707,24 @@ void smt2_convt::convert_expr(const exprt &expr)
else if(expr.id() == ID_function_application)
{
const auto &function_application_expr = to_function_application_expr(expr);

// Check for string operations by looking at the function symbol name
std::string fn_name;
if(function_application_expr.function().id() == ID_symbol)
fn_name = id2string(
to_symbol_expr(function_application_expr.function()).get_identifier());

if(fn_name == "Str.Concat" &&
function_application_expr.arguments().size() == 2)
{
out << "(str.++ ";
convert_expr(function_application_expr.arguments()[0]);
out << ' ';
convert_expr(function_application_expr.arguments()[1]);
Comment on lines +2717 to +2723
Copy link

Copilot AI Feb 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The str.++ (string concatenation) operation in SMT-LIB 2 can take any number of arguments (including 0, 1, or more than 2), but this implementation only handles exactly 2 arguments. When there are != 2 arguments, it falls through to the else case which will output "Str.Concat" instead of "str.++". Consider removing the size check or handling variable numbers of arguments to ensure all Str.Concat calls are properly converted to str.++.

Suggested change
if(fn_name == "Str.Concat" &&
function_application_expr.arguments().size() == 2)
{
out << "(str.++ ";
convert_expr(function_application_expr.arguments()[0]);
out << ' ';
convert_expr(function_application_expr.arguments()[1]);
if(fn_name == "Str.Concat")
{
out << "(str.++";
for(const auto &op : function_application_expr.arguments())
{
out << ' ';
convert_expr(op);
}

Copilot uses AI. Check for mistakes.
out << ')';
}
// do not use parentheses if there function is a constant
if(function_application_expr.arguments().empty())
else if(function_application_expr.arguments().empty())
{
convert_expr(function_application_expr.function());
}
Expand Down Expand Up @@ -3763,6 +3779,19 @@ void smt2_convt::convert_constant(const constant_exprt &expr)
out << "(_ bv" << (value_int - range_type.get_from()) << " " << width
<< ")";
}
else if(expr_type.id()==ID_string)
{
const std::string &value = id2string(expr.get_value());
out << "\"";
for(char c : value)
{
if(c == '"')
out << "\"\"";
else
out << c;
}
out << "\"";
}
else
UNEXPECTEDCASE("unknown constant: "+expr_type.id_string());
}
Expand Down Expand Up @@ -5991,6 +6020,8 @@ void smt2_convt::convert_type(const typet &type)
UNEXPECTEDCASE("unsuppored range type");
out << "(_ BitVec " << address_bits(size) << ")";
}
else if(type.id()==ID_string)
Copy link

Copilot AI Feb 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inconsistent spacing around the == operator. The codebase convention in this file is to use no spaces (e.g., type.id()==ID_string on line 6025, expr_type.id()==ID_string on line 3782). This line has spaces around == which is inconsistent with the rest of the file.

Copilot uses AI. Check for mistakes.
out << "String";
else
{
UNEXPECTEDCASE("unsupported type: "+type.id_string());
Expand Down
Loading