#include "clang/Basic/TypeTraits.h"
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/APSInt.h"
-#include "llvm/ADT/iterator.h"
-#include "llvm/ADT/iterator_range.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/AtomicOrdering.h"
return getNumAssocs();
}
- template <bool Const> class AssociationIteratorTy;
- /// Bundle together an association expression and its TypeSourceInfo.
- /// The Const template parameter is for the const and non-const versions
- /// of AssociationTy.
- template <bool Const> class AssociationTy {
- friend class GenericSelectionExpr;
- template <bool OtherConst> friend class AssociationIteratorTy;
- using ExprPtrTy =
- typename std::conditional<Const, const Expr *, Expr *>::type;
- using TSIPtrTy = typename std::conditional<Const, const TypeSourceInfo *,
- TypeSourceInfo *>::type;
- ExprPtrTy E;
- TSIPtrTy TSI;
- bool Selected;
- AssociationTy(ExprPtrTy E, TSIPtrTy TSI, bool Selected)
- : E(E), TSI(TSI), Selected(Selected) {}
-
- public:
- ExprPtrTy getAssociationExpr() const { return E; }
- TSIPtrTy getTypeSourceInfo() const { return TSI; }
- QualType getType() const { return TSI ? TSI->getType() : QualType(); }
- bool isSelected() const { return Selected; }
- AssociationTy *operator->() { return this; }
- const AssociationTy *operator->() const { return this; }
- }; // class AssociationTy
-
- /// Iterator over const and non-const Association objects. The Association
- /// objects are created on the fly when the iterator is dereferenced.
- /// This abstract over how exactly the association expressions and the
- /// corresponding TypeSourceInfo * are stored.
- template <bool Const>
- class AssociationIteratorTy
- : public llvm::iterator_facade_base<
- AssociationIteratorTy<Const>, std::input_iterator_tag,
- AssociationTy<Const>, std::ptrdiff_t, AssociationTy<Const>,
- AssociationTy<Const>> {
- friend class GenericSelectionExpr;
- // FIXME: This iterator could conceptually be a random access iterator, and
- // it would be nice if we could strengthen the iterator category someday.
- // However this iterator does not satisfy two requirements of forward
- // iterators:
- // a) reference = T& or reference = const T&
- // b) If It1 and It2 are both dereferenceable, then It1 == It2 if and only
- // if *It1 and *It2 are bound to the same objects.
- // An alternative design approach was discussed during review;
- // store an Association object inside the iterator, and return a reference
- // to it when dereferenced. This idea was discarded beacuse of nasty
- // lifetime issues:
- // AssociationIterator It = ...;
- // const Association &Assoc = *It++; // Oops, Assoc is dangling.
- using BaseTy = typename AssociationIteratorTy::iterator_facade_base;
- using StmtPtrPtrTy =
- typename std::conditional<Const, const Stmt *const *, Stmt **>::type;
- using TSIPtrPtrTy =
- typename std::conditional<Const, const TypeSourceInfo *const *,
- TypeSourceInfo **>::type;
- StmtPtrPtrTy E = nullptr;
- TSIPtrPtrTy TSI = nullptr; // Kept in sync with E.
- unsigned Offset = 0, SelectedOffset = 0;
- AssociationIteratorTy(StmtPtrPtrTy E, TSIPtrPtrTy TSI, unsigned Offset,
- unsigned SelectedOffset)
- : E(E), TSI(TSI), Offset(Offset), SelectedOffset(SelectedOffset) {}
-
- public:
- AssociationIteratorTy() = default;
- typename BaseTy::reference operator*() const {
- return AssociationTy<Const>(cast<Expr>(*E), *TSI,
- Offset == SelectedOffset);
- }
- typename BaseTy::pointer operator->() const { return **this; }
- using BaseTy::operator++;
- AssociationIteratorTy &operator++() {
- ++E;
- ++TSI;
- ++Offset;
- return *this;
- }
- bool operator==(AssociationIteratorTy Other) const { return E == Other.E; }
- }; // class AssociationIterator
-
/// Build a non-result-dependent generic selection expression.
GenericSelectionExpr(const ASTContext &Context, SourceLocation GenericLoc,
Expr *ControllingExpr,
static GenericSelectionExpr *CreateEmpty(const ASTContext &Context,
unsigned NumAssocs);
- using Association = AssociationTy<false>;
- using ConstAssociation = AssociationTy<true>;
- using AssociationIterator = AssociationIteratorTy<false>;
- using ConstAssociationIterator = AssociationIteratorTy<true>;
- using association_range = llvm::iterator_range<AssociationIterator>;
- using const_association_range =
- llvm::iterator_range<ConstAssociationIterator>;
-
/// The number of association expressions.
unsigned getNumAssocs() const { return NumAssocs; }
return {getTrailingObjects<TypeSourceInfo *>(), NumAssocs};
}
- /// Return the Ith association expression with its TypeSourceInfo,
- /// bundled together in GenericSelectionExpr::(Const)Association.
- Association getAssociation(unsigned I) {
- assert(I < getNumAssocs() &&
- "Out-of-range index in GenericSelectionExpr::getAssociation!");
- return Association(
- cast<Expr>(getTrailingObjects<Stmt *>()[AssocExprStartIndex + I]),
- getTrailingObjects<TypeSourceInfo *>()[I],
- !isResultDependent() && (getResultIndex() == I));
- }
- ConstAssociation getAssociation(unsigned I) const {
- assert(I < getNumAssocs() &&
- "Out-of-range index in GenericSelectionExpr::getAssociation!");
- return ConstAssociation(
- cast<Expr>(getTrailingObjects<Stmt *>()[AssocExprStartIndex + I]),
- getTrailingObjects<TypeSourceInfo *>()[I],
- !isResultDependent() && (getResultIndex() == I));
- }
-
- association_range associations() {
- AssociationIterator Begin(getTrailingObjects<Stmt *>() +
- AssocExprStartIndex,
- getTrailingObjects<TypeSourceInfo *>(),
- /*Offset=*/0, ResultIndex);
- AssociationIterator End(Begin.E + NumAssocs, Begin.TSI + NumAssocs,
- /*Offset=*/NumAssocs, ResultIndex);
- return llvm::make_range(Begin, End);
- }
-
- const_association_range associations() const {
- ConstAssociationIterator Begin(getTrailingObjects<Stmt *>() +
- AssocExprStartIndex,
- getTrailingObjects<TypeSourceInfo *>(),
- /*Offset=*/0, ResultIndex);
- ConstAssociationIterator End(Begin.E + NumAssocs, Begin.TSI + NumAssocs,
- /*Offset=*/NumAssocs, ResultIndex);
- return llvm::make_range(Begin, End);
+ Expr *getAssocExpr(unsigned i) {
+ return cast<Expr>(getTrailingObjects<Stmt *>()[AssocExprStartIndex + i]);
+ }
+ const Expr *getAssocExpr(unsigned i) const {
+ return cast<Expr>(getTrailingObjects<Stmt *>()[AssocExprStartIndex + i]);
+ }
+
+ TypeSourceInfo *getAssocTypeSourceInfo(unsigned i) {
+ return getTrailingObjects<TypeSourceInfo *>()[i];
+ }
+ const TypeSourceInfo *getAssocTypeSourceInfo(unsigned i) const {
+ return getTrailingObjects<TypeSourceInfo *>()[i];
+ }
+
+ QualType getAssocType(unsigned i) const {
+ const TypeSourceInfo *TSI = getAssocTypeSourceInfo(i);
+ return TSI ? TSI->getType() : QualType();
}
SourceLocation getGenericLoc() const {
unsigned resultIndex = gse->getResultIndex();
unsigned numAssocs = gse->getNumAssocs();
- SmallVector<Expr *, 8> assocExprs;
- SmallVector<TypeSourceInfo *, 8> assocTypes;
- assocExprs.reserve(numAssocs);
- assocTypes.reserve(numAssocs);
-
- for (const GenericSelectionExpr::Association &assoc :
- gse->associations()) {
- Expr *assocExpr = assoc.getAssociationExpr();
- if (assoc.isSelected())
- assocExpr = rebuild(assocExpr);
- assocExprs.push_back(assocExpr);
- assocTypes.push_back(assoc.getTypeSourceInfo());
+ SmallVector<Expr*, 8> assocs(numAssocs);
+ SmallVector<TypeSourceInfo*, 8> assocTypes(numAssocs);
+
+ for (unsigned i = 0; i != numAssocs; ++i) {
+ Expr *assoc = gse->getAssocExpr(i);
+ if (i == resultIndex) assoc = rebuild(assoc);
+ assocs[i] = assoc;
+ assocTypes[i] = gse->getAssocTypeSourceInfo(i);
}
return GenericSelectionExpr::Create(
S.Context, gse->getGenericLoc(), gse->getControllingExpr(),
- assocTypes, assocExprs, gse->getDefaultLoc(), gse->getRParenLoc(),
+ assocTypes, assocs, gse->getDefaultLoc(), gse->getRParenLoc(),
gse->containsUnexpandedParameterPack(), resultIndex);
}