/// \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
return CachedLocalOrUnnamed;
}
};
- enum { NumTypeBits = 16 };
+ enum { NumTypeBits = 17 };
protected:
// These classes allow subclasses to somewhat cleanly pack bitfields
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;
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;
}
public:
BuiltinType(Kind K)
: Type(Builtin, QualType(), /*Dependent=*/(K == Dependent),
- /*VariablyModified=*/false) {
+ /*VariablyModified=*/false,
+ /*Unexpanded paramter pack=*/false) {
BuiltinTypeBits.Kind = K;
}
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.
ParenType(QualType InnerType, QualType CanonType) :
Type(Paren, CanonType, InnerType->isDependentType(),
- InnerType->isVariablyModifiedType()),
+ InnerType->isVariablyModifiedType(),
+ InnerType->containsUnexpandedParameterPack()),
Inner(InnerType) {
}
friend class ASTContext; // ASTContext creates these.
PointerType(QualType Pointee, QualType CanonicalPtr) :
Type(Pointer, CanonicalPtr, Pointee->isDependentType(),
- Pointee->isVariablyModifiedType()),
+ Pointee->isVariablyModifiedType(),
+ Pointee->containsUnexpandedParameterPack()),
PointeeType(Pointee) {
}
friend class ASTContext; // ASTContext creates these.
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.
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();
}
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.
// 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;
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; }
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; }
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.
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:
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:
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:
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;
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:
/// 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,
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:
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");
}
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");
}
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
SubstTemplateTypeParmType(const TemplateTypeParmType *Param, QualType Canon)
: Type(SubstTemplateTypeParm, Canon, Canon->isDependentType(),
- Canon->isVariablyModifiedType()),
+ Canon->isVariablyModifiedType(),
+ Canon->containsUnexpandedParameterPack()),
Replaced(Param) { }
friend class ASTContext;
// 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());
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;
}
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 "
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");
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;
}
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.
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,
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,
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.
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");
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
: FunctionType(FunctionProto, Result, isVariadic, typeQuals, Canonical,
Result->isDependentType(),
Result->isVariablyModifiedType(),
+ Result->containsUnexpandedParameterPack(),
Info),
NumArgs(numArgs), NumExceptions(numExs), HasExceptionSpec(hasExs),
AnyExceptionSpec(hasAnyExs)
for (unsigned i = 0; i != numArgs; ++i) {
if (ArgArray[i]->isDependentType())
setDependent();
-
+
+ if (ArgArray[i]->containsUnexpandedParameterPack())
+ setContainsUnexpandedParameterPack();
+
ArgInfo[i] = ArgArray[i];
}
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 {
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) {
}
}
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) {
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() ||
if (Args[Arg].getKind() == TemplateArgument::Type &&
Args[Arg].getAsType()->isVariablyModifiedType())
setVariablyModified();
-
+ if (Args[Arg].containsUnexpandedParameterPack())
+ setContainsUnexpandedParameterPack();
+
new (&TemplateArgs[Arg]) TemplateArgument(Args[Arg]);
}
}