|
18 | 18 | #include <util/c_types.h>
|
19 | 19 | #include <util/config.h>
|
20 | 20 | #include <util/cprover_prefix.h>
|
| 21 | +#include <util/expr_util.h> |
21 | 22 | #include <util/ieee_float.h>
|
22 | 23 | #include <util/pointer_offset_size.h>
|
23 | 24 | #include <util/pointer_predicates.h>
|
| 25 | +#include <util/replace_symbol.h> |
24 | 26 | #include <util/simplify_expr.h>
|
25 | 27 | #include <util/string_constant.h>
|
26 | 28 |
|
@@ -1918,7 +1920,10 @@ void c_typecheck_baset::typecheck_side_effect_function_call(
|
1918 | 1920 | if(entry!=asm_label_map.end())
|
1919 | 1921 | identifier=entry->second;
|
1920 | 1922 |
|
1921 |
| - if(symbol_table.symbols.find(identifier)==symbol_table.symbols.end()) |
| 1923 | + symbol_tablet::symbolst::const_iterator sym_entry = |
| 1924 | + symbol_table.symbols.find(identifier); |
| 1925 | + |
| 1926 | + if(sym_entry == symbol_table.symbols.end()) |
1922 | 1927 | {
|
1923 | 1928 | // This is an undeclared function.
|
1924 | 1929 | // Is this a builtin?
|
@@ -1960,6 +1965,87 @@ void c_typecheck_baset::typecheck_side_effect_function_call(
|
1960 | 1965 | warning() << "function `" << identifier << "' is not declared" << eom;
|
1961 | 1966 | }
|
1962 | 1967 | }
|
| 1968 | + else if( |
| 1969 | + sym_entry->second.type.get_bool(ID_C_inlined) && |
| 1970 | + sym_entry->second.is_macro && sym_entry->second.value.is_not_nil()) |
| 1971 | + { |
| 1972 | + // calling a function marked as always_inline |
| 1973 | + const symbolt &func_sym = sym_entry->second; |
| 1974 | + const code_typet &func_type = to_code_type(func_sym.type); |
| 1975 | + |
| 1976 | + replace_symbolt replace; |
| 1977 | + |
| 1978 | + const code_typet::parameterst ¶meters = func_type.parameters(); |
| 1979 | + auto p_it = parameters.begin(); |
| 1980 | + for(const auto &arg : expr.arguments()) |
| 1981 | + { |
| 1982 | + if(p_it == parameters.end()) |
| 1983 | + { |
| 1984 | + // we don't support varargs with always_inline |
| 1985 | + err_location(f_op); |
| 1986 | + error() << "function call has additional arguments, " |
| 1987 | + << "cannot apply always_inline" << eom; |
| 1988 | + throw 0; |
| 1989 | + } |
| 1990 | + |
| 1991 | + irep_idt p_id = p_it->get_identifier(); |
| 1992 | + if(p_id.empty()) |
| 1993 | + { |
| 1994 | + p_id = id2string(func_sym.base_name) + "::" + |
| 1995 | + id2string(p_it->get_base_name()); |
| 1996 | + } |
| 1997 | + replace.insert(p_id, arg); |
| 1998 | + |
| 1999 | + ++p_it; |
| 2000 | + } |
| 2001 | + |
| 2002 | + if(p_it != parameters.end()) |
| 2003 | + { |
| 2004 | + err_location(f_op); |
| 2005 | + error() << "function call has missing arguments, " |
| 2006 | + << "cannot apply always_inline" << eom; |
| 2007 | + throw 0; |
| 2008 | + } |
| 2009 | + |
| 2010 | + codet body = to_code(func_sym.value); |
| 2011 | + replace(body); |
| 2012 | + |
| 2013 | + side_effect_exprt side_effect_expr( |
| 2014 | + ID_statement_expression, func_type.return_type()); |
| 2015 | + body.make_block(); |
| 2016 | + |
| 2017 | + // simulates parts of typecheck_function_body |
| 2018 | + typet cur_return_type = return_type; |
| 2019 | + return_type = func_type.return_type(); |
| 2020 | + typecheck_code(body); |
| 2021 | + return_type.swap(cur_return_type); |
| 2022 | + |
| 2023 | + // replace final return by an ID_expression |
| 2024 | + codet &last = to_code_block(body).find_last_statement(); |
| 2025 | + |
| 2026 | + if(last.get_statement() == ID_return) |
| 2027 | + last.set_statement(ID_expression); |
| 2028 | + |
| 2029 | + // NOLINTNEXTLINE(whitespace/braces) |
| 2030 | + const bool has_returns = has_subexpr(body, [&](const exprt &e) { |
| 2031 | + return e.id() == ID_code && to_code(e).get_statement() == ID_return; |
| 2032 | + }); |
| 2033 | + if(has_returns) |
| 2034 | + { |
| 2035 | + // we don't support multiple return statements with always_inline |
| 2036 | + err_location(last); |
| 2037 | + error() << "function has multiple return statements, " |
| 2038 | + << "cannot apply always_inline" << eom; |
| 2039 | + throw 0; |
| 2040 | + } |
| 2041 | + |
| 2042 | + side_effect_expr.copy_to_operands(body); |
| 2043 | + typecheck_side_effect_statement_expression(side_effect_expr); |
| 2044 | + |
| 2045 | + expr.swap(side_effect_expr); |
| 2046 | + |
| 2047 | + return; |
| 2048 | + } |
1963 | 2049 | }
|
1964 | 2050 |
|
1965 | 2051 | // typecheck it now
|
|
0 commit comments