[cfe-commits] r140460 - in /cfe/trunk: include/clang/Parse/Parser.h include/clang/Sema/MultiInitializer.h include/clang/Sema/Sema.h lib/Parse/ParseCXXInlineMethods.cpp lib/Parse/ParseDeclCXX.cpp lib/Parse/ParseTemplate.cpp lib/Sema/MultiInitializer.cpp lib/Sema/SemaDeclCXX.cpp lib/Sema/SemaTemplateInstantiateDecl.cpp test/SemaCXX/cxx0x-initializer-scalars.cpp test/SemaCXX/generalized-initializers.cpp

Sebastian Redl sebastian.redl at getdesigned.at
Sat Sep 24 10:48:25 PDT 2011


Author: cornedbee
Date: Sat Sep 24 12:48:25 2011
New Revision: 140460

URL: http://llvm.org/viewvc/llvm-project?rev=140460&view=rev
Log:
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.

Added:
    cfe/trunk/include/clang/Sema/MultiInitializer.h
    cfe/trunk/lib/Sema/MultiInitializer.cpp
    cfe/trunk/test/SemaCXX/cxx0x-initializer-scalars.cpp
Modified:
    cfe/trunk/include/clang/Parse/Parser.h
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp
    cfe/trunk/lib/Parse/ParseDeclCXX.cpp
    cfe/trunk/lib/Parse/ParseTemplate.cpp
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
    cfe/trunk/test/SemaCXX/generalized-initializers.cpp

Modified: cfe/trunk/include/clang/Parse/Parser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=140460&r1=140459&r2=140460&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Sat Sep 24 12:48:25 2011
@@ -1060,6 +1060,7 @@
   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,

Added: cfe/trunk/include/clang/Sema/MultiInitializer.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/MultiInitializer.h?rev=140460&view=auto
==============================================================================
--- cfe/trunk/include/clang/Sema/MultiInitializer.h (added)
+++ cfe/trunk/include/clang/Sema/MultiInitializer.h Sat Sep 24 12:48:25 2011
@@ -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

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=140460&r1=140459&r2=140460&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Sat Sep 24 12:48:25 2011
@@ -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 @@
                                     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,

Modified: cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp?rev=140460&r1=140459&r2=140460&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp (original)
+++ cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp Sat Sep 24 12:48:25 2011
@@ -125,8 +125,9 @@
   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 @@
     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);
+}

Modified: cfe/trunk/lib/Parse/ParseDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=140460&r1=140459&r2=140460&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Sat Sep 24 12:48:25 2011
@@ -2292,9 +2292,17 @@
 
   // 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();
 

Modified: cfe/trunk/lib/Parse/ParseTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseTemplate.cpp?rev=140460&r1=140459&r2=140460&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseTemplate.cpp (original)
+++ cfe/trunk/lib/Parse/ParseTemplate.cpp Sat Sep 24 12:48:25 2011
@@ -1252,7 +1252,7 @@
   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();

Added: cfe/trunk/lib/Sema/MultiInitializer.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/MultiInitializer.cpp?rev=140460&view=auto
==============================================================================
--- cfe/trunk/lib/Sema/MultiInitializer.cpp (added)
+++ cfe/trunk/lib/Sema/MultiInitializer.cpp Sat Sep 24 12:48:25 2011
@@ -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);
+}

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=140460&r1=140459&r2=140460&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Sat Sep 24 12:48:25 2011
@@ -1342,7 +1342,21 @@
   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 @@
                           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 @@
       = 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 @@
             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 @@
 
       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 @@
   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 @@
 }
 
 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 @@
   //   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 @@
     }
   }
 
-  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 @@
       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 @@
     // 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 @@
 
   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 @@
   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 @@
     = 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 @@
     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 @@
     // 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 @@
   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 @@
   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 @@
   // 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).

Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=140460&r1=140459&r2=140460&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Sat Sep 24 12:48:25 2011
@@ -2670,6 +2670,19 @@
   }
 }
 
+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 @@
         }
 
         // 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 @@
         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 @@
         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 @@
       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()) {

Added: cfe/trunk/test/SemaCXX/cxx0x-initializer-scalars.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx0x-initializer-scalars.cpp?rev=140460&view=auto
==============================================================================
--- cfe/trunk/test/SemaCXX/cxx0x-initializer-scalars.cpp (added)
+++ cfe/trunk/test/SemaCXX/cxx0x-initializer-scalars.cpp Sat Sep 24 12:48:25 2011
@@ -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} {}
+  };
+
+}

Modified: cfe/trunk/test/SemaCXX/generalized-initializers.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/generalized-initializers.cpp?rev=140460&r1=140459&r2=140460&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/generalized-initializers.cpp (original)
+++ cfe/trunk/test/SemaCXX/generalized-initializers.cpp Sat Sep 24 12:48:25 2011
@@ -40,25 +40,9 @@
 
 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 @@
     for (int i : {1, 2, 3, 4}) {}
   }
 
-  struct A {
-    int i;
-    A() : i{1} {}
-  };
-
 }
 
 namespace objects {





More information about the cfe-commits mailing list