diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/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 diff --git a/clang/test/SemaCXX/lambda-default-arg.cpp b/clang/test/SemaCXX/lambda-default-arg.cpp new file mode 100644 --- /dev/null +++ b/clang/test/SemaCXX/lambda-default-arg.cpp @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -std=c++17 -verify -fsyntax-only %s + +template bool test0() { + constexpr float a = 1e-5f; + return [=](float b = a) -> bool { + return a < 0; + }(); +} + +bool b0 = test0(); + +template 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();