|
@@ -72,10 +72,10 @@ public:
|
|
JumpScopeChecker(Stmt *Body, Sema &S);
|
|
JumpScopeChecker(Stmt *Body, Sema &S);
|
|
private:
|
|
private:
|
|
void BuildScopeInformation(Decl *D, unsigned &ParentScope);
|
|
void BuildScopeInformation(Decl *D, unsigned &ParentScope);
|
|
- void BuildScopeInformation(VarDecl *D, const BlockDecl *BDecl,
|
|
|
|
|
|
+ void BuildScopeInformation(VarDecl *D, const BlockDecl *BDecl,
|
|
unsigned &ParentScope);
|
|
unsigned &ParentScope);
|
|
void BuildScopeInformation(Stmt *S, unsigned &origParentScope);
|
|
void BuildScopeInformation(Stmt *S, unsigned &origParentScope);
|
|
-
|
|
|
|
|
|
+
|
|
void VerifyJumps();
|
|
void VerifyJumps();
|
|
void VerifyIndirectJumps();
|
|
void VerifyIndirectJumps();
|
|
void NoteJumpIntoScopes(ArrayRef<unsigned> ToScopes);
|
|
void NoteJumpIntoScopes(ArrayRef<unsigned> ToScopes);
|
|
@@ -166,7 +166,7 @@ static ScopePair GetDiagForGotoScopeDecl(Sema &S, const Decl *D) {
|
|
// A program that jumps from a point where a variable with automatic
|
|
// A program that jumps from a point where a variable with automatic
|
|
// storage duration is not in scope to a point where it is in scope
|
|
// storage duration is not in scope to a point where it is in scope
|
|
// is ill-formed unless the variable has scalar type, class type with
|
|
// is ill-formed unless the variable has scalar type, class type with
|
|
- // a trivial default constructor and a trivial destructor, a
|
|
|
|
|
|
+ // a trivial default constructor and a trivial destructor, a
|
|
// cv-qualified version of one of these types, or an array of one of
|
|
// cv-qualified version of one of these types, or an array of one of
|
|
// the preceding types and is declared without an initializer.
|
|
// the preceding types and is declared without an initializer.
|
|
|
|
|
|
@@ -218,7 +218,7 @@ void JumpScopeChecker::BuildScopeInformation(Decl *D, unsigned &ParentScope) {
|
|
D->getLocation()));
|
|
D->getLocation()));
|
|
ParentScope = Scopes.size()-1;
|
|
ParentScope = Scopes.size()-1;
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
// If the decl has an initializer, walk it with the potentially new
|
|
// If the decl has an initializer, walk it with the potentially new
|
|
// scope we just installed.
|
|
// scope we just installed.
|
|
if (VarDecl *VD = dyn_cast<VarDecl>(D))
|
|
if (VarDecl *VD = dyn_cast<VarDecl>(D))
|
|
@@ -227,8 +227,8 @@ void JumpScopeChecker::BuildScopeInformation(Decl *D, unsigned &ParentScope) {
|
|
}
|
|
}
|
|
|
|
|
|
/// \brief Build scope information for a captured block literal variables.
|
|
/// \brief Build scope information for a captured block literal variables.
|
|
-void JumpScopeChecker::BuildScopeInformation(VarDecl *D,
|
|
|
|
- const BlockDecl *BDecl,
|
|
|
|
|
|
+void JumpScopeChecker::BuildScopeInformation(VarDecl *D,
|
|
|
|
+ const BlockDecl *BDecl,
|
|
unsigned &ParentScope) {
|
|
unsigned &ParentScope) {
|
|
// exclude captured __block variables; there's no destructor
|
|
// exclude captured __block variables; there's no destructor
|
|
// associated with the block literal for them.
|
|
// associated with the block literal for them.
|
|
@@ -257,7 +257,7 @@ void JumpScopeChecker::BuildScopeInformation(VarDecl *D,
|
|
SourceLocation Loc = D->getLocation();
|
|
SourceLocation Loc = D->getLocation();
|
|
if (Loc.isInvalid())
|
|
if (Loc.isInvalid())
|
|
Loc = BDecl->getLocation();
|
|
Loc = BDecl->getLocation();
|
|
- Scopes.push_back(GotoScope(ParentScope,
|
|
|
|
|
|
+ Scopes.push_back(GotoScope(ParentScope,
|
|
Diags.first, Diags.second, Loc));
|
|
Diags.first, Diags.second, Loc));
|
|
ParentScope = Scopes.size()-1;
|
|
ParentScope = Scopes.size()-1;
|
|
}
|
|
}
|
|
@@ -272,11 +272,11 @@ void JumpScopeChecker::BuildScopeInformation(Stmt *S, unsigned &origParentScope)
|
|
// propagate out into the enclosing scope. Otherwise we have to worry
|
|
// propagate out into the enclosing scope. Otherwise we have to worry
|
|
// about block literals, which have the lifetime of their enclosing statement.
|
|
// about block literals, which have the lifetime of their enclosing statement.
|
|
unsigned independentParentScope = origParentScope;
|
|
unsigned independentParentScope = origParentScope;
|
|
- unsigned &ParentScope = ((isa<Expr>(S) && !isa<StmtExpr>(S))
|
|
|
|
|
|
+ unsigned &ParentScope = ((isa<Expr>(S) && !isa<StmtExpr>(S))
|
|
? origParentScope : independentParentScope);
|
|
? origParentScope : independentParentScope);
|
|
|
|
|
|
bool SkipFirstSubStmt = false;
|
|
bool SkipFirstSubStmt = false;
|
|
-
|
|
|
|
|
|
+
|
|
// If we found a label, remember that it is in ParentScope scope.
|
|
// If we found a label, remember that it is in ParentScope scope.
|
|
switch (S->getStmtClass()) {
|
|
switch (S->getStmtClass()) {
|
|
case Stmt::AddrLabelExprClass:
|
|
case Stmt::AddrLabelExprClass:
|
|
@@ -307,7 +307,7 @@ void JumpScopeChecker::BuildScopeInformation(Stmt *S, unsigned &origParentScope)
|
|
SkipFirstSubStmt = true;
|
|
SkipFirstSubStmt = true;
|
|
}
|
|
}
|
|
// Fall through
|
|
// Fall through
|
|
-
|
|
|
|
|
|
+
|
|
case Stmt::GotoStmtClass:
|
|
case Stmt::GotoStmtClass:
|
|
// Remember both what scope a goto is in as well as the fact that we have
|
|
// Remember both what scope a goto is in as well as the fact that we have
|
|
// it. This makes the second scan not have to walk the AST again.
|
|
// it. This makes the second scan not have to walk the AST again.
|
|
@@ -332,7 +332,7 @@ void JumpScopeChecker::BuildScopeInformation(Stmt *S, unsigned &origParentScope)
|
|
diag::note_protected_by_cxx_catch,
|
|
diag::note_protected_by_cxx_catch,
|
|
diag::note_exits_cxx_catch,
|
|
diag::note_exits_cxx_catch,
|
|
CS->getSourceRange().getBegin()));
|
|
CS->getSourceRange().getBegin()));
|
|
- BuildScopeInformation(CS->getHandlerBlock(),
|
|
|
|
|
|
+ BuildScopeInformation(CS->getHandlerBlock(),
|
|
(newParentScope = Scopes.size()-1));
|
|
(newParentScope = Scopes.size()-1));
|
|
}
|
|
}
|
|
return;
|
|
return;
|
|
@@ -354,14 +354,14 @@ void JumpScopeChecker::BuildScopeInformation(Stmt *S, unsigned &origParentScope)
|
|
diag::note_protected_by_seh_except,
|
|
diag::note_protected_by_seh_except,
|
|
diag::note_exits_seh_except,
|
|
diag::note_exits_seh_except,
|
|
Except->getSourceRange().getBegin()));
|
|
Except->getSourceRange().getBegin()));
|
|
- BuildScopeInformation(Except->getBlock(),
|
|
|
|
|
|
+ BuildScopeInformation(Except->getBlock(),
|
|
(newParentScope = Scopes.size()-1));
|
|
(newParentScope = Scopes.size()-1));
|
|
} else if (SEHFinallyStmt *Finally = TS->getFinallyHandler()) {
|
|
} else if (SEHFinallyStmt *Finally = TS->getFinallyHandler()) {
|
|
Scopes.push_back(GotoScope(ParentScope,
|
|
Scopes.push_back(GotoScope(ParentScope,
|
|
diag::note_protected_by_seh_finally,
|
|
diag::note_protected_by_seh_finally,
|
|
diag::note_exits_seh_finally,
|
|
diag::note_exits_seh_finally,
|
|
Finally->getSourceRange().getBegin()));
|
|
Finally->getSourceRange().getBegin()));
|
|
- BuildScopeInformation(Finally->getBlock(),
|
|
|
|
|
|
+ BuildScopeInformation(Finally->getBlock(),
|
|
(newParentScope = Scopes.size()-1));
|
|
(newParentScope = Scopes.size()-1));
|
|
}
|
|
}
|
|
|
|
|
|
@@ -377,7 +377,7 @@ void JumpScopeChecker::BuildScopeInformation(Stmt *S, unsigned &origParentScope)
|
|
SkipFirstSubStmt = false;
|
|
SkipFirstSubStmt = false;
|
|
continue;
|
|
continue;
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
Stmt *SubStmt = *CI;
|
|
Stmt *SubStmt = *CI;
|
|
if (!SubStmt) continue;
|
|
if (!SubStmt) continue;
|
|
|
|
|
|
@@ -428,7 +428,7 @@ void JumpScopeChecker::BuildScopeInformation(Stmt *S, unsigned &origParentScope)
|
|
diag::note_exits_objc_catch,
|
|
diag::note_exits_objc_catch,
|
|
AC->getAtCatchLoc()));
|
|
AC->getAtCatchLoc()));
|
|
// @catches are nested and it isn't
|
|
// @catches are nested and it isn't
|
|
- BuildScopeInformation(AC->getCatchBody(),
|
|
|
|
|
|
+ BuildScopeInformation(AC->getCatchBody(),
|
|
(newParentScope = Scopes.size()-1));
|
|
(newParentScope = Scopes.size()-1));
|
|
}
|
|
}
|
|
|
|
|
|
@@ -443,7 +443,7 @@ void JumpScopeChecker::BuildScopeInformation(Stmt *S, unsigned &origParentScope)
|
|
|
|
|
|
continue;
|
|
continue;
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
unsigned newParentScope;
|
|
unsigned newParentScope;
|
|
// Disallow jumps into the protected statement of an @synchronized, but
|
|
// Disallow jumps into the protected statement of an @synchronized, but
|
|
// allow jumps into the object expression it protects.
|
|
// allow jumps into the object expression it protects.
|
|
@@ -459,7 +459,7 @@ void JumpScopeChecker::BuildScopeInformation(Stmt *S, unsigned &origParentScope)
|
|
diag::note_protected_by_objc_synchronized,
|
|
diag::note_protected_by_objc_synchronized,
|
|
diag::note_exits_objc_synchronized,
|
|
diag::note_exits_objc_synchronized,
|
|
AS->getAtSynchronizedLoc()));
|
|
AS->getAtSynchronizedLoc()));
|
|
- BuildScopeInformation(AS->getSynchBody(),
|
|
|
|
|
|
+ BuildScopeInformation(AS->getSynchBody(),
|
|
(newParentScope = Scopes.size()-1));
|
|
(newParentScope = Scopes.size()-1));
|
|
continue;
|
|
continue;
|
|
}
|
|
}
|