diff options
-rw-r--r-- | include/clang/AST/DeclTemplate.h | 8 | ||||
-rw-r--r-- | include/clang/AST/Expr.h | 20 | ||||
-rw-r--r-- | include/clang/AST/NestedNameSpecifier.h | 4 | ||||
-rw-r--r-- | include/clang/AST/Stmt.h | 6 | ||||
-rw-r--r-- | include/clang/AST/TemplateBase.h | 4 | ||||
-rw-r--r-- | include/clang/AST/TemplateName.h | 4 | ||||
-rw-r--r-- | include/clang/AST/Type.h | 159 | ||||
-rw-r--r-- | include/clang/Basic/DiagnosticSemaKinds.td | 4 | ||||
-rw-r--r-- | include/clang/Sema/Sema.h | 38 | ||||
-rw-r--r-- | lib/AST/NestedNameSpecifier.cpp | 18 | ||||
-rw-r--r-- | lib/AST/TemplateBase.cpp | 33 | ||||
-rw-r--r-- | lib/AST/TemplateName.cpp | 16 | ||||
-rw-r--r-- | lib/AST/Type.cpp | 86 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 4 | ||||
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 5 | ||||
-rw-r--r-- | lib/Sema/SemaExprCXX.cpp | 3 | ||||
-rw-r--r-- | lib/Sema/SemaTemplate.cpp | 30 | ||||
-rw-r--r-- | lib/Serialization/ASTReaderStmt.cpp | 3 | ||||
-rw-r--r-- | lib/Serialization/ASTWriterStmt.cpp | 1 | ||||
-rw-r--r-- | test/CXX/temp/temp.decls/temp.variadic/p5.cpp | 11 |
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, |