Skip to content

Commit dba1477

Browse files
committed
[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 6d8e797 commit dba1477

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
@@ -4248,7 +4248,10 @@ class Sema final {
42484248
StmtResult ActOnStructuredBindingPattern(
42494249
SourceLocation ColonLoc, SourceLocation LLoc, SourceLocation RLoc,
42504250
SmallVectorImpl<Sema::ParsedPatEltResult> &PatList, Stmt *SubStmt,
4251-
Expr *Guard, bool ExcludedFromTypeDeduction);
4251+
Expr *Guard, Stmt *DecompStmt, bool ExcludedFromTypeDeduction);
4252+
StmtResult
4253+
ActOnPatternList(SmallVectorImpl<Sema::ParsedPatEltResult> &PatList,
4254+
SourceLocation LLoc);
42524255

42534256
ExprResult CheckPatternConstantExpr(Expr *MatchExpr,
42544257
SourceLocation MatchExprLoc);

clang/lib/Parse/ParseStmt.cpp

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

877877
ParseScope PatternScope(this, Scope::PatternScope | Scope::DeclScope, true);
878-
878+
StmtResult DecompDS;
879+
if (ValidPatList) {
880+
DecompDS = Actions.ActOnPatternList(PatList, LSquare);
881+
if (DecompDS.isInvalid())
882+
ValidPatList = false;
883+
}
879884
// FIXME: retrieve constexpr information from InspectExpr
880885
if (Tok.is(tok::kw_if))
881886
if (!ParsePatternGuard(Cond, IfLoc, false /*IsConstexprIf*/))
@@ -908,7 +913,7 @@ StmtResult Parser::ParseStructuralBindingPattern(ParsedStmtContext StmtCtx) {
908913
if (ValidPatList)
909914
Res = Actions.ActOnStructuredBindingPattern(
910915
ArrowLoc, LSquare, RSquare, PatList, nullptr, Cond.get().second,
911-
ExclaimLoc.isValid());
916+
DecompDS.get(), ExclaimLoc.isValid());
912917

913918
// Parse the statement
914919
//

clang/lib/Sema/SemaStmt.cpp

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -681,10 +681,9 @@ StmtResult Sema::ActOnExpressionPattern(SourceLocation MatchExprLoc,
681681
return EPS;
682682
}
683683

684-
StmtResult Sema::ActOnStructuredBindingPattern(
685-
SourceLocation ColonLoc, SourceLocation LLoc, SourceLocation RLoc,
686-
SmallVectorImpl<Sema::ParsedPatEltResult> &PatList, Stmt *SubStmt,
687-
Expr *Guard, bool ExcludedFromTypeDeduction) {
684+
StmtResult
685+
Sema::ActOnPatternList(SmallVectorImpl<Sema::ParsedPatEltResult> &PatList,
686+
SourceLocation LLoc) {
688687
if (PatList.empty()) {
689688
Diag(LLoc, diag::err_empty_stbind_pattern);
690689
return StmtError();
@@ -748,7 +747,8 @@ StmtResult Sema::ActOnStructuredBindingPattern(
748747

749748
// Deduce the type of the inspect condition.
750749
QualType DeducedType = deduceVarTypeFromInitializer(
751-
/*VarDecl*/ DecompCond, DeclarationName(), DeductType, TSI, SourceRange(LLoc),
750+
/*VarDecl*/ DecompCond, DeclarationName(), DeductType, TSI,
751+
SourceRange(LLoc),
752752
/*IsDirectInit*/ false, MatchSource);
753753
if (DeducedType.isNull()) // deduceVarTypeFromInitializer already emits diags
754754
return StmtError();
@@ -777,6 +777,18 @@ StmtResult Sema::ActOnStructuredBindingPattern(
777777
DecompCond->getBeginLoc(), DecompCond->getEndLoc());
778778
if (DecompDS.isInvalid())
779779
return StmtError();
780+
return DecompDS;
781+
}
782+
783+
StmtResult Sema::ActOnStructuredBindingPattern(
784+
SourceLocation ColonLoc, SourceLocation LLoc, SourceLocation RLoc,
785+
SmallVectorImpl<Sema::ParsedPatEltResult> &PatList, Stmt *SubStmt,
786+
Expr *Guard, Stmt *DecompStmt, bool ExcludedFromTypeDeduction) {
787+
auto *DS = static_cast<DeclStmt *>(DecompStmt);
788+
auto *DecompCond = cast<DecompositionDecl>(DS->getSingleDecl());
789+
if (getCurFunction()->InspectStack.empty())
790+
return StmtError();
791+
InspectExpr *Inspect = getCurFunction()->InspectStack.back().getPointer();
780792

781793
// Now that we got all bindings populated with the proper type, for each
782794
// element in the pattern list try to ==/match() with the equivalent element
@@ -792,7 +804,7 @@ StmtResult Sema::ActOnStructuredBindingPattern(
792804
case ParsedPatEltAction::Match: {
793805
ExprResult M =
794806
ActOnMatchBinOp(NewBindings[I]->getBinding(),
795-
cast<Expr>(PatList[I].Elt), MatchSourceLoc);
807+
cast<Expr>(PatList[I].Elt), PatList[I].Loc);
796808
if (M.isInvalid())
797809
continue;
798810
if (!PatCond) {
@@ -817,8 +829,8 @@ StmtResult Sema::ActOnStructuredBindingPattern(
817829
}
818830

819831
auto *SBP = StructuredBindingPatternStmt::Create(
820-
Context, LLoc, ColonLoc, LLoc, RLoc, DecompDS.get(), SubStmt, Guard,
821-
PatCond, ExcludedFromTypeDeduction);
832+
Context, LLoc, ColonLoc, LLoc, RLoc, DecompStmt, SubStmt, Guard, PatCond,
833+
ExcludedFromTypeDeduction);
822834

823835
Inspect->addPattern(SBP);
824836
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)