From a2bd2164c0c78e9bc1b91efd02ebc7bb85cf6616 Mon Sep 17 00:00:00 2001 From: Dan Katz Date: Mon, 30 Jun 2025 14:18:21 -0400 Subject: [PATCH] Serialization/Deserialization of expansion statements. Should fix #165. --- clang/include/clang/AST/ExprCXX.h | 35 ++++++ clang/include/clang/AST/StmtCXX.h | 12 +- .../include/clang/Serialization/ASTBitCodes.h | 5 +- clang/lib/AST/ExprCXX.cpp | 49 ++++++++ clang/lib/AST/StmtCXX.cpp | 9 +- clang/lib/Serialization/ASTReaderStmt.cpp | 108 ++++++++++++++++-- clang/lib/Serialization/ASTWriterStmt.cpp | 82 ++++++++++--- .../reflection/example-module.cppm | 18 +++ .../reflection/module-imports.sh.cpp | 4 +- 9 files changed, 290 insertions(+), 32 deletions(-) diff --git a/clang/include/clang/AST/ExprCXX.h b/clang/include/clang/AST/ExprCXX.h index e7731aa144e8..be1e51ae8175 100644 --- a/clang/include/clang/AST/ExprCXX.h +++ b/clang/include/clang/AST/ExprCXX.h @@ -5923,12 +5923,17 @@ class CXXExpansionInitListExpr : public Expr { unsigned NumSubExprs, SourceLocation LBraceLoc, SourceLocation RBraceLoc); + CXXExpansionInitListExpr(EmptyShell Empty); + public: static CXXExpansionInitListExpr *Create(const ASTContext &C, Expr **SubExprs, unsigned NumSubExprs, SourceLocation LBraceLoc, SourceLocation RBraceLoc); + static CXXExpansionInitListExpr *Create(const ASTContext &C, + EmptyShell Empty); + ArrayRef getSubExprs() const { return {SubExprs, NumSubExprs}; } bool containsPack() const { return ContainsPack; } @@ -5954,6 +5959,8 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == CXXExpansionInitListExprClass; } + + friend class ASTStmtReader; }; class CXXIterableExpansionSelectExpr : public Expr { @@ -5962,10 +5969,15 @@ class CXXIterableExpansionSelectExpr : public Expr { CXXIterableExpansionSelectExpr(QualType ResultTy, VarDecl *DD, Expr *Impl); + CXXIterableExpansionSelectExpr(EmptyShell Empty); + public: static CXXIterableExpansionSelectExpr *Create(const ASTContext &C, VarDecl *RangeVar, Expr *Impl); + static CXXIterableExpansionSelectExpr *Create(const ASTContext &C, + EmptyShell Empty); + Expr *getImplExpr() const { return ImplExpr; } VarDecl *getRangeVar() const { return RangeVar; } @@ -5990,6 +6002,8 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == CXXIterableExpansionSelectExprClass; } + + friend class ASTStmtReader; }; class CXXDestructurableExpansionSelectExpr : public Expr { @@ -6000,12 +6014,17 @@ class CXXDestructurableExpansionSelectExpr : public Expr { CXXDestructurableExpansionSelectExpr(QualType ResultTy, DecompositionDecl *DD, Expr *Idx, VarDecl *ExpansionVar); + CXXDestructurableExpansionSelectExpr(EmptyShell Empty); + public: static CXXDestructurableExpansionSelectExpr *Create(const ASTContext &C, DecompositionDecl *DD, Expr *Idx, VarDecl *ExpansionVar); + static CXXDestructurableExpansionSelectExpr *Create(const ASTContext &C, + EmptyShell Empty); + Expr *getIdxExpr() const { return IdxExpr; } DecompositionDecl *getDecompositionDecl() const { return DD; } VarDecl *getExpansionVar() const { return ExpansionVar; } @@ -6027,6 +6046,8 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == CXXDestructurableExpansionSelectExprClass; } + + friend class ASTStmtReader; }; class CXXIndeterminateExpansionSelectExpr : public Expr { @@ -6042,11 +6063,16 @@ class CXXIndeterminateExpansionSelectExpr : public Expr { unsigned NumLifetimeExtendTemps, MaterializeTemporaryExpr **LifetimeExtendTemps); + CXXIndeterminateExpansionSelectExpr(EmptyShell Empty); + public: static CXXIndeterminateExpansionSelectExpr *Create( const ASTContext &C, Expr *Range, Expr *Idx, VarDecl *ExpansionVar, ArrayRef LifetimeExtendTemps); + static CXXIndeterminateExpansionSelectExpr *Create(const ASTContext &C, + EmptyShell Empty); + Expr *getRangeExpr() const { return SubExprs[0]; } Expr *getIdxExpr() const { return SubExprs[1]; } VarDecl *getExpansionVar() const { return ExpansionVar; } @@ -6069,6 +6095,8 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == CXXIndeterminateExpansionSelectExprClass; } + + friend class ASTStmtReader; }; class CXXExpansionInitListSelectExpr : public Expr { @@ -6076,10 +6104,15 @@ class CXXExpansionInitListSelectExpr : public Expr { CXXExpansionInitListSelectExpr(QualType ResultTy, Expr *Range, Expr *Idx); + CXXExpansionInitListSelectExpr(EmptyShell Empty); + public: static CXXExpansionInitListSelectExpr *Create(const ASTContext &C, Expr *Range, Expr *Idx); + static CXXExpansionInitListSelectExpr *Create(const ASTContext &C, + EmptyShell Empty); + Expr *getRangeExpr() const { return SubExprs[0]; } Expr *getIdxExpr() const { return SubExprs[1]; } @@ -6100,6 +6133,8 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == CXXExpansionInitListSelectExprClass; } + + friend class ASTStmtReader; }; } // namespace clang diff --git a/clang/include/clang/AST/StmtCXX.h b/clang/include/clang/AST/StmtCXX.h index d6096f44373c..ac1d94a3738f 100644 --- a/clang/include/clang/AST/StmtCXX.h +++ b/clang/include/clang/AST/StmtCXX.h @@ -584,7 +584,9 @@ public: } - Expr *getSizeExpr() { return cast(SubStmts[SIZE]); } + Expr *getSizeExpr() { + return SubStmts[SIZE] ? cast(SubStmts[SIZE]) : nullptr; + } const Expr *getSizeExpr() const { return const_cast(this)->getSizeExpr(); } @@ -670,6 +672,8 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == CXXIndeterminateExpansionStmtClass; } + + friend class ASTStmtReader; }; /// CXXIterableExpansionStmt - Expansion over a iterable expression. @@ -712,6 +716,8 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == CXXIterableExpansionStmtClass; } + + friend class ASTStmtReader; }; /// CXXDestructurableExpansionStmt - Expansion over a destructurable expression. @@ -750,6 +756,8 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == CXXDestructurableExpansionStmtClass; } + + friend class ASTStmtReader; }; /// CXXInitListExpansionStmt - Expansion over an expansion-init-list. @@ -786,6 +794,8 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == CXXInitListExpansionStmtClass; } + + friend class ASTStmtReader; }; } // end namespace clang diff --git a/clang/include/clang/Serialization/ASTBitCodes.h b/clang/include/clang/Serialization/ASTBitCodes.h index 144c9be7c2bc..ddbb14356491 100644 --- a/clang/include/clang/Serialization/ASTBitCodes.h +++ b/clang/include/clang/Serialization/ASTBitCodes.h @@ -2054,7 +2054,10 @@ enum StmtCode { STMT_ITERABLE_EXPANSION, STMT_DESTRUCTURABLE_EXPANSION, STMT_INIT_LIST_EXPANSION, - EXPR_EXPANSION_SELECT, + EXPR_INDETERMINATE_EXPANSION_SELECT, + EXPR_ITERABLE_EXPANSION_SELECT, + EXPR_DESTRUCTURABLE_EXPANSION_SELECT, + EXPR_INIT_LIST_EXPANSION_SELECT, EXPR_EXPANSION_INIT_LIST, // FixedPointLiteral diff --git a/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp index c75827e29c87..b675ba1b8e78 100644 --- a/clang/lib/AST/ExprCXX.cpp +++ b/clang/lib/AST/ExprCXX.cpp @@ -2132,6 +2132,10 @@ CXXExpansionInitListExpr::CXXExpansionInitListExpr( setDependence(computeDependence(this)); } +CXXExpansionInitListExpr::CXXExpansionInitListExpr(EmptyShell Empty) + : Expr(CXXExpansionInitListExprClass, Empty) { +} + CXXExpansionInitListExpr *CXXExpansionInitListExpr::Create( const ASTContext &C, Expr ** SubExprs, unsigned NumSubExprs, SourceLocation LBraceLoc, SourceLocation RBraceLoc) { @@ -2139,6 +2143,11 @@ CXXExpansionInitListExpr *CXXExpansionInitListExpr::Create( LBraceLoc, RBraceLoc); } +CXXExpansionInitListExpr *CXXExpansionInitListExpr::Create( + const ASTContext &C, EmptyShell Empty) { + return new (C) CXXExpansionInitListExpr(Empty); +} + CXXIndeterminateExpansionSelectExpr::CXXIndeterminateExpansionSelectExpr( QualType ResultTy, Expr *Range, Expr *Idx, VarDecl *ExpansionVar, unsigned NumLifetimeExtendTemps, @@ -2151,6 +2160,11 @@ CXXIndeterminateExpansionSelectExpr::CXXIndeterminateExpansionSelectExpr( setDependence(computeDependence(this)); } +CXXIndeterminateExpansionSelectExpr::CXXIndeterminateExpansionSelectExpr( + EmptyShell Empty) + : Expr(CXXIndeterminateExpansionSelectExprClass, Empty) { +} + CXXIndeterminateExpansionSelectExpr * CXXIndeterminateExpansionSelectExpr::Create( const ASTContext &C, Expr *Range, Expr *Idx, VarDecl *ExpansionVar, @@ -2163,6 +2177,12 @@ CXXIndeterminateExpansionSelectExpr::Create( temps); } +CXXIndeterminateExpansionSelectExpr * +CXXIndeterminateExpansionSelectExpr::Create(const ASTContext &C, + EmptyShell Empty) { + return new (C) CXXIndeterminateExpansionSelectExpr(Empty); +} + ArrayRef CXXIndeterminateExpansionSelectExpr::getLifetimeExtendTemps() const { return ArrayRef(LifetimeExtendTemps, @@ -2177,12 +2197,21 @@ CXXIterableExpansionSelectExpr::CXXIterableExpansionSelectExpr( setDependence(computeDependence(this)); } +CXXIterableExpansionSelectExpr::CXXIterableExpansionSelectExpr(EmptyShell Empty) + : Expr(CXXIterableExpansionSelectExprClass, Empty) { +} + CXXIterableExpansionSelectExpr * CXXIterableExpansionSelectExpr::Create(const ASTContext &C, VarDecl *RangeVar, Expr *Impl) { return new (C) CXXIterableExpansionSelectExpr(C.DependentTy, RangeVar, Impl); } +CXXIterableExpansionSelectExpr * +CXXIterableExpansionSelectExpr::Create(const ASTContext &C, EmptyShell Empty) { + return new (C) CXXIterableExpansionSelectExpr(Empty); +} + CXXDestructurableExpansionSelectExpr::CXXDestructurableExpansionSelectExpr( QualType ResultTy, DecompositionDecl *DD, Expr *Idx, VarDecl *ExpansionVar) @@ -2192,6 +2221,11 @@ CXXDestructurableExpansionSelectExpr::CXXDestructurableExpansionSelectExpr( setDependence(computeDependence(this)); } +CXXDestructurableExpansionSelectExpr::CXXDestructurableExpansionSelectExpr( + EmptyShell Empty) + : Expr(CXXDestructurableExpansionSelectExprClass, Empty) { +} + CXXDestructurableExpansionSelectExpr * CXXDestructurableExpansionSelectExpr::Create(const ASTContext &C, DecompositionDecl *DD, Expr *Idx, @@ -2200,6 +2234,12 @@ CXXDestructurableExpansionSelectExpr::Create(const ASTContext &C, ExpansionVar); } +CXXDestructurableExpansionSelectExpr * +CXXDestructurableExpansionSelectExpr::Create(const ASTContext &C, + EmptyShell Empty) { + return new (C) CXXDestructurableExpansionSelectExpr(Empty); +} + CXXExpansionInitListSelectExpr::CXXExpansionInitListSelectExpr( QualType ResultTy, Expr *Range, Expr *Idx) : Expr(CXXExpansionInitListSelectExprClass, ResultTy, VK_PRValue, @@ -2208,12 +2248,21 @@ CXXExpansionInitListSelectExpr::CXXExpansionInitListSelectExpr( setDependence(computeDependence(this)); } +CXXExpansionInitListSelectExpr::CXXExpansionInitListSelectExpr(EmptyShell Empty) + : Expr(CXXExpansionInitListSelectExprClass, Empty) { +} + CXXExpansionInitListSelectExpr * CXXExpansionInitListSelectExpr::Create(const ASTContext &C, Expr *Range, Expr *Idx) { return new (C) CXXExpansionInitListSelectExpr(C.DependentTy, Range, Idx); } +CXXExpansionInitListSelectExpr * +CXXExpansionInitListSelectExpr::Create(const ASTContext &C, EmptyShell Empty) { + return new (C) CXXExpansionInitListSelectExpr(Empty); +} + CUDAKernelCallExpr::CUDAKernelCallExpr(Expr *Fn, CallExpr *Config, ArrayRef Args, QualType Ty, ExprValueKind VK, SourceLocation RP, diff --git a/clang/lib/AST/StmtCXX.cpp b/clang/lib/AST/StmtCXX.cpp index fe562cd65f9d..e8c580840011 100644 --- a/clang/lib/AST/StmtCXX.cpp +++ b/clang/lib/AST/StmtCXX.cpp @@ -181,6 +181,11 @@ CXXIndeterminateExpansionStmt *CXXIndeterminateExpansionStmt::Create( ColonLoc, RParenLoc, TParamRef); } +CXXIndeterminateExpansionStmt *CXXIndeterminateExpansionStmt::Create( + const ASTContext &C, EmptyShell Empty) { + return new (C) CXXIndeterminateExpansionStmt(Empty); +} + CXXIterableExpansionStmt *CXXIterableExpansionStmt::Create( const ASTContext &C, Stmt *Init, DeclStmt *ExpansionVar, Expr *SizeExpr, unsigned NumInstantiations, SourceLocation TemplateKWLoc, @@ -194,7 +199,7 @@ CXXIterableExpansionStmt *CXXIterableExpansionStmt::Create( CXXIterableExpansionStmt *CXXIterableExpansionStmt::Create(const ASTContext &C, EmptyShell Empty) { - return new CXXIterableExpansionStmt(Empty); + return new (C) CXXIterableExpansionStmt(Empty); } bool CXXIterableExpansionStmt::hasDependentSize() const { @@ -218,7 +223,7 @@ CXXDestructurableExpansionStmt *CXXDestructurableExpansionStmt::Create( CXXDestructurableExpansionStmt *CXXDestructurableExpansionStmt::Create( const ASTContext &C, EmptyShell Empty) { - return new CXXDestructurableExpansionStmt(Empty); + return new (C) CXXDestructurableExpansionStmt(Empty); } bool CXXDestructurableExpansionStmt::hasDependentSize() const { diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp index 4c97cd601514..0671cdceba67 100644 --- a/clang/lib/Serialization/ASTReaderStmt.cpp +++ b/clang/lib/Serialization/ASTReaderStmt.cpp @@ -551,46 +551,100 @@ void ASTStmtReader::VisitExplDependentCallExpr(ExplDependentCallExpr *E) { llvm_unreachable("unimplemented"); } +void ASTStmtReader::VisitCXXExpansionStmt(CXXExpansionStmt *S) { + VisitStmt(S); + + S->TemplateKWLoc = Record.readSourceLocation(); + S->ForLoc = Record.readSourceLocation(); + S->LParenLoc = Record.readSourceLocation(); + S->ColonLoc = Record.readSourceLocation(); + S->RParenLoc = Record.readSourceLocation(); + + S->SubStmts[CXXExpansionStmt::INIT] = Record.readStmt(); + S->SubStmts[CXXExpansionStmt::TPARAM] = Record.readStmt(); + S->SubStmts[CXXExpansionStmt::VAR] = Record.readStmt(); + S->SubStmts[CXXExpansionStmt::SIZE] = Record.readStmt(); + S->SubStmts[CXXExpansionStmt::BODY] = Record.readStmt(); + + if (unsigned NumExpansions = Record.readUInt32(); NumExpansions > 0) { + Stmt **Expansions = new (Record.getContext()) Stmt *[NumExpansions]; + for (size_t k = 0; k < NumExpansions; ++k) + Expansions[k] = Record.readStmt(); + S->Expansions = Expansions; + } +} + void ASTStmtReader::VisitCXXIndeterminateExpansionStmt( CXXIndeterminateExpansionStmt *S) { - llvm_unreachable("unimplemented"); + VisitCXXExpansionStmt(S); } void ASTStmtReader::VisitCXXIterableExpansionStmt(CXXIterableExpansionStmt *S) { - llvm_unreachable("unimplemented"); + VisitCXXExpansionStmt(S); + + S->NumInstantiations = Record.readUInt32(); } void ASTStmtReader::VisitCXXDestructurableExpansionStmt( CXXDestructurableExpansionStmt *S) { - llvm_unreachable("unimplemented"); + VisitCXXExpansionStmt(S); } void ASTStmtReader::VisitCXXInitListExpansionStmt(CXXInitListExpansionStmt *S) { - llvm_unreachable("unimplemented"); + VisitCXXExpansionStmt(S); } void ASTStmtReader::VisitCXXIndeterminateExpansionSelectExpr( CXXIndeterminateExpansionSelectExpr *E) { - llvm_unreachable("unimplemented"); + VisitExpr(E); + + E->SubExprs[0] = Record.readExpr(); + E->SubExprs[1] = Record.readExpr(); + E->ExpansionVar = readDeclAs(); + + E->NumLifetimeExtendTemps = Record.readUInt32(); + Expr **Temps = new (Record.getContext()) Expr *[E->NumLifetimeExtendTemps]; + for (size_t k = 0; k < E->NumLifetimeExtendTemps; ++k) + Temps[k] = Record.readExpr(); + E->LifetimeExtendTemps = reinterpret_cast(Temps); } void ASTStmtReader::VisitCXXIterableExpansionSelectExpr( CXXIterableExpansionSelectExpr *E) { - llvm_unreachable("unimplemented"); + VisitExpr(E); + + E->ImplExpr = Record.readExpr(); + E->RangeVar = readDeclAs(); } void ASTStmtReader::VisitCXXDestructurableExpansionSelectExpr( CXXDestructurableExpansionSelectExpr *E) { - llvm_unreachable("unimplemented"); + VisitExpr(E); + + E->IdxExpr = Record.readExpr(); + E->DD = Record.readDeclAs(); + E->ExpansionVar = Record.readDeclAs(); } void ASTStmtReader::VisitCXXExpansionInitListSelectExpr( CXXExpansionInitListSelectExpr *E) { - llvm_unreachable("unimplemented"); + VisitExpr(E); + + E->SubExprs[0] = Record.readExpr(); + E->SubExprs[1] = Record.readExpr(); } void ASTStmtReader::VisitCXXExpansionInitListExpr(CXXExpansionInitListExpr *E) { - llvm_unreachable("unimplemented"); + VisitExpr(E); + + E->LBraceLoc = readSourceLocation(); + E->RBraceLoc = readSourceLocation(); + + E->NumSubExprs = Record.readUInt32(); + Expr **SubExprs = new (Record.getContext()) Expr *[E->NumSubExprs]; + for (size_t k = 0; k < E->NumSubExprs; ++k) + SubExprs[k] = Record.readExpr(); + E->SubExprs = SubExprs; } void ASTStmtReader::VisitDependentCoawaitExpr(DependentCoawaitExpr *E) { @@ -4613,6 +4667,42 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { S = CXXDependentMemberSpliceExpr::CreateEmpty(Context); break; } + case STMT_INDETERMINATE_EXPANSION: { + S = CXXIndeterminateExpansionStmt::Create(Context, Empty); + break; + } + case STMT_ITERABLE_EXPANSION: { + S = CXXIterableExpansionStmt::Create(Context, Empty); + break; + } + case STMT_DESTRUCTURABLE_EXPANSION: { + S = CXXDestructurableExpansionStmt::Create(Context, Empty); + break; + } + case STMT_INIT_LIST_EXPANSION: { + S = CXXInitListExpansionStmt::Create(Context, Empty); + break; + } + case EXPR_INDETERMINATE_EXPANSION_SELECT: { + S = CXXIndeterminateExpansionSelectExpr::Create(Context, Empty); + break; + } + case EXPR_ITERABLE_EXPANSION_SELECT: { + S = CXXIterableExpansionSelectExpr::Create(Context, Empty); + break; + } + case EXPR_DESTRUCTURABLE_EXPANSION_SELECT: { + S = CXXDestructurableExpansionSelectExpr::Create(Context, Empty); + break; + } + case EXPR_INIT_LIST_EXPANSION_SELECT: { + S = CXXExpansionInitListSelectExpr::Create(Context, Empty); + break; + } + case EXPR_EXPANSION_INIT_LIST: { + S = CXXExpansionInitListExpr::Create(Context, Empty); + break; + } } // We hit a STMT_STOP, so we're done with this expression. diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp index c0027d0ef583..087e3e2c01ca 100644 --- a/clang/lib/Serialization/ASTWriterStmt.cpp +++ b/clang/lib/Serialization/ASTWriterStmt.cpp @@ -535,63 +535,111 @@ void ASTStmtWriter::VisitExplDependentCallExpr(ExplDependentCallExpr *E) { Code = serialization::EXPR_EXPL_DEPENDENT_CALL; } +void ASTStmtWriter::VisitCXXExpansionStmt(CXXExpansionStmt *S) { + VisitStmt(S); + + Record.AddSourceLocation(S->getTemplateKWLoc()); + Record.AddSourceLocation(S->getForLoc()); + Record.AddSourceLocation(S->getLParenLoc()); + Record.AddSourceLocation(S->getColonLoc()); + Record.AddSourceLocation(S->getRParenLoc()); + + Record.AddStmt(S->getInit()); + Record.AddStmt(S->getTParamRef()); + Record.AddStmt(S->getExpansionVarStmt()); + Record.AddStmt(S->getSizeExpr()); + Record.AddStmt(S->getBody()); + + Record.writeUInt32(S->getNumInstantiations()); + for (size_t k = 0; k < S->getNumInstantiations(); ++k) + Record.AddStmt(S->getInstantiation(k)); +} + void ASTStmtWriter::VisitCXXIndeterminateExpansionStmt( CXXIndeterminateExpansionStmt *S) { - VisitStmt(S); - // TODO(P2996): Implement this. + VisitCXXExpansionStmt(S); + Code = serialization::STMT_INDETERMINATE_EXPANSION; } void ASTStmtWriter::VisitCXXIterableExpansionStmt(CXXIterableExpansionStmt *S) { - VisitStmt(S); - // TODO(P2996): Implement this. + VisitCXXExpansionStmt(S); + Record.writeUInt32(S->getNumInstantiations()); + Code = serialization::STMT_ITERABLE_EXPANSION; } void ASTStmtWriter::VisitCXXDestructurableExpansionStmt( CXXDestructurableExpansionStmt *S) { - VisitStmt(S); - // TODO(P2996): Implement this. + VisitCXXExpansionStmt(S); + Code = serialization::STMT_DESTRUCTURABLE_EXPANSION; } void ASTStmtWriter::VisitCXXInitListExpansionStmt(CXXInitListExpansionStmt *S) { - VisitStmt(S); - // TODO(P2996): Implement this. + VisitCXXExpansionStmt(S); + Code = serialization::STMT_INIT_LIST_EXPANSION; } void ASTStmtWriter::VisitCXXIndeterminateExpansionSelectExpr( CXXIndeterminateExpansionSelectExpr *E) { VisitExpr(E); - // TODO(P2996): Implement this. - Code = serialization::EXPR_EXPANSION_SELECT; + + Record.AddStmt(E->getRangeExpr()); + Record.AddStmt(E->getIdxExpr()); + Record.AddDeclRef(E->getExpansionVar()); + + auto Temps = E->getLifetimeExtendTemps(); + Record.writeUInt32(Temps.size()); + for (auto Temp : Temps) + Record.AddStmt(Temp); + + Code = serialization::EXPR_INDETERMINATE_EXPANSION_SELECT; } void ASTStmtWriter::VisitCXXIterableExpansionSelectExpr( CXXIterableExpansionSelectExpr *E) { VisitExpr(E); - // TODO(P2996): Implement this. - Code = serialization::EXPR_EXPANSION_SELECT; + + Record.AddStmt(E->getImplExpr()); + Record.AddDeclRef(E->getRangeVar()); + + Code = serialization::EXPR_ITERABLE_EXPANSION_SELECT; } void ASTStmtWriter::VisitCXXDestructurableExpansionSelectExpr( CXXDestructurableExpansionSelectExpr *E) { VisitExpr(E); - // TODO(P2996): Implement this. - Code = serialization::EXPR_EXPANSION_SELECT; + + Record.AddStmt(E->getIdxExpr()); + Record.AddDeclRef(E->getDecompositionDecl()); + Record.AddDeclRef(E->getExpansionVar()); + + Code = serialization::EXPR_DESTRUCTURABLE_EXPANSION_SELECT; } void ASTStmtWriter::VisitCXXExpansionInitListSelectExpr( CXXExpansionInitListSelectExpr *E) { VisitExpr(E); - // TODO(P2996): Implement this. - Code = serialization::EXPR_EXPANSION_SELECT; + + Record.AddStmt(E->getRangeExpr()); + Record.AddStmt(E->getIdxExpr()); + + Code = serialization::EXPR_INIT_LIST_EXPANSION_SELECT; } void ASTStmtWriter::VisitCXXExpansionInitListExpr(CXXExpansionInitListExpr *E) { VisitExpr(E); - // TODO(P2996): Implement this. + + Record.AddSourceLocation(E->getLBraceLoc()); + Record.AddSourceLocation(E->getRBraceLoc()); + + auto Exprs = E->getSubExprs(); + Record.writeUInt32(Exprs.size()); + for (Expr *E : Exprs) + Record.AddStmt(E); + Code = serialization::EXPR_EXPANSION_INIT_LIST; } diff --git a/libcxx/test/std/experimental/reflection/example-module.cppm b/libcxx/test/std/experimental/reflection/example-module.cppm index 7bf598da440e..73bae16077e6 100644 --- a/libcxx/test/std/experimental/reflection/example-module.cppm +++ b/libcxx/test/std/experimental/reflection/example-module.cppm @@ -1,5 +1,6 @@ module; #include +#include export module Example; namespace Example { @@ -73,4 +74,21 @@ export constexpr auto rBase2 = bases_of(^^Child, ctx)[1]; export constexpr auto rTDMS = data_member_spec(^^int, {.name="test"}); + // ==================== + // Expansion statements + // ==================== + +void test() { + // Iterating expansion statement. + constexpr static auto sequence = std::array{0, 1, 2, 3, 4}; + template for (constexpr auto i : sequence) { (void) i; } + + // Destructurable expansion statement. + constexpr auto tup = std::make_tuple(1, true, 'c'); + template for (constexpr auto i : tup) { (void) i; } + + // Enumerating expansion statement. + template for (auto i : {1, 2, 3}) { (void) i; } +} + } // namespace Example diff --git a/libcxx/test/std/experimental/reflection/module-imports.sh.cpp b/libcxx/test/std/experimental/reflection/module-imports.sh.cpp index e82eabfdac0d..7f19abb52964 100644 --- a/libcxx/test/std/experimental/reflection/module-imports.sh.cpp +++ b/libcxx/test/std/experimental/reflection/module-imports.sh.cpp @@ -2,10 +2,10 @@ // // RUN: mkdir %t // RUN: %{cxx} %{compile_flags} -std=c++26 \ -// RUN: -freflection -fparameter-reflection \ +// RUN: -freflection-latest \ // RUN: --precompile example-module.cppm -o %t/example-module.pcm // RUN: %{cxx} %{compile_flags} %{link_flags} -std=c++26 \ -// RUN: -freflection -fparameter-reflection \ +// RUN: -freflection-latest \ // RUN: -fmodule-file=Example=%t/example-module.pcm %t/example-module.pcm \ // RUN: module-imports.sh.cpp -o %t/module-imports.sh.cpp.tsk // RUN: %t/module-imports.sh.cpp.tsk > %t/stdout.txt