]> granicus.if.org Git - clang/commitdiff
CodeGen: Don't crash when a lambda uses a local constexpr variable
authorDavid Majnemer <david.majnemer@gmail.com>
Thu, 1 Jan 2015 09:49:44 +0000 (09:49 +0000)
committerDavid Majnemer <david.majnemer@gmail.com>
Thu, 1 Jan 2015 09:49:44 +0000 (09:49 +0000)
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
test/CodeGenCXX/lambda-expressions.cpp

index 16b624a9c31fc0f5051ab425ccf158c24c4e8dde..8c04f138b8dc9d775efa8254dca5afb4d7934675 100644 (file)
@@ -1902,22 +1902,6 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
   QualType T = E->getType();
 
   if (const auto *VD = dyn_cast<VarDecl>(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<BlockDecl>(CurCodeDecl));
-      return MakeAddrLValue(GetAddrOfBlockDecl(VD, VD->hasAttr<BlocksAttr>()),
-                            T, Alignment);
-    }
-
     // Global Named registers access via intrinsics only
     if (VD->getStorageClass() == SC_Register &&
         VD->hasAttr<AsmLabelAttr>() && !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<BlockDecl>(CurCodeDecl));
+      return MakeAddrLValue(GetAddrOfBlockDecl(VD, VD->hasAttr<BlocksAttr>()),
+                            T, Alignment);
+    }
   }
 
   // FIXME: We should be able to assert this for FunctionDecls as well!
index e35c6163d564a2235b34b1a201d719755728101a..49b9efbdaba27a39025312747ed3bfb571fefb87 100644 (file)
@@ -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() {