From 2e98270d45c3201e0ad684a798d217a9d0bfb258 Mon Sep 17 00:00:00 2001 From: David Majnemer Date: Thu, 1 Jan 2015 09:49:44 +0000 Subject: [PATCH] CodeGen: Don't crash when a lambda uses a local constexpr variable The DeclRefExpr might be for a variable initialized by a constant expression which hasn't been ODR used. Emit the initializer for the variable instead of trying to capture the variable itself. This fixes PR22071. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@225060 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGExpr.cpp | 32 +++++++++++++------------- test/CodeGenCXX/lambda-expressions.cpp | 12 ++++++++-- 2 files changed, 26 insertions(+), 18 deletions(-) diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index 16b624a9c3..8c04f138b8 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -1902,22 +1902,6 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) { QualType T = E->getType(); if (const auto *VD = dyn_cast(ND)) { - // Check for captured variables. - if (E->refersToCapturedVariable()) { - if (auto *FD = LambdaCaptureFields.lookup(VD)) - return EmitCapturedFieldLValue(*this, FD, CXXABIThisValue); - else if (CapturedStmtInfo) { - if (auto *V = LocalDeclMap.lookup(VD)) - return MakeAddrLValue(V, T, Alignment); - else - return EmitCapturedFieldLValue(*this, CapturedStmtInfo->lookup(VD), - CapturedStmtInfo->getContextValue()); - } - assert(isa(CurCodeDecl)); - return MakeAddrLValue(GetAddrOfBlockDecl(VD, VD->hasAttr()), - T, Alignment); - } - // Global Named registers access via intrinsics only if (VD->getStorageClass() == SC_Register && VD->hasAttr() && !VD->isLocalVarDecl()) @@ -1935,6 +1919,22 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) { // FIXME: Eventually we will want to emit vector element references. return MakeAddrLValue(Val, T, Alignment); } + + // Check for captured variables. + if (E->refersToCapturedVariable()) { + if (auto *FD = LambdaCaptureFields.lookup(VD)) + return EmitCapturedFieldLValue(*this, FD, CXXABIThisValue); + else if (CapturedStmtInfo) { + if (auto *V = LocalDeclMap.lookup(VD)) + return MakeAddrLValue(V, T, Alignment); + else + return EmitCapturedFieldLValue(*this, CapturedStmtInfo->lookup(VD), + CapturedStmtInfo->getContextValue()); + } + assert(isa(CurCodeDecl)); + return MakeAddrLValue(GetAddrOfBlockDecl(VD, VD->hasAttr()), + T, Alignment); + } } // FIXME: We should be able to assert this for FunctionDecls as well! diff --git a/test/CodeGenCXX/lambda-expressions.cpp b/test/CodeGenCXX/lambda-expressions.cpp index e35c6163d5..49b9efbdab 100644 --- a/test/CodeGenCXX/lambda-expressions.cpp +++ b/test/CodeGenCXX/lambda-expressions.cpp @@ -91,9 +91,17 @@ void staticarrayref(){ }(); } -// CHECK: define internal void @"_ZZ1hvEN3$_88__invokeEv"(%struct.A* noalias sret %agg.result) {{.*}} { +// CHECK-LABEL: define internal i32* @"_ZZ11PR22071_funvENK3$_8clEv" +// CHECK: ret i32* @PR22071_var +int PR22071_var; +int *PR22071_fun() { + constexpr int &y = PR22071_var; + return [&] { return &y; }(); +} + +// CHECK: define internal void @"_ZZ1hvEN3$_98__invokeEv"(%struct.A* noalias sret %agg.result) {{.*}} { // CHECK-NOT: = -// CHECK: call void @"_ZZ1hvENK3$_8clEv"(%struct.A* sret %agg.result, +// CHECK: call void @"_ZZ1hvENK3$_9clEv"(%struct.A* sret %agg.result, // CHECK-NEXT: ret void struct A { ~A(); }; void h() { -- 2.40.0