Я хотел бы изменить Clang AST с помощью плагина. У меня есть следующие предложения по использованию объекта Clang Rewriter. Я использую compiler.createDefaultOutputFile (), чтобы получить выходной поток для записи измененного файла в него. компиляция работает нормально, но сгенерированный объектный файл поврежден. Я получаю следующую ошибку компоновщика: «Формат файла не распознан».
Командная строка сборки: clang ++ - 8 -Xclang -load -Xclang libcashpp.so -Xclang -add-plugin -Xclang ca sh -pp test. cpp
Вывод сборки: /tmp/test-eb7d3d.o: файл не распознан: формат файла не распознан
Вопрос: - Возможно ли обновить AST с помощью лязгать плагин? - Может кто-нибудь указать мне пример программы, которая делает это?
Исходный код:
#include <clang/Frontend/FrontendPluginRegistry.h>
#include <clang/AST/AST.h>
#include <clang/AST/ASTConsumer.h>
#include <clang/AST/RecursiveASTVisitor.h>
#include "clang/Rewrite/Core/Rewriter.h"
#include <clang/Frontend/CompilerInstance.h>
#include <clang/Sema/Sema.h>
#include <llvm/Support/raw_ostream.h>
#include <string>
#include <sstream>
namespace {
class VarDeclVisitor : public clang::RecursiveASTVisitor<VarDeclVisitor> {
public:
VarDeclVisitor(clang::Rewriter& rewriter)
: rewriter_(rewriter)
{}
bool VisitCallExpr(clang::CallExpr *ce) {
auto q = ce->getType();
auto t = q.getTypePtrOrNull();
if (t != NULL) {
auto callee = ce->getDirectCallee();
auto funcName = callee->getNameInfo().getAsString();
if (funcName == "getInstanceName") {
rewriter_.ReplaceText(ce->getBeginLoc(), callee->getIdentifier()->getName().size(), "getInstanceName2");
}
}
return true;
}
private:
clang::Rewriter& rewriter_;
};
class MyASTConsumer : public clang::ASTConsumer {
using Base = clang::ASTConsumer;
public:
MyASTConsumer(std::unique_ptr<llvm::raw_pwrite_stream>&& os)
: os_(std::move(os))
{}
void HandleTranslationUnit(clang::ASTContext &context) override {
clang::Rewriter rewriter(context.getSourceManager(), context.getLangOpts());
VarDeclVisitor visitor(rewriter);
auto &source_manager = context.getSourceManager();
const auto &mainFileID = source_manager.getMainFileID();
const auto &decls = context.getTranslationUnitDecl()->decls();
for (auto &decl : decls) {
const auto &fileID = source_manager.getFileID(decl->getLocation());
if (fileID != mainFileID)
continue;
visitor.TraverseDecl(decl);
}
auto rwbuf = rewriter.getRewriteBufferFor(mainFileID);
if (rwbuf) {
*os_ << std::string(rwbuf->begin(), rwbuf->end());
} else {
*os_ << source_manager.getBufferData(mainFileID);
}
}
private:
std::unique_ptr<llvm::raw_pwrite_stream> os_;
};
class MyPlugin : public clang::PluginASTAction {
public:
std::unique_ptr<clang::ASTConsumer> CreateASTConsumer(clang::CompilerInstance &compiler,
llvm::StringRef inFile) override {
auto os = compiler.createDefaultOutputFile(false, inFile, "cpp");
if (!os)
return nullptr;
return std::make_unique<MyASTConsumer>(std::move(os));
}
bool ParseArgs(const clang::CompilerInstance &compiler,
const std::vector<std::string> &args) override {
return true;
}
void PrintHelp(llvm::raw_ostream &ros) {}
};
}
static clang::FrontendPluginRegistry::Add<MyPlugin>
X("cash-pp", "My plugin");
Спасибо, -Blaise