Clang 工具,用于提取给定 lambda 类型的 lambda 主体
Clang Tool that extracts the lambda body given the lambda type
我目前正在尝试实现一个基于RecursiveASTVisitors(基于本教程(的Clang工具,该工具基于给定函数的lambda应用代码转换。
例如,根据作为foo
参数给出的lambda生成一些东西:
foo([](){});
这很容易实现。查找名称为foo
的所有callExpr
,然后查找作为此callExpr
后代的所有lambdaExpr
s:
struct LambdaExprVisitor : public RecursiveASTVisitor<LambdaExprVisitor> {
bool VisitLambdaExpr(LambdaExpr * lambdaExpr) {
//Do stuff
lambdaExpr->getCallOperator()->getBody()->dump();
return true;
}
};
struct CallVisitor : public RecursiveASTVisitor<CallVisitor> {
//Find call expressions based on the given name
bool VisitCallExpr(CallExpr * expr) {
auto * callee = expr->getDirectCallee();
if(callee != nullptr && callee->getName() == "foo") {
visitor.TraverseCallExpr(expr);
}
return true;
}
LambdaExprVisitor visitor;
};
我现在遇到的问题是,有多种方法可以将lambda函数传递给这个原始函数foo
,例如:
auto bar() { return [](){}; }
int main() {
foo(bar());
}
而早期获得身体的方法在这里不起作用。
现在我认为 lambda 的主体在编译时是已知的,因此给定参数的Expr
值,lambda 主体必须以某种方式推断:
struct CallVisitor : public RecursiveASTVisitor<CallVisitor> {
bool VisitCallExpr(CallExpr * expr) {
auto * callee = expr->getDirectCallee();
if(callee != nullptr && callee->getName() == "foo") {
//Get the first argument which must be the lambda
auto * arg = expr->getArg(0);
//do something with the the first argument
//?
};
return true;
}
};
此时有没有办法获得 lambda 正文? 如果没有,有没有办法以不同的方式推断 lambda 体,而不必诉诸实现所有可能的方法将 lambda 体传递给foo
?
注意:基于匹配器的解决方案也适合我。
解决方案是首先遍历翻译单元,并将所有lambdaExpr
收集到一个类型为键的地图中。然后,在翻译单元的第二次遍历中,可以通过类型推断 lambda 的主体。 以下是修改后的访问者,它们现在存储对此地图的引用(该类型编码为其字符串表示形式(:
struct LambdaExprVisitor : public RecursiveASTVisitor<LambdaExprVisitor> {
LambdaExprVisitor(std::map<std::string, LambdaExpr *>& id2Expr) : RecursiveASTVisitor<LambdaExprVisitor> {}, id2Expr { id2Expr } {}
std::map<std::string, LambdaExpr *>& id2Expr;
bool VisitLambdaExpr(LambdaExpr * lambdaExpr) {
id2Expr.emplace(
lambdaExpr->getType().getAsString(),
lambdaExpr
);
return true;
}
};
struct CallVisitor : public RecursiveASTVisitor<CallVisitor> {
CallVisitor(std::map<std::string, LambdaExpr *>& id2Expr) : RecursiveASTVisitor<CallVisitor> {}, id2Expr { id2Expr } {}
std::map<std::string, LambdaExpr *>& id2Expr;
bool VisitCallExpr(CallExpr * expr) {
auto * callee = expr->getDirectCallee();
if(callee != nullptr && callee->getName() == "foo") {
//Get the expr from the map
auto arg = expr->getArg(0)->getType().getAsString();
if(auto iter = id2Expr.find(arg); iter != id2Expr.end()) {
//Do stuff with the lambdaExpr
auto * lambdaExpr = iter->second;
lambdaExpr->dump();
}
};
return true;
}
};
处理此问题ASTConsumer
只是存储此地图并执行两个访问者:
struct Consumer : public ASTConsumer {
public:
virtual void HandleTranslationUnit(clang::ASTContext &Context) override {
visitor.TraverseDecl(Context.getTranslationUnitDecl());
visitor2.TraverseDecl(Context.getTranslationUnitDecl());
}
std::map<std::string, LambdaExpr *> id2Expr;
LambdaExprVisitor visitor { id2Expr };
CallVisitor visitor2 { id2Expr };
};
相关文章:
- 如何建立使用模板函数的lambda函数的尾部返回类型
- 在 lambda 捕获中声明的变量的类型推导
- C++ 模板类型的静态 lambda 成员的构造
- Clang 工具,用于提取给定 lambda 类型的 lambda 主体
- 如果 lambda 没有指定的类型,std::function 如何接受 lambda?
- Lambda可以用作非类型模板参数吗
- 如何确定捕获不可复制参数的 lambda 的类型?
- 如何制作可以接受任何类型的参数的 std::函数和 lambda
- C++模板函数中,指定回调函子/lambda 的参数类型,同时仍允许内联?
- 运算符中的不同类型? 具有无捕获,相同的签名,lambda
- 通过参数传递 lambda(无函数类型模板)
- 有没有办法根据 lambda 参数返回类型部分专用化我的模板化函数?
- C++ 中的 Java8 lambda 类型比较
- 推断衰减到函数指针的 lambda 类型
- 从 lambda 内部返回 C++11 中的 lambda 类型(平面映射函数)
- 如何强制编译器识别模板化函数中的lambda类型
- 初始化和 lambda 类型参数
- 具有相同签名和捕获的常见 lambda 类型
- 我可以在std::函数中使用模板类型T来传递lambda类型的函数C++11吗
- C++ upper_bound 对 <lambda 类型的对象没有匹配的函数调用