Как правильно сопоставить #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, но я не совсем нашел то, что искал.

7

Решение

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

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;
}
};
9

Другие решения

Я успешно реализовал это. Я не думаю, что метод 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;
}
1

По вопросам рекламы [email protected]