forked from OSchip/llvm-project
Re-commit "[AST] Introduce GenericSelectionExpr::Association"
This time with a fix to make gcc 4.8 happy. llvm-svn: 352486
This commit is contained in:
parent
e30d87ecea
commit
1ec7fd35ce
|
@ -28,6 +28,8 @@
|
||||||
#include "clang/Basic/TypeTraits.h"
|
#include "clang/Basic/TypeTraits.h"
|
||||||
#include "llvm/ADT/APFloat.h"
|
#include "llvm/ADT/APFloat.h"
|
||||||
#include "llvm/ADT/APSInt.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/SmallVector.h"
|
||||||
#include "llvm/ADT/StringRef.h"
|
#include "llvm/ADT/StringRef.h"
|
||||||
#include "llvm/Support/AtomicOrdering.h"
|
#include "llvm/Support/AtomicOrdering.h"
|
||||||
|
@ -5052,6 +5054,86 @@ class GenericSelectionExpr final
|
||||||
return getNumAssocs();
|
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.
|
/// Build a non-result-dependent generic selection expression.
|
||||||
GenericSelectionExpr(const ASTContext &Context, SourceLocation GenericLoc,
|
GenericSelectionExpr(const ASTContext &Context, SourceLocation GenericLoc,
|
||||||
Expr *ControllingExpr,
|
Expr *ControllingExpr,
|
||||||
|
@ -5092,6 +5174,14 @@ public:
|
||||||
static GenericSelectionExpr *CreateEmpty(const ASTContext &Context,
|
static GenericSelectionExpr *CreateEmpty(const ASTContext &Context,
|
||||||
unsigned NumAssocs);
|
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.
|
/// The number of association expressions.
|
||||||
unsigned getNumAssocs() const { return NumAssocs; }
|
unsigned getNumAssocs() const { return NumAssocs; }
|
||||||
|
|
||||||
|
@ -5135,23 +5225,43 @@ public:
|
||||||
return {getTrailingObjects<TypeSourceInfo *>(), NumAssocs};
|
return {getTrailingObjects<TypeSourceInfo *>(), NumAssocs};
|
||||||
}
|
}
|
||||||
|
|
||||||
Expr *getAssocExpr(unsigned i) {
|
/// Return the Ith association expression with its TypeSourceInfo,
|
||||||
return cast<Expr>(getTrailingObjects<Stmt *>()[AssocExprStartIndex + i]);
|
/// 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));
|
||||||
}
|
}
|
||||||
const Expr *getAssocExpr(unsigned i) const {
|
ConstAssociation getAssociation(unsigned I) const {
|
||||||
return cast<Expr>(getTrailingObjects<Stmt *>()[AssocExprStartIndex + i]);
|
assert(I < getNumAssocs() &&
|
||||||
|
"Out-of-range index in GenericSelectionExpr::getAssociation!");
|
||||||
|
return ConstAssociation(
|
||||||
|
cast<Expr>(getTrailingObjects<Stmt *>()[AssocExprStartIndex + I]),
|
||||||
|
getTrailingObjects<TypeSourceInfo *>()[I],
|
||||||
|
!isResultDependent() && (getResultIndex() == I));
|
||||||
}
|
}
|
||||||
|
|
||||||
TypeSourceInfo *getAssocTypeSourceInfo(unsigned i) {
|
association_range associations() {
|
||||||
return getTrailingObjects<TypeSourceInfo *>()[i];
|
AssociationIterator Begin(getTrailingObjects<Stmt *>() +
|
||||||
}
|
AssocExprStartIndex,
|
||||||
const TypeSourceInfo *getAssocTypeSourceInfo(unsigned i) const {
|
getTrailingObjects<TypeSourceInfo *>(),
|
||||||
return getTrailingObjects<TypeSourceInfo *>()[i];
|
/*Offset=*/0, ResultIndex);
|
||||||
|
AssociationIterator End(Begin.E + NumAssocs, Begin.TSI + NumAssocs,
|
||||||
|
/*Offset=*/NumAssocs, ResultIndex);
|
||||||
|
return llvm::make_range(Begin, End);
|
||||||
}
|
}
|
||||||
|
|
||||||
QualType getAssocType(unsigned i) const {
|
const_association_range associations() const {
|
||||||
const TypeSourceInfo *TSI = getAssocTypeSourceInfo(i);
|
ConstAssociationIterator Begin(getTrailingObjects<Stmt *>() +
|
||||||
return TSI ? TSI->getType() : QualType();
|
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 {
|
SourceLocation getGenericLoc() const {
|
||||||
|
|
|
@ -2301,10 +2301,10 @@ bool RecursiveASTVisitor<Derived>::TraverseInitListExpr(
|
||||||
// generic associations).
|
// generic associations).
|
||||||
DEF_TRAVERSE_STMT(GenericSelectionExpr, {
|
DEF_TRAVERSE_STMT(GenericSelectionExpr, {
|
||||||
TRY_TO(TraverseStmt(S->getControllingExpr()));
|
TRY_TO(TraverseStmt(S->getControllingExpr()));
|
||||||
for (unsigned i = 0; i != S->getNumAssocs(); ++i) {
|
for (const GenericSelectionExpr::Association &Assoc : S->associations()) {
|
||||||
if (TypeSourceInfo *TS = S->getAssocTypeSourceInfo(i))
|
if (TypeSourceInfo *TSI = Assoc.getTypeSourceInfo())
|
||||||
TRY_TO(TraverseTypeLoc(TS->getTypeLoc()));
|
TRY_TO(TraverseTypeLoc(TSI->getTypeLoc()));
|
||||||
TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getAssocExpr(i));
|
TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(Assoc.getAssociationExpr());
|
||||||
}
|
}
|
||||||
ShouldVisitChildren = false;
|
ShouldVisitChildren = false;
|
||||||
})
|
})
|
||||||
|
|
|
@ -189,8 +189,8 @@ class CXXFoldExpr {
|
||||||
}
|
}
|
||||||
class GenericSelectionExpr {
|
class GenericSelectionExpr {
|
||||||
code Code = [{
|
code Code = [{
|
||||||
for (unsigned i = 0; i < S->getNumAssocs(); ++i) {
|
for (const GenericSelectionExpr::ConstAssociation &Assoc : S->associations()) {
|
||||||
addData(S->getAssocType(i));
|
addData(Assoc.getType());
|
||||||
}
|
}
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
|
|
@ -1462,21 +1462,21 @@ void ASTDumper::VisitGenericSelectionExpr(const GenericSelectionExpr *E) {
|
||||||
dumpStmt(E->getControllingExpr());
|
dumpStmt(E->getControllingExpr());
|
||||||
dumpTypeAsChild(E->getControllingExpr()->getType()); // FIXME: remove
|
dumpTypeAsChild(E->getControllingExpr()->getType()); // FIXME: remove
|
||||||
|
|
||||||
for (unsigned I = 0, N = E->getNumAssocs(); I != N; ++I) {
|
for (const auto &Assoc : E->associations()) {
|
||||||
dumpChild([=] {
|
dumpChild([=] {
|
||||||
if (const TypeSourceInfo *TSI = E->getAssocTypeSourceInfo(I)) {
|
if (const TypeSourceInfo *TSI = Assoc.getTypeSourceInfo()) {
|
||||||
OS << "case ";
|
OS << "case ";
|
||||||
NodeDumper.dumpType(TSI->getType());
|
NodeDumper.dumpType(TSI->getType());
|
||||||
} else {
|
} else {
|
||||||
OS << "default";
|
OS << "default";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!E->isResultDependent() && E->getResultIndex() == I)
|
if (Assoc.isSelected())
|
||||||
OS << " selected";
|
OS << " selected";
|
||||||
|
|
||||||
if (const TypeSourceInfo *TSI = E->getAssocTypeSourceInfo(I))
|
if (const TypeSourceInfo *TSI = Assoc.getTypeSourceInfo())
|
||||||
dumpTypeAsChild(TSI->getType());
|
dumpTypeAsChild(TSI->getType());
|
||||||
dumpStmt(E->getAssocExpr(I));
|
dumpStmt(Assoc.getAssociationExpr());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1261,15 +1261,15 @@ void StmtPrinter::VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *Node){
|
||||||
void StmtPrinter::VisitGenericSelectionExpr(GenericSelectionExpr *Node) {
|
void StmtPrinter::VisitGenericSelectionExpr(GenericSelectionExpr *Node) {
|
||||||
OS << "_Generic(";
|
OS << "_Generic(";
|
||||||
PrintExpr(Node->getControllingExpr());
|
PrintExpr(Node->getControllingExpr());
|
||||||
for (unsigned i = 0; i != Node->getNumAssocs(); ++i) {
|
for (const GenericSelectionExpr::Association &Assoc : Node->associations()) {
|
||||||
OS << ", ";
|
OS << ", ";
|
||||||
QualType T = Node->getAssocType(i);
|
QualType T = Assoc.getType();
|
||||||
if (T.isNull())
|
if (T.isNull())
|
||||||
OS << "default";
|
OS << "default";
|
||||||
else
|
else
|
||||||
T.print(OS, Policy);
|
T.print(OS, Policy);
|
||||||
OS << ": ";
|
OS << ": ";
|
||||||
PrintExpr(Node->getAssocExpr(i));
|
PrintExpr(Assoc.getAssociationExpr());
|
||||||
}
|
}
|
||||||
OS << ")";
|
OS << ")";
|
||||||
}
|
}
|
||||||
|
|
|
@ -1260,13 +1260,14 @@ void StmtProfiler::VisitBlockExpr(const BlockExpr *S) {
|
||||||
|
|
||||||
void StmtProfiler::VisitGenericSelectionExpr(const GenericSelectionExpr *S) {
|
void StmtProfiler::VisitGenericSelectionExpr(const GenericSelectionExpr *S) {
|
||||||
VisitExpr(S);
|
VisitExpr(S);
|
||||||
for (unsigned i = 0; i != S->getNumAssocs(); ++i) {
|
for (const GenericSelectionExpr::ConstAssociation &Assoc :
|
||||||
QualType T = S->getAssocType(i);
|
S->associations()) {
|
||||||
|
QualType T = Assoc.getType();
|
||||||
if (T.isNull())
|
if (T.isNull())
|
||||||
ID.AddPointer(nullptr);
|
ID.AddPointer(nullptr);
|
||||||
else
|
else
|
||||||
VisitType(T);
|
VisitType(T);
|
||||||
VisitExpr(S->getAssocExpr(i));
|
VisitExpr(Assoc.getAssociationExpr());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4332,14 +4332,16 @@ Expr *Sema::stripARCUnbridgedCast(Expr *e) {
|
||||||
assert(!gse->isResultDependent());
|
assert(!gse->isResultDependent());
|
||||||
|
|
||||||
unsigned n = gse->getNumAssocs();
|
unsigned n = gse->getNumAssocs();
|
||||||
SmallVector<Expr*, 4> subExprs(n);
|
SmallVector<Expr *, 4> subExprs;
|
||||||
SmallVector<TypeSourceInfo*, 4> subTypes(n);
|
SmallVector<TypeSourceInfo *, 4> subTypes;
|
||||||
for (unsigned i = 0; i != n; ++i) {
|
subExprs.reserve(n);
|
||||||
subTypes[i] = gse->getAssocTypeSourceInfo(i);
|
subTypes.reserve(n);
|
||||||
Expr *sub = gse->getAssocExpr(i);
|
for (const GenericSelectionExpr::Association &assoc : gse->associations()) {
|
||||||
if (i == gse->getResultIndex())
|
subTypes.push_back(assoc.getTypeSourceInfo());
|
||||||
|
Expr *sub = assoc.getAssociationExpr();
|
||||||
|
if (assoc.isSelected())
|
||||||
sub = stripARCUnbridgedCast(sub);
|
sub = stripARCUnbridgedCast(sub);
|
||||||
subExprs[i] = sub;
|
subExprs.push_back(sub);
|
||||||
}
|
}
|
||||||
|
|
||||||
return GenericSelectionExpr::Create(
|
return GenericSelectionExpr::Create(
|
||||||
|
|
|
@ -140,19 +140,23 @@ namespace {
|
||||||
unsigned resultIndex = gse->getResultIndex();
|
unsigned resultIndex = gse->getResultIndex();
|
||||||
unsigned numAssocs = gse->getNumAssocs();
|
unsigned numAssocs = gse->getNumAssocs();
|
||||||
|
|
||||||
SmallVector<Expr*, 8> assocs(numAssocs);
|
SmallVector<Expr *, 8> assocExprs;
|
||||||
SmallVector<TypeSourceInfo*, 8> assocTypes(numAssocs);
|
SmallVector<TypeSourceInfo *, 8> assocTypes;
|
||||||
|
assocExprs.reserve(numAssocs);
|
||||||
|
assocTypes.reserve(numAssocs);
|
||||||
|
|
||||||
for (unsigned i = 0; i != numAssocs; ++i) {
|
for (const GenericSelectionExpr::Association &assoc :
|
||||||
Expr *assoc = gse->getAssocExpr(i);
|
gse->associations()) {
|
||||||
if (i == resultIndex) assoc = rebuild(assoc);
|
Expr *assocExpr = assoc.getAssociationExpr();
|
||||||
assocs[i] = assoc;
|
if (assoc.isSelected())
|
||||||
assocTypes[i] = gse->getAssocTypeSourceInfo(i);
|
assocExpr = rebuild(assocExpr);
|
||||||
|
assocExprs.push_back(assocExpr);
|
||||||
|
assocTypes.push_back(assoc.getTypeSourceInfo());
|
||||||
}
|
}
|
||||||
|
|
||||||
return GenericSelectionExpr::Create(
|
return GenericSelectionExpr::Create(
|
||||||
S.Context, gse->getGenericLoc(), gse->getControllingExpr(),
|
S.Context, gse->getGenericLoc(), gse->getControllingExpr(),
|
||||||
assocTypes, assocs, gse->getDefaultLoc(), gse->getRParenLoc(),
|
assocTypes, assocExprs, gse->getDefaultLoc(), gse->getRParenLoc(),
|
||||||
gse->containsUnexpandedParameterPack(), resultIndex);
|
gse->containsUnexpandedParameterPack(), resultIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9073,10 +9073,10 @@ TreeTransform<Derived>::TransformGenericSelectionExpr(GenericSelectionExpr *E) {
|
||||||
|
|
||||||
SmallVector<Expr *, 4> AssocExprs;
|
SmallVector<Expr *, 4> AssocExprs;
|
||||||
SmallVector<TypeSourceInfo *, 4> AssocTypes;
|
SmallVector<TypeSourceInfo *, 4> AssocTypes;
|
||||||
for (unsigned i = 0; i != E->getNumAssocs(); ++i) {
|
for (const GenericSelectionExpr::Association &Assoc : E->associations()) {
|
||||||
TypeSourceInfo *TS = E->getAssocTypeSourceInfo(i);
|
TypeSourceInfo *TSI = Assoc.getTypeSourceInfo();
|
||||||
if (TS) {
|
if (TSI) {
|
||||||
TypeSourceInfo *AssocType = getDerived().TransformType(TS);
|
TypeSourceInfo *AssocType = getDerived().TransformType(TSI);
|
||||||
if (!AssocType)
|
if (!AssocType)
|
||||||
return ExprError();
|
return ExprError();
|
||||||
AssocTypes.push_back(AssocType);
|
AssocTypes.push_back(AssocType);
|
||||||
|
@ -9084,7 +9084,8 @@ TreeTransform<Derived>::TransformGenericSelectionExpr(GenericSelectionExpr *E) {
|
||||||
AssocTypes.push_back(nullptr);
|
AssocTypes.push_back(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
ExprResult AssocExpr = getDerived().TransformExpr(E->getAssocExpr(i));
|
ExprResult AssocExpr =
|
||||||
|
getDerived().TransformExpr(Assoc.getAssociationExpr());
|
||||||
if (AssocExpr.isInvalid())
|
if (AssocExpr.isInvalid())
|
||||||
return ExprError();
|
return ExprError();
|
||||||
AssocExprs.push_back(AssocExpr.get());
|
AssocExprs.push_back(AssocExpr.get());
|
||||||
|
|
Loading…
Reference in New Issue