[cfe-commits] r122297 - in /cfe/trunk: include/clang/Sema/Sema.h lib/Sema/SemaTemplateInstantiate.cpp lib/Sema/SemaTemplateInstantiateDecl.cpp lib/Sema/SemaTemplateVariadic.cpp lib/Sema/TreeTransform.h test/CXX/temp/temp.decls/temp.variadic/p4.cpp
Douglas Gregor
dgregor at apple.com
Mon Dec 20 16:52:54 PST 2010
Author: dgregor
Date: Mon Dec 20 18:52:54 2010
New Revision: 122297
URL: http://llvm.org/viewvc/llvm-project?rev=122297&view=rev
Log:
Implement instantiation of pack expansions whose pattern is a type-id
in an exception specification.
Modified:
cfe/trunk/include/clang/Sema/Sema.h
cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp
cfe/trunk/lib/Sema/TreeTransform.h
cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/p4.cpp
Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=122297&r1=122296&r2=122297&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Mon Dec 20 18:52:54 2010
@@ -3249,7 +3249,15 @@
/// 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 @@
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
Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp?rev=122297&r1=122296&r2=122297&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Mon Dec 20 18:52:54 2010
@@ -595,7 +595,14 @@
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 @@
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;
Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=122297&r1=122296&r2=122297&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Mon Dec 20 18:52:54 2010
@@ -1983,6 +1983,61 @@
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());
Modified: cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp?rev=122297&r1=122296&r2=122297&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp Mon Dec 20 18:52:54 2010
@@ -259,6 +259,11 @@
.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 @@
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;
+}
Modified: cfe/trunk/lib/Sema/TreeTransform.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=122297&r1=122296&r2=122297&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/TreeTransform.h (original)
+++ cfe/trunk/lib/Sema/TreeTransform.h Mon Dec 20 18:52:54 2010
@@ -91,11 +91,10 @@
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 @@
/// 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
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=122297&r1=122296&r2=122297&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 Dec 20 18:52:54 2010
@@ -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 @@
// 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_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}}
+};
More information about the cfe-commits
mailing list