JumpDiagnostics.cpp revision 6490ae5003226cae28f980648948bea8b21a8638
15af280ce21af061f96b5b5b752746871e364ba99Chris Lattner//===--- JumpDiagnostics.cpp - Analyze Jump Targets for VLA issues --------===//
25af280ce21af061f96b5b5b752746871e364ba99Chris Lattner//
35af280ce21af061f96b5b5b752746871e364ba99Chris Lattner//                     The LLVM Compiler Infrastructure
45af280ce21af061f96b5b5b752746871e364ba99Chris Lattner//
55af280ce21af061f96b5b5b752746871e364ba99Chris Lattner// This file is distributed under the University of Illinois Open Source
65af280ce21af061f96b5b5b752746871e364ba99Chris Lattner// License. See LICENSE.TXT for details.
75af280ce21af061f96b5b5b752746871e364ba99Chris Lattner//
85af280ce21af061f96b5b5b752746871e364ba99Chris Lattner//===----------------------------------------------------------------------===//
95af280ce21af061f96b5b5b752746871e364ba99Chris Lattner//
105af280ce21af061f96b5b5b752746871e364ba99Chris Lattner// This file implements the JumpScopeChecker class, which is used to diagnose
115af280ce21af061f96b5b5b752746871e364ba99Chris Lattner// jumps that enter a VLA scope in an invalid way.
125af280ce21af061f96b5b5b752746871e364ba99Chris Lattner//
135af280ce21af061f96b5b5b752746871e364ba99Chris Lattner//===----------------------------------------------------------------------===//
145af280ce21af061f96b5b5b752746871e364ba99Chris Lattner
155af280ce21af061f96b5b5b752746871e364ba99Chris Lattner#include "Sema.h"
165af280ce21af061f96b5b5b752746871e364ba99Chris Lattner#include "clang/AST/Expr.h"
1716f0049415ec596504891259e2a83e19871c0d52Chris Lattner#include "clang/AST/StmtObjC.h"
18972041f45bdf8df7ea447221292d7827466ba94bSebastian Redl#include "clang/AST/StmtCXX.h"
195af280ce21af061f96b5b5b752746871e364ba99Chris Lattnerusing namespace clang;
205af280ce21af061f96b5b5b752746871e364ba99Chris Lattner
215af280ce21af061f96b5b5b752746871e364ba99Chris Lattnernamespace {
225af280ce21af061f96b5b5b752746871e364ba99Chris Lattner
235af280ce21af061f96b5b5b752746871e364ba99Chris Lattner/// JumpScopeChecker - This object is used by Sema to diagnose invalid jumps
245af280ce21af061f96b5b5b752746871e364ba99Chris Lattner/// into VLA and other protected scopes.  For example, this rejects:
255af280ce21af061f96b5b5b752746871e364ba99Chris Lattner///    goto L;
265af280ce21af061f96b5b5b752746871e364ba99Chris Lattner///    int a[n];
275af280ce21af061f96b5b5b752746871e364ba99Chris Lattner///  L:
285af280ce21af061f96b5b5b752746871e364ba99Chris Lattner///
295af280ce21af061f96b5b5b752746871e364ba99Chris Lattnerclass JumpScopeChecker {
305af280ce21af061f96b5b5b752746871e364ba99Chris Lattner  Sema &S;
311eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
325af280ce21af061f96b5b5b752746871e364ba99Chris Lattner  /// GotoScope - This is a record that we use to keep track of all of the
335af280ce21af061f96b5b5b752746871e364ba99Chris Lattner  /// scopes that are introduced by VLAs and other things that scope jumps like
345af280ce21af061f96b5b5b752746871e364ba99Chris Lattner  /// gotos.  This scope tree has nothing to do with the source scope tree,
355af280ce21af061f96b5b5b752746871e364ba99Chris Lattner  /// because you can have multiple VLA scopes per compound statement, and most
365af280ce21af061f96b5b5b752746871e364ba99Chris Lattner  /// compound statements don't introduce any scopes.
375af280ce21af061f96b5b5b752746871e364ba99Chris Lattner  struct GotoScope {
385af280ce21af061f96b5b5b752746871e364ba99Chris Lattner    /// ParentScope - The index in ScopeMap of the parent scope.  This is 0 for
395af280ce21af061f96b5b5b752746871e364ba99Chris Lattner    /// the parent scope is the function body.
405af280ce21af061f96b5b5b752746871e364ba99Chris Lattner    unsigned ParentScope;
411eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
425af280ce21af061f96b5b5b752746871e364ba99Chris Lattner    /// Diag - The diagnostic to emit if there is a jump into this scope.
435af280ce21af061f96b5b5b752746871e364ba99Chris Lattner    unsigned Diag;
441eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
455af280ce21af061f96b5b5b752746871e364ba99Chris Lattner    /// Loc - Location to emit the diagnostic.
465af280ce21af061f96b5b5b752746871e364ba99Chris Lattner    SourceLocation Loc;
471eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
485af280ce21af061f96b5b5b752746871e364ba99Chris Lattner    GotoScope(unsigned parentScope, unsigned diag, SourceLocation L)
495af280ce21af061f96b5b5b752746871e364ba99Chris Lattner    : ParentScope(parentScope), Diag(diag), Loc(L) {}
505af280ce21af061f96b5b5b752746871e364ba99Chris Lattner  };
511eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
525af280ce21af061f96b5b5b752746871e364ba99Chris Lattner  llvm::SmallVector<GotoScope, 48> Scopes;
535af280ce21af061f96b5b5b752746871e364ba99Chris Lattner  llvm::DenseMap<Stmt*, unsigned> LabelAndGotoScopes;
545af280ce21af061f96b5b5b752746871e364ba99Chris Lattner  llvm::SmallVector<Stmt*, 16> Jumps;
555af280ce21af061f96b5b5b752746871e364ba99Chris Lattnerpublic:
565af280ce21af061f96b5b5b752746871e364ba99Chris Lattner  JumpScopeChecker(Stmt *Body, Sema &S);
575af280ce21af061f96b5b5b752746871e364ba99Chris Lattnerprivate:
585af280ce21af061f96b5b5b752746871e364ba99Chris Lattner  void BuildScopeInformation(Stmt *S, unsigned ParentScope);
595af280ce21af061f96b5b5b752746871e364ba99Chris Lattner  void VerifyJumps();
605af280ce21af061f96b5b5b752746871e364ba99Chris Lattner  void CheckJump(Stmt *From, Stmt *To,
615af280ce21af061f96b5b5b752746871e364ba99Chris Lattner                 SourceLocation DiagLoc, unsigned JumpDiag);
625af280ce21af061f96b5b5b752746871e364ba99Chris Lattner};
635af280ce21af061f96b5b5b752746871e364ba99Chris Lattner} // end anonymous namespace
645af280ce21af061f96b5b5b752746871e364ba99Chris Lattner
655af280ce21af061f96b5b5b752746871e364ba99Chris Lattner
665af280ce21af061f96b5b5b752746871e364ba99Chris LattnerJumpScopeChecker::JumpScopeChecker(Stmt *Body, Sema &s) : S(s) {
675af280ce21af061f96b5b5b752746871e364ba99Chris Lattner  // Add a scope entry for function scope.
685af280ce21af061f96b5b5b752746871e364ba99Chris Lattner  Scopes.push_back(GotoScope(~0U, ~0U, SourceLocation()));
691eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
705af280ce21af061f96b5b5b752746871e364ba99Chris Lattner  // Build information for the top level compound statement, so that we have a
715af280ce21af061f96b5b5b752746871e364ba99Chris Lattner  // defined scope record for every "goto" and label.
725af280ce21af061f96b5b5b752746871e364ba99Chris Lattner  BuildScopeInformation(Body, 0);
731eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
745af280ce21af061f96b5b5b752746871e364ba99Chris Lattner  // Check that all jumps we saw are kosher.
755af280ce21af061f96b5b5b752746871e364ba99Chris Lattner  VerifyJumps();
765af280ce21af061f96b5b5b752746871e364ba99Chris Lattner}
771eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
785af280ce21af061f96b5b5b752746871e364ba99Chris Lattner/// GetDiagForGotoScopeDecl - If this decl induces a new goto scope, return a
795af280ce21af061f96b5b5b752746871e364ba99Chris Lattner/// diagnostic that should be emitted if control goes over it. If not, return 0.
8040b598eea1310ec9ed554d56ce3e25b34c585458Argyrios Kyrtzidisstatic unsigned GetDiagForGotoScopeDecl(const Decl *D) {
815af280ce21af061f96b5b5b752746871e364ba99Chris Lattner  if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
825af280ce21af061f96b5b5b752746871e364ba99Chris Lattner    if (VD->getType()->isVariablyModifiedType())
835af280ce21af061f96b5b5b752746871e364ba99Chris Lattner      return diag::note_protected_by_vla;
8440b598eea1310ec9ed554d56ce3e25b34c585458Argyrios Kyrtzidis    if (VD->hasAttr<CleanupAttr>())
855af280ce21af061f96b5b5b752746871e364ba99Chris Lattner      return diag::note_protected_by_cleanup;
86be6d259a375bbec49659d54a302c4758058f2eefChris Lattner    if (VD->hasAttr<BlocksAttr>())
87be6d259a375bbec49659d54a302c4758058f2eefChris Lattner      return diag::note_protected_by___block;
885af280ce21af061f96b5b5b752746871e364ba99Chris Lattner  } else if (const TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) {
895af280ce21af061f96b5b5b752746871e364ba99Chris Lattner    if (TD->getUnderlyingType()->isVariablyModifiedType())
905af280ce21af061f96b5b5b752746871e364ba99Chris Lattner      return diag::note_protected_by_vla_typedef;
915af280ce21af061f96b5b5b752746871e364ba99Chris Lattner  }
921eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
935af280ce21af061f96b5b5b752746871e364ba99Chris Lattner  return 0;
945af280ce21af061f96b5b5b752746871e364ba99Chris Lattner}
955af280ce21af061f96b5b5b752746871e364ba99Chris Lattner
965af280ce21af061f96b5b5b752746871e364ba99Chris Lattner
975af280ce21af061f96b5b5b752746871e364ba99Chris Lattner/// BuildScopeInformation - The statements from CI to CE are known to form a
985af280ce21af061f96b5b5b752746871e364ba99Chris Lattner/// coherent VLA scope with a specified parent node.  Walk through the
995af280ce21af061f96b5b5b752746871e364ba99Chris Lattner/// statements, adding any labels or gotos to LabelAndGotoScopes and recursively
1005af280ce21af061f96b5b5b752746871e364ba99Chris Lattner/// walking the AST as needed.
1015af280ce21af061f96b5b5b752746871e364ba99Chris Lattnervoid JumpScopeChecker::BuildScopeInformation(Stmt *S, unsigned ParentScope) {
1021eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1035af280ce21af061f96b5b5b752746871e364ba99Chris Lattner  // If we found a label, remember that it is in ParentScope scope.
1045af280ce21af061f96b5b5b752746871e364ba99Chris Lattner  if (isa<LabelStmt>(S) || isa<DefaultStmt>(S) || isa<CaseStmt>(S)) {
1055af280ce21af061f96b5b5b752746871e364ba99Chris Lattner    LabelAndGotoScopes[S] = ParentScope;
1065af280ce21af061f96b5b5b752746871e364ba99Chris Lattner  } else if (isa<GotoStmt>(S) || isa<SwitchStmt>(S) ||
1075af280ce21af061f96b5b5b752746871e364ba99Chris Lattner             isa<IndirectGotoStmt>(S) || isa<AddrLabelExpr>(S)) {
1085af280ce21af061f96b5b5b752746871e364ba99Chris Lattner    // Remember both what scope a goto is in as well as the fact that we have
1095af280ce21af061f96b5b5b752746871e364ba99Chris Lattner    // it.  This makes the second scan not have to walk the AST again.
1105af280ce21af061f96b5b5b752746871e364ba99Chris Lattner    LabelAndGotoScopes[S] = ParentScope;
1115af280ce21af061f96b5b5b752746871e364ba99Chris Lattner    Jumps.push_back(S);
1125af280ce21af061f96b5b5b752746871e364ba99Chris Lattner  }
1131eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1145af280ce21af061f96b5b5b752746871e364ba99Chris Lattner  for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end(); CI != E;
1155af280ce21af061f96b5b5b752746871e364ba99Chris Lattner       ++CI) {
1165af280ce21af061f96b5b5b752746871e364ba99Chris Lattner    Stmt *SubStmt = *CI;
1175af280ce21af061f96b5b5b752746871e364ba99Chris Lattner    if (SubStmt == 0) continue;
1181eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1195af280ce21af061f96b5b5b752746871e364ba99Chris Lattner    // FIXME: diagnose jumps past initialization: required in C++, warning in C.
1205af280ce21af061f96b5b5b752746871e364ba99Chris Lattner    //   goto L; int X = 4;   L: ;
1215af280ce21af061f96b5b5b752746871e364ba99Chris Lattner
1225af280ce21af061f96b5b5b752746871e364ba99Chris Lattner    // If this is a declstmt with a VLA definition, it defines a scope from here
1235af280ce21af061f96b5b5b752746871e364ba99Chris Lattner    // to the end of the containing context.
1245af280ce21af061f96b5b5b752746871e364ba99Chris Lattner    if (DeclStmt *DS = dyn_cast<DeclStmt>(SubStmt)) {
1255af280ce21af061f96b5b5b752746871e364ba99Chris Lattner      // The decl statement creates a scope if any of the decls in it are VLAs or
1265af280ce21af061f96b5b5b752746871e364ba99Chris Lattner      // have the cleanup attribute.
1275af280ce21af061f96b5b5b752746871e364ba99Chris Lattner      for (DeclStmt::decl_iterator I = DS->decl_begin(), E = DS->decl_end();
1285af280ce21af061f96b5b5b752746871e364ba99Chris Lattner           I != E; ++I) {
1295af280ce21af061f96b5b5b752746871e364ba99Chris Lattner        // If this decl causes a new scope, push and switch to it.
13040b598eea1310ec9ed554d56ce3e25b34c585458Argyrios Kyrtzidis        if (unsigned Diag = GetDiagForGotoScopeDecl(*I)) {
1315af280ce21af061f96b5b5b752746871e364ba99Chris Lattner          Scopes.push_back(GotoScope(ParentScope, Diag, (*I)->getLocation()));
1325af280ce21af061f96b5b5b752746871e364ba99Chris Lattner          ParentScope = Scopes.size()-1;
1335af280ce21af061f96b5b5b752746871e364ba99Chris Lattner        }
1341eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1355af280ce21af061f96b5b5b752746871e364ba99Chris Lattner        // If the decl has an initializer, walk it with the potentially new
1365af280ce21af061f96b5b5b752746871e364ba99Chris Lattner        // scope we just installed.
1375af280ce21af061f96b5b5b752746871e364ba99Chris Lattner        if (VarDecl *VD = dyn_cast<VarDecl>(*I))
1385af280ce21af061f96b5b5b752746871e364ba99Chris Lattner          if (Expr *Init = VD->getInit())
1395af280ce21af061f96b5b5b752746871e364ba99Chris Lattner            BuildScopeInformation(Init, ParentScope);
1405af280ce21af061f96b5b5b752746871e364ba99Chris Lattner      }
1415af280ce21af061f96b5b5b752746871e364ba99Chris Lattner      continue;
1425af280ce21af061f96b5b5b752746871e364ba99Chris Lattner    }
1435af280ce21af061f96b5b5b752746871e364ba99Chris Lattner
1445af280ce21af061f96b5b5b752746871e364ba99Chris Lattner    // Disallow jumps into any part of an @try statement by pushing a scope and
1455af280ce21af061f96b5b5b752746871e364ba99Chris Lattner    // walking all sub-stmts in that scope.
1465af280ce21af061f96b5b5b752746871e364ba99Chris Lattner    if (ObjCAtTryStmt *AT = dyn_cast<ObjCAtTryStmt>(SubStmt)) {
1475af280ce21af061f96b5b5b752746871e364ba99Chris Lattner      // Recursively walk the AST for the @try part.
1485af280ce21af061f96b5b5b752746871e364ba99Chris Lattner      Scopes.push_back(GotoScope(ParentScope,diag::note_protected_by_objc_try,
1495af280ce21af061f96b5b5b752746871e364ba99Chris Lattner                                 AT->getAtTryLoc()));
1505af280ce21af061f96b5b5b752746871e364ba99Chris Lattner      if (Stmt *TryPart = AT->getTryBody())
1515af280ce21af061f96b5b5b752746871e364ba99Chris Lattner        BuildScopeInformation(TryPart, Scopes.size()-1);
1525af280ce21af061f96b5b5b752746871e364ba99Chris Lattner
1535af280ce21af061f96b5b5b752746871e364ba99Chris Lattner      // Jump from the catch to the finally or try is not valid.
1545af280ce21af061f96b5b5b752746871e364ba99Chris Lattner      for (ObjCAtCatchStmt *AC = AT->getCatchStmts(); AC;
1555af280ce21af061f96b5b5b752746871e364ba99Chris Lattner           AC = AC->getNextCatchStmt()) {
1565af280ce21af061f96b5b5b752746871e364ba99Chris Lattner        Scopes.push_back(GotoScope(ParentScope,
1575af280ce21af061f96b5b5b752746871e364ba99Chris Lattner                                   diag::note_protected_by_objc_catch,
1585af280ce21af061f96b5b5b752746871e364ba99Chris Lattner                                   AC->getAtCatchLoc()));
1591eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump        // @catches are nested and it isn't
1605af280ce21af061f96b5b5b752746871e364ba99Chris Lattner        BuildScopeInformation(AC->getCatchBody(), Scopes.size()-1);
1615af280ce21af061f96b5b5b752746871e364ba99Chris Lattner      }
1621eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1635af280ce21af061f96b5b5b752746871e364ba99Chris Lattner      // Jump from the finally to the try or catch is not valid.
1645af280ce21af061f96b5b5b752746871e364ba99Chris Lattner      if (ObjCAtFinallyStmt *AF = AT->getFinallyStmt()) {
1655af280ce21af061f96b5b5b752746871e364ba99Chris Lattner        Scopes.push_back(GotoScope(ParentScope,
1665af280ce21af061f96b5b5b752746871e364ba99Chris Lattner                                   diag::note_protected_by_objc_finally,
1675af280ce21af061f96b5b5b752746871e364ba99Chris Lattner                                   AF->getAtFinallyLoc()));
1685af280ce21af061f96b5b5b752746871e364ba99Chris Lattner        BuildScopeInformation(AF, Scopes.size()-1);
1695af280ce21af061f96b5b5b752746871e364ba99Chris Lattner      }
1701eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1715af280ce21af061f96b5b5b752746871e364ba99Chris Lattner      continue;
1725af280ce21af061f96b5b5b752746871e364ba99Chris Lattner    }
1731eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
17446c3c4ba78766ac0f1c5ec631b424773e21f5271Chris Lattner    // Disallow jumps into the protected statement of an @synchronized, but
17546c3c4ba78766ac0f1c5ec631b424773e21f5271Chris Lattner    // allow jumps into the object expression it protects.
17646c3c4ba78766ac0f1c5ec631b424773e21f5271Chris Lattner    if (ObjCAtSynchronizedStmt *AS = dyn_cast<ObjCAtSynchronizedStmt>(SubStmt)){
17746c3c4ba78766ac0f1c5ec631b424773e21f5271Chris Lattner      // Recursively walk the AST for the @synchronized object expr, it is
17846c3c4ba78766ac0f1c5ec631b424773e21f5271Chris Lattner      // evaluated in the normal scope.
17946c3c4ba78766ac0f1c5ec631b424773e21f5271Chris Lattner      BuildScopeInformation(AS->getSynchExpr(), ParentScope);
1801eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
18146c3c4ba78766ac0f1c5ec631b424773e21f5271Chris Lattner      // Recursively walk the AST for the @synchronized part, protected by a new
18246c3c4ba78766ac0f1c5ec631b424773e21f5271Chris Lattner      // scope.
18346c3c4ba78766ac0f1c5ec631b424773e21f5271Chris Lattner      Scopes.push_back(GotoScope(ParentScope,
18446c3c4ba78766ac0f1c5ec631b424773e21f5271Chris Lattner                                 diag::note_protected_by_objc_synchronized,
18546c3c4ba78766ac0f1c5ec631b424773e21f5271Chris Lattner                                 AS->getAtSynchronizedLoc()));
18646c3c4ba78766ac0f1c5ec631b424773e21f5271Chris Lattner      BuildScopeInformation(AS->getSynchBody(), Scopes.size()-1);
18746c3c4ba78766ac0f1c5ec631b424773e21f5271Chris Lattner      continue;
18846c3c4ba78766ac0f1c5ec631b424773e21f5271Chris Lattner    }
189972041f45bdf8df7ea447221292d7827466ba94bSebastian Redl
190972041f45bdf8df7ea447221292d7827466ba94bSebastian Redl    // Disallow jumps into any part of a C++ try statement. This is pretty
191972041f45bdf8df7ea447221292d7827466ba94bSebastian Redl    // much the same as for Obj-C.
192972041f45bdf8df7ea447221292d7827466ba94bSebastian Redl    if (CXXTryStmt *TS = dyn_cast<CXXTryStmt>(SubStmt)) {
193972041f45bdf8df7ea447221292d7827466ba94bSebastian Redl      Scopes.push_back(GotoScope(ParentScope, diag::note_protected_by_cxx_try,
194972041f45bdf8df7ea447221292d7827466ba94bSebastian Redl                                 TS->getSourceRange().getBegin()));
195972041f45bdf8df7ea447221292d7827466ba94bSebastian Redl      if (Stmt *TryBlock = TS->getTryBlock())
196972041f45bdf8df7ea447221292d7827466ba94bSebastian Redl        BuildScopeInformation(TryBlock, Scopes.size()-1);
197972041f45bdf8df7ea447221292d7827466ba94bSebastian Redl
198972041f45bdf8df7ea447221292d7827466ba94bSebastian Redl      // Jump from the catch into the try is not allowed either.
1991eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump      for (unsigned I = 0, E = TS->getNumHandlers(); I != E; ++I) {
200972041f45bdf8df7ea447221292d7827466ba94bSebastian Redl        CXXCatchStmt *CS = TS->getHandler(I);
201972041f45bdf8df7ea447221292d7827466ba94bSebastian Redl        Scopes.push_back(GotoScope(ParentScope,
202972041f45bdf8df7ea447221292d7827466ba94bSebastian Redl                                   diag::note_protected_by_cxx_catch,
203972041f45bdf8df7ea447221292d7827466ba94bSebastian Redl                                   CS->getSourceRange().getBegin()));
204972041f45bdf8df7ea447221292d7827466ba94bSebastian Redl        BuildScopeInformation(CS->getHandlerBlock(), Scopes.size()-1);
205972041f45bdf8df7ea447221292d7827466ba94bSebastian Redl      }
206972041f45bdf8df7ea447221292d7827466ba94bSebastian Redl
207972041f45bdf8df7ea447221292d7827466ba94bSebastian Redl      continue;
208972041f45bdf8df7ea447221292d7827466ba94bSebastian Redl    }
209972041f45bdf8df7ea447221292d7827466ba94bSebastian Redl
2105af280ce21af061f96b5b5b752746871e364ba99Chris Lattner    // Recursively walk the AST.
2115af280ce21af061f96b5b5b752746871e364ba99Chris Lattner    BuildScopeInformation(SubStmt, ParentScope);
2125af280ce21af061f96b5b5b752746871e364ba99Chris Lattner  }
2135af280ce21af061f96b5b5b752746871e364ba99Chris Lattner}
2145af280ce21af061f96b5b5b752746871e364ba99Chris Lattner
2155af280ce21af061f96b5b5b752746871e364ba99Chris Lattner/// VerifyJumps - Verify each element of the Jumps array to see if they are
2165af280ce21af061f96b5b5b752746871e364ba99Chris Lattner/// valid, emitting diagnostics if not.
2175af280ce21af061f96b5b5b752746871e364ba99Chris Lattnervoid JumpScopeChecker::VerifyJumps() {
2185af280ce21af061f96b5b5b752746871e364ba99Chris Lattner  while (!Jumps.empty()) {
2195af280ce21af061f96b5b5b752746871e364ba99Chris Lattner    Stmt *Jump = Jumps.pop_back_val();
2201eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2211eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    // With a goto,
2225af280ce21af061f96b5b5b752746871e364ba99Chris Lattner    if (GotoStmt *GS = dyn_cast<GotoStmt>(Jump)) {
2235af280ce21af061f96b5b5b752746871e364ba99Chris Lattner      CheckJump(GS, GS->getLabel(), GS->getGotoLoc(),
2245af280ce21af061f96b5b5b752746871e364ba99Chris Lattner                diag::err_goto_into_protected_scope);
2255af280ce21af061f96b5b5b752746871e364ba99Chris Lattner      continue;
2265af280ce21af061f96b5b5b752746871e364ba99Chris Lattner    }
2271eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2285af280ce21af061f96b5b5b752746871e364ba99Chris Lattner    if (SwitchStmt *SS = dyn_cast<SwitchStmt>(Jump)) {
2295af280ce21af061f96b5b5b752746871e364ba99Chris Lattner      for (SwitchCase *SC = SS->getSwitchCaseList(); SC;
2305af280ce21af061f96b5b5b752746871e364ba99Chris Lattner           SC = SC->getNextSwitchCase()) {
2315af280ce21af061f96b5b5b752746871e364ba99Chris Lattner        assert(LabelAndGotoScopes.count(SC) && "Case not visited?");
2325af280ce21af061f96b5b5b752746871e364ba99Chris Lattner        CheckJump(SS, SC, SC->getLocStart(),
2335af280ce21af061f96b5b5b752746871e364ba99Chris Lattner                  diag::err_switch_into_protected_scope);
2345af280ce21af061f96b5b5b752746871e364ba99Chris Lattner      }
2355af280ce21af061f96b5b5b752746871e364ba99Chris Lattner      continue;
2365af280ce21af061f96b5b5b752746871e364ba99Chris Lattner    }
2375af280ce21af061f96b5b5b752746871e364ba99Chris Lattner
2385af280ce21af061f96b5b5b752746871e364ba99Chris Lattner    unsigned DiagnosticScope;
2391eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2405af280ce21af061f96b5b5b752746871e364ba99Chris Lattner    // We don't know where an indirect goto goes, require that it be at the
2415af280ce21af061f96b5b5b752746871e364ba99Chris Lattner    // top level of scoping.
2425af280ce21af061f96b5b5b752746871e364ba99Chris Lattner    if (IndirectGotoStmt *IG = dyn_cast<IndirectGotoStmt>(Jump)) {
2435af280ce21af061f96b5b5b752746871e364ba99Chris Lattner      assert(LabelAndGotoScopes.count(Jump) &&
2445af280ce21af061f96b5b5b752746871e364ba99Chris Lattner             "Jump didn't get added to scopes?");
2455af280ce21af061f96b5b5b752746871e364ba99Chris Lattner      unsigned GotoScope = LabelAndGotoScopes[IG];
2465af280ce21af061f96b5b5b752746871e364ba99Chris Lattner      if (GotoScope == 0) continue;  // indirect jump is ok.
2475af280ce21af061f96b5b5b752746871e364ba99Chris Lattner      S.Diag(IG->getGotoLoc(), diag::err_indirect_goto_in_protected_scope);
2485af280ce21af061f96b5b5b752746871e364ba99Chris Lattner      DiagnosticScope = GotoScope;
2495af280ce21af061f96b5b5b752746871e364ba99Chris Lattner    } else {
2505af280ce21af061f96b5b5b752746871e364ba99Chris Lattner      // We model &&Label as a jump for purposes of scope tracking.  We actually
2515af280ce21af061f96b5b5b752746871e364ba99Chris Lattner      // don't care *where* the address of label is, but we require the *label
2525af280ce21af061f96b5b5b752746871e364ba99Chris Lattner      // itself* to be in scope 0.  If it is nested inside of a VLA scope, then
2535af280ce21af061f96b5b5b752746871e364ba99Chris Lattner      // it is possible for an indirect goto to illegally enter the VLA scope by
2545af280ce21af061f96b5b5b752746871e364ba99Chris Lattner      // indirectly jumping to the label.
2555af280ce21af061f96b5b5b752746871e364ba99Chris Lattner      assert(isa<AddrLabelExpr>(Jump) && "Unknown jump type");
2565af280ce21af061f96b5b5b752746871e364ba99Chris Lattner      LabelStmt *TheLabel = cast<AddrLabelExpr>(Jump)->getLabel();
2571eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2585af280ce21af061f96b5b5b752746871e364ba99Chris Lattner      assert(LabelAndGotoScopes.count(TheLabel) &&
2595af280ce21af061f96b5b5b752746871e364ba99Chris Lattner             "Referenced label didn't get added to scopes?");
2605af280ce21af061f96b5b5b752746871e364ba99Chris Lattner      unsigned LabelScope = LabelAndGotoScopes[TheLabel];
2615af280ce21af061f96b5b5b752746871e364ba99Chris Lattner      if (LabelScope == 0) continue; // Addr of label is ok.
2621eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2635af280ce21af061f96b5b5b752746871e364ba99Chris Lattner      S.Diag(Jump->getLocStart(), diag::err_addr_of_label_in_protected_scope);
2645af280ce21af061f96b5b5b752746871e364ba99Chris Lattner      DiagnosticScope = LabelScope;
2655af280ce21af061f96b5b5b752746871e364ba99Chris Lattner    }
2665af280ce21af061f96b5b5b752746871e364ba99Chris Lattner
2675af280ce21af061f96b5b5b752746871e364ba99Chris Lattner    // Report all the things that would be skipped over by this &&label or
2685af280ce21af061f96b5b5b752746871e364ba99Chris Lattner    // indirect goto.
2695af280ce21af061f96b5b5b752746871e364ba99Chris Lattner    while (DiagnosticScope != 0) {
2705af280ce21af061f96b5b5b752746871e364ba99Chris Lattner      S.Diag(Scopes[DiagnosticScope].Loc, Scopes[DiagnosticScope].Diag);
2715af280ce21af061f96b5b5b752746871e364ba99Chris Lattner      DiagnosticScope = Scopes[DiagnosticScope].ParentScope;
2725af280ce21af061f96b5b5b752746871e364ba99Chris Lattner    }
2735af280ce21af061f96b5b5b752746871e364ba99Chris Lattner  }
2745af280ce21af061f96b5b5b752746871e364ba99Chris Lattner}
2755af280ce21af061f96b5b5b752746871e364ba99Chris Lattner
2765af280ce21af061f96b5b5b752746871e364ba99Chris Lattner/// CheckJump - Validate that the specified jump statement is valid: that it is
2775af280ce21af061f96b5b5b752746871e364ba99Chris Lattner/// jumping within or out of its current scope, not into a deeper one.
2785af280ce21af061f96b5b5b752746871e364ba99Chris Lattnervoid JumpScopeChecker::CheckJump(Stmt *From, Stmt *To,
2795af280ce21af061f96b5b5b752746871e364ba99Chris Lattner                                 SourceLocation DiagLoc, unsigned JumpDiag) {
2805af280ce21af061f96b5b5b752746871e364ba99Chris Lattner  assert(LabelAndGotoScopes.count(From) && "Jump didn't get added to scopes?");
2815af280ce21af061f96b5b5b752746871e364ba99Chris Lattner  unsigned FromScope = LabelAndGotoScopes[From];
2825af280ce21af061f96b5b5b752746871e364ba99Chris Lattner
2835af280ce21af061f96b5b5b752746871e364ba99Chris Lattner  assert(LabelAndGotoScopes.count(To) && "Jump didn't get added to scopes?");
2845af280ce21af061f96b5b5b752746871e364ba99Chris Lattner  unsigned ToScope = LabelAndGotoScopes[To];
2851eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2865af280ce21af061f96b5b5b752746871e364ba99Chris Lattner  // Common case: exactly the same scope, which is fine.
2875af280ce21af061f96b5b5b752746871e364ba99Chris Lattner  if (FromScope == ToScope) return;
2881eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2895af280ce21af061f96b5b5b752746871e364ba99Chris Lattner  // The only valid mismatch jump case happens when the jump is more deeply
2905af280ce21af061f96b5b5b752746871e364ba99Chris Lattner  // nested inside the jump target.  Do a quick scan to see if the jump is valid
2915af280ce21af061f96b5b5b752746871e364ba99Chris Lattner  // because valid code is more common than invalid code.
2925af280ce21af061f96b5b5b752746871e364ba99Chris Lattner  unsigned TestScope = Scopes[FromScope].ParentScope;
2935af280ce21af061f96b5b5b752746871e364ba99Chris Lattner  while (TestScope != ~0U) {
2945af280ce21af061f96b5b5b752746871e364ba99Chris Lattner    // If we found the jump target, then we're jumping out of our current scope,
2955af280ce21af061f96b5b5b752746871e364ba99Chris Lattner    // which is perfectly fine.
2965af280ce21af061f96b5b5b752746871e364ba99Chris Lattner    if (TestScope == ToScope) return;
2971eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2985af280ce21af061f96b5b5b752746871e364ba99Chris Lattner    // Otherwise, scan up the hierarchy.
2995af280ce21af061f96b5b5b752746871e364ba99Chris Lattner    TestScope = Scopes[TestScope].ParentScope;
3005af280ce21af061f96b5b5b752746871e364ba99Chris Lattner  }
3011eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
3025af280ce21af061f96b5b5b752746871e364ba99Chris Lattner  // If we get here, then we know we have invalid code.  Diagnose the bad jump,
3035af280ce21af061f96b5b5b752746871e364ba99Chris Lattner  // and then emit a note at each VLA being jumped out of.
3045af280ce21af061f96b5b5b752746871e364ba99Chris Lattner  S.Diag(DiagLoc, JumpDiag);
3055af280ce21af061f96b5b5b752746871e364ba99Chris Lattner
3065af280ce21af061f96b5b5b752746871e364ba99Chris Lattner  // Eliminate the common prefix of the jump and the target.  Start by
3075af280ce21af061f96b5b5b752746871e364ba99Chris Lattner  // linearizing both scopes, reversing them as we go.
3085af280ce21af061f96b5b5b752746871e364ba99Chris Lattner  std::vector<unsigned> FromScopes, ToScopes;
3095af280ce21af061f96b5b5b752746871e364ba99Chris Lattner  for (TestScope = FromScope; TestScope != ~0U;
3105af280ce21af061f96b5b5b752746871e364ba99Chris Lattner       TestScope = Scopes[TestScope].ParentScope)
3115af280ce21af061f96b5b5b752746871e364ba99Chris Lattner    FromScopes.push_back(TestScope);
3125af280ce21af061f96b5b5b752746871e364ba99Chris Lattner  for (TestScope = ToScope; TestScope != ~0U;
3135af280ce21af061f96b5b5b752746871e364ba99Chris Lattner       TestScope = Scopes[TestScope].ParentScope)
3145af280ce21af061f96b5b5b752746871e364ba99Chris Lattner    ToScopes.push_back(TestScope);
3155af280ce21af061f96b5b5b752746871e364ba99Chris Lattner
3165af280ce21af061f96b5b5b752746871e364ba99Chris Lattner  // Remove any common entries (such as the top-level function scope).
3175af280ce21af061f96b5b5b752746871e364ba99Chris Lattner  while (!FromScopes.empty() && FromScopes.back() == ToScopes.back()) {
3185af280ce21af061f96b5b5b752746871e364ba99Chris Lattner    FromScopes.pop_back();
3195af280ce21af061f96b5b5b752746871e364ba99Chris Lattner    ToScopes.pop_back();
3205af280ce21af061f96b5b5b752746871e364ba99Chris Lattner  }
3211eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
3225af280ce21af061f96b5b5b752746871e364ba99Chris Lattner  // Emit diagnostics for whatever is left in ToScopes.
3235af280ce21af061f96b5b5b752746871e364ba99Chris Lattner  for (unsigned i = 0, e = ToScopes.size(); i != e; ++i)
3245af280ce21af061f96b5b5b752746871e364ba99Chris Lattner    S.Diag(Scopes[ToScopes[i]].Loc, Scopes[ToScopes[i]].Diag);
3255af280ce21af061f96b5b5b752746871e364ba99Chris Lattner}
3265af280ce21af061f96b5b5b752746871e364ba99Chris Lattner
3275af280ce21af061f96b5b5b752746871e364ba99Chris Lattnervoid Sema::DiagnoseInvalidJumps(Stmt *Body) {
3286490ae5003226cae28f980648948bea8b21a8638Douglas Gregor  (void)JumpScopeChecker(Body, *this);
3295af280ce21af061f96b5b5b752746871e364ba99Chris Lattner}
330