我正在编写一个libtooling重构工具。我有一个课程,让我们说Foo
,在名为foo.h
的标题中定义。我想看看文件中是否包含foo.h
。目前,要检查bar.cc
是否包含foo.h
,我只是使用recordDecl(hasName("Foo"))
进行匹配。这是有效的,因为如果class Foo { ... };
包含bar.cc
,则预处理后bar.cc
的AST中会存在foo.h
。
但是,如果bar.cc
包含cat.h
包括foo.h
,则此功能不起作用。我希望bar.cc
明确地包含foo.h
。
此外,我希望能够匹配#define
个宏。
我编写工具的方式使得这两个目标无法实现,因为AST I匹配已经过预处理。是我试图做的甚至可能吗?我在Clang的Doxygen页面上挖掘Preprocessor
课程参考,但我还没有找到我想要的东西。
答案 0 :(得分:10)
我在Clang的Doxygen和代码中挖掘后想出了这个。我需要使用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;
}
};
答案 1 :(得分:1)
我成功实施了它。我不认为EndSourceFileAction()方法应该包含与Find_Includes相关的任何内容。
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;
}