您好我正在使用clang从c文件中提取信息。 我正在尝试提取宏的值。
e.g。从这里我想要值'13'或ast(+(* 3 4)1):
#define SOME_CONSTANT 3*4+1
或者从宏功能,我想要一个例如(SOME_MACROFUNC(x y)(+(add4 x)(* y 9))):
int add4(int q) {return q+4;}
#define SOME_MACROFUNC(x,y) add4(x)+y*9
到目前为止,我已经设法通过'Preprocessor'类的macro_begin()和macro_end()函数遍历所有宏。
然后从那里我得到了宏名称,并且从'MacroInfo'类我已经能够得到宏是否是函数(包括param名称)。我也可以访问宏中的令牌,但我只能获得令牌类型:string_literal,identifier,逗号,l_paren,r_paren等。
所以有两件事:
如何访问令牌的实际值,而不仅仅是它们的种类。
有没有办法从给定令牌的宏中生成ast? 我认为的一种方法是解析我的源代码,然后提取宏,并使用它们的名称,将包含这些宏的代码添加到我的源代码并重新分析它以获得ast。
e.g。类似的东西:
char *tempSOME_CONSTANT = SOME_CONSTANT;
void tempSOME_MACROFUNC(char *x, char *y) {SOME_MACROFUNC(x,y);}
虽然这种方法看起来很麻烦,但可能会遇到没有语句或表达式的宏。
感谢。
编辑: 为了澄清我主要想要每个宏的扩展体(直到没有宏,只有非宏标记)。
edit2解决了一些问题:
如果有兴趣的话,我打算手动扩展宏的主体。
“preprocessor.getSpelling(token)”获取标记值。
“preprocessor.getIdentifierTable()。get(StringRef(spelling))”获取令牌的identinfo。
使用“clang \ lib \ Lex \ PPMacroExpansion.cpp”作为参考。
还在考虑如何在不重新分析整个源代码树的情况下将其传递给解析器,但这不应该太难理解。
感谢Ira Baxter的讨论,它帮助我解决了这个问题。
答案 0 :(得分:7)
我正在做一些非常相似的事情。我使用clang前端来收集定义宏的上下文(w.r.t.类,函数等),然后使用(伪)表达式解析器来确定宏体是否是有效表达式。最终目标是将宏转换为C ++声明。最近我们在ICSM - 2012年接受了一篇论文,解释了我们如何实现这一目标。
托管here
的工具 - 用于摆脱宏的demacrofierIra Baxter的例子对宏的使用方式非常有见地。然而,这些宏的%年龄非常小\ ref(对Ernst等人使用的C预处理器的实证分析)。目前,我更关注常见案例。
答案 1 :(得分:0)
可能会或可能没有用的一个hack是暂时将所有类似函数的宏重新定义为函数。在你的情况下:
#define SOME_MACROFUNC(x,y) add4(x)+y*9
将成为
extern int SOME_MACROFUNC(int x, int y);
然后,您可以通过常规AST匹配器或访问者运行此操作,并执行您需要的任何处理(包括重构,如果适用)。这不能很好地扩展,但如果宏的数量众所周知且有限,那么它可能是一个可接受的解决方案。
为了使这个更干净,您可以创建一个仅由clang使用的单独头文件,并确保clang在运行分析时首先找到它,这样您就不需要修改原始源代码库了。