Skip to content

[Clang][P1061] Consolidate ResolvedUnpexandedPackExpr into FunctionParmPackExpr #125394

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

Merged
merged 6 commits into from
Feb 18, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 11 additions & 17 deletions clang/include/clang/AST/DeclCXX.h
Original file line number Diff line number Diff line change
Expand Up @@ -4194,8 +4194,8 @@ class BindingDecl : public ValueDecl {
/// decomposition declaration, and when the initializer is type-dependent.
Expr *getBinding() const { return Binding; }

// Get the array of Exprs when the binding represents a pack.
llvm::ArrayRef<Expr *> getBindingPackExprs() const;
// Get the array of nested BindingDecls when the binding represents a pack.
llvm::ArrayRef<BindingDecl *> getBindingPackDecls() const;

/// Get the decomposition declaration that this binding represents a
/// decomposition of.
Expand Down Expand Up @@ -4246,10 +4246,8 @@ class DecompositionDecl final
for (auto *B : Bindings) {
B->setDecomposedDecl(this);
if (B->isParameterPack() && B->getBinding()) {
for (Expr *E : B->getBindingPackExprs()) {
auto *DRE = cast<DeclRefExpr>(E);
auto *NestedB = cast<BindingDecl>(DRE->getDecl());
NestedB->setDecomposedDecl(this);
for (BindingDecl *NestedBD : B->getBindingPackDecls()) {
NestedBD->setDecomposedDecl(this);
}
}
}
Expand Down Expand Up @@ -4278,25 +4276,21 @@ class DecompositionDecl final
// Provide a flattened range to visit each binding.
auto flat_bindings() const {
llvm::ArrayRef<BindingDecl *> Bindings = bindings();
llvm::ArrayRef<Expr *> PackExprs;
llvm::ArrayRef<BindingDecl *> PackBindings;

// Split the bindings into subranges split by the pack.
auto S1 = Bindings.take_until(
llvm::ArrayRef<BindingDecl *> BeforePackBindings = Bindings.take_until(
[](BindingDecl *BD) { return BD->isParameterPack(); });

Bindings = Bindings.drop_front(S1.size());
Bindings = Bindings.drop_front(BeforePackBindings.size());
if (!Bindings.empty()) {
PackExprs = Bindings.front()->getBindingPackExprs();
PackBindings = Bindings.front()->getBindingPackDecls();
Bindings = Bindings.drop_front();
}

auto S2 = llvm::map_range(PackExprs, [](Expr *E) {
auto *DRE = cast<DeclRefExpr>(E);
return cast<BindingDecl>(DRE->getDecl());
});

return llvm::concat<BindingDecl *>(std::move(S1), std::move(S2),
std::move(Bindings));
return llvm::concat<BindingDecl *const>(std::move(BeforePackBindings),
std::move(PackBindings),
std::move(Bindings));
}

void printName(raw_ostream &OS, const PrintingPolicy &Policy) const override;
Expand Down
78 changes: 12 additions & 66 deletions clang/include/clang/AST/ExprCXX.h
Original file line number Diff line number Diff line change
Expand Up @@ -4633,8 +4633,8 @@ class SubstNonTypeTemplateParmPackExpr : public Expr {
}
};

/// Represents a reference to a function parameter pack or init-capture pack
/// that has been substituted but not yet expanded.
/// Represents a reference to a function parameter pack, init-capture pack,
/// or binding pack that has been substituted but not yet expanded.
///
/// When a pack expansion contains multiple parameter packs at different levels,
/// this node is used to represent a function parameter pack at an outer level
Expand All @@ -4649,49 +4649,48 @@ class SubstNonTypeTemplateParmPackExpr : public Expr {
/// \endcode
class FunctionParmPackExpr final
: public Expr,
private llvm::TrailingObjects<FunctionParmPackExpr, VarDecl *> {
private llvm::TrailingObjects<FunctionParmPackExpr, ValueDecl *> {
Comment on lines 4650 to +4652
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we also update the attached comments to reflect it now supports structure binding pack?

friend class ASTReader;
friend class ASTStmtReader;
friend TrailingObjects;

/// The function parameter pack which was referenced.
VarDecl *ParamPack;
ValueDecl *ParamPack;

/// The location of the function parameter pack reference.
SourceLocation NameLoc;

/// The number of expansions of this pack.
unsigned NumParameters;

FunctionParmPackExpr(QualType T, VarDecl *ParamPack,
SourceLocation NameLoc, unsigned NumParams,
VarDecl *const *Params);
FunctionParmPackExpr(QualType T, ValueDecl *ParamPack, SourceLocation NameLoc,
unsigned NumParams, ValueDecl *const *Params);

public:
static FunctionParmPackExpr *Create(const ASTContext &Context, QualType T,
VarDecl *ParamPack,
ValueDecl *ParamPack,
SourceLocation NameLoc,
ArrayRef<VarDecl *> Params);
ArrayRef<ValueDecl *> Params);
static FunctionParmPackExpr *CreateEmpty(const ASTContext &Context,
unsigned NumParams);

/// Get the parameter pack which this expression refers to.
VarDecl *getParameterPack() const { return ParamPack; }
ValueDecl *getParameterPack() const { return ParamPack; }

/// Get the location of the parameter pack.
SourceLocation getParameterPackLocation() const { return NameLoc; }

/// Iterators over the parameters which the parameter pack expanded
/// into.
using iterator = VarDecl * const *;
iterator begin() const { return getTrailingObjects<VarDecl *>(); }
using iterator = ValueDecl *const *;
iterator begin() const { return getTrailingObjects<ValueDecl *>(); }
iterator end() const { return begin() + NumParameters; }

/// Get the number of parameters in this parameter pack.
unsigned getNumExpansions() const { return NumParameters; }

/// Get an expansion of the parameter pack by index.
VarDecl *getExpansion(unsigned I) const { return begin()[I]; }
ValueDecl *getExpansion(unsigned I) const { return begin()[I]; }

SourceLocation getBeginLoc() const LLVM_READONLY { return NameLoc; }
SourceLocation getEndLoc() const LLVM_READONLY { return NameLoc; }
Expand Down Expand Up @@ -5319,59 +5318,6 @@ class BuiltinBitCastExpr final
}
};

// Represents an unexpanded pack where the list of expressions are
// known. These are used when structured bindings introduce a pack.
class ResolvedUnexpandedPackExpr final
: public Expr,
private llvm::TrailingObjects<ResolvedUnexpandedPackExpr, Expr *> {
friend class ASTStmtReader;
friend class ASTStmtWriter;
friend TrailingObjects;

SourceLocation BeginLoc;
unsigned NumExprs;

ResolvedUnexpandedPackExpr(SourceLocation BL, QualType QT, unsigned NumExprs);

public:
static ResolvedUnexpandedPackExpr *CreateDeserialized(ASTContext &C,
unsigned NumExprs);
static ResolvedUnexpandedPackExpr *
Create(ASTContext &C, SourceLocation BeginLoc, QualType T, unsigned NumExprs);
static ResolvedUnexpandedPackExpr *Create(ASTContext &C,
SourceLocation BeginLoc, QualType T,
llvm::ArrayRef<Expr *> Exprs);

unsigned getNumExprs() const { return NumExprs; }

llvm::MutableArrayRef<Expr *> getExprs() {
return {getTrailingObjects<Expr *>(), NumExprs};
}

llvm::ArrayRef<Expr *> getExprs() const {
return {getTrailingObjects<Expr *>(), NumExprs};
}

Expr *getExpansion(unsigned Idx) { return getExprs()[Idx]; }
Expr *getExpansion(unsigned Idx) const { return getExprs()[Idx]; }

// Iterators
child_range children() {
return child_range((Stmt **)getTrailingObjects<Expr *>(),
(Stmt **)getTrailingObjects<Expr *>() + getNumExprs());
}

SourceLocation getBeginLoc() const LLVM_READONLY { return BeginLoc; }
SourceLocation getEndLoc() const LLVM_READONLY { return BeginLoc; }

// Returns the resolved pack of a decl or nullptr
static ResolvedUnexpandedPackExpr *getFromDecl(Decl *);

static bool classof(const Stmt *T) {
return T->getStmtClass() == ResolvedUnexpandedPackExprClass;
}
};

} // namespace clang

#endif // LLVM_CLANG_AST_EXPRCXX_H
1 change: 0 additions & 1 deletion clang/include/clang/AST/RecursiveASTVisitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -2950,7 +2950,6 @@ DEF_TRAVERSE_STMT(FunctionParmPackExpr, {})
DEF_TRAVERSE_STMT(CXXFoldExpr, {})
DEF_TRAVERSE_STMT(AtomicExpr, {})
DEF_TRAVERSE_STMT(CXXParenListInitExpr, {})
DEF_TRAVERSE_STMT(ResolvedUnexpandedPackExpr, {})

DEF_TRAVERSE_STMT(MaterializeTemporaryExpr, {
if (S->getLifetimeExtendedTemporaryDecl()) {
Expand Down
1 change: 0 additions & 1 deletion clang/include/clang/Basic/StmtNodes.td
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,6 @@ def MaterializeTemporaryExpr : StmtNode<Expr>;
def LambdaExpr : StmtNode<Expr>;
def CXXFoldExpr : StmtNode<Expr>;
def CXXParenListInitExpr: StmtNode<Expr>;
def ResolvedUnexpandedPackExpr : StmtNode<Expr>;

// C++ Coroutines expressions
def CoroutineSuspendExpr : StmtNode<Expr, 1>;
Expand Down
3 changes: 1 addition & 2 deletions clang/include/clang/Sema/Sema.h
Original file line number Diff line number Diff line change
Expand Up @@ -232,8 +232,7 @@ void threadSafetyCleanup(BeforeSet *Cache);

// FIXME: No way to easily map from TemplateTypeParmTypes to
// TemplateTypeParmDecls, so we have this horrible PointerUnion.
typedef std::pair<llvm::PointerUnion<const TemplateTypeParmType *, NamedDecl *,
ResolvedUnexpandedPackExpr *>,
typedef std::pair<llvm::PointerUnion<const TemplateTypeParmType *, NamedDecl *>,
SourceLocation>
UnexpandedParameterPack;

Expand Down
2 changes: 1 addition & 1 deletion clang/include/clang/Sema/Template.h
Original file line number Diff line number Diff line change
Expand Up @@ -365,7 +365,7 @@ enum class TemplateSubstitutionKind : char {
class LocalInstantiationScope {
public:
/// A set of declarations.
using DeclArgumentPack = SmallVector<VarDecl *, 4>;
using DeclArgumentPack = SmallVector<ValueDecl *, 4>;

private:
/// Reference to the semantic analysis that is performing
Expand Down
1 change: 0 additions & 1 deletion clang/include/clang/Serialization/ASTBitCodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -1908,7 +1908,6 @@ enum StmtCode {
EXPR_PACK_EXPANSION, // PackExpansionExpr
EXPR_PACK_INDEXING, // PackIndexingExpr
EXPR_SIZEOF_PACK, // SizeOfPackExpr
EXPR_RESOLVED_UNEXPANDED_PACK, // ResolvedUnexpandedPackExpr
EXPR_SUBST_NON_TYPE_TEMPLATE_PARM, // SubstNonTypeTemplateParmExpr
EXPR_SUBST_NON_TYPE_TEMPLATE_PARM_PACK, // SubstNonTypeTemplateParmPackExpr
EXPR_FUNCTION_PARM_PACK, // FunctionParmPackExpr
Expand Down
9 changes: 6 additions & 3 deletions clang/lib/AST/DeclCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3492,10 +3492,13 @@ VarDecl *BindingDecl::getHoldingVar() const {
return VD;
}

llvm::ArrayRef<Expr *> BindingDecl::getBindingPackExprs() const {
llvm::ArrayRef<BindingDecl *> BindingDecl::getBindingPackDecls() const {
assert(Binding && "expecting a pack expr");
auto *RP = cast<ResolvedUnexpandedPackExpr>(Binding);
return RP->getExprs();
auto *FP = cast<FunctionParmPackExpr>(Binding);
ValueDecl *const *First = FP->getNumExpansions() > 0 ? FP->begin() : nullptr;
assert((!First || isa<BindingDecl>(*First)) && "expecting a BindingDecl");
return llvm::ArrayRef<BindingDecl *>(
reinterpret_cast<BindingDecl *const *>(First), FP->getNumExpansions());
Comment on lines +3500 to +3501
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we use llvm::cast here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

llvm::cast will not return a reference to the pointer so it cannot be used for the ArrayRef.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we use static_cast here?

}

void DecompositionDecl::anchor() {}
Expand Down
1 change: 0 additions & 1 deletion clang/lib/AST/Expr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3659,7 +3659,6 @@ bool Expr::HasSideEffects(const ASTContext &Ctx,
case PackIndexingExprClass:
case HLSLOutArgExprClass:
case OpenACCAsteriskSizeExprClass:
case ResolvedUnexpandedPackExprClass:
// These never have a side-effect.
return false;

Expand Down
63 changes: 7 additions & 56 deletions clang/lib/AST/ExprCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1779,31 +1779,31 @@ TemplateArgument SubstNonTypeTemplateParmPackExpr::getArgumentPack() const {
return TemplateArgument(llvm::ArrayRef(Arguments, NumArguments));
}

FunctionParmPackExpr::FunctionParmPackExpr(QualType T, VarDecl *ParamPack,
FunctionParmPackExpr::FunctionParmPackExpr(QualType T, ValueDecl *ParamPack,
SourceLocation NameLoc,
unsigned NumParams,
VarDecl *const *Params)
ValueDecl *const *Params)
: Expr(FunctionParmPackExprClass, T, VK_LValue, OK_Ordinary),
ParamPack(ParamPack), NameLoc(NameLoc), NumParameters(NumParams) {
if (Params)
std::uninitialized_copy(Params, Params + NumParams,
getTrailingObjects<VarDecl *>());
getTrailingObjects<ValueDecl *>());
setDependence(ExprDependence::TypeValueInstantiation |
ExprDependence::UnexpandedPack);
}

FunctionParmPackExpr *
FunctionParmPackExpr::Create(const ASTContext &Context, QualType T,
VarDecl *ParamPack, SourceLocation NameLoc,
ArrayRef<VarDecl *> Params) {
return new (Context.Allocate(totalSizeToAlloc<VarDecl *>(Params.size())))
ValueDecl *ParamPack, SourceLocation NameLoc,
ArrayRef<ValueDecl *> Params) {
return new (Context.Allocate(totalSizeToAlloc<ValueDecl *>(Params.size())))
FunctionParmPackExpr(T, ParamPack, NameLoc, Params.size(), Params.data());
}

FunctionParmPackExpr *
FunctionParmPackExpr::CreateEmpty(const ASTContext &Context,
unsigned NumParams) {
return new (Context.Allocate(totalSizeToAlloc<VarDecl *>(NumParams)))
return new (Context.Allocate(totalSizeToAlloc<ValueDecl *>(NumParams)))
FunctionParmPackExpr(QualType(), nullptr, SourceLocation(), 0, nullptr);
}

Expand Down Expand Up @@ -1965,52 +1965,3 @@ CXXFoldExpr::CXXFoldExpr(QualType T, UnresolvedLookupExpr *Callee,
SubExprs[SubExpr::RHS] = RHS;
setDependence(computeDependence(this));
}

ResolvedUnexpandedPackExpr::ResolvedUnexpandedPackExpr(SourceLocation BL,
QualType QT,
unsigned NumExprs)
: Expr(ResolvedUnexpandedPackExprClass, QT, VK_PRValue, OK_Ordinary),
BeginLoc(BL), NumExprs(NumExprs) {
// C++ [temp.dep.expr]p3
// An id-expression is type-dependent if it is
// - associated by name lookup with a pack
setDependence(ExprDependence::TypeValueInstantiation |
ExprDependence::UnexpandedPack);
}

ResolvedUnexpandedPackExpr *
ResolvedUnexpandedPackExpr::CreateDeserialized(ASTContext &Ctx,
unsigned NumExprs) {
void *Mem = Ctx.Allocate(totalSizeToAlloc<Expr *>(NumExprs),
alignof(ResolvedUnexpandedPackExpr));
return new (Mem)
ResolvedUnexpandedPackExpr(SourceLocation(), QualType(), NumExprs);
}

ResolvedUnexpandedPackExpr *
ResolvedUnexpandedPackExpr::Create(ASTContext &Ctx, SourceLocation BL,
QualType T, unsigned NumExprs) {
void *Mem = Ctx.Allocate(totalSizeToAlloc<Expr *>(NumExprs),
alignof(ResolvedUnexpandedPackExpr));
ResolvedUnexpandedPackExpr *New =
new (Mem) ResolvedUnexpandedPackExpr(BL, T, NumExprs);

auto Exprs = New->getExprs();
std::uninitialized_fill(Exprs.begin(), Exprs.end(), nullptr);

return New;
}

ResolvedUnexpandedPackExpr *
ResolvedUnexpandedPackExpr::Create(ASTContext &Ctx, SourceLocation BL,
QualType T, ArrayRef<Expr *> Exprs) {
auto *New = Create(Ctx, BL, T, Exprs.size());
std::uninitialized_copy(Exprs.begin(), Exprs.end(), New->getExprs().begin());
return New;
}

ResolvedUnexpandedPackExpr *ResolvedUnexpandedPackExpr::getFromDecl(Decl *D) {
if (auto *BD = dyn_cast<BindingDecl>(D))
return dyn_cast_if_present<ResolvedUnexpandedPackExpr>(BD->getBinding());
return nullptr;
}
7 changes: 0 additions & 7 deletions clang/lib/AST/ExprClassification.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -451,13 +451,6 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) {
case Expr::PackExpansionExprClass:
return ClassifyInternal(Ctx, cast<PackExpansionExpr>(E)->getPattern());

case Expr::ResolvedUnexpandedPackExprClass: {
if (cast<ResolvedUnexpandedPackExpr>(E)->getNumExprs() > 0)
return ClassifyInternal(
Ctx, cast<ResolvedUnexpandedPackExpr>(E)->getExpansion(0));
return Cl::CL_LValue;
}

case Expr::MaterializeTemporaryExprClass:
return cast<MaterializeTemporaryExpr>(E)->isBoundToLvalueReference()
? Cl::CL_LValue
Expand Down
1 change: 0 additions & 1 deletion clang/lib/AST/ExprConstant.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17253,7 +17253,6 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) {
case Expr::SYCLUniqueStableNameExprClass:
case Expr::CXXParenListInitExprClass:
case Expr::HLSLOutArgExprClass:
case Expr::ResolvedUnexpandedPackExprClass:
return ICEDiag(IK_NotICE, E->getBeginLoc());

case Expr::InitListExprClass: {
Expand Down
3 changes: 1 addition & 2 deletions clang/lib/AST/ItaniumMangle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4932,8 +4932,7 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity,
case Expr::AtomicExprClass:
case Expr::SourceLocExprClass:
case Expr::EmbedExprClass:
case Expr::BuiltinBitCastExprClass:
case Expr::ResolvedUnexpandedPackExprClass: {
case Expr::BuiltinBitCastExprClass: {
NotPrimaryExpr();
if (!NullOut) {
// As bad as this diagnostic is, it's better than crashing.
Expand Down
9 changes: 0 additions & 9 deletions clang/lib/AST/StmtPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2595,15 +2595,6 @@ void StmtPrinter::VisitPackIndexingExpr(PackIndexingExpr *E) {
OS << "]";
}

void StmtPrinter::VisitResolvedUnexpandedPackExpr(
ResolvedUnexpandedPackExpr *E) {
OS << "<<resolved pack(";
llvm::interleave(
E->getExprs().begin(), E->getExprs().end(),
[this](auto *X) { PrintExpr(X); }, [this] { OS << ", "; });
OS << ")>>";
}

void StmtPrinter::VisitSubstNonTypeTemplateParmPackExpr(
SubstNonTypeTemplateParmPackExpr *Node) {
OS << *Node->getParameterPack();
Expand Down
Loading