2

我只想重写特定的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 这将对我有很大帮助。谢谢

4

0 回答 0