Skip to content

Commit d83433c

Browse files
bcardosolopesJari Ronkainen
authored andcommitted
[PatternMatching] Fix pattern guards for pat id elements in structured bindings
Decouple binding creation from running sema for the structured bindings by acting early on the pattern list. Since we now create the variables before parsing the condition, their name is scope, available to be used from the guard condition.
1 parent 006b721 commit d83433c

File tree

5 files changed

+48
-18
lines changed

5 files changed

+48
-18
lines changed

clang/include/clang/Sema/Sema.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8861,7 +8861,10 @@ class Sema final {
88618861
StmtResult ActOnStructuredBindingPattern(
88628862
SourceLocation ColonLoc, SourceLocation LLoc, SourceLocation RLoc,
88638863
SmallVectorImpl<Sema::ParsedPatEltResult> &PatList, Stmt *SubStmt,
8864-
Expr *Guard, bool ExcludedFromTypeDeduction);
8864+
Expr *Guard, Stmt *DecompStmt, bool ExcludedFromTypeDeduction);
8865+
8866+
StmtResult ActOnPatternList(SmallVectorImpl<Sema::ParsedPatEltResult> &PatList,
8867+
SourceLocation LLoc);
88658868

88668869
ExprResult ActOnMatchBinOp(Expr *LHS, Expr *RHS, SourceLocation MatchExprLoc);
88678870
StmtResult CreatePatternIdBindingVar(Expr *From, IdentifierInfo *II,

clang/lib/Parse/ParseStmt.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1018,7 +1018,12 @@ StmtResult Parser::ParseStructuralBindingPattern(ParsedStmtContext StmtCtx) {
10181018
SourceLocation IfLoc;
10191019

10201020
ParseScope PatternScope(this, Scope::PatternScope | Scope::DeclScope, true);
1021-
1021+
StmtResult DecompDS;
1022+
if (ValidPatList) {
1023+
DecompDS = Actions.ActOnPatternList(PatList, LSquare);
1024+
if (DecompDS.isInvalid())
1025+
ValidPatList = false;
1026+
}
10221027
// FIXME: retrieve constexpr information from InspectExpr
10231028
if (Tok.is(tok::kw_if))
10241029
if (!ParsePatternGuard(Cond, IfLoc, false /*IsConstexprIf*/))
@@ -1051,7 +1056,7 @@ StmtResult Parser::ParseStructuralBindingPattern(ParsedStmtContext StmtCtx) {
10511056
if (ValidPatList)
10521057
Res = Actions.ActOnStructuredBindingPattern(
10531058
ArrowLoc, LSquare, RSquare, PatList, nullptr, Cond.get().second,
1054-
ExclaimLoc.isValid());
1059+
DecompDS.get(), ExclaimLoc.isValid());
10551060

10561061
// Parse the statement
10571062
//

clang/lib/Sema/SemaStmt.cpp

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -733,10 +733,9 @@ StmtResult Sema::ActOnExpressionPattern(SourceLocation MatchExprLoc,
733733
return EPS;
734734
}
735735

736-
StmtResult Sema::ActOnStructuredBindingPattern(
737-
SourceLocation ColonLoc, SourceLocation LLoc, SourceLocation RLoc,
738-
SmallVectorImpl<Sema::ParsedPatEltResult> &PatList, Stmt *SubStmt,
739-
Expr *Guard, bool ExcludedFromTypeDeduction) {
736+
StmtResult
737+
Sema::ActOnPatternList(SmallVectorImpl<Sema::ParsedPatEltResult> &PatList,
738+
SourceLocation LLoc) {
740739
if (PatList.empty()) {
741740
Diag(LLoc, diag::err_empty_stbind_pattern);
742741
return StmtError();
@@ -800,7 +799,8 @@ StmtResult Sema::ActOnStructuredBindingPattern(
800799

801800
// Deduce the type of the inspect condition.
802801
QualType DeducedType = deduceVarTypeFromInitializer(
803-
/*VarDecl*/ DecompCond, DeclarationName(), DeductType, TSI, SourceRange(LLoc),
802+
/*VarDecl*/ DecompCond, DeclarationName(), DeductType, TSI,
803+
SourceRange(LLoc),
804804
/*IsDirectInit*/ false, MatchSource);
805805
if (DeducedType.isNull()) // deduceVarTypeFromInitializer already emits diags
806806
return StmtError();
@@ -829,6 +829,18 @@ StmtResult Sema::ActOnStructuredBindingPattern(
829829
DecompCond->getBeginLoc(), DecompCond->getEndLoc());
830830
if (DecompDS.isInvalid())
831831
return StmtError();
832+
return DecompDS;
833+
}
834+
835+
StmtResult Sema::ActOnStructuredBindingPattern(
836+
SourceLocation ColonLoc, SourceLocation LLoc, SourceLocation RLoc,
837+
SmallVectorImpl<Sema::ParsedPatEltResult> &PatList, Stmt *SubStmt,
838+
Expr *Guard, Stmt *DecompStmt, bool ExcludedFromTypeDeduction) {
839+
auto *DS = static_cast<DeclStmt *>(DecompStmt);
840+
auto *DecompCond = cast<DecompositionDecl>(DS->getSingleDecl());
841+
if (getCurFunction()->InspectStack.empty())
842+
return StmtError();
843+
InspectExpr *Inspect = getCurFunction()->InspectStack.back().getPointer();
832844

833845
// Now that we got all bindings populated with the proper type, for each
834846
// element in the pattern list try to ==/match() with the equivalent element
@@ -844,7 +856,7 @@ StmtResult Sema::ActOnStructuredBindingPattern(
844856
case ParsedPatEltAction::Match: {
845857
ExprResult M =
846858
ActOnMatchBinOp(NewBindings[I]->getBinding(),
847-
cast<Expr>(PatList[I].Elt), MatchSourceLoc);
859+
cast<Expr>(PatList[I].Elt), PatList[I].Loc);
848860
if (M.isInvalid())
849861
continue;
850862
if (!PatCond) {
@@ -869,8 +881,8 @@ StmtResult Sema::ActOnStructuredBindingPattern(
869881
}
870882

871883
auto *SBP = StructuredBindingPatternStmt::Create(
872-
Context, LLoc, ColonLoc, LLoc, RLoc, DecompDS.get(), SubStmt, Guard,
873-
PatCond, ExcludedFromTypeDeduction);
884+
Context, LLoc, ColonLoc, LLoc, RLoc, DecompStmt, SubStmt, Guard, PatCond,
885+
ExcludedFromTypeDeduction);
874886

875887
Inspect->addPattern(SBP);
876888
return SBP;

clang/test/AST/ast-dump-inspect-stmt.cpp

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -162,19 +162,28 @@ void TestInspect(int a, int b) {
162162
};
163163
insn_type insn;
164164
inspect(insn) {
165-
[o, i] => { o++; };
165+
[o, i] if (o+i < 12) => { o++; };
166166
};
167167
// CHECK: InspectExpr
168168
// CHECK: StructuredBindingPatternStmt
169-
// CHECK: |-CompoundStmt {{.*}} <col:15, col:22>
170-
// CHECK: | `-UnaryOperator {{.*}} <col:17, col:18> 'unsigned int' postfix '++'
171-
// CHECK: | `-DeclRefExpr {{.*}} <col:17> 'unsigned int' lvalue bitfield Binding {{.*}} 'o' 'unsigned int'
172-
// CHECK: `-DeclStmt
169+
// CHECK: |-CompoundStmt {{.*}} <col:29, col:36>
170+
// CHECK: | `-UnaryOperator {{.*}} <col:31, col:32> 'unsigned int' postfix '++'
171+
// CHECK: | `-DeclRefExpr {{.*}} <col:31> 'unsigned int' lvalue bitfield Binding {{.*}} 'o' 'unsigned int'
172+
// CHECK: |-DeclStmt
173173
// CHECK: `-DecompositionDecl {{.*}} used 'insn_type &' cinit
174174
// CHECK: |-BindingDecl {{.*}} col:6 referenced o 'unsigned int'
175175
// CHECK: | `-MemberExpr {{.*}} <col:6> 'unsigned int' lvalue bitfield .opc
176-
// CHECK: `-BindingDecl {{.*}} <col:9> col:9 i 'unsigned int'
177-
// CHECK: `-MemberExpr {{.*}} <col:9> 'unsigned int' lvalue bitfield .imm
176+
// CHECK: `-BindingDecl {{.*}} <col:9> col:9 referenced i 'unsigned int'
177+
// CHECK: `-MemberExpr {{.*}} <col:9> 'unsigned int' lvalue bitfield .imm
178+
// CHECK: `-BinaryOperator {{.*}} <col:16, col:22> 'bool' '<'
179+
// CHECK: |-BinaryOperator {{.*}} <col:16, col:18> 'int' '+'
180+
// CHECK: | |-ImplicitCastExpr {{.*}} <col:16> 'int' <IntegralCast>
181+
// CHECK: | | `-ImplicitCastExpr {{.*}} <col:16> 'unsigned int' <LValueToRValue>
182+
// CHECK: | | `-DeclRefExpr {{.*}} <col:16> 'unsigned int' lvalue bitfield Binding {{.*}} 'o' 'unsigned int'
183+
// CHECK: | `-ImplicitCastExpr {{.*}} <col:18> 'int' <IntegralCast>
184+
// CHECK: | `-ImplicitCastExpr {{.*}} <col:18> 'unsigned int' <LValueToRValue>
185+
// CHECK: | `-DeclRefExpr {{.*}} <col:18> 'unsigned int' lvalue bitfield Binding {{.*}} 'i' 'unsigned int'
186+
// CHECK: `-IntegerLiteral {{.*}} <col:22> 'int' 12
178187
}
179188

180189
using size_t = decltype(sizeof(0));

clang/test/SemaCXX/inspect.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,7 @@ void stbind0(int x) {
199199
int array[2] = {2,1};
200200
inspect (array) {
201201
[1,2] =>;
202+
[id0, id1] if (id0+id1 < 10) =>;
202203
};
203204

204205
using FourUInts = unsigned __attribute__((__vector_size__(16)));

0 commit comments

Comments
 (0)