我只想重写特定的ctor定义。要找到改变的女巫我使用'普通'的DeclarationMatcher
DeclarationMatcher ClassMatcher2 =
cxxRecordDecl(isDerivedFrom("X"),
has(fieldDecl(
hasType(
cxxRecordDecl(
isDerivedFrom("AA")))))
).bind("className2");
找到特定的类/ ctor非常有用,但是如何在cpp类中从头转换到定义。运行工具的命令是:
loop-convert -extra-arg-before="-xc++" bin/playground/derived_t1.cpp --
要处理回调,我使用MatchCallback:
if (const CXXRecordDecl *FS = Result.Nodes.getNodeAs<clang::CXXRecordDecl>("className2")) {
llvm::outs() << "~~~~~~~~~~~~~~~~~~~BEGIN3\n";
FS->dump();
if(FS->hasUserDeclaredConstructor()) {
llvm::outs() << "FS->hasUserDeclaredConstructor() true\n";
}
if(FS->hasUserProvidedDefaultConstructor()) {
llvm::outs() << "FS->hasUserProvidedDefaultConstructor() true\n";
}
CXXRecordDecl::ctor_iterator bIt = FS->ctor_begin();
CXXRecordDecl::ctor_iterator eIt = FS->ctor_end();
llvm::outs() << "~~~~~~~~~~~~~~~~~~~BEGIN33\n";
while(bIt != eIt) {
bIt->dump();
++bIt;
}
llvm::outs() << "~~~~~~~~~~~~~~~~~~~~~END33\n";
m_rewrite.InsertText(FS->getLocStart(), "/* increment */", true, true);
llvm::outs() << "~~~~~~~~~~~~~~~~~~~~~END3\n";
}
正如你在描述中已经知道的那样m_rewriter.InsertText对我来说不起作用 - 根本没有(标题没有改变)。
输入文件derived_t1.h:
class AA {};
class AAA : public AA {};
class X {};
class Y : public X {}; // directly derived
class Z : public Y {}; // indirectly derived
typedef X A;
typedef A B;
class C : public B {}; // derived from a typedef of X
class BB : public X {
AAA aaa;
AAA aaa2;
int ttsd;
AA *as_ptr;
AA as;
public:
BB();
};
class CC : public X {
AAA * aaa_ptr;
};
class D {
AAA aaa;
AAA * aaa_ptr;
int g;
};
class E {
AAA aaa;
AAA * aaa_ptr;
int *gg_ptr;
};
输入文件derived_t1.cpp:
#include "derived_t1.h"
BB::BB() {
//nothing for now here
}
整个示例工具:
#include "clang/Frontend/FrontendActions.h"
#include "clang/Tooling/CommonOptionsParser.h"
#include "clang/Tooling/Tooling.h"
#include "llvm/Support/CommandLine.h"
#include "clang/ASTMatchers/ASTMatchers.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/AST/ASTContext.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Rewrite/Core/Rewriter.h"
//#include "clang/AST/RecursiveASTVisitor.h"
using namespace clang::tooling;
using namespace llvm;
using namespace clang;
using namespace clang::ast_matchers;
//static bool areSameVariable(const ValueDecl *First, const ValueDecl *Second) {
// return First && Second &&
// First->getCanonicalDecl() == Second->getCanonicalDecl();
//}
//static bool areSameExpr(ASTContext *Context, const Expr *First,
// const Expr *Second) {
// if (!First || !Second)
// return false;
// llvm::FoldingSetNodeID FirstID, SecondID;
// First->Profile(FirstID, *Context, true);
// Second->Profile(SecondID, *Context, true);
// return FirstID == SecondID;
//}
DeclarationMatcher ClassMatcher =
cxxRecordDecl(isDerivedFrom("X"
)).bind("className");
DeclarationMatcher MemberMatcher =
fieldDecl(
hasType(
cxxRecordDecl(
isDerivedFrom("AA"))
)).bind("field_decl");
DeclarationMatcher ClassMatcher2 =
cxxRecordDecl(isDerivedFrom("X"),
has(fieldDecl(
hasType(
cxxRecordDecl(
isDerivedFrom("AA")))))
).bind("className2");
class ClassPrinter : public MatchFinder::MatchCallback {
public:
ClassPrinter(Rewriter &rewriter):m_rewrite(rewriter) {
}
virtual void run(const MatchFinder::MatchResult &Result) {
if (const CXXRecordDecl *FS = Result.Nodes.getNodeAs<clang::CXXRecordDecl>("className")) {
llvm::outs() << "~~~~~~~~~~~~~~~~~~~BEGIN\n";
FS->dump();
llvm::outs() << "~~~~~~~~~~~~~~~~~~~~~END\n";
}
if (const CXXRecordDecl *F = Result.Nodes.getNodeAs<clang::CXXRecordDecl>("field_decl")) {
llvm::outs() << "~~~~~~~~~~~~~~~~~~~BEGIN2\n";
const auto& SM = *Result.SourceManager;
const auto& Loc = F->getLocation();
llvm::outs() << "Fname:"
<< SM.getFilename(Loc) << ":"
<< SM.getSpellingLineNumber(Loc) << ":"
<< SM.getSpellingColumnNumber(Loc) << "\n";
F->dump();
llvm::outs() << "~~~~~~~~~~~~~~~~~~~~~END2\n";
}
if (const CXXRecordDecl *FS = Result.Nodes.getNodeAs<clang::CXXRecordDecl>("className2")) {
llvm::outs() << "~~~~~~~~~~~~~~~~~~~BEGIN3\n";
FS->dump();
if(FS->hasUserDeclaredConstructor()) {
llvm::outs() << "FS->hasUserDeclaredConstructor() true\n";
}
if(FS->hasUserProvidedDefaultConstructor()) {
llvm::outs() << "FS->hasUserProvidedDefaultConstructor() true\n";
}
CXXRecordDecl::ctor_iterator bIt = FS->ctor_begin();
CXXRecordDecl::ctor_iterator eIt = FS->ctor_end();
llvm::outs() << "~~~~~~~~~~~~~~~~~~~BEGIN33\n";
while(bIt != eIt) {
//CXXConstructorDecl
bIt->dump();
++bIt;
}
llvm::outs() << "~~~~~~~~~~~~~~~~~~~~~END33\n";
m_rewrite.InsertText(FS->getLocStart(), "/* increment */", true, true);
llvm::outs() << "~~~~~~~~~~~~~~~~~~~~~END3\n";
}
if (const FieldDecl* fd = Result.Nodes.getNodeAs<clang::FieldDecl>("field_decl"))
{
llvm::outs() << "======== FieldDecl found ======\n";
const clang::RecordDecl* rd = fd->getParent();
const clang::QualType qt = fd->getType();
const clang::Type* t = qt.getTypePtr();
llvm::outs() << "FieldDecl found '"
<< fd->getQualifiedNameAsString() << " "
<< fd->getName().str() << "' in '"
<< rd->getName().str() << "'. "
<< "is Builtintype = " << t->isBuiltinType()
<< "\n";
if(Result.Nodes.getNodeAs<clang::CXXRecordDecl>("className")) {
llvm::outs() << "same AST as className\n";
}
else {
llvm::outs() << "NOT same AST as className\n";
}
}
if (const CXXConstructorDecl *FS = Result.Nodes.getNodeAs<clang::CXXConstructorDecl>("")) {
llvm::outs() << "~~~~~~~~~~~~~~~~~~~BEGIN4\n";
FS->dump();
llvm::outs() << "~~~~~~~~~~~~~~~~~~~~~END4\n";
}
}
private:
Rewriter &m_rewrite;
};
class IncrementForLoopHandler : public MatchFinder::MatchCallback {
public:
IncrementForLoopHandler(Rewriter &Rewrite) : Rewrite(Rewrite) {}
virtual void run(const MatchFinder::MatchResult &Result) {
const VarDecl *IncVar = Result.Nodes.getNodeAs<VarDecl>("incVarName");
Rewrite.InsertText(IncVar->getLocStart(), "/* increment */", true, true);
}
private:
Rewriter &Rewrite;
};//IncrementForLoopHandler
class MyASTConsumer : public ASTConsumer {
public:
MyASTConsumer(Rewriter &rewriter) : m_classPrinter(rewriter) {
Matcher.addMatcher(ClassMatcher, &m_classPrinter);
Matcher.addMatcher(MemberMatcher, &m_classPrinter);
Matcher.addMatcher(ClassMatcher2, &m_classPrinter);
}
void HandleTranslationUnit(ASTContext &Context) override {
// Run the matchers when we have the whole TU parsed.
llvm::outs() << "HANDLE TU:\n";
Matcher.matchAST(Context);
}
private:
ClassPrinter m_classPrinter;
MatchFinder Matcher;
};//MyASTConsumer
class MyFrontendAction : public ASTFrontendAction {
public:
MyFrontendAction() {}
void EndSourceFileAction() override {
llvm::outs() << "END OF FILE ACTION:\n";
m_theRewriter.getEditBuffer(m_theRewriter.getSourceMgr().getMainFileID())
.write(llvm::outs());
}
std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, StringRef file) override {
m_theRewriter.setSourceMgr(CI.getSourceManager(), CI.getLangOpts());
return llvm::make_unique<MyASTConsumer>(m_theRewriter);
}
private:
Rewriter m_theRewriter;
};//MyFrontendAction
static llvm::cl::OptionCategory MyToolCategory("my-tool options");
static cl::extrahelp CommonHelp(CommonOptionsParser::HelpMessage);
// A help message for this specific tool can be added afterwards.
static cl::extrahelp MoreHelp("\nMore help text...\n");
int main(int argc, const char **argv) {
CommonOptionsParser OptionsParser(argc, argv, MyToolCategory);
ClangTool Tool(OptionsParser.getCompilations(),
OptionsParser.getSourcePathList());
return Tool.run(newFrontendActionFactory<MyFrontendAction>().get());
// return Tool.run(newFrontendActionFactory<clang::ASTPrintAction>().get());
}
因此,如果有人知道如何在cpp文件中更改ctor它会对我有很大帮助。 THX