tbaeder created this revision.
tbaeder added reviewers: aaron.ballman, erichkeane, tahonermann, shafik.
Herald added a project: All.
tbaeder requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.
Move the logic for initialization of a lambda into
visitRecordInitializer(). When we visit a LambdaExpr outside of the
visitInitializer() logic, we need to create a new local variable so we
have a place to write the lambda members into.
This fixes passing lambas as arguments to function calls.
In that case, we visit a `LambdaExpr` without it being an initializer to
anything, so we should create a new local variable and return a pointer to it,
which we then pass to the function call.
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D153616
Files:
clang/lib/AST/Interp/ByteCodeExprGen.cpp
clang/test/AST/Interp/lambda.cpp
Index: clang/test/AST/Interp/lambda.cpp
===
--- clang/test/AST/Interp/lambda.cpp
+++ clang/test/AST/Interp/lambda.cpp
@@ -107,6 +107,29 @@
static_assert(foo() == 1); // expected-error {{not an integral constant expression}}
}
+namespace LambdasAsParams {
+ template
+ constexpr auto call(F f) {
+return f();
+ }
+ static_assert(call([](){ return 1;}) == 1);
+ static_assert(call([](){ return 2;}) == 2);
+
+
+ constexpr unsigned L = call([](){ return 12;});
+ static_assert(L == 12);
+
+
+ constexpr float heh() {
+auto a = []() {
+ return 1.0;
+};
+
+return static_cast(a());
+ }
+ static_assert(heh() == 1.0);
+}
+
namespace StaticInvoker {
constexpr int sv1(int i) {
auto l = []() { return 12; };
Index: clang/lib/AST/Interp/ByteCodeExprGen.cpp
===
--- clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -1062,39 +1062,15 @@
template
bool ByteCodeExprGen::VisitLambdaExpr(const LambdaExpr *E) {
- // XXX We assume here that a pointer-to-initialize is on the stack.
- const Record *R = P.getOrCreateRecord(E->getLambdaClass());
-
- auto *CaptureInitIt = E->capture_init_begin();
- // Initialize all fields (which represent lambda captures) of the
- // record with their initializers.
- for (const Record::Field &F : R->fields()) {
-const Expr *Init = *CaptureInitIt;
-++CaptureInitIt;
-
-if (std::optional T = classify(Init)) {
- if (!this->visit(Init))
-return false;
-
- if (!this->emitSetField(*T, F.Offset, E))
-return false;
-} else {
- if (!this->emitDupPtr(E))
-return false;
-
- if (!this->emitGetPtrField(F.Offset, E))
-return false;
-
- if (!this->visitInitializer(Init))
-return false;
+ if (std::optional GI = allocateLocal(E, /*IsExtended=*/false)) {
+if (!this->emitGetPtrLocal(*GI, E))
+ return false;
- if (!this->emitPopPtr(E))
-return false;
-}
+return this->visitRecordInitializer(E);
}
- return true;
+ return false;
}
template
@@ -1714,7 +1690,39 @@
return this->visitConditional(
ACO, [this](const Expr *E) { return this->visitRecordInitializer(E); });
} else if (const auto *LE = dyn_cast(Initializer)) {
-return this->VisitLambdaExpr(LE);
+// XXX We assume here that a pointer-to-initialize is on the stack.
+
+const Record *R = P.getOrCreateRecord(LE->getLambdaClass());
+
+auto *CaptureInitIt = LE->capture_init_begin();
+// Initialize all fields (which represent lambda captures) of the
+// record with their initializers.
+for (const Record::Field &F : R->fields()) {
+ const Expr *Init = *CaptureInitIt;
+ ++CaptureInitIt;
+
+ if (std::optional T = classify(Init)) {
+if (!this->visit(Init))
+ return false;
+
+if (!this->emitSetField(*T, F.Offset, LE))
+ return false;
+ } else {
+if (!this->emitDupPtr(LE))
+ return false;
+
+if (!this->emitGetPtrField(F.Offset, LE))
+ return false;
+
+if (!this->visitInitializer(Init))
+ return false;
+
+if (!this->emitPopPtr(LE))
+ return false;
+ }
+}
+
+return true;
}
return false;
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits