[cfe-commits] r122793 - in /cfe/trunk: include/clang/AST/DeclCXX.h include/clang/Basic/DiagnosticSemaKinds.td include/clang/Sema/Sema.h lib/AST/DeclCXX.cpp lib/Parse/ParseDeclCXX.cpp lib/Sema/SemaDeclCXX.cpp lib/Sema/SemaTemplateInstantiate.cpp lib/Sema/SemaTemplateInstantiateDecl.cpp lib/Serialization/ASTReader.cpp test/CXX/temp/temp.decls/temp.variadic/p4.cpp

Douglas Gregor dgregor at apple.com
Mon Jan 3 16:32:56 PST 2011


Author: dgregor
Date: Mon Jan  3 18:32:56 2011
New Revision: 122793

URL: http://llvm.org/viewvc/llvm-project?rev=122793&view=rev
Log:
Implement pack expansion of base initializers, so that we can
initialize those lovely mixins that come from pack expansions of base
specifiers.

Modified:
    cfe/trunk/include/clang/AST/DeclCXX.h
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/lib/AST/DeclCXX.cpp
    cfe/trunk/lib/Parse/ParseDeclCXX.cpp
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
    cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
    cfe/trunk/lib/Serialization/ASTReader.cpp
    cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/p4.cpp

Modified: cfe/trunk/include/clang/AST/DeclCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclCXX.h?rev=122793&r1=122792&r2=122793&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclCXX.h (original)
+++ cfe/trunk/include/clang/AST/DeclCXX.h Mon Jan  3 18:32:56 2011
@@ -1122,11 +1122,14 @@
 /// @endcode
 class CXXBaseOrMemberInitializer {
   /// \brief Either the base class name (stored as a TypeSourceInfo*), an normal
-  /// field (FieldDecl) or an anonymous field (IndirectFieldDecl*) being initialized.
-  llvm::PointerUnion3<TypeSourceInfo *, FieldDecl *, IndirectFieldDecl *> BaseOrMember;
-  
-  /// \brief The source location for the field name.
-  SourceLocation MemberLocation;
+  /// field (FieldDecl) or an anonymous field (IndirectFieldDecl*) being 
+  /// initialized.
+  llvm::PointerUnion3<TypeSourceInfo *, FieldDecl *, IndirectFieldDecl *> 
+    BaseOrMember;
+  
+  /// \brief The source location for the field name or, for a base initializer
+  /// pack expansion, the location of the ellipsis.
+  SourceLocation MemberOrEllipsisLocation;
   
   /// \brief The argument used to initialize the base or member, which may
   /// end up constructing an object (when multiple arguments are involved).
@@ -1168,7 +1171,8 @@
                              TypeSourceInfo *TInfo, bool IsVirtual,
                              SourceLocation L, 
                              Expr *Init,
-                             SourceLocation R);
+                             SourceLocation R,
+                             SourceLocation EllipsisLoc);
 
   /// CXXBaseOrMemberInitializer - Creates a new member initializer.
   explicit
@@ -1213,6 +1217,17 @@
     return BaseOrMember.is<IndirectFieldDecl*>();
   }
 
+  /// \brief Determine whether this initializer is a pack expansion.
+  bool isPackExpansion() const { 
+    return isBaseInitializer() && MemberOrEllipsisLocation.isValid(); 
+  }
+  
+  // \brief For a pack expansion, returns the location of the ellipsis.
+  SourceLocation getEllipsisLoc() const {
+    assert(isPackExpansion() && "Initializer is not a pack expansion");
+    return MemberOrEllipsisLocation;
+  }
+           
   /// If this is a base class initializer, returns the type of the 
   /// base class with location information. Otherwise, returns an NULL
   /// type location.
@@ -1261,7 +1276,7 @@
   }
 
   SourceLocation getMemberLocation() const { 
-    return MemberLocation;
+    return MemberOrEllipsisLocation;
   }
   
   /// \brief Determine the source location of the initializer.

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=122793&r1=122792&r2=122793&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Mon Jan  3 18:32:56 2011
@@ -1862,6 +1862,8 @@
 def err_pack_expansion_length_conflict : Error<
   "pack expansion contains parameter packs %0 and %1 that have different "
   "lengths (%2 vs. %3)">;
+def err_pack_expansion_member_init : Error<
+  "pack expansion for initialization of member %0">;
 
 def err_function_parameter_pack_without_parameter_packs : Error<
   "type %0 of function parameter pack does not contain any unexpanded "

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=122793&r1=122792&r2=122793&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Mon Jan  3 18:32:56 2011
@@ -2541,7 +2541,8 @@
                                     SourceLocation IdLoc,
                                     SourceLocation LParenLoc,
                                     Expr **Args, unsigned NumArgs,
-                                    SourceLocation RParenLoc);
+                                    SourceLocation RParenLoc,
+                                    SourceLocation EllipsisLoc);
 
   MemInitResult BuildMemberInitializer(ValueDecl *Member, Expr **Args,
                                        unsigned NumArgs, SourceLocation IdLoc,
@@ -2553,7 +2554,8 @@
                                      Expr **Args, unsigned NumArgs,
                                      SourceLocation LParenLoc,
                                      SourceLocation RParenLoc,
-                                     CXXRecordDecl *ClassDecl);
+                                     CXXRecordDecl *ClassDecl,
+                                     SourceLocation EllipsisLoc);
 
   bool SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor,
                                    CXXBaseOrMemberInitializer **Initializers,

Modified: cfe/trunk/lib/AST/DeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclCXX.cpp?rev=122793&r1=122792&r2=122793&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclCXX.cpp (original)
+++ cfe/trunk/lib/AST/DeclCXX.cpp Mon Jan  3 18:32:56 2011
@@ -1002,8 +1002,9 @@
 CXXBaseOrMemberInitializer::
 CXXBaseOrMemberInitializer(ASTContext &Context,
                            TypeSourceInfo *TInfo, bool IsVirtual,
-                           SourceLocation L, Expr *Init, SourceLocation R)
-  : BaseOrMember(TInfo), Init(Init), 
+                           SourceLocation L, Expr *Init, SourceLocation R,
+                           SourceLocation EllipsisLoc)
+  : BaseOrMember(TInfo), MemberOrEllipsisLocation(EllipsisLoc), Init(Init), 
     LParenLoc(L), RParenLoc(R), IsVirtual(IsVirtual), IsWritten(false),
     SourceOrderOrNumArrayIndices(0)
 {
@@ -1013,7 +1014,7 @@
 CXXBaseOrMemberInitializer(ASTContext &Context,
                            FieldDecl *Member, SourceLocation MemberLoc,
                            SourceLocation L, Expr *Init, SourceLocation R)
-  : BaseOrMember(Member), MemberLocation(MemberLoc), Init(Init),
+  : BaseOrMember(Member), MemberOrEllipsisLocation(MemberLoc), Init(Init),
     LParenLoc(L), RParenLoc(R), IsVirtual(false),
     IsWritten(false), SourceOrderOrNumArrayIndices(0)
 {
@@ -1023,7 +1024,7 @@
 CXXBaseOrMemberInitializer(ASTContext &Context,
                            IndirectFieldDecl *Member, SourceLocation MemberLoc,
                            SourceLocation L, Expr *Init, SourceLocation R)
-  : BaseOrMember(Member), MemberLocation(MemberLoc), Init(Init),
+  : BaseOrMember(Member), MemberOrEllipsisLocation(MemberLoc), Init(Init),
     LParenLoc(L), RParenLoc(R), IsVirtual(false),
     IsWritten(false), SourceOrderOrNumArrayIndices(0)
 {
@@ -1035,7 +1036,7 @@
                            SourceLocation L, Expr *Init, SourceLocation R,
                            VarDecl **Indices,
                            unsigned NumIndices)
-  : BaseOrMember(Member), MemberLocation(MemberLoc), Init(Init), 
+  : BaseOrMember(Member), MemberOrEllipsisLocation(MemberLoc), Init(Init), 
     LParenLoc(L), RParenLoc(R), IsVirtual(false),
     IsWritten(false), SourceOrderOrNumArrayIndices(NumIndices)
 {

Modified: cfe/trunk/lib/Parse/ParseDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=122793&r1=122792&r2=122793&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Mon Jan  3 18:32:56 2011
@@ -1739,8 +1739,8 @@
 ///          ':' mem-initializer-list
 ///
 /// [C++]  mem-initializer-list:
-///          mem-initializer
-///          mem-initializer , mem-initializer-list
+///          mem-initializer ...[opt]
+///          mem-initializer ...[opt] , mem-initializer-list
 void Parser::ParseConstructorInitializer(Decl *ConstructorDecl) {
   assert(Tok.is(tok::colon) && "Constructor initializer always starts with ':'");
 
@@ -1839,10 +1839,15 @@
 
   SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
 
+  SourceLocation EllipsisLoc;
+  if (Tok.is(tok::ellipsis))
+    EllipsisLoc = ConsumeToken();
+  
   return Actions.ActOnMemInitializer(ConstructorDecl, getCurScope(), SS, II,
                                      TemplateTypeTy, IdLoc,
                                      LParenLoc, ArgExprs.take(),
-                                     ArgExprs.size(), RParenLoc);
+                                     ArgExprs.size(), RParenLoc,
+                                     EllipsisLoc);
 }
 
 /// ParseExceptionSpecification - Parse a C++ exception-specification

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=122793&r1=122792&r2=122793&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Mon Jan  3 18:32:56 2011
@@ -1057,7 +1057,8 @@
                           SourceLocation IdLoc,
                           SourceLocation LParenLoc,
                           ExprTy **Args, unsigned NumArgs,
-                          SourceLocation RParenLoc) {
+                          SourceLocation RParenLoc,
+                          SourceLocation EllipsisLoc) {
   if (!ConstructorD)
     return true;
 
@@ -1093,15 +1094,26 @@
     if (Result.first != Result.second) {
       Member = dyn_cast<FieldDecl>(*Result.first);
     
-      if (Member)
+      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);
+      }
+      
       // Handle anonymous union case.
       if (IndirectFieldDecl* IndirectField
-            = dyn_cast<IndirectFieldDecl>(*Result.first))
+            = dyn_cast<IndirectFieldDecl>(*Result.first)) {
+        if (EllipsisLoc.isValid())
+          Diag(EllipsisLoc, diag::err_pack_expansion_member_init)
+            << MemberOrBase << SourceRange(IdLoc, RParenLoc);
+
          return BuildMemberInitializer(IndirectField, (Expr**)Args,
                                        NumArgs, IdLoc,
                                        LParenLoc, RParenLoc);
+      }
     }
   }
   // It didn't name a member, so see if it names a class.
@@ -1210,7 +1222,7 @@
     TInfo = Context.getTrivialTypeSourceInfo(BaseType, IdLoc);
 
   return BuildBaseInitializer(BaseType, TInfo, (Expr **)Args, NumArgs, 
-                              LParenLoc, RParenLoc, ClassDecl);
+                              LParenLoc, RParenLoc, ClassDecl, EllipsisLoc);
 }
 
 /// Checks an initializer expression for use of uninitialized fields, such as
@@ -1383,7 +1395,8 @@
 Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo,
                            Expr **Args, unsigned NumArgs, 
                            SourceLocation LParenLoc, SourceLocation RParenLoc, 
-                           CXXRecordDecl *ClassDecl) {
+                           CXXRecordDecl *ClassDecl,
+                           SourceLocation EllipsisLoc) {
   bool HasDependentArg = false;
   for (unsigned i = 0; i < NumArgs; i++)
     HasDependentArg |= Args[i]->isTypeDependent();
@@ -1403,6 +1416,24 @@
   //   name that denotes that base class type.
   bool Dependent = BaseType->isDependentType() || HasDependentArg;
 
+  if (EllipsisLoc.isValid()) {
+    // This is a pack expansion.
+    if (!BaseType->containsUnexpandedParameterPack())  {
+      Diag(EllipsisLoc, diag::err_pack_expansion_without_parameter_packs)
+        << SourceRange(BaseLoc, RParenLoc);
+      
+      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;
+  }
+  
   // Check for direct and virtual base classes.
   const CXXBaseSpecifier *DirectBaseSpec = 0;
   const CXXBaseSpecifier *VirtualBaseSpec = 0;
@@ -1447,7 +1478,8 @@
                                                     /*IsVirtual=*/false,
                                                     LParenLoc, 
                                                     BaseInit.takeAs<Expr>(),
-                                                    RParenLoc);
+                                                    RParenLoc,
+                                                    EllipsisLoc);
   }
 
   // C++ [base.class.init]p2:
@@ -1501,14 +1533,16 @@
                                                     BaseSpec->isVirtual(),
                                                     LParenLoc, 
                                                     Init.takeAs<Expr>(),
-                                                    RParenLoc);
+                                                    RParenLoc,
+                                                    EllipsisLoc);
   }
 
   return new (Context) CXXBaseOrMemberInitializer(Context, BaseTInfo,
                                                   BaseSpec->isVirtual(),
                                                   LParenLoc, 
                                                   BaseInit.takeAs<Expr>(),
-                                                  RParenLoc);
+                                                  RParenLoc,
+                                                  EllipsisLoc);
 }
 
 /// ImplicitInitializerKind - How an implicit base or member initializer should
@@ -1586,6 +1620,7 @@
                                              BaseSpec->isVirtual(),
                                              SourceLocation(),
                                              BaseInit.takeAs<Expr>(),
+                                             SourceLocation(),
                                              SourceLocation());
 
   return false;

Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp?rev=122793&r1=122792&r2=122793&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Mon Jan  3 18:32:56 2011
@@ -1169,8 +1169,8 @@
                                           Unexpanded.data(), Unexpanded.size(),
                                           TemplateArgs, ShouldExpand, 
                                           NumExpansions)) {
-        continue;
         Invalid = true;
+        continue;
       }
       
       // If we should expand this pack expansion now, do so.

Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=122793&r1=122792&r2=122793&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Mon Jan  3 18:32:56 2011
@@ -2362,6 +2362,69 @@
     SourceLocation LParenLoc, RParenLoc;
     ASTOwningVector<Expr*> NewArgs(*this);
 
+    SourceLocation EllipsisLoc;
+    
+    if (Init->isPackExpansion()) {
+      // This is a pack expansion. We should expand it now.
+      TypeLoc BaseTL = Init->getBaseClassInfo()->getTypeLoc();
+      llvm::SmallVector<UnexpandedParameterPack, 2> Unexpanded;
+      collectUnexpandedParameterPacks(BaseTL, Unexpanded);
+      bool ShouldExpand = false;
+      unsigned NumExpansions = 0;
+      if (CheckParameterPacksForExpansion(Init->getEllipsisLoc(), 
+                                          BaseTL.getSourceRange(),
+                                          Unexpanded.data(), 
+                                          Unexpanded.size(),
+                                          TemplateArgs, ShouldExpand, 
+                                          NumExpansions)) {
+        AnyErrors = true;
+        New->setInvalidDecl();
+        continue;
+      }
+      assert(ShouldExpand && "Partial instantiation of base initializer?");
+      
+      // Loop over all of the arguments in the argument pack(s), 
+      for (unsigned I = 0; I != NumExpansions; ++I) {
+        Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(*this, I);
+
+        // Instantiate the initializer.
+        if (InstantiateInitializer(*this, Init->getInit(), TemplateArgs, 
+                                   LParenLoc, NewArgs, RParenLoc)) {
+          AnyErrors = true;
+          break;
+        }
+
+        // Instantiate the base type.
+        TypeSourceInfo *BaseTInfo = SubstType(Init->getBaseClassInfo(), 
+                                              TemplateArgs, 
+                                              Init->getSourceLocation(), 
+                                              New->getDeclName());
+        if (!BaseTInfo) {
+          AnyErrors = true;
+          break;
+        }
+
+        // Build the initializer.
+        MemInitResult NewInit = BuildBaseInitializer(BaseTInfo->getType(), 
+                                                     BaseTInfo,
+                                                     (Expr **)NewArgs.data(),
+                                                     NewArgs.size(),
+                                                     Init->getLParenLoc(),
+                                                     Init->getRParenLoc(),
+                                                     New->getParent(),
+                                                     SourceLocation());
+        if (NewInit.isInvalid()) {
+          AnyErrors = true;
+          break;
+        }
+        
+        NewInits.push_back(NewInit.get());
+        NewArgs.clear();
+      }
+      
+      continue;
+    }
+
     // Instantiate the initializer.
     if (InstantiateInitializer(*this, Init->getInit(), TemplateArgs, 
                                LParenLoc, NewArgs, RParenLoc)) {
@@ -2386,7 +2449,8 @@
                                      NewArgs.size(),
                                      Init->getLParenLoc(),
                                      Init->getRParenLoc(),
-                                     New->getParent());
+                                     New->getParent(),
+                                     EllipsisLoc);
     } else if (Init->isMemberInitializer()) {
       FieldDecl *Member = cast<FieldDecl>(FindInstantiatedDecl(
                                                      Init->getMemberLocation(),

Modified: cfe/trunk/lib/Serialization/ASTReader.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReader.cpp?rev=122793&r1=122792&r2=122793&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReader.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReader.cpp Mon Jan  3 18:32:56 2011
@@ -4325,7 +4325,7 @@
         else
           Member = cast<FieldDecl>(GetDecl(Record[Idx++]));
       }
-      SourceLocation MemberLoc = ReadSourceLocation(F, Record, Idx);
+      SourceLocation MemberOrEllipsisLoc = ReadSourceLocation(F, Record, Idx);
       Expr *Init = ReadExpr(F);
       SourceLocation LParenLoc = ReadSourceLocation(F, Record, Idx);
       SourceLocation RParenLoc = ReadSourceLocation(F, Record, Idx);
@@ -4345,18 +4345,22 @@
       if (IsBaseInitializer) {
         BOMInit = new (C) CXXBaseOrMemberInitializer(C, BaseClassInfo,
                                                      IsBaseVirtual, LParenLoc,
-                                                     Init, RParenLoc);
+                                                     Init, RParenLoc,
+                                                     MemberOrEllipsisLoc);
       } else if (IsWritten) {
         if (Member)
-          BOMInit = new (C) CXXBaseOrMemberInitializer(C, Member, MemberLoc,
+          BOMInit = new (C) CXXBaseOrMemberInitializer(C, Member, 
+                                                       MemberOrEllipsisLoc,
                                                        LParenLoc, Init,
                                                        RParenLoc);
         else 
           BOMInit = new (C) CXXBaseOrMemberInitializer(C, IndirectMember,
-                                                       MemberLoc, LParenLoc,
+                                                       MemberOrEllipsisLoc,
+                                                       LParenLoc,
                                                        Init, RParenLoc);
       } else {
-        BOMInit = CXXBaseOrMemberInitializer::Create(C, Member, MemberLoc,
+        BOMInit = CXXBaseOrMemberInitializer::Create(C, Member, 
+                                                     MemberOrEllipsisLoc,
                                                      LParenLoc, Init, RParenLoc,
                                                      Indices.data(),
                                                      Indices.size());

Modified: cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/p4.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/p4.cpp?rev=122793&r1=122792&r2=122793&view=diff
==============================================================================
--- cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/p4.cpp (original)
+++ cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/p4.cpp Mon Jan  3 18:32:56 2011
@@ -36,9 +36,14 @@
 
 // In a base-specifier-list (Clause 10); the pattern is a base-specifier.
 template<typename ...Mixins>
-struct HasMixins : public Mixins... { };
+struct HasMixins : public Mixins... { 
+  HasMixins();
+  HasMixins(const HasMixins&);
+  HasMixins(int i);
+};
 
-struct A { };
+struct A { }; // expected-note{{candidate constructor (the implicit copy constructor) not viable: no known conversion from 'int' to 'const A' for 1st argument}} \
+// expected-note{{candidate constructor (the implicit default constructor) not viable: requires 0 arguments, but 1 was provided}}
 struct B { };
 struct C { };
 struct D { };
@@ -52,6 +57,29 @@
 template<typename Mixins>
 struct BrokenMixins : public Mixins... { }; // expected-error{{pack expansion does not contain any unexpanded parameter packs}}
 
+// In a mem-initializer-list (12.6.2); the pattern is a mem-initializer.
+template<typename ...Mixins>
+HasMixins<Mixins...>::HasMixins(): Mixins()... { }
+
+template<typename ...Mixins>
+HasMixins<Mixins...>::HasMixins(const HasMixins &other): Mixins(other)... { }
+
+template<typename ...Mixins>
+HasMixins<Mixins...>::HasMixins(int i): Mixins(i)... { } // expected-error{{no matching constructor for initialization of 'A'}}
+
+void test_has_mixins() {
+  HasMixins<A, B> ab;
+  HasMixins<A, B> ab2 = ab;
+  HasMixins<A, B> ab3(17); // expected-note{{in instantiation of member function 'HasMixins<A, B>::HasMixins' requested here}}
+}
+
+template<typename T>
+struct X {
+  T member;
+
+  X() : member()... { } // expected-error{{pack expansion for initialization of member 'member'}}
+};
+
 // In a template-argument-list (14.3); the pattern is a template-argument.
 template<typename ...Types>
 struct tuple_of_refs {





More information about the cfe-commits mailing list