[cfe-commits] r121724 - in /cfe/trunk: include/clang/AST/ include/clang/Basic/ include/clang/Sema/ lib/AST/ lib/Sema/ lib/Serialization/ test/CXX/temp/temp.decls/temp.variadic/

Douglas Gregor dgregor at apple.com
Mon Dec 13 14:49:23 PST 2010


Author: dgregor
Date: Mon Dec 13 16:49:22 2010
New Revision: 121724

URL: http://llvm.org/viewvc/llvm-project?rev=121724&view=rev
Log:
Variadic templates: extend Type, NestedNameSpecifier, TemplateName,
and TemplateArgument with an operation that determines whether there
are any unexpanded parameter packs within that construct. Use this
information to diagnose the appearance of the names of parameter packs
that have not been expanded (C++ [temp.variadic]p5). Since this
property is checked often (every declaration, ever expression
statement, etc.), we extend Type and Expr with a bit storing the
result of this computation, rather than walking the AST each time to
determine whether any unexpanded parameter packs occur.

This commit is deficient in several ways, which will be remedied with
future commits:
  - Expr has a bit to store the presence of an unexpanded parameter
  pack, but it is never set.
  - The error messages don't point out where the unexpanded parameter
  packs were named in the type/expression, but they should. 
  - We don't check for unexpanded parameter packs in all of the places
  where we should.
  - Testing is sparse, pending the resolution of the above three
  issues.


Added:
    cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/p5.cpp   (with props)
Modified:
    cfe/trunk/include/clang/AST/DeclTemplate.h
    cfe/trunk/include/clang/AST/Expr.h
    cfe/trunk/include/clang/AST/NestedNameSpecifier.h
    cfe/trunk/include/clang/AST/Stmt.h
    cfe/trunk/include/clang/AST/TemplateBase.h
    cfe/trunk/include/clang/AST/TemplateName.h
    cfe/trunk/include/clang/AST/Type.h
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/lib/AST/NestedNameSpecifier.cpp
    cfe/trunk/lib/AST/TemplateBase.cpp
    cfe/trunk/lib/AST/TemplateName.cpp
    cfe/trunk/lib/AST/Type.cpp
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/lib/Sema/SemaExprCXX.cpp
    cfe/trunk/lib/Sema/SemaTemplate.cpp
    cfe/trunk/lib/Serialization/ASTReaderStmt.cpp
    cfe/trunk/lib/Serialization/ASTWriterStmt.cpp

Modified: cfe/trunk/include/clang/AST/DeclTemplate.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclTemplate.h?rev=121724&r1=121723&r2=121724&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclTemplate.h (original)
+++ cfe/trunk/include/clang/AST/DeclTemplate.h Mon Dec 13 16:49:22 2010
@@ -1080,6 +1080,14 @@
   using TemplateParmPosition::getPosition;
   using TemplateParmPosition::getIndex;
 
+  /// \brief Whether this template template parameter is a template
+  /// parameter pack.
+  ///
+  /// \code
+  /// template<template <class T> ...MetaFunctions> struct Apply;
+  /// \endcode
+  bool isParameterPack() const { return /*FIXME: variadic templates*/false; }
+
   /// \brief Determine whether this template parameter has a default
   /// argument.
   bool hasDefaultArgument() const {

Modified: cfe/trunk/include/clang/AST/Expr.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Expr.h?rev=121724&r1=121723&r2=121724&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Expr.h (original)
+++ cfe/trunk/include/clang/AST/Expr.h Mon Dec 13 16:49:22 2010
@@ -62,6 +62,8 @@
     ExprBits.ValueDependent = VD;
     ExprBits.ValueKind = VK;
     ExprBits.ObjectKind = OK;
+    // FIXME: Variadic templates.
+    ExprBits.ContainsUnexpandedParameterPack = false;
     setType(T);
   }
 
@@ -112,6 +114,24 @@
   /// \brief Set whether this expression is type-dependent or not.
   void setTypeDependent(bool TD) { ExprBits.TypeDependent = TD; }
 
+  /// \brief Whether this expression contains an unexpanded parameter
+  /// pack (for C++0x variadic templates).
+  ///
+  /// Given the following function template:
+  ///
+  /// \code
+  /// template<typename F, typename ...Types>
+  /// void forward(const F &f, Types &&...args) {
+  ///   f(static_cast<Types&&>(args)...);
+  /// }
+  /// \endcode
+  ///
+  /// The expressions \c args and \c static_cast<Types&&>(args) both
+  /// contain parameter packs.
+  bool containsUnexpandedParameterPack() const { 
+    return ExprBits.ContainsUnexpandedParameterPack; 
+  }
+
   /// SourceLocation tokens are not useful in isolation - they are low level
   /// value objects created/interpreted by SourceManager. We assume AST
   /// clients will have a pointer to the respective SourceManager.

Modified: cfe/trunk/include/clang/AST/NestedNameSpecifier.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/NestedNameSpecifier.h?rev=121724&r1=121723&r2=121724&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/NestedNameSpecifier.h (original)
+++ cfe/trunk/include/clang/AST/NestedNameSpecifier.h Mon Dec 13 16:49:22 2010
@@ -172,6 +172,10 @@
   /// type or not.
   bool isDependent() const;
 
+  /// \brief Whether this nested-name-specifier contains an unexpanded
+  /// parameter pack (for C++0x variadic templates).
+  bool containsUnexpandedParameterPack() const;
+
   /// \brief Print this nested name specifier to the given output
   /// stream.
   void print(llvm::raw_ostream &OS, const PrintingPolicy &Policy) const;

Modified: cfe/trunk/include/clang/AST/Stmt.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Stmt.h?rev=121724&r1=121723&r2=121724&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Stmt.h (original)
+++ cfe/trunk/include/clang/AST/Stmt.h Mon Dec 13 16:49:22 2010
@@ -143,14 +143,16 @@
     friend class DeclRefExpr; // computeDependence
     friend class InitListExpr; // ctor
     friend class DesignatedInitExpr; // ctor
+    friend class ASTStmtReader;
     unsigned : NumStmtBits;
 
     unsigned ValueKind : 2;
     unsigned ObjectKind : 2;
     unsigned TypeDependent : 1;
     unsigned ValueDependent : 1;
+    unsigned ContainsUnexpandedParameterPack : 1;
   };
-  enum { NumExprBits = 14 };
+  enum { NumExprBits = 15 };
 
   class CastExprBitfields {
     friend class CastExpr;
@@ -168,6 +170,8 @@
     CastExprBitfields CastExprBits;
   };
 
+  friend class ASTStmtReader;
+
 public:
   // Only allow allocation of Stmts using the allocator in ASTContext
   // or by doing a placement new.

Modified: cfe/trunk/include/clang/AST/TemplateBase.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/TemplateBase.h?rev=121724&r1=121723&r2=121724&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/TemplateBase.h (original)
+++ cfe/trunk/include/clang/AST/TemplateBase.h Mon Dec 13 16:49:22 2010
@@ -182,6 +182,10 @@
   /// \brief Determine whether this template argument has no value.
   bool isNull() const { return Kind == Null; }
 
+  /// \brief Whether this template argument contains an unexpanded
+  /// parameter pack.
+  bool containsUnexpandedParameterPack() const;
+
   /// \brief Retrieve the template argument as a type.
   QualType getAsType() const {
     if (Kind != Type)

Modified: cfe/trunk/include/clang/AST/TemplateName.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/TemplateName.h?rev=121724&r1=121723&r2=121724&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/TemplateName.h (original)
+++ cfe/trunk/include/clang/AST/TemplateName.h Mon Dec 13 16:49:22 2010
@@ -157,6 +157,10 @@
   /// \brief Determines whether this is a dependent template name.
   bool isDependent() const;
 
+  /// \brief Determines whether this template name contains an
+  /// unexpanded parameter pack (for C++0x variadic templates).
+  bool containsUnexpandedParameterPack() const;
+
   /// \brief Print the template name.
   ///
   /// \param OS the output stream to which the template name will be

Modified: cfe/trunk/include/clang/AST/Type.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Type.h?rev=121724&r1=121723&r2=121724&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Type.h (original)
+++ cfe/trunk/include/clang/AST/Type.h Mon Dec 13 16:49:22 2010
@@ -851,6 +851,10 @@
   
     /// \brief Whether this type is a variably-modified type (C99 6.7.5).
     unsigned VariablyModified : 1;
+
+    /// \brief Whether this type contains an unexpanded parameter pack
+    /// (for C++0x variadic templates).
+    unsigned ContainsUnexpandedParameterPack : 1;
   
     /// \brief Nonzero if the cache (i.e. the bitfields here starting
     /// with 'Cache') is valid.  If so, then this is a
@@ -882,7 +886,7 @@
       return CachedLocalOrUnnamed;
     }
   };
-  enum { NumTypeBits = 16 };
+  enum { NumTypeBits = 17 };
 
 protected:
   // These classes allow subclasses to somewhat cleanly pack bitfields
@@ -1010,12 +1014,14 @@
 protected:
   // silence VC++ warning C4355: 'this' : used in base member initializer list
   Type *this_() { return this; }
-  Type(TypeClass tc, QualType Canonical, bool Dependent, bool VariablyModified)
+  Type(TypeClass tc, QualType Canonical, bool Dependent, bool VariablyModified,
+       bool ContainsUnexpandedParameterPack)
     : ExtQualsTypeCommonBase(this), 
       CanonicalType(Canonical.isNull() ? QualType(this_(), 0) : Canonical) {
     TypeBits.TC = tc;
     TypeBits.Dependent = Dependent;
     TypeBits.VariablyModified = VariablyModified;
+    TypeBits.ContainsUnexpandedParameterPack = ContainsUnexpandedParameterPack;
     TypeBits.CacheValidAndVisibility = 0;
     TypeBits.CachedLocalOrUnnamed = false;
     TypeBits.CachedLinkage = NoLinkage;
@@ -1025,13 +1031,35 @@
 
   void setDependent(bool D = true) { TypeBits.Dependent = D; }
   void setVariablyModified(bool VM = true) { TypeBits.VariablyModified = VM; }
-  
+  void setContainsUnexpandedParameterPack(bool PP = true) {
+    TypeBits.ContainsUnexpandedParameterPack = PP;
+  }
+
 public:
   TypeClass getTypeClass() const { return static_cast<TypeClass>(TypeBits.TC); }
 
   /// \brief Whether this type comes from an AST file.
   bool isFromAST() const { return TypeBits.FromAST; }
 
+  /// \brief Whether this type is or contains an unexpanded parameter
+  /// pack, used to support C++0x variadic templates.
+  ///
+  /// A type that contains a parameter pack shall be expanded by the
+  /// ellipsis operator at some point. For example, the typedef in the
+  /// following example contains an unexpanded parameter pack 'T':
+  ///
+  /// \code
+  /// template<typename ...T>
+  /// struct X {
+  ///   typedef T* pointer_types; // ill-formed; T is a parameter pack.
+  /// };
+  /// \endcode
+  ///
+  /// Note that this routine does not specify which 
+  bool containsUnexpandedParameterPack() const { 
+    return TypeBits.ContainsUnexpandedParameterPack;
+  }
+
   bool isCanonicalUnqualified() const {
     return CanonicalType.getTypePtr() == this;
   }
@@ -1363,7 +1391,8 @@
 public:
   BuiltinType(Kind K)
     : Type(Builtin, QualType(), /*Dependent=*/(K == Dependent),
-           /*VariablyModified=*/false) {
+           /*VariablyModified=*/false,
+           /*Unexpanded paramter pack=*/false) {
     BuiltinTypeBits.Kind = K;
   }
 
@@ -1408,7 +1437,8 @@
   QualType ElementType;
   ComplexType(QualType Element, QualType CanonicalPtr) :
     Type(Complex, CanonicalPtr, Element->isDependentType(),
-         Element->isVariablyModifiedType()),
+         Element->isVariablyModifiedType(),
+         Element->containsUnexpandedParameterPack()),
     ElementType(Element) {
   }
   friend class ASTContext;  // ASTContext creates these.
@@ -1437,7 +1467,8 @@
 
   ParenType(QualType InnerType, QualType CanonType) :
     Type(Paren, CanonType, InnerType->isDependentType(),
-         InnerType->isVariablyModifiedType()),
+         InnerType->isVariablyModifiedType(),
+         InnerType->containsUnexpandedParameterPack()),
     Inner(InnerType) {
   }
   friend class ASTContext;  // ASTContext creates these.
@@ -1467,7 +1498,8 @@
 
   PointerType(QualType Pointee, QualType CanonicalPtr) :
     Type(Pointer, CanonicalPtr, Pointee->isDependentType(),
-         Pointee->isVariablyModifiedType()), 
+         Pointee->isVariablyModifiedType(),
+         Pointee->containsUnexpandedParameterPack()), 
     PointeeType(Pointee) {
   }
   friend class ASTContext;  // ASTContext creates these.
@@ -1498,7 +1530,8 @@
   QualType PointeeType;  // Block is some kind of pointer type
   BlockPointerType(QualType Pointee, QualType CanonicalCls) :
     Type(BlockPointer, CanonicalCls, Pointee->isDependentType(),
-         Pointee->isVariablyModifiedType()),
+         Pointee->isVariablyModifiedType(),
+         Pointee->containsUnexpandedParameterPack()),
     PointeeType(Pointee) {
   }
   friend class ASTContext;  // ASTContext creates these.
@@ -1533,7 +1566,10 @@
   ReferenceType(TypeClass tc, QualType Referencee, QualType CanonicalRef,
                 bool SpelledAsLValue) :
     Type(tc, CanonicalRef, Referencee->isDependentType(),
-         Referencee->isVariablyModifiedType()), PointeeType(Referencee) {
+         Referencee->isVariablyModifiedType(),
+         Referencee->containsUnexpandedParameterPack()), 
+    PointeeType(Referencee) 
+  {
     ReferenceTypeBits.SpelledAsLValue = SpelledAsLValue;
     ReferenceTypeBits.InnerRef = Referencee->isReferenceType();
   }
@@ -1614,7 +1650,9 @@
   MemberPointerType(QualType Pointee, const Type *Cls, QualType CanonicalPtr) :
     Type(MemberPointer, CanonicalPtr,
          Cls->isDependentType() || Pointee->isDependentType(),
-         Pointee->isVariablyModifiedType()),
+         Pointee->isVariablyModifiedType(),
+         (Cls->containsUnexpandedParameterPack() || 
+          Pointee->containsUnexpandedParameterPack())),
     PointeeType(Pointee), Class(Cls) {
   }
   friend class ASTContext; // ASTContext creates these.
@@ -1676,9 +1714,11 @@
   //       size is specified by a constant expression that is
   //       value-dependent,
   ArrayType(TypeClass tc, QualType et, QualType can,
-            ArraySizeModifier sm, unsigned tq)
+            ArraySizeModifier sm, unsigned tq,
+            bool ContainsUnexpandedParameterPack)
     : Type(tc, can, et->isDependentType() || tc == DependentSizedArray,
-           (tc == VariableArray || et->isVariablyModifiedType())),
+           (tc == VariableArray || et->isVariablyModifiedType()),
+           ContainsUnexpandedParameterPack),
       ElementType(et) {
     ArrayTypeBits.IndexTypeQuals = tq;
     ArrayTypeBits.SizeModifier = sm;
@@ -1716,12 +1756,14 @@
 
   ConstantArrayType(QualType et, QualType can, const llvm::APInt &size,
                     ArraySizeModifier sm, unsigned tq)
-    : ArrayType(ConstantArray, et, can, sm, tq),
+    : ArrayType(ConstantArray, et, can, sm, tq,
+                et->containsUnexpandedParameterPack()),
       Size(size) {}
 protected:
   ConstantArrayType(TypeClass tc, QualType et, QualType can,
                     const llvm::APInt &size, ArraySizeModifier sm, unsigned tq)
-    : ArrayType(tc, et, can, sm, tq), Size(size) {}
+    : ArrayType(tc, et, can, sm, tq, et->containsUnexpandedParameterPack()), 
+      Size(size) {}
   friend class ASTContext;  // ASTContext creates these.
 public:
   const llvm::APInt &getSize() const { return Size; }
@@ -1764,7 +1806,8 @@
 
   IncompleteArrayType(QualType et, QualType can,
                       ArraySizeModifier sm, unsigned tq)
-    : ArrayType(IncompleteArray, et, can, sm, tq) {}
+    : ArrayType(IncompleteArray, et, can, sm, tq, 
+                et->containsUnexpandedParameterPack()) {}
   friend class ASTContext;  // ASTContext creates these.
 public:
   bool isSugared() const { return false; }
@@ -1815,7 +1858,8 @@
   VariableArrayType(QualType et, QualType can, Expr *e,
                     ArraySizeModifier sm, unsigned tq,
                     SourceRange brackets)
-    : ArrayType(VariableArray, et, can, sm, tq),
+    : ArrayType(VariableArray, et, can, sm, tq, 
+                et->containsUnexpandedParameterPack()),
       SizeExpr((Stmt*) e), Brackets(brackets) {}
   friend class ASTContext;  // ASTContext creates these.
 
@@ -1872,9 +1916,8 @@
 
   DependentSizedArrayType(ASTContext &Context, QualType et, QualType can,
                           Expr *e, ArraySizeModifier sm, unsigned tq,
-                          SourceRange brackets)
-    : ArrayType(DependentSizedArray, et, can, sm, tq),
-      Context(Context), SizeExpr((Stmt*) e), Brackets(brackets) {}
+                          SourceRange brackets);
+
   friend class ASTContext;  // ASTContext creates these.
 
 public:
@@ -1924,11 +1967,8 @@
   SourceLocation loc;
 
   DependentSizedExtVectorType(ASTContext &Context, QualType ElementType,
-                              QualType can, Expr *SizeExpr, SourceLocation loc)
-    : Type(DependentSizedExtVector, can, /*Dependent=*/true,
-           ElementType->isVariablyModifiedType()),
-      Context(Context), SizeExpr(SizeExpr), ElementType(ElementType),
-      loc(loc) {}
+                              QualType can, Expr *SizeExpr, SourceLocation loc);
+
   friend class ASTContext;
 
 public:
@@ -1973,20 +2013,11 @@
   QualType ElementType;
 
   VectorType(QualType vecType, unsigned nElements, QualType canonType,
-             VectorKind vecKind) :
-    Type(Vector, canonType, vecType->isDependentType(),
-         vecType->isVariablyModifiedType()), ElementType(vecType) {
-    VectorTypeBits.VecKind = vecKind;
-    VectorTypeBits.NumElements = nElements;
-  }
+             VectorKind vecKind);
   
   VectorType(TypeClass tc, QualType vecType, unsigned nElements,
-             QualType canonType, VectorKind vecKind)
-    : Type(tc, canonType, vecType->isDependentType(),
-           vecType->isVariablyModifiedType()), ElementType(vecType) {
-    VectorTypeBits.VecKind = vecKind;
-    VectorTypeBits.NumElements = nElements;
-  }
+             QualType canonType, VectorKind vecKind);
+
   friend class ASTContext;  // ASTContext creates these.
   
 public:
@@ -2173,8 +2204,11 @@
 protected:
   FunctionType(TypeClass tc, QualType res, bool SubclassInfo,
                unsigned typeQuals, QualType Canonical, bool Dependent,
-               bool VariablyModified, ExtInfo Info)
-    : Type(tc, Canonical, Dependent, VariablyModified), ResultType(res) {
+               bool VariablyModified, bool ContainsUnexpandedParameterPack, 
+               ExtInfo Info)
+    : Type(tc, Canonical, Dependent, VariablyModified, 
+           ContainsUnexpandedParameterPack), 
+      ResultType(res) {
     FunctionTypeBits.ExtInfo = Info.Bits;
     FunctionTypeBits.SubclassInfo = SubclassInfo;
     FunctionTypeBits.TypeQuals = typeQuals;
@@ -2211,7 +2245,8 @@
   FunctionNoProtoType(QualType Result, QualType Canonical, ExtInfo Info)
     : FunctionType(FunctionNoProto, Result, false, 0, Canonical,
                    /*Dependent=*/false, Result->isVariablyModifiedType(), 
-                   Info) {}
+                   /*ContainsUnexpandedParameterPack=*/false, Info) {}
+
   friend class ASTContext;  // ASTContext creates these.
   
 public:
@@ -2241,6 +2276,17 @@
 /// exception specification, but this specification is not part of the canonical
 /// type.
 class FunctionProtoType : public FunctionType, public llvm::FoldingSetNode {
+  /// \brief Determine whether there are any argument types that
+  /// contain an unexpanded parameter pack.
+  static bool containsAnyUnexpandedParameterPack(const QualType *ArgArray, 
+                                                 unsigned numArgs) {
+    for (unsigned Idx = 0; Idx < numArgs; ++Idx)
+      if (ArgArray[Idx]->containsUnexpandedParameterPack())
+        return true;
+
+    return false;
+  }
+
   FunctionProtoType(QualType Result, const QualType *ArgArray, unsigned numArgs,
                     bool isVariadic, unsigned typeQuals, bool hasExs,
                     bool hasAnyExs, const QualType *ExArray,
@@ -2330,7 +2376,8 @@
   UnresolvedUsingTypenameDecl *Decl;
 
   UnresolvedUsingType(const UnresolvedUsingTypenameDecl *D)
-    : Type(UnresolvedUsing, QualType(), true, false),
+    : Type(UnresolvedUsing, QualType(), true, false, 
+           /*ContainsUnexpandedParameterPack=*/false),
       Decl(const_cast<UnresolvedUsingTypenameDecl*>(D)) {}
   friend class ASTContext; // ASTContext creates these.
 public:
@@ -2359,7 +2406,8 @@
   TypedefDecl *Decl;
 protected:
   TypedefType(TypeClass tc, const TypedefDecl *D, QualType can)
-    : Type(tc, can, can->isDependentType(), can->isVariablyModifiedType()),
+    : Type(tc, can, can->isDependentType(), can->isVariablyModifiedType(), 
+           /*ContainsUnexpandedParameterPack=*/false),
       Decl(const_cast<TypedefDecl*>(D)) {
     assert(!isa<TypedefType>(can) && "Invalid canonical type");
   }
@@ -2424,7 +2472,8 @@
 class TypeOfType : public Type {
   QualType TOType;
   TypeOfType(QualType T, QualType can)
-    : Type(TypeOf, can, T->isDependentType(), T->isVariablyModifiedType()), 
+    : Type(TypeOf, can, T->isDependentType(), T->isVariablyModifiedType(), 
+           T->containsUnexpandedParameterPack()), 
       TOType(T) {
     assert(!isa<TypedefType>(can) && "Invalid canonical type");
   }
@@ -2579,12 +2628,12 @@
   TemplateTypeParmType(unsigned D, unsigned I, bool PP, IdentifierInfo *N,
                        QualType Canon)
     : Type(TemplateTypeParm, Canon, /*Dependent=*/true,
-           /*VariablyModified=*/false),
+           /*VariablyModified=*/false, PP),
       Depth(D), ParameterPack(PP), Index(I), Name(N) { }
 
   TemplateTypeParmType(unsigned D, unsigned I, bool PP)
     : Type(TemplateTypeParm, QualType(this, 0), /*Dependent=*/true,
-           /*VariablyModified=*/false),
+           /*VariablyModified=*/false, PP),
       Depth(D), ParameterPack(PP), Index(I), Name(0) { }
 
   friend class ASTContext;  // ASTContext creates these
@@ -2630,7 +2679,8 @@
 
   SubstTemplateTypeParmType(const TemplateTypeParmType *Param, QualType Canon)
     : Type(SubstTemplateTypeParm, Canon, Canon->isDependentType(),
-           Canon->isVariablyModifiedType()),
+           Canon->isVariablyModifiedType(),
+           Canon->containsUnexpandedParameterPack()),
       Replaced(Param) { }
 
   friend class ASTContext;
@@ -2805,7 +2855,8 @@
                           // interdependencies.
   InjectedClassNameType(CXXRecordDecl *D, QualType TST)
     : Type(InjectedClassName, QualType(), /*Dependent=*/true,
-           /*VariablyModified=*/false),
+           /*VariablyModified=*/false, 
+           /*ContainsUnexpandedParameterPack=*/false),
       Decl(D), InjectedType(TST) {
     assert(isa<TemplateSpecializationType>(TST));
     assert(!TST.hasQualifiers());
@@ -2866,8 +2917,10 @@
 class TypeWithKeyword : public Type {
 protected:
   TypeWithKeyword(ElaboratedTypeKeyword Keyword, TypeClass tc,
-                  QualType Canonical, bool Dependent, bool VariablyModified)
-    : Type(tc, Canonical, Dependent, VariablyModified) {
+                  QualType Canonical, bool Dependent, bool VariablyModified, 
+                  bool ContainsUnexpandedParameterPack)
+  : Type(tc, Canonical, Dependent, VariablyModified, 
+         ContainsUnexpandedParameterPack) {
     TypeWithKeywordBits.Keyword = Keyword;
   }
 
@@ -2926,7 +2979,8 @@
                  QualType NamedType, QualType CanonType)
     : TypeWithKeyword(Keyword, Elaborated, CanonType,
                       NamedType->isDependentType(),
-                      NamedType->isVariablyModifiedType()),
+                      NamedType->isVariablyModifiedType(),
+                      NamedType->containsUnexpandedParameterPack()),
       NNS(NNS), NamedType(NamedType) {
     assert(!(Keyword == ETK_None && NNS == 0) &&
            "ElaboratedType cannot have elaborated type keyword "
@@ -2987,7 +3041,8 @@
   DependentNameType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS, 
                     const IdentifierInfo *Name, QualType CanonType)
     : TypeWithKeyword(Keyword, DependentName, CanonType, /*Dependent=*/true,
-                      /*VariablyModified=*/false),
+                      /*VariablyModified=*/false,
+                      NNS->containsUnexpandedParameterPack()),
       NNS(NNS), Name(Name) {
     assert(NNS->isDependent() &&
            "DependentNameType requires a dependent nested-name-specifier");
@@ -3148,7 +3203,7 @@
 
   enum Nonce_ObjCInterface { Nonce_ObjCInterface };
   ObjCObjectType(enum Nonce_ObjCInterface)
-    : Type(ObjCInterface, QualType(), false, false),
+        : Type(ObjCInterface, QualType(), false, false, false),
       BaseType(QualType(this_(), 0)) {
     ObjCObjectTypeBits.NumProtocols = 0;
   }
@@ -3305,7 +3360,7 @@
   QualType PointeeType;
 
   ObjCObjectPointerType(QualType Canonical, QualType Pointee)
-    : Type(ObjCObjectPointer, Canonical, false, false),
+    : Type(ObjCObjectPointer, Canonical, false, false, false),
       PointeeType(Pointee) {}
   friend class ASTContext;  // ASTContext creates these.
 

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=121724&r1=121723&r2=121724&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Mon Dec 13 16:49:22 2010
@@ -1821,6 +1821,10 @@
   "previous template %select{type|non-type|template}0 "
   "parameter%select{| pack}1 declared here">;
   
+def err_unexpanded_parameter_pack : Error<
+  "%select{expression|base type|declaration type|template argument}0 contains "
+  "unexpanded parameter pack">;
+
 def err_unexpected_typedef : Error<
   "unexpected type name %0: expected expression">;
 def err_unexpected_namespace : Error<

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=121724&r1=121723&r2=121724&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Mon Dec 13 16:49:22 2010
@@ -165,7 +165,9 @@
 
   LocInfoType(QualType ty, TypeSourceInfo *TInfo)
     : Type((TypeClass)LocInfo, ty, ty->isDependentType(), 
-           ty->isVariablyModifiedType()), DeclInfo(TInfo) {
+           ty->isVariablyModifiedType(),
+           ty->containsUnexpandedParameterPack()), 
+      DeclInfo(TInfo) {
     assert(getTypeClass() == (TypeClass)LocInfo && "LocInfo didn't fit in TC?");
   }
   friend class Sema;
@@ -3127,6 +3129,40 @@
                                   const TemplateArgument *Args,
                                   unsigned NumArgs);
 
+  /// \brief The context in which an unexpanded parameter pack is
+  /// being diagnosed.
+  ///
+  /// Note that the values of this enumeration line up with the first
+  /// argument to the \c err_unexpanded_parameter_pack diagnostic.
+  enum UnexpandedParameterPackContext {
+    UPPC_Expression = 0,
+    UPPC_BaseType,
+    UPPC_DeclarationType,
+    UPPC_TemplateArgument
+  };
+
+  /// \brief If the given type contains an unexpanded parameter pack,
+  /// diagnose the error.
+  ///
+  /// \param Loc The source location where a diagnostc should be emitted.
+  ///
+  /// \param T The type that is being checked for unexpanded parameter
+  /// packs.
+  ///
+  /// \returns true if an error ocurred, false otherwise.
+  bool DiagnoseUnexpandedParameterPack(SourceLocation Loc, TypeSourceInfo *T,
+                                       UnexpandedParameterPackContext UPPC);
+
+  /// \brief If the given expression contains an unexpanded parameter
+  /// pack, diagnose the error.
+  ///
+  /// \param E The expression that is being checked for unexpanded
+  /// parameter packs.
+  ///
+  /// \returns true if an error ocurred, false otherwise.
+  bool DiagnoseUnexpandedParameterPack(Expr *E,
+                       UnexpandedParameterPackContext UPPC = UPPC_Expression);
+
   /// \brief Describes the result of template argument deduction.
   ///
   /// The TemplateDeductionResult enumeration describes the result of

Modified: cfe/trunk/lib/AST/NestedNameSpecifier.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/NestedNameSpecifier.cpp?rev=121724&r1=121723&r2=121724&view=diff
==============================================================================
--- cfe/trunk/lib/AST/NestedNameSpecifier.cpp (original)
+++ cfe/trunk/lib/AST/NestedNameSpecifier.cpp Mon Dec 13 16:49:22 2010
@@ -113,6 +113,24 @@
   return false;
 }
 
+bool NestedNameSpecifier::containsUnexpandedParameterPack() const {
+  switch (getKind()) {
+  case Identifier:
+    return getPrefix() && getPrefix()->containsUnexpandedParameterPack();
+
+  case Namespace:
+  case Global:
+    return false;
+
+  case TypeSpec:
+  case TypeSpecWithTemplate:
+    return getAsType()->containsUnexpandedParameterPack();
+  }
+
+  // Necessary to suppress a GCC warning.
+  return false;  
+}
+
 /// \brief Print this nested name specifier to the given output
 /// stream.
 void

Modified: cfe/trunk/lib/AST/TemplateBase.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/TemplateBase.cpp?rev=121724&r1=121723&r2=121724&view=diff
==============================================================================
--- cfe/trunk/lib/AST/TemplateBase.cpp (original)
+++ cfe/trunk/lib/AST/TemplateBase.cpp Mon Dec 13 16:49:22 2010
@@ -26,6 +26,39 @@
 // TemplateArgument Implementation
 //===----------------------------------------------------------------------===//
 
+bool TemplateArgument::containsUnexpandedParameterPack() const {
+  switch (getKind()) {
+  case Null:
+  case Declaration:
+  case Integral:
+    break;
+
+  case Type:
+    if (getAsType()->containsUnexpandedParameterPack())
+      return true;
+    break;
+
+  case Template:
+    if (getAsTemplate().containsUnexpandedParameterPack())
+      return true;
+    break;
+        
+  case Expression:
+    if (getAsExpr()->containsUnexpandedParameterPack())
+      return true;
+    break;
+
+  case Pack:
+    for (pack_iterator P = pack_begin(), PEnd = pack_end(); P != PEnd; ++P)
+      if (P->containsUnexpandedParameterPack())
+        return true;
+
+    break;
+  }
+
+  return false;
+}
+
 void TemplateArgument::Profile(llvm::FoldingSetNodeID &ID,
                                ASTContext &Context) const {
   ID.AddInteger(Kind);

Modified: cfe/trunk/lib/AST/TemplateName.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/TemplateName.cpp?rev=121724&r1=121723&r2=121724&view=diff
==============================================================================
--- cfe/trunk/lib/AST/TemplateName.cpp (original)
+++ cfe/trunk/lib/AST/TemplateName.cpp Mon Dec 13 16:49:22 2010
@@ -60,6 +60,22 @@
   return true;
 }
 
+bool TemplateName::containsUnexpandedParameterPack() const {
+  if (TemplateDecl *Template = getAsTemplateDecl()) {
+    if (TemplateTemplateParmDecl *TTP 
+                                  = dyn_cast<TemplateTemplateParmDecl>(Template))
+      return TTP->isParameterPack();
+
+    return false;
+  }
+
+  if (DependentTemplateName *DTN = getAsDependentTemplateName())
+    return DTN->getQualifier() && 
+      DTN->getQualifier()->containsUnexpandedParameterPack();
+
+  return false;
+}
+
 void
 TemplateName::print(llvm::raw_ostream &OS, const PrintingPolicy &Policy,
                     bool SuppressNNS) const {

Modified: cfe/trunk/lib/AST/Type.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Type.cpp?rev=121724&r1=121723&r2=121724&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Type.cpp (original)
+++ cfe/trunk/lib/AST/Type.cpp Mon Dec 13 16:49:22 2010
@@ -63,6 +63,18 @@
   return Bits;
 }
 
+DependentSizedArrayType::DependentSizedArrayType(ASTContext &Context, 
+                                                 QualType et, QualType can,
+                                                 Expr *e, ArraySizeModifier sm,
+                                                 unsigned tq,
+                                                 SourceRange brackets)
+    : ArrayType(DependentSizedArray, et, can, sm, tq, 
+                (et->containsUnexpandedParameterPack() ||
+                 (e && e->containsUnexpandedParameterPack()))),
+      Context(Context), SizeExpr((Stmt*) e), Brackets(brackets) 
+{
+}
+
 void DependentSizedArrayType::Profile(llvm::FoldingSetNodeID &ID,
                                       ASTContext &Context,
                                       QualType ET,
@@ -75,6 +87,20 @@
   E->Profile(ID, Context, true);
 }
 
+DependentSizedExtVectorType::DependentSizedExtVectorType(ASTContext &Context, 
+                                                         QualType ElementType,
+                                                         QualType can, 
+                                                         Expr *SizeExpr, 
+                                                         SourceLocation loc)
+    : Type(DependentSizedExtVector, can, /*Dependent=*/true,
+           ElementType->isVariablyModifiedType(), 
+           (ElementType->containsUnexpandedParameterPack() ||
+            (SizeExpr && SizeExpr->containsUnexpandedParameterPack()))),
+      Context(Context), SizeExpr(SizeExpr), ElementType(ElementType),
+      loc(loc) 
+{
+}
+
 void
 DependentSizedExtVectorType::Profile(llvm::FoldingSetNodeID &ID,
                                      ASTContext &Context,
@@ -83,6 +109,28 @@
   SizeExpr->Profile(ID, Context, true);
 }
 
+VectorType::VectorType(QualType vecType, unsigned nElements, QualType canonType,
+                       VectorKind vecKind)
+  : Type(Vector, canonType, vecType->isDependentType(),
+         vecType->isVariablyModifiedType(),
+         vecType->containsUnexpandedParameterPack()),
+    ElementType(vecType) 
+{
+  VectorTypeBits.VecKind = vecKind;
+  VectorTypeBits.NumElements = nElements;
+}
+
+VectorType::VectorType(TypeClass tc, QualType vecType, unsigned nElements,
+                       QualType canonType, VectorKind vecKind)
+  : Type(tc, canonType, vecType->isDependentType(),
+         vecType->isVariablyModifiedType(),
+         vecType->containsUnexpandedParameterPack()), 
+    ElementType(vecType) 
+{
+  VectorTypeBits.VecKind = vecKind;
+  VectorTypeBits.NumElements = nElements;
+}
+
 /// getArrayElementTypeNoTypeQual - If this is an array type, return the
 /// element type of the array, potentially with type qualifiers missing.
 /// This method should never be used when type qualifiers are meaningful.
@@ -321,8 +369,9 @@
 ObjCObjectType::ObjCObjectType(QualType Canonical, QualType Base,
                                ObjCProtocolDecl * const *Protocols,
                                unsigned NumProtocols)
-  : Type(ObjCObject, Canonical, false, false),
-    BaseType(Base) {
+  : Type(ObjCObject, Canonical, false, false, false),
+    BaseType(Base) 
+{
   ObjCObjectTypeBits.NumProtocols = NumProtocols;
   assert(getNumProtocols() == NumProtocols &&
          "bitfield overflow in protocol count");
@@ -924,12 +973,17 @@
                          unsigned NumArgs, const TemplateArgument *Args,
                          QualType Canon)
   : TypeWithKeyword(Keyword, DependentTemplateSpecialization, Canon, true,
-                    false),
+                    /*VariablyModified=*/false,
+                    NNS->containsUnexpandedParameterPack()),
     NNS(NNS), Name(Name), NumArgs(NumArgs) {
   assert(NNS && NNS->isDependent() &&
          "DependentTemplateSpecializatonType requires dependent qualifier");
-  for (unsigned I = 0; I != NumArgs; ++I)
+  for (unsigned I = 0; I != NumArgs; ++I) {
+    if (Args[I].containsUnexpandedParameterPack())
+      setContainsUnexpandedParameterPack();
+
     new (&getArgBuffer()[I]) TemplateArgument(Args[I]);
+  }
 }
 
 void
@@ -1052,6 +1106,7 @@
   : FunctionType(FunctionProto, Result, isVariadic, typeQuals, Canonical,
                  Result->isDependentType(),
                  Result->isVariablyModifiedType(),
+                 Result->containsUnexpandedParameterPack(),
                  Info),
     NumArgs(numArgs), NumExceptions(numExs), HasExceptionSpec(hasExs),
     AnyExceptionSpec(hasAnyExs) 
@@ -1061,7 +1116,10 @@
   for (unsigned i = 0; i != numArgs; ++i) {
     if (ArgArray[i]->isDependentType())
       setDependent();
-    
+
+    if (ArgArray[i]->containsUnexpandedParameterPack())
+      setContainsUnexpandedParameterPack();
+
     ArgInfo[i] = ArgArray[i];
   }
   
@@ -1106,7 +1164,9 @@
 
 TypeOfExprType::TypeOfExprType(Expr *E, QualType can)
   : Type(TypeOfExpr, can, E->isTypeDependent(), 
-         E->getType()->isVariablyModifiedType()), TOExpr(E) {
+         E->getType()->isVariablyModifiedType(),
+         E->containsUnexpandedParameterPack()), 
+    TOExpr(E) {
 }
 
 QualType TypeOfExprType::desugar() const {
@@ -1120,7 +1180,9 @@
 
 DecltypeType::DecltypeType(Expr *E, QualType underlyingType, QualType can)
   : Type(Decltype, can, E->isTypeDependent(), 
-         E->getType()->isVariablyModifiedType()), E(E),
+         E->getType()->isVariablyModifiedType(), 
+         E->containsUnexpandedParameterPack()), 
+    E(E),
   UnderlyingType(underlyingType) {
 }
 
@@ -1133,7 +1195,8 @@
 }
 
 TagType::TagType(TypeClass TC, const TagDecl *D, QualType can)
-  : Type(TC, can, D->isDependentType(), /*VariablyModified=*/false),
+  : Type(TC, can, D->isDependentType(), /*VariablyModified=*/false, 
+         /*ContainsUnexpandedParameterPack=*/false),
     decl(const_cast<TagDecl*>(D)) {}
 
 static TagDecl *getInterestingTagDecl(TagDecl *decl) {
@@ -1233,7 +1296,8 @@
                            unsigned NumArgs, QualType Canon)
   : Type(TemplateSpecialization,
          Canon.isNull()? QualType(this, 0) : Canon,
-         T.isDependent(), false),
+         T.isDependent(), false,
+         T.containsUnexpandedParameterPack()),
     Template(T), NumArgs(NumArgs) 
 {
   assert((!Canon.isNull() ||
@@ -1249,7 +1313,9 @@
     if (Args[Arg].getKind() == TemplateArgument::Type &&
         Args[Arg].getAsType()->isVariablyModifiedType())
       setVariablyModified();
-    
+    if (Args[Arg].containsUnexpandedParameterPack())
+      setContainsUnexpandedParameterPack();
+
     new (&TemplateArgs[Arg]) TemplateArgument(Args[Arg]);
   }
 }

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=121724&r1=121723&r2=121724&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Mon Dec 13 16:49:22 2010
@@ -2414,6 +2414,10 @@
   TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S);
   QualType R = TInfo->getType();
 
+  if (DiagnoseUnexpandedParameterPack(D.getIdentifierLoc(), TInfo,
+                                      UPPC_DeclarationType))
+    D.setInvalidType();
+
   LookupResult Previous(*this, NameInfo, LookupOrdinaryName,
                         ForRedeclaration);
 

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=121724&r1=121723&r2=121724&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Mon Dec 13 16:49:22 2010
@@ -543,6 +543,11 @@
 
   TypeSourceInfo *TInfo = 0;
   GetTypeFromParser(basetype, &TInfo);
+
+  if (DiagnoseUnexpandedParameterPack(SpecifierRange.getBegin(), TInfo, 
+                                      UPPC_BaseType))
+    return true;
+
   if (CXXBaseSpecifier *BaseSpec = CheckBaseSpecifier(Class, SpecifierRange,
                                                       Virtual, Access, TInfo))
     return BaseSpec;

Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=121724&r1=121723&r2=121724&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Mon Dec 13 16:49:22 2010
@@ -3629,6 +3629,9 @@
 ExprResult Sema::ActOnFinishFullExpr(Expr *FullExpr) {
   if (!FullExpr) return ExprError();
 
+  if (DiagnoseUnexpandedParameterPack(FullExpr))
+    return ExprError();
+
   IgnoredValueConversions(FullExpr);
   CheckImplicitConversions(FullExpr);
   return MaybeCreateExprWithCleanups(FullExpr);

Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=121724&r1=121723&r2=121724&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Mon Dec 13 16:49:22 2010
@@ -5954,3 +5954,33 @@
   Result += ']';
   return Result;
 }
+
+bool Sema::DiagnoseUnexpandedParameterPack(SourceLocation Loc, 
+                                           TypeSourceInfo *T,
+                                         UnexpandedParameterPackContext UPPC) {
+  // C++0x [temp.variadic]p5:
+  //   An appearance of a name of a parameter pack that is not expanded is 
+  //   ill-formed.
+  if (!T->getType()->containsUnexpandedParameterPack())
+    return false;
+
+  // FIXME: Provide the names and locations of the unexpanded parameter packs.
+  Diag(Loc, diag::err_unexpanded_parameter_pack)
+    << (int)UPPC << T->getTypeLoc().getSourceRange();
+  return true;
+}
+
+bool Sema::DiagnoseUnexpandedParameterPack(Expr *E,
+                                           UnexpandedParameterPackContext UPPC) {
+  // C++0x [temp.variadic]p5:
+  //   An appearance of a name of a parameter pack that is not expanded is 
+  //   ill-formed.
+  if (!E->containsUnexpandedParameterPack())
+    return false;
+
+  // FIXME: Provide the names and locations of the unexpanded parameter packs.
+  Diag(E->getSourceRange().getBegin(), diag::err_unexpanded_parameter_pack)
+    << (int)UPPC << E->getSourceRange();
+  return true;
+}
+

Modified: cfe/trunk/lib/Serialization/ASTReaderStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderStmt.cpp?rev=121724&r1=121723&r2=121724&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReaderStmt.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReaderStmt.cpp Mon Dec 13 16:49:22 2010
@@ -59,7 +59,7 @@
 
     /// \brief The number of record fields required for the Expr class
     /// itself.
-    static const unsigned NumExprFields = NumStmtFields + 5;
+    static const unsigned NumExprFields = NumStmtFields + 6;
     
     /// \brief Read and initialize a ExplicitTemplateArgumentList structure.
     void ReadExplicitTemplateArgumentList(ExplicitTemplateArgumentList &ArgList,
@@ -399,6 +399,7 @@
   E->setType(Reader.GetType(Record[Idx++]));
   E->setTypeDependent(Record[Idx++]);
   E->setValueDependent(Record[Idx++]);
+  E->ExprBits.ContainsUnexpandedParameterPack = Record[Idx++];
   E->setValueKind(static_cast<ExprValueKind>(Record[Idx++]));
   E->setObjectKind(static_cast<ExprObjectKind>(Record[Idx++]));
   assert(Idx == NumExprFields && "Incorrect expression field count");

Modified: cfe/trunk/lib/Serialization/ASTWriterStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterStmt.cpp?rev=121724&r1=121723&r2=121724&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriterStmt.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriterStmt.cpp Mon Dec 13 16:49:22 2010
@@ -359,6 +359,7 @@
   Writer.AddTypeRef(E->getType(), Record);
   Record.push_back(E->isTypeDependent());
   Record.push_back(E->isValueDependent());
+  Record.push_back(E->containsUnexpandedParameterPack());
   Record.push_back(E->getValueKind());
   Record.push_back(E->getObjectKind());
 }

Added: cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/p5.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/p5.cpp?rev=121724&view=auto
==============================================================================
--- cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/p5.cpp (added)
+++ cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/p5.cpp Mon Dec 13 16:49:22 2010
@@ -0,0 +1,11 @@
+// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s
+
+
+// An appearance of a name of a parameter pack that is not expanded is
+// ill-formed.
+template<typename ... Types>
+struct TestPPName 
+  : public Types  // expected-error{{base type contains unexpanded parameter pack}}
+{
+  typedef Types *types_pointer; // expected-error{{declaration type contains unexpanded parameter pack}}
+};

Propchange: cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/p5.cpp
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/p5.cpp
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/p5.cpp
------------------------------------------------------------------------------
    svn:mime-type = text/plain





More information about the cfe-commits mailing list