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