aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2013-04-20 22:23:05 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2013-04-20 22:23:05 +0000
commitc3bf52ced9652f555aa0767bb822ec4c64546212 (patch)
treee1bc9a6ecec46f15038eb98b525de05179d8479b
parent7db58e0fe92a7a64daf14f78ceea103ba7fbf03d (diff)
C++1y: Allow aggregates to have default initializers.
Add a CXXDefaultInitExpr, analogous to CXXDefaultArgExpr, and use it both in CXXCtorInitializers and in InitListExprs to represent a default initializer. There's an additional complication here: because the default initializer can refer to the initialized object via its 'this' pointer, we need to make sure that 'this' points to the right thing within the evaluation. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@179958 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/AST/DeclCXX.h14
-rw-r--r--include/clang/AST/ExprCXX.h47
-rw-r--r--include/clang/AST/RecursiveASTVisitor.h1
-rw-r--r--include/clang/Basic/StmtNodes.td1
-rw-r--r--include/clang/Serialization/ASTBitCodes.h1
-rw-r--r--lib/AST/DeclCXX.cpp7
-rw-r--r--lib/AST/DeclPrinter.cpp2
-rw-r--r--lib/AST/Expr.cpp26
-rw-r--r--lib/AST/ExprCXX.cpp11
-rw-r--r--lib/AST/ExprClassification.cpp4
-rw-r--r--lib/AST/ExprConstant.cpp38
-rw-r--r--lib/AST/ItaniumMangle.cpp4
-rw-r--r--lib/AST/StmtPrinter.cpp6
-rw-r--r--lib/AST/StmtProfile.cpp5
-rw-r--r--lib/Analysis/CFG.cpp5
-rw-r--r--lib/CodeGen/CGClass.cpp1
-rw-r--r--lib/CodeGen/CGExpr.cpp4
-rw-r--r--lib/CodeGen/CGExprAgg.cpp9
-rw-r--r--lib/CodeGen/CGExprComplex.cpp4
-rw-r--r--lib/CodeGen/CGExprConstant.cpp6
-rw-r--r--lib/CodeGen/CGExprScalar.cpp4
-rw-r--r--lib/CodeGen/CodeGenFunction.cpp1
-rw-r--r--lib/CodeGen/CodeGenFunction.h41
-rw-r--r--lib/Sema/SemaDeclCXX.cpp8
-rw-r--r--lib/Sema/SemaExceptionSpec.cpp7
-rw-r--r--lib/Sema/SemaInit.cpp59
-rw-r--r--lib/Sema/TreeTransform.h26
-rw-r--r--lib/Serialization/ASTReaderStmt.cpp9
-rw-r--r--lib/Serialization/ASTWriterStmt.cpp7
-rw-r--r--lib/StaticAnalyzer/Core/ExprEngine.cpp1
-rw-r--r--test/CXX/dcl.decl/dcl.init/dcl.init.aggr/p1-0x.cpp13
-rw-r--r--test/CXX/dcl.decl/dcl.init/dcl.init.aggr/p7.cpp23
-rw-r--r--test/CodeGenCXX/cxx1y-initializer-aggregate.cpp74
-rw-r--r--test/SemaCXX/cxx1y-initializer-aggregates.cpp63
-rw-r--r--tools/libclang/CXCursor.cpp1
-rw-r--r--tools/libclang/RecursiveASTVisitor.h1
-rw-r--r--www/cxx_status.html2
37 files changed, 495 insertions, 41 deletions
diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h
index 5506d211cc..eb6035680b 100644
--- a/include/clang/AST/DeclCXX.h
+++ b/include/clang/AST/DeclCXX.h
@@ -1754,8 +1754,6 @@ class CXXCtorInitializer {
/// \brief The argument used to initialize the base or member, which may
/// end up constructing an object (when multiple arguments are involved).
- /// If 0, this is a field initializer, and the in-class member initializer
- /// will be used.
Stmt *Init;
/// LParenLoc - Location of the left paren of the ctor-initializer.
@@ -1840,7 +1838,7 @@ public:
/// implicit ctor initializer generated for a field with an initializer
/// defined on the member declaration.
bool isInClassMemberInitializer() const {
- return !Init;
+ return isa<CXXDefaultInitExpr>(Init);
}
/// isDelegatingInitializer - Returns true when this initializer is creating
@@ -1967,14 +1965,8 @@ public:
getNumArrayIndices());
}
- /// \brief Get the initializer. This is 0 if this is an in-class initializer
- /// for a non-static data member which has not yet been parsed.
- Expr *getInit() const {
- if (!Init)
- return getAnyMember()->getInClassInitializer();
-
- return static_cast<Expr*>(Init);
- }
+ /// \brief Get the initializer.
+ Expr *getInit() const { return static_cast<Expr*>(Init); }
};
/// CXXConstructorDecl - Represents a C++ constructor within a
diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h
index 3189426f9d..91e5b21eac 100644
--- a/include/clang/AST/ExprCXX.h
+++ b/include/clang/AST/ExprCXX.h
@@ -884,6 +884,53 @@ public:
friend class ASTStmtWriter;
};
+/// \brief This wraps a use of a C++ default initializer (technically,
+/// a brace-or-equal-initializer for a non-static data member) when it
+/// is implicitly used in a mem-initializer-list in a constructor
+/// (C++11 [class.base.init]p8) or in aggregate initialization
+/// (C++1y [dcl.init.aggr]p7).
+class CXXDefaultInitExpr : public Expr {
+ /// \brief The field whose default is being used.
+ FieldDecl *Field;
+
+ /// \brief The location where the default initializer expression was used.
+ SourceLocation Loc;
+
+ CXXDefaultInitExpr(ASTContext &C, SourceLocation Loc, FieldDecl *Field,
+ QualType T);
+
+ CXXDefaultInitExpr(EmptyShell Empty) : Expr(CXXDefaultInitExprClass, Empty) {}
+
+public:
+ // Field is the non-static data member whose default initializer is used
+ // by this expression.
+ static CXXDefaultInitExpr *Create(ASTContext &C, SourceLocation Loc,
+ FieldDecl *Field) {
+ return new (C) CXXDefaultInitExpr(C, Loc, Field, Field->getType());
+ }
+
+ // Get the field whose initializer will be used.
+ FieldDecl *getField() { return Field; }
+ const FieldDecl *getField() const { return Field; }
+
+ // Get the initialization expression that will be used.
+ const Expr *getExpr() const { return Field->getInClassInitializer(); }
+ Expr *getExpr() { return Field->getInClassInitializer(); }
+
+ SourceLocation getLocStart() const LLVM_READONLY { return Loc; }
+ SourceLocation getLocEnd() const LLVM_READONLY { return Loc; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CXXDefaultInitExprClass;
+ }
+
+ // Iterators
+ child_range children() { return child_range(); }
+
+ friend class ASTReader;
+ friend class ASTStmtReader;
+};
+
/// CXXTemporary - Represents a C++ temporary.
class CXXTemporary {
/// Destructor - The destructor that needs to be called.
diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h
index df41b6fa5a..eb5a8123c2 100644
--- a/include/clang/AST/RecursiveASTVisitor.h
+++ b/include/clang/AST/RecursiveASTVisitor.h
@@ -2170,6 +2170,7 @@ DEF_TRAVERSE_STMT(CompoundLiteralExpr, {
DEF_TRAVERSE_STMT(CXXBindTemporaryExpr, { })
DEF_TRAVERSE_STMT(CXXBoolLiteralExpr, { })
DEF_TRAVERSE_STMT(CXXDefaultArgExpr, { })
+DEF_TRAVERSE_STMT(CXXDefaultInitExpr, { })
DEF_TRAVERSE_STMT(CXXDeleteExpr, { })
DEF_TRAVERSE_STMT(ExprWithCleanups, { })
DEF_TRAVERSE_STMT(CXXNullPtrLiteralExpr, { })
diff --git a/include/clang/Basic/StmtNodes.td b/include/clang/Basic/StmtNodes.td
index ad25e57c89..cbfce83c4b 100644
--- a/include/clang/Basic/StmtNodes.td
+++ b/include/clang/Basic/StmtNodes.td
@@ -108,6 +108,7 @@ def CXXNullPtrLiteralExpr : DStmt<Expr>;
def CXXThisExpr : DStmt<Expr>;
def CXXThrowExpr : DStmt<Expr>;
def CXXDefaultArgExpr : DStmt<Expr>;
+def CXXDefaultInitExpr : DStmt<Expr>;
def CXXScalarValueInitExpr : DStmt<Expr>;
def CXXNewExpr : DStmt<Expr>;
def CXXDeleteExpr : DStmt<Expr>;
diff --git a/include/clang/Serialization/ASTBitCodes.h b/include/clang/Serialization/ASTBitCodes.h
index 9f5e8b1224..81f8980425 100644
--- a/include/clang/Serialization/ASTBitCodes.h
+++ b/include/clang/Serialization/ASTBitCodes.h
@@ -1267,6 +1267,7 @@ namespace clang {
EXPR_CXX_THIS, // CXXThisExpr
EXPR_CXX_THROW, // CXXThrowExpr
EXPR_CXX_DEFAULT_ARG, // CXXDefaultArgExpr
+ EXPR_CXX_DEFAULT_INIT, // CXXDefaultInitExpr
EXPR_CXX_BIND_TEMPORARY, // CXXBindTemporaryExpr
EXPR_CXX_SCALAR_VALUE_INIT, // CXXScalarValueInitExpr
diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp
index 2c7c4d335d..ece831571c 100644
--- a/lib/AST/DeclCXX.cpp
+++ b/lib/AST/DeclCXX.cpp
@@ -505,7 +505,7 @@ void CXXRecordDecl::addedMember(Decl *D) {
// C++ [dcl.init.aggr]p1:
// An aggregate is an array or a class with no user-declared
// constructors [...].
- // C++0x [dcl.init.aggr]p1:
+ // C++11 [dcl.init.aggr]p1:
// An aggregate is an array or a class with no user-provided
// constructors [...].
if (getASTContext().getLangOpts().CPlusPlus11
@@ -690,7 +690,10 @@ void CXXRecordDecl::addedMember(Decl *D) {
// C++11 [dcl.init.aggr]p1:
// An aggregate is a [...] class with [...] no
// brace-or-equal-initializers for non-static data members.
- data().Aggregate = false;
+ //
+ // This rule was removed in C++1y.
+ if (!getASTContext().getLangOpts().CPlusPlus1y)
+ data().Aggregate = false;
// C++11 [class]p10:
// A POD struct is [...] a trivial class.
diff --git a/lib/AST/DeclPrinter.cpp b/lib/AST/DeclPrinter.cpp
index 995925350c..bcc4e3865a 100644
--- a/lib/AST/DeclPrinter.cpp
+++ b/lib/AST/DeclPrinter.cpp
@@ -487,7 +487,7 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
for (CXXConstructorDecl::init_const_iterator B = CDecl->init_begin(),
E = CDecl->init_end();
B != E; ++B) {
- CXXCtorInitializer * BMInitializer = (*B);
+ CXXCtorInitializer *BMInitializer = (*B);
if (BMInitializer->isInClassMemberInitializer())
continue;
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index 748d3084fe..1303fb0cee 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -100,11 +100,20 @@ Expr::skipRValueSubobjectAdjustments(
const Expr *
Expr::findMaterializedTemporary(const MaterializeTemporaryExpr *&MTE) const {
const Expr *E = this;
+
+ // This might be a default initializer for a reference member. Walk over the
+ // wrapper node for that.
+ if (const CXXDefaultInitExpr *DAE = dyn_cast<CXXDefaultInitExpr>(E))
+ E = DAE->getExpr();
+
// Look through single-element init lists that claim to be lvalues. They're
// just syntactic wrappers in this case.
if (const InitListExpr *ILE = dyn_cast<InitListExpr>(E)) {
- if (ILE->getNumInits() == 1 && ILE->isGLValue())
+ if (ILE->getNumInits() == 1 && ILE->isGLValue()) {
E = ILE->getInit(0);
+ if (const CXXDefaultInitExpr *DAE = dyn_cast<CXXDefaultInitExpr>(E))
+ E = DAE->getExpr();
+ }
}
// Look through expressions for materialized temporaries (for now).
@@ -2174,6 +2183,9 @@ bool Expr::isUnusedResultAWarning(const Expr *&WarnE, SourceLocation &Loc,
case CXXDefaultArgExprClass:
return (cast<CXXDefaultArgExpr>(this)
->getExpr()->isUnusedResultAWarning(WarnE, Loc, R1, R2, Ctx));
+ case CXXDefaultInitExprClass:
+ return (cast<CXXDefaultInitExpr>(this)
+ ->getExpr()->isUnusedResultAWarning(WarnE, Loc, R1, R2, Ctx));
case CXXNewExprClass:
// FIXME: In theory, there might be new expressions that don't have side
@@ -2851,6 +2863,12 @@ bool Expr::HasSideEffects(const ASTContext &Ctx) const {
case CXXDefaultArgExprClass:
return cast<CXXDefaultArgExpr>(this)->getExpr()->HasSideEffects(Ctx);
+ case CXXDefaultInitExprClass:
+ if (const Expr *E = cast<CXXDefaultInitExpr>(this)->getExpr())
+ return E->HasSideEffects(Ctx);
+ // If we've not yet parsed the initializer, assume it has side-effects.
+ return true;
+
case CXXDynamicCastExprClass: {
// A dynamic_cast expression has side-effects if it can throw.
const CXXDynamicCastExpr *DCE = cast<CXXDynamicCastExpr>(this);
@@ -3038,8 +3056,12 @@ Expr::isNullPointerConstant(ASTContext &Ctx,
return GE->getResultExpr()->isNullPointerConstant(Ctx, NPC);
} else if (const CXXDefaultArgExpr *DefaultArg
= dyn_cast<CXXDefaultArgExpr>(this)) {
- // See through default argument expressions
+ // See through default argument expressions.
return DefaultArg->getExpr()->isNullPointerConstant(Ctx, NPC);
+ } else if (const CXXDefaultInitExpr *DefaultInit
+ = dyn_cast<CXXDefaultInitExpr>(this)) {
+ // See through default initializer expressions.
+ return DefaultInit->getExpr()->isNullPointerConstant(Ctx, NPC);
} else if (isa<GNUNullExpr>(this)) {
// The GNU __null extension is always a null pointer constant.
return NPCK_GNUNull;
diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp
index 12a47fcd78..277c8c09a5 100644
--- a/lib/AST/ExprCXX.cpp
+++ b/lib/AST/ExprCXX.cpp
@@ -704,6 +704,17 @@ CXXDefaultArgExpr::Create(ASTContext &C, SourceLocation Loc,
SubExpr);
}
+CXXDefaultInitExpr::CXXDefaultInitExpr(ASTContext &C, SourceLocation Loc,
+ FieldDecl *Field, QualType T)
+ : Expr(CXXDefaultInitExprClass, T.getNonLValueExprType(C),
+ T->isLValueReferenceType() ? VK_LValue : T->isRValueReferenceType()
+ ? VK_XValue
+ : VK_RValue,
+ /*FIXME*/ OK_Ordinary, false, false, false, false),
+ Field(Field), Loc(Loc) {
+ assert(Field->hasInClassInitializer());
+}
+
CXXTemporary *CXXTemporary::Create(ASTContext &C,
const CXXDestructorDecl *Destructor) {
return new (C) CXXTemporary(Destructor);
diff --git a/lib/AST/ExprClassification.cpp b/lib/AST/ExprClassification.cpp
index c2a35f42c1..bcb6d4e809 100644
--- a/lib/AST/ExprClassification.cpp
+++ b/lib/AST/ExprClassification.cpp
@@ -298,6 +298,10 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) {
case Expr::CXXDefaultArgExprClass:
return ClassifyInternal(Ctx, cast<CXXDefaultArgExpr>(E)->getExpr());
+ // Same idea for default initializers.
+ case Expr::CXXDefaultInitExprClass:
+ return ClassifyInternal(Ctx, cast<CXXDefaultInitExpr>(E)->getExpr());
+
// Same idea for temporary binding.
case Expr::CXXBindTemporaryExprClass:
return ClassifyInternal(Ctx, cast<CXXBindTemporaryExpr>(E)->getSubExpr());
diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp
index 3675b2ff44..4e468806dc 100644
--- a/lib/AST/ExprConstant.cpp
+++ b/lib/AST/ExprConstant.cpp
@@ -301,6 +301,22 @@ namespace {
~CallStackFrame();
};
+ /// Temporarily override 'this'.
+ class ThisOverrideRAII {
+ public:
+ ThisOverrideRAII(CallStackFrame &Frame, const LValue *NewThis, bool Enable)
+ : Frame(Frame), OldThis(Frame.This) {
+ if (Enable)
+ Frame.This = NewThis;
+ }
+ ~ThisOverrideRAII() {
+ Frame.This = OldThis;
+ }
+ private:
+ CallStackFrame &Frame;
+ const LValue *OldThis;
+ };
+
/// A partial diagnostic which we might know in advance that we are not going
/// to emit.
class OptionalDiagnostic {
@@ -2397,6 +2413,8 @@ public:
{ return StmtVisitorTy::Visit(E->getReplacement()); }
RetTy VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *E)
{ return StmtVisitorTy::Visit(E->getExpr()); }
+ RetTy VisitCXXDefaultInitExpr(const CXXDefaultInitExpr *E)
+ { return StmtVisitorTy::Visit(E->getExpr()); }
// We cannot create any objects for which cleanups are required, so there is
// nothing to do here; all cleanups must come from unevaluated subexpressions.
RetTy VisitExprWithCleanups(const ExprWithCleanups *E)
@@ -3398,12 +3416,20 @@ bool RecordExprEvaluator::VisitInitListExpr(const InitListExpr *E) {
// If the initializer list for a union does not contain any elements, the
// first element of the union is value-initialized.
+ // FIXME: The element should be initialized from an initializer list.
+ // Is this difference ever observable for initializer lists which
+ // we don't build?
ImplicitValueInitExpr VIE(Field->getType());
const Expr *InitExpr = E->getNumInits() ? E->getInit(0) : &VIE;
LValue Subobject = This;
if (!HandleLValueMember(Info, InitExpr, Subobject, Field, &Layout))
return false;
+
+ // Temporarily override This, in case there's a CXXDefaultInitExpr in here.
+ ThisOverrideRAII ThisOverride(*Info.CurrentCall, &This,
+ isa<CXXDefaultInitExpr>(InitExpr));
+
return EvaluateInPlace(Result.getUnionValue(), Info, Subobject, InitExpr);
}
@@ -3433,10 +3459,14 @@ bool RecordExprEvaluator::VisitInitListExpr(const InitListExpr *E) {
// Perform an implicit value-initialization for members beyond the end of
// the initializer list.
ImplicitValueInitExpr VIE(HaveInit ? Info.Ctx.IntTy : Field->getType());
+ const Expr *Init = HaveInit ? E->getInit(ElementNo++) : &VIE;
- if (!EvaluateInPlace(
- Result.getStructField(Field->getFieldIndex()),
- Info, Subobject, HaveInit ? E->getInit(ElementNo++) : &VIE)) {
+ // Temporarily override This, in case there's a CXXDefaultInitExpr in here.
+ ThisOverrideRAII ThisOverride(*Info.CurrentCall, &This,
+ isa<CXXDefaultInitExpr>(Init));
+
+ if (!EvaluateInPlace(Result.getStructField(Field->getFieldIndex()), Info,
+ Subobject, Init)) {
if (!Info.keepEvaluatingAfterFailure())
return false;
Success = false;
@@ -6807,6 +6837,8 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) {
}
case Expr::CXXDefaultArgExprClass:
return CheckICE(cast<CXXDefaultArgExpr>(E)->getExpr(), Ctx);
+ case Expr::CXXDefaultInitExprClass:
+ return CheckICE(cast<CXXDefaultInitExpr>(E)->getExpr(), Ctx);
case Expr::ChooseExprClass: {
return CheckICE(cast<ChooseExpr>(E)->getChosenSubExpr(Ctx), Ctx);
}
diff --git a/lib/AST/ItaniumMangle.cpp b/lib/AST/ItaniumMangle.cpp
index e82b017e4a..0b77933f0b 100644
--- a/lib/AST/ItaniumMangle.cpp
+++ b/lib/AST/ItaniumMangle.cpp
@@ -2473,6 +2473,10 @@ recurse:
mangleExpression(cast<CXXDefaultArgExpr>(E)->getExpr(), Arity);
break;
+ case Expr::CXXDefaultInitExprClass:
+ mangleExpression(cast<CXXDefaultInitExpr>(E)->getExpr(), Arity);
+ break;
+
case Expr::SubstNonTypeTemplateParmExprClass:
mangleExpression(cast<SubstNonTypeTemplateParmExpr>(E)->getReplacement(),
Arity);
diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp
index 1b2285c794..95bacb64b3 100644
--- a/lib/AST/StmtPrinter.cpp
+++ b/lib/AST/StmtPrinter.cpp
@@ -1314,7 +1314,11 @@ void StmtPrinter::VisitCXXThrowExpr(CXXThrowExpr *Node) {
}
void StmtPrinter::VisitCXXDefaultArgExpr(CXXDefaultArgExpr *Node) {
- // Nothing to print: we picked up the default argument
+ // Nothing to print: we picked up the default argument.
+}
+
+void StmtPrinter::VisitCXXDefaultInitExpr(CXXDefaultInitExpr *Node) {
+ // Nothing to print: we picked up the default initializer.
}
void StmtPrinter::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *Node) {
diff --git a/lib/AST/StmtProfile.cpp b/lib/AST/StmtProfile.cpp
index d99400c603..8ade242d56 100644
--- a/lib/AST/StmtProfile.cpp
+++ b/lib/AST/StmtProfile.cpp
@@ -789,6 +789,11 @@ void StmtProfiler::VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *S) {
VisitDecl(S->getParam());
}
+void StmtProfiler::VisitCXXDefaultInitExpr(const CXXDefaultInitExpr *S) {
+ VisitExpr(S);
+ VisitDecl(S->getField());
+}
+
void StmtProfiler::VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *S) {
VisitExpr(S);
VisitDecl(
diff --git a/lib/Analysis/CFG.cpp b/lib/Analysis/CFG.cpp
index 1adb8b84e4..096c7a080b 100644
--- a/lib/Analysis/CFG.cpp
+++ b/lib/Analysis/CFG.cpp
@@ -1085,11 +1085,16 @@ CFGBlock *CFGBuilder::Visit(Stmt * S, AddStmtChoice asc) {
return VisitExprWithCleanups(cast<ExprWithCleanups>(S), asc);
case Stmt::CXXDefaultArgExprClass:
+ case Stmt::CXXDefaultInitExprClass:
// FIXME: The expression inside a CXXDefaultArgExpr is owned by the
// called function's declaration, not by the caller. If we simply add
// this expression to the CFG, we could end up with the same Expr
// appearing multiple times.
// PR13385 / <rdar://problem/12156507>
+ //
+ // It's likewise possible for multiple CXXDefaultInitExprs for the same
+ // expression to be used in the same function (through aggregate
+ // initialization).
return VisitStmt(S, asc);
case Stmt::CXXBindTemporaryExprClass:
diff --git a/lib/CodeGen/CGClass.cpp b/lib/CodeGen/CGClass.cpp
index 05925567b0..2b9a55b2a6 100644
--- a/lib/CodeGen/CGClass.cpp
+++ b/lib/CodeGen/CGClass.cpp
@@ -1139,6 +1139,7 @@ void CodeGenFunction::EmitCtorPrologue(const CXXConstructorDecl *CD,
InitializeVTablePointers(ClassDecl);
// And finally, initialize class members.
+ FieldConstructionScope FCS(*this, CXXThisValue);
ConstructorMemcpyizer CM(*this, CD, Args);
for (; B != E; B++) {
CXXCtorInitializer *Member = (*B);
diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp
index a0725b5f9c..ea13de17ab 100644
--- a/lib/CodeGen/CGExpr.cpp
+++ b/lib/CodeGen/CGExpr.cpp
@@ -903,6 +903,10 @@ LValue CodeGenFunction::EmitLValue(const Expr *E) {
return EmitNullInitializationLValue(cast<CXXScalarValueInitExpr>(E));
case Expr::CXXDefaultArgExprClass:
return EmitLValue(cast<CXXDefaultArgExpr>(E)->getExpr());
+ case Expr::CXXDefaultInitExprClass: {
+ CXXDefaultInitExprScope Scope(*this);
+ return EmitLValue(cast<CXXDefaultInitExpr>(E)->getExpr());
+ }
case Expr::CXXTypeidExprClass:
return EmitCXXTypeidLValue(cast<CXXTypeidExpr>(E));
diff --git a/lib/CodeGen/CGExprAgg.cpp b/lib/CodeGen/CGExprAgg.cpp
index 6b29b3155a..b974e1dcc6 100644
--- a/lib/CodeGen/CGExprAgg.cpp
+++ b/lib/CodeGen/CGExprAgg.cpp
@@ -170,6 +170,10 @@ public:
void VisitCXXDefaultArgExpr(CXXDefaultArgExpr *DAE) {
Visit(DAE->getExpr());
}
+ void VisitCXXDefaultInitExpr(CXXDefaultInitExpr *DIE) {
+ CodeGenFunction::CXXDefaultInitExprScope Scope(CGF);
+ Visit(DIE->getExpr());
+ }
void VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E);
void VisitCXXConstructExpr(const CXXConstructExpr *E);
void VisitLambdaExpr(LambdaExpr *E);
@@ -1189,7 +1193,10 @@ void AggExprEmitter::VisitInitListExpr(InitListExpr *E) {
// the optimizer, especially with bitfields.
unsigned NumInitElements = E->getNumInits();
RecordDecl *record = E->getType()->castAs<RecordType>()->getDecl();
-
+
+ // Prepare a 'this' for CXXDefaultInitExprs.
+ CodeGenFunction::FieldConstructionScope FCS(CGF, Dest.getAddr());
+
if (record->isUnion()) {
// Only initialize one field of a union. The field itself is
// specified by the initializer list.
diff --git a/lib/CodeGen/CGExprComplex.cpp b/lib/CodeGen/CGExprComplex.cpp
index 5fc73aa790..36f974a313 100644
--- a/lib/CodeGen/CGExprComplex.cpp
+++ b/lib/CodeGen/CGExprComplex.cpp
@@ -182,6 +182,10 @@ public:
ComplexPairTy VisitCXXDefaultArgExpr(CXXDefaultArgExpr *DAE) {
return Visit(DAE->getExpr());
}
+ ComplexPairTy VisitCXXDefaultInitExpr(CXXDefaultInitExpr *DIE) {
+ CodeGenFunction::CXXDefaultInitExprScope Scope(CGF);
+ return Visit(DIE->getExpr());
+ }
ComplexPairTy VisitExprWithCleanups(ExprWithCleanups *E) {
CGF.enterFullExpression(E);
CodeGenFunction::RunCleanupsScope Scope(CGF);
diff --git a/lib/CodeGen/CGExprConstant.cpp b/lib/CodeGen/CGExprConstant.cpp
index faaf6468f1..f5c8187c26 100644
--- a/lib/CodeGen/CGExprConstant.cpp
+++ b/lib/CodeGen/CGExprConstant.cpp
@@ -757,6 +757,12 @@ public:
return Visit(DAE->getExpr());
}
+ llvm::Constant *VisitCXXDefaultInitExpr(CXXDefaultInitExpr *DIE) {
+ // No need for a DefaultInitExprScope: we don't handle 'this' in a
+ // constant expression.
+ return Visit(DIE->getExpr());
+ }
+
llvm::Constant *VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E) {
return Visit(E->GetTemporaryExpr());
}
diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp
index ea1eae8088..c1c252d12b 100644
--- a/lib/CodeGen/CGExprScalar.cpp
+++ b/lib/CodeGen/CGExprScalar.cpp
@@ -344,6 +344,10 @@ public:
Value *VisitCXXDefaultArgExpr(CXXDefaultArgExpr *DAE) {
return Visit(DAE->getExpr());
}
+ Value *VisitCXXDefaultInitExpr(CXXDefaultInitExpr *DIE) {
+ CodeGenFunction::CXXDefaultInitExprScope Scope(CGF);
+ return Visit(DIE->getExpr());
+ }
Value *VisitCXXThisExpr(CXXThisExpr *TE) {
return CGF.LoadCXXThis();
}
diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp
index cda3ce0286..a12e7dc445 100644
--- a/lib/CodeGen/CodeGenFunction.cpp
+++ b/lib/CodeGen/CodeGenFunction.cpp
@@ -45,6 +45,7 @@ CodeGenFunction::CodeGenFunction(CodeGenModule &cgm, bool suppressNewContext)
DidCallStackSave(false),
IndirectBranch(0), SwitchInsn(0), CaseRangeBlock(0), UnreachableBlock(0),
CXXABIThisDecl(0), CXXABIThisValue(0), CXXThisValue(0),
+ CXXDefaultInitExprThis(0),
CXXStructorImplicitParamDecl(0), CXXStructorImplicitParamValue(0),
OutermostConditional(0), CurLexicalScope(0), TerminateLandingPad(0),
TerminateHandler(0), TrapBB(0) {
diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h
index 6e2d62760f..f0c2c1e672 100644
--- a/lib/CodeGen/CodeGenFunction.h
+++ b/lib/CodeGen/CodeGenFunction.h
@@ -1206,12 +1206,53 @@ private:
/// lazily by getUnreachableBlock().
llvm::BasicBlock *UnreachableBlock;
+public:
+ /// A scope within which we are constructing the fields of an object which
+ /// might use a CXXDefaultInitExpr. This stashes away a 'this' value to use
+ /// if we need to evaluate a CXXDefaultInitExpr within the evaluation.
+ class FieldConstructionScope {
+ public:
+ FieldConstructionScope(CodeGenFunction &CGF, llvm::Value *This)
+ : CGF(CGF), OldCXXDefaultInitExprThis(CGF.CXXDefaultInitExprThis) {
+ CGF.CXXDefaultInitExprThis = This;
+ }
+ ~FieldConstructionScope() {
+ CGF.CXXDefaultInitExprThis = OldCXXDefaultInitExprThis;
+ }
+
+ private:
+ CodeGenFunction &CGF;
+ llvm::Value *OldCXXDefaultInitExprThis;
+ };
+
+ /// The scope of a CXXDefaultInitExpr. Within this scope, the value of 'this'
+ /// is overridden to be the object under construction.
+ class CXXDefaultInitExprScope {
+ public:
+ CXXDefaultInitExprScope(CodeGenFunction &CGF)
+ : CGF(CGF), OldCXXThisValue(CGF.CXXThisValue) {
+ CGF.CXXThisValue = CGF.CXXDefaultInitExprThis;
+ }
+ ~CXXDefaultInitExprScope() {
+ CGF.CXXThisValue = OldCXXThisValue;
+ }
+
+ public:
+ CodeGenFunction &CGF;
+ llvm::Value *OldCXXThisValue;
+ };
+
+private:
/// CXXThisDecl - When generating code for a C++ member function,
/// this will hold the implicit 'this' declaration.
ImplicitParamDecl *CXXABIThisDecl;
llvm::Value *CXXABIThisValue;
llvm::Value *CXXThisValue;
+ /// The value of 'this' to use when evaluating CXXDefaultInitExprs within
+ /// this expression.
+ llvm::Value *CXXDefaultInitExprThis;
+
/// CXXStructorImplicitParamDecl - When generating code for a