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

编写clang-tidy检查:如何获取ref qualifier的正确插入源位置?

问题

我想要编写一个clang-tidy检查,为特定C++方法添加左值引用限定符(lvalue ref qualifier)。已成功检测到需要修复的方法,但无法找到添加限定符的正确源位置。

当前尝试的代码如下:

void MyCheck::check(const MatchFinder::MatchResult &Result) {
  const auto *MatchedDecl = Result.Nodes.getNodeAs<CXXMethodDecl>("x");

  if (RQ_None != MatchedDecl->getRefQualifier()) {
    return;
  }

  diag(MatchedDecl->getBeginLoc(),
       "Member Function %0 should have lvalue ref qualifier.")
      << MatchedDecl
      << FixItHint::CreateInsertion(
             MatchedDecl->getTypeSpecEndLoc().getLocWithOffset(1), " &");
  diag(MatchedDecl->getTypeSpecEndLoc().getLocWithOffset(1),
       "Add ref-qualifier for lvalues.", DiagnosticIDs::Note);
}

该代码在方法返回值写在方法名前时能正常工作,例如将Test& modify1();修复为Test& modify1() &;,但针对带尾置返回类型的方法(如auto modify2() -> Test&),会错误地修复为auto modify2() -> Test& &;,出现语法错误。

现需替代getTypeSpecEndLoc().getLocWithOffset(1),从AST匹配器中找到ref qualifier的预期插入位置,请问该如何实现?

解决方案

核心思路是找到C++语法中规定的引用限定符标准插入位置:参数列表右括号之后、cv限定符(如果有)之后、尾置返回类型之前。利用Clang AST提供的定位API,可以精准获取该位置,无需区分返回值写法。

具体实现步骤

  1. 判断是否存在CV限定符:通过CXXMethodDecl的getQualifiers()方法检查方法是否带有const/volatile限定符。
  2. 确定插入位置:
    • 若有CV限定符,插入位置为CV限定符的结束位置(Qualifiers::getEndLoc());
    • 若无CV限定符,插入位置为参数列表右括号的结束位置(CXXMethodDecl::getParenEndLoc())。
  3. 生成修复提示:在确定的位置插入 &即可。

修改后的代码

void MyCheck::check(const MatchFinder::MatchResult &Result) {
  const auto *MatchedDecl = Result.Nodes.getNodeAs<CXXMethodDecl>("x");

  if (MatchedDecl->getRefQualifier() != RQ_None) {
    return;
  }

  SourceLocation InsertLoc;
  const Qualifiers &quals = MatchedDecl->getQualifiers();
  if (quals.hasAnyQualifiers()) {
    // 有CV限定符时,插入到限定符末尾
    InsertLoc = quals.getEndLoc();
  } else {
    // 无CV限定符时,插入到参数列表右括号后
    InsertLoc = MatchedDecl->getParenEndLoc();
  }

  diag(MatchedDecl->getBeginLoc(),
       "Member function %0 should have an lvalue reference qualifier")
      << MatchedDecl
      << FixItHint::CreateInsertion(InsertLoc, " &");
  diag(InsertLoc,
       "Add lvalue reference qualifier here", DiagnosticIDs::Note);
}

效果验证

  • 普通返回值方法:Test& modify1() → Test& modify1() &
  • 带CV限定方法:void modify3() const → void modify3() const &
  • 尾置返回类型方法:auto modify2() -> Test& → auto modify2() & -> Test&(符合C++标准语法,编译器可正确解析)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 05:22:15