Index: cfe/trunk/include/clang/AST/Expr.h =================================================================== --- cfe/trunk/include/clang/AST/Expr.h +++ cfe/trunk/include/clang/AST/Expr.h @@ -5013,9 +5013,13 @@ /// 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 { +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 @@ -5028,13 +5032,27 @@ AssocExprStartIndex = 1 }; - /// The location of the "_Generic", "default" and of the right parenthesis. - SourceLocation GenericLoc, DefaultLoc, RParenLoc; + /// The location of the "default" and of the right parenthesis. + SourceLocation DefaultLoc, RParenLoc; - TypeSourceInfo **AssocTypes; - Stmt **SubExprs; + // 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 expressions. + unsigned numTrailingObjects(OverloadToken) const { + // Add one to account for the controlling expression; the remainder + // are the associated expressions. + return 1 + getNumAssocs(); + } -public: + unsigned numTrailingObjects(OverloadToken) const { + return getNumAssocs(); + } + + /// Build a non-result-dependent generic selection expression. GenericSelectionExpr(const ASTContext &Context, SourceLocation GenericLoc, Expr *ControllingExpr, ArrayRef AssocTypes, @@ -5043,7 +5061,7 @@ bool ContainsUnexpandedParameterPack, unsigned ResultIndex); - /// This constructor is used in the result-dependent case. + /// Build a result-dependent generic selection expression. GenericSelectionExpr(const ASTContext &Context, SourceLocation GenericLoc, Expr *ControllingExpr, ArrayRef AssocTypes, @@ -5051,8 +5069,28 @@ 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); /// The number of association expressions. unsigned getNumAssocs() const { return NumAssocs; } @@ -5070,38 +5108,45 @@ bool isResultDependent() const { return ResultIndex == ResultDependentIndex; } /// Return the controlling expression of this generic selection expression. - Expr *getControllingExpr() { return cast(SubExprs[ControllingIndex]); } + Expr *getControllingExpr() { + return cast(getTrailingObjects()[ControllingIndex]); + } const Expr *getControllingExpr() const { - return cast(SubExprs[ControllingIndex]); + return cast(getTrailingObjects()[ControllingIndex]); } /// 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()]); + return cast( + getTrailingObjects()[AssocExprStartIndex + getResultIndex()]); } const Expr *getResultExpr() const { - return cast(SubExprs[AssocExprStartIndex + getResultIndex()]); + return cast( + getTrailingObjects()[AssocExprStartIndex + getResultIndex()]); } ArrayRef getAssocExprs() const { - return {reinterpret_cast(SubExprs + AssocExprStartIndex), + return {reinterpret_cast(getTrailingObjects() + + AssocExprStartIndex), NumAssocs}; } ArrayRef getAssocTypeSourceInfos() const { - return {AssocTypes, NumAssocs}; + return {getTrailingObjects(), NumAssocs}; } Expr *getAssocExpr(unsigned i) { - return cast(SubExprs[AssocExprStartIndex + i]); + return cast(getTrailingObjects()[AssocExprStartIndex + i]); } const Expr *getAssocExpr(unsigned i) const { - return cast(SubExprs[AssocExprStartIndex + i]); + return cast(getTrailingObjects()[AssocExprStartIndex + i]); } - TypeSourceInfo *getAssocTypeSourceInfo(unsigned i) { return AssocTypes[i]; } + TypeSourceInfo *getAssocTypeSourceInfo(unsigned i) { + return getTrailingObjects()[i]; + } const TypeSourceInfo *getAssocTypeSourceInfo(unsigned i) const { - return AssocTypes[i]; + return getTrailingObjects()[i]; } QualType getAssocType(unsigned i) const { @@ -5109,7 +5154,9 @@ return TSI ? TSI->getType() : QualType(); } - SourceLocation getGenericLoc() const { return GenericLoc; } + SourceLocation getGenericLoc() const { + return GenericSelectionExprBits.GenericLoc; + } SourceLocation getDefaultLoc() const { return DefaultLoc; } SourceLocation getRParenLoc() const { return RParenLoc; } SourceLocation getBeginLoc() const { return getGenericLoc(); } @@ -5120,11 +5167,14 @@ } child_range children() { - return child_range(SubExprs, SubExprs + AssocExprStartIndex + NumAssocs); + return child_range(getTrailingObjects(), + getTrailingObjects() + + numTrailingObjects(OverloadToken())); } const_child_range children() const { - return const_child_range(SubExprs, - SubExprs + AssocExprStartIndex + NumAssocs); + return const_child_range(getTrailingObjects(), + getTrailingObjects() + + numTrailingObjects(OverloadToken())); } }; Index: cfe/trunk/include/clang/AST/Stmt.h =================================================================== --- cfe/trunk/include/clang/AST/Stmt.h +++ cfe/trunk/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: cfe/trunk/lib/AST/Expr.cpp =================================================================== --- cfe/trunk/lib/AST/Expr.cpp +++ cfe/trunk/lib/AST/Expr.cpp @@ -3775,7 +3775,7 @@ } GenericSelectionExpr::GenericSelectionExpr( - const ASTContext &Context, SourceLocation GenericLoc, Expr *ControllingExpr, + const ASTContext &, SourceLocation GenericLoc, Expr *ControllingExpr, ArrayRef AssocTypes, ArrayRef AssocExprs, SourceLocation DefaultLoc, SourceLocation RParenLoc, bool ContainsUnexpandedParameterPack, unsigned ResultIndex) @@ -3787,18 +3787,18 @@ 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) { + 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); + GenericSelectionExprBits.GenericLoc = GenericLoc; + getTrailingObjects()[ControllingIndex] = ControllingExpr; std::copy(AssocExprs.begin(), AssocExprs.end(), - SubExprs + AssocExprStartIndex); + getTrailingObjects() + AssocExprStartIndex); + std::copy(AssocTypes.begin(), AssocTypes.end(), + getTrailingObjects()); } GenericSelectionExpr::GenericSelectionExpr( @@ -3812,17 +3812,57 @@ /*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) { + 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); + GenericSelectionExprBits.GenericLoc = GenericLoc; + getTrailingObjects()[ControllingIndex] = ControllingExpr; std::copy(AssocExprs.begin(), AssocExprs.end(), - SubExprs + AssocExprStartIndex); + getTrailingObjects() + AssocExprStartIndex); + 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: cfe/trunk/lib/Sema/SemaExpr.cpp =================================================================== --- cfe/trunk/lib/Sema/SemaExpr.cpp +++ cfe/trunk/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: cfe/trunk/lib/Sema/SemaExprObjC.cpp =================================================================== --- cfe/trunk/lib/Sema/SemaExprObjC.cpp +++ cfe/trunk/lib/Sema/SemaExprObjC.cpp @@ -4342,13 +4342,10 @@ subExprs[i] = 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: cfe/trunk/lib/Sema/SemaOverload.cpp =================================================================== --- cfe/trunk/lib/Sema/SemaOverload.cpp +++ cfe/trunk/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: cfe/trunk/lib/Sema/SemaPseudoObject.cpp =================================================================== --- cfe/trunk/lib/Sema/SemaPseudoObject.cpp +++ cfe/trunk/lib/Sema/SemaPseudoObject.cpp @@ -150,15 +150,10 @@ assocTypes[i] = gse->getAssocTypeSourceInfo(i); } - 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: cfe/trunk/lib/Serialization/ASTReaderStmt.cpp =================================================================== --- cfe/trunk/lib/Serialization/ASTReaderStmt.cpp +++ cfe/trunk/lib/Serialization/ASTReaderStmt.cpp @@ -1022,23 +1022,24 @@ void ASTStmtReader::VisitGenericSelectionExpr(GenericSelectionExpr *E) { VisitExpr(E); - E->NumAssocs = Record.readInt(); - 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::ControllingIndex] = Record.readSubExpr(); - for (unsigned I = 0, N = E->getNumAssocs(); I != N; ++I) { - E->AssocTypes[I] = GetTypeSourceInfo(); - E->SubExprs[GenericSelectionExpr::AssocExprStartIndex + I] = - Record.readSubExpr(); - } - 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(); + // Add 1 to account for the controlling expression which is the first + // expression in the trailing array of Stmt *. This is not needed for + // the trailing array of TypeSourceInfo *. + 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) { @@ -2677,7 +2678,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: cfe/trunk/lib/Serialization/ASTWriterStmt.cpp =================================================================== --- cfe/trunk/lib/Serialization/ASTWriterStmt.cpp +++ cfe/trunk/lib/Serialization/ASTWriterStmt.cpp @@ -968,18 +968,24 @@ 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.AddSourceLocation(E->getGenericLoc()); Record.AddSourceLocation(E->getDefaultLoc()); Record.AddSourceLocation(E->getRParenLoc()); + + Stmt **Stmts = E->getTrailingObjects(); + // Add 1 to account for the controlling expression which is the first + // expression in the trailing array of Stmt *. This is not needed for + // the trailing array of TypeSourceInfo *. + 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; }