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

如何利用Clang AST Matcher正确获取静态函数CallExpr的源位置?

解决clang-tidy获取静态成员函数CallExpr正确源位置的问题

我在构建用于重构的自定义clang-tidy工具时,遇到了获取静态成员函数CallExpr正确源位置的问题:

示例C++代码

class Test
{
    public:
    static void foo(){}
};

对应的clang-tidy匹配代码

Finder->addMatcher(
traverse(TraversalKind::TK_IgnoreUnlessSpelledInSource,
         callExpr(callee(functionDecl(hasAncestor(
                      namespaceDecl(hasName("my_namespace"))))))
             .bind("call_expr")),
this);

当前输出(使用MatchedCallExpr->getExprLoc())

Test::foo()
~~~~
^
This function name should blahblahblah

期望输出

Test::foo()
      ~~~
      ^
This function name should blahblahblah

解决方案

问题核心是getExprLoc()返回的是整个调用表达式的起始位置(即Test的位置),而非目标函数名foo的位置。要精准定位到函数名,需要从CallExpr中提取被调用函数的声明,再获取函数名的具体位置:

修改后的核心代码

const auto *CallExpr = Result.Nodes.getNodeAs<clang::CallExpr>("call_expr");
if (!CallExpr) return;

const auto *CalleeDecl = CallExpr->getCalleeDecl();
const auto *FuncDecl = llvm::dyn_cast<clang::FunctionDecl>(CalleeDecl);
if (!FuncDecl || !FuncDecl->getIdentifier()) return;

// 获取函数名的起始位置
clang::SourceLocation FuncNameLoc = FuncDecl->getIdentifier()->getLocation();
// 获取函数名的长度,用于标记波浪线范围
unsigned int FuncNameLength = FuncDecl->getName().size();

// 生成诊断信息
Diag(FuncNameLoc, "This function name should blahblahblah")
    << clang::FixItHint::CreateReplacement(
        clang::SourceRange(FuncNameLoc, FuncNameLoc.getLocWithOffset(FuncNameLength)),
        /* 按需填写替换内容 */);

关键说明

  • CallExpr->getCalleeDecl():获取被调用函数的声明对象,转换为FunctionDecl后可访问函数名相关信息。
  • FuncDecl->getIdentifier()->getLocation():精准定位到函数名(如foo)的起始字符位置。
  • FuncDecl->getName().size():获取函数名的长度,用于生成覆盖整个函数名的波浪线标记范围。

内容的提问来源于stack exchange,提问作者armques

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 03:58:25