[Sema][ObjC] Disallow jumping into ObjC fast enumeration loops.
authorAkira Hatanaka <ahatanaka@apple.com>
Wed, 19 Apr 2017 17:54:08 +0000 (17:54 +0000)
committerAkira Hatanaka <ahatanaka@apple.com>
Wed, 19 Apr 2017 17:54:08 +0000 (17:54 +0000)
rdar://problem/31635406

Differential Revision: https://reviews.llvm.org/D32187

llvm-svn: 300722

clang/include/clang/Basic/DiagnosticSemaKinds.td
clang/lib/Sema/JumpDiagnostics.cpp
clang/lib/Sema/SemaStmt.cpp
clang/test/SemaObjC/foreach.m

index 3912a85491889ed3f8aa32ac6c7bead9eb63552d..6cb872cc27c529768fe6fd4cab5ba9b129932d74 100644 (file)
@@ -5000,6 +5000,8 @@ def note_protected_by_if_available : Note<
   "jump enters controlled statement of if available">;
 def note_protected_by_vla : Note<
   "jump bypasses initialization of variable length array">;
+def note_protected_by_objc_fast_enumeration : Note<
+  "jump enters Objective-C fast enumeration loop">;
 def note_protected_by_objc_try : Note<
   "jump bypasses initialization of @try block">;
 def note_protected_by_objc_catch : Note<
index 899d3fa83cc3c84aba9fffb88c1afe8719bc2aa2..865aea9e2284cc2ef47b8947087d4a9e3ae2a676 100644 (file)
@@ -287,6 +287,15 @@ void JumpScopeChecker::BuildScopeInformation(Stmt *S,
     IndirectJumpTargets.push_back(cast<AddrLabelExpr>(S)->getLabel());
     break;
 
+  case Stmt::ObjCForCollectionStmtClass: {
+    auto *CS = cast<ObjCForCollectionStmt>(S);
+    unsigned Diag = diag::note_protected_by_objc_fast_enumeration;
+    unsigned NewParentScope = Scopes.size();
+    Scopes.push_back(GotoScope(ParentScope, Diag, 0, S->getLocStart()));
+    BuildScopeInformation(CS->getBody(), NewParentScope);
+    return;
+  }
+
   case Stmt::IndirectGotoStmtClass:
     // "goto *&&lbl;" is a special case which we treat as equivalent
     // to a normal goto.  In addition, we don't calculate scope in the
index 9be1c56f062277fda96231cd26027d3a06551205..9ffc23b5adbab5972078e3849a76e23c6febb5da 100644 (file)
@@ -1783,6 +1783,7 @@ StmtResult
 Sema::ActOnObjCForCollectionStmt(SourceLocation ForLoc,
                                  Stmt *First, Expr *collection,
                                  SourceLocation RParenLoc) {
+  getCurFunction()->setHasBranchProtectedScope();
 
   ExprResult CollectionExprResult =
     CheckObjCForCollectionOperand(ForLoc, collection);
index 91ea2ec4e0d48a03c5b8a063969cfe04a9f38851..477c4fc383633db0a2bd548600ce9cd597740a98 100644 (file)
@@ -55,3 +55,27 @@ void test2(NSObject<NSFastEnumeration> *collection) {
   for (obj.prop in collection) { /* expected-error {{selector element is not a valid lvalue}} */
   }
 }
+
+int cond();
+
+void test3(NSObject<NSFastEnumeration> *a0, NSObject<NSFastEnumeration> *a1) {
+  for (id i in a0) { /* expected-note 2 {{jump enters Objective-C fast enumeration loop}} */
+    for (id j in a1) { /* expected-note 2 {{jump enters Objective-C fast enumeration loop}} */
+      (void)i, (void)j;
+label0:
+      if (cond())
+        goto label1;
+    }
+label1:
+    if (cond())
+      goto label0; /* expected-error {{cannot jump from this goto statement to its label}} */
+    if (cond())
+      goto label2;
+  }
+
+label2:
+  if (cond())
+    goto label0; /* expected-error {{cannot jump from this goto statement to its label}} */
+  if (cond())
+    goto label1; /* expected-error{{cannot jump from this goto statement to its label}} */
+}