aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorSebastian Redl <sebastian.redl@getdesigned.at>2012-02-11 23:51:47 +0000
committerSebastian Redl <sebastian.redl@getdesigned.at>2012-02-11 23:51:47 +0000
commit5b9cc5df25c2198f270dd1d5c438fdce70d4051d (patch)
tree8d2c36bd9fe0e47cc5ce4e5a2fd02d8dd0e31f7f /lib
parentecfcd5655758955d8958dc2a7a7b2c8eff2395b7 (diff)
Represent C++ direct initializers as ParenListExprs before semantic analysis
instead of having a special-purpose function. - ActOnCXXDirectInitializer, which was mostly duplication of AddInitializerToDecl (leading e.g. to PR10620, which Eli fixed a few days ago), is dropped completely. - MultiInitializer, which was an ugly hack I added, is dropped again. - We now have the infrastructure in place to distinguish between int x = {1}; int x({1}); int x{1}; -- VarDecl now has getInitStyle(), which indicates which of the above was used. -- CXXConstructExpr now has a flag to indicate that it represents list- initialization, although this is not yet used. - InstantiateInitializer was renamed to SubstInitializer and simplified. - ActOnParenOrParenListExpr has been replaced by ActOnParenListExpr, which always produces a ParenListExpr. Placed that so far failed to convert that back to a ParenExpr containing comma operators have been fixed. I'm pretty sure I could have made a crashing test case before this. The end result is a (I hope) considerably cleaner design of initializers. More importantly, the fact that I can now distinguish between the various initialization kinds means that I can get the tricky generalized initializer test cases Johannes Schaub supplied to work. (This is not yet done.) This commit passed self-host, with the resulting compiler passing the tests. I hope it doesn't break more complicated code. It's a pretty big change, but one that I feel is necessary. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@150318 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r--lib/AST/DeclPrinter.cpp22
-rw-r--r--lib/AST/DumpXML.cpp8
-rw-r--r--lib/AST/Expr.cpp5
-rw-r--r--lib/AST/ExprCXX.cpp10
-rw-r--r--lib/CodeGen/CGObjC.cpp3
-rw-r--r--lib/Parse/ParseDecl.cpp9
-rw-r--r--lib/Parse/ParseExpr.cpp4
-rw-r--r--lib/Sema/CMakeLists.txt1
-rw-r--r--lib/Sema/MultiInitializer.cpp93
-rw-r--r--lib/Sema/SemaDecl.cpp122
-rw-r--r--lib/Sema/SemaDeclCXX.cpp345
-rw-r--r--lib/Sema/SemaExpr.cpp22
-rw-r--r--lib/Sema/SemaInit.cpp7
-rw-r--r--lib/Sema/SemaTemplateInstantiate.cpp14
-rw-r--r--lib/Sema/SemaTemplateInstantiateDecl.cpp170
-rw-r--r--lib/Sema/TreeTransform.h7
-rw-r--r--lib/Serialization/ASTReaderDecl.cpp2
-rw-r--r--lib/Serialization/ASTWriterDecl.cpp6
18 files changed, 310 insertions, 540 deletions
diff --git a/lib/AST/DeclPrinter.cpp b/lib/AST/DeclPrinter.cpp
index 5a6686d164..32bdba1a0b 100644
--- a/lib/AST/DeclPrinter.cpp
+++ b/lib/AST/DeclPrinter.cpp
@@ -621,16 +621,20 @@ void DeclPrinter::VisitVarDecl(VarDecl *D) {
Out << Name;
Expr *Init = D->getInit();
if (!Policy.SuppressInitializers && Init) {
- if (D->hasCXXDirectInitializer())
- Out << "(";
- else {
- CXXConstructExpr *CCE = dyn_cast<CXXConstructExpr>(Init);
- if (!CCE || CCE->getConstructor()->isCopyOrMoveConstructor())
- Out << " = ";
+ bool ImplicitInit = false;
+ if (CXXConstructExpr *Construct = dyn_cast<CXXConstructExpr>(Init))
+ ImplicitInit = D->getInitStyle() == VarDecl::CallInit &&
+ Construct->getNumArgs() == 0 && !Construct->isListInitialization();
+ if (!ImplicitInit) {
+ if (D->getInitStyle() == VarDecl::CallInit)
+ Out << "(";
+ else if (D->getInitStyle() == VarDecl::CInit) {
+ Out << " = ";
+ }
+ Init->printPretty(Out, Context, 0, Policy, Indentation);
+ if (D->getInitStyle() == VarDecl::CallInit)
+ Out << ")";
}
- Init->printPretty(Out, Context, 0, Policy, Indentation);
- if (D->hasCXXDirectInitializer())
- Out << ")";
}
prettyPrintAttributes(D);
}
diff --git a/lib/AST/DumpXML.cpp b/lib/AST/DumpXML.cpp
index dcbc5180a0..b4038ddaf9 100644
--- a/lib/AST/DumpXML.cpp
+++ b/lib/AST/DumpXML.cpp
@@ -461,7 +461,13 @@ struct XMLDumper : public XMLDeclVisitor<XMLDumper>,
if (D->getStorageClass() != SC_None)
set("storage",
VarDecl::getStorageClassSpecifierString(D->getStorageClass()));
- setFlag("directinit", D->hasCXXDirectInitializer());
+ StringRef initStyle = "";
+ switch (D->getInitStyle()) {
+ case VarDecl::CInit: initStyle = "c"; break;
+ case VarDecl::CallInit: initStyle = "call"; break;
+ case VarDecl::ListInit: initStyle = "list"; break;
+ }
+ set("initstyle", initStyle);
setFlag("nrvo", D->isNRVOVariable());
// TODO: instantiation, etc.
}
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index 398e27ea97..5d22d144f4 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -3414,11 +3414,10 @@ void DesignatedInitExpr::ExpandDesignator(ASTContext &C, unsigned Idx,
ParenListExpr::ParenListExpr(ASTContext& C, SourceLocation lparenloc,
Expr **exprs, unsigned nexprs,
- SourceLocation rparenloc, QualType T)
- : Expr(ParenListExprClass, T, VK_RValue, OK_Ordinary,
+ SourceLocation rparenloc)
+ : Expr(ParenListExprClass, QualType(), VK_RValue, OK_Ordinary,
false, false, false, false),
NumExprs(nexprs), LParenLoc(lparenloc), RParenLoc(rparenloc) {
- assert(!T.isNull() && "ParenListExpr must have a valid type");
Exprs = new (C) Stmt*[nexprs];
for (unsigned i = 0; i != nexprs; ++i) {
if (exprs[i]->isTypeDependent())
diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp
index 51dd57cfe3..a38488b877 100644
--- a/lib/AST/ExprCXX.cpp
+++ b/lib/AST/ExprCXX.cpp
@@ -653,7 +653,7 @@ CXXTemporaryObjectExpr::CXXTemporaryObjectExpr(ASTContext &C,
Type->getType().getNonReferenceType(),
Type->getTypeLoc().getBeginLoc(),
Cons, false, Args, NumArgs,
- HadMultipleCandidates, ZeroInitialization,
+ HadMultipleCandidates, /*FIXME*/false, ZeroInitialization,
CXXConstructExpr::CK_Complete, parenRange),
Type(Type) {
}
@@ -668,13 +668,15 @@ CXXConstructExpr *CXXConstructExpr::Create(ASTContext &C, QualType T,
CXXConstructorDecl *D, bool Elidable,
Expr **Args, unsigned NumArgs,
bool HadMultipleCandidates,
+ bool ListInitialization,
bool ZeroInitialization,
ConstructionKind ConstructKind,
SourceRange ParenRange) {
return new (C) CXXConstructExpr(C, CXXConstructExprClass, T, Loc, D,
Elidable, Args, NumArgs,
- HadMultipleCandidates, ZeroInitialization,
- ConstructKind, ParenRange);
+ HadMultipleCandidates, ListInitialization,
+ ZeroInitialization, ConstructKind,
+ ParenRange);
}
CXXConstructExpr::CXXConstructExpr(ASTContext &C, StmtClass SC, QualType T,
@@ -682,6 +684,7 @@ CXXConstructExpr::CXXConstructExpr(ASTContext &C, StmtClass SC, QualType T,
CXXConstructorDecl *D, bool elidable,
Expr **args, unsigned numargs,
bool HadMultipleCandidates,
+ bool ListInitialization,
bool ZeroInitialization,
ConstructionKind ConstructKind,
SourceRange ParenRange)
@@ -691,6 +694,7 @@ CXXConstructExpr::CXXConstructExpr(ASTContext &C, StmtClass SC, QualType T,
T->containsUnexpandedParameterPack()),
Constructor(D), Loc(Loc), ParenRange(ParenRange), NumArgs(numargs),
Elidable(elidable), HadMultipleCandidates(HadMultipleCandidates),
+ ListInitialization(ListInitialization),
ZeroInitialization(ZeroInitialization),
ConstructKind(ConstructKind), Args(0)
{
diff --git a/lib/CodeGen/CGObjC.cpp b/lib/CodeGen/CGObjC.cpp
index dc68605555..94bad92180 100644
--- a/lib/CodeGen/CGObjC.cpp
+++ b/lib/CodeGen/CGObjC.cpp
@@ -2740,7 +2740,8 @@ CodeGenFunction::GenerateObjCAtomicGetterCopyHelperFunction(
CXXConstExpr->getConstructor(),
CXXConstExpr->isElidable(),
&ConstructorArgs[0], ConstructorArgs.size(),
- CXXConstExpr->hadMultipleCandidates(),
+ CXXConstExpr->hadMultipleCandidates(),
+ CXXConstExpr->isListInitialization(),
CXXConstExpr->requiresZeroInitialization(),
CXXConstExpr->getConstructionKind(), SourceRange());
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index 0c8a647f65..914a5acd09 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -1344,10 +1344,11 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(Declarator &D,
ExitScope();
}
- Actions.AddCXXDirectInitializerToDecl(ThisDecl, T.getOpenLocation(),
- move_arg(Exprs),
- T.getCloseLocation(),
- TypeContainsAuto);
+ ExprResult Initializer = Actions.ActOnParenListExpr(T.getOpenLocation(),
+ T.getCloseLocation(),
+ move_arg(Exprs));
+ Actions.AddInitializerToDecl(ThisDecl, Initializer.take(),
+ /*DirectInit=*/true, TypeContainsAuto);
}
} else if (getLang().CPlusPlus0x && Tok.is(tok::l_brace)) {
// Parse C++0x braced-init-list.
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp
index 3660b01816..b5e4a5f620 100644
--- a/lib/Parse/ParseExpr.cpp
+++ b/lib/Parse/ParseExpr.cpp
@@ -2006,8 +2006,8 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
if (!ParseExpressionList(ArgExprs, CommaLocs)) {
ExprType = SimpleExpr;
- Result = Actions.ActOnParenOrParenListExpr(OpenLoc, Tok.getLocation(),
- move_arg(ArgExprs));
+ Result = Actions.ActOnParenListExpr(OpenLoc, Tok.getLocation(),
+ move_arg(ArgExprs));
}
} else {
InMessageExpressionRAIIObject InMessage(*this, false);
diff --git a/lib/Sema/CMakeLists.txt b/lib/Sema/CMakeLists.txt
index dece5bd998..c576d765b2 100644
--- a/lib/Sema/CMakeLists.txt
+++ b/lib/Sema/CMakeLists.txt
@@ -8,7 +8,6 @@ add_clang_library(clangSema
DelayedDiagnostic.cpp
IdentifierResolver.cpp
JumpDiagnostics.cpp
- MultiInitializer.cpp
Scope.cpp
Sema.cpp
SemaAccess.cpp
diff --git a/lib/Sema/MultiInitializer.cpp b/lib/Sema/MultiInitializer.cpp
deleted file mode 100644
index d8944efba3..0000000000
--- a/lib/Sema/MultiInitializer.cpp
+++ /dev/null
@@ -1,93 +0,0 @@
-//===--- MultiInitializer.cpp - Initializer expression group ----*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements the MultiInitializer class, which can represent a list
-// initializer or a parentheses-wrapped group of expressions in a C++ member
-// initializer.
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/Sema/MultiInitializer.h"
-#include "clang/Sema/Initialization.h"
-#include "clang/Sema/Sema.h"
-#include "clang/AST/Expr.h"
-
-using namespace clang;
-
-InitListExpr *MultiInitializer::getInitList() const {
- return cast<InitListExpr>(InitListOrExpressions.get<Expr*>());
-}
-
-SourceLocation MultiInitializer::getStartLoc() const {
- return isInitializerList() ? getInitList()->getLBraceLoc() : LParenLoc;
-}
-
-SourceLocation MultiInitializer::getEndLoc() const {
- return isInitializerList() ? getInitList()->getRBraceLoc() : RParenLoc;
-}
-
-MultiInitializer::iterator MultiInitializer::begin() const {
- return isInitializerList() ? getInitList()->getInits() : getExpressions();
-}
-
-MultiInitializer::iterator MultiInitializer::end() const {
- if (isInitializerList()) {
- InitListExpr *ILE = getInitList();
- return ILE->getInits() + ILE->getNumInits();
- }
- return getExpressions() + NumInitializers;
-}
-
-bool MultiInitializer::isTypeDependent() const {
- if (isInitializerList())
- return getInitList()->isTypeDependent();
- for (iterator I = begin(), E = end(); I != E; ++I) {
- if ((*I)->isTypeDependent())
- return true;
- }
- return false;
-}
-
-bool MultiInitializer::DiagnoseUnexpandedParameterPack(Sema &SemaRef) const {
- if (isInitializerList())
- return SemaRef.DiagnoseUnexpandedParameterPack(getInitList(),
- Sema::UPPC_Initializer);
- for (iterator I = begin(), E = end(); I != E; ++I) {
- if (SemaRef.DiagnoseUnexpandedParameterPack(*I, Sema::UPPC_Initializer))
- return true;
- }
- return false;
-}
-
-Expr *MultiInitializer::CreateInitExpr(ASTContext &Ctx, QualType T) const {
- if (isInitializerList())
- return InitListOrExpressions.get<Expr*>();
-
- return new (Ctx) ParenListExpr(Ctx, LParenLoc, getExpressions(),
- NumInitializers, RParenLoc, T);
-}
-
-ExprResult MultiInitializer::PerformInit(Sema &SemaRef,
- InitializedEntity Entity,
- InitializationKind Kind) const {
- Expr *Single;
- Expr **Args;
- unsigned NumArgs;
- if (isInitializerList()) {
- Single = InitListOrExpressions.get<Expr*>();
- Args = &Single;
- NumArgs = 1;
- } else {
- Args = getExpressions();
- NumArgs = NumInitializers;
- }
- InitializationSequence InitSeq(SemaRef, Entity, Kind, Args, NumArgs);
- return InitSeq.Perform(SemaRef, Entity, Kind,
- MultiExprArg(SemaRef, Args, NumArgs), 0);
-}
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 6ba3228b08..feffaf13fa 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -2139,9 +2139,8 @@ void Sema::mergeObjCMethodDecls(ObjCMethodDecl *newMethod,
/// emitting diagnostics as appropriate.
///
/// Declarations using the auto type specifier (C++ [decl.spec.auto]) call back
-/// to here in AddInitializerToDecl and AddCXXDirectInitializerToDecl. We can't
-/// check them before the initializer is attached.
-///
+/// to here in AddInitializerToDecl. We can't check them before the initializer
+/// is attached.
void Sema::MergeVarDeclTypes(VarDecl *New, VarDecl *Old) {
if (New->isInvalidDecl() || Old->isInvalidDecl())
return;
@@ -5983,17 +5982,6 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
if (RealDecl == 0 || RealDecl->isInvalidDecl())
return;
- // Check for self-references within variable initializers.
- if (VarDecl *vd = dyn_cast<VarDecl>(RealDecl)) {
- // Variables declared within a function/method body are handled
- // by a dataflow analysis.
- if (!vd->hasLocalStorage() && !vd->isStaticLocal())
- CheckSelfReference(RealDecl, Init);
- }
- else {
- CheckSelfReference(RealDecl, Init);
- }
-
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(RealDecl)) {
// With declarators parsed the way they are, the parser cannot
// distinguish between a normal initializer and a pure-specifier.
@@ -6018,12 +6006,44 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
return;
}
+ // Check for self-references within variable initializers.
+ // Variables declared within a function/method body are handled
+ // by a dataflow analysis.
+ if (!VDecl->hasLocalStorage() && !VDecl->isStaticLocal())
+ CheckSelfReference(RealDecl, Init);
+
+ ParenListExpr *CXXDirectInit = dyn_cast<ParenListExpr>(Init);
+
// C++11 [decl.spec.auto]p6. Deduce the type which 'auto' stands in for.
if (TypeMayContainAuto && VDecl->getType()->getContainedAutoType()) {
+ Expr *DeduceInit = Init;
+ // Initializer could be a C++ direct-initializer. Deduction only works if it
+ // contains exactly one expression.
+ if (CXXDirectInit) {
+ if (CXXDirectInit->getNumExprs() == 0) {
+ // It isn't possible to write this directly, but it is possible to
+ // end up in this situation with "auto x(some_pack...);"
+ Diag(CXXDirectInit->getSourceRange().getBegin(),
+ diag::err_auto_var_init_no_expression)
+ << VDecl->getDeclName() << VDecl->getType()
+ << VDecl->getSourceRange();
+ RealDecl->setInvalidDecl();
+ return;
+ } else if (CXXDirectInit->getNumExprs() > 1) {
+ Diag(CXXDirectInit->getExpr(1)->getSourceRange().getBegin(),
+ diag::err_auto_var_init_multiple_expressions)
+ << VDecl->getDeclName() << VDecl->getType()
+ << VDecl->getSourceRange();
+ RealDecl->setInvalidDecl();
+ return;
+ } else {
+ DeduceInit = CXXDirectInit->getExpr(0);
+ }
+ }
TypeSourceInfo *DeducedType = 0;
- if (DeduceAutoType(VDecl->getTypeSourceInfo(), Init, DeducedType) ==
+ if (DeduceAutoType(VDecl->getTypeSourceInfo(), DeduceInit, DeducedType) ==
DAR_Failed)
- DiagnoseAutoDeductionFailure(VDecl, Init);
+ DiagnoseAutoDeductionFailure(VDecl, DeduceInit);
if (!DeducedType) {
RealDecl->setInvalidDecl();
return;
@@ -6048,25 +6068,26 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
return;
}
+ if (!VDecl->getType()->isDependentType()) {
+ // A definition must end up with a complete type, which means it must be
+ // complete with the restriction that an array type might be completed by
+ // the initializer; note that later code assumes this restriction.
+ QualType BaseDeclType = VDecl->getType();
+ if (const ArrayType *Array = Context.getAsIncompleteArrayType(BaseDeclType))
+ BaseDeclType = Array->getElementType();
+ if (RequireCompleteType(VDecl->getLocation(), BaseDeclType,
+ diag::err_typecheck_decl_incomplete_type)) {
+ RealDecl->setInvalidDecl();
+ return;
+ }
- // A definition must end up with a complete type, which means it must be
- // complete with the restriction that an array type might be completed by the
- // initializer; note that later code assumes this restriction.
- QualType BaseDeclType = VDecl->getType();
- if (const ArrayType *Array = Context.getAsIncompleteArrayType(BaseDeclType))
- BaseDeclType = Array->getElementType();
- if (RequireCompleteType(VDecl->getLocation(), BaseDeclType,
- diag::err_typecheck_decl_incomplete_type)) {
- RealDecl->setInvalidDecl();
- return;
+ // The variable can not have an abstract class type.
+ if (RequireNonAbstractType(VDecl->getLocation(), VDecl->getType(),
+ diag::err_abstract_type_in_decl,
+ AbstractVariableType))
+ VDecl->setInvalidDecl();
}
- // The variable can not have an abstract class type.
- if (RequireNonAbstractType(VDecl->getLocation(), VDecl->getType(),
- diag::err_abstract_type_in_decl,
- AbstractVariableType))
- VDecl->setInvalidDecl();
-
const VarDecl *Def;
if ((Def = VDecl->getDefinition()) && Def != VDecl) {
Diag(VDecl->getLocation(), diag::err_redefinition)
@@ -6128,9 +6149,15 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
: InitializationKind::CreateCopy(VDecl->getLocation(),
Init->getLocStart());
- InitializationSequence InitSeq(*this, Entity, Kind, &Init, 1);
+ Expr **Args = &Init;
+ unsigned NumArgs = 1;
+ if (CXXDirectInit) {
+ Args = CXXDirectInit->getExprs();
+ NumArgs = CXXDirectInit->getNumExprs();
+ }
+ InitializationSequence InitSeq(*this, Entity, Kind, Args, NumArgs);
ExprResult Result = InitSeq.Perform(*this, Entity, Kind,
- MultiExprArg(*this, &Init, 1),
+ MultiExprArg(*this, Args,NumArgs),
&DclT);
if (Result.isInvalid()) {
VDecl->setInvalidDecl();
@@ -6266,6 +6293,28 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
CheckForConstantInitializer(Init, DclT);
}
+ // We will represent direct-initialization similarly to copy-initialization:
+ // int x(1); -as-> int x = 1;
+ // ClassType x(a,b,c); -as-> ClassType x = ClassType(a,b,c);
+ //
+ // Clients that want to distinguish between the two forms, can check for
+ // direct initializer using VarDecl::getInitStyle().
+ // A major benefit is that clients that don't particularly care about which
+ // exactly form was it (like the CodeGen) can handle both cases without
+ // special case code.
+
+ // C++ 8.5p11:
+ // The form of initialization (using parentheses or '=') is generally
+ // insignificant, but does matter when the entity being initialized has a
+ // class type.
+ if (CXXDirectInit) {
+ assert(DirectInit && "Call-style initializer must be direct init.");
+ VDecl->setInitStyle(VarDecl::CallInit);
+ } else if (DirectInit) {
+ // This must be list-initialization. No other way is direct-initialization.
+ VDecl->setInitStyle(VarDecl::ListInit);
+ }
+
CheckCompleteVariableDeclaration(VDecl);
}
@@ -6496,8 +6545,11 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl,
MultiExprArg(*this, 0, 0));
if (Init.isInvalid())
Var->setInvalidDecl();
- else if (Init.get())
+ else if (Init.get()) {
Var->setInit(MaybeCreateExprWithCleanups(Init.get()));
+ // This is important for template substitution.
+ Var->setInitStyle(VarDecl::CallInit);
+ }
CheckCompleteVariableDeclaration(Var);
}
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index a6d7d63b3a..72a8de2b71 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -1768,7 +1768,7 @@ Sema::ActOnMemInitializer(Decl *ConstructorD,
Expr *InitList,
SourceLocation EllipsisLoc) {
return BuildMemInitializer(ConstructorD, S, SS, MemberOrBase, TemplateTypeTy,
- DS, IdLoc, MultiInitializer(InitList),
+ DS, IdLoc, InitList,
EllipsisLoc);
}
@@ -1785,10 +1785,10 @@ Sema::ActOnMemInitializer(Decl *ConstructorD,
Expr **Args, unsigned NumArgs,
SourceLocation RParenLoc,
SourceLocation EllipsisLoc) {
+ Expr *List = new (Context) ParenListExpr(Context, LParenLoc, Args, NumArgs,
+ RParenLoc);
return BuildMemInitializer(ConstructorD, S, SS, MemberOrBase, TemplateTypeTy,
- DS, IdLoc, MultiInitializer(LParenLoc, Args,
- NumArgs, RParenLoc),
- EllipsisLoc);
+ DS, IdLoc, List, EllipsisLoc);
}
namespace {
@@ -1825,7 +1825,7 @@ Sema::BuildMemInitializer(Decl *ConstructorD,
ParsedType TemplateTypeTy,
const DeclSpec &DS,
SourceLocation IdLoc,
- const MultiInitializer &Args,
+ Expr *Init,
SourceLocation EllipsisLoc) {
if (!ConstructorD)
return true;
@@ -1864,9 +1864,10 @@ Sema::BuildMemInitializer(Decl *ConstructorD,
(Member = dyn_cast<IndirectFieldDecl>(*Result.first))) {
if (EllipsisLoc.isValid())
Diag(EllipsisLoc, diag::err_pack_expansion_member_init)
- << MemberOrBase << SourceRange(IdLoc, Args.getEndLoc());
+ << MemberOrBase
+ << SourceRange(IdLoc, Init->getSourceRange().getEnd());
- return BuildMemberInitializer(Member, Args, IdLoc);
+ return BuildMemberInitializer(Member, Init, IdLoc);
}
}
}
@@ -1927,7 +1928,7 @@ Sema::BuildMemInitializer(Decl *ConstructorD,
Diag(Member->getLocation(), diag::note_previous_decl)
<< CorrectedQuotedStr;
- return BuildMemberInitializer(Member, Args, IdLoc);
+ return BuildMemberInitializer(Member, Init, IdLoc);
} else if (TypeDecl *Type = Corr.getCorrectionDeclAs<TypeDecl>()) {
const CXXBaseSpecifier *DirectBaseSpec;
const CXXBaseSpecifier *VirtualBaseSpec;
@@ -1955,7 +1956,7 @@ Sema::BuildMemInitializer(Decl *ConstructorD,
if (!TyD && BaseType.isNull()) {
Diag(IdLoc, diag::err_mem_init_not_member_or_class)
- << MemberOrBase << SourceRange(IdLoc, Args.getEndLoc());
+ << MemberOrBase << SourceRange(IdLoc,Init->getSourceRange().getEnd());
return true;
}
}
@@ -1975,7 +1976,7 @@ Sema::BuildMemInitializer(Decl *ConstructorD,
if (!TInfo)
TInfo = Context.getTrivialTypeSourceInfo(BaseType, IdLoc);
- return BuildBaseInitializer(BaseType, TInfo, Args, ClassDecl, EllipsisLoc);
+ return BuildBaseInitializer(BaseType, TInfo, Init, ClassDecl, EllipsisLoc);
}
/// Checks a member initializer expression for cases where reference (or
@@ -2102,15 +2103,14 @@ static bool InitExprContainsUninitializedFields(const Stmt *S,
}
MemInitResult
-Sema::BuildMemberInitializer(ValueDecl *Member,
- const MultiInitializer &Args,
+Sema::BuildMemberInitializer(ValueDecl *Member, Expr *Init,
SourceLocation IdLoc) {
FieldDecl *DirectMember = dyn_cast<FieldDecl>(Member);
IndirectFieldDecl *IndirectMember = dyn_cast<IndirectFieldDecl>(Member);
assert((DirectMember || IndirectMember) &&
"Member must be a FieldDecl or IndirectFieldDecl");
- if (Args.DiagnoseUnexpandedParameterPack(*this))
+ if (DiagnoseUnexpandedParameterPack(Init, UPPC_Initializer))
return true;
if (Member->isInvalidDecl())
@@ -2120,13 +2120,19 @@ Sema::BuildMemberInitializer(ValueDecl *Member,
// foo(foo)
// where foo is not also a parameter to the constructor.
// TODO: implement -Wuninitialized and fold this into that framework.
- for (MultiInitializer::iterator I = Args.begin(), E = Args.end();
- I != E; ++I) {
+ Expr **Args;
+ unsigned NumArgs;
+ if (ParenListExpr *ParenList = dyn_cast<ParenListExpr>(Init)) {
+ Args = ParenList->getExprs();
+ NumArgs = ParenList->getNumExprs();
+ } else {
+ InitListExpr *InitList = cast<InitListExpr>(Init);
+ Args = InitList->getInits();
+ NumArgs = InitList->getNumInits();
+ }
+ for (unsigned i = 0; i < NumArgs; ++i) {
SourceLocation L;
- Expr *Arg = *I;
- if (DesignatedInitExpr *DIE = dyn_cast<DesignatedInitExpr>(Arg))
- Arg = DIE->getInit();
- if (InitExprContainsUninitializedFields(Arg, Member, &L)) {
+ if (InitExprContainsUninitializedFields(Args[i], Member, &L)) {
// FIXME: Return true in the case when other fields are used before being
// uninitialized. For example, let this field be the i'th field. When
// initializing the i'th field, throw a warning if any of the >= i'th
@@ -2137,14 +2143,11 @@ Sema::BuildMemberInitializer(ValueDecl *Member,
}
}
- bool HasDependentArg = Args.isTypeDependent();
+ SourceRange InitRange = Init->getSourceRange();
- Expr *Init;
- if (Member->getType()->isDependentType() || HasDependentArg) {
+ if (Member->getType()->isDependentType() || Init->isTypeDependent()) {
// Can't check initialization for a member of dependent type or when
// any of the arguments are type-dependent expressions.
- Init = Args.CreateInitExpr(Context,Member->getType().getNonReferenceType());
-
DiscardCleanupsInEvaluationContext();
} else {
// Initialize the member.
@@ -2152,14 +2155,22 @@ Sema::BuildMemberInitializer(ValueDecl *Member,
DirectMember ? InitializedEntity::InitializeMember(DirectMember, 0)
: InitializedEntity::InitializeMember(IndirectMember, 0);
InitializationKind Kind =
- InitializationKind::CreateDirect(IdLoc, Args.getStartLoc(),
- Args.getEndLoc());
+ InitializationKind::CreateDirect(IdLoc, InitRange.getBegin(),
+ InitRange.getEnd());
- ExprResult MemberInit = Args.PerformInit(*this, MemberEntity, Kind);
+ if (isa<InitListExpr>(Init)) {
+ Args = &Init;
+ NumArgs = 1;
+ }
+ InitializationSequence InitSeq(*this, MemberEntity, Kind, Args, NumArgs);
+ ExprResult MemberInit = InitSeq.Perform(*this, MemberEntity, Kind,
+ MultiExprArg(*this, Args, NumArgs),
+ 0);
if (MemberInit.isInvalid())
return true;
- CheckImplicitConversions(MemberInit.get(), Args.getStartLoc());
+ CheckImplicitConversions(MemberInit.get(),
+ InitRange.getBegin());
// C++0x [class.base.init]p7:
// The initialization of each base and member constitutes a
@@ -2170,14 +2181,13 @@ Sema::BuildMemberInitializer(ValueDecl *Member,
// If we are in a dependent context, template instantiation will
// perform this type-checking again. Just save the arguments that we
- // received in a ParenListExpr.
+ // received.
// FIXME: This isn't quite ideal, since our ASTs don't capture all
// of the information that we have about the member
// initializer. However, deconstructing the ASTs is a dicey process,
// and this approach is far more likely to get the corner cases right.
if (CurContext->isDependentContext()) {
- Init = Args.CreateInitExpr(Context,
- Member->getType().getNonReferenceType());
+ // The existing Init will do fine.
} else {
Init = MemberInit.get();
CheckForDanglingReferenceOrPointer(*this, Member, Init, IdLoc);
@@ -2185,19 +2195,18 @@ Sema::BuildMemberInitializer(ValueDecl *Member,
}
if (DirectMember) {
- return new (Context) CXXCtorInitializer(Context, DirectMember,
- IdLoc, Args.getStartLoc(),
- Init, Args.getEndLoc());
+ return new (Context) CXXCtorInitializer(Context, DirectMember, IdLoc,
+ InitRange.getBegin(), Init,
+ InitRange.getEnd());
} else {
- return new (Context) CXXCtorInitializer(Context, IndirectMember,
- IdLoc, Args.getStartLoc(),
- Init, Args.getEndLoc());
+ return new (Context) CXXCtorInitializer(Context, IndirectMember, IdLoc,
+ InitRange.getBegin(), Init,
+ InitRange.getEnd());
}
}
MemInitResult
-Sema::BuildDelegatingInitializer(TypeSourceInfo *TInfo,
- const MultiInitializer &Args,
+Sema::BuildDelegatingInitializer(TypeSourceInfo *TInfo, Expr *Init,
CXXRecordDecl *ClassDecl) {
SourceLocation NameLoc = TInfo->getTypeLoc().getLocalSourceRange().getBegin();
if (!LangOpts.CPlusPlus0x)
@@ -2205,21 +2214,31 @@ Sema::BuildDelegatingInitializer(TypeSourceInfo *TInfo,
<< TInfo->getTypeLoc().getLocalSourceRange();
Diag(NameLoc, diag::warn_cxx98_compat_delegating_ctor);
+ SourceRange InitRange = Init->getSourceRange();
// Initialize the object.
InitializedEntity DelegationEntity = InitializedEntity::InitializeDelegation(
QualType(ClassDecl->getTypeForDecl(), 0));
InitializationKind Kind =
- InitializationKind::CreateDirect(NameLoc, Args.getStartLoc(),
- Args.getEndLoc());
-
- ExprResult DelegationInit = Args.PerformInit(*this, DelegationEntity, Kind);
+ InitializationKind::CreateDirect(NameLoc, InitRange.getBegin(),
+ InitRange.getEnd());
+
+ Expr **Args = &Init;
+ unsigned NumArgs = 1;
+ if (ParenListExpr *ParenList = dyn_cast<ParenListExpr>(Init)) {
+ Args = ParenList->getExprs();
+ NumArgs = ParenList->getNumExprs();
+ }
+ InitializationSequence InitSeq(*this, DelegationEntity, Kind, Args, NumArgs);
+ ExprResult DelegationInit = InitSeq.Perform(*this, DelegationEntity, Kind,
+ MultiExprArg(*this, Args,NumArgs),
+ 0);
if (DelegationInit.isInvalid())
return true;
assert(cast<CXXConstructExpr>(DelegationInit.get())->getConstructor() &&
"Delegating constructor with no target?");
- CheckImplicitConversions(DelegationInit.get(), Args.getStartLoc());
+ CheckImplicitConversions(DelegationInit.get(), InitRange.getBegin());
// C++0x [class.base.init]p7:
// The initialization of each base and member constitutes a
@@ -2228,18 +2247,15 @@ Sema::BuildDelegatingInitializer(TypeSourceInfo *TInfo,
if (DelegationInit.isInvalid())