Skip to content

Commit 116aff1

Browse files
committed
[Clang][P1061] Improve visiting HoldingVars; Improve parsing diagnostics of binding packs
1 parent 3c81c5b commit 116aff1

16 files changed

+51
-80
lines changed

clang/include/clang/AST/DeclCXX.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4166,7 +4166,6 @@ class BindingDecl : public ValueDecl {
41664166
void setDecomposedDecl(ValueDecl *Decomposed) { Decomp = Decomposed; }
41674167

41684168
VarDecl *getHoldingVar() const;
4169-
static VarDecl *getHoldingVar(Expr *E);
41704169

41714170
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
41724171
static bool classofKind(Kind K) { return K == Decl::Binding; }
@@ -4224,7 +4223,7 @@ class DecompositionDecl final
42244223
/// binding. Only present for user-defined bindings for tuple-like types.
42254224
void VisitHoldingVars(llvm::function_ref<void(VarDecl *)> F) const;
42264225

4227-
// Visit the concrete bindings. (workaround)
4226+
// Visit the concrete bindings.
42284227
void VisitBindings(llvm::function_ref<void(BindingDecl *)> F) const;
42294228

42304229
static bool classof(const Decl *D) { return classofKind(D->getKind()); }

clang/include/clang/AST/ExprCXX.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5321,6 +5321,8 @@ class BuiltinBitCastExpr final
53215321
}
53225322
};
53235323

5324+
// Represents an unexpanded pack where the list of expressions are
5325+
// known. These are used when structured bindings introduce a pack.
53245326
class ResolvedUnexpandedPackExpr final
53255327
: public Expr,
53265328
private llvm::TrailingObjects<ResolvedUnexpandedPackExpr, Stmt *> {

clang/include/clang/Basic/DiagnosticParseKinds.td

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1101,9 +1101,11 @@ def err_lambda_capture_multiple_ellipses : Error<
11011101
"multiple ellipses in pack capture">;
11021102
def err_binding_multiple_ellipses : Error<
11031103
"multiple ellipses in structured binding declaration">;
1104-
def warn_cxx2c_binding_pack : Warning<
1104+
def note_previous_ellipsis : Note<
1105+
"previous ellipsis specified here">;
1106+
def ext_cxx_binding_pack : ExtWarn<
11051107
"structured binding pack is incompatible with C++ standards before C++2c">,
1106-
DefaultIgnore, InGroup<CXXPre26Compat>;
1108+
InGroup<CXX26>;
11071109
def err_capture_default_first : Error<
11081110
"capture default must be first">;
11091111
def ext_decl_attrs_on_lambda : ExtWarn<

clang/lib/AST/DeclBase.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -237,12 +237,10 @@ bool Decl::isTemplateParameterPack() const {
237237
}
238238

239239
bool Decl::isParameterPack() const {
240-
if (isTemplateParameterPack())
241-
return true;
242240
if (const auto *Var = dyn_cast<ValueDecl>(this))
243241
return Var->isParameterPack();
244242

245-
return false;
243+
return isTemplateParameterPack();
246244
}
247245

248246
FunctionDecl *Decl::getAsFunction() {

clang/lib/AST/DeclCXX.cpp

Lines changed: 6 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -3395,7 +3395,7 @@ VarDecl *ValueDecl::getPotentiallyDecomposedVarDecl() {
33953395
if (auto *Var = llvm::dyn_cast<VarDecl>(this))
33963396
return Var;
33973397
if (auto *BD = llvm::dyn_cast<BindingDecl>(this))
3398-
return llvm::dyn_cast_or_null<VarDecl>(BD->getDecomposedDecl());
3398+
return llvm::dyn_cast_if_present<VarDecl>(BD->getDecomposedDecl());
33993399
return nullptr;
34003400
}
34013401

@@ -3416,16 +3416,7 @@ VarDecl *BindingDecl::getHoldingVar() const {
34163416
Expr *B = getBinding();
34173417
if (!B)
34183418
return nullptr;
3419-
return getHoldingVar(B);
3420-
}
3421-
3422-
VarDecl *BindingDecl::getHoldingVar(Expr *E) {
3423-
auto *DRE = dyn_cast<DeclRefExpr>(E->IgnoreImplicit());
3424-
if (!DRE)
3425-
return nullptr;
3426-
if (auto *BD = dyn_cast<BindingDecl>(DRE->getDecl())) {
3427-
DRE = dyn_cast<DeclRefExpr>(BD->getBinding());
3428-
}
3419+
auto *DRE = dyn_cast<DeclRefExpr>(B->IgnoreImplicit());
34293420
if (!DRE)
34303421
return nullptr;
34313422

@@ -3434,27 +3425,13 @@ VarDecl *BindingDecl::getHoldingVar(Expr *E) {
34343425
return VD;
34353426
}
34363427

3428+
34373429
void DecompositionDecl::VisitHoldingVars(
34383430
llvm::function_ref<void(VarDecl *)> F) const {
3439-
for (BindingDecl *B : bindings()) {
3440-
Expr *BE = B->getBinding();
3441-
// All BindingDecls will contain holding vars or none will
3442-
if (!BE)
3443-
return;
3444-
3445-
llvm::ArrayRef<Expr *> Exprs;
3446-
if (auto *RP = dyn_cast<ResolvedUnexpandedPackExpr>(BE))
3447-
Exprs = llvm::ArrayRef(RP->getExprs(), RP->getNumExprs());
3448-
else
3449-
Exprs = BE;
3450-
3451-
for (Expr *E : Exprs) {
3452-
VarDecl *VD = BindingDecl::getHoldingVar(E);
3453-
if (!VD)
3454-
return;
3431+
VisitBindings([&](BindingDecl* BD) {
3432+
if (VarDecl* VD = BD->getHoldingVar())
34553433
F(VD);
3456-
}
3457-
}
3434+
});
34583435
}
34593436

34603437
void DecompositionDecl::VisitBindings(

clang/lib/AST/Expr.cpp

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3653,12 +3653,8 @@ bool Expr::HasSideEffects(const ASTContext &Ctx,
36533653
case PackIndexingExprClass:
36543654
case HLSLOutArgExprClass:
36553655
case OpenACCAsteriskSizeExprClass:
3656-
// These never have a side-effect.
3657-
return false;
3658-
3659-
// ResolvedUnexpandedPackExpr is currently only used for
3660-
// structed bindings which have no side effects
36613656
case ResolvedUnexpandedPackExprClass:
3657+
// These never have a side-effect.
36623658
return false;
36633659

36643660
case ConstantExprClass:

clang/lib/AST/ExprCXX.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1971,6 +1971,9 @@ ResolvedUnexpandedPackExpr::ResolvedUnexpandedPackExpr(SourceLocation BL,
19711971
unsigned NumExprs)
19721972
: Expr(ResolvedUnexpandedPackExprClass, QT, VK_PRValue, OK_Ordinary),
19731973
BeginLoc(BL), NumExprs(NumExprs) {
1974+
// C++ [temp.dep.expr]p3
1975+
// An id-expression is type-dependent if it is
1976+
// - associated by name lookup with a pack
19741977
setDependence(ExprDependence::TypeValueInstantiation |
19751978
ExprDependence::UnexpandedPack);
19761979
}
@@ -2007,9 +2010,7 @@ ResolvedUnexpandedPackExpr::Create(ASTContext &Ctx, SourceLocation BL,
20072010
}
20082011

20092012
ResolvedUnexpandedPackExpr *ResolvedUnexpandedPackExpr::getFromDecl(Decl *D) {
2010-
// TODO P1858: Extend to VarDecls for P1858
2011-
if (auto *BD = dyn_cast<BindingDecl>(D)) {
2012-
return dyn_cast_or_null<ResolvedUnexpandedPackExpr>(BD->getBinding());
2013-
}
2013+
if (auto *BD = dyn_cast<BindingDecl>(D))
2014+
return dyn_cast_if_present<ResolvedUnexpandedPackExpr>(BD->getBinding());
20142015
return nullptr;
20152016
}

clang/lib/AST/ExprClassification.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -455,7 +455,7 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) {
455455
if (cast<ResolvedUnexpandedPackExpr>(E)->getNumExprs() > 0)
456456
return ClassifyInternal(
457457
Ctx, cast<ResolvedUnexpandedPackExpr>(E)->getExpansion(0));
458-
return Cl::CL_PRValue;
458+
return Cl::CL_LValue;
459459
}
460460

461461
case Expr::MaterializeTemporaryExprClass:

clang/lib/Parse/ParseDecl.cpp

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7310,14 +7310,14 @@ void Parser::ParseDecompositionDeclarator(Declarator &D) {
73107310
// array declarator.
73117311
if (!(Tok.isOneOf(tok::identifier, tok::ellipsis) &&
73127312
NextToken().isOneOf(tok::comma, tok::r_square, tok::kw_alignas,
7313-
tok::identifier, tok::l_square)) &&
7313+
tok::identifier, tok::l_square, tok::ellipsis)) &&
73147314
!(Tok.is(tok::r_square) &&
73157315
NextToken().isOneOf(tok::equal, tok::l_brace))) {
73167316
PA.Revert();
73177317
return ParseMisplacedBracketDeclarator(D);
73187318
}
73197319

7320-
bool HasEllipsis = false;
7320+
SourceLocation PrevEllipsisLoc;
73217321
SmallVector<DecompositionDeclarator::Binding, 32> Bindings;
73227322
while (Tok.isNot(tok::r_square)) {
73237323
if (!Bindings.empty()) {
@@ -7332,9 +7332,8 @@ void Parser::ParseDecompositionDeclarator(Declarator &D) {
73327332
Diag(Tok, diag::err_expected_comma_or_rsquare);
73337333
}
73347334

7335-
// I don't know why this skipping was here
7336-
// SkipUntil(tok::r_square, tok::comma, tok::identifier,
7337-
// StopAtSemi | StopBeforeMatch);
7335+
SkipUntil({tok::r_square, tok::comma, tok::identifier, tok::ellipsis},
7336+
StopAtSemi | StopBeforeMatch);
73387337
if (Tok.is(tok::comma))
73397338
ConsumeToken();
73407339
else if (Tok.is(tok::r_square))
@@ -7345,17 +7344,18 @@ void Parser::ParseDecompositionDeclarator(Declarator &D) {
73457344
if (isCXX11AttributeSpecifier())
73467345
DiagnoseAndSkipCXX11Attributes();
73477346

7348-
SourceLocation EllipsisLoc = {};
7347+
SourceLocation EllipsisLoc;
73497348

73507349
if (Tok.is(tok::ellipsis)) {
73517350
if (!getLangOpts().CPlusPlus26)
7352-
Diag(Tok, diag::warn_cxx2c_binding_pack);
7353-
if (HasEllipsis) {
7351+
Diag(Tok, diag::ext_cxx_binding_pack);
7352+
if (PrevEllipsisLoc.isValid()) {
73547353
Diag(Tok, diag::err_binding_multiple_ellipses);
7354+
Diag(PrevEllipsisLoc, diag::note_previous_ellipsis);
73557355
break;
73567356
}
7357-
HasEllipsis = true;
73587357
EllipsisLoc = Tok.getLocation();
7358+
PrevEllipsisLoc = EllipsisLoc;
73597359
ConsumeToken();
73607360
}
73617361

@@ -7368,6 +7368,13 @@ void Parser::ParseDecompositionDeclarator(Declarator &D) {
73687368
SourceLocation Loc = Tok.getLocation();
73697369
ConsumeToken();
73707370

7371+
if (Tok.is(tok::ellipsis) && !PrevEllipsisLoc.isValid()) {
7372+
DiagnoseMisplacedEllipsis(Tok.getLocation(), Loc,
7373+
EllipsisLoc.isValid(), true);
7374+
EllipsisLoc = Tok.getLocation();
7375+
ConsumeToken();
7376+
}
7377+
73717378
ParsedAttributes Attrs(AttrFactory);
73727379
if (isCXX11AttributeSpecifier()) {
73737380
Diag(Tok, getLangOpts().CPlusPlus26

clang/lib/Sema/SemaDecl.cpp

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9780,7 +9780,6 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
97809780
QualType R = TInfo->getType();
97819781

97829782
assert(R->isFunctionType());
9783-
bool NeedsExpansion = false;
97849783

97859784
if (R.getCanonicalType()->castAs<FunctionType>()->getCmseNSCallAttr())
97869785
Diag(D.getIdentifierLoc(), diag::err_function_decl_cmse_ns_call);
@@ -10966,14 +10965,6 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
1096610965
D.getFunctionDefinitionKind() == FunctionDefinitionKind::Declaration)
1096710966
ExternalDeclarations.push_back(NewFD);
1096810967

10969-
if (NeedsExpansion) {
10970-
CodeSynthesisContext SynthCtx{};
10971-
pushCodeSynthesisContext(SynthCtx);
10972-
NewFD = dyn_cast_or_null<FunctionDecl>(
10973-
SubstDecl(NewFD, DC, MultiLevelTemplateArgumentList{}));
10974-
popCodeSynthesisContext();
10975-
}
10976-
1097710968
return NewFD;
1097810969
}
1097910970

0 commit comments

Comments
 (0)