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; 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; };