mirror of
https://github.com/intel/llvm.git
synced 2026-02-04 19:44:15 +08:00
Implement IRGen for C++11's "T{1, 2, 3}", where T is an aggregate and the
expression is treated as an lvalue. llvm-svn: 156781
This commit is contained in:
@@ -671,10 +671,7 @@ LValue CodeGenFunction::EmitLValue(const Expr *E) {
|
||||
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 @@ LValue CodeGenFunction::EmitCompoundLiteralLValue(const CompoundLiteralExpr *E){
|
||||
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 @@ EmitConditionalOperatorLValue(const AbstractConditionalOperator *expr) {
|
||||
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) {
|
||||
|
||||
@@ -2104,6 +2104,7 @@ public:
|
||||
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);
|
||||
|
||||
@@ -28,6 +28,10 @@ namespace reference {
|
||||
// CHECK-NEXT: store %{{.*}}* %{{.*}}, %{{.*}}** %
|
||||
A &ra1a = {a};
|
||||
|
||||
using T = A&;
|
||||
// CHECK-NEXT: store %{{.*}}* %{{.*}}, %{{.*}}** %
|
||||
A &ra1b = T{a};
|
||||
|
||||
// CHECK-NEXT: ret
|
||||
}
|
||||
|
||||
|
||||
25
clang/test/CodeGenCXX/cxx11-initializer-aggregate.cpp
Normal file
25
clang/test/CodeGenCXX/cxx11-initializer-aggregate.cpp
Normal file
@@ -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();
|
||||
}
|
||||
Reference in New Issue
Block a user