You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 04:45:41