aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/AST/DeclTemplate.h8
-rw-r--r--include/clang/AST/Expr.h20
-rw-r--r--include/clang/AST/NestedNameSpecifier.h4
-rw-r--r--include/clang/AST/Stmt.h6
-rw-r--r--include/clang/AST/TemplateBase.h4
-rw-r--r--include/clang/AST/TemplateName.h4
-rw-r--r--include/clang/AST/Type.h159
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td4
-rw-r--r--include/clang/Sema/Sema.h38
-rw-r--r--lib/AST/NestedNameSpecifier.cpp18
-rw-r--r--lib/AST/TemplateBase.cpp33
-rw-r--r--lib/AST/TemplateName.cpp16
-rw-r--r--lib/AST/Type.cpp86
-rw-r--r--lib/Sema/SemaDecl.cpp4
-rw-r--r--lib/Sema/SemaDeclCXX.cpp5
-rw-r--r--lib/Sema/SemaExprCXX.cpp3
-rw-r--r--lib/Sema/SemaTemplate.cpp30
-rw-r--r--lib/Serialization/ASTReaderStmt.cpp3
-rw-r--r--lib/Serialization/ASTWriterStmt.cpp1
-rw-r--r--test/CXX/temp/temp.decls/temp.variadic/p5.cpp11
20 files changed, 392 insertions, 65 deletions
diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h
index 6e79bad682..6628b3ffb0 100644
--- a/include/clang/AST/DeclTemplate.h
+++ b/include/clang/AST/DeclTemplate.h
@@ -1080,6 +1080,14 @@ public:
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 {
diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h
index c288ec6ea1..5039baa03a 100644
--- a/include/clang/AST/Expr.h
+++ b/include/clang/AST/Expr.h
@@ -62,6 +62,8 @@ protected:
ExprBits.ValueDependent = VD;
ExprBits.ValueKind = VK;
ExprBits.ObjectKind = OK;
+ // FIXME: Variadic templates.
+ ExprBits.ContainsUnexpandedParameterPack = false;
setType(T);
}
@@ -112,6 +114,24 @@ public:
/// \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.
diff --git a/include/clang/AST/NestedNameSpecifier.h b/include/clang/AST/NestedNameSpecifier.h
index 3b25f3bb40..41389da36b 100644
--- a/include/clang/AST/NestedNameSpecifier.h
+++ b/include/clang/AST/NestedNameSpecifier.h
@@ -172,6 +172,10 @@ public:
/// 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;
diff --git a/include/clang/AST/Stmt.h b/include/clang/AST/Stmt.h
index 421c59661b..124977d97f 100644
--- a/include/clang/AST/Stmt.h
+++ b/include/clang/AST/Stmt.h
@@ -143,14 +143,16 @@ protected:
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 @@ protected:
CastExprBitfields CastExprBits;
};
+ friend class ASTStmtReader;
+
public:
// Only allow allocation of Stmts using the allocator in ASTContext
// or by doing a placement new.
diff --git a/include/clang/AST/TemplateBase.h b/include/clang/AST/TemplateBase.h
index 3fe77405ae..e5057e547e 100644
--- a/include/clang/AST/TemplateBase.h
+++ b/include/clang/AST/TemplateBase.h
@@ -182,6 +182,10 @@ public:
/// \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)
diff --git a/include/clang/AST/TemplateName.h b/include/clang/AST/TemplateName.h
index ddfac71273..9b213a3b7a 100644
--- a/include/clang/AST/TemplateName.h
+++ b/include/clang/AST/TemplateName.h
@@ -157,6 +157,10 @@ public:
/// \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
diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h
index 81230b7a54..ba588ec1aa 100644
--- a/include/clang/AST/Type.h
+++ b/include/clang/AST/Type.h
@@ -851,6 +851,10 @@ private:
/// \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 @@ private:
return CachedLocalOrUnnamed;
}
};
- enum { NumTypeBits = 16 };
+ enum { NumTypeBits = 17 };
protected:
// These classes allow subclasses to somewhat cleanly pack bitfields
@@ -1010,12 +1014,14 @@ private:
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 @@ protected:
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:
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 @@ class ComplexType : public Type, public llvm::FoldingSetNode {
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 @@ class ParenType : public Type, public llvm::FoldingSetNode {
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 @@ class PointerType : public Type, public llvm::FoldingSetNode {
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 @@ class BlockPointerType : public Type, public llvm::FoldingSetNode {
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 @@ protected:
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 @@ class MemberPointerType : public Type, public llvm::FoldingSetNode {
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 @@ protected:
// 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 @@ class ConstantArrayType : public ArrayType {
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 @@ class IncompleteArrayType : public ArrayType {
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 @@ class VariableArrayType : public ArrayType {
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 @@ class DependentSizedArrayType : public ArrayType {
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 @@ class DependentSizedExtVectorType : public Type, public llvm::FoldingSetNode {
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 @@ protected:
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 @@ class FunctionType : public Type {
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 @@ class FunctionNoProtoType : public FunctionType, public llvm::FoldingSetNode {
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 @@ public:
/// 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 @@ class UnresolvedUsingType : public Type {
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 @@ class TypedefType : public Type {
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 @@ public:
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 @@ class TemplateTypeParmType : public Type, public llvm::FoldingSetNode {
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 @@ class SubstTemplateTypeParmType : public Type, public llvm::FoldingSetNode {
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 @@ class InjectedClassNameType : public Type {
// 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 @@ enum ElaboratedTypeKeyword {
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 @@ class ElaboratedType : public TypeWithKeyword, public llvm::FoldingSetNode {
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 @@ class DependentNameType : public TypeWithKeyword, public llvm::FoldingSetNode {
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 @@ protected:
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 @@ class ObjCObjectPointerType : public Type, public llvm::FoldingSetNode {
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.
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index 1b23aaaf63..3675ca953c 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -1821,6 +1821,10 @@ def note_template_parameter_pack_here : Note<
"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<
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h
index 4df4b7b535..dd8ae51e90 100644
--- a/include/clang/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -165,7 +165,9 @@ class LocInfoType : public Type {
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 @@ public:
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
diff --git a/lib/AST/NestedNameSpecifier.cpp b/lib/AST/NestedNameSpecifier.cpp
index 212def8565..10035acdcf 100644
--- a/lib/AST/NestedNameSpecifier.cpp
+++ b/lib/AST/NestedNameSpecifier.cpp
@@ -113,6 +113,24 @@ bool NestedNameSpecifier::isDependent() const {
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
diff --git a/lib/AST/TemplateBase.cpp b/lib/AST/TemplateBase.cpp
index 4a1ebb46c1..ef2deea8c8 100644
--- a/lib/AST/TemplateBase.cpp
+++ b/lib/AST/TemplateBase.cpp
@@ -26,6 +26,39 @@ using namespace clang;
// 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);
diff --git a/lib/AST/TemplateName.cpp b/lib/AST/TemplateName.cpp
index 439f4e81ad..73ff402b07 100644
--- a/lib/AST/TemplateName.cpp
+++ b/lib/AST/TemplateName.cpp
@@ -60,6 +60,22 @@ bool TemplateName::isDependent() const {
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 {
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index ed05a39305..127613ed32 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -63,6 +63,18 @@ unsigned ConstantArrayType::getMaxSizeBits(ASTContext &Context) {
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 @@ void DependentSizedArrayType::Profile(llvm::FoldingSetNodeID &ID,
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 @@ DependentSizedExtVectorType::Profile(llvm::FoldingSetNodeID &ID,
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 @@ const RecordType *Type::getAsUnionType() const {
ObjCObjectType::ObjCObjectType(QualType Canonical, QualType Base,
ObjCProtocolDecl * const *Protocols,