如何在C/C++源代码中公开typedef

How to unveil typedef in C/C++ sources?

本文关键字:typedef 源代码 C++      更新时间:2023-10-16

我想用我的基元解析器解析C/C++代码,以获得ast树。

但它不支持宏和typedef。

借助gcc选项,可以在任何C/C++项目中公布宏定义。在那之后,我自己的解析器能够处理C/C++代码,但只有在没有typedef的情况下

所以,我想在某种程度上摆脱typedefs。但我不知道该怎么办。

我想替换重新定义的类型名称,例如:

typedef char CHAR;
typedef int& INT;
INT a;
CHAR b;

按原件:

int &a;
char b;

因此,我想获得相同的源,但有原始类型,没有typedef。

我想,这对编译器来说是一项非常简单的任务,但对学生的项目来说却不是

据我所知,g++的DECL_ORIGINAL_TYPE(TYPE_NAME(t))指向具有原始对象类型的树节点。但我真的不想深入研究g++源来满足我的需求。

那么,推出typedefs最简单的方法是什么呢?

如有任何帮助,我们将不胜感激。

编辑:

GCCXML的解决方案非常好,但我仍然不明白,如何获得C/C++代码。你能解释一下,我应该如何转换XML:吗

(an example from http://www.gccxml.org/HTML/example1out.html)
<?xml version="1.0"?>
<GCC_XML>
  <Namespace id="_1" name="::" members="_2 _3 _4 "/>
  <Function id="_2" name="main" returns="_5" context="_1" location="f0:8"/>
  <Function id="_3" name="a_function" returns="_5" context="_1" location="f0:4">
    <Argument name="f" type="_6"/>
    <Argument name="e" type="_4"/>
  </Function>
  <Struct id="_4" name="EmptyClass" context="_1" location="f0:1" members="_7 _8 " bases=""/>
  <FundamentalType id="_5" name="int"/>
  <FundamentalType id="_6" name="float"/>
  <Constructor id="_7" name="EmptyClass" context="_4" location="f0:1">
    <Argument name="_ctor_arg" type="_9"/>
  </Constructor>
  <Constructor id="_8" name="EmptyClass" context="_4" location="f0:1"/>
  <ReferenceType id="_9" type="_4c"/>
  <File id="f0" name="example1.cxx"/>
</GCC_XML>

返回C/C++:

(an example from http://www.gccxml.org/HTML/example1in.html)
struct EmptyClass {};
int a_function(float f, EmptyClass e)
{
}
int main(void)
{
  return 0;
}

你能解释一下吗?

由于类型是一个非常复杂的参数,我建议使用GCCXML。它是一个前端,从具体的源代码中生成一个抽象的语法树。我用它来生成Prolog/OOpenGL接口。如果你想充分利用它,你需要一个好的XML阅读器(SWI-Prolog非常擅长这方面)。

编辑

以下微文件x.c

typedef struct A {
  int X, Y;
} T;
T v[100];

处理

gccxml -fxml=x.xml x.c

在x.xml(以及许多其他文件)中生成以下xml语句

...
<Variable id="_3" name="v" type="_141" context="_1" location="f0:5" file="f0" line="5"/>
...
<Struct id="_139" name="A" context="_1" mangled="1A" demangled="A" location="f0:1" file="f0" line="1" artificial="1" size="64" align="32" members="_160 _161 _162 _163 _164 _165 " bases=""/>
<Typedef id="_140" name="T" type="_139" context="_1" location="f0:3" file="f0" line="3"/>
<ArrayType id="_141" min="0" max="99u" type="_140" size="6400" align="32"/>
...
<Field id="_160" name="X" type="_147" offset="0" context="_139" access="public" location="f0:2" file="f0" line="2"/>
<Field id="_161" name="Y" type="_147" offset="32" context="_139" access="public" location="f0:2" file="f0" line="2"/>
<Destructor id="_162" name="A" artificial="1" throw="" context="_139" access="public" mangled="_ZN1AD1Ev *INTERNAL* " demangled="A::~A()" location="f0:1" file="f0" line="1" endline="1" inline="1">
</Destructor>

您可以看到,在type="…"符号链之后,您可以重构分配给typedef的类型。

为了解析宏,您可以使用gcc预处理器cpp,它将预处理的代码打印到stdout。不幸的是,typedef不是宏,所以您需要自己处理它们。

在我看来,你是在跳过翻译阶段。与注释替换相比,Typedef替换似乎很容易。您的程序是否将以下内容识别为注释?如果没有,那么我建议回到翻译阶段1&2,然后尝试3&4.

// this is a basic comment
/* this is another basic comment */
// this is a slightly
   less basic comment
/* this is a slightly
 * less basic comment */
/??/
*??/
c??/
o??/
m??/
m??/
e??/
n??/
t??/
*??/
/

解析C++非常困难,需要递归下降语法分析器。我建议您按照@CapelliC的建议使用GCCXML,或者作为一个更好维护的替代方案,使用libclang。甚至存在Python绑定,这使得它的使用更加简单。