Index: include/clang/AST/Expr.h =================================================================== --- include/clang/AST/Expr.h +++ include/clang/AST/Expr.h @@ -5040,37 +5040,50 @@ explicit GenericSelectionExpr(EmptyShell Empty) : Expr(GenericSelectionExprClass, Empty) { } + class Association { + Expr *E; + TypeSourceInfo *TSI; + bool Selected; + + public: + Association(Expr *E, TypeSourceInfo *TSI, bool Selected) + : E(E), TSI(TSI), Selected(Selected) {} + + Expr *getExpr() { return E; } + const Expr *getExpr() const { return E; } + TypeSourceInfo *getTypeSourceInfo() { return TSI; } + const TypeSourceInfo *getTypeSourceInfo() const { return TSI; } + + QualType getType() const { + if (TSI) + return TSI->getType(); + return QualType(); + } + + bool IsSelected() const { return Selected; } + }; + unsigned getNumAssocs() const { return NumAssocs; } + Association getAssociation(unsigned I) const { + return Association(cast(SubExprs[END_EXPR + I]), AssocTypes[I], + !isResultDependent() && getResultIndex() == I); + } + 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]); } @@ -5089,8 +5102,12 @@ /// 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()); } + const Expr *getResultExpr() const { + return cast(SubExprs[END_EXPR + getResultIndex()]); + } + Expr *getResultExpr() { + return cast(SubExprs[END_EXPR + getResultIndex()]); + } SourceLocation getBeginLoc() const LLVM_READONLY { return GenericLoc; } SourceLocation getEndLoc() const LLVM_READONLY { return RParenLoc; } Index: include/clang/AST/RecursiveASTVisitor.h =================================================================== --- include/clang/AST/RecursiveASTVisitor.h +++ include/clang/AST/RecursiveASTVisitor.h @@ -2301,9 +2301,10 @@ DEF_TRAVERSE_STMT(GenericSelectionExpr, { TRY_TO(TraverseStmt(S->getControllingExpr())); for (unsigned i = 0; i != S->getNumAssocs(); ++i) { - if (TypeSourceInfo *TS = S->getAssocTypeSourceInfo(i)) + auto Assoc = S->getAssociation(i); + if (const TypeSourceInfo *TS = Assoc.getTypeSourceInfo()) TRY_TO(TraverseTypeLoc(TS->getTypeLoc())); - TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getAssocExpr(i)); + TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(Assoc.getExpr()); } ShouldVisitChildren = false; }) Index: include/clang/AST/StmtDataCollectors.td =================================================================== --- include/clang/AST/StmtDataCollectors.td +++ include/clang/AST/StmtDataCollectors.td @@ -190,7 +190,7 @@ class GenericSelectionExpr { code Code = [{ for (unsigned i = 0; i < S->getNumAssocs(); ++i) { - addData(S->getAssocType(i)); + addData(S->getAssociation(i).getType()); } }]; } Index: lib/AST/ASTDumper.cpp =================================================================== --- lib/AST/ASTDumper.cpp +++ lib/AST/ASTDumper.cpp @@ -1464,19 +1464,21 @@ for (unsigned I = 0, N = E->getNumAssocs(); I != N; ++I) { dumpChild([=] { - if (const TypeSourceInfo *TSI = E->getAssocTypeSourceInfo(I)) { + const auto Assoc = E->getAssociation(I); + const TypeSourceInfo *TSI = Assoc.getTypeSourceInfo(); + if (TSI) { 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 (TSI) dumpTypeAsChild(TSI->getType()); - dumpStmt(E->getAssocExpr(I)); + dumpStmt(Assoc.getExpr()); }); } } Index: lib/AST/StmtPrinter.cpp =================================================================== --- lib/AST/StmtPrinter.cpp +++ lib/AST/StmtPrinter.cpp @@ -1263,13 +1263,14 @@ PrintExpr(Node->getControllingExpr()); for (unsigned i = 0; i != Node->getNumAssocs(); ++i) { OS << ", "; - QualType T = Node->getAssocType(i); + auto Assoc = Node->getAssociation(i); + QualType T = Assoc.getType(); if (T.isNull()) OS << "default"; else T.print(OS, Policy); OS << ": "; - PrintExpr(Node->getAssocExpr(i)); + PrintExpr(Assoc.getExpr()); } OS << ")"; } Index: lib/AST/StmtProfile.cpp =================================================================== --- lib/AST/StmtProfile.cpp +++ lib/AST/StmtProfile.cpp @@ -1260,12 +1260,13 @@ void StmtProfiler::VisitGenericSelectionExpr(const GenericSelectionExpr *S) { VisitExpr(S); for (unsigned i = 0; i != S->getNumAssocs(); ++i) { - QualType T = S->getAssocType(i); + auto Assoc = S->getAssociation(i); + QualType T = Assoc.getType(); if (T.isNull()) ID.AddPointer(nullptr); else VisitType(T); - VisitExpr(S->getAssocExpr(i)); + VisitExpr(Assoc.getExpr()); } } Index: lib/Sema/SemaExprObjC.cpp =================================================================== --- lib/Sema/SemaExprObjC.cpp +++ lib/Sema/SemaExprObjC.cpp @@ -4335,8 +4335,9 @@ SmallVector subExprs(n); SmallVector subTypes(n); for (unsigned i = 0; i != n; ++i) { - subTypes[i] = gse->getAssocTypeSourceInfo(i); - Expr *sub = gse->getAssocExpr(i); + auto Assoc = gse->getAssociation(i); + subTypes[i] = Assoc.getTypeSourceInfo(); + Expr *sub = Assoc.getExpr(); if (i == gse->getResultIndex()) sub = stripARCUnbridgedCast(sub); subExprs[i] = sub; Index: lib/Sema/SemaPseudoObject.cpp =================================================================== --- lib/Sema/SemaPseudoObject.cpp +++ lib/Sema/SemaPseudoObject.cpp @@ -144,10 +144,11 @@ SmallVector assocTypes(numAssocs); for (unsigned i = 0; i != numAssocs; ++i) { - Expr *assoc = gse->getAssocExpr(i); + auto A = gse->getAssociation(i); + Expr *assoc = A.getExpr(); if (i == resultIndex) assoc = rebuild(assoc); assocs[i] = assoc; - assocTypes[i] = gse->getAssocTypeSourceInfo(i); + assocTypes[i] = A.getTypeSourceInfo(); } return new (S.Context) GenericSelectionExpr(S.Context, Index: lib/Sema/TreeTransform.h =================================================================== --- lib/Sema/TreeTransform.h +++ lib/Sema/TreeTransform.h @@ -9072,7 +9072,8 @@ SmallVector AssocExprs; SmallVector AssocTypes; for (unsigned i = 0; i != E->getNumAssocs(); ++i) { - TypeSourceInfo *TS = E->getAssocTypeSourceInfo(i); + auto Assoc = E->getAssociation(i); + TypeSourceInfo *TS = Assoc.getTypeSourceInfo(); if (TS) { TypeSourceInfo *AssocType = getDerived().TransformType(TS); if (!AssocType) @@ -9082,7 +9083,7 @@ AssocTypes.push_back(nullptr); } - ExprResult AssocExpr = getDerived().TransformExpr(E->getAssocExpr(i)); + ExprResult AssocExpr = getDerived().TransformExpr(Assoc.getExpr()); if (AssocExpr.isInvalid()) return ExprError(); AssocExprs.push_back(AssocExpr.get()); Index: lib/Serialization/ASTWriterStmt.cpp =================================================================== --- lib/Serialization/ASTWriterStmt.cpp +++ lib/Serialization/ASTWriterStmt.cpp @@ -972,8 +972,9 @@ Record.AddStmt(E->getControllingExpr()); for (unsigned I = 0, N = E->getNumAssocs(); I != N; ++I) { - Record.AddTypeSourceInfo(E->getAssocTypeSourceInfo(I)); - Record.AddStmt(E->getAssocExpr(I)); + auto Assoc = E->getAssociation(I); + Record.AddTypeSourceInfo(Assoc.getTypeSourceInfo()); + Record.AddStmt(Assoc.getExpr()); } Record.push_back(E->isResultDependent() ? -1U : E->getResultIndex());