Further refactoring of the tree transformation for template argument

lists, so that all such transformations go through a single,
iterator-based transformation function. This is the only place where
we need to implement the logic for transforming pack expansions whose
pattern is a template argument.

Unfortunately, the new cases this refactoring brings into the fold
can't be meaningfully tested yet. We need template argument deduction
to work well enough for variadic function templates first.

llvm-svn: 122289
This commit is contained in:
Douglas Gregor 2010-12-20 23:36:19 +00:00
parent 9be3ec6264
commit fe921a79f3
1 changed files with 164 additions and 42 deletions

View File

@ -344,6 +344,10 @@ public:
/// in the input set using \c TransformTemplateArgument(), and appends /// in the input set using \c TransformTemplateArgument(), and appends
/// the transformed arguments to the output list. /// the transformed arguments to the output list.
/// ///
/// Note that this overload of \c TransformTemplateArguments() is merely
/// a convenience function. Subclasses that wish to override this behavior
/// should override the iterator-based member template version.
///
/// \param Inputs The set of template arguments to be transformed. /// \param Inputs The set of template arguments to be transformed.
/// ///
/// \param NumInputs The number of template arguments in \p Inputs. /// \param NumInputs The number of template arguments in \p Inputs.
@ -354,7 +358,9 @@ public:
/// Returns true if an error occurred. /// Returns true if an error occurred.
bool TransformTemplateArguments(const TemplateArgumentLoc *Inputs, bool TransformTemplateArguments(const TemplateArgumentLoc *Inputs,
unsigned NumInputs, unsigned NumInputs,
TemplateArgumentListInfo &Outputs); TemplateArgumentListInfo &Outputs) {
return TransformTemplateArguments(Inputs, Inputs + NumInputs, Outputs);
}
/// \brief Transform the given set of template arguments. /// \brief Transform the given set of template arguments.
/// ///
@ -362,17 +368,18 @@ public:
/// in the input set using \c TransformTemplateArgument(), and appends /// in the input set using \c TransformTemplateArgument(), and appends
/// the transformed arguments to the output list. /// the transformed arguments to the output list.
/// ///
/// \param Inputs The set of template arguments to be transformed. The /// \param First An iterator to the first template argument.
/// \c getArgLoc() function will be invoked on each argument indexed, while ///
/// the number of arguments is determined via \c getNumArgs(). /// \param Last An iterator one step past the last template argument.
/// ///
/// \param Outputs The set of transformed template arguments output by this /// \param Outputs The set of transformed template arguments output by this
/// routine. /// routine.
/// ///
/// Returns true if an error occurred. /// Returns true if an error occurred.
template<typename InputsType> template<typename InputIterator>
bool TransformTemplateArgumentsFromArgLoc(const InputsType &Inputs, bool TransformTemplateArguments(InputIterator First,
TemplateArgumentListInfo &Outputs); InputIterator Last,
TemplateArgumentListInfo &Outputs);
/// \brief Fakes up a TemplateArgumentLoc for a given TemplateArgument. /// \brief Fakes up a TemplateArgumentLoc for a given TemplateArgument.
void InventTemplateArgumentLoc(const TemplateArgument &Arg, void InventTemplateArgumentLoc(const TemplateArgument &Arg,
@ -2507,50 +2514,89 @@ bool TreeTransform<Derived>::TransformTemplateArgument(
return true; return true;
} }
template<typename Derived> /// \brief Iterator adaptor that invents template argument location information
bool TreeTransform<Derived>::TransformTemplateArguments( /// for each of the template arguments in its underlying iterator.
const TemplateArgumentLoc *Inputs, template<typename Derived, typename InputIterator>
unsigned NumInputs, class TemplateArgumentLocInventIterator {
TemplateArgumentListInfo &Outputs) { TreeTransform<Derived> &Self;
for (unsigned I = 0; I != NumInputs; ++I) { InputIterator Iter;
TemplateArgumentLoc Out;
if (getDerived().TransformTemplateArgument(Inputs[I], Out)) public:
return true; typedef TemplateArgumentLoc value_type;
typedef TemplateArgumentLoc reference;
typedef typename std::iterator_traits<InputIterator>::difference_type
difference_type;
typedef std::input_iterator_tag iterator_category;
class pointer {
TemplateArgumentLoc Arg;
Outputs.addArgument(Out); public:
explicit pointer(TemplateArgumentLoc Arg) : Arg(Arg) { }
const TemplateArgumentLoc *operator->() const { return &Arg; }
};
TemplateArgumentLocInventIterator() { }
explicit TemplateArgumentLocInventIterator(TreeTransform<Derived> &Self,
InputIterator Iter)
: Self(Self), Iter(Iter) { }
TemplateArgumentLocInventIterator &operator++() {
++Iter;
return *this;
} }
return false; TemplateArgumentLocInventIterator operator++(int) {
} TemplateArgumentLocInventIterator Old(*this);
++(*this);
return Old;
}
reference operator*() const {
TemplateArgumentLoc Result;
Self.InventTemplateArgumentLoc(*Iter, Result);
return Result;
}
pointer operator->() const { return pointer(**this); }
friend bool operator==(const TemplateArgumentLocInventIterator &X,
const TemplateArgumentLocInventIterator &Y) {
return X.Iter == Y.Iter;
}
friend bool operator!=(const TemplateArgumentLocInventIterator &X,
const TemplateArgumentLocInventIterator &Y) {
return X.Iter != Y.Iter;
}
};
template<typename Derived> template<typename Derived>
template<typename InputsType> template<typename InputIterator>
bool TreeTransform<Derived>::TransformTemplateArgumentsFromArgLoc( bool TreeTransform<Derived>::TransformTemplateArguments(InputIterator First,
const InputsType &Inputs, InputIterator Last,
TemplateArgumentListInfo &Outputs) { TemplateArgumentListInfo &Outputs) {
for (unsigned I = 0, N = Inputs.getNumArgs(); I != N; ++I) { for (; First != Last; ++First) {
TemplateArgumentLoc Out; TemplateArgumentLoc Out;
TemplateArgumentLoc In = Inputs.getArgLoc(I); TemplateArgumentLoc In = *First;
if (In.getArgument().getKind() == TemplateArgument::Pack) { if (In.getArgument().getKind() == TemplateArgument::Pack) {
// Unpack argument packs, which we translate them into separate // Unpack argument packs, which we translate them into separate
// arguments. // arguments.
// FIXME: It would be far better to make this a recursive call using // FIXME: We could do much better if we could guarantee that the
// some kind of argument-pack adaptor. // TemplateArgumentLocInfo for the pack expansion would be usable for
for (TemplateArgument::pack_iterator P = In.getArgument().pack_begin(), // all of the template arguments in the argument pack.
PEnd = In.getArgument().pack_end(); typedef TemplateArgumentLocInventIterator<Derived,
P != PEnd; ++P) { TemplateArgument::pack_iterator>
TemplateArgumentLoc PLoc; PackLocIterator;
if (TransformTemplateArguments(PackLocIterator(*this,
// FIXME: We could do much better if we could guarantee that the In.getArgument().pack_begin()),
// TemplateArgumentLocInfo for the pack expansion would be usable for PackLocIterator(*this,
// all of the template arguments in the argument pack. In.getArgument().pack_end()),
getDerived().InventTemplateArgumentLoc(*P, PLoc); Outputs))
if (getDerived().TransformTemplateArgument(PLoc, Out)) return true;
return true;
Outputs.addArgument(Out);
}
continue; continue;
} }
@ -3528,6 +3574,73 @@ QualType TreeTransform<Derived>::TransformTemplateSpecializationType(
return getDerived().TransformTemplateSpecializationType(TLB, TL, Template); return getDerived().TransformTemplateSpecializationType(TLB, TL, Template);
} }
namespace {
/// \brief Simple iterator that traverses the template arguments in a
/// container that provides a \c getArgLoc() member function.
///
/// This iterator is intended to be used with the iterator form of
/// \c TreeTransform<Derived>::TransformTemplateArguments().
template<typename ArgLocContainer>
class TemplateArgumentLocContainerIterator {
ArgLocContainer *Container;
unsigned Index;
public:
typedef TemplateArgumentLoc value_type;
typedef TemplateArgumentLoc reference;
typedef int difference_type;
typedef std::input_iterator_tag iterator_category;
class pointer {
TemplateArgumentLoc Arg;
public:
explicit pointer(TemplateArgumentLoc Arg) : Arg(Arg) { }
const TemplateArgumentLoc *operator->() const {
return &Arg;
}
};
TemplateArgumentLocContainerIterator() {}
TemplateArgumentLocContainerIterator(ArgLocContainer &Container,
unsigned Index)
: Container(&Container), Index(Index) { }
TemplateArgumentLocContainerIterator &operator++() {
++Index;
return *this;
}
TemplateArgumentLocContainerIterator operator++(int) {
TemplateArgumentLocContainerIterator Old(*this);
++(*this);
return Old;
}
TemplateArgumentLoc operator*() const {
return Container->getArgLoc(Index);
}
pointer operator->() const {
return pointer(Container->getArgLoc(Index));
}
friend bool operator==(const TemplateArgumentLocContainerIterator &X,
TemplateArgumentLocContainerIterator &Y) {
return X.Container == Y.Container && X.Index == Y.Index;
}
friend bool operator!=(const TemplateArgumentLocContainerIterator &X,
TemplateArgumentLocContainerIterator &Y) {
return !(X == Y);
}
};
}
template <typename Derived> template <typename Derived>
QualType TreeTransform<Derived>::TransformTemplateSpecializationType( QualType TreeTransform<Derived>::TransformTemplateSpecializationType(
TypeLocBuilder &TLB, TypeLocBuilder &TLB,
@ -3536,7 +3649,11 @@ QualType TreeTransform<Derived>::TransformTemplateSpecializationType(
TemplateArgumentListInfo NewTemplateArgs; TemplateArgumentListInfo NewTemplateArgs;
NewTemplateArgs.setLAngleLoc(TL.getLAngleLoc()); NewTemplateArgs.setLAngleLoc(TL.getLAngleLoc());
NewTemplateArgs.setRAngleLoc(TL.getRAngleLoc()); NewTemplateArgs.setRAngleLoc(TL.getRAngleLoc());
if (getDerived().TransformTemplateArgumentsFromArgLoc(TL, NewTemplateArgs)) typedef TemplateArgumentLocContainerIterator<TemplateSpecializationTypeLoc>
ArgIterator;
if (getDerived().TransformTemplateArguments(ArgIterator(TL, 0),
ArgIterator(TL, TL.getNumArgs()),
NewTemplateArgs))
return QualType(); return QualType();
// FIXME: maybe don't rebuild if all the template arguments are the same. // FIXME: maybe don't rebuild if all the template arguments are the same.
@ -3679,7 +3796,12 @@ QualType TreeTransform<Derived>::
TemplateArgumentListInfo NewTemplateArgs; TemplateArgumentListInfo NewTemplateArgs;
NewTemplateArgs.setLAngleLoc(TL.getLAngleLoc()); NewTemplateArgs.setLAngleLoc(TL.getLAngleLoc());
NewTemplateArgs.setRAngleLoc(TL.getRAngleLoc()); NewTemplateArgs.setRAngleLoc(TL.getRAngleLoc());
if (getDerived().TransformTemplateArgumentsFromArgLoc(TL, NewTemplateArgs))
typedef TemplateArgumentLocContainerIterator<
DependentTemplateSpecializationTypeLoc> ArgIterator;
if (getDerived().TransformTemplateArguments(ArgIterator(TL, 0),
ArgIterator(TL, TL.getNumArgs()),
NewTemplateArgs))
return QualType(); return QualType();
QualType Result QualType Result