@@ -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>
@@ -1820,6 +1821,71 @@ void cpp_typecheckt::typecheck_side_effect_function_call(
18201821
18211822 add_implicit_dereference (expr);
18221823
1824+ if (auto sym_expr = expr_try_dynamic_cast<symbol_exprt>(expr.function ()))
1825+ {
1826+ const auto &symbol = lookup (sym_expr->get_identifier ());
1827+ if (symbol.is_macro )
1828+ {
1829+ // constexpr functions evaluated using a mini interpreter
1830+ const auto &code_type = to_code_type (symbol.type );
1831+ // PRECONDITION(code_type.return_type().id() != ID_empty);
1832+ PRECONDITION (expr.arguments ().size () == code_type.parameters ().size ());
1833+ replace_symbolt value_map;
1834+ auto param_it = code_type.parameters ().begin ();
1835+ for (const auto &arg : expr.arguments ())
1836+ {
1837+ value_map.insert (
1838+ symbol_exprt{param_it->get_identifier (), param_it->type ()},
1839+ typecast_exprt::conditional_cast (arg, param_it->type ()));
1840+ ++param_it;
1841+ }
1842+ const auto &block = to_code_block (to_code (symbol.value ));
1843+ for (const auto &stmt : block.statements ())
1844+ {
1845+ if (
1846+ auto return_stmt = expr_try_dynamic_cast<code_frontend_returnt>(stmt))
1847+ {
1848+ PRECONDITION (return_stmt->has_return_value ());
1849+ exprt tmp = return_stmt->return_value ();
1850+ value_map.replace (tmp);
1851+ expr.swap (tmp);
1852+ return ;
1853+ }
1854+ else if (auto expr_stmt = expr_try_dynamic_cast<code_expressiont>(stmt))
1855+ {
1856+ // C++14 and later only
1857+ if (
1858+ auto assign = expr_try_dynamic_cast<side_effect_expr_assignt>(
1859+ expr_stmt->expression ()))
1860+ {
1861+ PRECONDITION (assign->lhs ().id () == ID_symbol);
1862+ exprt rhs = assign->rhs ();
1863+ value_map.replace (rhs);
1864+ value_map.set (to_symbol_expr (assign->lhs ()), rhs);
1865+ }
1866+ else
1867+ UNIMPLEMENTED_FEATURE (
1868+ " constexpr with " + expr_stmt->expression ().pretty ());
1869+ }
1870+ else if (stmt.get_statement () == ID_decl_block)
1871+ {
1872+ // C++14 and later only
1873+ for (const auto &expect_decl : stmt.operands ())
1874+ {
1875+ PRECONDITION (to_code (expect_decl).get_statement () == ID_decl);
1876+ PRECONDITION (!to_code_frontend_decl (to_code (expect_decl))
1877+ .initial_value ()
1878+ .has_value ());
1879+ }
1880+ }
1881+ else
1882+ {
1883+ UNIMPLEMENTED_FEATURE (" constexpr with " + stmt.pretty ());
1884+ }
1885+ }
1886+ }
1887+ }
1888+
18231889 // we will deal with some 'special' functions here
18241890 exprt tmp=do_special_functions (expr);
18251891 if (tmp.is_not_nil ())
0 commit comments