Как правильно сопоставить #include (или #defines) с помощью libtooling Clang?

Я пишу инструмент рефакторинга libtooling. У меня есть класс, скажем Fooопределяется в заголовке foo.h, Я хочу увидеть, если foo.h включен в файл. В настоящее время, чтобы проверить, если bar.cc включает в себя foo.hЯ просто соответствую, используя recordDecl(hasName("Foo")), Это работает, потому что class Foo { ... }; будет существовать внутри bar.ccАСТ после предварительной обработки, если bar.cc включает в себя foo.h,

Но это не работает, если, например, bar.cc включает в себя cat.h который включает в себя foo.h, я хочу bar.cc ТОЧНО включать foo.h,

Кроме того, я хотел бы иметь возможность соответствовать #define макросы.

То, как я писал свой инструмент, сделало эти две цели невозможными, потому что AST, с которым я сопоставляюсь, уже был предварительно обработан. Возможно ли то, что я пытаюсь сделать? Я покопался Preprocessor ссылка на класс на страницах Кланга о Doxygen, но я не совсем нашел то, что искал.

2 ответа

Решение

Я понял это после того, как покопался в Dog и коде Кланга. Мне нужно было использовать PPCallbacks класс вместе с Preprocessor учебный класс. Пример ниже. Обратите внимание, что это не обязательно является функциональным фрагментом кода, но он иллюстрирует общее использование. Для получения дополнительной информации см. Документацию Clang по PPCallbacks, а также документацию для addPPCallbacks и getPPCallbacks в clang:: Preprocessor.

class Find_Includes : public PPCallbacks
{
public:
  bool has_include;

  void InclusionDirective(
    SourceLocation hash_loc,
    const Token &include_token,
    StringRef file_name,
    bool is_angled,
    CharSourceRange filename_range,
    const FileEntry *file,
    StringRef search_path,
    StringRef relative_path,
    const Module *imported)
  {
    // do something with the include
    has_include = true;
  }
};

class Include_Matching_Action : public ASTFrontendAction
{
  bool BeginSourceFileAction(CompilerInstance &ci, StringRef)
  {
    std::unique_ptr<Find_Includes> find_includes_callback(new Find_Includes());

    Preprocessor &pp = ci.getPreprocessor();
    pp.addPPCallbacks(std::move(find_includes_callback));

    return true;
  }

  void EndSourceFileAction()
  {
    CompilerInstance &ci = getCompilerInstance();
    Preprocessor &pp = ci.getPreprocessor();
    Find_Includes *find_includes_callback = static_cast<Find_Includes>(pp.getPPCallbacks());

    // do whatever you want with the callback now
    if (find_includes_callback->has_include)
      std::cout << "Found at least one include" << std::endl;
  }
};

Я успешно реализовал это. Я не думаю, что метод EndSourceFileAction() должен содержать что-либо, связанное с Find_Include.

void InclusionDirective( SourceLocation hash_loc, const Token &include_token, StringRef file_name, bool is_angled, CharSourceRange filename_range,
                            const FileEntry *file, StringRef search_path, StringRef relative_path, const Module *imported)
              {
                  // Add your code here.
              }
bool BeginSourceFileAction(CompilerInstance &CI) 
{     std::unique_ptr<Find_Includes> find_includes_callback(new Find_Includes(TheRewriter));
      Preprocessor &pp = CI.getPreprocessor();
      pp.addPPCallbacks(std::move(find_includes_callback));
      return true;
}
Другие вопросы по тегам