更改函数名称并使用Clang的AST API修改字符串文字参数?

问题描述

我正在尝试编写一个整洁的规则,该规则将更改函数名称​​ 修改字符串文字参数。目标是从tinyFormat自动移植到libfmt。

在这里找到了我认为是很好的匹配者:

finder->addMatcher(
            callExpr(
                    callee(functionDecl(hasName("::tiny::Format"))),optionally(hasArgument(
                            0,ignoringImpCasts(
                                    declRefExpr(
                                            to(varDecl(hasType(hasUnqualifiedDesugaredType(
                                                    recordtype(hasDeclaration(
                                                            cxxRecordDecl(isDerivedFrom(
                                                                    "::std::basic_ostream")))))))))
                                            .bind("streamArg")))),anyOf(hasArgument(0,stringLiteral().bind("fmtLiteral")),hasArgument(1,stringLiteral().bind("fmtLiteral"))))
                    .bind("call"),this);

麻烦在于编写替换规则。如果我创建了1个fixit来替换名称,并创建了一个单独的替换来更改字符串文字(从%s样式更改为{}样式),则它们会互相tom脚。在尝试编写单个长替换字符串时,我遇到了一个非常棘手的问题:似乎不可能可靠地获取字符串文字 last 字符。目前我有这个,但是它使文字是否在宏中(例如ASSERT_ALWAYS)感到窒息。我也尝试过使用findLocationAfterToken并没有运气。

    fmtDiag << clang::FixItHint::CreateReplacement(
            callExpr->getSourceRange(),(llvm::Twine(streamArg ? "fmt::print(" : "fmt::format(") // use fmt::print if we're printing to a stream
             + (streamArg ? clang::tooling::fixit::getText(
                                    streamArg->getSourceRange(),*result.Context)
                                + ","
                          : StringRef())
             + llvm::Twine(TransformFormatString(fmtLiteral->getString()))
             + clang::tooling::fixit::getText(
                     SourceRange(
                             // Note(wgray): I have no idea why this is required,but just
                             // using fmtLiteral->getEndLoc() doesn't work. This magic
                             // incantation was taken from
                             // bugprone/NotNullTerminatedResultCheck.cpp
                             Lexer::getLocForEndOfToken(
                                     fmtLiteral->getEndLoc(),*result.sourceManager,result.Context->getLangOpts()),endLoc,callExpr->getEndLoc()),*result.Context));
    ```

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)