[clang] [Clang][C++26] Implement Pack Indexing (P2662R3). (PR #72644)
Erich Keane via cfe-commits
cfe-commits at lists.llvm.org
Fri Jan 12 11:10:26 PST 2024
================
@@ -4344,6 +4344,108 @@ class SizeOfPackExpr final
}
};
+class PackIndexingExpr final
+ : public Expr,
+ private llvm::TrailingObjects<PackIndexingExpr, Expr *> {
+ friend class ASTStmtReader;
+ friend class ASTStmtWriter;
+ friend TrailingObjects;
+
+ SourceLocation EllipsisLoc;
+
+ // The location of the closing bracket
+ SourceLocation RSquareLoc;
+
+ // The pack being indexed, followed by the index
+ Stmt *SubExprs[2];
+
+ size_t TransformedExpressions;
+
+ PackIndexingExpr(QualType Type, SourceLocation EllipsisLoc,
+ SourceLocation RSquareLoc, Expr *PackIdExpr, Expr *IndexExpr,
+ ArrayRef<Expr *> SubstitutedExprs = {})
+ : Expr(PackIndexingExprClass, Type, VK_LValue, OK_Ordinary),
+ EllipsisLoc(EllipsisLoc), RSquareLoc(RSquareLoc),
+ SubExprs{PackIdExpr, IndexExpr},
+ TransformedExpressions(SubstitutedExprs.size()) {
+
+ auto *Exprs = getTrailingObjects<Expr *>();
+ std::uninitialized_copy(SubstitutedExprs.begin(), SubstitutedExprs.end(),
+ Exprs);
+
+ setDependence(computeDependence(this));
+ if(!isInstantiationDependent())
+ setValueKind(getSelectedExpr()->getValueKind());
+ }
+
+ /// Create an empty expression.
+ PackIndexingExpr(EmptyShell Empty) : Expr(PackIndexingExprClass, Empty) {}
+
+ unsigned numTrailingObjects(OverloadToken<Expr *>) const {
+ return TransformedExpressions;
+ }
+
+public:
+ static PackIndexingExpr *Create(ASTContext &Context,
+ SourceLocation EllipsisLoc,
+ SourceLocation RSquareLoc, Expr *PackIdExpr,
+ Expr *IndexExpr, std::optional<int64_t> Index,
+ ArrayRef<Expr *> SubstitutedExprs = {});
+ static PackIndexingExpr *CreateDeserialized(ASTContext &Context,
+ unsigned NumTransformedExprs);
+
+ /// Determine the location of the 'sizeof' keyword.
+ SourceLocation getEllipsisLoc() const { return EllipsisLoc; }
+
+ /// Determine the location of the parameter pack.
+ SourceLocation getPackLoc() const { return SubExprs[0]->getBeginLoc(); }
+
+ /// Determine the location of the right parenthesis.
+ SourceLocation getRSquareLoc() const { return RSquareLoc; }
+
+ SourceLocation getBeginLoc() const LLVM_READONLY { return getPackLoc(); }
+ SourceLocation getEndLoc() const LLVM_READONLY { return RSquareLoc; }
+
+ Expr *getPackIdExpression() const { return cast<Expr>(SubExprs[0]); }
+
+ NamedDecl *getPackDecl() const;
+
+ Expr *getIndexExpr() const { return cast<Expr>(SubExprs[1]); }
+
+
+ std::optional<unsigned> getSelectedIndex() const {
+ if (isInstantiationDependent())
+ return std::nullopt;
+ ConstantExpr* CE = cast<ConstantExpr>(getIndexExpr());
+ auto Index = CE->getResultAsAPSInt();
+ assert(Index.isNonNegative() && "Invalid index");
+ return static_cast<unsigned>(Index.getExtValue());
+ }
+
+ Expr *getSelectedExpr() const {
+ std::optional<unsigned> Index = getSelectedIndex();
+ assert(Index && "extracting the indexed expression of a dependant pack");
+ return getTrailingObjects<Expr *>()[*Index];
+ }
+
+ ArrayRef<Expr *> getExpressions() const {
+ if (TransformedExpressions == 0)
----------------
erichkeane wrote:
Is this test necessary? Worst case it just gives an empty collection, right?
https://github.com/llvm/llvm-project/pull/72644
More information about the cfe-commits
mailing list