@@ -22,6 +22,7 @@ Author: Daniel Kroening, kroening@cs.cmu.edu
2222#include < util/mathematical_types.h>
2323#include < util/pointer_expr.h>
2424#include < util/pointer_offset_size.h>
25+ #include < util/replace_symbol.h>
2526#include < util/symbol_table_base.h>
2627
2728#include < ansi-c/c_qualifiers.h>
@@ -1825,6 +1826,71 @@ void cpp_typecheckt::typecheck_side_effect_function_call(
18251826
18261827 add_implicit_dereference (expr);
18271828
1829+ if (auto sym_expr = expr_try_dynamic_cast<symbol_exprt>(expr.function ()))
1830+ {
1831+ const auto &symbol = lookup (sym_expr->get_identifier ());
1832+ if (symbol.is_macro )
1833+ {
1834+ // constexpr functions evaluated using a mini interpreter
1835+ const auto &code_type = to_code_type (symbol.type );
1836+ // PRECONDITION(code_type.return_type().id() != ID_empty);
1837+ PRECONDITION (expr.arguments ().size () == code_type.parameters ().size ());
1838+ replace_symbolt value_map;
1839+ auto param_it = code_type.parameters ().begin ();
1840+ for (const auto &arg : expr.arguments ())
1841+ {
1842+ value_map.insert (
1843+ symbol_exprt{param_it->get_identifier (), param_it->type ()},
1844+ typecast_exprt::conditional_cast (arg, param_it->type ()));
1845+ ++param_it;
1846+ }
1847+ const auto &block = to_code_block (to_code (symbol.value ));
1848+ for (const auto &stmt : block.statements ())
1849+ {
1850+ if (
1851+ auto return_stmt = expr_try_dynamic_cast<code_frontend_returnt>(stmt))
1852+ {
1853+ PRECONDITION (return_stmt->has_return_value ());
1854+ exprt tmp = return_stmt->return_value ();
1855+ value_map.replace (tmp);
1856+ expr.swap (tmp);
1857+ return ;
1858+ }
1859+ else if (auto expr_stmt = expr_try_dynamic_cast<code_expressiont>(stmt))
1860+ {
1861+ // C++14 and later only
1862+ if (
1863+ auto assign = expr_try_dynamic_cast<side_effect_expr_assignt>(
1864+ expr_stmt->expression ()))
1865+ {
1866+ PRECONDITION (assign->lhs ().id () == ID_symbol);
1867+ exprt rhs = assign->rhs ();
1868+ value_map.replace (rhs);
1869+ value_map.set (to_symbol_expr (assign->lhs ()), rhs);
1870+ }
1871+ else
1872+ UNIMPLEMENTED_FEATURE (
1873+ " constexpr with " + expr_stmt->expression ().pretty ());
1874+ }
1875+ else if (stmt.get_statement () == ID_decl_block)
1876+ {
1877+ // C++14 and later only
1878+ for (const auto &expect_decl : stmt.operands ())
1879+ {
1880+ PRECONDITION (to_code (expect_decl).get_statement () == ID_decl);
1881+ PRECONDITION (!to_code_frontend_decl (to_code (expect_decl))
1882+ .initial_value ()
1883+ .has_value ());
1884+ }
1885+ }
1886+ else
1887+ {
1888+ UNIMPLEMENTED_FEATURE (" constexpr with " + stmt.pretty ());
1889+ }
1890+ }
1891+ }
1892+ }
1893+
18281894 // we will deal with some 'special' functions here
18291895 exprt tmp=do_special_functions (expr);
18301896 if (tmp.is_not_nil ())
0 commit comments