-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[Clang][C++26] Implement Pack Indexing (P2662R3). #72644
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
6ea0829
b2c99f7
e9acd75
eceb938
5da783b
5d127b8
23eff9a
992e342
523f9c1
b8e82eb
d4e696c
28ed1fe
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4331,6 +4331,105 @@ 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()) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is there good reason this isn't an assert? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's called from places that don't have another way to check whether an it would be valid. |
||
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 { | ||
return {getTrailingObjects<Expr *>(), TransformedExpressions}; | ||
} | ||
|
||
static bool classof(const Stmt *T) { | ||
return T->getStmtClass() == PackIndexingExprClass; | ||
} | ||
|
||
// Iterators | ||
child_range children() { return child_range(SubExprs, SubExprs + 2); } | ||
|
||
const_child_range children() const { | ||
return const_child_range(SubExprs, SubExprs + 2); | ||
} | ||
}; | ||
|
||
/// Represents a reference to a non-type template parameter | ||
/// that has been substituted with a template argument. | ||
class SubstNonTypeTemplateParmExpr : public Expr { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4934,6 +4934,73 @@ class DependentDecltypeType : public DecltypeType, public llvm::FoldingSetNode { | |
Expr *E); | ||
}; | ||
|
||
class PackIndexingType final | ||
: public Type, | ||
public llvm::FoldingSetNode, | ||
private llvm::TrailingObjects<PackIndexingType, QualType> { | ||
friend TrailingObjects; | ||
|
||
const ASTContext &Context; | ||
QualType Pattern; | ||
Expr *IndexExpr; | ||
|
||
unsigned Size; | ||
|
||
protected: | ||
friend class ASTContext; // ASTContext creates these. | ||
PackIndexingType(const ASTContext &Context, QualType Canonical, | ||
QualType Pattern, Expr *IndexExpr, | ||
ArrayRef<QualType> Expansions = {}); | ||
|
||
public: | ||
Expr *getIndexExpr() const { return IndexExpr; } | ||
QualType getPattern() const { return Pattern; } | ||
|
||
bool isSugared() const { return hasSelectedType(); } | ||
|
||
QualType desugar() const { | ||
if (hasSelectedType()) | ||
return getSelectedType(); | ||
return QualType(this, 0); | ||
} | ||
Comment on lines
+4961
to
+4965
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this correct? Calling Maybe the issue lies elsewhere, but something is strange with the error recovery for these types. Perhaps because |
||
|
||
QualType getSelectedType() const { | ||
assert(hasSelectedType() && "Type is dependant"); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Trying to dump/print a broken pack indexing expression/type breaks on this assertion. Try adding -ast-dump to cxx2c-pack-indexing.cpp and see what happens. |
||
return *(getExpansionsPtr() + *getSelectedIndex()); | ||
} | ||
|
||
std::optional<unsigned> getSelectedIndex() const; | ||
|
||
bool hasSelectedType() const { return getSelectedIndex() != std::nullopt; } | ||
|
||
ArrayRef<QualType> getExpansions() const { | ||
return {getExpansionsPtr(), Size}; | ||
} | ||
|
||
static bool classof(const Type *T) { | ||
return T->getTypeClass() == PackIndexing; | ||
} | ||
|
||
void Profile(llvm::FoldingSetNodeID &ID) { | ||
if (hasSelectedType()) | ||
getSelectedType().Profile(ID); | ||
else | ||
Profile(ID, Context, getPattern(), getIndexExpr()); | ||
} | ||
static void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context, | ||
QualType Pattern, Expr *E); | ||
|
||
private: | ||
const QualType *getExpansionsPtr() const { | ||
return getTrailingObjects<QualType>(); | ||
} | ||
|
||
static TypeDependence computeDependence(QualType Pattern, Expr *IndexExpr, | ||
ArrayRef<QualType> Expansions = {}); | ||
|
||
unsigned numTrailingObjects(OverloadToken<QualType>) const { return Size; } | ||
}; | ||
|
||
/// A unary type transform, which is a type constructed from another. | ||
class UnaryTransformType : public Type { | ||
public: | ||
|
Uh oh!
There was an error while loading. Please reload this page.