@@ -968,6 +968,47 @@ namespace {
968
968
};
969
969
} // unnamed namespace
970
970
971
+ static void parseWhereGuard (Parser &P, GuardedPattern &result,
972
+ ParserStatus &status,
973
+ GuardedPatternContext parsingContext,
974
+ bool isExprBasic) {
975
+ if (P.Tok .is (tok::kw_where)) {
976
+ SyntaxParsingContext WhereClauseCtxt (P.SyntaxContext ,
977
+ SyntaxKind::WhereClause);
978
+ result.WhereLoc = P.consumeToken (tok::kw_where);
979
+ SourceLoc startOfGuard = P.Tok .getLoc ();
980
+
981
+ auto diagKind = [=]() -> Diag<> {
982
+ switch (parsingContext) {
983
+ case GuardedPatternContext::Case:
984
+ return diag::expected_case_where_expr;
985
+ case GuardedPatternContext::Catch:
986
+ return diag::expected_catch_where_expr;
987
+ }
988
+ llvm_unreachable (" bad context" );
989
+ }();
990
+ ParserResult<Expr> guardResult = P.parseExprImpl (diagKind, isExprBasic);
991
+ status |= guardResult;
992
+
993
+ // Use the parsed guard expression if possible.
994
+ if (guardResult.isNonNull ()) {
995
+ result.Guard = guardResult.get ();
996
+
997
+ // Otherwise, fake up an ErrorExpr.
998
+ } else {
999
+ // If we didn't consume any tokens failing to parse the
1000
+ // expression, don't put in the source range of the ErrorExpr.
1001
+ SourceRange errorRange;
1002
+ if (startOfGuard == P.Tok .getLoc ()) {
1003
+ errorRange = result.WhereLoc ;
1004
+ } else {
1005
+ errorRange = SourceRange (startOfGuard, P.PreviousLoc );
1006
+ }
1007
+ result.Guard = new (P.Context ) ErrorExpr (errorRange);
1008
+ }
1009
+ }
1010
+ }
1011
+
971
1012
// / Parse a pattern-matching clause for a case or catch statement,
972
1013
// / including the guard expression:
973
1014
// /
@@ -1045,7 +1086,6 @@ static void parseGuardedPattern(Parser &P, GuardedPattern &result,
1045
1086
patternResult = makeParserResult (varPattern);
1046
1087
}
1047
1088
1048
-
1049
1089
// Okay, if the special code-completion didn't kick in, parse a
1050
1090
// matching pattern.
1051
1091
if (patternResult.isNull ()) {
@@ -1074,26 +1114,28 @@ static void parseGuardedPattern(Parser &P, GuardedPattern &result,
1074
1114
if (VD->hasName ()) P.addToScope (VD);
1075
1115
boundDecls.push_back (VD);
1076
1116
});
1117
+
1118
+ // Now that we have them, mark them as being initialized without a PBD.
1119
+ for (auto VD : boundDecls)
1120
+ VD->setHasNonPatternBindingInit ();
1121
+
1122
+ // Parse the optional 'where' guard.
1123
+ parseWhereGuard (P, result, status, parsingContext, isExprBasic);
1077
1124
} else {
1078
1125
// If boundDecls already contains variables, then we must match the
1079
1126
// same number and same names in this pattern as were declared in a
1080
1127
// previous pattern (and later we will make sure they have the same
1081
1128
// types).
1129
+ Scope guardScope (&P, ScopeKind::CaseVars);
1082
1130
SmallVector<VarDecl*, 4 > repeatedDecls;
1083
1131
patternResult.get ()->forEachVariable ([&](VarDecl *VD) {
1084
1132
if (!VD->hasName ())
1085
1133
return ;
1086
1134
1087
- for (auto repeat : repeatedDecls)
1088
- if (repeat->getName () == VD->getName ())
1089
- P.addToScope (VD); // will diagnose a duplicate declaration
1090
-
1091
1135
bool found = false ;
1092
1136
for (auto previous : boundDecls) {
1093
1137
if (previous->hasName () && previous->getName () == VD->getName ()) {
1094
1138
found = true ;
1095
- // Use the same local discriminator.
1096
- VD->setLocalDiscriminator (previous->getLocalDiscriminator ());
1097
1139
break ;
1098
1140
}
1099
1141
}
@@ -1103,6 +1145,9 @@ static void parseGuardedPattern(Parser &P, GuardedPattern &result,
1103
1145
status.setIsParseError ();
1104
1146
}
1105
1147
repeatedDecls.push_back (VD);
1148
+ P.setLocalDiscriminator (VD);
1149
+ if (VD->hasName ())
1150
+ P.addToScope (VD);
1106
1151
});
1107
1152
1108
1153
for (auto previous : boundDecls) {
@@ -1124,47 +1169,10 @@ static void parseGuardedPattern(Parser &P, GuardedPattern &result,
1124
1169
VD->setHasNonPatternBindingInit ();
1125
1170
VD->setImplicit ();
1126
1171
}
1127
- }
1128
-
1129
- // Now that we have them, mark them as being initialized without a PBD.
1130
- for (auto VD : boundDecls)
1131
- VD->setHasNonPatternBindingInit ();
1132
-
1133
- // Parse the optional 'where' guard.
1134
- if (P.Tok .is (tok::kw_where)) {
1135
- SyntaxParsingContext WhereClauseCtxt (P.SyntaxContext ,
1136
- SyntaxKind::WhereClause);
1137
- result.WhereLoc = P.consumeToken (tok::kw_where);
1138
- SourceLoc startOfGuard = P.Tok .getLoc ();
1139
1172
1140
- auto diagKind = [=]() -> Diag<> {
1141
- switch (parsingContext) {
1142
- case GuardedPatternContext::Case:
1143
- return diag::expected_case_where_expr;
1144
- case GuardedPatternContext::Catch:
1145
- return diag::expected_catch_where_expr;
1146
- }
1147
- llvm_unreachable (" bad context" );
1148
- }();
1149
- ParserResult<Expr> guardResult = P.parseExprImpl (diagKind, isExprBasic);
1150
- status |= guardResult;
1151
-
1152
- // Use the parsed guard expression if possible.
1153
- if (guardResult.isNonNull ()) {
1154
- result.Guard = guardResult.get ();
1155
-
1156
- // Otherwise, fake up an ErrorExpr.
1157
- } else {
1158
- // If we didn't consume any tokens failing to parse the
1159
- // expression, don't put in the source range of the ErrorExpr.
1160
- SourceRange errorRange;
1161
- if (startOfGuard == P.Tok .getLoc ()) {
1162
- errorRange = result.WhereLoc ;
1163
- } else {
1164
- errorRange = SourceRange (startOfGuard, P.PreviousLoc );
1165
- }
1166
- result.Guard = new (P.Context ) ErrorExpr (errorRange);
1167
- }
1173
+ // Parse the optional 'where' guard, with this particular pattern's bound
1174
+ // vars in scope.
1175
+ parseWhereGuard (P, result, status, parsingContext, isExprBasic);
1168
1176
}
1169
1177
}
1170
1178
0 commit comments