Index: include/clang/AST/Expr.h =================================================================== --- include/clang/AST/Expr.h +++ include/clang/AST/Expr.h @@ -5013,72 +5013,167 @@ /// which names a dependent type in its association list is result-dependent, /// which means that the choice of result expression is dependent. /// Result-dependent generic associations are both type- and value-dependent. -class GenericSelectionExpr : public Expr { - enum { CONTROLLING, END_EXPR }; - TypeSourceInfo **AssocTypes; - Stmt **SubExprs; +class GenericSelectionExpr final + : public Expr, + private llvm::TrailingObjects { + friend class ASTStmtReader; + friend class ASTStmtWriter; + friend TrailingObjects; + + /// The number of association expressions and the index of the + /// result expression in the case where the generic selection expression + /// is not result-dependent. The result index is equal to -1u if and only + /// if the generic selection expression is result-dependent. unsigned NumAssocs, ResultIndex; - SourceLocation GenericLoc, DefaultLoc, RParenLoc; -public: - GenericSelectionExpr(const ASTContext &Context, - SourceLocation GenericLoc, Expr *ControllingExpr, - ArrayRef AssocTypes, - ArrayRef AssocExprs, - SourceLocation DefaultLoc, SourceLocation RParenLoc, + /// The location of the "default" and of the right parenthese. + SourceLocation DefaultLoc, RParenLoc; + + // GenericSelectionExpr is followed by several trailing objects. + // They are in order: + // + // * A single Stmt * for the controlling expression. + // * An array of getNumAssocs() Stmt * for the association expressions. + // * An array of getNumAssocs() TypeSourceInfo *, one for each of the + // association expression. + enum { CONTROLLING = 0, ASSOC_EXPR_START = 1 }; + + unsigned numTrailingObjects(OverloadToken) const { + return 1 + getNumAssocs(); + } + + unsigned numTrailingObjects(OverloadToken) const { + return getNumAssocs(); + } + + template 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 class AssociationTy { + friend class GenericSelectionExpr; + template friend class AssociationIteratorTy; + using ExprPtrTy = + typename std::conditional::type; + using TSIPtrTy = typename std::conditional::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 associations. Note that this is + /// only a forward iterator, not because of any fundamental limitations, + /// but because it is good enough to be usable in ranges. + template class AssociationIteratorTy { + friend class GenericSelectionExpr; + using StmtPtrPtrTy = + typename std::conditional::type; + using TSIPtrPtrTy = + typename std::conditional::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: + using iterator_category = std::forward_iterator_tag; + using value_type = AssociationTy; + using difference_type = std::ptrdiff_t; + using pointer = AssociationTy; + using reference = AssociationTy; + AssociationIteratorTy() = default; + AssociationTy operator*() const { + return AssociationTy(cast(*E), *TSI, + Offset == SelectedOffset); + } + AssociationTy operator->() const { return **this; } + AssociationIteratorTy &operator++() { + E += 1; + TSI += 1; + Offset += 1; + return *this; + } + AssociationIteratorTy operator++(int) { + AssociationIteratorTy Tmp = *this; + ++*this; + return Tmp; + } + friend bool operator==(AssociationIteratorTy It1, + AssociationIteratorTy It2) { + return It1.E == It2.E; + } + friend bool operator!=(AssociationIteratorTy It1, + AssociationIteratorTy It2) { + return !(It1 == It2); + } + }; // class AssociationIterator + + /// Build a non-result-dependent generic selection expression. + GenericSelectionExpr(const ASTContext &Context, SourceLocation GenericLoc, + Expr *ControllingExpr, + ArrayRef AssocTypes, + ArrayRef AssocExprs, SourceLocation DefaultLoc, + SourceLocation RParenLoc, bool ContainsUnexpandedParameterPack, unsigned ResultIndex); - /// This constructor is used in the result-dependent case. - GenericSelectionExpr(const ASTContext &Context, - SourceLocation GenericLoc, Expr *ControllingExpr, - ArrayRef AssocTypes, - ArrayRef AssocExprs, - SourceLocation DefaultLoc, SourceLocation RParenLoc, + /// Build a result-dependent generic selection expression. + GenericSelectionExpr(const ASTContext &Context, SourceLocation GenericLoc, + Expr *ControllingExpr, + ArrayRef AssocTypes, + ArrayRef AssocExprs, SourceLocation DefaultLoc, + SourceLocation RParenLoc, bool ContainsUnexpandedParameterPack); - explicit GenericSelectionExpr(EmptyShell Empty) - : Expr(GenericSelectionExprClass, Empty) { } + /// Build an empty generic selection expression for deserialization. + explicit GenericSelectionExpr(EmptyShell Empty, unsigned NumAssocs); +public: + /// Create a non-result-dependent generic selection expression. + static GenericSelectionExpr * + Create(const ASTContext &Context, SourceLocation GenericLoc, + Expr *ControllingExpr, ArrayRef AssocTypes, + ArrayRef AssocExprs, SourceLocation DefaultLoc, + SourceLocation RParenLoc, bool ContainsUnexpandedParameterPack, + unsigned ResultIndex); + + /// Create a result-dependent generic selection expression. + static GenericSelectionExpr * + Create(const ASTContext &Context, SourceLocation GenericLoc, + Expr *ControllingExpr, ArrayRef AssocTypes, + ArrayRef AssocExprs, SourceLocation DefaultLoc, + SourceLocation RParenLoc, bool ContainsUnexpandedParameterPack); + + /// Create an empty generic selection expression for deserialization. + static GenericSelectionExpr *CreateEmpty(const ASTContext &Context, + unsigned NumAssocs); + + using Association = AssociationTy; + using ConstAssociation = AssociationTy; + using AssociationIterator = AssociationIteratorTy; + using ConstAssociationIterator = AssociationIteratorTy; + using association_range = llvm::iterator_range; + using const_association_range = + llvm::iterator_range; + + /// The number of association expressions. unsigned getNumAssocs() const { return NumAssocs; } - SourceLocation getGenericLoc() const { return GenericLoc; } - SourceLocation getDefaultLoc() const { return DefaultLoc; } - SourceLocation getRParenLoc() const { return RParenLoc; } - - const Expr *getAssocExpr(unsigned i) const { - return cast(SubExprs[END_EXPR+i]); - } - Expr *getAssocExpr(unsigned i) { return cast(SubExprs[END_EXPR+i]); } - ArrayRef getAssocExprs() const { - return NumAssocs - ? llvm::makeArrayRef( - &reinterpret_cast(SubExprs)[END_EXPR], NumAssocs) - : None; - } - const TypeSourceInfo *getAssocTypeSourceInfo(unsigned i) const { - return AssocTypes[i]; - } - TypeSourceInfo *getAssocTypeSourceInfo(unsigned i) { return AssocTypes[i]; } - ArrayRef getAssocTypeSourceInfos() const { - return NumAssocs ? llvm::makeArrayRef(&AssocTypes[0], NumAssocs) : None; - } - - QualType getAssocType(unsigned i) const { - if (const TypeSourceInfo *TS = getAssocTypeSourceInfo(i)) - return TS->getType(); - else - return QualType(); - } - - const Expr *getControllingExpr() const { - return cast(SubExprs[CONTROLLING]); - } - Expr *getControllingExpr() { return cast(SubExprs[CONTROLLING]); } - - /// Whether this generic selection is result-dependent. - bool isResultDependent() const { return ResultIndex == -1U; } - /// The zero-based index of the result expression's generic association in /// the generic selection's association list. Defined only if the /// generic selection is not result-dependent. @@ -5087,25 +5182,97 @@ return ResultIndex; } - /// The generic selection's result expression. Defined only if the - /// generic selection is not result-dependent. - const Expr *getResultExpr() const { return getAssocExpr(getResultIndex()); } - Expr *getResultExpr() { return getAssocExpr(getResultIndex()); } + /// Whether this generic selection is result-dependent. + bool isResultDependent() const { return ResultIndex == -1U; } - SourceLocation getBeginLoc() const LLVM_READONLY { return GenericLoc; } - SourceLocation getEndLoc() const LLVM_READONLY { return RParenLoc; } + /// Return the controlling expression of this generic selection expression. + Expr *getControllingExpr() { + return cast(getTrailingObjects()[CONTROLLING]); + } + const Expr *getControllingExpr() const { + return cast(getTrailingObjects()[CONTROLLING]); + } + + /// Return the result expression of this controlling expression. Defined if + /// and only if the generic selection expression is not result-dependent. + Expr *getResultExpr() { + return cast( + getTrailingObjects()[ASSOC_EXPR_START + getResultIndex()]); + } + const Expr *getResultExpr() const { + return cast( + getTrailingObjects()[ASSOC_EXPR_START + getResultIndex()]); + } + + ArrayRef getAssocExprs() const { + return {reinterpret_cast(getTrailingObjects() + + ASSOC_EXPR_START), + NumAssocs}; + } + ArrayRef getAssocTypeSourceInfos() const { + return {getTrailingObjects(), 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(getTrailingObjects()[ASSOC_EXPR_START + I]), + getTrailingObjects()[I], + !isResultDependent() && (getResultIndex() == I)); + } + ConstAssociation getAssociation(unsigned I) const { + assert((I < getNumAssocs()) && + "Out-of-range index in GenericSelectionExpr::getAssociation!"); + return ConstAssociation( + cast(getTrailingObjects()[ASSOC_EXPR_START + I]), + getTrailingObjects()[I], + !isResultDependent() && (getResultIndex() == I)); + } + + association_range associations() { + AssociationIterator Begin(getTrailingObjects() + ASSOC_EXPR_START, + getTrailingObjects(), + /*Offset=*/0, ResultIndex); + AssociationIterator End(Begin.E + NumAssocs, Begin.TSI + NumAssocs, + /*Offset=*/NumAssocs, ResultIndex); + return {Begin, End}; + } + + const_association_range associations() const { + ConstAssociationIterator Begin(getTrailingObjects() + + ASSOC_EXPR_START, + getTrailingObjects(), + /*Offset=*/0, ResultIndex); + ConstAssociationIterator End(Begin.E + NumAssocs, Begin.TSI + NumAssocs, + /*Offset=*/NumAssocs, ResultIndex); + return {Begin, End}; + } + + SourceLocation getGenericLoc() const { + return GenericSelectionExprBits.GenericLoc; + } + SourceLocation getDefaultLoc() const { return DefaultLoc; } + SourceLocation getRParenLoc() const { return RParenLoc; } + SourceLocation getBeginLoc() const { return getGenericLoc(); } + SourceLocation getEndLoc() const { return getRParenLoc(); } static bool classof(const Stmt *T) { return T->getStmtClass() == GenericSelectionExprClass; } child_range children() { - return child_range(SubExprs, SubExprs+END_EXPR+NumAssocs); + return child_range(getTrailingObjects(), + getTrailingObjects() + + numTrailingObjects(OverloadToken())); } const_child_range children() const { - return const_child_range(SubExprs, SubExprs + END_EXPR + NumAssocs); + return const_child_range(getTrailingObjects(), + getTrailingObjects() + + numTrailingObjects(OverloadToken())); } - friend class ASTStmtReader; }; //===----------------------------------------------------------------------===// Index: include/clang/AST/RecursiveASTVisitor.h =================================================================== --- include/clang/AST/RecursiveASTVisitor.h +++ include/clang/AST/RecursiveASTVisitor.h @@ -2300,10 +2300,10 @@ // 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 (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; }) Index: include/clang/AST/Stmt.h =================================================================== --- include/clang/AST/Stmt.h +++ include/clang/AST/Stmt.h @@ -520,6 +520,16 @@ unsigned NumExprs; }; + class GenericSelectionExprBitfields { + friend class ASTStmtReader; + friend class GenericSelectionExpr; + + unsigned : NumExprBits; + + /// The location of the "_Generic". + SourceLocation GenericLoc; + }; + class PseudoObjectExprBitfields { friend class ASTStmtReader; // deserialization friend class PseudoObjectExpr; @@ -915,6 +925,7 @@ BinaryOperatorBitfields BinaryOperatorBits; InitListExprBitfields InitListExprBits; ParenListExprBitfields ParenListExprBits; + GenericSelectionExprBitfields GenericSelectionExprBits; PseudoObjectExprBitfields PseudoObjectExprBits; // C++ Expressions Index: include/clang/AST/StmtDataCollectors.td =================================================================== --- include/clang/AST/StmtDataCollectors.td +++ include/clang/AST/StmtDataCollectors.td @@ -189,8 +189,8 @@ } class GenericSelectionExpr { code Code = [{ - for (unsigned i = 0; i < S->getNumAssocs(); ++i) { - addData(S->getAssocType(i)); + for (GenericSelectionExpr::ConstAssociation Assoc : S->associations()) { + addData(Assoc.getType()); } }]; } Index: lib/AST/ASTDumper.cpp =================================================================== --- lib/AST/ASTDumper.cpp +++ lib/AST/ASTDumper.cpp @@ -1462,21 +1462,21 @@ dumpStmt(E->getControllingExpr()); dumpTypeAsChild(E->getControllingExpr()->getType()); // FIXME: remove - for (unsigned I = 0, N = E->getNumAssocs(); I != N; ++I) { + for (GenericSelectionExpr::ConstAssociation 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()); }); } } Index: lib/AST/Expr.cpp =================================================================== --- lib/AST/Expr.cpp +++ lib/AST/Expr.cpp @@ -3774,55 +3774,95 @@ memcpy(SubExprs, Exprs.data(), sizeof(Expr *) * Exprs.size()); } -GenericSelectionExpr::GenericSelectionExpr(const ASTContext &Context, - SourceLocation GenericLoc, Expr *ControllingExpr, - ArrayRef AssocTypes, - ArrayRef AssocExprs, - SourceLocation DefaultLoc, - SourceLocation RParenLoc, - bool ContainsUnexpandedParameterPack, - unsigned ResultIndex) - : Expr(GenericSelectionExprClass, - AssocExprs[ResultIndex]->getType(), - AssocExprs[ResultIndex]->getValueKind(), - AssocExprs[ResultIndex]->getObjectKind(), - AssocExprs[ResultIndex]->isTypeDependent(), - AssocExprs[ResultIndex]->isValueDependent(), - AssocExprs[ResultIndex]->isInstantiationDependent(), - ContainsUnexpandedParameterPack), - AssocTypes(new (Context) TypeSourceInfo*[AssocTypes.size()]), - SubExprs(new (Context) Stmt*[END_EXPR+AssocExprs.size()]), - NumAssocs(AssocExprs.size()), ResultIndex(ResultIndex), - GenericLoc(GenericLoc), DefaultLoc(DefaultLoc), RParenLoc(RParenLoc) { - SubExprs[CONTROLLING] = ControllingExpr; - assert(AssocTypes.size() == AssocExprs.size()); - std::copy(AssocTypes.begin(), AssocTypes.end(), this->AssocTypes); - std::copy(AssocExprs.begin(), AssocExprs.end(), SubExprs+END_EXPR); -} - -GenericSelectionExpr::GenericSelectionExpr(const ASTContext &Context, - SourceLocation GenericLoc, Expr *ControllingExpr, - ArrayRef AssocTypes, - ArrayRef AssocExprs, - SourceLocation DefaultLoc, - SourceLocation RParenLoc, - bool ContainsUnexpandedParameterPack) - : Expr(GenericSelectionExprClass, - Context.DependentTy, - VK_RValue, - OK_Ordinary, - /*isTypeDependent=*/true, - /*isValueDependent=*/true, - /*isInstantiationDependent=*/true, - ContainsUnexpandedParameterPack), - AssocTypes(new (Context) TypeSourceInfo*[AssocTypes.size()]), - SubExprs(new (Context) Stmt*[END_EXPR+AssocExprs.size()]), - NumAssocs(AssocExprs.size()), ResultIndex(-1U), GenericLoc(GenericLoc), - DefaultLoc(DefaultLoc), RParenLoc(RParenLoc) { - SubExprs[CONTROLLING] = ControllingExpr; - assert(AssocTypes.size() == AssocExprs.size()); - std::copy(AssocTypes.begin(), AssocTypes.end(), this->AssocTypes); - std::copy(AssocExprs.begin(), AssocExprs.end(), SubExprs+END_EXPR); +GenericSelectionExpr::GenericSelectionExpr( + const ASTContext &, SourceLocation GenericLoc, Expr *ControllingExpr, + ArrayRef AssocTypes, ArrayRef AssocExprs, + SourceLocation DefaultLoc, SourceLocation RParenLoc, + bool ContainsUnexpandedParameterPack, unsigned ResultIndex) + : Expr(GenericSelectionExprClass, AssocExprs[ResultIndex]->getType(), + AssocExprs[ResultIndex]->getValueKind(), + AssocExprs[ResultIndex]->getObjectKind(), + AssocExprs[ResultIndex]->isTypeDependent(), + AssocExprs[ResultIndex]->isValueDependent(), + AssocExprs[ResultIndex]->isInstantiationDependent(), + ContainsUnexpandedParameterPack), + NumAssocs(AssocExprs.size()), ResultIndex(ResultIndex), + DefaultLoc(DefaultLoc), RParenLoc(RParenLoc) { + assert((AssocTypes.size() == AssocExprs.size()) && + "Must have the same number of association expressions" + " and TypeSourceInfo!"); + assert((ResultIndex < NumAssocs) && "ResultIndex is out-of-bounds!"); + + GenericSelectionExprBits.GenericLoc = GenericLoc; + getTrailingObjects()[CONTROLLING] = ControllingExpr; + std::copy(AssocExprs.begin(), AssocExprs.end(), + getTrailingObjects() + ASSOC_EXPR_START); + std::copy(AssocTypes.begin(), AssocTypes.end(), + getTrailingObjects()); +} + +GenericSelectionExpr::GenericSelectionExpr( + const ASTContext &Context, SourceLocation GenericLoc, Expr *ControllingExpr, + ArrayRef AssocTypes, ArrayRef AssocExprs, + SourceLocation DefaultLoc, SourceLocation RParenLoc, + bool ContainsUnexpandedParameterPack) + : Expr(GenericSelectionExprClass, Context.DependentTy, VK_RValue, + OK_Ordinary, + /*isTypeDependent=*/true, + /*isValueDependent=*/true, + /*isInstantiationDependent=*/true, ContainsUnexpandedParameterPack), + NumAssocs(AssocExprs.size()), ResultIndex(-1U), DefaultLoc(DefaultLoc), + RParenLoc(RParenLoc) { + assert((AssocTypes.size() == AssocExprs.size()) && + "Must have the same number of association expressions" + " and TypeSourceInfo!"); + + GenericSelectionExprBits.GenericLoc = GenericLoc; + getTrailingObjects()[CONTROLLING] = ControllingExpr; + std::copy(AssocExprs.begin(), AssocExprs.end(), + getTrailingObjects() + ASSOC_EXPR_START); + std::copy(AssocTypes.begin(), AssocTypes.end(), + getTrailingObjects()); +} + +GenericSelectionExpr::GenericSelectionExpr(EmptyShell Empty, unsigned NumAssocs) + : Expr(GenericSelectionExprClass, Empty), NumAssocs(NumAssocs) {} + +GenericSelectionExpr *GenericSelectionExpr::Create( + const ASTContext &Context, SourceLocation GenericLoc, Expr *ControllingExpr, + ArrayRef AssocTypes, ArrayRef AssocExprs, + SourceLocation DefaultLoc, SourceLocation RParenLoc, + bool ContainsUnexpandedParameterPack, unsigned ResultIndex) { + unsigned NumAssocs = AssocExprs.size(); + void *Mem = Context.Allocate( + totalSizeToAlloc(1 + NumAssocs, NumAssocs), + alignof(GenericSelectionExpr)); + return new (Mem) GenericSelectionExpr( + Context, GenericLoc, ControllingExpr, AssocTypes, AssocExprs, DefaultLoc, + RParenLoc, ContainsUnexpandedParameterPack, ResultIndex); +} + +GenericSelectionExpr *GenericSelectionExpr::Create( + const ASTContext &Context, SourceLocation GenericLoc, Expr *ControllingExpr, + ArrayRef AssocTypes, ArrayRef AssocExprs, + SourceLocation DefaultLoc, SourceLocation RParenLoc, + bool ContainsUnexpandedParameterPack) { + unsigned NumAssocs = AssocExprs.size(); + void *Mem = Context.Allocate( + totalSizeToAlloc(1 + NumAssocs, NumAssocs), + alignof(GenericSelectionExpr)); + return new (Mem) GenericSelectionExpr( + Context, GenericLoc, ControllingExpr, AssocTypes, AssocExprs, DefaultLoc, + RParenLoc, ContainsUnexpandedParameterPack); +} + +GenericSelectionExpr * +GenericSelectionExpr::CreateEmpty(const ASTContext &Context, + unsigned NumAssocs) { + void *Mem = Context.Allocate( + totalSizeToAlloc(1 + NumAssocs, NumAssocs), + alignof(GenericSelectionExpr)); + return new (Mem) GenericSelectionExpr(EmptyShell(), NumAssocs); } //===----------------------------------------------------------------------===// Index: lib/AST/StmtPrinter.cpp =================================================================== --- lib/AST/StmtPrinter.cpp +++ lib/AST/StmtPrinter.cpp @@ -1261,15 +1261,15 @@ void StmtPrinter::VisitGenericSelectionExpr(GenericSelectionExpr *Node) { OS << "_Generic("; PrintExpr(Node->getControllingExpr()); - for (unsigned i = 0; i != Node->getNumAssocs(); ++i) { + for (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 << ")"; } Index: lib/AST/StmtProfile.cpp =================================================================== --- lib/AST/StmtProfile.cpp +++ lib/AST/StmtProfile.cpp @@ -1259,13 +1259,13 @@ void StmtProfiler::VisitGenericSelectionExpr(const GenericSelectionExpr *S) { VisitExpr(S); - for (unsigned i = 0; i != S->getNumAssocs(); ++i) { - QualType T = S->getAssocType(i); + for (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()); } } Index: lib/Sema/SemaExpr.cpp =================================================================== --- lib/Sema/SemaExpr.cpp +++ lib/Sema/SemaExpr.cpp @@ -1534,9 +1534,9 @@ // If we determined that the generic selection is result-dependent, don't // try to compute the result expression. if (IsResultDependent) - return new (Context) GenericSelectionExpr( - Context, KeyLoc, ControllingExpr, Types, Exprs, DefaultLoc, RParenLoc, - ContainsUnexpandedParameterPack); + return GenericSelectionExpr::Create(Context, KeyLoc, ControllingExpr, Types, + Exprs, DefaultLoc, RParenLoc, + ContainsUnexpandedParameterPack); SmallVector CompatIndices; unsigned DefaultIndex = -1U; @@ -1587,7 +1587,7 @@ unsigned ResultIndex = CompatIndices.size() ? CompatIndices[0] : DefaultIndex; - return new (Context) GenericSelectionExpr( + return GenericSelectionExpr::Create( Context, KeyLoc, ControllingExpr, Types, Exprs, DefaultLoc, RParenLoc, ContainsUnexpandedParameterPack, ResultIndex); } Index: lib/Sema/SemaExprObjC.cpp =================================================================== --- lib/Sema/SemaExprObjC.cpp +++ lib/Sema/SemaExprObjC.cpp @@ -4332,23 +4332,22 @@ assert(!gse->isResultDependent()); unsigned n = gse->getNumAssocs(); - SmallVector subExprs(n); - SmallVector subTypes(n); - for (unsigned i = 0; i != n; ++i) { - subTypes[i] = gse->getAssocTypeSourceInfo(i); - Expr *sub = gse->getAssocExpr(i); - if (i == gse->getResultIndex()) + SmallVector subExprs; + SmallVector subTypes; + subExprs.reserve(n); + subTypes.reserve(n); + for (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 new (Context) GenericSelectionExpr(Context, gse->getGenericLoc(), - gse->getControllingExpr(), - subTypes, subExprs, - gse->getDefaultLoc(), - gse->getRParenLoc(), - gse->containsUnexpandedParameterPack(), - gse->getResultIndex()); + return GenericSelectionExpr::Create( + Context, gse->getGenericLoc(), gse->getControllingExpr(), subTypes, + subExprs, gse->getDefaultLoc(), gse->getRParenLoc(), + gse->containsUnexpandedParameterPack(), gse->getResultIndex()); } else { assert(isa(e) && "bad form of unbridged cast!"); return cast(e)->getSubExpr(); Index: lib/Sema/SemaOverload.cpp =================================================================== --- lib/Sema/SemaOverload.cpp +++ lib/Sema/SemaOverload.cpp @@ -13711,7 +13711,7 @@ unsigned ResultIdx = GSE->getResultIndex(); AssocExprs[ResultIdx] = SubExpr; - return new (Context) GenericSelectionExpr( + return GenericSelectionExpr::Create( Context, GSE->getGenericLoc(), GSE->getControllingExpr(), GSE->getAssocTypeSourceInfos(), AssocExprs, GSE->getDefaultLoc(), GSE->getRParenLoc(), GSE->containsUnexpandedParameterPack(), Index: lib/Sema/SemaPseudoObject.cpp =================================================================== --- lib/Sema/SemaPseudoObject.cpp +++ lib/Sema/SemaPseudoObject.cpp @@ -140,25 +140,23 @@ unsigned resultIndex = gse->getResultIndex(); unsigned numAssocs = gse->getNumAssocs(); - SmallVector assocs(numAssocs); - SmallVector 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); + SmallVector assocs; + SmallVector assocTypes; + assocs.reserve(numAssocs); + assocTypes.reserve(numAssocs); + + for (GenericSelectionExpr::Association Assoc : gse->associations()) { + Expr *assoc = Assoc.getAssociationExpr(); + if (Assoc.isSelected()) + assoc = rebuild(assoc); + assocs.push_back(assoc); + assocTypes.push_back(Assoc.getTypeSourceInfo()); } - return new (S.Context) GenericSelectionExpr(S.Context, - gse->getGenericLoc(), - gse->getControllingExpr(), - assocTypes, - assocs, - gse->getDefaultLoc(), - gse->getRParenLoc(), - gse->containsUnexpandedParameterPack(), - resultIndex); + return GenericSelectionExpr::Create( + S.Context, gse->getGenericLoc(), gse->getControllingExpr(), + assocTypes, assocs, gse->getDefaultLoc(), gse->getRParenLoc(), + gse->containsUnexpandedParameterPack(), resultIndex); } if (ChooseExpr *ce = dyn_cast(e)) { Index: lib/Sema/TreeTransform.h =================================================================== --- lib/Sema/TreeTransform.h +++ lib/Sema/TreeTransform.h @@ -9071,10 +9071,10 @@ SmallVector AssocExprs; SmallVector AssocTypes; - for (unsigned i = 0; i != E->getNumAssocs(); ++i) { - TypeSourceInfo *TS = E->getAssocTypeSourceInfo(i); - if (TS) { - TypeSourceInfo *AssocType = getDerived().TransformType(TS); + for (GenericSelectionExpr::Association Assoc : E->associations()) { + TypeSourceInfo *TSI = Assoc.getTypeSourceInfo(); + if (TSI) { + TypeSourceInfo *AssocType = getDerived().TransformType(TSI); if (!AssocType) return ExprError(); AssocTypes.push_back(AssocType); @@ -9082,7 +9082,8 @@ 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()); Index: lib/Serialization/ASTReaderStmt.cpp =================================================================== --- lib/Serialization/ASTReaderStmt.cpp +++ lib/Serialization/ASTReaderStmt.cpp @@ -1022,21 +1022,22 @@ void ASTStmtReader::VisitGenericSelectionExpr(GenericSelectionExpr *E) { VisitExpr(E); - E->NumAssocs = Record.readInt(); - E->AssocTypes = new (Record.getContext()) TypeSourceInfo*[E->NumAssocs]; - E->SubExprs = - new(Record.getContext()) Stmt*[GenericSelectionExpr::END_EXPR+E->NumAssocs]; - - E->SubExprs[GenericSelectionExpr::CONTROLLING] = Record.readSubExpr(); - for (unsigned I = 0, N = E->getNumAssocs(); I != N; ++I) { - E->AssocTypes[I] = GetTypeSourceInfo(); - E->SubExprs[GenericSelectionExpr::END_EXPR+I] = Record.readSubExpr(); - } - E->ResultIndex = Record.readInt(); - E->GenericLoc = ReadSourceLocation(); + unsigned NumAssocs = Record.readInt(); + assert((NumAssocs == E->getNumAssocs()) && "Wrong NumAssocs!"); + E->ResultIndex = Record.readInt(); + E->GenericSelectionExprBits.GenericLoc = ReadSourceLocation(); E->DefaultLoc = ReadSourceLocation(); E->RParenLoc = ReadSourceLocation(); + + Stmt **Stmts = E->getTrailingObjects(); + for (unsigned I = 0, N = NumAssocs + 1; I < N; ++I) + Stmts[I] = Record.readSubExpr(); + + TypeSourceInfo **TSIs = E->getTrailingObjects(); + for (unsigned I = 0, N = NumAssocs; I < N; ++I) + TSIs[I] = GetTypeSourceInfo(); + ; } void ASTStmtReader::VisitPseudoObjectExpr(PseudoObjectExpr *E) { @@ -2675,7 +2676,9 @@ break; case EXPR_GENERIC_SELECTION: - S = new (Context) GenericSelectionExpr(Empty); + S = GenericSelectionExpr::CreateEmpty( + Context, + /*NumAssocs=*/Record[ASTStmtReader::NumExprFields]); break; case EXPR_OBJC_STRING_LITERAL: Index: lib/Serialization/ASTWriterStmt.cpp =================================================================== --- lib/Serialization/ASTWriterStmt.cpp +++ lib/Serialization/ASTWriterStmt.cpp @@ -968,18 +968,21 @@ void ASTStmtWriter::VisitGenericSelectionExpr(GenericSelectionExpr *E) { VisitExpr(E); - Record.push_back(E->getNumAssocs()); - Record.AddStmt(E->getControllingExpr()); - for (unsigned I = 0, N = E->getNumAssocs(); I != N; ++I) { - Record.AddTypeSourceInfo(E->getAssocTypeSourceInfo(I)); - Record.AddStmt(E->getAssocExpr(I)); - } + Record.push_back(E->getNumAssocs()); Record.push_back(E->isResultDependent() ? -1U : E->getResultIndex()); - Record.AddSourceLocation(E->getGenericLoc()); Record.AddSourceLocation(E->getDefaultLoc()); Record.AddSourceLocation(E->getRParenLoc()); + + Stmt **Stmts = E->getTrailingObjects(); + for (unsigned I = 0, N = E->getNumAssocs() + 1; I < N; ++I) + Record.AddStmt(Stmts[I]); + + TypeSourceInfo **TSIs = E->getTrailingObjects(); + for (unsigned I = 0, N = E->getNumAssocs(); I < N; ++I) + Record.AddTypeSourceInfo(TSIs[I]); + Code = serialization::EXPR_GENERIC_SELECTION; }