ahatanak created this revision. ahatanak added reviewers: tahonermann, erichkeane, aaron.ballman, shafik, Bigcheese, arphaman. ahatanak added a project: clang. Herald added a project: All. ahatanak requested review of this revision.
This is needed to fix https://github.com/llvm/llvm-project/issues/60155. An assertion in `tryCaptureVariable` fails because `SubstDefaultArgument` pushes the context for the lambda's function operator, but the LambdaScopeInfo isn't being pushed to the stack. It appears that the assertion started to fail in 4409a83c293537e22da046b54e9f69454cdd3dca <https://reviews.llvm.org/rG4409a83c293537e22da046b54e9f69454cdd3dca>, which delays instantiation of default arguments. By the time the default arguments are instantiated, which happens after `inherited::TransformLambdaExpr` is called, the lambda scope has already been popped. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D143109 Files: clang/lib/Sema/SemaTemplateInstantiate.cpp clang/test/SemaCXX/lambda-default-arg.cpp Index: clang/test/SemaCXX/lambda-default-arg.cpp =================================================================== --- /dev/null +++ clang/test/SemaCXX/lambda-default-arg.cpp @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -std=c++17 -verify -fsyntax-only %s + +template <class T> bool test0() { + constexpr float a = 1e-5f; + return [=](float b = a) -> bool { + return a < 0; + }(); +} + +bool b0 = test0<int>(); + +template <class T> bool test1() { + float a = 1e-5f; + return [=](float b = a) -> bool { // expected-error {{default argument references local variable 'a'}} + return a < 0; + }(); +} + +bool b1 = test1<int>(); Index: clang/lib/Sema/SemaTemplateInstantiate.cpp =================================================================== --- clang/lib/Sema/SemaTemplateInstantiate.cpp +++ clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -1348,6 +1348,13 @@ Expr *UninstExpr = PVD->getUninstantiatedDefaultArg(); // FIXME: Obtain the source location for the '=' token. SourceLocation EqualLoc = UninstExpr->getBeginLoc(); + + // Push an empty lambda scope. This is needed as SubstDefaultArgument + // pushes the context for the lambda's function call operator and we + // need to keep the contexts and the function scopes in sync. + getSema().PushLambdaScope(); + Sema::FunctionScopeRAII FuncScopeCleanup(getSema()); + if (SemaRef.SubstDefaultArgument(EqualLoc, PVD, TemplateArgs)) { // If substitution fails, the default argument is set to a // RecoveryExpr that wraps the uninstantiated default argument so
Index: clang/test/SemaCXX/lambda-default-arg.cpp =================================================================== --- /dev/null +++ clang/test/SemaCXX/lambda-default-arg.cpp @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -std=c++17 -verify -fsyntax-only %s + +template <class T> bool test0() { + constexpr float a = 1e-5f; + return [=](float b = a) -> bool { + return a < 0; + }(); +} + +bool b0 = test0<int>(); + +template <class T> bool test1() { + float a = 1e-5f; + return [=](float b = a) -> bool { // expected-error {{default argument references local variable 'a'}} + return a < 0; + }(); +} + +bool b1 = test1<int>(); Index: clang/lib/Sema/SemaTemplateInstantiate.cpp =================================================================== --- clang/lib/Sema/SemaTemplateInstantiate.cpp +++ clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -1348,6 +1348,13 @@ Expr *UninstExpr = PVD->getUninstantiatedDefaultArg(); // FIXME: Obtain the source location for the '=' token. SourceLocation EqualLoc = UninstExpr->getBeginLoc(); + + // Push an empty lambda scope. This is needed as SubstDefaultArgument + // pushes the context for the lambda's function call operator and we + // need to keep the contexts and the function scopes in sync. + getSema().PushLambdaScope(); + Sema::FunctionScopeRAII FuncScopeCleanup(getSema()); + if (SemaRef.SubstDefaultArgument(EqualLoc, PVD, TemplateArgs)) { // If substitution fails, the default argument is set to a // RecoveryExpr that wraps the uninstantiated default argument so
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits