@@ -234,6 +234,65 @@ std::pair<bool, Stmt *> SemaAnnotator::walkToStmtPre(Stmt *S) {
234
234
// Already walked children.
235
235
return { false , Continue ? DeferS : nullptr };
236
236
}
237
+
238
+ auto doSkipChildren = [&]() -> std::pair<bool , Stmt *> {
239
+ if (!walkToStmtPost (S))
240
+ return {false , nullptr };
241
+ return {false , S};
242
+ };
243
+
244
+ auto doStopTraversal = [&]() -> std::pair<bool , Stmt *> {
245
+ Cancelled = true ;
246
+ return {false , nullptr };
247
+ };
248
+
249
+ // Make sure to walk a ForEachStmt in source order. Note this is a narrow
250
+ // fix for release/5.5. On main, this is fixed in the ASTWalker itself.
251
+ // rdar://78781061
252
+ if (auto *FE = dyn_cast<ForEachStmt>(S)) {
253
+ if (auto *P = FE->getPattern ()) {
254
+ auto *NewP = P->walk (*this );
255
+ if (!NewP)
256
+ return doStopTraversal ();
257
+ assert (NewP == P);
258
+ }
259
+ if (auto *SE = FE->getSequence ()) {
260
+ auto *NewSE = SE->walk (*this );
261
+ if (!NewSE)
262
+ return doStopTraversal ();
263
+ assert (NewSE == SE);
264
+ }
265
+ if (auto *Where = FE->getWhere ()) {
266
+ auto *NewWhere = Where->walk (*this );
267
+ if (!NewWhere)
268
+ return doStopTraversal ();
269
+ assert (NewWhere == Where);
270
+ }
271
+ if (auto *IteratorNext = FE->getConvertElementExpr ()) {
272
+ auto *NewIteratorNext = IteratorNext->walk (*this );
273
+ if (!NewIteratorNext)
274
+ return doStopTraversal ();
275
+ assert (NewIteratorNext == IteratorNext);
276
+ }
277
+ if (auto *IteratorVar = FE->getIteratorVar ()) {
278
+ if (IteratorVar->walk (*this ))
279
+ return doStopTraversal ();
280
+ }
281
+ if (auto *IteratorVarRef = FE->getIteratorVarRef ()) {
282
+ auto *NewIteratorVarRef = IteratorVarRef->walk (*this );
283
+ if (!NewIteratorVarRef)
284
+ return doStopTraversal ();
285
+ assert (NewIteratorVarRef == IteratorVarRef);
286
+ }
287
+ if (auto *Body = FE->getBody ()) {
288
+ auto *NewBody = Body->walk (*this );
289
+ if (!NewBody)
290
+ return doStopTraversal ();
291
+ assert (NewBody == Body);
292
+ }
293
+ // Already visited.
294
+ return doSkipChildren ();
295
+ }
237
296
}
238
297
return { TraverseChildren, S };
239
298
}
0 commit comments