Clang: Получение общедоступных методов

Я хочу определить функцию, которая будет возвращать указатель на последний определенный общедоступный метод, используя библиотеку Clang LibTooling.

В настоящее время у меня есть указатель CXXRecordDecl *decl и следующая строка, чтобы получить исходное местоположение первого метода.

const SourceLocation method_begin_location = decl->method_begin()->getLocation();

В идеале я хочу заменить это функцией для получения местоположения последнего определенного публичного метода или местоположения начала публичного объявления, если нет следующих методов.

const SourceLocation last_public_method_location = get_last_public_method_loc(decl);

Любые идеи по написанию этой функции? method_end() указывает на конец определения метода, поэтому он не так полезен, как я надеялся.


person Lucas    schedule 03.07.2014    source источник
comment
Этот уровень отражения во время компиляции (пока) не поддерживается. Еще меньше информации о времени выполнения.   -  person Deduplicator    schedule 04.07.2014


Ответы (1)


Это может быть то, что вы могли бы попробовать. У меня есть одна переменная, которая должна хранить имя последнего общедоступного метода, который вы явно определили, что означает, что он не был добавлен компилятором автоматически. Каждая функция, соответствующая сопоставителю methodDecl(isPublic(), unless(isImplicit())), будет храниться в строковой переменной lastPublicMethodName, которая в конце будет содержать последний посещенный метод.

Я настоятельно рекомендую держать этот сайт в своем заднем кармане для всех, кто сопоставляет AST: http://clang.llvm.org/docs/LibASTMatchersReference.html. Кроме того, tools/clang/unitests/ASTMatchers/ASTMatchersTest.cpp является ценным ресурсом, если вы хотите узнать, как работает конкретный сопоставитель.

Это код, который я разбираю:

/tmp/Foo.hpp:

class Foo { 
    public:
        virtual ~Foo() {}
        virtual void somePublicFunction1() = 0;
        virtual void somePublicFunction2() = 0;
        virtual void somePublicFunction3() = 0;
        virtual void somePublicFunction4() = 0;
        virtual void somePublicFunction5() = 0;
    private:
        virtual void somePrivateFunction1() = 0;
        virtual void somePrivateFunction2() = 0;
        virtual void somePrivateFunction3() = 0;
        virtual void somePrivateFunction4() = 0;
        virtual void somePrivateFunction5() = 0;
};

Вот программный код моего инструмента Clang:

llvm/tools/clang/tools/extra/mytool/MyTool.cpp

// Declares clang::SyntaxOnlyAction.
#include "clang/Frontend/FrontendActions.h"
#include "clang/Tooling/CommonOptionsParser.h"
#include "clang/Tooling/Tooling.h"
// Declares llvm::cl::extrahelp.
#include "llvm/Support/CommandLine.h"
#include "clang/ASTMatchers/ASTMatchers.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include <iostream>

using namespace clang;
using namespace clang::ast_matchers;
using namespace clang::tooling;
using namespace llvm;

// Apply a custom category to all command-line options so that they are the
// only ones displayed.
static llvm::cl::OptionCategory MyToolCategory("my-tool options");

// CommonOptionsParser declares HelpMessage with a description of the common
// command-line options related to the compilation database and input files.
// It's nice to have this help message in all tools.
static cl::extrahelp CommonHelp(CommonOptionsParser::HelpMessage);

// A help message for this specific tool can be added afterwards.
static cl::extrahelp MoreHelp("\nMore help text...");

DeclarationMatcher methodMatcher = methodDecl(isPublic(),unless(isImplicit())).bind("methods");

class MethodPrinter : public MatchFinder::MatchCallback {
public :
  virtual void run(const MatchFinder::MatchResult &Result) {
    if (const CXXMethodDecl *md = Result.Nodes.getNodeAs<clang::CXXMethodDecl>("methods")) {    
      lastPublicMethodName = md->getNameAsString();
    }
  }

  std::string lastPublicMethodName;
};

int main(int argc, const char **argv) {
  CommonOptionsParser OptionsParser(argc, argv, MyToolCategory);
  ClangTool Tool(OptionsParser.getCompilations(),
                 OptionsParser.getSourcePathList());

  MethodPrinter Printer;
  MatchFinder Finder;
  Finder.addMatcher(methodMatcher, &Printer);

  Tool.run(newFrontendActionFactory(&Finder).get());

  std::cout << "The last public method is: " << Printer.lastPublicMethodName << std::endl;
  return 0;
}

Я надеюсь, это поможет вам.

person Konrad Kleine    schedule 04.07.2014
comment
Я думаю, хотя технически это работает. У меня есть другие функции в моем сопоставителе, где я не могу дождаться завершения всего процесса сопоставления, прежде чем получить указатель на последний общедоступный метод. Спасибо за пример, я думаю, что в конечном итоге я могу написать сопоставитель только для тела общедоступного метода. Я надеялся, что кто-нибудь поможет мне с использованием method_iterator, я новичок в C++. - person Lucas; 07.07.2014