mirror of https://github.com/microsoft/clang.git
[Sema][ObjC] Disallow jumping into ObjC fast enumeration loops.
rdar://problem/31635406 Differential Revision: https://reviews.llvm.org/D32187 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@300722 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
bfb79c8fec
commit
17081268e2
|
@ -5000,6 +5000,8 @@ def note_protected_by_if_available : Note<
|
||||||
"jump enters controlled statement of if available">;
|
"jump enters controlled statement of if available">;
|
||||||
def note_protected_by_vla : Note<
|
def note_protected_by_vla : Note<
|
||||||
"jump bypasses initialization of variable length array">;
|
"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<
|
def note_protected_by_objc_try : Note<
|
||||||
"jump bypasses initialization of @try block">;
|
"jump bypasses initialization of @try block">;
|
||||||
def note_protected_by_objc_catch : Note<
|
def note_protected_by_objc_catch : Note<
|
||||||
|
|
|
@ -287,6 +287,15 @@ void JumpScopeChecker::BuildScopeInformation(Stmt *S,
|
||||||
IndirectJumpTargets.push_back(cast<AddrLabelExpr>(S)->getLabel());
|
IndirectJumpTargets.push_back(cast<AddrLabelExpr>(S)->getLabel());
|
||||||
break;
|
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:
|
case Stmt::IndirectGotoStmtClass:
|
||||||
// "goto *&&lbl;" is a special case which we treat as equivalent
|
// "goto *&&lbl;" is a special case which we treat as equivalent
|
||||||
// to a normal goto. In addition, we don't calculate scope in the
|
// to a normal goto. In addition, we don't calculate scope in the
|
||||||
|
|
|
@ -1783,6 +1783,7 @@ StmtResult
|
||||||
Sema::ActOnObjCForCollectionStmt(SourceLocation ForLoc,
|
Sema::ActOnObjCForCollectionStmt(SourceLocation ForLoc,
|
||||||
Stmt *First, Expr *collection,
|
Stmt *First, Expr *collection,
|
||||||
SourceLocation RParenLoc) {
|
SourceLocation RParenLoc) {
|
||||||
|
getCurFunction()->setHasBranchProtectedScope();
|
||||||
|
|
||||||
ExprResult CollectionExprResult =
|
ExprResult CollectionExprResult =
|
||||||
CheckObjCForCollectionOperand(ForLoc, collection);
|
CheckObjCForCollectionOperand(ForLoc, collection);
|
||||||
|
|
|
@ -55,3 +55,27 @@ void test2(NSObject<NSFastEnumeration> *collection) {
|
||||||
for (obj.prop in collection) { /* expected-error {{selector element is not a valid lvalue}} */
|
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}} */
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue