isa = PBXProject;
buildConfigurationList = 1DEB923508733DC60010E9CD /* Build configuration list for PBXProject "clang" */;
compatibilityVersion = "Xcode 2.4";
- developmentRegion = English;
hasScannedForEncodings = 1;
knownRegions = (
English,
body_iterator body_begin() { return Body; }
body_iterator body_end() { return Body + NumStmts; }
Stmt *body_back() { return NumStmts ? Body[NumStmts-1] : 0; }
+
+ void setLastStmt(Stmt *S)
+ { assert(NumStmts && "setLastStmt"); Body[NumStmts-1] = S; }
typedef Stmt* const * const_body_iterator;
const_body_iterator body_begin() const { return Body; }
// If there are sub stmts in the compound stmt, take the type of the last one
// as the type of the stmtexpr.
QualType Ty = Context.VoidTy;
-
+ bool StmtExprMayBindToTemp = false;
if (!Compound->body_empty()) {
Stmt *LastStmt = Compound->body_back();
+ LabelStmt *LastLabelStmt = 0;
// If LastStmt is a label, skip down through into the body.
- while (LabelStmt *Label = dyn_cast<LabelStmt>(LastStmt))
+ while (LabelStmt *Label = dyn_cast<LabelStmt>(LastStmt)) {
+ LastLabelStmt = Label;
LastStmt = Label->getSubStmt();
-
- if (Expr *LastExpr = dyn_cast<Expr>(LastStmt))
+ }
+ if (Expr *LastExpr = dyn_cast<Expr>(LastStmt)) {
Ty = LastExpr->getType();
+ if (!Ty->isDependentType() && !LastExpr->isTypeDependent()) {
+ ExprResult Res = PerformCopyInitialization(
+ InitializedEntity::InitializeResult(LPLoc,
+ Ty,
+ false),
+ SourceLocation(),
+ Owned(LastExpr));
+ if (Res.isInvalid())
+ return ExprError();
+ if ((LastExpr = Res.takeAs<Expr>())) {
+ if (!LastLabelStmt)
+ Compound->setLastStmt(LastExpr);
+ else
+ LastLabelStmt->setSubStmt(LastExpr);
+ StmtExprMayBindToTemp = true;
+ }
+ }
+ }
}
// FIXME: Check that expression type is complete/non-abstract; statement
// expressions are not lvalues.
-
- return Owned(new (Context) StmtExpr(Compound, Ty, LPLoc, RPLoc));
+ Expr *ResStmtExpr = new (Context) StmtExpr(Compound, Ty, LPLoc, RPLoc);
+ if (StmtExprMayBindToTemp)
+ return MaybeBindToTemporary(ResStmtExpr);
+ return Owned(ResStmtExpr);
}
ExprResult Sema::BuildBuiltinOffsetOf(SourceLocation BuiltinLoc,
--- /dev/null
+// RUN: %clang_cc1 -Wno-unused-value -emit-llvm -o - %s | FileCheck %s
+// rdar: //8540501
+extern "C" int printf(...);
+extern "C" void abort();
+
+struct A
+{
+ int i;
+ A (int j) : i(j) {printf("this = %p A(%d)\n", this, j);}
+ A (const A &j) : i(j.i) {printf("this = %p const A&(%d)\n", this, i);}
+ A& operator= (const A &j) { i = j.i; abort(); return *this; }
+ ~A() { printf("this = %p ~A(%d)\n", this, i); }
+};
+
+struct B
+{
+ int i;
+ B (const A& a) { i = a.i; }
+ B() {printf("this = %p B()\n", this);}
+ B (const B &j) : i(j.i) {printf("this = %p const B&(%d)\n", this, i);}
+ ~B() { printf("this = %p ~B(%d)\n", this, i); }
+};
+
+A foo(int j)
+{
+ return ({ j ? A(1) : A(0); });
+}
+
+
+void foo2()
+{
+ A b = ({ A a(1); A a1(2); A a2(3); a1; a2; a; });
+ if (b.i != 1)
+ abort();
+ A c = ({ A a(1); A a1(2); A a2(3); a1; a2; a; A a3(4); a2; a3; });
+ if (c.i != 4)
+ abort();
+}
+
+void foo3()
+{
+ const A &b = ({ A a(1); a; });
+ if (b.i != 1)
+ abort();
+}
+
+void foo4()
+{
+// CHECK: call void @_ZN1AC1Ei
+// CHECK: call void @_ZN1AC1ERKS_
+// CHECK: call void @_ZN1AD1Ev
+// CHECK: call void @_ZN1BC1ERK1A
+// CHECK: call void @_ZN1AD1Ev
+ const B &b = ({ A a(1); a; });
+ if (b.i != 1)
+ abort();
+}
+
+int main()
+{
+ foo2();
+ foo3();
+ foo4();
+ return foo(1).i-1;
+}