зеркало из https://github.com/microsoft/clang-1.git
Implement instantiation of pack expansions whose pattern is a type-id
in an exception specification. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@122297 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
00ccbefcff
Коммит
b99268b308
|
@ -3249,7 +3249,15 @@ public:
|
|||
/// unexpanded parameter packs.
|
||||
void collectUnexpandedParameterPacks(TemplateArgumentLoc Arg,
|
||||
llvm::SmallVectorImpl<UnexpandedParameterPack> &Unexpanded);
|
||||
|
||||
|
||||
/// \brief Collect the set of unexpanded parameter packs within the given
|
||||
/// type.
|
||||
///
|
||||
/// \param Arg The template argument that will be traversed to find
|
||||
/// unexpanded parameter packs.
|
||||
void collectUnexpandedParameterPacks(QualType T,
|
||||
llvm::SmallVectorImpl<UnexpandedParameterPack> &Unexpanded);
|
||||
|
||||
/// \brief Invoked when parsing a template argument followed by an
|
||||
/// ellipsis, which creates a pack expansion.
|
||||
///
|
||||
|
@ -3274,6 +3282,42 @@ public:
|
|||
TypeSourceInfo *CheckPackExpansion(TypeSourceInfo *Pattern,
|
||||
SourceLocation EllipsisLoc);
|
||||
|
||||
/// \brief Determine whether we could expand a pack expansion with the
|
||||
/// given set of parameter packs into separate arguments by repeatedly
|
||||
/// transforming the pattern.
|
||||
///
|
||||
/// \param EllipsisLoc The location of the ellipsis that identifies the
|
||||
/// pack expansion.
|
||||
///
|
||||
/// \param PatternRange The source range that covers the entire pattern of
|
||||
/// the pack expansion.
|
||||
///
|
||||
/// \param Unexpanded The set of unexpanded parameter packs within the
|
||||
/// pattern.
|
||||
///
|
||||
/// \param NumUnexpanded The number of unexpanded parameter packs in
|
||||
/// \p Unexpanded.
|
||||
///
|
||||
/// \param ShouldExpand Will be set to \c true if the transformer should
|
||||
/// expand the corresponding pack expansions into separate arguments. When
|
||||
/// set, \c NumExpansions must also be set.
|
||||
///
|
||||
/// \param NumExpansions The number of separate arguments that will be in
|
||||
/// the expanded form of the corresponding pack expansion. Must be set when
|
||||
/// \c ShouldExpand is \c true.
|
||||
///
|
||||
/// \returns true if an error occurred (e.g., because the parameter packs
|
||||
/// are to be instantiated with arguments of different lengths), false
|
||||
/// otherwise. If false, \c ShouldExpand (and possibly \c NumExpansions)
|
||||
/// must be set.
|
||||
bool CheckParameterPacksForExpansion(SourceLocation EllipsisLoc,
|
||||
SourceRange PatternRange,
|
||||
const UnexpandedParameterPack *Unexpanded,
|
||||
unsigned NumUnexpanded,
|
||||
const MultiLevelTemplateArgumentList &TemplateArgs,
|
||||
bool &ShouldExpand,
|
||||
unsigned &NumExpansions);
|
||||
|
||||
/// \brief Describes the result of template argument deduction.
|
||||
///
|
||||
/// The TemplateDeductionResult enumeration describes the result of
|
||||
|
|
|
@ -595,7 +595,14 @@ namespace {
|
|||
const UnexpandedParameterPack *Unexpanded,
|
||||
unsigned NumUnexpanded,
|
||||
bool &ShouldExpand,
|
||||
unsigned &NumExpansions);
|
||||
unsigned &NumExpansions) {
|
||||
return getSema().CheckParameterPacksForExpansion(EllipsisLoc,
|
||||
PatternRange, Unexpanded,
|
||||
NumUnexpanded,
|
||||
TemplateArgs,
|
||||
ShouldExpand,
|
||||
NumExpansions);
|
||||
}
|
||||
|
||||
/// \brief Transform the given declaration by instantiating a reference to
|
||||
/// this declaration.
|
||||
|
@ -663,79 +670,6 @@ bool TemplateInstantiator::AlreadyTransformed(QualType T) {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool TemplateInstantiator::TryExpandParameterPacks(SourceLocation EllipsisLoc,
|
||||
SourceRange PatternRange,
|
||||
const UnexpandedParameterPack *Unexpanded,
|
||||
unsigned NumUnexpanded,
|
||||
bool &ShouldExpand,
|
||||
unsigned &NumExpansions) {
|
||||
ShouldExpand = true;
|
||||
std::pair<IdentifierInfo *, SourceLocation> FirstPack;
|
||||
bool HaveFirstPack = false;
|
||||
|
||||
for (unsigned I = 0; I != NumUnexpanded; ++I) {
|
||||
// Compute the depth and index for this parameter pack.
|
||||
unsigned Depth;
|
||||
unsigned Index;
|
||||
IdentifierInfo *Name;
|
||||
|
||||
if (const TemplateTypeParmType *TTP
|
||||
= Unexpanded[I].first.dyn_cast<const TemplateTypeParmType *>()) {
|
||||
Depth = TTP->getDepth();
|
||||
Index = TTP->getIndex();
|
||||
Name = TTP->getName();
|
||||
} else {
|
||||
NamedDecl *ND = Unexpanded[I].first.get<NamedDecl *>();
|
||||
if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(ND)) {
|
||||
Depth = TTP->getDepth();
|
||||
Index = TTP->getIndex();
|
||||
} else if (NonTypeTemplateParmDecl *NTTP
|
||||
= dyn_cast<NonTypeTemplateParmDecl>(ND)) {
|
||||
Depth = NTTP->getDepth();
|
||||
Index = NTTP->getIndex();
|
||||
} else {
|
||||
TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(ND);
|
||||
Depth = TTP->getDepth();
|
||||
Index = TTP->getIndex();
|
||||
}
|
||||
// FIXME: Variadic templates function parameter packs?
|
||||
Name = ND->getIdentifier();
|
||||
}
|
||||
|
||||
// If we don't have a template argument at this depth/index, then we
|
||||
// cannot expand the pack expansion. Make a note of this, but we still
|
||||
// want to check that any parameter packs we *do* have arguments for.
|
||||
if (!TemplateArgs.hasTemplateArgument(Depth, Index)) {
|
||||
ShouldExpand = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Determine the size of the argument pack.
|
||||
unsigned NewPackSize = TemplateArgs(Depth, Index).pack_size();
|
||||
if (!HaveFirstPack) {
|
||||
// The is the first pack we've seen for which we have an argument.
|
||||
// Record it.
|
||||
NumExpansions = NewPackSize;
|
||||
FirstPack.first = Name;
|
||||
FirstPack.second = Unexpanded[I].second;
|
||||
HaveFirstPack = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (NewPackSize != NumExpansions) {
|
||||
// C++0x [temp.variadic]p5:
|
||||
// All of the parameter packs expanded by a pack expansion shall have
|
||||
// the same number of arguments specified.
|
||||
getSema().Diag(EllipsisLoc, diag::err_pack_expansion_length_conflict)
|
||||
<< FirstPack.first << Name << NumExpansions << NewPackSize
|
||||
<< SourceRange(FirstPack.second) << SourceRange(Unexpanded[I].second);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Decl *TemplateInstantiator::TransformDecl(SourceLocation Loc, Decl *D) {
|
||||
if (!D)
|
||||
return 0;
|
||||
|
|
|
@ -1983,6 +1983,61 @@ TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New,
|
|||
llvm::SmallVector<QualType, 4> Exceptions;
|
||||
for (unsigned I = 0, N = Proto->getNumExceptions(); I != N; ++I) {
|
||||
// FIXME: Poor location information!
|
||||
if (const PackExpansionType *PackExpansion
|
||||
= Proto->getExceptionType(I)->getAs<PackExpansionType>()) {
|
||||
// We have a pack expansion. Instantiate it.
|
||||
llvm::SmallVector<UnexpandedParameterPack, 2> Unexpanded;
|
||||
SemaRef.collectUnexpandedParameterPacks(PackExpansion->getPattern(),
|
||||
Unexpanded);
|
||||
assert(!Unexpanded.empty() &&
|
||||
"Pack expansion without parameter packs?");
|
||||
|
||||
bool Expand = false;
|
||||
unsigned NumExpansions = 0;
|
||||
if (SemaRef.CheckParameterPacksForExpansion(New->getLocation(),
|
||||
SourceRange(),
|
||||
Unexpanded.data(),
|
||||
Unexpanded.size(),
|
||||
TemplateArgs,
|
||||
Expand, NumExpansions))
|
||||
break;
|
||||
|
||||
if (!Expand) {
|
||||
// We can't expand this pack expansion into separate arguments yet;
|
||||
// just substitute into the argument pack.
|
||||
Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(SemaRef, -1);
|
||||
QualType T = SemaRef.SubstType(PackExpansion->getPattern(),
|
||||
TemplateArgs,
|
||||
New->getLocation(), New->getDeclName());
|
||||
if (T.isNull())
|
||||
break;
|
||||
|
||||
Exceptions.push_back(T);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Substitute into the pack expansion pattern for each template
|
||||
bool Invalid = false;
|
||||
for (unsigned ArgIdx = 0; ArgIdx != NumExpansions; ++ArgIdx) {
|
||||
Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(SemaRef, ArgIdx);
|
||||
|
||||
QualType T = SemaRef.SubstType(PackExpansion->getPattern(),
|
||||
TemplateArgs,
|
||||
New->getLocation(), New->getDeclName());
|
||||
if (T.isNull()) {
|
||||
Invalid = true;
|
||||
break;
|
||||
}
|
||||
|
||||
Exceptions.push_back(T);
|
||||
}
|
||||
|
||||
if (Invalid)
|
||||
break;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
QualType T
|
||||
= SemaRef.SubstType(Proto->getExceptionType(I), TemplateArgs,
|
||||
New->getLocation(), New->getDeclName());
|
||||
|
|
|
@ -259,6 +259,11 @@ void Sema::collectUnexpandedParameterPacks(TemplateArgumentLoc Arg,
|
|||
.TraverseTemplateArgumentLoc(Arg);
|
||||
}
|
||||
|
||||
void Sema::collectUnexpandedParameterPacks(QualType T,
|
||||
llvm::SmallVectorImpl<UnexpandedParameterPack> &Unexpanded) {
|
||||
CollectUnexpandedParameterPacksVisitor(Unexpanded).TraverseType(T);
|
||||
}
|
||||
|
||||
ParsedTemplateArgument
|
||||
Sema::ActOnPackExpansion(const ParsedTemplateArgument &Arg,
|
||||
SourceLocation EllipsisLoc) {
|
||||
|
@ -327,3 +332,78 @@ TypeSourceInfo *Sema::CheckPackExpansion(TypeSourceInfo *Pattern,
|
|||
Pattern->getTypeLoc().getFullDataSize());
|
||||
return TSResult;
|
||||
}
|
||||
|
||||
|
||||
bool Sema::CheckParameterPacksForExpansion(SourceLocation EllipsisLoc,
|
||||
SourceRange PatternRange,
|
||||
const UnexpandedParameterPack *Unexpanded,
|
||||
unsigned NumUnexpanded,
|
||||
const MultiLevelTemplateArgumentList &TemplateArgs,
|
||||
bool &ShouldExpand,
|
||||
unsigned &NumExpansions) {
|
||||
ShouldExpand = true;
|
||||
std::pair<IdentifierInfo *, SourceLocation> FirstPack;
|
||||
bool HaveFirstPack = false;
|
||||
|
||||
for (unsigned I = 0; I != NumUnexpanded; ++I) {
|
||||
// Compute the depth and index for this parameter pack.
|
||||
unsigned Depth;
|
||||
unsigned Index;
|
||||
IdentifierInfo *Name;
|
||||
|
||||
if (const TemplateTypeParmType *TTP
|
||||
= Unexpanded[I].first.dyn_cast<const TemplateTypeParmType *>()) {
|
||||
Depth = TTP->getDepth();
|
||||
Index = TTP->getIndex();
|
||||
Name = TTP->getName();
|
||||
} else {
|
||||
NamedDecl *ND = Unexpanded[I].first.get<NamedDecl *>();
|
||||
if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(ND)) {
|
||||
Depth = TTP->getDepth();
|
||||
Index = TTP->getIndex();
|
||||
} else if (NonTypeTemplateParmDecl *NTTP
|
||||
= dyn_cast<NonTypeTemplateParmDecl>(ND)) {
|
||||
Depth = NTTP->getDepth();
|
||||
Index = NTTP->getIndex();
|
||||
} else {
|
||||
TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(ND);
|
||||
Depth = TTP->getDepth();
|
||||
Index = TTP->getIndex();
|
||||
}
|
||||
// FIXME: Variadic templates function parameter packs?
|
||||
Name = ND->getIdentifier();
|
||||
}
|
||||
|
||||
// If we don't have a template argument at this depth/index, then we
|
||||
// cannot expand the pack expansion. Make a note of this, but we still
|
||||
// want to check that any parameter packs we *do* have arguments for.
|
||||
if (!TemplateArgs.hasTemplateArgument(Depth, Index)) {
|
||||
ShouldExpand = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Determine the size of the argument pack.
|
||||
unsigned NewPackSize = TemplateArgs(Depth, Index).pack_size();
|
||||
if (!HaveFirstPack) {
|
||||
// The is the first pack we've seen for which we have an argument.
|
||||
// Record it.
|
||||
NumExpansions = NewPackSize;
|
||||
FirstPack.first = Name;
|
||||
FirstPack.second = Unexpanded[I].second;
|
||||
HaveFirstPack = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (NewPackSize != NumExpansions) {
|
||||
// C++0x [temp.variadic]p5:
|
||||
// All of the parameter packs expanded by a pack expansion shall have
|
||||
// the same number of arguments specified.
|
||||
Diag(EllipsisLoc, diag::err_pack_expansion_length_conflict)
|
||||
<< FirstPack.first << Name << NumExpansions << NewPackSize
|
||||
<< SourceRange(FirstPack.second) << SourceRange(Unexpanded[I].second);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -91,11 +91,10 @@ template<typename Derived>
|
|||
class TreeTransform {
|
||||
protected:
|
||||
Sema &SemaRef;
|
||||
Sema::ArgumentPackSubstitutionIndexRAII SubstIndex;
|
||||
|
||||
public:
|
||||
/// \brief Initializes a new tree transformer.
|
||||
TreeTransform(Sema &SemaRef) : SemaRef(SemaRef), SubstIndex(SemaRef, -1) { }
|
||||
TreeTransform(Sema &SemaRef) : SemaRef(SemaRef) { }
|
||||
|
||||
/// \brief Retrieves a reference to the derived class.
|
||||
Derived &getDerived() { return static_cast<Derived&>(*this); }
|
||||
|
@ -186,7 +185,7 @@ public:
|
|||
/// given set of parameter packs into separate arguments by repeatedly
|
||||
/// transforming the pattern.
|
||||
///
|
||||
/// By default, the transformed never tries to expand pack expansions.
|
||||
/// By default, the transformer never tries to expand pack expansions.
|
||||
/// Subclasses can override this routine to provide different behavior.
|
||||
///
|
||||
/// \param EllipsisLoc The location of the ellipsis that identifies the
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s
|
||||
// RUN: %clang_cc1 -std=c++0x -fsyntax-only -fexceptions -verify %s
|
||||
|
||||
template<typename... Types> struct tuple;
|
||||
|
||||
|
@ -30,12 +30,9 @@ extract_nested_types<identity<int>, identity<float> >::types *t_int_float_2
|
|||
// In a dynamic-exception-specification (15.4); the pattern is a type-id.
|
||||
template<typename ...Types>
|
||||
struct f_with_except {
|
||||
virtual void f() throw(Types...);
|
||||
virtual void f() throw(Types...); // expected-note{{overridden virtual function is here}}
|
||||
};
|
||||
|
||||
// FIXME: the code below requires the ability to instantiate pack
|
||||
// expansions whose pattern is a type-id.
|
||||
#if 0
|
||||
struct check_f_with_except_1 : f_with_except<int, float> {
|
||||
virtual void f() throw(int, float);
|
||||
};
|
||||
|
@ -43,4 +40,7 @@ struct check_f_with_except_1 : f_with_except<int, float> {
|
|||
struct check_f_with_except_2 : f_with_except<int, float> {
|
||||
virtual void f() throw(int);
|
||||
};
|
||||
#endif
|
||||
|
||||
struct check_f_with_except_3 : f_with_except<int, float> {
|
||||
virtual void f() throw(int, float, double); // expected-error{{exception specification of overriding function is more lax than base version}}
|
||||
};
|
||||
|
|
Загрузка…
Ссылка в новой задаче