r352486 - Re-commit "[AST] Introduce GenericSelectionExpr::Association"
Bruno Ricci via cfe-commits
cfe-commits at lists.llvm.org
Tue Jan 29 04:57:11 PST 2019
Author: brunoricci
Date: Tue Jan 29 04:57:11 2019
New Revision: 352486
URL: http://llvm.org/viewvc/llvm-project?rev=352486&view=rev
Log:
Re-commit "[AST] Introduce GenericSelectionExpr::Association"
This time with a fix to make gcc 4.8 happy.
Modified:
cfe/trunk/include/clang/AST/Expr.h
cfe/trunk/include/clang/AST/RecursiveASTVisitor.h
cfe/trunk/include/clang/AST/StmtDataCollectors.td
cfe/trunk/lib/AST/ASTDumper.cpp
cfe/trunk/lib/AST/StmtPrinter.cpp
cfe/trunk/lib/AST/StmtProfile.cpp
cfe/trunk/lib/Sema/SemaExprObjC.cpp
cfe/trunk/lib/Sema/SemaPseudoObject.cpp
cfe/trunk/lib/Sema/TreeTransform.h
Modified: cfe/trunk/include/clang/AST/Expr.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Expr.h?rev=352486&r1=352485&r2=352486&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Expr.h (original)
+++ cfe/trunk/include/clang/AST/Expr.h Tue Jan 29 04:57:11 2019
@@ -28,6 +28,8 @@
#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"
@@ -5052,6 +5054,86 @@ class GenericSelectionExpr final
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; FIXME: Once support for gcc 4.8 is dropped.
+ TSIPtrPtrTy TSI; // 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() : E(nullptr), TSI(nullptr) {}
+ 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,
@@ -5092,6 +5174,14 @@ public:
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; }
@@ -5135,23 +5225,43 @@ public:
return {getTrailingObjects<TypeSourceInfo *>(), NumAssocs};
}
- 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();
+ /// 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);
}
SourceLocation getGenericLoc() const {
Modified: cfe/trunk/include/clang/AST/RecursiveASTVisitor.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/RecursiveASTVisitor.h?rev=352486&r1=352485&r2=352486&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/RecursiveASTVisitor.h (original)
+++ cfe/trunk/include/clang/AST/RecursiveASTVisitor.h Tue Jan 29 04:57:11 2019
@@ -2301,10 +2301,10 @@ bool RecursiveASTVisitor<Derived>::Trave
// generic associations).
DEF_TRAVERSE_STMT(GenericSelectionExpr, {
TRY_TO(TraverseStmt(S->getControllingExpr()));
- for (unsigned i = 0; i != S->getNumAssocs(); ++i) {
- if (TypeSourceInfo *TS = S->getAssocTypeSourceInfo(i))
- TRY_TO(TraverseTypeLoc(TS->getTypeLoc()));
- TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getAssocExpr(i));
+ for (const GenericSelectionExpr::Association &Assoc : S->associations()) {
+ if (TypeSourceInfo *TSI = Assoc.getTypeSourceInfo())
+ TRY_TO(TraverseTypeLoc(TSI->getTypeLoc()));
+ TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(Assoc.getAssociationExpr());
}
ShouldVisitChildren = false;
})
Modified: cfe/trunk/include/clang/AST/StmtDataCollectors.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/StmtDataCollectors.td?rev=352486&r1=352485&r2=352486&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/StmtDataCollectors.td (original)
+++ cfe/trunk/include/clang/AST/StmtDataCollectors.td Tue Jan 29 04:57:11 2019
@@ -189,8 +189,8 @@ class CXXFoldExpr {
}
class GenericSelectionExpr {
code Code = [{
- for (unsigned i = 0; i < S->getNumAssocs(); ++i) {
- addData(S->getAssocType(i));
+ for (const GenericSelectionExpr::ConstAssociation &Assoc : S->associations()) {
+ addData(Assoc.getType());
}
}];
}
Modified: cfe/trunk/lib/AST/ASTDumper.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTDumper.cpp?rev=352486&r1=352485&r2=352486&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTDumper.cpp (original)
+++ cfe/trunk/lib/AST/ASTDumper.cpp Tue Jan 29 04:57:11 2019
@@ -1462,21 +1462,21 @@ void ASTDumper::VisitGenericSelectionExp
dumpStmt(E->getControllingExpr());
dumpTypeAsChild(E->getControllingExpr()->getType()); // FIXME: remove
- for (unsigned I = 0, N = E->getNumAssocs(); I != N; ++I) {
+ for (const auto &Assoc : E->associations()) {
dumpChild([=] {
- if (const TypeSourceInfo *TSI = E->getAssocTypeSourceInfo(I)) {
+ if (const TypeSourceInfo *TSI = Assoc.getTypeSourceInfo()) {
OS << "case ";
NodeDumper.dumpType(TSI->getType());
} else {
OS << "default";
}
- if (!E->isResultDependent() && E->getResultIndex() == I)
+ if (Assoc.isSelected())
OS << " selected";
- if (const TypeSourceInfo *TSI = E->getAssocTypeSourceInfo(I))
+ if (const TypeSourceInfo *TSI = Assoc.getTypeSourceInfo())
dumpTypeAsChild(TSI->getType());
- dumpStmt(E->getAssocExpr(I));
+ dumpStmt(Assoc.getAssociationExpr());
});
}
}
Modified: cfe/trunk/lib/AST/StmtPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtPrinter.cpp?rev=352486&r1=352485&r2=352486&view=diff
==============================================================================
--- cfe/trunk/lib/AST/StmtPrinter.cpp (original)
+++ cfe/trunk/lib/AST/StmtPrinter.cpp Tue Jan 29 04:57:11 2019
@@ -1261,15 +1261,15 @@ void StmtPrinter::VisitUnaryExprOrTypeTr
void StmtPrinter::VisitGenericSelectionExpr(GenericSelectionExpr *Node) {
OS << "_Generic(";
PrintExpr(Node->getControllingExpr());
- for (unsigned i = 0; i != Node->getNumAssocs(); ++i) {
+ for (const GenericSelectionExpr::Association &Assoc : Node->associations()) {
OS << ", ";
- QualType T = Node->getAssocType(i);
+ QualType T = Assoc.getType();
if (T.isNull())
OS << "default";
else
T.print(OS, Policy);
OS << ": ";
- PrintExpr(Node->getAssocExpr(i));
+ PrintExpr(Assoc.getAssociationExpr());
}
OS << ")";
}
Modified: cfe/trunk/lib/AST/StmtProfile.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtProfile.cpp?rev=352486&r1=352485&r2=352486&view=diff
==============================================================================
--- cfe/trunk/lib/AST/StmtProfile.cpp (original)
+++ cfe/trunk/lib/AST/StmtProfile.cpp Tue Jan 29 04:57:11 2019
@@ -1260,13 +1260,14 @@ void StmtProfiler::VisitBlockExpr(const
void StmtProfiler::VisitGenericSelectionExpr(const GenericSelectionExpr *S) {
VisitExpr(S);
- for (unsigned i = 0; i != S->getNumAssocs(); ++i) {
- QualType T = S->getAssocType(i);
+ for (const GenericSelectionExpr::ConstAssociation &Assoc :
+ S->associations()) {
+ QualType T = Assoc.getType();
if (T.isNull())
ID.AddPointer(nullptr);
else
VisitType(T);
- VisitExpr(S->getAssocExpr(i));
+ VisitExpr(Assoc.getAssociationExpr());
}
}
Modified: cfe/trunk/lib/Sema/SemaExprObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprObjC.cpp?rev=352486&r1=352485&r2=352486&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprObjC.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprObjC.cpp Tue Jan 29 04:57:11 2019
@@ -4332,14 +4332,16 @@ Expr *Sema::stripARCUnbridgedCast(Expr *
assert(!gse->isResultDependent());
unsigned n = gse->getNumAssocs();
- SmallVector<Expr*, 4> subExprs(n);
- SmallVector<TypeSourceInfo*, 4> subTypes(n);
- for (unsigned i = 0; i != n; ++i) {
- subTypes[i] = gse->getAssocTypeSourceInfo(i);
- Expr *sub = gse->getAssocExpr(i);
- if (i == gse->getResultIndex())
+ SmallVector<Expr *, 4> subExprs;
+ SmallVector<TypeSourceInfo *, 4> subTypes;
+ subExprs.reserve(n);
+ subTypes.reserve(n);
+ for (const GenericSelectionExpr::Association &assoc : gse->associations()) {
+ subTypes.push_back(assoc.getTypeSourceInfo());
+ Expr *sub = assoc.getAssociationExpr();
+ if (assoc.isSelected())
sub = stripARCUnbridgedCast(sub);
- subExprs[i] = sub;
+ subExprs.push_back(sub);
}
return GenericSelectionExpr::Create(
Modified: cfe/trunk/lib/Sema/SemaPseudoObject.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaPseudoObject.cpp?rev=352486&r1=352485&r2=352486&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaPseudoObject.cpp (original)
+++ cfe/trunk/lib/Sema/SemaPseudoObject.cpp Tue Jan 29 04:57:11 2019
@@ -140,19 +140,23 @@ namespace {
unsigned resultIndex = gse->getResultIndex();
unsigned numAssocs = gse->getNumAssocs();
- SmallVector<Expr*, 8> assocs(numAssocs);
- SmallVector<TypeSourceInfo*, 8> assocTypes(numAssocs);
+ SmallVector<Expr *, 8> assocExprs;
+ SmallVector<TypeSourceInfo *, 8> assocTypes;
+ assocExprs.reserve(numAssocs);
+ assocTypes.reserve(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);
+ 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());
}
return GenericSelectionExpr::Create(
S.Context, gse->getGenericLoc(), gse->getControllingExpr(),
- assocTypes, assocs, gse->getDefaultLoc(), gse->getRParenLoc(),
+ assocTypes, assocExprs, gse->getDefaultLoc(), gse->getRParenLoc(),
gse->containsUnexpandedParameterPack(), resultIndex);
}
Modified: cfe/trunk/lib/Sema/TreeTransform.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=352486&r1=352485&r2=352486&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/TreeTransform.h (original)
+++ cfe/trunk/lib/Sema/TreeTransform.h Tue Jan 29 04:57:11 2019
@@ -9073,10 +9073,10 @@ TreeTransform<Derived>::TransformGeneric
SmallVector<Expr *, 4> AssocExprs;
SmallVector<TypeSourceInfo *, 4> AssocTypes;
- for (unsigned i = 0; i != E->getNumAssocs(); ++i) {
- TypeSourceInfo *TS = E->getAssocTypeSourceInfo(i);
- if (TS) {
- TypeSourceInfo *AssocType = getDerived().TransformType(TS);
+ for (const GenericSelectionExpr::Association &Assoc : E->associations()) {
+ TypeSourceInfo *TSI = Assoc.getTypeSourceInfo();
+ if (TSI) {
+ TypeSourceInfo *AssocType = getDerived().TransformType(TSI);
if (!AssocType)
return ExprError();
AssocTypes.push_back(AssocType);
@@ -9084,7 +9084,8 @@ TreeTransform<Derived>::TransformGeneric
AssocTypes.push_back(nullptr);
}
- ExprResult AssocExpr = getDerived().TransformExpr(E->getAssocExpr(i));
+ ExprResult AssocExpr =
+ getDerived().TransformExpr(Assoc.getAssociationExpr());
if (AssocExpr.isInvalid())
return ExprError();
AssocExprs.push_back(AssocExpr.get());
More information about the cfe-commits
mailing list