summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Redl <sebastian.redl@getdesigned.at>2011-09-24 17:48:25 +0000
committerSebastian Redl <sebastian.redl@getdesigned.at>2011-09-24 17:48:25 +0000
commita74948d347913c284009e0fca41b120980db3fa4 (patch)
tree1b03ccb521c321c2a94d73ef6e641115764ed707
parent12757ab4cb49f64071d1cd8d6a186c9a975721fa (diff)
downloadbcm5719-llvm-a74948d347913c284009e0fca41b120980db3fa4.tar.gz
bcm5719-llvm-a74948d347913c284009e0fca41b120980db3fa4.zip
Correctly parse braced member initializers (even in delayed parsing) and correctly pass
the information on to Sema. There's still an incorrectness in the way template instantiation works now, but that is due to a far larger underlying representational problem. Also add a test case for various list initialization cases of scalars, which test this commit as well as the previous one. llvm-svn: 140460
-rw-r--r--clang/include/clang/Parse/Parser.h1
-rw-r--r--clang/include/clang/Sema/MultiInitializer.h72
-rw-r--r--clang/include/clang/Sema/Sema.h34
-rw-r--r--clang/lib/Parse/ParseCXXInlineMethods.cpp52
-rw-r--r--clang/lib/Parse/ParseDeclCXX.cpp14
-rw-r--r--clang/lib/Parse/ParseTemplate.cpp2
-rw-r--r--clang/lib/Sema/MultiInitializer.cpp92
-rw-r--r--clang/lib/Sema/SemaDeclCXX.cpp200
-rw-r--r--clang/lib/Sema/SemaTemplateInstantiateDecl.cpp54
-rw-r--r--clang/test/SemaCXX/cxx0x-initializer-scalars.cpp34
-rw-r--r--clang/test/SemaCXX/generalized-initializers.cpp21
11 files changed, 410 insertions, 166 deletions
diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h
index ee2dbd55198..22349205976 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -1060,6 +1060,7 @@ private:
void ParseLexedMemberInitializers(ParsingClass &Class);
void ParseLexedMemberInitializer(LateParsedMemberInitializer &MI);
Decl *ParseLexedObjCMethodDefs(LexedMethod &LM);
+ bool ConsumeAndStoreTryAndInitializers(CachedTokens &Toks);
bool ConsumeAndStoreUntil(tok::TokenKind T1,
CachedTokens &Toks,
bool StopAtSemi = true,
diff --git a/clang/include/clang/Sema/MultiInitializer.h b/clang/include/clang/Sema/MultiInitializer.h
new file mode 100644
index 00000000000..c44e3934db6
--- /dev/null
+++ b/clang/include/clang/Sema/MultiInitializer.h
@@ -0,0 +1,72 @@
+//===--- MultiInitializer.h - 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 defines the MultiInitializer class, which can represent a list
+// initializer or a parentheses-wrapped group of expressions in a C++ member
+// initializer.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SEMA_MULTIINITIALIZER_H
+#define LLVM_CLANG_SEMA_MULTIINITIALIZER_H
+
+#include "clang/Sema/Ownership.h"
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/PointerUnion.h"
+
+namespace clang {
+ class ASTContext;
+ class Expr;
+ class InitializationKind;
+ class InitializedEntity;
+ class InitListExpr;
+ class Sema;
+
+class MultiInitializer {
+ llvm::PointerUnion<Expr*, Expr**> InitListOrExpressions;
+ unsigned NumInitializers;
+ SourceLocation LParenLoc;
+ SourceLocation RParenLoc;
+
+ InitListExpr *getInitList() const;
+ Expr **getExpressions() const { return InitListOrExpressions.get<Expr**>(); }
+
+public:
+ MultiInitializer(Expr* InitList)
+ : InitListOrExpressions(InitList)
+ {}
+
+ MultiInitializer(SourceLocation LParenLoc, Expr **Exprs, unsigned NumInits,
+ SourceLocation RParenLoc)
+ : InitListOrExpressions(Exprs), NumInitializers(NumInits),
+ LParenLoc(LParenLoc), RParenLoc(RParenLoc)
+ {}
+
+ bool isInitializerList() const { return InitListOrExpressions.is<Expr*>(); }
+
+ SourceLocation getStartLoc() const;
+ SourceLocation getEndLoc() const;
+
+ typedef Expr **iterator;
+ iterator begin() const;
+ iterator end() const;
+
+ bool isTypeDependent() const;
+
+ bool DiagnoseUnexpandedParameterPack(Sema &SemaRef) const;
+
+ // Return the InitListExpr or create a ParenListExpr.
+ Expr *CreateInitExpr(ASTContext &Ctx, QualType T) const;
+
+ ExprResult PerformInit(Sema &SemaRef, InitializedEntity Entity,
+ InitializationKind Kind) const;
+};
+}
+
+#endif
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index a7a0c2f7ae8..e52d2fefbcc 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -22,6 +22,7 @@
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/ExternalSemaSource.h"
#include "clang/Sema/LocInfoType.h"
+#include "clang/Sema/MultiInitializer.h"
#include "clang/Sema/TypoCorrection.h"
#include "clang/Sema/Weak.h"
#include "clang/AST/Expr.h"
@@ -3398,24 +3399,37 @@ public:
SourceLocation RParenLoc,
SourceLocation EllipsisLoc);
- MemInitResult BuildMemberInitializer(ValueDecl *Member, Expr **Args,
- unsigned NumArgs, SourceLocation IdLoc,
- SourceLocation LParenLoc,
- SourceLocation RParenLoc);
+ MemInitResult ActOnMemInitializer(Decl *ConstructorD,
+ Scope *S,
+ CXXScopeSpec &SS,
+ IdentifierInfo *MemberOrBase,
+ ParsedType TemplateTypeTy,
+ SourceLocation IdLoc,
+ Expr *InitList,
+ SourceLocation EllipsisLoc);
+
+ MemInitResult BuildMemInitializer(Decl *ConstructorD,
+ Scope *S,
+ CXXScopeSpec &SS,
+ IdentifierInfo *MemberOrBase,
+ ParsedType TemplateTypeTy,
+ SourceLocation IdLoc,
+ const MultiInitializer &Init,
+ SourceLocation EllipsisLoc);
+
+ MemInitResult BuildMemberInitializer(ValueDecl *Member,
+ const MultiInitializer &Args,
+ SourceLocation IdLoc);
MemInitResult BuildBaseInitializer(QualType BaseType,
TypeSourceInfo *BaseTInfo,
- Expr **Args, unsigned NumArgs,
- SourceLocation LParenLoc,
- SourceLocation RParenLoc,
+ const MultiInitializer &Args,
CXXRecordDecl *ClassDecl,
SourceLocation EllipsisLoc);
MemInitResult BuildDelegatingInitializer(TypeSourceInfo *TInfo,
- Expr **Args, unsigned NumArgs,
+ const MultiInitializer &Args,
SourceLocation BaseLoc,
- SourceLocation RParenLoc,
- SourceLocation LParenLoc,
CXXRecordDecl *ClassDecl);
bool SetDelegatingInitializer(CXXConstructorDecl *Constructor,
diff --git a/clang/lib/Parse/ParseCXXInlineMethods.cpp b/clang/lib/Parse/ParseCXXInlineMethods.cpp
index 1b364537cc0..0ca249fd1a9 100644
--- a/clang/lib/Parse/ParseCXXInlineMethods.cpp
+++ b/clang/lib/Parse/ParseCXXInlineMethods.cpp
@@ -125,8 +125,9 @@ Decl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS, ParsingDeclarator &D,
tok::TokenKind kind = Tok.getKind();
// We may have a constructor initializer or function-try-block here.
if (kind == tok::colon || kind == tok::kw_try) {
- // Consume everything up to (and including) the left brace.
- if (!ConsumeAndStoreUntil(tok::l_brace, Toks)) {
+ // Consume everything up to (and including) the left brace of the
+ // function body.
+ if (ConsumeAndStoreTryAndInitializers(Toks)) {
// We didn't find the left-brace we expected after the
// constructor initializer.
if (Tok.is(tok::semi)) {
@@ -579,3 +580,50 @@ bool Parser::ConsumeAndStoreUntil(tok::TokenKind T1, tok::TokenKind T2,
isFirstTokenConsumed = false;
}
}
+
+/// \brief Consume tokens and store them in the passed token container until
+/// we've passed the try keyword and constructor initializers and have consumed
+/// the opening brace of the function body.
+///
+/// \return True on error.
+bool Parser::ConsumeAndStoreTryAndInitializers(CachedTokens &Toks) {
+ if (Tok.is(tok::kw_try)) {
+ Toks.push_back(Tok);
+ ConsumeToken();
+ }
+ if (Tok.is(tok::colon)) {
+ // Initializers can contain braces too.
+ Toks.push_back(Tok);
+ ConsumeToken();
+
+ while (Tok.is(tok::identifier) || Tok.is(tok::coloncolon)) {
+ if (Tok.is(tok::eof) || Tok.is(tok::semi))
+ return true;
+
+ // Grab the identifier.
+ if (!ConsumeAndStoreUntil(tok::l_paren, tok::l_brace, Toks,
+ /*StopAtSemi=*/true,
+ /*ConsumeFinalToken=*/false))
+ return true;
+
+ tok::TokenKind kind = Tok.getKind();
+ Toks.push_back(Tok);
+ if (kind == tok::l_paren)
+ ConsumeParen();
+ else {
+ assert(kind == tok::l_brace && "Must be left paren or brace here.");
+ ConsumeBrace();
+ }
+
+ // Grab the initializer
+ if (!ConsumeAndStoreUntil(kind == tok::l_paren ? tok::r_paren :
+ tok::r_brace,
+ Toks, /*StopAtSemi=*/true))
+ return true;
+ }
+ }
+
+ // Grab any remaining garbage to be diagnosed later, and the opening
+ // brace of the function body.
+ return !ConsumeAndStoreUntil(tok::l_brace, Toks, /*StopAtSemi=*/true);
+}
diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp
index 0fcc863b125..21cf3a1e1cf 100644
--- a/clang/lib/Parse/ParseDeclCXX.cpp
+++ b/clang/lib/Parse/ParseDeclCXX.cpp
@@ -2292,9 +2292,17 @@ Parser::MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) {
// Parse the '('.
if (getLang().CPlusPlus0x && Tok.is(tok::l_brace)) {
- // FIXME: Do something with the braced-init-list.
- ParseBraceInitializer();
- return true;
+ ExprResult InitList = ParseBraceInitializer();
+ if (InitList.isInvalid())
+ return true;
+
+ SourceLocation EllipsisLoc;
+ if (Tok.is(tok::ellipsis))
+ EllipsisLoc = ConsumeToken();
+
+ return Actions.ActOnMemInitializer(ConstructorDecl, getCurScope(), SS, II,
+ TemplateTypeTy, IdLoc, InitList.take(),
+ EllipsisLoc);
} else if(Tok.is(tok::l_paren)) {
SourceLocation LParenLoc = ConsumeParen();
diff --git a/clang/lib/Parse/ParseTemplate.cpp b/clang/lib/Parse/ParseTemplate.cpp
index 5cc604bde12..5ffd5353370 100644
--- a/clang/lib/Parse/ParseTemplate.cpp
+++ b/clang/lib/Parse/ParseTemplate.cpp
@@ -1252,7 +1252,7 @@ void Parser::LexTemplateFunctionForLateParsing(CachedTokens &Toks) {
tok::TokenKind kind = Tok.getKind();
// We may have a constructor initializer or function-try-block here.
if (kind == tok::colon || kind == tok::kw_try)
- ConsumeAndStoreUntil(tok::l_brace, Toks);
+ ConsumeAndStoreTryAndInitializers(Toks);
else {
Toks.push_back(Tok);
ConsumeBrace();
diff --git a/clang/lib/Sema/MultiInitializer.cpp b/clang/lib/Sema/MultiInitializer.cpp
new file mode 100644
index 00000000000..8bd2213b570
--- /dev/null
+++ b/clang/lib/Sema/MultiInitializer.cpp
@@ -0,0 +1,92 @@
+//===--- 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());
+ for (iterator I = begin(), E = end(); I != E; ++I) {
+ if (SemaRef.DiagnoseUnexpandedParameterPack(*I))
+ 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/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 23b128db596..72c74084b27 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -1342,7 +1342,21 @@ static bool FindBaseInitializer(Sema &SemaRef,
return DirectBaseSpec || VirtualBaseSpec;
}
-/// ActOnMemInitializer - Handle a C++ member initializer.
+/// \brief Handle a C++ member initializer using braced-init-list syntax.
+MemInitResult
+Sema::ActOnMemInitializer(Decl *ConstructorD,
+ Scope *S,
+ CXXScopeSpec &SS,
+ IdentifierInfo *MemberOrBase,
+ ParsedType TemplateTypeTy,
+ SourceLocation IdLoc,
+ Expr *InitList,
+ SourceLocation EllipsisLoc) {
+ return BuildMemInitializer(ConstructorD, S, SS, MemberOrBase, TemplateTypeTy,
+ IdLoc, MultiInitializer(InitList), EllipsisLoc);
+}
+
+/// \brief Handle a C++ member initializer using parentheses syntax.
MemInitResult
Sema::ActOnMemInitializer(Decl *ConstructorD,
Scope *S,
@@ -1354,6 +1368,22 @@ Sema::ActOnMemInitializer(Decl *ConstructorD,
Expr **Args, unsigned NumArgs,
SourceLocation RParenLoc,
SourceLocation EllipsisLoc) {
+ return BuildMemInitializer(ConstructorD, S, SS, MemberOrBase, TemplateTypeTy,
+ IdLoc, MultiInitializer(LParenLoc, Args, NumArgs,
+ RParenLoc),
+ EllipsisLoc);
+}
+
+/// \brief Handle a C++ member initializer.
+MemInitResult
+Sema::BuildMemInitializer(Decl *ConstructorD,
+ Scope *S,
+ CXXScopeSpec &SS,
+ IdentifierInfo *MemberOrBase,
+ ParsedType TemplateTypeTy,
+ SourceLocation IdLoc,
+ const MultiInitializer &Args,
+ SourceLocation EllipsisLoc) {
if (!ConstructorD)
return true;
@@ -1388,26 +1418,23 @@ Sema::ActOnMemInitializer(Decl *ConstructorD,
= ClassDecl->lookup(MemberOrBase);
if (Result.first != Result.second) {
Member = dyn_cast<FieldDecl>(*Result.first);
-
+
if (Member) {
if (EllipsisLoc.isValid())
Diag(EllipsisLoc, diag::err_pack_expansion_member_init)
- << MemberOrBase << SourceRange(IdLoc, RParenLoc);
-
- return BuildMemberInitializer(Member, (Expr**)Args, NumArgs, IdLoc,
- LParenLoc, RParenLoc);
+ << MemberOrBase << SourceRange(IdLoc, Args.getEndLoc());
+
+ return BuildMemberInitializer(Member, Args, IdLoc);
}
-
+
// Handle anonymous union case.
if (IndirectFieldDecl* IndirectField
= dyn_cast<IndirectFieldDecl>(*Result.first)) {
if (EllipsisLoc.isValid())
Diag(EllipsisLoc, diag::err_pack_expansion_member_init)
- << MemberOrBase << SourceRange(IdLoc, RParenLoc);
+ << MemberOrBase << SourceRange(IdLoc, Args.getEndLoc());
- return BuildMemberInitializer(IndirectField, (Expr**)Args,
- NumArgs, IdLoc,
- LParenLoc, RParenLoc);
+ return BuildMemberInitializer(IndirectField, Args, IdLoc);
}
}
}
@@ -1466,8 +1493,7 @@ Sema::ActOnMemInitializer(Decl *ConstructorD,
Diag(Member->getLocation(), diag::note_previous_decl)
<< CorrectedQuotedStr;
- return BuildMemberInitializer(Member, (Expr**)Args, NumArgs, IdLoc,
- LParenLoc, RParenLoc);
+ return BuildMemberInitializer(Member, Args, IdLoc);
}
} else if (TypeDecl *Type = Corr.getCorrectionDeclAs<TypeDecl>()) {
const CXXBaseSpecifier *DirectBaseSpec;
@@ -1496,7 +1522,7 @@ Sema::ActOnMemInitializer(Decl *ConstructorD,
if (!TyD && BaseType.isNull()) {
Diag(IdLoc, diag::err_mem_init_not_member_or_class)
- << MemberOrBase << SourceRange(IdLoc, RParenLoc);
+ << MemberOrBase << SourceRange(IdLoc, Args.getEndLoc());
return true;
}
}
@@ -1516,8 +1542,7 @@ Sema::ActOnMemInitializer(Decl *ConstructorD,
if (!TInfo)
TInfo = Context.getTrivialTypeSourceInfo(BaseType, IdLoc);
- return BuildBaseInitializer(BaseType, TInfo, (Expr **)Args, NumArgs,
- LParenLoc, RParenLoc, ClassDecl, EllipsisLoc);
+ return BuildBaseInitializer(BaseType, TInfo, Args, ClassDecl, EllipsisLoc);
}
/// Checks a member initializer expression for cases where reference (or
@@ -1644,10 +1669,9 @@ static bool InitExprContainsUninitializedFields(const Stmt *S,
}
MemInitResult
-Sema::BuildMemberInitializer(ValueDecl *Member, Expr **Args,
- unsigned NumArgs, SourceLocation IdLoc,
- SourceLocation LParenLoc,
- SourceLocation RParenLoc) {
+Sema::BuildMemberInitializer(ValueDecl *Member,
+ const MultiInitializer &Args,
+ SourceLocation IdLoc) {
FieldDecl *DirectMember = dyn_cast<FieldDecl>(Member);
IndirectFieldDecl *IndirectMember = dyn_cast<IndirectFieldDecl>(Member);
assert((DirectMember || IndirectMember) &&
@@ -1660,9 +1684,13 @@ Sema::BuildMemberInitializer(ValueDecl *Member, Expr **Args,
// foo(foo)
// where foo is not also a parameter to the constructor.
// TODO: implement -Wuninitialized and fold this into that framework.
- for (unsigned i = 0; i < NumArgs; ++i) {
+ for (MultiInitializer::iterator I = Args.begin(), E = Args.end();
+ I != E; ++I) {
SourceLocation L;
- if (InitExprContainsUninitializedFields(Args[i], Member, &L)) {
+ Expr *Arg = *I;
+ if (DesignatedInitExpr *DIE = dyn_cast<DesignatedInitExpr>(Arg))
+ Arg = DIE->getInit();
+ if (InitExprContainsUninitializedFields(Arg, 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
@@ -1673,17 +1701,13 @@ Sema::BuildMemberInitializer(ValueDecl *Member, Expr **Args,
}
}
- bool HasDependentArg = false;
- for (unsigned i = 0; i < NumArgs; i++)
- HasDependentArg |= Args[i]->isTypeDependent();
+ bool HasDependentArg = Args.isTypeDependent();
Expr *Init;
if (Member->getType()->isDependentType() || HasDependentArg) {
// Can't check initialization for a member of dependent type or when
// any of the arguments are type-dependent expressions.
- Init = new (Context) ParenListExpr(Context, LParenLoc, Args, NumArgs,
- RParenLoc,
- Member->getType().getNonReferenceType());
+ Init = Args.CreateInitExpr(Context,Member->getType().getNonReferenceType());
DiscardCleanupsInEvaluationContext();
} else {
@@ -1692,17 +1716,14 @@ Sema::BuildMemberInitializer(ValueDecl *Member, Expr **Args,
DirectMember ? InitializedEntity::InitializeMember(DirectMember, 0)
: InitializedEntity::InitializeMember(IndirectMember, 0);
InitializationKind Kind =
- InitializationKind::CreateDirect(IdLoc, LParenLoc, RParenLoc);
+ InitializationKind::CreateDirect(IdLoc, Args.getStartLoc(),
+ Args.getEndLoc());
- InitializationSequence InitSeq(*this, MemberEntity, Kind, Args, NumArgs);
-
- ExprResult MemberInit =
- InitSeq.Perform(*this, MemberEntity, Kind,
- MultiExprArg(*this, Args, NumArgs), 0);
+ ExprResult MemberInit = Args.PerformInit(*this, MemberEntity, Kind);
if (MemberInit.isInvalid())
return true;
- CheckImplicitConversions(MemberInit.get(), LParenLoc);
+ CheckImplicitConversions(MemberInit.get(), Args.getStartLoc());
// C++0x [class.base.init]p7:
// The initialization of each base and member constitutes a
@@ -1719,9 +1740,8 @@ Sema::BuildMemberInitializer(ValueDecl *Member, Expr **Args,
// 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 = new (Context) ParenListExpr(
- Context, LParenLoc, Args, NumArgs, RParenLoc,
- Member->getType().getNonReferenceType());
+ Init = Args.CreateInitExpr(Context,
+ Member->getType().getNonReferenceType());
} else {
Init = MemberInit.get();
CheckForDanglingReferenceOrPointer(*this, Member, Init, IdLoc);
@@ -1730,21 +1750,19 @@ Sema::BuildMemberInitializer(ValueDecl *Member, Expr **Args,
if (DirectMember) {
return new (Context) CXXCtorInitializer(Context, DirectMember,
- IdLoc, LParenLoc, Init,
- RParenLoc);
+ IdLoc, Args.getStartLoc(),
+ Init, Args.getEndLoc());
} else {
return new (Context) CXXCtorInitializer(Context, IndirectMember,
- IdLoc, LParenLoc, Init,
- RParenLoc);
+ IdLoc, Args.getStartLoc(),
+ Init, Args.getEndLoc());
}
}
MemInitResult
Sema::BuildDelegatingInitializer(TypeSourceInfo *TInfo,
- Expr **Args, unsigned NumArgs,
+ const MultiInitializer &Args,
SourceLocation NameLoc,
- SourceLocation LParenLoc,
- SourceLocation RParenLoc,
CXXRecordDecl *ClassDecl) {
SourceLocation Loc = TInfo->getTypeLoc().getLocalSourceRange().getBegin();
if (!LangOpts.CPlusPlus0x)
@@ -1755,13 +1773,10 @@ Sema::BuildDelegatingInitializer(TypeSourceInfo *TInfo,
InitializedEntity DelegationEntity = InitializedEntity::InitializeDelegation(
QualType(ClassDecl->getTypeForDecl(), 0));
InitializationKind Kind =
- InitializationKind::CreateDirect(NameLoc, LParenLoc, RParenLoc);
-
- InitializationSequence InitSeq(*this, DelegationEntity, Kind, Args, NumArgs);
+ InitializationKind::CreateDirect(NameLoc, Args.getStartLoc(),
+ Args.getEndLoc());
- ExprResult DelegationInit =
- InitSeq.Perform(*this, DelegationEntity, Kind,
- MultiExprArg(*this, Args, NumArgs), 0);
+ ExprResult DelegationInit = Args.PerformInit(*this, DelegationEntity, Kind);
if (DelegationInit.isInvalid())
return true;
@@ -1770,7 +1785,7 @@ Sema::BuildDelegatingInitializer(TypeSourceInfo *TInfo,
= ConExpr->getConstructor();
assert(Constructor && "Delegating constructor with no target?");
- CheckImplicitConversions(DelegationInit.get(), LParenLoc);
+ CheckImplicitConversions(DelegationInit.get(), Args.getStartLoc());
// C++0x [class.base.init]p7:
// The initialization of each base and member constitutes a
@@ -1780,24 +1795,22 @@ Sema::BuildDelegatingInitializer(TypeSourceInfo *TInfo,
return true;
assert(!CurContext->isDependentContext());
- return new (Context) CXXCtorInitializer(Context, Loc, LParenLoc, Constructor,
+ return new (Context) CXXCtorInitializer(Context, Loc, Args.getStartLoc(),
+ Constructor,
DelegationInit.takeAs<Expr>(),
- RParenLoc);
+ Args.getEndLoc());
}
MemInitResult
Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo,
- Expr **Args, unsigned NumArgs,
- SourceLocation LParenLoc, SourceLocation RParenLoc,
+ const MultiInitializer &Args,
CXXRecordDecl *ClassDecl,
SourceLocation EllipsisLoc) {
- bool HasDependentArg = false;
- for (unsigned i = 0; i < NumArgs; i++)
- HasDependentArg |= Args[i]->isTypeDependent();
+ bool HasDependentArg = Args.isTypeDependent();
SourceLocation BaseLoc
= BaseTInfo->getTypeLoc().getLocalSourceRange().getBegin();
-
+
if (!BaseType->isDependentType() && !BaseType->isRecordType())
return Diag(BaseLoc, diag::err_base_init_does_not_name_class)
<< BaseType << BaseTInfo->getTypeLoc().getLocalSourceRange();
@@ -1814,28 +1827,26 @@ Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo,
// This is a pack expansion.
if (!BaseType->containsUnexpandedParameterPack()) {
Diag(EllipsisLoc, diag::err_pack_expansion_without_parameter_packs)
- << SourceRange(BaseLoc, RParenLoc);
-
+ << SourceRange(BaseLoc, Args.getEndLoc());
+
EllipsisLoc = SourceLocation();
}
} else {
// Check for any unexpanded parameter packs.
if (DiagnoseUnexpandedParameterPack(BaseLoc, BaseTInfo, UPPC_Initializer))
return true;
-
- for (unsigned I = 0; I != NumArgs; ++I)
- if (DiagnoseUnexpandedParameterPack(Args[I]))
- return true;
+
+ if (Args.DiagnoseUnexpandedParameterPack(*this))
+ return true;
}
-
+
// Check for direct and virtual base classes.
const CXXBaseSpecifier *DirectBaseSpec = 0;
const CXXBaseSpecifier *VirtualBaseSpec = 0;
if (!Dependent) {
if (Context.hasSameUnqualifiedType(QualType(ClassDecl->getTypeForDecl(),0),
BaseType))
- return BuildDelegatingInitializer(BaseTInfo, Args, NumArgs, BaseLoc,
- LParenLoc, RParenLoc, ClassDecl);
+ return BuildDelegatingInitializer(BaseTInfo, Args, BaseLoc, ClassDecl);
FindBaseInitializer(*this, ClassDecl, BaseType, DirectBaseSpec,
VirtualBaseSpec);
@@ -1862,18 +1873,14 @@ Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo,
if (Dependent) {
// Can't check initialization for a base of dependent type or when
// any of the arguments are type-dependent expressions.
- ExprResult BaseInit
- = Owned(new (Context) ParenListExpr(Context, LParenLoc, Args, NumArgs,
- RParenLoc, BaseType));
+ Expr *BaseInit = Args.CreateInitExpr(Context, BaseType);
DiscardCleanupsInEvaluationContext();
- return new (Context) CXXCtorInitializer(Context, BaseTInfo,
- /*IsVirtual=*/false,
- LParenLoc,
- BaseInit.takeAs<Expr>(),
- RParenLoc,
- EllipsisLoc);
+ return new (Context) CXXCtorInitializer(Context, BaseTInfo,
+ /*IsVirtual=*/false,
+ Args.getStartLoc(), BaseInit,
+ Args.getEndLoc(), EllipsisLoc);
}
// C++ [base.class.init]p2:
@@ -1893,18 +1900,15 @@ Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo,
InitializedEntity BaseEntity =
InitializedEntity::InitializeBase(Context, BaseSpec, VirtualBaseSpec);
InitializationKind Kind =
- InitializationKind::CreateDirect(BaseLoc, LParenLoc, RParenLoc);
-
- InitializationSequence InitSeq(*this, BaseEntity, Kind, Args, NumArgs);
-
- ExprResult BaseInit =
- InitSeq.Perform(*this, BaseEntity, Kind,
- MultiExprArg(*this, Args, NumArgs), 0);
+ InitializationKind::CreateDirect(BaseLoc, Args.getStartLoc(),
+ Args.getEndLoc());
+
+ ExprResult BaseInit = Args.PerformInit(*this, BaseEntity, Kind);
if (BaseInit.isInvalid())
return true;
- CheckImplicitConversions(BaseInit.get(), LParenLoc);
-
+ CheckImplicitConversions(BaseInit.get(), Args.getStartLoc());
+
// C++0x [class.base.init]p7:
// The initialization of each base and member constitutes a
// full-expression.
@@ -1919,24 +1923,14 @@ Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo,
// of the information that we have about the base
// 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()) {
- ExprResult Init
- = Owned(new (Context) ParenListExpr(Context, LParenLoc, Args, NumArgs,
- RParenLoc, BaseType));
- return new (Context) CXXCtorInitializer(Context, BaseTInfo,
- BaseSpec->isVirtual(),
- LParenLoc,
- Init.takeAs<Expr>(),
- RParenLoc,
- EllipsisLoc);
- }
+ if (CurContext->isDependentContext())
+ BaseInit = Owned(Args.CreateInitExpr(Context, BaseType));
return new (Context) CXXCtorInitializer(Context, BaseTInfo,
- BaseSpec->isVirtual(),
- LParenLoc,
- BaseInit.takeAs<Expr>(),
- RParenLoc,
- EllipsisLoc);
+ BaseSpec->isVirtual(),
+ Args.getStartLoc(),
+ BaseInit.takeAs<Expr>(),
+ Args.getEndLoc(), EllipsisLoc);
}
// Create a static_cast\<T&&>(expr).
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 43db5cbbd66..e29b75a2c27 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -2670,6 +2670,19 @@ void Sema::InstantiateStaticDataMemberDefinition(
}
}
+static MultiInitializer CreateMultiInitializer(
+ const SmallVectorImpl<Expr*> &Args,
+ const CXXCtorInitializer *Init) {
+ // FIXME: This is a hack that will do slightly the wrong thing for an
+ // initializer of the form foo({...}).
+ // The right thing to do would be to modify InstantiateInitializer to create
+ // the MultiInitializer.
+ if (Args.size() == 1 && isa<InitListExpr>(Args[0]))
+ return MultiInitializer(Args[0]);
+ return MultiInitializer(Init->getLParenLoc(), (Expr **)Args.data(),
+ Args.size(), Init->getRParenLoc());
+}
+
void
Sema::InstantiateMemInitializers(CXXConstructorDecl *New,
const CXXConstructorDecl *Tmpl,
@@ -2736,12 +2749,9 @@ Sema::InstantiateMemInitializers(CXXConstructorDecl *New,
}
// Build the initializer.
- MemInitResult NewInit = BuildBaseInitializer(BaseTInfo->getType(),
- BaseTInfo,
- (Expr **)NewArgs.data(),
- NewArgs.size(),
- Init->getLParenLoc(),
- Init->getRParenLoc(),
+ MultiInitializer MultiInit(CreateMultiInitializer(NewArgs, Init));
+ MemInitResult NewInit = BuildBaseInitializer(BaseTInfo->getType(),
+ BaseTInfo, MultiInit,
New->getParent(),
SourceLocation());
if (NewInit.isInvalid()) {
@@ -2774,14 +2784,10 @@ Sema::InstantiateMemInitializers(CXXConstructorDecl *New,
New->setInvalidDecl();
continue;
}
-
- NewInit = BuildBaseInitializer(BaseTInfo->getType(), BaseTInfo,
- (Expr **)NewArgs.data(),
- NewArgs.size(),
- Init->getLParenLoc(),
- Init->getRParenLoc(),
- New->getParent(),
- EllipsisLoc);
+
+ MultiInitializer MultiInit(CreateMultiInitializer(NewArgs, Init));
+ NewInit = BuildBaseInitializer(BaseTInfo->getType(), BaseTInfo, MultiInit,
+ New->getParent(), EllipsisLoc);
} else if (Init->isMemberInitializer()) {
FieldDecl *Member = cast_or_null<FieldDecl>(FindInstantiatedDecl(
Init->getMemberLocation(),
@@ -2793,11 +2799,9 @@ Sema::InstantiateMemInitializers(CXXConstructorDecl *New,
continue;
}
- NewInit = BuildMemberInitializer(Member, (Expr **)NewArgs.data(),
- NewArgs.size(),
- Init->getSourceLocation(),
- Init->getLParenLoc(),
- Init->getRParenLoc());
+ MultiInitializer MultiInit(CreateMultiInitializer(NewArgs, Init));
+ NewInit = BuildMemberInitializer(Member, MultiInit,
+ Init->getSourceLocation());
} else if (Init->isIndirectMemberInitializer()) {
IndirectFieldDecl *IndirectMember =
cast_or_null<IndirectFieldDecl>(FindInstantiatedDecl(
@@ -2807,14 +2811,12 @@ Sema::InstantiateMemInitializers(CXXConstructorDecl *New,
if (!IndirectMember) {
AnyErrors = true;
New->setInvalidDecl();
- continue;
+ continue;
}
-
- NewInit = BuildMemberInitializer(IndirectMember, (Expr **)NewArgs.data(),
- NewArgs.size(),
- Init->getSourceLocation(),
- Init->getLParenLoc(),
- Init->getRParenLoc());
+
+ MultiInitializer MultiInit(CreateMultiInitializer(NewArgs, Init));
+ NewInit = BuildMemberInitializer(IndirectMember, MultiInit,
+ Init->getSourceLocation());
}
if (NewInit.isInvalid()) {
diff --git a/clang/test/SemaCXX/cxx0x-initializer-scalars.cpp b/clang/test/SemaCXX/cxx0x-initializer-scalars.cpp
new file mode 100644
index 00000000000..71c4c8ecfcd
--- /dev/null
+++ b/clang/test/SemaCXX/cxx0x-initializer-scalars.cpp
@@ -0,0 +1,34 @@
+// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s
+
+namespace integral {
+
+ void initialization() {
+ { const int a{}; static_assert(a == 0, ""); }
+ { const int a = {}; static_assert(a == 0, ""); }
+ { const int a{1}; static_assert(a == 1, ""); }
+ { const int a = {1}; static_assert(a == 1, ""); }
+ { const int a{1, 2}; } // expected-error {{excess elements}}
+ { const int a = {1, 2}; } // expected-error {{excess elements}}
+ // FIXME: Redundant warnings.
+ { const short a{100000}; } // expected-error {{cannot be narrowed}} expected-note {{inserting an explicit cast}} expected-warning {{changes value}}
+ { const short a = {100000}; } // expected-error {{cannot be narrowed}} expected-note {{inserting an explicit cast}} expected-warning {{changes value}}
+ }
+
+ int direct_usage() {
+ int ar[10];
+ (void) ar[{1}]; // expected-error {{array subscript is not an integer}}
+
+ return {1};
+ }
+
+ void inline_init() {
+ (void) int{1};
+ (void) new int{1};
+ }
+
+ struct A {
+ int i;
+ A() : i{1} {}
+ };
+
+}
diff --git a/clang/test/SemaCXX/generalized-initializers.cpp b/clang/test/SemaCXX/generalized-initializers.cpp
index cf1b61e683c..5a420c6fc50 100644
--- a/clang/test/SemaCXX/generalized-initializers.cpp
+++ b/clang/test/SemaCXX/generalized-initializers.cpp
@@ -40,25 +40,9 @@ namespace std {
namespace integral {
- void initialization() {
- { const int a{}; static_assert(a == 0, ""); }
- { const int a = {}; static_assert(a == 0, ""); }
- { const int a{1}; static_assert(a == 1, ""); }
- { const int a = {1}; static_assert(a == 1, ""); }
- { const int a{1, 2}; } // expected-error {{excess elements}}
- { const int a = {1, 2}; } // expected-error {{excess elements}}
- { const short a{100000}; } // expected-error {{cannot be narrowed}}
- { const short a = {100000}; } // expected-error {{cannot be narrowed}}
- }
-
int function_call() {
void takes_int(int);
takes_int({1});
-
- int ar[10];
- (void) ar[{1}]; // expected-error {{initializer list is illegal with the built-in index operator}}
-
- return {1};
}
void inline_init() {
@@ -76,11 +60,6 @@ namespace integral {
for (int i : {1, 2, 3, 4}) {}
}
- struct A {
- int i;
- A() : i{1} {}
- };
-
}
namespace objects {
OpenPOWER on IntegriCloud