|
24 | 24 | #include <util/std_expr.h>
|
25 | 25 | #include <util/pointer_offset_size.h>
|
26 | 26 | #include <util/pointer_predicates.h>
|
| 27 | +#include <util/replace_symbol.h> |
27 | 28 |
|
28 | 29 | #include "c_typecast.h"
|
29 | 30 | #include "c_qualifiers.h"
|
@@ -1913,7 +1914,10 @@ void c_typecheck_baset::typecheck_side_effect_function_call(
|
1913 | 1914 | if(entry!=asm_label_map.end())
|
1914 | 1915 | identifier=entry->second;
|
1915 | 1916 |
|
1916 |
| - if(symbol_table.symbols.find(identifier)==symbol_table.symbols.end()) |
| 1917 | + symbol_tablet::symbolst::const_iterator sym_entry= |
| 1918 | + symbol_table.symbols.find(identifier); |
| 1919 | + |
| 1920 | + if(sym_entry==symbol_table.symbols.end()) |
1917 | 1921 | {
|
1918 | 1922 | // This is an undeclared function. Let's just add it.
|
1919 | 1923 | // We do a bit of return-type guessing, but just a bit.
|
@@ -1945,6 +1949,72 @@ void c_typecheck_baset::typecheck_side_effect_function_call(
|
1945 | 1949 | warning().source_location=f_op.find_source_location();
|
1946 | 1950 | warning() << "function `" << identifier << "' is not declared" << eom;
|
1947 | 1951 | }
|
| 1952 | + else if(sym_entry->second.type.get_bool(ID_C_inlined) && |
| 1953 | + sym_entry->second.is_macro && |
| 1954 | + sym_entry->second.value.is_not_nil()) |
| 1955 | + { |
| 1956 | + // calling a function marked as always_inline |
| 1957 | + const symbolt &func_sym=sym_entry->second; |
| 1958 | + const code_typet &func_type=to_code_type(func_sym.type); |
| 1959 | + |
| 1960 | + replace_symbolt replace; |
| 1961 | + |
| 1962 | + const code_typet::parameterst ¶meters=func_type.parameters(); |
| 1963 | + auto p_it=parameters.begin(); |
| 1964 | + for(const auto &arg : expr.arguments()) |
| 1965 | + { |
| 1966 | + if(p_it==parameters.end()) |
| 1967 | + { |
| 1968 | + err_location(f_op); |
| 1969 | + error() << "function call has additional arguments, " |
| 1970 | + << "cannot apply always_inline" << eom; |
| 1971 | + throw 0; |
| 1972 | + } |
| 1973 | + |
| 1974 | + irep_idt p_id=p_it->get_identifier(); |
| 1975 | + if(p_id.empty()) |
| 1976 | + p_id= |
| 1977 | + id2string(func_sym.base_name)+"::"+ |
| 1978 | + id2string(p_it->get_base_name()); |
| 1979 | + replace.insert(p_id, arg); |
| 1980 | + |
| 1981 | + ++p_it; |
| 1982 | + } |
| 1983 | + |
| 1984 | + if(p_it!=parameters.end()) |
| 1985 | + { |
| 1986 | + err_location(f_op); |
| 1987 | + error() << "function call has missing arguments, " |
| 1988 | + << "cannot apply always_inline" << eom; |
| 1989 | + throw 0; |
| 1990 | + } |
| 1991 | + |
| 1992 | + codet body=to_code(func_sym.value); |
| 1993 | + replace(body); |
| 1994 | + |
| 1995 | + side_effect_exprt side_effect_expr( |
| 1996 | + ID_statement_expression, func_type.return_type()); |
| 1997 | + body.make_block(); |
| 1998 | + |
| 1999 | + // simulates parts of typecheck_function_body |
| 2000 | + typet cur_return_type=return_type; |
| 2001 | + return_type=func_type.return_type(); |
| 2002 | + typecheck_code(body); |
| 2003 | + return_type.swap(cur_return_type); |
| 2004 | + |
| 2005 | + // replace final return by an ID_expression |
| 2006 | + codet &last=to_code_block(body).find_last_statement(); |
| 2007 | + |
| 2008 | + if(last.get_statement()==ID_return) |
| 2009 | + last.set_statement(ID_expression); |
| 2010 | + |
| 2011 | + side_effect_expr.copy_to_operands(body); |
| 2012 | + typecheck_side_effect_statement_expression(side_effect_expr); |
| 2013 | + |
| 2014 | + expr.swap(side_effect_expr); |
| 2015 | + |
| 2016 | + return; |
| 2017 | + } |
1948 | 2018 | }
|
1949 | 2019 |
|
1950 | 2020 | // typecheck it now
|
|
0 commit comments