[cfe-commits] r122782 - in /cfe/trunk: include/clang/AST/DeclCXX.h include/clang/Sema/Sema.h lib/AST/ASTImporter.cpp lib/AST/DeclCXX.cpp lib/CodeGen/Mangle.cpp lib/Parse/ParseDeclCXX.cpp lib/Sema/SemaDeclCXX.cpp lib/Sema/SemaTemplateInstantiate.cpp lib/Sema/SemaTemplateVariadic.cpp lib/Serialization/ASTReader.cpp lib/Serialization/ASTWriter.cpp test/CXX/temp/temp.decls/temp.variadic/p4.cpp
Douglas Gregor
dgregor at apple.com
Mon Jan 3 14:36:03 PST 2011
Author: dgregor
Date: Mon Jan 3 16:36:02 2011
New Revision: 122782
URL: http://llvm.org/viewvc/llvm-project?rev=122782&view=rev
Log:
Implement pack expansions whose pattern is a base-specifier.
Modified:
cfe/trunk/include/clang/AST/DeclCXX.h
cfe/trunk/include/clang/Sema/Sema.h
cfe/trunk/lib/AST/ASTImporter.cpp
cfe/trunk/lib/AST/DeclCXX.cpp
cfe/trunk/lib/CodeGen/Mangle.cpp
cfe/trunk/lib/Parse/ParseDeclCXX.cpp
cfe/trunk/lib/Sema/SemaDeclCXX.cpp
cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp
cfe/trunk/lib/Serialization/ASTReader.cpp
cfe/trunk/lib/Serialization/ASTWriter.cpp
cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/p4.cpp
Modified: cfe/trunk/include/clang/AST/DeclCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclCXX.h?rev=122782&r1=122781&r2=122782&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclCXX.h (original)
+++ cfe/trunk/include/clang/AST/DeclCXX.h Mon Jan 3 16:36:02 2011
@@ -168,6 +168,10 @@
/// specifier (if present).
SourceRange Range;
+ /// \brief The source location of the ellipsis, if this is a pack
+ /// expansion.
+ SourceLocation EllipsisLoc;
+
/// Virtual - Whether this is a virtual base class or not.
bool Virtual : 1;
@@ -192,8 +196,9 @@
CXXBaseSpecifier() { }
CXXBaseSpecifier(SourceRange R, bool V, bool BC, AccessSpecifier A,
- TypeSourceInfo *TInfo)
- : Range(R), Virtual(V), BaseOfClass(BC), Access(A), BaseTypeInfo(TInfo) { }
+ TypeSourceInfo *TInfo, SourceLocation EllipsisLoc)
+ : Range(R), EllipsisLoc(EllipsisLoc), Virtual(V), BaseOfClass(BC),
+ Access(A), BaseTypeInfo(TInfo) { }
/// getSourceRange - Retrieves the source range that contains the
/// entire base specifier.
@@ -207,6 +212,14 @@
/// with the 'class' keyword (vs. one declared with the 'struct' keyword).
bool isBaseOfClass() const { return BaseOfClass; }
+ /// \brief Determine whether this base specifier is a pack expansion.
+ bool isPackExpansion() const { return EllipsisLoc.isValid(); }
+
+ /// \brief For a pack expansion, determine the location of the ellipsis.
+ SourceLocation getEllipsisLoc() const {
+ return EllipsisLoc;
+ }
+
/// getAccessSpecifier - Returns the access specifier for this base
/// specifier. This is the actual base specifier as used for
/// semantic analysis, so the result can never be AS_none. To
Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=122782&r1=122781&r2=122782&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Mon Jan 3 16:36:02 2011
@@ -127,6 +127,7 @@
class TemplateTemplateParmDecl;
class Token;
class TypedefDecl;
+ class TypeLoc;
class UnqualifiedId;
class UnresolvedLookupExpr;
class UnresolvedMemberExpr;
@@ -2653,13 +2654,15 @@
CXXBaseSpecifier *CheckBaseSpecifier(CXXRecordDecl *Class,
SourceRange SpecifierRange,
bool Virtual, AccessSpecifier Access,
- TypeSourceInfo *TInfo);
+ TypeSourceInfo *TInfo,
+ SourceLocation EllipsisLoc);
BaseResult ActOnBaseSpecifier(Decl *classdecl,
SourceRange SpecifierRange,
bool Virtual, AccessSpecifier Access,
- ParsedType basetype, SourceLocation
- BaseLoc);
+ ParsedType basetype,
+ SourceLocation BaseLoc,
+ SourceLocation EllipsisLoc);
bool AttachBaseSpecifiers(CXXRecordDecl *Class, CXXBaseSpecifier **Bases,
unsigned NumBases);
@@ -3273,11 +3276,19 @@
/// \brief Collect the set of unexpanded parameter packs within the given
/// type.
///
- /// \param Arg The template argument that will be traversed to find
+ /// \param T The type that will be traversed to find
/// unexpanded parameter packs.
void collectUnexpandedParameterPacks(QualType T,
llvm::SmallVectorImpl<UnexpandedParameterPack> &Unexpanded);
+ /// \brief Collect the set of unexpanded parameter packs within the given
+ /// type.
+ ///
+ /// \param TL The type that will be traversed to find
+ /// unexpanded parameter packs.
+ void collectUnexpandedParameterPacks(TypeLoc TL,
+ llvm::SmallVectorImpl<UnexpandedParameterPack> &Unexpanded);
+
/// \brief Invoked when parsing a template argument followed by an
/// ellipsis, which creates a pack expansion.
///
Modified: cfe/trunk/lib/AST/ASTImporter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTImporter.cpp?rev=122782&r1=122781&r2=122782&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTImporter.cpp (original)
+++ cfe/trunk/lib/AST/ASTImporter.cpp Mon Jan 3 16:36:02 2011
@@ -1709,6 +1709,10 @@
QualType T = Importer.Import(Base1->getType());
if (T.isNull())
return true;
+
+ SourceLocation EllipsisLoc;
+ if (Base1->isPackExpansion())
+ EllipsisLoc = Importer.Import(Base1->getEllipsisLoc());
Bases.push_back(
new (Importer.getToContext())
@@ -1716,7 +1720,8 @@
Base1->isVirtual(),
Base1->isBaseOfClass(),
Base1->getAccessSpecifierAsWritten(),
- Importer.Import(Base1->getTypeSourceInfo())));
+ Importer.Import(Base1->getTypeSourceInfo()),
+ EllipsisLoc));
}
if (!Bases.empty())
ToCXX->setBases(Bases.data(), Bases.size());
Modified: cfe/trunk/lib/AST/DeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclCXX.cpp?rev=122782&r1=122781&r2=122782&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclCXX.cpp (original)
+++ cfe/trunk/lib/AST/DeclCXX.cpp Mon Jan 3 16:36:02 2011
@@ -196,7 +196,8 @@
data().getVBases()[I] =
CXXBaseSpecifier(VBaseClassDecl->getSourceRange(), true,
VBaseClassDecl->getTagKind() == TTK_Class,
- VBases[I]->getAccessSpecifier(), VBaseTypeInfo);
+ VBases[I]->getAccessSpecifier(), VBaseTypeInfo,
+ SourceLocation());
}
}
Modified: cfe/trunk/lib/CodeGen/Mangle.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/Mangle.cpp?rev=122782&r1=122781&r2=122782&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/Mangle.cpp (original)
+++ cfe/trunk/lib/CodeGen/Mangle.cpp Mon Jan 3 16:36:02 2011
@@ -2137,8 +2137,9 @@
// ::= I <template-arg>* E # argument pack
// ::= sp <expression> # pack expansion of (C++0x)
switch (A.getKind()) {
- default:
- assert(0 && "Unknown template argument kind!");
+ case TemplateArgument::Null:
+ llvm_unreachable("Cannot mangle NULL template argument");
+
case TemplateArgument::Type:
mangleType(A.getAsType());
break;
@@ -2187,6 +2188,16 @@
break;
}
+
+ case TemplateArgument::Pack: {
+ // Note: proposal by Mike Herrick on 12/20/10
+ Out << 'J';
+ for (TemplateArgument::pack_iterator PA = A.pack_begin(),
+ PAEnd = A.pack_end();
+ PA != PAEnd; ++PA)
+ mangleTemplateArg(P, *PA);
+ Out << 'E';
+ }
}
}
Modified: cfe/trunk/lib/Parse/ParseDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=122782&r1=122781&r2=122782&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Mon Jan 3 16:36:02 2011
@@ -1196,13 +1196,20 @@
if (BaseType.isInvalid())
return true;
+ // Parse the optional ellipsis (for a pack expansion). The ellipsis is
+ // actually part of the base-specifier-list grammar productions, but we
+ // parse it here for convenience.
+ SourceLocation EllipsisLoc;
+ if (Tok.is(tok::ellipsis))
+ EllipsisLoc = ConsumeToken();
+
// Find the complete source range for the base-specifier.
SourceRange Range(StartLoc, EndLocation);
// Notify semantic analysis that we have parsed a complete
// base-specifier.
return Actions.ActOnBaseSpecifier(ClassDecl, Range, IsVirtual, Access,
- BaseType.get(), BaseLoc);
+ BaseType.get(), BaseLoc, EllipsisLoc);
}
/// getAccessSpecifierIfPresent - Determine whether the next token is
Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=122782&r1=122781&r2=122782&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Mon Jan 3 16:36:02 2011
@@ -464,7 +464,8 @@
Sema::CheckBaseSpecifier(CXXRecordDecl *Class,
SourceRange SpecifierRange,
bool Virtual, AccessSpecifier Access,
- TypeSourceInfo *TInfo) {
+ TypeSourceInfo *TInfo,
+ SourceLocation EllipsisLoc) {
QualType BaseType = TInfo->getType();
// C++ [class.union]p1:
@@ -475,10 +476,17 @@
return 0;
}
+ if (EllipsisLoc.isValid() &&
+ !TInfo->getType()->containsUnexpandedParameterPack()) {
+ Diag(EllipsisLoc, diag::err_pack_expansion_without_parameter_packs)
+ << TInfo->getTypeLoc().getSourceRange();
+ EllipsisLoc = SourceLocation();
+ }
+
if (BaseType->isDependentType())
return new (Context) CXXBaseSpecifier(SpecifierRange, Virtual,
Class->getTagKind() == TTK_Class,
- Access, TInfo);
+ Access, TInfo, EllipsisLoc);
SourceLocation BaseLoc = TInfo->getTypeLoc().getBeginLoc();
@@ -527,7 +535,7 @@
// Create the base specifier.
return new (Context) CXXBaseSpecifier(SpecifierRange, Virtual,
Class->getTagKind() == TTK_Class,
- Access, TInfo);
+ Access, TInfo, EllipsisLoc);
}
/// ActOnBaseSpecifier - Parsed a base specifier. A base specifier is
@@ -538,7 +546,8 @@
BaseResult
Sema::ActOnBaseSpecifier(Decl *classdecl, SourceRange SpecifierRange,
bool Virtual, AccessSpecifier Access,
- ParsedType basetype, SourceLocation BaseLoc) {
+ ParsedType basetype, SourceLocation BaseLoc,
+ SourceLocation EllipsisLoc) {
if (!classdecl)
return true;
@@ -550,12 +559,14 @@
TypeSourceInfo *TInfo = 0;
GetTypeFromParser(basetype, &TInfo);
- if (DiagnoseUnexpandedParameterPack(SpecifierRange.getBegin(), TInfo,
+ if (EllipsisLoc.isInvalid() &&
+ DiagnoseUnexpandedParameterPack(SpecifierRange.getBegin(), TInfo,
UPPC_BaseType))
return true;
-
+
if (CXXBaseSpecifier *BaseSpec = CheckBaseSpecifier(Class, SpecifierRange,
- Virtual, Access, TInfo))
+ Virtual, Access, TInfo,
+ EllipsisLoc))
return BaseSpec;
return true;
Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp?rev=122782&r1=122781&r2=122782&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Mon Jan 3 16:36:02 2011
@@ -1155,6 +1155,58 @@
continue;
}
+ SourceLocation EllipsisLoc;
+ if (Base->isPackExpansion()) {
+ // This is a pack expansion. See whether we should expand it now, or
+ // wait until later.
+ llvm::SmallVector<UnexpandedParameterPack, 2> Unexpanded;
+ collectUnexpandedParameterPacks(Base->getTypeSourceInfo()->getTypeLoc(),
+ Unexpanded);
+ bool ShouldExpand = false;
+ unsigned NumExpansions = 0;
+ if (CheckParameterPacksForExpansion(Base->getEllipsisLoc(),
+ Base->getSourceRange(),
+ Unexpanded.data(), Unexpanded.size(),
+ TemplateArgs, ShouldExpand,
+ NumExpansions)) {
+ continue;
+ Invalid = true;
+ }
+
+ // If we should expand this pack expansion now, do so.
+ if (ShouldExpand) {
+ for (unsigned I = 0; I != NumExpansions; ++I) {
+ Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(*this, I);
+
+ TypeSourceInfo *BaseTypeLoc = SubstType(Base->getTypeSourceInfo(),
+ TemplateArgs,
+ Base->getSourceRange().getBegin(),
+ DeclarationName());
+ if (!BaseTypeLoc) {
+ Invalid = true;
+ continue;
+ }
+
+ if (CXXBaseSpecifier *InstantiatedBase
+ = CheckBaseSpecifier(Instantiation,
+ Base->getSourceRange(),
+ Base->isVirtual(),
+ Base->getAccessSpecifierAsWritten(),
+ BaseTypeLoc,
+ SourceLocation()))
+ InstantiatedBases.push_back(InstantiatedBase);
+ else
+ Invalid = true;
+ }
+
+ continue;
+ }
+
+ // The resulting base specifier will (still) be a pack expansion.
+ EllipsisLoc = Base->getEllipsisLoc();
+ }
+
+ Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(*this, -1);
TypeSourceInfo *BaseTypeLoc = SubstType(Base->getTypeSourceInfo(),
TemplateArgs,
Base->getSourceRange().getBegin(),
@@ -1169,7 +1221,8 @@
Base->getSourceRange(),
Base->isVirtual(),
Base->getAccessSpecifierAsWritten(),
- BaseTypeLoc))
+ BaseTypeLoc,
+ EllipsisLoc))
InstantiatedBases.push_back(InstantiatedBase);
else
Invalid = true;
Modified: cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp?rev=122782&r1=122781&r2=122782&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp Mon Jan 3 16:36:02 2011
@@ -294,6 +294,11 @@
CollectUnexpandedParameterPacksVisitor(Unexpanded).TraverseType(T);
}
+void Sema::collectUnexpandedParameterPacks(TypeLoc TL,
+ llvm::SmallVectorImpl<UnexpandedParameterPack> &Unexpanded) {
+ CollectUnexpandedParameterPacksVisitor(Unexpanded).TraverseTypeLoc(TL);
+}
+
ParsedTemplateArgument
Sema::ActOnPackExpansion(const ParsedTemplateArgument &Arg,
SourceLocation EllipsisLoc) {
Modified: cfe/trunk/lib/Serialization/ASTReader.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReader.cpp?rev=122782&r1=122781&r2=122782&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReader.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReader.cpp Mon Jan 3 16:36:02 2011
@@ -4292,7 +4292,9 @@
AccessSpecifier AS = static_cast<AccessSpecifier>(Record[Idx++]);
TypeSourceInfo *TInfo = GetTypeSourceInfo(F, Record, Idx);
SourceRange Range = ReadSourceRange(F, Record, Idx);
- return CXXBaseSpecifier(Range, isVirtual, isBaseOfClass, AS, TInfo);
+ SourceLocation EllipsisLoc = ReadSourceLocation(F, Record, Idx);
+ return CXXBaseSpecifier(Range, isVirtual, isBaseOfClass, AS, TInfo,
+ EllipsisLoc);
}
std::pair<CXXBaseOrMemberInitializer **, unsigned>
Modified: cfe/trunk/lib/Serialization/ASTWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=122782&r1=122781&r2=122782&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriter.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriter.cpp Mon Jan 3 16:36:02 2011
@@ -3231,6 +3231,9 @@
Record.push_back(Base.getAccessSpecifierAsWritten());
AddTypeSourceInfo(Base.getTypeSourceInfo(), Record);
AddSourceRange(Base.getSourceRange(), Record);
+ AddSourceLocation(Base.isPackExpansion()? Base.getEllipsisLoc()
+ : SourceLocation(),
+ Record);
}
void ASTWriter::FlushCXXBaseSpecifiers() {
Modified: cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/p4.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/p4.cpp?rev=122782&r1=122781&r2=122782&view=diff
==============================================================================
--- cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/p4.cpp (original)
+++ cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/p4.cpp Mon Jan 3 16:36:02 2011
@@ -34,6 +34,24 @@
template void initializer_list_expansion<1, 2, 3, 4, 5>();
template void initializer_list_expansion<1, 2, 3, 4, 5, 6>(); // expected-note{{in instantiation of function template specialization 'initializer_list_expansion<1, 2, 3, 4, 5, 6>' requested here}}
+// In a base-specifier-list (Clause 10); the pattern is a base-specifier.
+template<typename ...Mixins>
+struct HasMixins : public Mixins... { };
+
+struct A { };
+struct B { };
+struct C { };
+struct D { };
+
+A *checkA = new HasMixins<A, B, C, D>;
+B *checkB = new HasMixins<A, B, C, D>;
+D *checkD = new HasMixins<A, B, C, D>;
+C *checkC = new HasMixins<A, B, D>; // expected-error{{cannot initialize a variable of type 'C *' with an rvalue of type 'HasMixins<A, B, D> *'}}
+HasMixins<> *checkNone = new HasMixins<>;
+
+template<typename Mixins>
+struct BrokenMixins : public Mixins... { }; // expected-error{{pack expansion does not contain any unexpanded parameter packs}}
+
// In a template-argument-list (14.3); the pattern is a template-argument.
template<typename ...Types>
struct tuple_of_refs {
More information about the cfe-commits
mailing list