diff --git a/modcc/functioninliner.cpp b/modcc/functioninliner.cpp index 5692da136ea63009efac8563eda224fbb6118a3c..ddfcbf6283258826dbff91248ad7a2e21148c9c0 100644 --- a/modcc/functioninliner.cpp +++ b/modcc/functioninliner.cpp @@ -6,6 +6,17 @@ #include "errorvisitor.hpp" #include "symdiff.hpp" +// Note: on renaming variables when inlining functions: +// Identifiers will refer either to a local variable, or a function argument, +// or both (in the case when a local variable shadows a function argument.) +// +// All local variables are renamed and the mapping is stored in local_arg_map_. +// The mapping from function arguments to call arguments is in call_args_map_. +// +// Local variable renaming of identifiers should be performed before call +// argument renaming. This means that if a local variable shadows a function +// argument, the local variable takes precedence. + expression_ptr inline_function_calls(std::string calling_func, BlockExpression* block) { auto inline_block = block->clone(); @@ -164,26 +175,20 @@ void FunctionInliner::visit(AssignmentExpression* e) { // If we're inlining a function call, take care of variable renaming if (auto lhs = e->lhs()->is_identifier()) { - std::string iden_name = lhs->spelling(); - // if the identifier name matches the function name, then we are setting the return value - if (iden_name == inlining_func_) { + if (lhs->spelling() == inlining_func_) { e->replace_lhs(lhs_->clone()); return_set_ = true; } else { - if (local_arg_map_.count(iden_name)) { - e->replace_lhs(local_arg_map_.at(iden_name)->clone()); - } + // lhs can only be a local variable, since call variables are read only + e->replace_lhs(substitute(e->lhs(), local_arg_map_)); } } - if (auto rhs = e->rhs()->is_identifier()) { - if (local_arg_map_.count(rhs->spelling())) { - e->replace_rhs(local_arg_map_.at(rhs->spelling())->clone()); - } - if (call_arg_map_.count(rhs->spelling())) { - e->replace_rhs(call_arg_map_.at(rhs->spelling())->clone()); - } + if (e->rhs()->is_identifier()) { + auto sub_rhs = substitute(e->rhs(), local_arg_map_); + sub_rhs = substitute(sub_rhs, call_arg_map_); + e->replace_rhs(std::move(sub_rhs)); } else { e->rhs()->accept(this); @@ -249,14 +254,9 @@ void FunctionInliner::visit(CallExpression* e) { auto& args = e->is_function_call() ? e->is_function_call()->args() : e->is_procedure_call()->args(); for (auto& a: args) { - if (auto id = a->is_identifier()) { - std::string iden_name = id->spelling(); - if (local_arg_map_.count(iden_name)) { - a = local_arg_map_.at(iden_name)->clone(); - } - if (call_arg_map_.count(iden_name)) { - a = call_arg_map_.at(iden_name)->clone(); - } + if (a->is_identifier()) { + a = substitute(a, local_arg_map_); + a = substitute(a, call_arg_map_); } else { a->accept(this); }