GCC GIMPLE C++ API:如何在成员函数中插入成员函数调用?
GCC插件:修复
[[invariant]]契约插入调用的错误 问题定位
错误提示call to non-function 'void Heap::invariant()'说明代码构建的调用语句存在类型不匹配,核心问题出在方法调用的构建逻辑上:
- 错误地将
this作为显式参数传递给成员函数(成员函数的this是隐式绑定的,不需要手动传入) gimple_build_call的使用方式错误,直接传入build_new_method_call返回的表达式而非正确的函数引用
修复方案
以下是修正后的insert_instrumentation_fn函数代码:
static void insert_instrumentation_fn(gimple* curr_stmt) { tree ctype = DECL_CONTEXT(current_function_decl); tree fn_id = get_identifier("invariant"); // 查找成员函数,确保拿到正确的函数声明 tree fn_decl = lookup_member(ctype, fn_id, 1, 0, tf_warning_or_error); if (!fn_decl) return; // 处理继承链中的BASELINK if (TREE_CODE(fn_decl) == BASELINK) fn_decl = BASELINK_FUNCTIONS(fn_decl); // 验证找到的确实是函数声明 if (TREE_CODE(fn_decl) != FUNCTION_DECL) return; // 获取当前函数的this指针(不需要解引用,build_new_method_call会处理) tree this_ptr = DECL_ARGUMENTS(current_function_decl); // 构建成员函数调用表达式:this->invariant() // 注意:成员函数不需要显式传this,build_new_method_call会自动绑定 vec<tree, va_gc>* args = NULL; tree call_expr = build_new_method_call(this_ptr, fn_decl, &args, NULL_TREE, LOOKUP_NORMAL, NULL, tf_warning_or_error); if (!call_expr) return; // 将表达式转换为gimple语句并插入 gimple* call_stmt = gimple_build_call_from_tree(call_expr); gimple_stmt_iterator gsi = gsi_for_stmt(curr_stmt); gsi_insert_before(&gsi, call_stmt, GSI_SAME_STMT); }
关键修正点
- 移除显式的
this参数:成员函数的this是隐式参数,build_new_method_call会自动处理绑定,不需要通过make_tree_vector_single传递this_ptr - 使用
gimple_build_call_from_tree替代gimple_build_call:直接基于build_new_method_call生成的表达式构建gimple语句,避免手动构造调用时的类型错误 - 增加类型校验:确保
lookup_member返回的确实是FUNCTION_DECL,防止非函数类型导致的调用错误 - 简化
this_ptr获取:直接使用DECL_ARGUMENTS(current_function_decl)(即未解引用的this指针),build_new_method_call内部会处理解引用逻辑
额外注意事项
- 确保插入时机在gimple语句生成完成后(比如在
pass_instrument_function阶段),此时类成员的类型已经完全解析 - 跳过
invariant函数自身的插入逻辑,避免无限递归调用
内容的提问来源于stack exchange,提问作者Gavin Ray
相关产品推荐
相关产品推荐

