зеркало из https://github.com/microsoft/clang-1.git
Implement pack expansions whose pattern is a base-specifier.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@122782 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
0fe5397b26
Коммит
f90b27ad07
|
@ -168,6 +168,10 @@ class CXXBaseSpecifier {
|
|||
/// 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 @@ public:
|
|||
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 @@ public:
|
|||
/// 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
|
||||
|
|
|
@ -127,6 +127,7 @@ namespace clang {
|
|||
class TemplateTemplateParmDecl;
|
||||
class Token;
|
||||
class TypedefDecl;
|
||||
class TypeLoc;
|
||||
class UnqualifiedId;
|
||||
class UnresolvedLookupExpr;
|
||||
class UnresolvedMemberExpr;
|
||||
|
@ -2653,13 +2654,15 @@ public:
|
|||
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 @@ public:
|
|||
/// \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.
|
||||
///
|
||||
|
|
|
@ -1709,6 +1709,10 @@ bool ASTNodeImporter::ImportDefinition(RecordDecl *From, RecordDecl *To) {
|
|||
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 @@ bool ASTNodeImporter::ImportDefinition(RecordDecl *From, RecordDecl *To) {
|
|||
Base1->isVirtual(),
|
||||
Base1->isBaseOfClass(),
|
||||
Base1->getAccessSpecifierAsWritten(),
|
||||
Importer.Import(Base1->getTypeSourceInfo())));
|
||||
Importer.Import(Base1->getTypeSourceInfo()),
|
||||
EllipsisLoc));
|
||||
}
|
||||
if (!Bases.empty())
|
||||
ToCXX->setBases(Bases.data(), Bases.size());
|
||||
|
|
|
@ -196,7 +196,8 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases,
|
|||
data().getVBases()[I] =
|
||||
CXXBaseSpecifier(VBaseClassDecl->getSourceRange(), true,
|
||||
VBaseClassDecl->getTagKind() == TTK_Class,
|
||||
VBases[I]->getAccessSpecifier(), VBaseTypeInfo);
|
||||
VBases[I]->getAccessSpecifier(), VBaseTypeInfo,
|
||||
SourceLocation());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2137,8 +2137,9 @@ void CXXNameMangler::mangleTemplateArg(const NamedDecl *P,
|
|||
// ::= 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 @@ void CXXNameMangler::mangleTemplateArg(const NamedDecl *P,
|
|||
|
||||
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';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1196,13 +1196,20 @@ Parser::BaseResult Parser::ParseBaseSpecifier(Decl *ClassDecl) {
|
|||
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
|
||||
|
|
|
@ -464,7 +464,8 @@ CXXBaseSpecifier *
|
|||
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 @@ Sema::CheckBaseSpecifier(CXXRecordDecl *Class,
|
|||
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 @@ Sema::CheckBaseSpecifier(CXXRecordDecl *Class,
|
|||
// 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 @@ Sema::CheckBaseSpecifier(CXXRecordDecl *Class,
|
|||
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 @@ Sema::ActOnBaseSpecifier(Decl *classdecl, SourceRange SpecifierRange,
|
|||
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;
|
||||
|
|
|
@ -1155,6 +1155,58 @@ Sema::SubstBaseSpecifiers(CXXRecordDecl *Instantiation,
|
|||
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 @@ Sema::SubstBaseSpecifiers(CXXRecordDecl *Instantiation,
|
|||
Base->getSourceRange(),
|
||||
Base->isVirtual(),
|
||||
Base->getAccessSpecifierAsWritten(),
|
||||
BaseTypeLoc))
|
||||
BaseTypeLoc,
|
||||
EllipsisLoc))
|
||||
InstantiatedBases.push_back(InstantiatedBase);
|
||||
else
|
||||
Invalid = true;
|
||||
|
|
|
@ -294,6 +294,11 @@ void Sema::collectUnexpandedParameterPacks(QualType T,
|
|||
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) {
|
||||
|
|
|
@ -4292,7 +4292,9 @@ ASTReader::ReadCXXBaseSpecifier(PerFileData &F,
|
|||
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>
|
||||
|
|
|
@ -3231,6 +3231,9 @@ void ASTWriter::AddCXXBaseSpecifier(const CXXBaseSpecifier &Base,
|
|||
Record.push_back(Base.getAccessSpecifierAsWritten());
|
||||
AddTypeSourceInfo(Base.getTypeSourceInfo(), Record);
|
||||
AddSourceRange(Base.getSourceRange(), Record);
|
||||
AddSourceLocation(Base.isPackExpansion()? Base.getEllipsisLoc()
|
||||
: SourceLocation(),
|
||||
Record);
|
||||
}
|
||||
|
||||
void ASTWriter::FlushCXXBaseSpecifiers() {
|
||||
|
|
|
@ -34,6 +34,24 @@ void initializer_list_expansion() {
|
|||
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 {
|
||||
|
|
Загрузка…
Ссылка в новой задаче