Index: cfe/trunk/include/clang/AST/Expr.h =================================================================== --- cfe/trunk/include/clang/AST/Expr.h +++ cfe/trunk/include/clang/AST/Expr.h @@ -5014,98 +5014,118 @@ /// 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; + friend class ASTStmtReader; + friend class ASTStmtWriter; + + /// 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 ResultDependentIndex + /// if and only if the generic selection expression is result-dependent. unsigned NumAssocs, ResultIndex; + enum : unsigned { + ResultDependentIndex = std::numeric_limits::max(), + ControllingIndex = 0, + AssocExprStartIndex = 1 + }; + + /// The location of the "_Generic", "default" and of the right parenthesis. SourceLocation GenericLoc, DefaultLoc, RParenLoc; + TypeSourceInfo **AssocTypes; + Stmt **SubExprs; + public: - GenericSelectionExpr(const ASTContext &Context, - SourceLocation GenericLoc, Expr *ControllingExpr, - ArrayRef AssocTypes, - ArrayRef AssocExprs, - SourceLocation DefaultLoc, SourceLocation RParenLoc, + 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, + 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) { } + : Expr(GenericSelectionExprClass, Empty) {} + /// 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; } + /// 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. + unsigned getResultIndex() const { + assert(!isResultDependent() && + "Generic selection is result-dependent but getResultIndex called!"); + return ResultIndex; + } - const Expr *getAssocExpr(unsigned i) const { - return cast(SubExprs[END_EXPR+i]); + /// Whether this generic selection is result-dependent. + bool isResultDependent() const { return ResultIndex == ResultDependentIndex; } + + /// Return the controlling expression of this generic selection expression. + Expr *getControllingExpr() { return cast(SubExprs[ControllingIndex]); } + const Expr *getControllingExpr() const { + return cast(SubExprs[ControllingIndex]); } - Expr *getAssocExpr(unsigned i) { return cast(SubExprs[END_EXPR+i]); } - ArrayRef getAssocExprs() const { - return NumAssocs - ? llvm::makeArrayRef( - &reinterpret_cast(SubExprs)[END_EXPR], NumAssocs) - : None; + + /// 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(SubExprs[AssocExprStartIndex + getResultIndex()]); } - const TypeSourceInfo *getAssocTypeSourceInfo(unsigned i) const { - return AssocTypes[i]; + const Expr *getResultExpr() const { + return cast(SubExprs[AssocExprStartIndex + getResultIndex()]); + } + + ArrayRef getAssocExprs() const { + return {reinterpret_cast(SubExprs + AssocExprStartIndex), + NumAssocs}; } - TypeSourceInfo *getAssocTypeSourceInfo(unsigned i) { return AssocTypes[i]; } ArrayRef getAssocTypeSourceInfos() const { - return NumAssocs ? llvm::makeArrayRef(&AssocTypes[0], NumAssocs) : None; + return {AssocTypes, NumAssocs}; } - QualType getAssocType(unsigned i) const { - if (const TypeSourceInfo *TS = getAssocTypeSourceInfo(i)) - return TS->getType(); - else - return QualType(); + Expr *getAssocExpr(unsigned i) { + return cast(SubExprs[AssocExprStartIndex + i]); } - - const Expr *getControllingExpr() const { - return cast(SubExprs[CONTROLLING]); + const Expr *getAssocExpr(unsigned i) const { + return cast(SubExprs[AssocExprStartIndex + i]); } - 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. - unsigned getResultIndex() const { - assert(!isResultDependent() && "Generic selection is result-dependent"); - return ResultIndex; + TypeSourceInfo *getAssocTypeSourceInfo(unsigned i) { return AssocTypes[i]; } + const TypeSourceInfo *getAssocTypeSourceInfo(unsigned i) const { + return AssocTypes[i]; } - /// 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()); } + QualType getAssocType(unsigned i) const { + const TypeSourceInfo *TSI = getAssocTypeSourceInfo(i); + return TSI ? TSI->getType() : QualType(); + } - SourceLocation getBeginLoc() const LLVM_READONLY { return GenericLoc; } - SourceLocation getEndLoc() const LLVM_READONLY { return RParenLoc; } + SourceLocation getGenericLoc() const { return 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(SubExprs, SubExprs + AssocExprStartIndex + NumAssocs); } const_child_range children() const { - return const_child_range(SubExprs, SubExprs + END_EXPR + NumAssocs); + return const_child_range(SubExprs, + SubExprs + AssocExprStartIndex + NumAssocs); } - friend class ASTStmtReader; }; //===----------------------------------------------------------------------===// Index: cfe/trunk/lib/AST/Expr.cpp =================================================================== --- cfe/trunk/lib/AST/Expr.cpp +++ cfe/trunk/lib/AST/Expr.cpp @@ -3774,55 +3774,55 @@ 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()); +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), + NumAssocs(AssocExprs.size()), ResultIndex(ResultIndex), + AssocTypes(new (Context) TypeSourceInfo *[AssocTypes.size()]), + SubExprs(new (Context) Stmt *[AssocExprStartIndex + AssocExprs.size()]), + GenericLoc(GenericLoc), 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!"); + + SubExprs[ControllingIndex] = ControllingExpr; std::copy(AssocTypes.begin(), AssocTypes.end(), this->AssocTypes); - std::copy(AssocExprs.begin(), AssocExprs.end(), SubExprs+END_EXPR); + std::copy(AssocExprs.begin(), AssocExprs.end(), + SubExprs + AssocExprStartIndex); } -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()); +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(ResultDependentIndex), + AssocTypes(new (Context) TypeSourceInfo *[AssocTypes.size()]), + SubExprs(new (Context) Stmt *[AssocExprStartIndex + AssocExprs.size()]), + GenericLoc(GenericLoc), DefaultLoc(DefaultLoc), RParenLoc(RParenLoc) { + assert(AssocTypes.size() == AssocExprs.size() && + "Must have the same number of association expressions" + " and TypeSourceInfo!"); + + SubExprs[ControllingIndex] = ControllingExpr; std::copy(AssocTypes.begin(), AssocTypes.end(), this->AssocTypes); - std::copy(AssocExprs.begin(), AssocExprs.end(), SubExprs+END_EXPR); + std::copy(AssocExprs.begin(), AssocExprs.end(), + SubExprs + AssocExprStartIndex); } //===----------------------------------------------------------------------===// Index: cfe/trunk/lib/Serialization/ASTReaderStmt.cpp =================================================================== --- cfe/trunk/lib/Serialization/ASTReaderStmt.cpp +++ cfe/trunk/lib/Serialization/ASTReaderStmt.cpp @@ -1023,16 +1023,18 @@ 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->ResultIndex = Record.readInt(); + + E->AssocTypes = new (Record.getContext()) TypeSourceInfo *[E->NumAssocs]; + E->SubExprs = new (Record.getContext()) + Stmt *[GenericSelectionExpr::AssocExprStartIndex + E->NumAssocs]; - E->SubExprs[GenericSelectionExpr::CONTROLLING] = Record.readSubExpr(); + E->SubExprs[GenericSelectionExpr::ControllingIndex] = 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->SubExprs[GenericSelectionExpr::AssocExprStartIndex + I] = + Record.readSubExpr(); } - E->ResultIndex = Record.readInt(); E->GenericLoc = ReadSourceLocation(); E->DefaultLoc = ReadSourceLocation(); Index: cfe/trunk/lib/Serialization/ASTWriterStmt.cpp =================================================================== --- cfe/trunk/lib/Serialization/ASTWriterStmt.cpp +++ cfe/trunk/lib/Serialization/ASTWriterStmt.cpp @@ -969,13 +969,13 @@ void ASTStmtWriter::VisitGenericSelectionExpr(GenericSelectionExpr *E) { VisitExpr(E); Record.push_back(E->getNumAssocs()); + Record.push_back(E->ResultIndex); 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->isResultDependent() ? -1U : E->getResultIndex()); Record.AddSourceLocation(E->getGenericLoc()); Record.AddSourceLocation(E->getDefaultLoc());