Skip to content

Commit

Permalink
[PatternMatching] Fix pattern guards for pat id elements in structure…
Browse files Browse the repository at this point in the history
…d 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.
  • Loading branch information
bcardosolopes committed Dec 23, 2020
1 parent 6d8e797 commit dba1477
Show file tree
Hide file tree
Showing 5 changed files with 48 additions and 18 deletions.
5 changes: 4 additions & 1 deletion clang/include/clang/Sema/Sema.h
Original file line number Diff line number Diff line change
Expand Up @@ -4248,7 +4248,10 @@ class Sema final {
StmtResult ActOnStructuredBindingPattern(
SourceLocation ColonLoc, SourceLocation LLoc, SourceLocation RLoc,
SmallVectorImpl<Sema::ParsedPatEltResult> &PatList, Stmt *SubStmt,
Expr *Guard, bool ExcludedFromTypeDeduction);
Expr *Guard, Stmt *DecompStmt, bool ExcludedFromTypeDeduction);
StmtResult
ActOnPatternList(SmallVectorImpl<Sema::ParsedPatEltResult> &PatList,
SourceLocation LLoc);

ExprResult CheckPatternConstantExpr(Expr *MatchExpr,
SourceLocation MatchExprLoc);
Expand Down
9 changes: 7 additions & 2 deletions clang/lib/Parse/ParseStmt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -875,7 +875,12 @@ StmtResult Parser::ParseStructuralBindingPattern(ParsedStmtContext StmtCtx) {
SourceLocation IfLoc;

ParseScope PatternScope(this, Scope::PatternScope | Scope::DeclScope, true);

StmtResult DecompDS;
if (ValidPatList) {
DecompDS = Actions.ActOnPatternList(PatList, LSquare);
if (DecompDS.isInvalid())
ValidPatList = false;
}
// FIXME: retrieve constexpr information from InspectExpr
if (Tok.is(tok::kw_if))
if (!ParsePatternGuard(Cond, IfLoc, false /*IsConstexprIf*/))
Expand Down Expand Up @@ -908,7 +913,7 @@ StmtResult Parser::ParseStructuralBindingPattern(ParsedStmtContext StmtCtx) {
if (ValidPatList)
Res = Actions.ActOnStructuredBindingPattern(
ArrowLoc, LSquare, RSquare, PatList, nullptr, Cond.get().second,
ExclaimLoc.isValid());
DecompDS.get(), ExclaimLoc.isValid());

// Parse the statement
//
Expand Down
28 changes: 20 additions & 8 deletions clang/lib/Sema/SemaStmt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -681,10 +681,9 @@ StmtResult Sema::ActOnExpressionPattern(SourceLocation MatchExprLoc,
return EPS;
}

StmtResult Sema::ActOnStructuredBindingPattern(
SourceLocation ColonLoc, SourceLocation LLoc, SourceLocation RLoc,
SmallVectorImpl<Sema::ParsedPatEltResult> &PatList, Stmt *SubStmt,
Expr *Guard, bool ExcludedFromTypeDeduction) {
StmtResult
Sema::ActOnPatternList(SmallVectorImpl<Sema::ParsedPatEltResult> &PatList,
SourceLocation LLoc) {
if (PatList.empty()) {
Diag(LLoc, diag::err_empty_stbind_pattern);
return StmtError();
Expand Down Expand Up @@ -748,7 +747,8 @@ StmtResult Sema::ActOnStructuredBindingPattern(

// Deduce the type of the inspect condition.
QualType DeducedType = deduceVarTypeFromInitializer(
/*VarDecl*/ DecompCond, DeclarationName(), DeductType, TSI, SourceRange(LLoc),
/*VarDecl*/ DecompCond, DeclarationName(), DeductType, TSI,
SourceRange(LLoc),
/*IsDirectInit*/ false, MatchSource);
if (DeducedType.isNull()) // deduceVarTypeFromInitializer already emits diags
return StmtError();
Expand Down Expand Up @@ -777,6 +777,18 @@ StmtResult Sema::ActOnStructuredBindingPattern(
DecompCond->getBeginLoc(), DecompCond->getEndLoc());
if (DecompDS.isInvalid())
return StmtError();
return DecompDS;
}

StmtResult Sema::ActOnStructuredBindingPattern(
SourceLocation ColonLoc, SourceLocation LLoc, SourceLocation RLoc,
SmallVectorImpl<Sema::ParsedPatEltResult> &PatList, Stmt *SubStmt,
Expr *Guard, Stmt *DecompStmt, bool ExcludedFromTypeDeduction) {
auto *DS = static_cast<DeclStmt *>(DecompStmt);
auto *DecompCond = cast<DecompositionDecl>(DS->getSingleDecl());
if (getCurFunction()->InspectStack.empty())
return StmtError();
InspectExpr *Inspect = getCurFunction()->InspectStack.back().getPointer();

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

auto *SBP = StructuredBindingPatternStmt::Create(
Context, LLoc, ColonLoc, LLoc, RLoc, DecompDS.get(), SubStmt, Guard,
PatCond, ExcludedFromTypeDeduction);
Context, LLoc, ColonLoc, LLoc, RLoc, DecompStmt, SubStmt, Guard, PatCond,
ExcludedFromTypeDeduction);

Inspect->addPattern(SBP);
return SBP;
Expand Down
23 changes: 16 additions & 7 deletions clang/test/AST/ast-dump-inspect-stmt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -162,19 +162,28 @@ void TestInspect(int a, int b) {
};
insn_type insn;
inspect(insn) {
[o, i] => { o++; };
[o, i] if (o+i < 12) => { o++; };
};
// CHECK: InspectExpr
// CHECK: StructuredBindingPatternStmt
// CHECK: |-CompoundStmt {{.*}} <col:15, col:22>
// CHECK: | `-UnaryOperator {{.*}} <col:17, col:18> 'unsigned int' postfix '++'
// CHECK: | `-DeclRefExpr {{.*}} <col:17> 'unsigned int' lvalue bitfield Binding {{.*}} 'o' 'unsigned int'
// CHECK: `-DeclStmt
// CHECK: |-CompoundStmt {{.*}} <col:29, col:36>
// CHECK: | `-UnaryOperator {{.*}} <col:31, col:32> 'unsigned int' postfix '++'
// CHECK: | `-DeclRefExpr {{.*}} <col:31> 'unsigned int' lvalue bitfield Binding {{.*}} 'o' 'unsigned int'
// CHECK: |-DeclStmt
// CHECK: `-DecompositionDecl {{.*}} used 'insn_type &' cinit
// CHECK: |-BindingDecl {{.*}} col:6 referenced o 'unsigned int'
// CHECK: | `-MemberExpr {{.*}} <col:6> 'unsigned int' lvalue bitfield .opc
// CHECK: `-BindingDecl {{.*}} <col:9> col:9 i 'unsigned int'
// CHECK: `-MemberExpr {{.*}} <col:9> 'unsigned int' lvalue bitfield .imm
// CHECK: `-BindingDecl {{.*}} <col:9> col:9 referenced i 'unsigned int'
// CHECK: `-MemberExpr {{.*}} <col:9> 'unsigned int' lvalue bitfield .imm
// CHECK: `-BinaryOperator {{.*}} <col:16, col:22> 'bool' '<'
// CHECK: |-BinaryOperator {{.*}} <col:16, col:18> 'int' '+'
// CHECK: | |-ImplicitCastExpr {{.*}} <col:16> 'int' <IntegralCast>
// CHECK: | | `-ImplicitCastExpr {{.*}} <col:16> 'unsigned int' <LValueToRValue>
// CHECK: | | `-DeclRefExpr {{.*}} <col:16> 'unsigned int' lvalue bitfield Binding {{.*}} 'o' 'unsigned int'
// CHECK: | `-ImplicitCastExpr {{.*}} <col:18> 'int' <IntegralCast>
// CHECK: | `-ImplicitCastExpr {{.*}} <col:18> 'unsigned int' <LValueToRValue>
// CHECK: | `-DeclRefExpr {{.*}} <col:18> 'unsigned int' lvalue bitfield Binding {{.*}} 'i' 'unsigned int'
// CHECK: `-IntegerLiteral {{.*}} <col:22> 'int' 12
}

using size_t = decltype(sizeof(0));
Expand Down
1 change: 1 addition & 0 deletions clang/test/SemaCXX/inspect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,7 @@ void stbind0(int x) {
int array[2] = {2,1};
inspect (array) {
[1,2] =>;
[id0, id1] if (id0+id1 < 10) =>;
};

using FourUInts = unsigned __attribute__((__vector_size__(16)));
Expand Down

0 comments on commit dba1477

Please sign in to comment.