[cfe-commits] r123163 - in /cfe/trunk: include/clang/AST/ include/clang/Sema/ lib/Sema/ test/CXX/temp/temp.decls/temp.variadic/ test/CXX/temp/temp.fct.spec/temp.arg.explicit/
Douglas Gregor
dgregor at apple.com
Sun Jan 9 23:32:04 PST 2011
Author: dgregor
Date: Mon Jan 10 01:32:04 2011
New Revision: 123163
URL: http://llvm.org/viewvc/llvm-project?rev=123163&view=rev
Log:
Work-in-progress implementation of C++0x [temp.arg.explicit]p9, which
allows an argument pack determines via explicit specification of
function template arguments to be extended by further, deduced
arguments. For example:
template<class ... Types> void f(Types ... values);
void g() {
f<int*, float*>(0, 0, 0); // Types is deduced to the sequence int*, float*, int
}
There are a number of FIXMEs in here that indicate places where we
need to implement + test retained expansions, plus a number of other
places in deduction where we need to correctly cope with the
explicitly-specified arguments when deducing an argument
pack. Furthermore, it appears that the RecursiveASTVisitor needs to be
auditied; it's missing some traversals (especially w.r.t. template
arguments) that cause it not to find unexpanded parameter packs when
it should.
The good news, however, is that the tr1::tuple implementation now
works fully, and the tr1::bind example (both from N2080) is actually
working now.
Added:
cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/example-bind.cpp (with props)
Modified:
cfe/trunk/include/clang/AST/RecursiveASTVisitor.h
cfe/trunk/include/clang/AST/TemplateBase.h
cfe/trunk/include/clang/Sema/Sema.h
cfe/trunk/include/clang/Sema/Template.h
cfe/trunk/lib/Sema/SemaTemplate.cpp
cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp
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/example-tuple.cpp
cfe/trunk/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p9-0x.cpp
Modified: cfe/trunk/include/clang/AST/RecursiveASTVisitor.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/RecursiveASTVisitor.h?rev=123163&r1=123162&r2=123163&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/RecursiveASTVisitor.h (original)
+++ cfe/trunk/include/clang/AST/RecursiveASTVisitor.h Mon Jan 10 01:32:04 2011
@@ -1801,7 +1801,7 @@
DEF_TRAVERSE_STMT(CXXDeleteExpr, { })
DEF_TRAVERSE_STMT(ExprWithCleanups, { })
DEF_TRAVERSE_STMT(CXXNullPtrLiteralExpr, { })
-DEF_TRAVERSE_STMT(CXXPseudoDestructorExpr, { })
+ DEF_TRAVERSE_STMT(CXXPseudoDestructorExpr, { }) // FIXME: Incomplete!
DEF_TRAVERSE_STMT(CXXThisExpr, { })
DEF_TRAVERSE_STMT(CXXThrowExpr, { })
DEF_TRAVERSE_STMT(DesignatedInitExpr, { })
@@ -1820,8 +1820,18 @@
DEF_TRAVERSE_STMT(PredefinedExpr, { })
DEF_TRAVERSE_STMT(ShuffleVectorExpr, { })
DEF_TRAVERSE_STMT(StmtExpr, { })
-DEF_TRAVERSE_STMT(UnresolvedLookupExpr, { })
-DEF_TRAVERSE_STMT(UnresolvedMemberExpr, { })
+DEF_TRAVERSE_STMT(UnresolvedLookupExpr, {
+ TRY_TO(TraverseNestedNameSpecifier(S->getQualifier()));
+ TRY_TO(TraverseTemplateArgumentLocsHelper(S->getTemplateArgs(),
+ S->getNumTemplateArgs()));
+})
+
+DEF_TRAVERSE_STMT(UnresolvedMemberExpr, {
+ TRY_TO(TraverseNestedNameSpecifier(S->getQualifier()));
+ TRY_TO(TraverseTemplateArgumentLocsHelper(S->getTemplateArgs(),
+ S->getNumTemplateArgs()));
+})
+
DEF_TRAVERSE_STMT(CXXOperatorCallExpr, { })
DEF_TRAVERSE_STMT(OpaqueValueExpr, { })
Modified: cfe/trunk/include/clang/AST/TemplateBase.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/TemplateBase.h?rev=123163&r1=123162&r2=123163&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/TemplateBase.h (original)
+++ cfe/trunk/include/clang/AST/TemplateBase.h Mon Jan 10 01:32:04 2011
@@ -77,7 +77,7 @@
void *Type;
} Integer;
struct {
- TemplateArgument *Args;
+ const TemplateArgument *Args;
unsigned NumArgs;
} Args;
};
@@ -136,7 +136,7 @@
///
/// We assume that storage for the template arguments provided
/// outlives the TemplateArgument itself.
- TemplateArgument(TemplateArgument *Args, unsigned NumArgs) : Kind(Pack) {
+ TemplateArgument(const TemplateArgument *Args, unsigned NumArgs) : Kind(Pack){
this->Args.Args = Args;
this->Args.NumArgs = NumArgs;
}
Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=123163&r1=123162&r2=123163&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Mon Jan 10 01:32:04 2011
@@ -3361,6 +3361,11 @@
/// expand the corresponding pack expansions into separate arguments. When
/// set, \c NumExpansions must also be set.
///
+ /// \param RetainExpansion Whether the caller should add an unexpanded
+ /// pack expansion after all of the expanded arguments. This is used
+ /// when extending explicitly-specified template argument packs per
+ /// C++0x [temp.arg.explicit]p9.
+ ///
/// \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.
@@ -3375,6 +3380,7 @@
unsigned NumUnexpanded,
const MultiLevelTemplateArgumentList &TemplateArgs,
bool &ShouldExpand,
+ bool &RetainExpansion,
unsigned &NumExpansions);
/// \brief Determine whether the given declarator contains any unexpanded
Modified: cfe/trunk/include/clang/Sema/Template.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Template.h?rev=123163&r1=123162&r2=123163&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Template.h (original)
+++ cfe/trunk/include/clang/Sema/Template.h Mon Jan 10 01:32:04 2011
@@ -81,6 +81,16 @@
return !(*this)(Depth, Index).isNull();
}
+ /// \brief Clear out a specific template argument.
+ void setArgument(unsigned Depth, unsigned Index,
+ TemplateArgument Arg) {
+ assert(Depth < TemplateArgumentLists.size());
+ assert(Index < TemplateArgumentLists[getNumLevels() - Depth - 1].second);
+ const_cast<TemplateArgument&>(
+ TemplateArgumentLists[getNumLevels() - Depth - 1].first[Index])
+ = Arg;
+ }
+
/// \brief Add a new outermost level to the multi-level template argument
/// list.
void addOuterTemplateArguments(const TemplateArgumentList *TemplateArgs) {
@@ -141,7 +151,7 @@
: TemplateArgument(Arg), DeducedFromArrayBound(DeducedFromArrayBound) { }
/// \brief Construct an integral non-type template argument that
- /// has been deduced, possible from an array bound.
+ /// has been deduced, possibly from an array bound.
DeducedTemplateArgument(const llvm::APSInt &Value,
QualType ValueType,
bool DeducedFromArrayBound)
@@ -214,6 +224,19 @@
/// lookup will search our outer scope.
bool CombineWithOuterScope;
+ /// \brief If non-NULL, the template parameter pack that has been
+ /// partially substituted per C++0x [temp.arg.explicit]p9.
+ NamedDecl *PartiallySubstitutedPack;
+
+ /// \brief If \c PartiallySubstitutedPack is non-null, the set of
+ /// explicitly-specified template arguments in that pack.
+ const TemplateArgument *ArgsInPartiallySubstitutedPack;
+
+ /// \brief If \c PartiallySubstitutedPack, the number of
+ /// explicitly-specified template arguments in
+ /// ArgsInPartiallySubstitutedPack.
+ unsigned NumArgsInPartiallySubstitutedPack;
+
// This class is non-copyable
LocalInstantiationScope(const LocalInstantiationScope &);
LocalInstantiationScope &operator=(const LocalInstantiationScope &);
@@ -221,7 +244,8 @@
public:
LocalInstantiationScope(Sema &SemaRef, bool CombineWithOuterScope = false)
: SemaRef(SemaRef), Outer(SemaRef.CurrentInstantiationScope),
- Exited(false), CombineWithOuterScope(CombineWithOuterScope)
+ Exited(false), CombineWithOuterScope(CombineWithOuterScope),
+ PartiallySubstitutedPack(0)
{
SemaRef.CurrentInstantiationScope = this;
}
@@ -271,6 +295,29 @@
void InstantiatedLocal(const Decl *D, Decl *Inst);
void InstantiatedLocalPackArg(const Decl *D, Decl *Inst);
void MakeInstantiatedLocalArgPack(const Decl *D);
+
+ /// \brief Note that the given parameter pack has been partially substituted
+ /// via explicit specification of template arguments
+ /// (C++0x [temp.arg.explicit]p9).
+ ///
+ /// \param Pack The parameter pack, which will always be a template
+ /// parameter pack.
+ ///
+ /// \param ExplicitArgs The explicitly-specified template arguments provided
+ /// for this parameter pack.
+ ///
+ /// \param NumExplicitArgs The number of explicitly-specified template
+ /// arguments provided for this parameter pack.
+ void SetPartiallySubstitutedPack(NamedDecl *Pack,
+ const TemplateArgument *ExplicitArgs,
+ unsigned NumExplicitArgs);
+
+ /// \brief Retrieve the partially-substitued template parameter pack.
+ ///
+ /// If there is no partially-substituted parameter pack, returns NULL.
+ NamedDecl *getPartiallySubstitutedPack(
+ const TemplateArgument **ExplicitArgs = 0,
+ unsigned *NumExplicitArgs = 0) const;
};
class TemplateDeclInstantiator
Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=123163&r1=123162&r2=123163&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Mon Jan 10 01:32:04 2011
@@ -2550,10 +2550,13 @@
// Form argument packs for each of the parameter packs remaining.
while (Param != ParamEnd) {
+ // If we're checking a partial list of template arguments, don't fill
+ // in arguments for non-template parameter packs.
+
if ((*Param)->isTemplateParameterPack()) {
- // The parameter pack takes the contents of the current argument pack,
- // which we built up earlier.
- if (ArgumentPack.empty()) {
+ if (PartialTemplateArgs && ArgumentPack.empty()) {
+ Converted.push_back(TemplateArgument());
+ } else if (ArgumentPack.empty()) {
Converted.push_back(TemplateArgument(0, 0));
} else {
TemplateArgument *PackedArgs
@@ -3600,7 +3603,7 @@
Sema::BuildExpressionFromIntegralTemplateArgument(const TemplateArgument &Arg,
SourceLocation Loc) {
assert(Arg.getKind() == TemplateArgument::Integral &&
- "Operation is only value for integral template arguments");
+ "Operation is only valid for integral template arguments");
QualType T = Arg.getIntegralType();
if (T->isCharType() || T->isWideCharType())
return Owned(new (Context) CharacterLiteral(
Modified: cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp?rev=123163&r1=123162&r2=123163&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp Mon Jan 10 01:32:04 2011
@@ -478,14 +478,9 @@
}
}
-/// \brief Retrieve the depth and index of an unexpanded parameter pack.
+/// \brief Retrieve the depth and index of a template parameter.
static std::pair<unsigned, unsigned>
-getDepthAndIndex(UnexpandedParameterPack UPP) {
- if (const TemplateTypeParmType *TTP
- = UPP.first.dyn_cast<const TemplateTypeParmType *>())
- return std::make_pair(TTP->getDepth(), TTP->getIndex());
-
- NamedDecl *ND = UPP.first.get<NamedDecl *>();
+getDepthAndIndex(NamedDecl *ND) {
if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(ND))
return std::make_pair(TTP->getDepth(), TTP->getIndex());
@@ -496,6 +491,16 @@
return std::make_pair(TTP->getDepth(), TTP->getIndex());
}
+/// \brief Retrieve the depth and index of an unexpanded parameter pack.
+static std::pair<unsigned, unsigned>
+getDepthAndIndex(UnexpandedParameterPack UPP) {
+ if (const TemplateTypeParmType *TTP
+ = UPP.first.dyn_cast<const TemplateTypeParmType *>())
+ return std::make_pair(TTP->getDepth(), TTP->getIndex());
+
+ return getDepthAndIndex(UPP.first.get<NamedDecl *>());
+}
+
/// \brief Helper function to build a TemplateParameter when we don't
/// know its type statically.
static TemplateParameter makeTemplateParameter(Decl *D) {
@@ -602,6 +607,12 @@
}
assert(!PackIndices.empty() && "Pack expansion without unexpanded packs?");
+ // Keep track of the deduced template arguments for each parameter pack
+ // expanded by this pack expansion (the outer index) and for each
+ // template argument (the inner SmallVectors).
+ llvm::SmallVector<llvm::SmallVector<DeducedTemplateArgument, 4>, 2>
+ NewlyDeducedPacks(PackIndices.size());
+
// Save the deduced template arguments for each parameter pack expanded
// by this pack expansion, then clear out the deduction.
llvm::SmallVector<DeducedTemplateArgument, 2>
@@ -609,13 +620,21 @@
for (unsigned I = 0, N = PackIndices.size(); I != N; ++I) {
SavedPacks[I] = Deduced[PackIndices[I]];
Deduced[PackIndices[I]] = DeducedTemplateArgument();
+
+ // If the template arugment pack was explicitly specified, add that to
+ // the set of deduced arguments.
+ const TemplateArgument *ExplicitArgs;
+ unsigned NumExplicitArgs;
+ if (NamedDecl *PartiallySubstitutedPack
+ = S.CurrentInstantiationScope->getPartiallySubstitutedPack(
+ &ExplicitArgs,
+ &NumExplicitArgs)) {
+ if (getDepthAndIndex(PartiallySubstitutedPack).second == PackIndices[I])
+ NewlyDeducedPacks[I].append(ExplicitArgs,
+ ExplicitArgs + NumExplicitArgs);
+ }
}
- // Keep track of the deduced template arguments for each parameter pack
- // expanded by this pack expansion (the outer index) and for each
- // template argument (the inner SmallVectors).
- llvm::SmallVector<llvm::SmallVector<DeducedTemplateArgument, 4>, 2>
- NewlyDeducedPacks(PackIndices.size());
bool HasAnyArguments = false;
for (; ArgIdx < NumArgs; ++ArgIdx) {
HasAnyArguments = true;
@@ -1879,13 +1898,30 @@
TemplateArgumentList *ExplicitArgumentList
= TemplateArgumentList::CreateCopy(Context, Builder.data(), Builder.size());
Info.reset(ExplicitArgumentList);
-
+
// Template argument deduction and the final substitution should be
// done in the context of the templated declaration. Explicit
// argument substitution, on the other hand, needs to happen in the
// calling context.
ContextRAII SavedContext(*this, FunctionTemplate->getTemplatedDecl());
+ // If we deduced template arguments for a template parameter pack,
+ // note that the template argument pack is partially substituted and record
+ // the explicit template arguments. They'll be used as part of deduction
+ // for this template parameter pack.
+ bool HasPartiallySubstitutedPack = false;
+ for (unsigned I = 0, N = Builder.size(); I != N; ++I) {
+ const TemplateArgument &Arg = Builder[I];
+ if (Arg.getKind() == TemplateArgument::Pack) {
+ HasPartiallySubstitutedPack = true;
+ CurrentInstantiationScope->SetPartiallySubstitutedPack(
+ TemplateParams->getParam(I),
+ Arg.pack_begin(),
+ Arg.pack_size());
+ break;
+ }
+ }
+
// Instantiate the types of each of the function parameters given the
// explicitly-specified template arguments.
if (SubstParmTypes(Function->getLocation(),
@@ -1927,11 +1963,18 @@
// template arguments can be deduced, they may all be omitted; in this
// case, the empty template argument list <> itself may also be omitted.
//
- // Take all of the explicitly-specified arguments and put them into the
- // set of deduced template arguments.
+ // Take all of the explicitly-specified arguments and put them into
+ // the set of deduced template arguments. Explicitly-specified
+ // parameter packs, however, will be set to NULL since the deduction
+ // mechanisms handle explicitly-specified argument packs directly.
Deduced.reserve(TemplateParams->size());
- for (unsigned I = 0, N = ExplicitArgumentList->size(); I != N; ++I)
- Deduced.push_back(ExplicitArgumentList->get(I));
+ for (unsigned I = 0, N = ExplicitArgumentList->size(); I != N; ++I) {
+ const TemplateArgument &Arg = ExplicitArgumentList->get(I);
+ if (Arg.getKind() == TemplateArgument::Pack)
+ Deduced.push_back(DeducedTemplateArgument());
+ else
+ Deduced.push_back(Arg);
+ }
return TDK_Success;
}
@@ -2025,7 +2068,18 @@
// be deduced to an empty sequence of template arguments.
// FIXME: Where did the word "trailing" come from?
if (Param->isTemplateParameterPack()) {
- Builder.push_back(TemplateArgument(0, 0));
+ // We may have had explicitly-specified template arguments for this
+ // template parameter pack. If so, our empty deduction extends the
+ // explicitly-specified set (C++0x [temp.arg.explicit]p9).
+ const TemplateArgument *ExplicitArgs;
+ unsigned NumExplicitArgs;
+ if (CurrentInstantiationScope->getPartiallySubstitutedPack(&ExplicitArgs,
+ &NumExplicitArgs)
+ == Param)
+ Builder.push_back(TemplateArgument(ExplicitArgs, NumExplicitArgs));
+ else
+ Builder.push_back(TemplateArgument(0, 0));
+
continue;
}
@@ -2446,20 +2500,36 @@
}
assert(!PackIndices.empty() && "Pack expansion without unexpanded packs?");
+ // Keep track of the deduced template arguments for each parameter pack
+ // expanded by this pack expansion (the outer index) and for each
+ // template argument (the inner SmallVectors).
+ llvm::SmallVector<llvm::SmallVector<DeducedTemplateArgument, 4>, 2>
+ NewlyDeducedPacks(PackIndices.size());
+
// Save the deduced template arguments for each parameter pack expanded
// by this pack expansion, then clear out the deduction.
llvm::SmallVector<DeducedTemplateArgument, 2>
- SavedPacks(PackIndices.size());
+ SavedPacks(PackIndices.size());
for (unsigned I = 0, N = PackIndices.size(); I != N; ++I) {
+ // Save the previously-deduced argument pack, then clear it out so that we
+ // can deduce a new argument pack.
SavedPacks[I] = Deduced[PackIndices[I]];
- Deduced[PackIndices[I]] = DeducedTemplateArgument();
+ Deduced[PackIndices[I]] = TemplateArgument();
+
+ // If the template arugment pack was explicitly specified, add that to
+ // the set of deduced arguments.
+ const TemplateArgument *ExplicitArgs;
+ unsigned NumExplicitArgs;
+ if (NamedDecl *PartiallySubstitutedPack
+ = CurrentInstantiationScope->getPartiallySubstitutedPack(
+ &ExplicitArgs,
+ &NumExplicitArgs)) {
+ if (getDepthAndIndex(PartiallySubstitutedPack).second == PackIndices[I])
+ NewlyDeducedPacks[I].append(ExplicitArgs,
+ ExplicitArgs + NumExplicitArgs);
+ }
}
- // Keep track of the deduced template arguments for each parameter pack
- // expanded by this pack expansion (the outer index) and for each
- // template argument (the inner SmallVectors).
- llvm::SmallVector<llvm::SmallVector<DeducedTemplateArgument, 4>, 2>
- NewlyDeducedPacks(PackIndices.size());
bool HasAnyArguments = false;
for (; ArgIdx < NumArgs; ++ArgIdx) {
HasAnyArguments = true;
Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp?rev=123163&r1=123162&r2=123163&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Mon Jan 10 01:32:04 2011
@@ -564,6 +564,19 @@
return 0;
}
+/// \brief Retrieve the depth and index of a parameter pack.
+static std::pair<unsigned, unsigned>
+getDepthAndIndex(NamedDecl *ND) {
+ if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(ND))
+ return std::make_pair(TTP->getDepth(), TTP->getIndex());
+
+ if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(ND))
+ return std::make_pair(NTTP->getDepth(), NTTP->getIndex());
+
+ TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(ND);
+ return std::make_pair(TTP->getDepth(), TTP->getIndex());
+}
+
//===----------------------------------------------------------------------===/
// Template Instantiation for Types
//===----------------------------------------------------------------------===/
@@ -608,12 +621,14 @@
const UnexpandedParameterPack *Unexpanded,
unsigned NumUnexpanded,
bool &ShouldExpand,
+ bool &RetainExpansion,
unsigned &NumExpansions) {
return getSema().CheckParameterPacksForExpansion(EllipsisLoc,
PatternRange, Unexpanded,
NumUnexpanded,
TemplateArgs,
ShouldExpand,
+ RetainExpansion,
NumExpansions);
}
@@ -621,6 +636,37 @@
SemaRef.CurrentInstantiationScope->MakeInstantiatedLocalArgPack(Pack);
}
+ TemplateArgument ForgetPartiallySubstitutedPack() {
+ TemplateArgument Result;
+ if (NamedDecl *PartialPack
+ = SemaRef.CurrentInstantiationScope->getPartiallySubstitutedPack()){
+ MultiLevelTemplateArgumentList &TemplateArgs
+ = const_cast<MultiLevelTemplateArgumentList &>(this->TemplateArgs);
+ unsigned Depth, Index;
+ llvm::tie(Depth, Index) = getDepthAndIndex(PartialPack);
+ if (TemplateArgs.hasTemplateArgument(Depth, Index)) {
+ Result = TemplateArgs(Depth, Index);
+ TemplateArgs.setArgument(Depth, Index, TemplateArgument());
+ }
+ }
+
+ return Result;
+ }
+
+ void RememberPartiallySubstitutedPack(TemplateArgument Arg) {
+ if (Arg.isNull())
+ return;
+
+ if (NamedDecl *PartialPack
+ = SemaRef.CurrentInstantiationScope->getPartiallySubstitutedPack()){
+ MultiLevelTemplateArgumentList &TemplateArgs
+ = const_cast<MultiLevelTemplateArgumentList &>(this->TemplateArgs);
+ unsigned Depth, Index;
+ llvm::tie(Depth, Index) = getDepthAndIndex(PartialPack);
+ TemplateArgs.setArgument(Depth, Index, Arg);
+ }
+ }
+
/// \brief Transform the given declaration by instantiating a reference to
/// this declaration.
Decl *TransformDecl(SourceLocation Loc, Decl *D);
@@ -713,6 +759,7 @@
return 0;
}
+ assert(getSema().ArgumentPackSubstitutionIndex < (int)Arg.pack_size());
Arg = Arg.pack_begin()[getSema().ArgumentPackSubstitutionIndex];
}
@@ -761,6 +808,7 @@
return 0;
}
+ assert(getSema().ArgumentPackSubstitutionIndex < (int)Arg.pack_size());
Arg = Arg.pack_begin()[getSema().ArgumentPackSubstitutionIndex];
}
@@ -877,6 +925,7 @@
return ExprError();
}
+ assert(getSema().ArgumentPackSubstitutionIndex < (int)Arg.pack_size());
Arg = Arg.pack_begin()[getSema().ArgumentPackSubstitutionIndex];
}
@@ -981,6 +1030,7 @@
return QualType();
}
+ assert(getSema().ArgumentPackSubstitutionIndex < (int)Arg.pack_size());
Arg = Arg.pack_begin()[getSema().ArgumentPackSubstitutionIndex];
}
@@ -1272,11 +1322,13 @@
collectUnexpandedParameterPacks(Base->getTypeSourceInfo()->getTypeLoc(),
Unexpanded);
bool ShouldExpand = false;
+ bool RetainExpansion = false;
unsigned NumExpansions = 0;
if (CheckParameterPacksForExpansion(Base->getEllipsisLoc(),
Base->getSourceRange(),
Unexpanded.data(), Unexpanded.size(),
TemplateArgs, ShouldExpand,
+ RetainExpansion,
NumExpansions)) {
Invalid = true;
continue;
@@ -1959,9 +2011,13 @@
void LocalInstantiationScope::InstantiatedLocal(const Decl *D, Decl *Inst) {
llvm::PointerUnion<Decl *, DeclArgumentPack *> &Stored = LocalDecls[D];
- assert((Stored.isNull() ||
- (Stored.get<Decl *>() == Inst)) && "Already instantiated this local");
- Stored = Inst;
+ if (Stored.isNull())
+ Stored = Inst;
+ else if (Stored.is<Decl *>()) {
+ assert(Stored.get<Decl *>() == Inst && "Already instantiated this local");
+ Stored = Inst;
+ } else
+ LocalDecls[D].get<DeclArgumentPack *>()->push_back(Inst);
}
void LocalInstantiationScope::InstantiatedLocalPackArg(const Decl *D,
@@ -1978,3 +2034,41 @@
ArgumentPacks.push_back(Pack);
}
+void LocalInstantiationScope::SetPartiallySubstitutedPack(NamedDecl *Pack,
+ const TemplateArgument *ExplicitArgs,
+ unsigned NumExplicitArgs) {
+ assert((!PartiallySubstitutedPack || PartiallySubstitutedPack == Pack) &&
+ "Already have a partially-substituted pack");
+ assert((!PartiallySubstitutedPack
+ || NumArgsInPartiallySubstitutedPack == NumExplicitArgs) &&
+ "Wrong number of arguments in partially-substituted pack");
+ PartiallySubstitutedPack = Pack;
+ ArgsInPartiallySubstitutedPack = ExplicitArgs;
+ NumArgsInPartiallySubstitutedPack = NumExplicitArgs;
+}
+
+NamedDecl *LocalInstantiationScope::getPartiallySubstitutedPack(
+ const TemplateArgument **ExplicitArgs,
+ unsigned *NumExplicitArgs) const {
+ if (ExplicitArgs)
+ *ExplicitArgs = 0;
+ if (NumExplicitArgs)
+ *NumExplicitArgs = 0;
+
+ for (const LocalInstantiationScope *Current = this; Current;
+ Current = Current->Outer) {
+ if (Current->PartiallySubstitutedPack) {
+ if (ExplicitArgs)
+ *ExplicitArgs = Current->ArgsInPartiallySubstitutedPack;
+ if (NumExplicitArgs)
+ *NumExplicitArgs = Current->NumArgsInPartiallySubstitutedPack;
+
+ return Current->PartiallySubstitutedPack;
+ }
+
+ if (!Current->CombineWithOuterScope)
+ break;
+ }
+
+ return 0;
+}
Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=123163&r1=123162&r2=123163&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Mon Jan 10 01:32:04 2011
@@ -1973,13 +1973,16 @@
"Pack expansion without parameter packs?");
bool Expand = false;
+ bool RetainExpansion = false;
unsigned NumExpansions = 0;
if (SemaRef.CheckParameterPacksForExpansion(New->getLocation(),
SourceRange(),
Unexpanded.data(),
Unexpanded.size(),
TemplateArgs,
- Expand, NumExpansions))
+ Expand,
+ RetainExpansion,
+ NumExpansions))
break;
if (!Expand) {
@@ -2377,12 +2380,14 @@
llvm::SmallVector<UnexpandedParameterPack, 2> Unexpanded;
collectUnexpandedParameterPacks(BaseTL, Unexpanded);
bool ShouldExpand = false;
+ bool RetainExpansion = false;
unsigned NumExpansions = 0;
if (CheckParameterPacksForExpansion(Init->getEllipsisLoc(),
BaseTL.getSourceRange(),
Unexpanded.data(),
Unexpanded.size(),
TemplateArgs, ShouldExpand,
+ RetainExpansion,
NumExpansions)) {
AnyErrors = true;
New->setInvalidDecl();
Modified: cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp?rev=123163&r1=123162&r2=123163&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp Mon Jan 10 01:32:04 2011
@@ -419,14 +419,29 @@
EllipsisLoc));
}
+/// \brief Retrieve the depth and index of a parameter pack.
+static std::pair<unsigned, unsigned>
+getDepthAndIndex(NamedDecl *ND) {
+ if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(ND))
+ return std::make_pair(TTP->getDepth(), TTP->getIndex());
+
+ if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(ND))
+ return std::make_pair(NTTP->getDepth(), NTTP->getIndex());
+
+ TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(ND);
+ return std::make_pair(TTP->getDepth(), TTP->getIndex());
+}
+
bool Sema::CheckParameterPacksForExpansion(SourceLocation EllipsisLoc,
SourceRange PatternRange,
const UnexpandedParameterPack *Unexpanded,
unsigned NumUnexpanded,
const MultiLevelTemplateArgumentList &TemplateArgs,
bool &ShouldExpand,
+ bool &RetainExpansion,
unsigned &NumExpansions) {
ShouldExpand = true;
+ RetainExpansion = false;
std::pair<IdentifierInfo *, SourceLocation> FirstPack;
bool HaveFirstPack = false;
@@ -444,21 +459,11 @@
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 if (TemplateTemplateParmDecl *TTP
- = dyn_cast<TemplateTemplateParmDecl>(ND)) {
- Depth = TTP->getDepth();
- Index = TTP->getIndex();
- } else {
- assert(cast<ParmVarDecl>(ND)->isParameterPack());
+ if (isa<ParmVarDecl>(ND))
IsFunctionParameterPack = true;
- }
+ else
+ llvm::tie(Depth, Index) = getDepthAndIndex(ND);
+
Name = ND->getIdentifier();
}
@@ -495,6 +500,18 @@
NewPackSize = TemplateArgs(Depth, Index).pack_size();
}
+ // C++0x [temp.arg.explicit]p9:
+ // Template argument deduction can extend the sequence of template
+ // arguments corresponding to a template parameter pack, even when the
+ // sequence contains explicitly specified template arguments.
+ if (NamedDecl *PartialPack
+ = CurrentInstantiationScope->getPartiallySubstitutedPack()) {
+ unsigned PartialDepth, PartialIndex;
+ llvm::tie(PartialDepth, PartialIndex) = getDepthAndIndex(PartialPack);
+ if (PartialDepth == Depth && PartialIndex == Index)
+ RetainExpansion = true;
+ }
+
if (!HaveFirstPack) {
// The is the first pack we've seen for which we have an argument.
// Record it.
Modified: cfe/trunk/lib/Sema/TreeTransform.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=123163&r1=123162&r2=123163&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/TreeTransform.h (original)
+++ cfe/trunk/lib/Sema/TreeTransform.h Mon Jan 10 01:32:04 2011
@@ -89,6 +89,23 @@
/// (\c getBaseLocation(), \c getBaseEntity()).
template<typename Derived>
class TreeTransform {
+ /// \brief Private RAII object that helps us forget and then re-remember
+ /// the template argument corresponding to a partially-substituted parameter
+ /// pack.
+ class ForgetPartiallySubstitutedPackRAII {
+ Derived &Self;
+ TemplateArgument Old;
+
+ public:
+ ForgetPartiallySubstitutedPackRAII(Derived &Self) : Self(Self) {
+ Old = Self.ForgetPartiallySubstitutedPack();
+ }
+
+ ~ForgetPartiallySubstitutedPackRAII() {
+ Self.RememberPartiallySubstitutedPack(Old);
+ }
+ };
+
protected:
Sema &SemaRef;
@@ -204,6 +221,11 @@
/// expand the corresponding pack expansions into separate arguments. When
/// set, \c NumExpansions must also be set.
///
+ /// \param RetainExpansion Whether the caller should add an unexpanded
+ /// pack expansion after all of the expanded arguments. This is used
+ /// when extending explicitly-specified template argument packs per
+ /// C++0x [temp.arg.explicit]p9.
+ ///
/// \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.
@@ -217,11 +239,28 @@
const UnexpandedParameterPack *Unexpanded,
unsigned NumUnexpanded,
bool &ShouldExpand,
+ bool &RetainExpansion,
unsigned &NumExpansions) {
ShouldExpand = false;
return false;
}
+ /// \brief "Forget" about the partially-substituted pack template argument,
+ /// when performing an instantiation that must preserve the parameter pack
+ /// use.
+ ///
+ /// This routine is meant to be overridden by the template instantiator.
+ TemplateArgument ForgetPartiallySubstitutedPack() {
+ return TemplateArgument();
+ }
+
+ /// \brief "Remember" the partially-substituted pack template argument
+ /// after performing an instantiation that must preserve the parameter pack
+ /// use.
+ ///
+ /// This routine is meant to be overridden by the template instantiator.
+ void RememberPartiallySubstitutedPack(TemplateArgument Arg) { }
+
/// \brief Note to the derived class when a function parameter pack is
/// being expanded.
void ExpandingFunctionParameterPack(ParmVarDecl *Pack) { }
@@ -2250,12 +2289,14 @@
// Determine whether the set of unexpanded parameter packs can and should
// be expanded.
bool Expand = true;
+ bool RetainExpansion = false;
unsigned NumExpansions = 0;
if (getDerived().TryExpandParameterPacks(Expansion->getEllipsisLoc(),
Pattern->getSourceRange(),
Unexpanded.data(),
Unexpanded.size(),
- Expand, NumExpansions))
+ Expand, RetainExpansion,
+ NumExpansions))
return true;
if (!Expand) {
@@ -2770,12 +2811,15 @@
// Determine whether the set of unexpanded parameter packs can and should
// be expanded.
bool Expand = true;
+ bool RetainExpansion = false;
unsigned NumExpansions = 0;
if (getDerived().TryExpandParameterPacks(Ellipsis,
Pattern.getSourceRange(),
Unexpanded.data(),
Unexpanded.size(),
- Expand, NumExpansions))
+ Expand,
+ RetainExpansion,
+ NumExpansions))
return true;
if (!Expand) {
@@ -2806,6 +2850,8 @@
Outputs.addArgument(Out);
}
+ // FIXME: Variadic templates retain expansion!
+
continue;
}
@@ -3415,12 +3461,15 @@
// Determine whether we should expand the parameter packs.
bool ShouldExpand = false;
+ bool RetainExpansion = false;
unsigned NumExpansions = 0;
if (getDerived().TryExpandParameterPacks(ExpansionTL.getEllipsisLoc(),
Pattern.getSourceRange(),
Unexpanded.data(),
Unexpanded.size(),
- ShouldExpand, NumExpansions)) {
+ ShouldExpand,
+ RetainExpansion,
+ NumExpansions)) {
return true;
}
@@ -3439,7 +3488,21 @@
if (PVars)
PVars->push_back(NewParm);
}
-
+
+ // If we're supposed to retain a pack expansion, do so by temporarily
+ // forgetting the partially-substituted parameter pack.
+ if (RetainExpansion) {
+ ForgetPartiallySubstitutedPackRAII Forget(getDerived());
+ ParmVarDecl *NewParm
+ = getDerived().TransformFunctionTypeParam(OldParm);
+ if (!NewParm)
+ return true;
+
+ OutParamTypes.push_back(NewParm->getType());
+ if (PVars)
+ PVars->push_back(NewParm);
+ }
+
// We're done with the pack expansion.
continue;
}
@@ -3472,11 +3535,14 @@
// Determine whether we should expand the parameter packs.
bool ShouldExpand = false;
+ bool RetainExpansion = false;
unsigned NumExpansions = 0;
if (getDerived().TryExpandParameterPacks(Loc, SourceRange(),
Unexpanded.data(),
Unexpanded.size(),
- ShouldExpand, NumExpansions)) {
+ ShouldExpand,
+ RetainExpansion,
+ NumExpansions)) {
return true;
}
@@ -3498,6 +3564,8 @@
continue;
}
+ // FIXME: Variadic templates retain pack expansion!
+
// We'll substitute the parameter now without expanding the pack
// expansion.
OldType = Expansion->getPattern();
@@ -6674,13 +6742,15 @@
// so
UnexpandedParameterPack Unexpanded(E->getPack(), E->getPackLoc());
bool ShouldExpand = false;
+ bool RetainExpansion = false;
unsigned NumExpansions = 0;
if (getDerived().TryExpandParameterPacks(E->getOperatorLoc(), E->getPackLoc(),
&Unexpanded, 1,
- ShouldExpand, NumExpansions))
+ ShouldExpand, RetainExpansion,
+ NumExpansions))
return ExprError();
- if (!ShouldExpand)
+ if (!ShouldExpand || RetainExpansion)
return SemaRef.Owned(E);
// We now know the length of the parameter pack, so build a new expression
Added: cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/example-bind.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/example-bind.cpp?rev=123163&view=auto
==============================================================================
--- cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/example-bind.cpp (added)
+++ cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/example-bind.cpp Mon Jan 10 01:32:04 2011
@@ -0,0 +1,352 @@
+// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s
+
+// Example bind implementation from the variadic templates proposal,
+// ISO C++ committee document number N2080.
+
+// Helper type traits
+template<typename T>
+struct add_reference {
+ typedef T &type;
+};
+
+template<typename T>
+struct add_reference<T&> {
+ typedef T &type;
+};
+
+template<typename T>
+struct add_const_reference {
+ typedef T const &type;
+};
+
+template<typename T>
+struct add_const_reference<T&> {
+ typedef T &type;
+};
+
+template<typename T, typename U>
+struct is_same {
+ static const bool value = false;
+};
+
+template<typename T>
+struct is_same<T, T> {
+ static const bool value = true;
+};
+
+template<typename T>
+class reference_wrapper {
+ T *ptr;
+
+public:
+ reference_wrapper(T& t) : ptr(&t) { }
+ operator T&() const { return *ptr; }
+};
+
+template<typename T> reference_wrapper<T> ref(T& t) {
+ return reference_wrapper<T>(t);
+}
+template<typename T> reference_wrapper<const T> cref(const T& t) {
+ return reference_wrapper<const T>(t);
+}
+
+template<typename... Values> class tuple;
+
+// Basis case: zero-length tuple
+template<> class tuple<> { };
+
+template<typename Head, typename... Tail>
+class tuple<Head, Tail...> : private tuple<Tail...> {
+ typedef tuple<Tail...> inherited;
+
+public:
+ tuple() { }
+ // implicit copy-constructor is okay
+
+ // Construct tuple from separate arguments.
+ tuple(typename add_const_reference<Head>::type v,
+ typename add_const_reference<Tail>::type... vtail)
+ : m_head(v), inherited(vtail...) { }
+
+ // Construct tuple from another tuple.
+ template<typename... VValues> tuple(const tuple<VValues...>& other)
+ : m_head(other.head()), inherited(other.tail()) { }
+
+ template<typename... VValues> tuple&
+ operator=(const tuple<VValues...>& other) {
+ m_head = other.head();
+ tail() = other.tail();
+ return *this;
+ }
+
+ typename add_reference<Head>::type head() { return m_head; }
+ typename add_reference<const Head>::type head() const { return m_head; }
+ inherited& tail() { return *this; }
+ const inherited& tail() const { return *this; }
+
+protected:
+ Head m_head;
+};
+
+// Creation functions
+template<typename T>
+struct make_tuple_result {
+ typedef T type;
+};
+
+template<typename T>
+struct make_tuple_result<reference_wrapper<T> > {
+ typedef T& type;
+};
+
+template<typename... Values>
+tuple<typename make_tuple_result<Values>::type...>
+make_tuple(const Values&... values) {
+ return tuple<typename make_tuple_result<Values>::type...>(values...);
+}
+
+template<typename... Values>
+tuple<Values&...> tie(Values&... values) {
+ return tuple<Values&...>(values...);
+}
+
+// Helper classes
+template<typename Tuple> struct tuple_size;
+
+template<typename... Values> struct tuple_size<tuple<Values...> > {
+ static const int value = sizeof...(Values);
+};
+
+template<int I, typename Tuple> struct tuple_element;
+
+template<int I, typename Head, typename... Tail>
+struct tuple_element<I, tuple<Head, Tail...> > {
+ typedef typename tuple_element<I-1, tuple<Tail...> >::type type;
+};
+
+template<typename Head, typename... Tail>
+struct tuple_element<0, tuple<Head, Tail...> > {
+ typedef Head type;
+};
+
+// Element access
+template<int I, typename Tuple> class get_impl;
+template<int I, typename Head, typename... Values>
+class get_impl<I, tuple<Head, Values...> > {
+ typedef typename tuple_element<I-1, tuple<Values...> >::type Element;
+ typedef typename add_reference<Element>::type RJ;
+ typedef typename add_const_reference<Element>::type PJ;
+ typedef get_impl<I-1, tuple<Values...> > Next;
+public:
+ static RJ get(tuple<Head, Values...>& t) { return Next::get(t.tail()); }
+ static PJ get(const tuple<Head, Values...>& t) { return Next::get(t.tail()); }
+};
+
+template<typename Head, typename... Values>
+class get_impl<0, tuple<Head, Values...> > {
+ typedef typename add_reference<Head>::type RJ;
+ typedef typename add_const_reference<Head>::type PJ;
+public:
+ static RJ get(tuple<Head, Values...>& t) { return t.head(); }
+ static PJ get(const tuple<Head, Values...>& t) { return t.head(); }
+};
+
+template<int I, typename... Values> typename add_reference<
+typename tuple_element<I, tuple<Values...> >::type >::type
+get(tuple<Values...>& t) {
+ return get_impl<I, tuple<Values...> >::get(t);
+}
+
+template<int I, typename... Values> typename add_const_reference<
+typename tuple_element<I, tuple<Values...> >::type >::type
+get(const tuple<Values...>& t) {
+ return get_impl<I, tuple<Values...> >::get(t);
+}
+
+// Relational operators
+inline bool operator==(const tuple<>&, const tuple<>&) { return true; }
+
+template<typename T, typename... TTail, typename U, typename... UTail>
+bool operator==(const tuple<T, TTail...>& t, const tuple<U, UTail...>& u) {
+ return t.head() == u.head() && t.tail() == u.tail();
+}
+
+template<typename... TValues, typename... UValues>
+bool operator!=(const tuple<TValues...>& t, const tuple<UValues...>& u) {
+ return !(t == u);
+}
+
+inline bool operator<(const tuple<>&, const tuple<>&) { return false; }
+
+template<typename T, typename... TTail, typename U, typename... UTail>
+bool operator<(const tuple<T, TTail...>& t, const tuple<U, UTail...>& u) {
+ return (t.head() < u.head() || (!(t.head() < u.head()) && t.tail() < u.tail()));
+}
+
+template<typename... TValues, typename... UValues>
+bool operator>(const tuple<TValues...>& t, const tuple<UValues...>& u) {
+ return u < t;
+}
+
+template<typename... TValues, typename... UValues>
+bool operator<=(const tuple<TValues...>& t, const tuple<UValues...>& u) {
+ return !(u < t);
+}
+
+template<typename... TValues, typename... UValues>
+bool operator>=(const tuple<TValues...>& t, const tuple<UValues...>& u) {
+ return !(t < u);
+}
+
+// make_indices helper
+template<int...> struct int_tuple {};
+// make_indexes impl is a helper for make_indexes
+template<int I, typename IntTuple, typename... Types> struct make_indexes_impl;
+
+template<int I, int... Indexes, typename T, typename... Types>
+struct make_indexes_impl<I, int_tuple<Indexes...>, T, Types...> {
+ typedef typename make_indexes_impl<I+1, int_tuple<Indexes..., I>, Types...>::type type;
+};
+
+template<int I, int... Indexes>
+struct make_indexes_impl<I, int_tuple<Indexes...> > {
+ typedef int_tuple<Indexes...> type;
+};
+
+template<typename... Types>
+struct make_indexes : make_indexes_impl<0, int_tuple<>, Types...> {
+};
+
+// Bind
+template<typename T> struct is_bind_expression {
+ static const bool value = false;
+};
+
+template<typename T> struct is_placeholder {
+ static const int value = 0;
+};
+
+
+template<typename F, typename... BoundArgs> class bound_functor {
+ typedef typename make_indexes<BoundArgs...>::type indexes;
+public:
+ typedef typename F::result_type result_type;
+ explicit bound_functor(const F& f, const BoundArgs&... bound_args)
+ : f(f), bound_args(bound_args...) { } template<typename... Args>
+ typename F::result_type operator()(Args&... args);
+private: F f;
+ tuple<BoundArgs...> bound_args;
+};
+
+template<typename F, typename... BoundArgs>
+inline bound_functor<F, BoundArgs...> bind(const F& f, const BoundArgs&... bound_args) {
+ return bound_functor<F, BoundArgs...>(f, bound_args...);
+}
+
+template<typename F, typename ...BoundArgs>
+struct is_bind_expression<bound_functor<F, BoundArgs...> > {
+ static const bool value = true;
+};
+
+// enable_if helper
+template<bool Cond, typename T = void>
+struct enable_if;
+
+template<typename T>
+struct enable_if<true, T> {
+ typedef T type;
+};
+
+template<typename T>
+struct enable_if<false, T> { };
+
+// safe_tuple_element helper
+template<int I, typename Tuple, typename = void>
+struct safe_tuple_element { };
+
+template<int I, typename... Values>
+struct safe_tuple_element<I, tuple<Values...>,
+ typename enable_if<(I >= 0 && I < tuple_size<tuple<Values...> >::value)>::type> {
+ typedef typename tuple_element<I, tuple<Values...> >::type type;
+};
+
+// mu
+template<typename Bound, typename... Args>
+inline typename safe_tuple_element<is_placeholder<Bound>::value -1,
+ tuple<Args...> >::type
+mu(Bound& bound_arg, const tuple<Args&...>& args) {
+ return get<is_placeholder<Bound>::value-1>(args);
+}
+
+template<typename T, typename... Args>
+inline T& mu(reference_wrapper<T>& bound_arg, const tuple<Args&...>&) {
+ return bound_arg.get();
+}
+
+template<typename F, int... Indexes, typename... Args>
+inline typename F::result_type
+unwrap_and_forward(F& f, int_tuple<Indexes...>, const tuple<Args&...>& args) {
+ return f(get<Indexes>(args)...);
+}
+
+template<typename Bound, typename... Args>
+inline typename enable_if<is_bind_expression<Bound>::value,
+ typename Bound::result_type>::type
+mu(Bound& bound_arg, const tuple<Args&...>& args) {
+ typedef typename make_indexes<Args...>::type Indexes;
+ return unwrap_and_forward(bound_arg, Indexes(), args);
+}
+
+template<typename T>
+struct is_reference_wrapper {
+ static const bool value = false;
+};
+
+template<typename T>
+struct is_reference_wrapper<reference_wrapper<T>> {
+ static const bool value = true;
+};
+
+template<typename Bound, typename... Args>
+inline typename enable_if<(!is_bind_expression<Bound>::value
+ && !is_placeholder<Bound>::value
+ && !is_reference_wrapper<Bound>::value),
+ Bound&>::type
+mu(Bound& bound_arg, const tuple<Args&...>&) {
+ return bound_arg;
+}
+
+template<typename F, typename... BoundArgs, int... Indexes, typename... Args>
+typename F::result_type apply_functor(F& f, tuple<BoundArgs...>& bound_args,
+ int_tuple<Indexes...>,
+ const tuple<Args&...>& args) {
+ return f(mu(get<Indexes>(bound_args), args)...);
+}
+
+template<typename F, typename... BoundArgs>
+template<typename... Args>
+typename F::result_type bound_functor<F, BoundArgs...>::operator()(Args&... args) {
+ return apply_functor(f, bound_args, indexes(), tie(args...));
+}
+
+template<int N> struct placeholder { };
+template<int N>
+struct is_placeholder<placeholder<N>> {
+ static const int value = N;
+};
+
+template<typename T>
+struct plus {
+ typedef T result_type;
+
+ T operator()(T x, T y) { return x + y; }
+};
+
+placeholder<1> _1;
+
+// Test bind
+void test_bind() {
+ int x = 17;
+ int y = 25;
+ bind(plus<int>(), x, _1)(y);
+}
Propchange: cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/example-bind.cpp
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/example-bind.cpp
------------------------------------------------------------------------------
svn:keywords = Id
Propchange: cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/example-bind.cpp
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified: cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/example-tuple.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/example-tuple.cpp?rev=123163&r1=123162&r2=123163&view=diff
==============================================================================
--- cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/example-tuple.cpp (original)
+++ cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/example-tuple.cpp Mon Jan 10 01:32:04 2011
@@ -206,9 +206,6 @@
return get_impl<I, tuple<Values...> >::get(t);
}
-#if 0
-// FIXME: Not yet functional, because we aren't currently able to
-// extend a partially-explicitly-specified parameter pack.
void test_element_access(tuple<int*, float*, double*&> t3) {
int i;
float f;
@@ -217,7 +214,6 @@
get<1>(t3) = &f;
get<2>(t3) = &d;
}
-#endif
// Relational operators
inline bool operator==(const tuple<>&, const tuple<>&) { return true; }
Modified: cfe/trunk/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p9-0x.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p9-0x.cpp?rev=123163&r1=123162&r2=123163&view=diff
==============================================================================
--- cfe/trunk/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p9-0x.cpp (original)
+++ cfe/trunk/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p9-0x.cpp Mon Jan 10 01:32:04 2011
@@ -35,13 +35,11 @@
// Template argument deduction can extend the sequence of template
// arguments corresponding to a template parameter pack, even when the
// sequence contains explicitly specified template arguments.
-// FIXME: Actually test what this paragraph specifies.
-#if 0
-void test_explicit_spec_extension() {
+void test_explicit_spec_extension(double *dp) {
int *ip1 = first_arg<int *>(0, 0);
int *ip2 = first_arg<int *, float*>(0, 0, 0, 0);
float *fp1 = first_arg<float *, double*, int*>(0, 0, 0);
- int i1 = second_arg<float *>(0, 0, 0);
+ int *i1 = second_arg<float *>(0, (int*)0, 0);
+ double *dp1 = first_arg<>(dp);
}
-#endif
More information about the cfe-commits
mailing list