diff options
Diffstat (limited to 'lib')
-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 |
10 files changed, 188 insertions, 11 deletions
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, 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 @@ DependentTemplateSpecializationType::DependentTemplateSpecializationType( 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 @@ FunctionProtoType::FunctionProtoType(QualType Result, const QualType *ArgArray, : 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 @@ FunctionProtoType::FunctionProtoType(QualType Result, const QualType *ArgArray, 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 @@ QualType TypedefType::desugar() const { 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 @@ void DependentTypeOfExprType::Profile(llvm::FoldingSetNodeID &ID, 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 @@ void DependentDecltypeType::Profile(llvm::FoldingSetNodeID &ID, } 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 @@ TemplateSpecializationType(TemplateName T, 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 @@ TemplateSpecializationType(TemplateName T, if (Args[Arg].getKind() == TemplateArgument::Type && Args[Arg].getAsType()->isVariablyModifiedType()) setVariablyModified(); - + if (Args[Arg].containsUnexpandedParameterPack()) + setContainsUnexpandedParameterPack(); + new (&TemplateArgs[Arg]) TemplateArgument(Args[Arg]); } } diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index dbf9b6dad4..403838176c 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -2414,6 +2414,10 @@ Decl *Sema::HandleDeclarator(Scope *S, Declarator &D, TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S); QualType R = TInfo->getType(); + if (DiagnoseUnexpandedParameterPack(D.getIdentifierLoc(), TInfo, + UPPC_DeclarationType)) + D.setInvalidType(); + LookupResult Previous(*this, NameInfo, LookupOrdinaryName, ForRedeclaration); diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 4fc770eecf..3cfde26d24 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -543,6 +543,11 @@ Sema::ActOnBaseSpecifier(Decl *classdecl, SourceRange SpecifierRange, 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; diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 92441918d1..41a342942c 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -3629,6 +3629,9 @@ void Sema::IgnoredValueConversions(Expr *&E) { ExprResult Sema::ActOnFinishFullExpr(Expr *FullExpr) { if (!FullExpr) return ExprError(); + if (DiagnoseUnexpandedParameterPack(FullExpr)) + return ExprError(); + IgnoredValueConversions(FullExpr); CheckImplicitConversions(FullExpr); return MaybeCreateExprWithCleanups(FullExpr); diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 53a02a9886..141c41618d 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -5954,3 +5954,33 @@ Sema::getTemplateArgumentBindingsText(const TemplateParameterList *Params, 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; +} + diff --git a/lib/Serialization/ASTReaderStmt.cpp b/lib/Serialization/ASTReaderStmt.cpp index 353477d963..aa669b34b3 100644 --- a/lib/Serialization/ASTReaderStmt.cpp +++ b/lib/Serialization/ASTReaderStmt.cpp @@ -59,7 +59,7 @@ namespace clang { /// \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 @@ void ASTStmtReader::VisitExpr(Expr *E) { 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"); diff --git a/lib/Serialization/ASTWriterStmt.cpp b/lib/Serialization/ASTWriterStmt.cpp index 35b096e655..89c293fe6c 100644 --- a/lib/Serialization/ASTWriterStmt.cpp +++ b/lib/Serialization/ASTWriterStmt.cpp @@ -359,6 +359,7 @@ void ASTStmtWriter::VisitExpr(Expr *E) { 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()); } |