[cfe-commits] r156781 - in /cfe/trunk: lib/CodeGen/CGExpr.cpp lib/CodeGen/CodeGenFunction.h test/CodeGenCXX/cxx0x-initializer-references.cpp test/CodeGenCXX/cxx11-initializer-aggregate.cpp

Richard Smith richard-llvm at metafoo.co.uk
Mon May 14 14:57:22 PDT 2012


Author: rsmith
Date: Mon May 14 16:57:21 2012
New Revision: 156781

URL: http://llvm.org/viewvc/llvm-project?rev=156781&view=rev
Log:
Implement IRGen for C++11's "T{1, 2, 3}", where T is an aggregate and the
expression is treated as an lvalue.

Added:
    cfe/trunk/test/CodeGenCXX/cxx11-initializer-aggregate.cpp
Modified:
    cfe/trunk/lib/CodeGen/CGExpr.cpp
    cfe/trunk/lib/CodeGen/CodeGenFunction.h
    cfe/trunk/test/CodeGenCXX/cxx0x-initializer-references.cpp

Modified: cfe/trunk/lib/CodeGen/CGExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExpr.cpp?rev=156781&r1=156780&r2=156781&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExpr.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExpr.cpp Mon May 14 16:57:21 2012
@@ -671,10 +671,7 @@
   case Expr::PseudoObjectExprClass:
     return EmitPseudoObjectLValue(cast<PseudoObjectExpr>(E));
   case Expr::InitListExprClass:
-    assert(cast<InitListExpr>(E)->getNumInits() == 1 &&
-           "Only single-element init list can be lvalue.");
-    return EmitLValue(cast<InitListExpr>(E)->getInit(0));
-
+    return EmitInitListLValue(cast<InitListExpr>(E));
   case Expr::CXXTemporaryObjectExprClass:
   case Expr::CXXConstructExprClass:
     return EmitCXXConstructLValue(cast<CXXConstructExpr>(E));
@@ -2129,6 +2126,16 @@
   return Result;
 }
 
+LValue CodeGenFunction::EmitInitListLValue(const InitListExpr *E) {
+  if (!E->isGLValue())
+    // Initializing an aggregate temporary in C++11: T{...}.
+    return EmitAggExprToLValue(E);
+
+  // An lvalue initializer list must be initializing a reference.
+  assert(E->getNumInits() == 1 && "reference init with multiple values");
+  return EmitLValue(E->getInit(0));
+}
+
 LValue CodeGenFunction::
 EmitConditionalOperatorLValue(const AbstractConditionalOperator *expr) {
   if (!expr->isGLValue()) {
@@ -2188,11 +2195,11 @@
   return MakeAddrLValue(phi, expr->getType());
 }
 
-/// EmitCastLValue - Casts are never lvalues unless that cast is a dynamic_cast.
-/// If the cast is a dynamic_cast, we can have the usual lvalue result,
+/// EmitCastLValue - Casts are never lvalues unless that cast is to a reference
+/// type. If the cast is to a reference, we can have the usual lvalue result,
 /// otherwise if a cast is needed by the code generator in an lvalue context,
 /// then it must mean that we need the address of an aggregate in order to
-/// access one of its fields.  This can happen for all the reasons that casts
+/// access one of its members.  This can happen for all the reasons that casts
 /// are permitted with aggregate result, including noop aggregate casts, and
 /// cast from scalar to union.
 LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) {

Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=156781&r1=156780&r2=156781&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Mon May 14 16:57:21 2012
@@ -2104,6 +2104,7 @@
   LValue EmitMemberExpr(const MemberExpr *E);
   LValue EmitObjCIsaExpr(const ObjCIsaExpr *E);
   LValue EmitCompoundLiteralLValue(const CompoundLiteralExpr *E);
+  LValue EmitInitListLValue(const InitListExpr *E);
   LValue EmitConditionalOperatorLValue(const AbstractConditionalOperator *E);
   LValue EmitCastLValue(const CastExpr *E);
   LValue EmitNullInitializationLValue(const CXXScalarValueInitExpr *E);

Modified: cfe/trunk/test/CodeGenCXX/cxx0x-initializer-references.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/cxx0x-initializer-references.cpp?rev=156781&r1=156780&r2=156781&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/cxx0x-initializer-references.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/cxx0x-initializer-references.cpp Mon May 14 16:57:21 2012
@@ -28,6 +28,10 @@
     // CHECK-NEXT: store %{{.*}}* %{{.*}}, %{{.*}}** %
     A &ra1a = {a};
 
+    using T = A&;
+    // CHECK-NEXT: store %{{.*}}* %{{.*}}, %{{.*}}** %
+    A &ra1b = T{a};
+
     // CHECK-NEXT: ret
   }
 

Added: cfe/trunk/test/CodeGenCXX/cxx11-initializer-aggregate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/cxx11-initializer-aggregate.cpp?rev=156781&view=auto
==============================================================================
--- cfe/trunk/test/CodeGenCXX/cxx11-initializer-aggregate.cpp (added)
+++ cfe/trunk/test/CodeGenCXX/cxx11-initializer-aggregate.cpp Mon May 14 16:57:21 2012
@@ -0,0 +1,25 @@
+// RUN: %clang_cc1 -std=c++11 -S -emit-llvm -o - %s -triple x86_64-linux-gnu | FileCheck %s
+
+struct A { int a, b; int f(); };
+
+// CHECK: define {{.*}}@_Z3fn1i(
+int fn1(int x) {
+  // CHECK: %[[INITLIST:.*]] = alloca %struct.A
+  // CHECK: %[[A:.*]] = getelementptr inbounds %struct.A* %[[INITLIST]], i32 0, i32 0
+  // CHECK: store i32 %{{.*}}, i32* %[[A]], align 4
+  // CHECK: %[[B:.*]] = getelementptr inbounds %struct.A* %[[INITLIST]], i32 0, i32 1
+  // CHECK: store i32 5, i32* %[[B]], align 4
+  // CHECK: call i32 @_ZN1A1fEv(%struct.A* %[[INITLIST]])
+  return A{x, 5}.f();
+}
+
+struct B { int &r; int &f() { return r; } };
+
+// CHECK: define {{.*}}@_Z3fn2Ri(
+int &fn2(int &v) {
+  // CHECK: %[[INITLIST2:.*]] = alloca %struct.B, align 8
+  // CHECK: %[[R:.*]] = getelementptr inbounds %struct.B* %[[INITLIST2:.*]], i32 0, i32 0
+  // CHECK: store i32* %{{.*}}, i32** %[[R]], align 8
+  // CHECK: %call = call i32* @_ZN1B1fEv(%struct.B* %[[INITLIST2:.*]])
+  return B{v}.f();
+}





More information about the cfe-commits mailing list