手柄 C++使用 clang API 插入代码的函数

发布于 2024-11-18 13:52:47 字数 1432 浏览 2 评论 0原文

我需要预处理一些 C++ 文件以自动插入代码以进行测试和分析,并且我需要使用 clang API 来完成此操作。

现在,我希望能够执行以下操作: 如果有一个函数:

int SomeFn(int a, int b, int c) {
    doStuff();
}

我想预处理它,它看起来像这样:

int SomeFn(int a, int b, int c) {
    cout << "SomeFn is invoked with the following arguments: a=" << a << ", b=" << b << ", c=" << c << endl;
    doStuff();
}

我尝试扩展 ASTConsumer 并使用方法 HandleTopLevelDeclHandleTopLevelSingleDecl< /code> 并检查传递的 Decls 是否为 FunctionDecls 并将其向下转换,以便我可以获得它们的名称和主体位置。 但我不能那样处理类方法,只能处理全局函数。

我在 ASTConsumerHandleTagDeclDefinition(TagDecl* D) 中找到了一个函数。文档说:

每次调用此回调 TagDecl(例如结构、联合、枚举、 类)已完成。

但当我测试它时,看起来这个方法甚至没有被调用。

所以我的问题是,完成这项任务的正确方法是什么? C++ 类在 clang API 中是如何表示的?也许有人知道,我在哪里可以找到示例,因为 clang API 的文档很少。


更新:

我知道还有Visitors 的概念,并且有一个方法VisitRecordDecl(RecordDecl *D)。文档说 RecordDecl 代表类。因此,我扩展了 RecursiveASTVisitor 并实现了 VisitRecordDecl(RecordDecl *D) ,但似乎该方法也没有被调用。 相反,当找到类定义时,会调用 VisitVarDecl,就好像它被视为变量声明一样。 所以我有点困惑。我希望有人可以提供帮助...


UPDATE2:

我尝试解析另一个文件,这次 clang 找到了一个 RecordDecl。但该文件定义了一个结构体和两个类,因此我认为我的 clang 代码解析的是 C 而不是 C++。是否有任何设置可以在 C 和 C++ 之间切换

I need to preprocess some C++ files to automatically insert code for testing and profiling, and I need to do it with the clang API.

For now, I want to be able to do the following:
If there is a function:

int SomeFn(int a, int b, int c) {
    doStuff();
}

I want to preprocess it, that it looks like this:

int SomeFn(int a, int b, int c) {
    cout << "SomeFn is invoked with the following arguments: a=" << a << ", b=" << b << ", c=" << c << endl;
    doStuff();
}

I've tried to extend ASTConsumer and use the methods HandleTopLevelDecl and HandleTopLevelSingleDecl and check if the passed Decls are FunctionDecls and downcast them, so I can get their names and body-locations.
But I can't handle class-methods that way, only global functions.

I found a function in the ASTConsumer class HandleTagDeclDefinition(TagDecl* D). The documentation says:

This callback is invoked each time a
TagDecl (e.g. struct, union, enum,
class) is completed.

But it looks like this method isn't even invoked, when I test it.

So my question is, what would be the right way to do this task? And how are C++ classes are represented in the clang API? Maybe someone knows, where I can find examples because the clang API is poorly documented.


UPDATE:

I know there is also the concept of Visitors and there is a method VisitRecordDecl(RecordDecl *D). The documentation says that RecordDecl represents classes. So I extended RecursiveASTVisitor and implemented VisitRecordDecl(RecordDecl *D) but it seems, that this method isn't invoked neither.
Instead VisitVarDecl is invoked, when a class definition is find, as if it is seen as a variable declaration.
So I'm a bit confused. I hope, someone can help...


UPDATE2:

I tried to parse another file and this time clang found one RecordDecl. But the file defined one struct and two classes, so I think my clang code parses C instead of C++. Are there any settings to switch between C and C++ ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

动次打次papapa 2024-11-25 13:52:47

是否有任何设置可以在 C 和 C++ 之间切换?

最后我找到了如何处理这个问题:

我从 ASTConsumerRecursiveASTVisitor 扩展来遍历 AST 并实现 VisitCXXRecordDecl(CXXRecordDecl* D)。然后我必须为预处理器设置 LangOptions 参数,以便它解析 C++。

langOpts.CPlusPlus = 1;

我的错误是认为它会立即解析 C++,但事实并非如此,它默认解析 C,因此无法识别类。

Are there any settings to switch between C and C++ ?

Finally I found out how to handle this:

I extended from ASTConsumer and RecursiveASTVisitor<MyConsumer> to traverse the AST and implemented VisitCXXRecordDecl(CXXRecordDecl* D). Then I had to set the LangOptions parameter for the preprocessor, so it parses C++.

langOpts.CPlusPlus = 1;

My fault was to think that it would parse C++ right away, but that was not the case, it parses C as default and so doesn't recognize classes.

我是男神闪亮亮 2024-11-25 13:52:47

我想知道为什么你想即时进行这种转换(如果我理解正确的话)。这对于在类中定义的 C++ 方法尤其棘手,因为它们的编译就像在类外部定义的一样(即所有类成员都是可用的,即使是那些尚未声明的成员)。

无论如何,当你有一个 RecordDecl 时,你可以访问它的会员通过 field_begin

显然,当您遇到下一个类时,您也需要枚举它们。事实上,由于您可以在函数的类中定义方法,因此您几乎需要在所有地方检查嵌套声明。

I'm wondering why you want to do this transform on the fly (if I understand you right). This is especially tricky with C++ methods defined in-class, since they're compiled as-if they're defined outside the class (i.e. all class members are usable, even those not declared yet).

Anyway, when you have a RecordDecl, you can access its members via field_begin.

Obviously, when you encounter nexted classes, you'll need to enumerate those as well. In fact, since you can define methods in classes in functions, you'll need to check for nested declarations almost everywhere.

终难遇 2024-11-25 13:52:47

我同意 CLang 的文档在某些方面可能缺乏。不幸的是,这就是开源的工作方式:直到有人需要它、弄清楚并决定贡献他的发现之前,它都会缺乏。

对于您的具体问题,我建议您在 Clang Dev 邮件列表上发布(或从筛选开始档案)。有关 ASTConsumers 或其他转换分析的问题非常常见,并且通常会得到及时答复。

然后,当您了解了所需内容后,请考虑升级文档;)

I agree that the documentation of CLang might be lacking in some area. This is, unfortunately, the way Open Source works: it will lacking until someone needs it, figures it out and decide to contribute back his findings.

For you specific problem I suggest you post on the Clang Dev mailing list (or begin by sifting through the archives). Questions about ASTConsumers or other transform analysis are quite frequent and usually promptly answered to.

And then, when you've learned what you were looking for, do think about upgrading the documentation ;)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文