Мне нужно заменить строковые литералы, расположенные в макросах TEXT, на libtooling. Например, в приведенном ниже фрагменте кода:
fd_ = CreateFile(TEXT("\\\\.\\") TEXT(PMEM_DEVICE_NAME),
// Write is needed for IOCTL.
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
Если я сопоставлю все строки с ASTMatcher, getBeginLoc () будет указывать на первый T из TEXT, но getEndLoc () будет указывать на последний T из TEXT.
Как мне получить исходные местоположения контента между кавычками?
В libTooling есть много API-интерфейсов, которые задают местоположение чего-либо, но слишком мало документации об их различиях.
Я уже пробовал:
clang::SourceRange LiteralRange = clang::SourceRange(
ASTRewriter->getSourceMgr().getFileLoc(pLiteral->getBeginLoc()),
ASTRewriter->getSourceMgr().getFileLoc(pLiteral->getEndLoc())
);
А также:
bool isMacro = ASTRewriter->getSourceMgr().isMacroBodyExpansion(pLiteral->getBeginLoc());
bool ReplaceResult;
std::string Replacement("test");
if (isMacro) {
StringRef OrigText = clang::Lexer::getSourceText(CharSourceRange(pLiteral->getSourceRange(), true),
pContext->getSourceManager(), pContext->getLangOpts());
if (OrigText.find("TEXT") != std::string::npos) {
auto EndLoc = clang::Lexer::findLocationAfterToken(LiteralRange.getBegin(), tok::r_paren,
pContext->getSourceManager(), ASTRewriter->getLangOpts(),
true);
LiteralRange.setEnd(ASTRewriter->getSourceMgr().getFileLoc(pLiteral->getEndLoc().getLocWithOffset(-1)));
LiteralRange.setEnd(EndLoc);
ASTRewriter->RemoveText(LiteralRange);
ReplaceResult = ASTRewriter->ReplaceText(LiteralRange, Replacement);
Фрагмент, приведенный выше, работает хорошо в некоторых случаях, но в большинстве случаев яполучите следующее:
TEXT("something")
=> test("something")
, тогда как я ожидаю TEXT("something")
или просто "test"
.
Любая помощь с благодарностью!