|
22 | 22 | #include <util/mathematical_types.h> |
23 | 23 | #include <util/pointer_expr.h> |
24 | 24 | #include <util/pointer_offset_size.h> |
| 25 | +#include <util/replace_symbol.h> |
25 | 26 | #include <util/symbol_table_base.h> |
26 | 27 |
|
27 | 28 | #include <ansi-c/c_qualifiers.h> |
@@ -1825,6 +1826,71 @@ void cpp_typecheckt::typecheck_side_effect_function_call( |
1825 | 1826 |
|
1826 | 1827 | add_implicit_dereference(expr); |
1827 | 1828 |
|
| 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 | + |
1828 | 1894 | // we will deal with some 'special' functions here |
1829 | 1895 | exprt tmp=do_special_functions(expr); |
1830 | 1896 | if(tmp.is_not_nil()) |
|
0 commit comments