JumpDiagnostics.cpp revision be6d259a375bbec49659d54a302c4758058f2eef
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; 315af280ce21af061f96b5b5b752746871e364ba99Chris Lattner 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; 415af280ce21af061f96b5b5b752746871e364ba99Chris Lattner 425af280ce21af061f96b5b5b752746871e364ba99Chris Lattner /// Diag - The diagnostic to emit if there is a jump into this scope. 435af280ce21af061f96b5b5b752746871e364ba99Chris Lattner unsigned Diag; 445af280ce21af061f96b5b5b752746871e364ba99Chris Lattner 455af280ce21af061f96b5b5b752746871e364ba99Chris Lattner /// Loc - Location to emit the diagnostic. 465af280ce21af061f96b5b5b752746871e364ba99Chris Lattner SourceLocation Loc; 475af280ce21af061f96b5b5b752746871e364ba99Chris Lattner 485af280ce21af061f96b5b5b752746871e364ba99Chris Lattner GotoScope(unsigned parentScope, unsigned diag, SourceLocation L) 495af280ce21af061f96b5b5b752746871e364ba99Chris Lattner : ParentScope(parentScope), Diag(diag), Loc(L) {} 505af280ce21af061f96b5b5b752746871e364ba99Chris Lattner }; 515af280ce21af061f96b5b5b752746871e364ba99Chris Lattner 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())); 695af280ce21af061f96b5b5b752746871e364ba99Chris Lattner 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); 735af280ce21af061f96b5b5b752746871e364ba99Chris Lattner 745af280ce21af061f96b5b5b752746871e364ba99Chris Lattner // Check that all jumps we saw are kosher. 755af280ce21af061f96b5b5b752746871e364ba99Chris Lattner VerifyJumps(); 765af280ce21af061f96b5b5b752746871e364ba99Chris Lattner} 775af280ce21af061f96b5b5b752746871e364ba99Chris Lattner 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 } 925af280ce21af061f96b5b5b752746871e364ba99Chris Lattner 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) { 1025af280ce21af061f96b5b5b752746871e364ba99Chris Lattner 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 } 1135af280ce21af061f96b5b5b752746871e364ba99Chris Lattner 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; 1185af280ce21af061f96b5b5b752746871e364ba99Chris Lattner 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 } 1345af280ce21af061f96b5b5b752746871e364ba99Chris Lattner 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())); 1595af280ce21af061f96b5b5b752746871e364ba99Chris Lattner // @catches are nested and it isn't 1605af280ce21af061f96b5b5b752746871e364ba99Chris Lattner BuildScopeInformation(AC->getCatchBody(), Scopes.size()-1); 1615af280ce21af061f96b5b5b752746871e364ba99Chris Lattner } 1625af280ce21af061f96b5b5b752746871e364ba99Chris Lattner 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 } 1705af280ce21af061f96b5b5b752746871e364ba99Chris Lattner 1715af280ce21af061f96b5b5b752746871e364ba99Chris Lattner continue; 1725af280ce21af061f96b5b5b752746871e364ba99Chris Lattner } 1735af280ce21af061f96b5b5b752746871e364ba99Chris Lattner 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); 18046c3c4ba78766ac0f1c5ec631b424773e21f5271Chris Lattner 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. 199972041f45bdf8df7ea447221292d7827466ba94bSebastian Redl 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(); 2205af280ce21af061f96b5b5b752746871e364ba99Chris Lattner 2215af280ce21af061f96b5b5b752746871e364ba99Chris Lattner // 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 } 2275af280ce21af061f96b5b5b752746871e364ba99Chris Lattner 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; 2395af280ce21af061f96b5b5b752746871e364ba99Chris Lattner 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(); 2575af280ce21af061f96b5b5b752746871e364ba99Chris Lattner 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. 2625af280ce21af061f96b5b5b752746871e364ba99Chris Lattner 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]; 2855af280ce21af061f96b5b5b752746871e364ba99Chris Lattner 2865af280ce21af061f96b5b5b752746871e364ba99Chris Lattner // Common case: exactly the same scope, which is fine. 2875af280ce21af061f96b5b5b752746871e364ba99Chris Lattner if (FromScope == ToScope) return; 2885af280ce21af061f96b5b5b752746871e364ba99Chris Lattner 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; 2975af280ce21af061f96b5b5b752746871e364ba99Chris Lattner 2985af280ce21af061f96b5b5b752746871e364ba99Chris Lattner // Otherwise, scan up the hierarchy. 2995af280ce21af061f96b5b5b752746871e364ba99Chris Lattner TestScope = Scopes[TestScope].ParentScope; 3005af280ce21af061f96b5b5b752746871e364ba99Chris Lattner } 3015af280ce21af061f96b5b5b752746871e364ba99Chris Lattner 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 } 3215af280ce21af061f96b5b5b752746871e364ba99Chris Lattner 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) { 3285af280ce21af061f96b5b5b752746871e364ba99Chris Lattner JumpScopeChecker(Body, *this); 3295af280ce21af061f96b5b5b752746871e364ba99Chris Lattner} 330