aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-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
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());
}