JumpDiagnostics.cpp revision 16f0049415ec596504891259e2a83e19871c0d52
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" 185af280ce21af061f96b5b5b752746871e364ba99Chris Lattnerusing namespace clang; 195af280ce21af061f96b5b5b752746871e364ba99Chris Lattner 205af280ce21af061f96b5b5b752746871e364ba99Chris Lattnernamespace { 215af280ce21af061f96b5b5b752746871e364ba99Chris Lattner 225af280ce21af061f96b5b5b752746871e364ba99Chris Lattner/// JumpScopeChecker - This object is used by Sema to diagnose invalid jumps 235af280ce21af061f96b5b5b752746871e364ba99Chris Lattner/// into VLA and other protected scopes. For example, this rejects: 245af280ce21af061f96b5b5b752746871e364ba99Chris Lattner/// goto L; 255af280ce21af061f96b5b5b752746871e364ba99Chris Lattner/// int a[n]; 265af280ce21af061f96b5b5b752746871e364ba99Chris Lattner/// L: 275af280ce21af061f96b5b5b752746871e364ba99Chris Lattner/// 285af280ce21af061f96b5b5b752746871e364ba99Chris Lattnerclass JumpScopeChecker { 295af280ce21af061f96b5b5b752746871e364ba99Chris Lattner Sema &S; 305af280ce21af061f96b5b5b752746871e364ba99Chris Lattner 315af280ce21af061f96b5b5b752746871e364ba99Chris Lattner /// GotoScope - This is a record that we use to keep track of all of the 325af280ce21af061f96b5b5b752746871e364ba99Chris Lattner /// scopes that are introduced by VLAs and other things that scope jumps like 335af280ce21af061f96b5b5b752746871e364ba99Chris Lattner /// gotos. This scope tree has nothing to do with the source scope tree, 345af280ce21af061f96b5b5b752746871e364ba99Chris Lattner /// because you can have multiple VLA scopes per compound statement, and most 355af280ce21af061f96b5b5b752746871e364ba99Chris Lattner /// compound statements don't introduce any scopes. 365af280ce21af061f96b5b5b752746871e364ba99Chris Lattner struct GotoScope { 375af280ce21af061f96b5b5b752746871e364ba99Chris Lattner /// ParentScope - The index in ScopeMap of the parent scope. This is 0 for 385af280ce21af061f96b5b5b752746871e364ba99Chris Lattner /// the parent scope is the function body. 395af280ce21af061f96b5b5b752746871e364ba99Chris Lattner unsigned ParentScope; 405af280ce21af061f96b5b5b752746871e364ba99Chris Lattner 415af280ce21af061f96b5b5b752746871e364ba99Chris Lattner /// Diag - The diagnostic to emit if there is a jump into this scope. 425af280ce21af061f96b5b5b752746871e364ba99Chris Lattner unsigned Diag; 435af280ce21af061f96b5b5b752746871e364ba99Chris Lattner 445af280ce21af061f96b5b5b752746871e364ba99Chris Lattner /// Loc - Location to emit the diagnostic. 455af280ce21af061f96b5b5b752746871e364ba99Chris Lattner SourceLocation Loc; 465af280ce21af061f96b5b5b752746871e364ba99Chris Lattner 475af280ce21af061f96b5b5b752746871e364ba99Chris Lattner GotoScope(unsigned parentScope, unsigned diag, SourceLocation L) 485af280ce21af061f96b5b5b752746871e364ba99Chris Lattner : ParentScope(parentScope), Diag(diag), Loc(L) {} 495af280ce21af061f96b5b5b752746871e364ba99Chris Lattner }; 505af280ce21af061f96b5b5b752746871e364ba99Chris Lattner 515af280ce21af061f96b5b5b752746871e364ba99Chris Lattner llvm::SmallVector<GotoScope, 48> Scopes; 525af280ce21af061f96b5b5b752746871e364ba99Chris Lattner llvm::DenseMap<Stmt*, unsigned> LabelAndGotoScopes; 535af280ce21af061f96b5b5b752746871e364ba99Chris Lattner llvm::SmallVector<Stmt*, 16> Jumps; 545af280ce21af061f96b5b5b752746871e364ba99Chris Lattnerpublic: 555af280ce21af061f96b5b5b752746871e364ba99Chris Lattner JumpScopeChecker(Stmt *Body, Sema &S); 565af280ce21af061f96b5b5b752746871e364ba99Chris Lattnerprivate: 575af280ce21af061f96b5b5b752746871e364ba99Chris Lattner void BuildScopeInformation(Stmt *S, unsigned ParentScope); 585af280ce21af061f96b5b5b752746871e364ba99Chris Lattner void VerifyJumps(); 595af280ce21af061f96b5b5b752746871e364ba99Chris Lattner void CheckJump(Stmt *From, Stmt *To, 605af280ce21af061f96b5b5b752746871e364ba99Chris Lattner SourceLocation DiagLoc, unsigned JumpDiag); 615af280ce21af061f96b5b5b752746871e364ba99Chris Lattner}; 625af280ce21af061f96b5b5b752746871e364ba99Chris Lattner} // end anonymous namespace 635af280ce21af061f96b5b5b752746871e364ba99Chris Lattner 645af280ce21af061f96b5b5b752746871e364ba99Chris Lattner 655af280ce21af061f96b5b5b752746871e364ba99Chris LattnerJumpScopeChecker::JumpScopeChecker(Stmt *Body, Sema &s) : S(s) { 665af280ce21af061f96b5b5b752746871e364ba99Chris Lattner // Add a scope entry for function scope. 675af280ce21af061f96b5b5b752746871e364ba99Chris Lattner Scopes.push_back(GotoScope(~0U, ~0U, SourceLocation())); 685af280ce21af061f96b5b5b752746871e364ba99Chris Lattner 695af280ce21af061f96b5b5b752746871e364ba99Chris Lattner // Build information for the top level compound statement, so that we have a 705af280ce21af061f96b5b5b752746871e364ba99Chris Lattner // defined scope record for every "goto" and label. 715af280ce21af061f96b5b5b752746871e364ba99Chris Lattner BuildScopeInformation(Body, 0); 725af280ce21af061f96b5b5b752746871e364ba99Chris Lattner 735af280ce21af061f96b5b5b752746871e364ba99Chris Lattner // Check that all jumps we saw are kosher. 745af280ce21af061f96b5b5b752746871e364ba99Chris Lattner VerifyJumps(); 755af280ce21af061f96b5b5b752746871e364ba99Chris Lattner} 765af280ce21af061f96b5b5b752746871e364ba99Chris Lattner 775af280ce21af061f96b5b5b752746871e364ba99Chris Lattner/// GetDiagForGotoScopeDecl - If this decl induces a new goto scope, return a 785af280ce21af061f96b5b5b752746871e364ba99Chris Lattner/// diagnostic that should be emitted if control goes over it. If not, return 0. 795af280ce21af061f96b5b5b752746871e364ba99Chris Lattnerstatic unsigned GetDiagForGotoScopeDecl(const Decl *D) { 805af280ce21af061f96b5b5b752746871e364ba99Chris Lattner if (const VarDecl *VD = dyn_cast<VarDecl>(D)) { 815af280ce21af061f96b5b5b752746871e364ba99Chris Lattner if (VD->getType()->isVariablyModifiedType()) 825af280ce21af061f96b5b5b752746871e364ba99Chris Lattner return diag::note_protected_by_vla; 835af280ce21af061f96b5b5b752746871e364ba99Chris Lattner if (VD->hasAttr<CleanupAttr>()) 845af280ce21af061f96b5b5b752746871e364ba99Chris Lattner return diag::note_protected_by_cleanup; 855af280ce21af061f96b5b5b752746871e364ba99Chris Lattner } else if (const TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) { 865af280ce21af061f96b5b5b752746871e364ba99Chris Lattner if (TD->getUnderlyingType()->isVariablyModifiedType()) 875af280ce21af061f96b5b5b752746871e364ba99Chris Lattner return diag::note_protected_by_vla_typedef; 885af280ce21af061f96b5b5b752746871e364ba99Chris Lattner } 895af280ce21af061f96b5b5b752746871e364ba99Chris Lattner 905af280ce21af061f96b5b5b752746871e364ba99Chris Lattner return 0; 915af280ce21af061f96b5b5b752746871e364ba99Chris Lattner} 925af280ce21af061f96b5b5b752746871e364ba99Chris Lattner 935af280ce21af061f96b5b5b752746871e364ba99Chris Lattner 945af280ce21af061f96b5b5b752746871e364ba99Chris Lattner/// BuildScopeInformation - The statements from CI to CE are known to form a 955af280ce21af061f96b5b5b752746871e364ba99Chris Lattner/// coherent VLA scope with a specified parent node. Walk through the 965af280ce21af061f96b5b5b752746871e364ba99Chris Lattner/// statements, adding any labels or gotos to LabelAndGotoScopes and recursively 975af280ce21af061f96b5b5b752746871e364ba99Chris Lattner/// walking the AST as needed. 985af280ce21af061f96b5b5b752746871e364ba99Chris Lattnervoid JumpScopeChecker::BuildScopeInformation(Stmt *S, unsigned ParentScope) { 995af280ce21af061f96b5b5b752746871e364ba99Chris Lattner 1005af280ce21af061f96b5b5b752746871e364ba99Chris Lattner // If we found a label, remember that it is in ParentScope scope. 1015af280ce21af061f96b5b5b752746871e364ba99Chris Lattner if (isa<LabelStmt>(S) || isa<DefaultStmt>(S) || isa<CaseStmt>(S)) { 1025af280ce21af061f96b5b5b752746871e364ba99Chris Lattner LabelAndGotoScopes[S] = ParentScope; 1035af280ce21af061f96b5b5b752746871e364ba99Chris Lattner } else if (isa<GotoStmt>(S) || isa<SwitchStmt>(S) || 1045af280ce21af061f96b5b5b752746871e364ba99Chris Lattner isa<IndirectGotoStmt>(S) || isa<AddrLabelExpr>(S)) { 1055af280ce21af061f96b5b5b752746871e364ba99Chris Lattner // Remember both what scope a goto is in as well as the fact that we have 1065af280ce21af061f96b5b5b752746871e364ba99Chris Lattner // it. This makes the second scan not have to walk the AST again. 1075af280ce21af061f96b5b5b752746871e364ba99Chris Lattner LabelAndGotoScopes[S] = ParentScope; 1085af280ce21af061f96b5b5b752746871e364ba99Chris Lattner Jumps.push_back(S); 1095af280ce21af061f96b5b5b752746871e364ba99Chris Lattner } 1105af280ce21af061f96b5b5b752746871e364ba99Chris Lattner 1115af280ce21af061f96b5b5b752746871e364ba99Chris Lattner for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end(); CI != E; 1125af280ce21af061f96b5b5b752746871e364ba99Chris Lattner ++CI) { 1135af280ce21af061f96b5b5b752746871e364ba99Chris Lattner Stmt *SubStmt = *CI; 1145af280ce21af061f96b5b5b752746871e364ba99Chris Lattner if (SubStmt == 0) continue; 1155af280ce21af061f96b5b5b752746871e364ba99Chris Lattner 1165af280ce21af061f96b5b5b752746871e364ba99Chris Lattner // FIXME: diagnose jumps past initialization: required in C++, warning in C. 1175af280ce21af061f96b5b5b752746871e364ba99Chris Lattner // goto L; int X = 4; L: ; 1185af280ce21af061f96b5b5b752746871e364ba99Chris Lattner // FIXME: what about jumps into C++ catch blocks, what are the rules? 1195af280ce21af061f96b5b5b752746871e364ba99Chris Lattner 1205af280ce21af061f96b5b5b752746871e364ba99Chris Lattner // If this is a declstmt with a VLA definition, it defines a scope from here 1215af280ce21af061f96b5b5b752746871e364ba99Chris Lattner // to the end of the containing context. 1225af280ce21af061f96b5b5b752746871e364ba99Chris Lattner if (DeclStmt *DS = dyn_cast<DeclStmt>(SubStmt)) { 1235af280ce21af061f96b5b5b752746871e364ba99Chris Lattner // The decl statement creates a scope if any of the decls in it are VLAs or 1245af280ce21af061f96b5b5b752746871e364ba99Chris Lattner // have the cleanup attribute. 1255af280ce21af061f96b5b5b752746871e364ba99Chris Lattner for (DeclStmt::decl_iterator I = DS->decl_begin(), E = DS->decl_end(); 1265af280ce21af061f96b5b5b752746871e364ba99Chris Lattner I != E; ++I) { 1275af280ce21af061f96b5b5b752746871e364ba99Chris Lattner // If this decl causes a new scope, push and switch to it. 1285af280ce21af061f96b5b5b752746871e364ba99Chris Lattner if (unsigned Diag = GetDiagForGotoScopeDecl(*I)) { 1295af280ce21af061f96b5b5b752746871e364ba99Chris Lattner Scopes.push_back(GotoScope(ParentScope, Diag, (*I)->getLocation())); 1305af280ce21af061f96b5b5b752746871e364ba99Chris Lattner ParentScope = Scopes.size()-1; 1315af280ce21af061f96b5b5b752746871e364ba99Chris Lattner } 1325af280ce21af061f96b5b5b752746871e364ba99Chris Lattner 1335af280ce21af061f96b5b5b752746871e364ba99Chris Lattner // If the decl has an initializer, walk it with the potentially new 1345af280ce21af061f96b5b5b752746871e364ba99Chris Lattner // scope we just installed. 1355af280ce21af061f96b5b5b752746871e364ba99Chris Lattner if (VarDecl *VD = dyn_cast<VarDecl>(*I)) 1365af280ce21af061f96b5b5b752746871e364ba99Chris Lattner if (Expr *Init = VD->getInit()) 1375af280ce21af061f96b5b5b752746871e364ba99Chris Lattner BuildScopeInformation(Init, ParentScope); 1385af280ce21af061f96b5b5b752746871e364ba99Chris Lattner } 1395af280ce21af061f96b5b5b752746871e364ba99Chris Lattner continue; 1405af280ce21af061f96b5b5b752746871e364ba99Chris Lattner } 1415af280ce21af061f96b5b5b752746871e364ba99Chris Lattner 1425af280ce21af061f96b5b5b752746871e364ba99Chris Lattner // Disallow jumps into any part of an @try statement by pushing a scope and 1435af280ce21af061f96b5b5b752746871e364ba99Chris Lattner // walking all sub-stmts in that scope. 1445af280ce21af061f96b5b5b752746871e364ba99Chris Lattner if (ObjCAtTryStmt *AT = dyn_cast<ObjCAtTryStmt>(SubStmt)) { 1455af280ce21af061f96b5b5b752746871e364ba99Chris Lattner // Recursively walk the AST for the @try part. 1465af280ce21af061f96b5b5b752746871e364ba99Chris Lattner Scopes.push_back(GotoScope(ParentScope,diag::note_protected_by_objc_try, 1475af280ce21af061f96b5b5b752746871e364ba99Chris Lattner AT->getAtTryLoc())); 1485af280ce21af061f96b5b5b752746871e364ba99Chris Lattner if (Stmt *TryPart = AT->getTryBody()) 1495af280ce21af061f96b5b5b752746871e364ba99Chris Lattner BuildScopeInformation(TryPart, Scopes.size()-1); 1505af280ce21af061f96b5b5b752746871e364ba99Chris Lattner 1515af280ce21af061f96b5b5b752746871e364ba99Chris Lattner // Jump from the catch to the finally or try is not valid. 1525af280ce21af061f96b5b5b752746871e364ba99Chris Lattner for (ObjCAtCatchStmt *AC = AT->getCatchStmts(); AC; 1535af280ce21af061f96b5b5b752746871e364ba99Chris Lattner AC = AC->getNextCatchStmt()) { 1545af280ce21af061f96b5b5b752746871e364ba99Chris Lattner Scopes.push_back(GotoScope(ParentScope, 1555af280ce21af061f96b5b5b752746871e364ba99Chris Lattner diag::note_protected_by_objc_catch, 1565af280ce21af061f96b5b5b752746871e364ba99Chris Lattner AC->getAtCatchLoc())); 1575af280ce21af061f96b5b5b752746871e364ba99Chris Lattner // @catches are nested and it isn't 1585af280ce21af061f96b5b5b752746871e364ba99Chris Lattner BuildScopeInformation(AC->getCatchBody(), Scopes.size()-1); 1595af280ce21af061f96b5b5b752746871e364ba99Chris Lattner } 1605af280ce21af061f96b5b5b752746871e364ba99Chris Lattner 1615af280ce21af061f96b5b5b752746871e364ba99Chris Lattner // Jump from the finally to the try or catch is not valid. 1625af280ce21af061f96b5b5b752746871e364ba99Chris Lattner if (ObjCAtFinallyStmt *AF = AT->getFinallyStmt()) { 1635af280ce21af061f96b5b5b752746871e364ba99Chris Lattner Scopes.push_back(GotoScope(ParentScope, 1645af280ce21af061f96b5b5b752746871e364ba99Chris Lattner diag::note_protected_by_objc_finally, 1655af280ce21af061f96b5b5b752746871e364ba99Chris Lattner AF->getAtFinallyLoc())); 1665af280ce21af061f96b5b5b752746871e364ba99Chris Lattner BuildScopeInformation(AF, Scopes.size()-1); 1675af280ce21af061f96b5b5b752746871e364ba99Chris Lattner } 1685af280ce21af061f96b5b5b752746871e364ba99Chris Lattner 1695af280ce21af061f96b5b5b752746871e364ba99Chris Lattner continue; 1705af280ce21af061f96b5b5b752746871e364ba99Chris Lattner } 1715af280ce21af061f96b5b5b752746871e364ba99Chris Lattner 17246c3c4ba78766ac0f1c5ec631b424773e21f5271Chris Lattner // Disallow jumps into the protected statement of an @synchronized, but 17346c3c4ba78766ac0f1c5ec631b424773e21f5271Chris Lattner // allow jumps into the object expression it protects. 17446c3c4ba78766ac0f1c5ec631b424773e21f5271Chris Lattner if (ObjCAtSynchronizedStmt *AS = dyn_cast<ObjCAtSynchronizedStmt>(SubStmt)){ 17546c3c4ba78766ac0f1c5ec631b424773e21f5271Chris Lattner // Recursively walk the AST for the @synchronized object expr, it is 17646c3c4ba78766ac0f1c5ec631b424773e21f5271Chris Lattner // evaluated in the normal scope. 17746c3c4ba78766ac0f1c5ec631b424773e21f5271Chris Lattner BuildScopeInformation(AS->getSynchExpr(), ParentScope); 17846c3c4ba78766ac0f1c5ec631b424773e21f5271Chris Lattner 17946c3c4ba78766ac0f1c5ec631b424773e21f5271Chris Lattner // Recursively walk the AST for the @synchronized part, protected by a new 18046c3c4ba78766ac0f1c5ec631b424773e21f5271Chris Lattner // scope. 18146c3c4ba78766ac0f1c5ec631b424773e21f5271Chris Lattner Scopes.push_back(GotoScope(ParentScope, 18246c3c4ba78766ac0f1c5ec631b424773e21f5271Chris Lattner diag::note_protected_by_objc_synchronized, 18346c3c4ba78766ac0f1c5ec631b424773e21f5271Chris Lattner AS->getAtSynchronizedLoc())); 18446c3c4ba78766ac0f1c5ec631b424773e21f5271Chris Lattner BuildScopeInformation(AS->getSynchBody(), Scopes.size()-1); 18546c3c4ba78766ac0f1c5ec631b424773e21f5271Chris Lattner continue; 18646c3c4ba78766ac0f1c5ec631b424773e21f5271Chris Lattner } 18746c3c4ba78766ac0f1c5ec631b424773e21f5271Chris Lattner 1885af280ce21af061f96b5b5b752746871e364ba99Chris Lattner // Recursively walk the AST. 1895af280ce21af061f96b5b5b752746871e364ba99Chris Lattner BuildScopeInformation(SubStmt, ParentScope); 1905af280ce21af061f96b5b5b752746871e364ba99Chris Lattner } 1915af280ce21af061f96b5b5b752746871e364ba99Chris Lattner} 1925af280ce21af061f96b5b5b752746871e364ba99Chris Lattner 1935af280ce21af061f96b5b5b752746871e364ba99Chris Lattner/// VerifyJumps - Verify each element of the Jumps array to see if they are 1945af280ce21af061f96b5b5b752746871e364ba99Chris Lattner/// valid, emitting diagnostics if not. 1955af280ce21af061f96b5b5b752746871e364ba99Chris Lattnervoid JumpScopeChecker::VerifyJumps() { 1965af280ce21af061f96b5b5b752746871e364ba99Chris Lattner while (!Jumps.empty()) { 1975af280ce21af061f96b5b5b752746871e364ba99Chris Lattner Stmt *Jump = Jumps.pop_back_val(); 1985af280ce21af061f96b5b5b752746871e364ba99Chris Lattner 1995af280ce21af061f96b5b5b752746871e364ba99Chris Lattner // With a goto, 2005af280ce21af061f96b5b5b752746871e364ba99Chris Lattner if (GotoStmt *GS = dyn_cast<GotoStmt>(Jump)) { 2015af280ce21af061f96b5b5b752746871e364ba99Chris Lattner CheckJump(GS, GS->getLabel(), GS->getGotoLoc(), 2025af280ce21af061f96b5b5b752746871e364ba99Chris Lattner diag::err_goto_into_protected_scope); 2035af280ce21af061f96b5b5b752746871e364ba99Chris Lattner continue; 2045af280ce21af061f96b5b5b752746871e364ba99Chris Lattner } 2055af280ce21af061f96b5b5b752746871e364ba99Chris Lattner 2065af280ce21af061f96b5b5b752746871e364ba99Chris Lattner if (SwitchStmt *SS = dyn_cast<SwitchStmt>(Jump)) { 2075af280ce21af061f96b5b5b752746871e364ba99Chris Lattner for (SwitchCase *SC = SS->getSwitchCaseList(); SC; 2085af280ce21af061f96b5b5b752746871e364ba99Chris Lattner SC = SC->getNextSwitchCase()) { 2095af280ce21af061f96b5b5b752746871e364ba99Chris Lattner assert(LabelAndGotoScopes.count(SC) && "Case not visited?"); 2105af280ce21af061f96b5b5b752746871e364ba99Chris Lattner CheckJump(SS, SC, SC->getLocStart(), 2115af280ce21af061f96b5b5b752746871e364ba99Chris Lattner diag::err_switch_into_protected_scope); 2125af280ce21af061f96b5b5b752746871e364ba99Chris Lattner } 2135af280ce21af061f96b5b5b752746871e364ba99Chris Lattner continue; 2145af280ce21af061f96b5b5b752746871e364ba99Chris Lattner } 2155af280ce21af061f96b5b5b752746871e364ba99Chris Lattner 2165af280ce21af061f96b5b5b752746871e364ba99Chris Lattner unsigned DiagnosticScope; 2175af280ce21af061f96b5b5b752746871e364ba99Chris Lattner 2185af280ce21af061f96b5b5b752746871e364ba99Chris Lattner // We don't know where an indirect goto goes, require that it be at the 2195af280ce21af061f96b5b5b752746871e364ba99Chris Lattner // top level of scoping. 2205af280ce21af061f96b5b5b752746871e364ba99Chris Lattner if (IndirectGotoStmt *IG = dyn_cast<IndirectGotoStmt>(Jump)) { 2215af280ce21af061f96b5b5b752746871e364ba99Chris Lattner assert(LabelAndGotoScopes.count(Jump) && 2225af280ce21af061f96b5b5b752746871e364ba99Chris Lattner "Jump didn't get added to scopes?"); 2235af280ce21af061f96b5b5b752746871e364ba99Chris Lattner unsigned GotoScope = LabelAndGotoScopes[IG]; 2245af280ce21af061f96b5b5b752746871e364ba99Chris Lattner if (GotoScope == 0) continue; // indirect jump is ok. 2255af280ce21af061f96b5b5b752746871e364ba99Chris Lattner S.Diag(IG->getGotoLoc(), diag::err_indirect_goto_in_protected_scope); 2265af280ce21af061f96b5b5b752746871e364ba99Chris Lattner DiagnosticScope = GotoScope; 2275af280ce21af061f96b5b5b752746871e364ba99Chris Lattner } else { 2285af280ce21af061f96b5b5b752746871e364ba99Chris Lattner // We model &&Label as a jump for purposes of scope tracking. We actually 2295af280ce21af061f96b5b5b752746871e364ba99Chris Lattner // don't care *where* the address of label is, but we require the *label 2305af280ce21af061f96b5b5b752746871e364ba99Chris Lattner // itself* to be in scope 0. If it is nested inside of a VLA scope, then 2315af280ce21af061f96b5b5b752746871e364ba99Chris Lattner // it is possible for an indirect goto to illegally enter the VLA scope by 2325af280ce21af061f96b5b5b752746871e364ba99Chris Lattner // indirectly jumping to the label. 2335af280ce21af061f96b5b5b752746871e364ba99Chris Lattner assert(isa<AddrLabelExpr>(Jump) && "Unknown jump type"); 2345af280ce21af061f96b5b5b752746871e364ba99Chris Lattner LabelStmt *TheLabel = cast<AddrLabelExpr>(Jump)->getLabel(); 2355af280ce21af061f96b5b5b752746871e364ba99Chris Lattner 2365af280ce21af061f96b5b5b752746871e364ba99Chris Lattner assert(LabelAndGotoScopes.count(TheLabel) && 2375af280ce21af061f96b5b5b752746871e364ba99Chris Lattner "Referenced label didn't get added to scopes?"); 2385af280ce21af061f96b5b5b752746871e364ba99Chris Lattner unsigned LabelScope = LabelAndGotoScopes[TheLabel]; 2395af280ce21af061f96b5b5b752746871e364ba99Chris Lattner if (LabelScope == 0) continue; // Addr of label is ok. 2405af280ce21af061f96b5b5b752746871e364ba99Chris Lattner 2415af280ce21af061f96b5b5b752746871e364ba99Chris Lattner S.Diag(Jump->getLocStart(), diag::err_addr_of_label_in_protected_scope); 2425af280ce21af061f96b5b5b752746871e364ba99Chris Lattner DiagnosticScope = LabelScope; 2435af280ce21af061f96b5b5b752746871e364ba99Chris Lattner } 2445af280ce21af061f96b5b5b752746871e364ba99Chris Lattner 2455af280ce21af061f96b5b5b752746871e364ba99Chris Lattner // Report all the things that would be skipped over by this &&label or 2465af280ce21af061f96b5b5b752746871e364ba99Chris Lattner // indirect goto. 2475af280ce21af061f96b5b5b752746871e364ba99Chris Lattner while (DiagnosticScope != 0) { 2485af280ce21af061f96b5b5b752746871e364ba99Chris Lattner S.Diag(Scopes[DiagnosticScope].Loc, Scopes[DiagnosticScope].Diag); 2495af280ce21af061f96b5b5b752746871e364ba99Chris Lattner DiagnosticScope = Scopes[DiagnosticScope].ParentScope; 2505af280ce21af061f96b5b5b752746871e364ba99Chris Lattner } 2515af280ce21af061f96b5b5b752746871e364ba99Chris Lattner } 2525af280ce21af061f96b5b5b752746871e364ba99Chris Lattner} 2535af280ce21af061f96b5b5b752746871e364ba99Chris Lattner 2545af280ce21af061f96b5b5b752746871e364ba99Chris Lattner/// CheckJump - Validate that the specified jump statement is valid: that it is 2555af280ce21af061f96b5b5b752746871e364ba99Chris Lattner/// jumping within or out of its current scope, not into a deeper one. 2565af280ce21af061f96b5b5b752746871e364ba99Chris Lattnervoid JumpScopeChecker::CheckJump(Stmt *From, Stmt *To, 2575af280ce21af061f96b5b5b752746871e364ba99Chris Lattner SourceLocation DiagLoc, unsigned JumpDiag) { 2585af280ce21af061f96b5b5b752746871e364ba99Chris Lattner assert(LabelAndGotoScopes.count(From) && "Jump didn't get added to scopes?"); 2595af280ce21af061f96b5b5b752746871e364ba99Chris Lattner unsigned FromScope = LabelAndGotoScopes[From]; 2605af280ce21af061f96b5b5b752746871e364ba99Chris Lattner 2615af280ce21af061f96b5b5b752746871e364ba99Chris Lattner assert(LabelAndGotoScopes.count(To) && "Jump didn't get added to scopes?"); 2625af280ce21af061f96b5b5b752746871e364ba99Chris Lattner unsigned ToScope = LabelAndGotoScopes[To]; 2635af280ce21af061f96b5b5b752746871e364ba99Chris Lattner 2645af280ce21af061f96b5b5b752746871e364ba99Chris Lattner // Common case: exactly the same scope, which is fine. 2655af280ce21af061f96b5b5b752746871e364ba99Chris Lattner if (FromScope == ToScope) return; 2665af280ce21af061f96b5b5b752746871e364ba99Chris Lattner 2675af280ce21af061f96b5b5b752746871e364ba99Chris Lattner // The only valid mismatch jump case happens when the jump is more deeply 2685af280ce21af061f96b5b5b752746871e364ba99Chris Lattner // nested inside the jump target. Do a quick scan to see if the jump is valid 2695af280ce21af061f96b5b5b752746871e364ba99Chris Lattner // because valid code is more common than invalid code. 2705af280ce21af061f96b5b5b752746871e364ba99Chris Lattner unsigned TestScope = Scopes[FromScope].ParentScope; 2715af280ce21af061f96b5b5b752746871e364ba99Chris Lattner while (TestScope != ~0U) { 2725af280ce21af061f96b5b5b752746871e364ba99Chris Lattner // If we found the jump target, then we're jumping out of our current scope, 2735af280ce21af061f96b5b5b752746871e364ba99Chris Lattner // which is perfectly fine. 2745af280ce21af061f96b5b5b752746871e364ba99Chris Lattner if (TestScope == ToScope) return; 2755af280ce21af061f96b5b5b752746871e364ba99Chris Lattner 2765af280ce21af061f96b5b5b752746871e364ba99Chris Lattner // Otherwise, scan up the hierarchy. 2775af280ce21af061f96b5b5b752746871e364ba99Chris Lattner TestScope = Scopes[TestScope].ParentScope; 2785af280ce21af061f96b5b5b752746871e364ba99Chris Lattner } 2795af280ce21af061f96b5b5b752746871e364ba99Chris Lattner 2805af280ce21af061f96b5b5b752746871e364ba99Chris Lattner // If we get here, then we know we have invalid code. Diagnose the bad jump, 2815af280ce21af061f96b5b5b752746871e364ba99Chris Lattner // and then emit a note at each VLA being jumped out of. 2825af280ce21af061f96b5b5b752746871e364ba99Chris Lattner S.Diag(DiagLoc, JumpDiag); 2835af280ce21af061f96b5b5b752746871e364ba99Chris Lattner 2845af280ce21af061f96b5b5b752746871e364ba99Chris Lattner // Eliminate the common prefix of the jump and the target. Start by 2855af280ce21af061f96b5b5b752746871e364ba99Chris Lattner // linearizing both scopes, reversing them as we go. 2865af280ce21af061f96b5b5b752746871e364ba99Chris Lattner std::vector<unsigned> FromScopes, ToScopes; 2875af280ce21af061f96b5b5b752746871e364ba99Chris Lattner for (TestScope = FromScope; TestScope != ~0U; 2885af280ce21af061f96b5b5b752746871e364ba99Chris Lattner TestScope = Scopes[TestScope].ParentScope) 2895af280ce21af061f96b5b5b752746871e364ba99Chris Lattner FromScopes.push_back(TestScope); 2905af280ce21af061f96b5b5b752746871e364ba99Chris Lattner for (TestScope = ToScope; TestScope != ~0U; 2915af280ce21af061f96b5b5b752746871e364ba99Chris Lattner TestScope = Scopes[TestScope].ParentScope) 2925af280ce21af061f96b5b5b752746871e364ba99Chris Lattner ToScopes.push_back(TestScope); 2935af280ce21af061f96b5b5b752746871e364ba99Chris Lattner 2945af280ce21af061f96b5b5b752746871e364ba99Chris Lattner // Remove any common entries (such as the top-level function scope). 2955af280ce21af061f96b5b5b752746871e364ba99Chris Lattner while (!FromScopes.empty() && FromScopes.back() == ToScopes.back()) { 2965af280ce21af061f96b5b5b752746871e364ba99Chris Lattner FromScopes.pop_back(); 2975af280ce21af061f96b5b5b752746871e364ba99Chris Lattner ToScopes.pop_back(); 2985af280ce21af061f96b5b5b752746871e364ba99Chris Lattner } 2995af280ce21af061f96b5b5b752746871e364ba99Chris Lattner 3005af280ce21af061f96b5b5b752746871e364ba99Chris Lattner // Emit diagnostics for whatever is left in ToScopes. 3015af280ce21af061f96b5b5b752746871e364ba99Chris Lattner for (unsigned i = 0, e = ToScopes.size(); i != e; ++i) 3025af280ce21af061f96b5b5b752746871e364ba99Chris Lattner S.Diag(Scopes[ToScopes[i]].Loc, Scopes[ToScopes[i]].Diag); 3035af280ce21af061f96b5b5b752746871e364ba99Chris Lattner} 3045af280ce21af061f96b5b5b752746871e364ba99Chris Lattner 3055af280ce21af061f96b5b5b752746871e364ba99Chris Lattnervoid Sema::DiagnoseInvalidJumps(Stmt *Body) { 3065af280ce21af061f96b5b5b752746871e364ba99Chris Lattner JumpScopeChecker(Body, *this); 3075af280ce21af061f96b5b5b752746871e364ba99Chris Lattner} 308