]> granicus.if.org Git - clang/commitdiff
Correctly parse braced member initializers (even in delayed parsing) and correctly...
authorSebastian Redl <sebastian.redl@getdesigned.at>
Sat, 24 Sep 2011 17:48:25 +0000 (17:48 +0000)
committerSebastian Redl <sebastian.redl@getdesigned.at>
Sat, 24 Sep 2011 17:48:25 +0000 (17:48 +0000)
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.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@140460 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Parse/Parser.h
include/clang/Sema/MultiInitializer.h [new file with mode: 0644]
include/clang/Sema/Sema.h
lib/Parse/ParseCXXInlineMethods.cpp
lib/Parse/ParseDeclCXX.cpp
lib/Parse/ParseTemplate.cpp
lib/Sema/MultiInitializer.cpp [new file with mode: 0644]
lib/Sema/SemaDeclCXX.cpp
lib/Sema/SemaTemplateInstantiateDecl.cpp
test/SemaCXX/cxx0x-initializer-scalars.cpp [new file with mode: 0644]
test/SemaCXX/generalized-initializers.cpp

index ee2dbd55198209c152554330f214c427d6558d9a..22349205976a28f2fc4a935102626444c526c383 100644 (file)
@@ -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/include/clang/Sema/MultiInitializer.h b/include/clang/Sema/MultiInitializer.h
new file mode 100644 (file)
index 0000000..c44e393
--- /dev/null
@@ -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
index a7a0c2f7ae84be3b09cb87a864bf2c097db95337..e52d2fefbcc3120bd6163b2eac066aece87397d9 100644 (file)
@@ -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,
index 1b364537cc010ffcb569151f0c9c60d6b9d1bb4e..0ca249fd1a979fb8a56b664552aefb5957685bf5 100644 (file)
@@ -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);
+}
index 0fcc863b1254178b8f0f2d2afd464a5dcfef797d..21cf3a1e1cfd01cba26c545ca2942c9ed11c1a16 100644 (file)
@@ -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();
 
index 5cc604bde12f721cd9b31046680e6b3019053bb6..5ffd535337007e47f2141acd7b121b451b7a0d8f 100644 (file)
@@ -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/lib/Sema/MultiInitializer.cpp b/lib/Sema/MultiInitializer.cpp
new file mode 100644 (file)
index 0000000..8bd2213
--- /dev/null
@@ -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);
+}
index 23b128db596d25bed92e2c6e17141b0d52cc447e..72c74084b27dbdf23794f3d5e49f3358e0698d73 100644 (file)
@@ -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).
index 43db5cbbd666631220af078e28650ba7227decab..e29b75a2c27fad3bc702ef0a759d75aaeedf3aa3 100644 (file)
@@ -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/test/SemaCXX/cxx0x-initializer-scalars.cpp b/test/SemaCXX/cxx0x-initializer-scalars.cpp
new file mode 100644 (file)
index 0000000..71c4c8e
--- /dev/null
@@ -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} {}
+  };
+
+}
index cf1b61e683c0cbe71c2dd2bd91387b9a0babc718..5a420c6fc500130b4e2d846ae3e6d3d9b7a51b80 100644 (file)
@@ -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 {