clang API Documentation
00001 //===--- JumpDiagnostics.cpp - Protected scope jump analysis ------*- C++ -*-=// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file implements the JumpScopeChecker class, which is used to diagnose 00011 // jumps that enter a protected scope in an invalid way. 00012 // 00013 //===----------------------------------------------------------------------===// 00014 00015 #include "clang/Sema/SemaInternal.h" 00016 #include "clang/AST/DeclCXX.h" 00017 #include "clang/AST/Expr.h" 00018 #include "clang/AST/ExprCXX.h" 00019 #include "clang/AST/StmtObjC.h" 00020 #include "clang/AST/StmtCXX.h" 00021 #include "llvm/ADT/BitVector.h" 00022 using namespace clang; 00023 00024 namespace { 00025 00026 /// JumpScopeChecker - This object is used by Sema to diagnose invalid jumps 00027 /// into VLA and other protected scopes. For example, this rejects: 00028 /// goto L; 00029 /// int a[n]; 00030 /// L: 00031 /// 00032 class JumpScopeChecker { 00033 Sema &S; 00034 00035 /// GotoScope - This is a record that we use to keep track of all of the 00036 /// scopes that are introduced by VLAs and other things that scope jumps like 00037 /// gotos. This scope tree has nothing to do with the source scope tree, 00038 /// because you can have multiple VLA scopes per compound statement, and most 00039 /// compound statements don't introduce any scopes. 00040 struct GotoScope { 00041 /// ParentScope - The index in ScopeMap of the parent scope. This is 0 for 00042 /// the parent scope is the function body. 00043 unsigned ParentScope; 00044 00045 /// InDiag - The note to emit if there is a jump into this scope. 00046 unsigned InDiag; 00047 00048 /// OutDiag - The note to emit if there is an indirect jump out 00049 /// of this scope. Direct jumps always clean up their current scope 00050 /// in an orderly way. 00051 unsigned OutDiag; 00052 00053 /// Loc - Location to emit the diagnostic. 00054 SourceLocation Loc; 00055 00056 GotoScope(unsigned parentScope, unsigned InDiag, unsigned OutDiag, 00057 SourceLocation L) 00058 : ParentScope(parentScope), InDiag(InDiag), OutDiag(OutDiag), Loc(L) {} 00059 }; 00060 00061 SmallVector<GotoScope, 48> Scopes; 00062 llvm::DenseMap<Stmt*, unsigned> LabelAndGotoScopes; 00063 SmallVector<Stmt*, 16> Jumps; 00064 00065 SmallVector<IndirectGotoStmt*, 4> IndirectJumps; 00066 SmallVector<LabelDecl*, 4> IndirectJumpTargets; 00067 public: 00068 JumpScopeChecker(Stmt *Body, Sema &S); 00069 private: 00070 void BuildScopeInformation(Decl *D, unsigned &ParentScope); 00071 void BuildScopeInformation(VarDecl *D, const BlockDecl *BDecl, 00072 unsigned &ParentScope); 00073 void BuildScopeInformation(Stmt *S, unsigned &origParentScope); 00074 00075 void VerifyJumps(); 00076 void VerifyIndirectJumps(); 00077 void NoteJumpIntoScopes(ArrayRef<unsigned> ToScopes); 00078 void DiagnoseIndirectJump(IndirectGotoStmt *IG, unsigned IGScope, 00079 LabelDecl *Target, unsigned TargetScope); 00080 void CheckJump(Stmt *From, Stmt *To, SourceLocation DiagLoc, 00081 unsigned JumpDiag, unsigned JumpDiagWarning, 00082 unsigned JumpDiagCXX98Compat); 00083 00084 unsigned GetDeepestCommonScope(unsigned A, unsigned B); 00085 }; 00086 } // end anonymous namespace 00087 00088 00089 JumpScopeChecker::JumpScopeChecker(Stmt *Body, Sema &s) : S(s) { 00090 // Add a scope entry for function scope. 00091 Scopes.push_back(GotoScope(~0U, ~0U, ~0U, SourceLocation())); 00092 00093 // Build information for the top level compound statement, so that we have a 00094 // defined scope record for every "goto" and label. 00095 unsigned BodyParentScope = 0; 00096 BuildScopeInformation(Body, BodyParentScope); 00097 00098 // Check that all jumps we saw are kosher. 00099 VerifyJumps(); 00100 VerifyIndirectJumps(); 00101 } 00102 00103 /// GetDeepestCommonScope - Finds the innermost scope enclosing the 00104 /// two scopes. 00105 unsigned JumpScopeChecker::GetDeepestCommonScope(unsigned A, unsigned B) { 00106 while (A != B) { 00107 // Inner scopes are created after outer scopes and therefore have 00108 // higher indices. 00109 if (A < B) { 00110 assert(Scopes[B].ParentScope < B); 00111 B = Scopes[B].ParentScope; 00112 } else { 00113 assert(Scopes[A].ParentScope < A); 00114 A = Scopes[A].ParentScope; 00115 } 00116 } 00117 return A; 00118 } 00119 00120 typedef std::pair<unsigned,unsigned> ScopePair; 00121 00122 /// GetDiagForGotoScopeDecl - If this decl induces a new goto scope, return a 00123 /// diagnostic that should be emitted if control goes over it. If not, return 0. 00124 static ScopePair GetDiagForGotoScopeDecl(ASTContext &Context, const Decl *D) { 00125 if (const VarDecl *VD = dyn_cast<VarDecl>(D)) { 00126 unsigned InDiag = 0, OutDiag = 0; 00127 if (VD->getType()->isVariablyModifiedType()) 00128 InDiag = diag::note_protected_by_vla; 00129 00130 if (VD->hasAttr<BlocksAttr>()) 00131 return ScopePair(diag::note_protected_by___block, 00132 diag::note_exits___block); 00133 00134 if (VD->hasAttr<CleanupAttr>()) 00135 return ScopePair(diag::note_protected_by_cleanup, 00136 diag::note_exits_cleanup); 00137 00138 if (Context.getLangOpts().ObjCAutoRefCount && VD->hasLocalStorage()) { 00139 switch (VD->getType().getObjCLifetime()) { 00140 case Qualifiers::OCL_None: 00141 case Qualifiers::OCL_ExplicitNone: 00142 case Qualifiers::OCL_Autoreleasing: 00143 break; 00144 00145 case Qualifiers::OCL_Strong: 00146 case Qualifiers::OCL_Weak: 00147 return ScopePair(diag::note_protected_by_objc_ownership, 00148 diag::note_exits_objc_ownership); 00149 } 00150 } 00151 00152 if (Context.getLangOpts().CPlusPlus && VD->hasLocalStorage()) { 00153 // C++11 [stmt.dcl]p3: 00154 // A program that jumps from a point where a variable with automatic 00155 // storage duration is not in scope to a point where it is in scope 00156 // is ill-formed unless the variable has scalar type, class type with 00157 // a trivial default constructor and a trivial destructor, a 00158 // cv-qualified version of one of these types, or an array of one of 00159 // the preceding types and is declared without an initializer. 00160 00161 // C++03 [stmt.dcl.p3: 00162 // A program that jumps from a point where a local variable 00163 // with automatic storage duration is not in scope to a point 00164 // where it is in scope is ill-formed unless the variable has 00165 // POD type and is declared without an initializer. 00166 00167 if (const Expr *init = VD->getInit()) { 00168 // We actually give variables of record type (or array thereof) 00169 // an initializer even if that initializer only calls a trivial 00170 // ctor. Detect that case. 00171 // FIXME: With generalized initializer lists, this may 00172 // classify "X x{};" as having no initializer. 00173 unsigned inDiagToUse = diag::note_protected_by_variable_init; 00174 00175 const CXXRecordDecl *record = 0; 00176 00177 if (const CXXConstructExpr *cce = dyn_cast<CXXConstructExpr>(init)) { 00178 const CXXConstructorDecl *ctor = cce->getConstructor(); 00179 record = ctor->getParent(); 00180 00181 if (ctor->isTrivial() && ctor->isDefaultConstructor()) { 00182 if (!record->hasTrivialDestructor()) 00183 inDiagToUse = diag::note_protected_by_variable_nontriv_destructor; 00184 else if (!record->isPOD()) 00185 inDiagToUse = diag::note_protected_by_variable_non_pod; 00186 else 00187 inDiagToUse = 0; 00188 } 00189 } else if (VD->getType()->isArrayType()) { 00190 record = VD->getType()->getBaseElementTypeUnsafe() 00191 ->getAsCXXRecordDecl(); 00192 } 00193 00194 if (inDiagToUse) 00195 InDiag = inDiagToUse; 00196 00197 // Also object to indirect jumps which leave scopes with dtors. 00198 if (record && !record->hasTrivialDestructor()) 00199 OutDiag = diag::note_exits_dtor; 00200 } 00201 } 00202 00203 return ScopePair(InDiag, OutDiag); 00204 } 00205 00206 if (const TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) { 00207 if (TD->getUnderlyingType()->isVariablyModifiedType()) 00208 return ScopePair(diag::note_protected_by_vla_typedef, 0); 00209 } 00210 00211 if (const TypeAliasDecl *TD = dyn_cast<TypeAliasDecl>(D)) { 00212 if (TD->getUnderlyingType()->isVariablyModifiedType()) 00213 return ScopePair(diag::note_protected_by_vla_type_alias, 0); 00214 } 00215 00216 return ScopePair(0U, 0U); 00217 } 00218 00219 /// \brief Build scope information for a declaration that is part of a DeclStmt. 00220 void JumpScopeChecker::BuildScopeInformation(Decl *D, unsigned &ParentScope) { 00221 // If this decl causes a new scope, push and switch to it. 00222 std::pair<unsigned,unsigned> Diags = GetDiagForGotoScopeDecl(S.Context, D); 00223 if (Diags.first || Diags.second) { 00224 Scopes.push_back(GotoScope(ParentScope, Diags.first, Diags.second, 00225 D->getLocation())); 00226 ParentScope = Scopes.size()-1; 00227 } 00228 00229 // If the decl has an initializer, walk it with the potentially new 00230 // scope we just installed. 00231 if (VarDecl *VD = dyn_cast<VarDecl>(D)) 00232 if (Expr *Init = VD->getInit()) 00233 BuildScopeInformation(Init, ParentScope); 00234 } 00235 00236 /// \brief Build scope information for a captured block literal variables. 00237 void JumpScopeChecker::BuildScopeInformation(VarDecl *D, 00238 const BlockDecl *BDecl, 00239 unsigned &ParentScope) { 00240 // exclude captured __block variables; there's no destructor 00241 // associated with the block literal for them. 00242 if (D->hasAttr<BlocksAttr>()) 00243 return; 00244 QualType T = D->getType(); 00245 QualType::DestructionKind destructKind = T.isDestructedType(); 00246 if (destructKind != QualType::DK_none) { 00247 std::pair<unsigned,unsigned> Diags; 00248 switch (destructKind) { 00249 case QualType::DK_cxx_destructor: 00250 Diags = ScopePair(diag::note_enters_block_captures_cxx_obj, 00251 diag::note_exits_block_captures_cxx_obj); 00252 break; 00253 case QualType::DK_objc_strong_lifetime: 00254 Diags = ScopePair(diag::note_enters_block_captures_strong, 00255 diag::note_exits_block_captures_strong); 00256 break; 00257 case QualType::DK_objc_weak_lifetime: 00258 Diags = ScopePair(diag::note_enters_block_captures_weak, 00259 diag::note_exits_block_captures_weak); 00260 break; 00261 case QualType::DK_none: 00262 llvm_unreachable("non-lifetime captured variable"); 00263 } 00264 SourceLocation Loc = D->getLocation(); 00265 if (Loc.isInvalid()) 00266 Loc = BDecl->getLocation(); 00267 Scopes.push_back(GotoScope(ParentScope, 00268 Diags.first, Diags.second, Loc)); 00269 ParentScope = Scopes.size()-1; 00270 } 00271 } 00272 00273 /// BuildScopeInformation - The statements from CI to CE are known to form a 00274 /// coherent VLA scope with a specified parent node. Walk through the 00275 /// statements, adding any labels or gotos to LabelAndGotoScopes and recursively 00276 /// walking the AST as needed. 00277 void JumpScopeChecker::BuildScopeInformation(Stmt *S, unsigned &origParentScope) { 00278 // If this is a statement, rather than an expression, scopes within it don't 00279 // propagate out into the enclosing scope. Otherwise we have to worry 00280 // about block literals, which have the lifetime of their enclosing statement. 00281 unsigned independentParentScope = origParentScope; 00282 unsigned &ParentScope = ((isa<Expr>(S) && !isa<StmtExpr>(S)) 00283 ? origParentScope : independentParentScope); 00284 00285 bool SkipFirstSubStmt = false; 00286 00287 // If we found a label, remember that it is in ParentScope scope. 00288 switch (S->getStmtClass()) { 00289 case Stmt::AddrLabelExprClass: 00290 IndirectJumpTargets.push_back(cast<AddrLabelExpr>(S)->getLabel()); 00291 break; 00292 00293 case Stmt::IndirectGotoStmtClass: 00294 // "goto *&&lbl;" is a special case which we treat as equivalent 00295 // to a normal goto. In addition, we don't calculate scope in the 00296 // operand (to avoid recording the address-of-label use), which 00297 // works only because of the restricted set of expressions which 00298 // we detect as constant targets. 00299 if (cast<IndirectGotoStmt>(S)->getConstantTarget()) { 00300 LabelAndGotoScopes[S] = ParentScope; 00301 Jumps.push_back(S); 00302 return; 00303 } 00304 00305 LabelAndGotoScopes[S] = ParentScope; 00306 IndirectJumps.push_back(cast<IndirectGotoStmt>(S)); 00307 break; 00308 00309 case Stmt::SwitchStmtClass: 00310 // Evaluate the condition variable before entering the scope of the switch 00311 // statement. 00312 if (VarDecl *Var = cast<SwitchStmt>(S)->getConditionVariable()) { 00313 BuildScopeInformation(Var, ParentScope); 00314 SkipFirstSubStmt = true; 00315 } 00316 // Fall through 00317 00318 case Stmt::GotoStmtClass: 00319 // Remember both what scope a goto is in as well as the fact that we have 00320 // it. This makes the second scan not have to walk the AST again. 00321 LabelAndGotoScopes[S] = ParentScope; 00322 Jumps.push_back(S); 00323 break; 00324 00325 default: 00326 break; 00327 } 00328 00329 for (Stmt::child_range CI = S->children(); CI; ++CI) { 00330 if (SkipFirstSubStmt) { 00331 SkipFirstSubStmt = false; 00332 continue; 00333 } 00334 00335 Stmt *SubStmt = *CI; 00336 if (SubStmt == 0) continue; 00337 00338 // Cases, labels, and defaults aren't "scope parents". It's also 00339 // important to handle these iteratively instead of recursively in 00340 // order to avoid blowing out the stack. 00341 while (true) { 00342 Stmt *Next; 00343 if (CaseStmt *CS = dyn_cast<CaseStmt>(SubStmt)) 00344 Next = CS->getSubStmt(); 00345 else if (DefaultStmt *DS = dyn_cast<DefaultStmt>(SubStmt)) 00346 Next = DS->getSubStmt(); 00347 else if (LabelStmt *LS = dyn_cast<LabelStmt>(SubStmt)) 00348 Next = LS->getSubStmt(); 00349 else 00350 break; 00351 00352 LabelAndGotoScopes[SubStmt] = ParentScope; 00353 SubStmt = Next; 00354 } 00355 00356 // If this is a declstmt with a VLA definition, it defines a scope from here 00357 // to the end of the containing context. 00358 if (DeclStmt *DS = dyn_cast<DeclStmt>(SubStmt)) { 00359 // The decl statement creates a scope if any of the decls in it are VLAs 00360 // or have the cleanup attribute. 00361 for (DeclStmt::decl_iterator I = DS->decl_begin(), E = DS->decl_end(); 00362 I != E; ++I) 00363 BuildScopeInformation(*I, ParentScope); 00364 continue; 00365 } 00366 // Disallow jumps into any part of an @try statement by pushing a scope and 00367 // walking all sub-stmts in that scope. 00368 if (ObjCAtTryStmt *AT = dyn_cast<ObjCAtTryStmt>(SubStmt)) { 00369 unsigned newParentScope; 00370 // Recursively walk the AST for the @try part. 00371 Scopes.push_back(GotoScope(ParentScope, 00372 diag::note_protected_by_objc_try, 00373 diag::note_exits_objc_try, 00374 AT->getAtTryLoc())); 00375 if (Stmt *TryPart = AT->getTryBody()) 00376 BuildScopeInformation(TryPart, (newParentScope = Scopes.size()-1)); 00377 00378 // Jump from the catch to the finally or try is not valid. 00379 for (unsigned I = 0, N = AT->getNumCatchStmts(); I != N; ++I) { 00380 ObjCAtCatchStmt *AC = AT->getCatchStmt(I); 00381 Scopes.push_back(GotoScope(ParentScope, 00382 diag::note_protected_by_objc_catch, 00383 diag::note_exits_objc_catch, 00384 AC->getAtCatchLoc())); 00385 // @catches are nested and it isn't 00386 BuildScopeInformation(AC->getCatchBody(), 00387 (newParentScope = Scopes.size()-1)); 00388 } 00389 00390 // Jump from the finally to the try or catch is not valid. 00391 if (ObjCAtFinallyStmt *AF = AT->getFinallyStmt()) { 00392 Scopes.push_back(GotoScope(ParentScope, 00393 diag::note_protected_by_objc_finally, 00394 diag::note_exits_objc_finally, 00395 AF->getAtFinallyLoc())); 00396 BuildScopeInformation(AF, (newParentScope = Scopes.size()-1)); 00397 } 00398 00399 continue; 00400 } 00401 00402 unsigned newParentScope; 00403 // Disallow jumps into the protected statement of an @synchronized, but 00404 // allow jumps into the object expression it protects. 00405 if (ObjCAtSynchronizedStmt *AS = dyn_cast<ObjCAtSynchronizedStmt>(SubStmt)){ 00406 // Recursively walk the AST for the @synchronized object expr, it is 00407 // evaluated in the normal scope. 00408 BuildScopeInformation(AS->getSynchExpr(), ParentScope); 00409 00410 // Recursively walk the AST for the @synchronized part, protected by a new 00411 // scope. 00412 Scopes.push_back(GotoScope(ParentScope, 00413 diag::note_protected_by_objc_synchronized, 00414 diag::note_exits_objc_synchronized, 00415 AS->getAtSynchronizedLoc())); 00416 BuildScopeInformation(AS->getSynchBody(), 00417 (newParentScope = Scopes.size()-1)); 00418 continue; 00419 } 00420 00421 // Disallow jumps into any part of a C++ try statement. This is pretty 00422 // much the same as for Obj-C. 00423 if (CXXTryStmt *TS = dyn_cast<CXXTryStmt>(SubStmt)) { 00424 Scopes.push_back(GotoScope(ParentScope, 00425 diag::note_protected_by_cxx_try, 00426 diag::note_exits_cxx_try, 00427 TS->getSourceRange().getBegin())); 00428 if (Stmt *TryBlock = TS->getTryBlock()) 00429 BuildScopeInformation(TryBlock, (newParentScope = Scopes.size()-1)); 00430 00431 // Jump from the catch into the try is not allowed either. 00432 for (unsigned I = 0, E = TS->getNumHandlers(); I != E; ++I) { 00433 CXXCatchStmt *CS = TS->getHandler(I); 00434 Scopes.push_back(GotoScope(ParentScope, 00435 diag::note_protected_by_cxx_catch, 00436 diag::note_exits_cxx_catch, 00437 CS->getSourceRange().getBegin())); 00438 BuildScopeInformation(CS->getHandlerBlock(), 00439 (newParentScope = Scopes.size()-1)); 00440 } 00441 00442 continue; 00443 } 00444 00445 // Disallow jumps into the protected statement of an @autoreleasepool. 00446 if (ObjCAutoreleasePoolStmt *AS = dyn_cast<ObjCAutoreleasePoolStmt>(SubStmt)){ 00447 // Recursively walk the AST for the @autoreleasepool part, protected by a new 00448 // scope. 00449 Scopes.push_back(GotoScope(ParentScope, 00450 diag::note_protected_by_objc_autoreleasepool, 00451 diag::note_exits_objc_autoreleasepool, 00452 AS->getAtLoc())); 00453 BuildScopeInformation(AS->getSubStmt(), (newParentScope = Scopes.size()-1)); 00454 continue; 00455 } 00456 00457 if (const BlockExpr *BE = dyn_cast<BlockExpr>(SubStmt)) { 00458 const BlockDecl *BDecl = BE->getBlockDecl(); 00459 for (BlockDecl::capture_const_iterator ci = BDecl->capture_begin(), 00460 ce = BDecl->capture_end(); ci != ce; ++ci) { 00461 VarDecl *variable = ci->getVariable(); 00462 BuildScopeInformation(variable, BDecl, ParentScope); 00463 } 00464 } 00465 00466 // Recursively walk the AST. 00467 BuildScopeInformation(SubStmt, ParentScope); 00468 } 00469 } 00470 00471 /// VerifyJumps - Verify each element of the Jumps array to see if they are 00472 /// valid, emitting diagnostics if not. 00473 void JumpScopeChecker::VerifyJumps() { 00474 while (!Jumps.empty()) { 00475 Stmt *Jump = Jumps.pop_back_val(); 00476 00477 // With a goto, 00478 if (GotoStmt *GS = dyn_cast<GotoStmt>(Jump)) { 00479 CheckJump(GS, GS->getLabel()->getStmt(), GS->getGotoLoc(), 00480 diag::err_goto_into_protected_scope, 00481 diag::warn_goto_into_protected_scope, 00482 diag::warn_cxx98_compat_goto_into_protected_scope); 00483 continue; 00484 } 00485 00486 // We only get indirect gotos here when they have a constant target. 00487 if (IndirectGotoStmt *IGS = dyn_cast<IndirectGotoStmt>(Jump)) { 00488 LabelDecl *Target = IGS->getConstantTarget(); 00489 CheckJump(IGS, Target->getStmt(), IGS->getGotoLoc(), 00490 diag::err_goto_into_protected_scope, 00491 diag::warn_goto_into_protected_scope, 00492 diag::warn_cxx98_compat_goto_into_protected_scope); 00493 continue; 00494 } 00495 00496 SwitchStmt *SS = cast<SwitchStmt>(Jump); 00497 for (SwitchCase *SC = SS->getSwitchCaseList(); SC; 00498 SC = SC->getNextSwitchCase()) { 00499 assert(LabelAndGotoScopes.count(SC) && "Case not visited?"); 00500 CheckJump(SS, SC, SC->getLocStart(), 00501 diag::err_switch_into_protected_scope, 0, 00502 diag::warn_cxx98_compat_switch_into_protected_scope); 00503 } 00504 } 00505 } 00506 00507 /// VerifyIndirectJumps - Verify whether any possible indirect jump 00508 /// might cross a protection boundary. Unlike direct jumps, indirect 00509 /// jumps count cleanups as protection boundaries: since there's no 00510 /// way to know where the jump is going, we can't implicitly run the 00511 /// right cleanups the way we can with direct jumps. 00512 /// 00513 /// Thus, an indirect jump is "trivial" if it bypasses no 00514 /// initializations and no teardowns. More formally, an indirect jump 00515 /// from A to B is trivial if the path out from A to DCA(A,B) is 00516 /// trivial and the path in from DCA(A,B) to B is trivial, where 00517 /// DCA(A,B) is the deepest common ancestor of A and B. 00518 /// Jump-triviality is transitive but asymmetric. 00519 /// 00520 /// A path in is trivial if none of the entered scopes have an InDiag. 00521 /// A path out is trivial is none of the exited scopes have an OutDiag. 00522 /// 00523 /// Under these definitions, this function checks that the indirect 00524 /// jump between A and B is trivial for every indirect goto statement A 00525 /// and every label B whose address was taken in the function. 00526 void JumpScopeChecker::VerifyIndirectJumps() { 00527 if (IndirectJumps.empty()) return; 00528 00529 // If there aren't any address-of-label expressions in this function, 00530 // complain about the first indirect goto. 00531 if (IndirectJumpTargets.empty()) { 00532 S.Diag(IndirectJumps[0]->getGotoLoc(), 00533 diag::err_indirect_goto_without_addrlabel); 00534 return; 00535 } 00536 00537 // Collect a single representative of every scope containing an 00538 // indirect goto. For most code bases, this substantially cuts 00539 // down on the number of jump sites we'll have to consider later. 00540 typedef std::pair<unsigned, IndirectGotoStmt*> JumpScope; 00541 SmallVector<JumpScope, 32> JumpScopes; 00542 { 00543 llvm::DenseMap<unsigned, IndirectGotoStmt*> JumpScopesMap; 00544 for (SmallVectorImpl<IndirectGotoStmt*>::iterator 00545 I = IndirectJumps.begin(), E = IndirectJumps.end(); I != E; ++I) { 00546 IndirectGotoStmt *IG = *I; 00547 assert(LabelAndGotoScopes.count(IG) && 00548 "indirect jump didn't get added to scopes?"); 00549 unsigned IGScope = LabelAndGotoScopes[IG]; 00550 IndirectGotoStmt *&Entry = JumpScopesMap[IGScope]; 00551 if (!Entry) Entry = IG; 00552 } 00553 JumpScopes.reserve(JumpScopesMap.size()); 00554 for (llvm::DenseMap<unsigned, IndirectGotoStmt*>::iterator 00555 I = JumpScopesMap.begin(), E = JumpScopesMap.end(); I != E; ++I) 00556 JumpScopes.push_back(*I); 00557 } 00558 00559 // Collect a single representative of every scope containing a 00560 // label whose address was taken somewhere in the function. 00561 // For most code bases, there will be only one such scope. 00562 llvm::DenseMap<unsigned, LabelDecl*> TargetScopes; 00563 for (SmallVectorImpl<LabelDecl*>::iterator 00564 I = IndirectJumpTargets.begin(), E = IndirectJumpTargets.end(); 00565 I != E; ++I) { 00566 LabelDecl *TheLabel = *I; 00567 assert(LabelAndGotoScopes.count(TheLabel->getStmt()) && 00568 "Referenced label didn't get added to scopes?"); 00569 unsigned LabelScope = LabelAndGotoScopes[TheLabel->getStmt()]; 00570 LabelDecl *&Target = TargetScopes[LabelScope]; 00571 if (!Target) Target = TheLabel; 00572 } 00573 00574 // For each target scope, make sure it's trivially reachable from 00575 // every scope containing a jump site. 00576 // 00577 // A path between scopes always consists of exitting zero or more 00578 // scopes, then entering zero or more scopes. We build a set of 00579 // of scopes S from which the target scope can be trivially 00580 // entered, then verify that every jump scope can be trivially 00581 // exitted to reach a scope in S. 00582 llvm::BitVector Reachable(Scopes.size(), false); 00583 for (llvm::DenseMap<unsigned,LabelDecl*>::iterator 00584 TI = TargetScopes.begin(), TE = TargetScopes.end(); TI != TE; ++TI) { 00585 unsigned TargetScope = TI->first; 00586 LabelDecl *TargetLabel = TI->second; 00587 00588 Reachable.reset(); 00589 00590 // Mark all the enclosing scopes from which you can safely jump 00591 // into the target scope. 'Min' will end up being the index of 00592 // the shallowest such scope. 00593 unsigned Min = TargetScope; 00594 while (true) { 00595 Reachable.set(Min); 00596 00597 // Don't go beyond the outermost scope. 00598 if (Min == 0) break; 00599 00600 // Stop if we can't trivially enter the current scope. 00601 if (Scopes[Min].InDiag) break; 00602 00603 Min = Scopes[Min].ParentScope; 00604 } 00605 00606 // Walk through all the jump sites, checking that they can trivially 00607 // reach this label scope. 00608 for (SmallVectorImpl<JumpScope>::iterator 00609 I = JumpScopes.begin(), E = JumpScopes.end(); I != E; ++I) { 00610 unsigned Scope = I->first; 00611 00612 // Walk out the "scope chain" for this scope, looking for a scope 00613 // we've marked reachable. For well-formed code this amortizes 00614 // to O(JumpScopes.size() / Scopes.size()): we only iterate 00615 // when we see something unmarked, and in well-formed code we 00616 // mark everything we iterate past. 00617 bool IsReachable = false; 00618 while (true) { 00619 if (Reachable.test(Scope)) { 00620 // If we find something reachable, mark all the scopes we just 00621 // walked through as reachable. 00622 for (unsigned S = I->first; S != Scope; S = Scopes[S].ParentScope) 00623 Reachable.set(S); 00624 IsReachable = true; 00625 break; 00626 } 00627 00628 // Don't walk out if we've reached the top-level scope or we've 00629 // gotten shallower than the shallowest reachable scope. 00630 if (Scope == 0 || Scope < Min) break; 00631 00632 // Don't walk out through an out-diagnostic. 00633 if (Scopes[Scope].OutDiag) break; 00634 00635 Scope = Scopes[Scope].ParentScope; 00636 } 00637 00638 // Only diagnose if we didn't find something. 00639 if (IsReachable) continue; 00640 00641 DiagnoseIndirectJump(I->second, I->first, TargetLabel, TargetScope); 00642 } 00643 } 00644 } 00645 00646 /// Return true if a particular error+note combination must be downgraded to a 00647 /// warning in Microsoft mode. 00648 static bool IsMicrosoftJumpWarning(unsigned JumpDiag, unsigned InDiagNote) { 00649 return (JumpDiag == diag::err_goto_into_protected_scope && 00650 (InDiagNote == diag::note_protected_by_variable_init || 00651 InDiagNote == diag::note_protected_by_variable_nontriv_destructor)); 00652 } 00653 00654 /// Return true if a particular note should be downgraded to a compatibility 00655 /// warning in C++11 mode. 00656 static bool IsCXX98CompatWarning(Sema &S, unsigned InDiagNote) { 00657 return S.getLangOpts().CPlusPlus0x && 00658 InDiagNote == diag::note_protected_by_variable_non_pod; 00659 } 00660 00661 /// Produce primary diagnostic for an indirect jump statement. 00662 static void DiagnoseIndirectJumpStmt(Sema &S, IndirectGotoStmt *Jump, 00663 LabelDecl *Target, bool &Diagnosed) { 00664 if (Diagnosed) 00665 return; 00666 S.Diag(Jump->getGotoLoc(), diag::err_indirect_goto_in_protected_scope); 00667 S.Diag(Target->getStmt()->getIdentLoc(), diag::note_indirect_goto_target); 00668 Diagnosed = true; 00669 } 00670 00671 /// Produce note diagnostics for a jump into a protected scope. 00672 void JumpScopeChecker::NoteJumpIntoScopes(ArrayRef<unsigned> ToScopes) { 00673 assert(!ToScopes.empty()); 00674 for (unsigned I = 0, E = ToScopes.size(); I != E; ++I) 00675 if (Scopes[ToScopes[I]].InDiag) 00676 S.Diag(Scopes[ToScopes[I]].Loc, Scopes[ToScopes[I]].InDiag); 00677 } 00678 00679 /// Diagnose an indirect jump which is known to cross scopes. 00680 void JumpScopeChecker::DiagnoseIndirectJump(IndirectGotoStmt *Jump, 00681 unsigned JumpScope, 00682 LabelDecl *Target, 00683 unsigned TargetScope) { 00684 assert(JumpScope != TargetScope); 00685 00686 unsigned Common = GetDeepestCommonScope(JumpScope, TargetScope); 00687 bool Diagnosed = false; 00688 00689 // Walk out the scope chain until we reach the common ancestor. 00690 for (unsigned I = JumpScope; I != Common; I = Scopes[I].ParentScope) 00691 if (Scopes[I].OutDiag) { 00692 DiagnoseIndirectJumpStmt(S, Jump, Target, Diagnosed); 00693 S.Diag(Scopes[I].Loc, Scopes[I].OutDiag); 00694 } 00695 00696 SmallVector<unsigned, 10> ToScopesCXX98Compat; 00697 00698 // Now walk into the scopes containing the label whose address was taken. 00699 for (unsigned I = TargetScope; I != Common; I = Scopes[I].ParentScope) 00700 if (IsCXX98CompatWarning(S, Scopes[I].InDiag)) 00701 ToScopesCXX98Compat.push_back(I); 00702 else if (Scopes[I].InDiag) { 00703 DiagnoseIndirectJumpStmt(S, Jump, Target, Diagnosed); 00704 S.Diag(Scopes[I].Loc, Scopes[I].InDiag); 00705 } 00706 00707 // Diagnose this jump if it would be ill-formed in C++98. 00708 if (!Diagnosed && !ToScopesCXX98Compat.empty()) { 00709 S.Diag(Jump->getGotoLoc(), 00710 diag::warn_cxx98_compat_indirect_goto_in_protected_scope); 00711 S.Diag(Target->getStmt()->getIdentLoc(), diag::note_indirect_goto_target); 00712 NoteJumpIntoScopes(ToScopesCXX98Compat); 00713 } 00714 } 00715 00716 /// CheckJump - Validate that the specified jump statement is valid: that it is 00717 /// jumping within or out of its current scope, not into a deeper one. 00718 void JumpScopeChecker::CheckJump(Stmt *From, Stmt *To, SourceLocation DiagLoc, 00719 unsigned JumpDiagError, unsigned JumpDiagWarning, 00720 unsigned JumpDiagCXX98Compat) { 00721 assert(LabelAndGotoScopes.count(From) && "Jump didn't get added to scopes?"); 00722 unsigned FromScope = LabelAndGotoScopes[From]; 00723 00724 assert(LabelAndGotoScopes.count(To) && "Jump didn't get added to scopes?"); 00725 unsigned ToScope = LabelAndGotoScopes[To]; 00726 00727 // Common case: exactly the same scope, which is fine. 00728 if (FromScope == ToScope) return; 00729 00730 unsigned CommonScope = GetDeepestCommonScope(FromScope, ToScope); 00731 00732 // It's okay to jump out from a nested scope. 00733 if (CommonScope == ToScope) return; 00734 00735 // Pull out (and reverse) any scopes we might need to diagnose skipping. 00736 SmallVector<unsigned, 10> ToScopesCXX98Compat; 00737 SmallVector<unsigned, 10> ToScopesError; 00738 SmallVector<unsigned, 10> ToScopesWarning; 00739 for (unsigned I = ToScope; I != CommonScope; I = Scopes[I].ParentScope) { 00740 if (S.getLangOpts().MicrosoftMode && JumpDiagWarning != 0 && 00741 IsMicrosoftJumpWarning(JumpDiagError, Scopes[I].InDiag)) 00742 ToScopesWarning.push_back(I); 00743 else if (IsCXX98CompatWarning(S, Scopes[I].InDiag)) 00744 ToScopesCXX98Compat.push_back(I); 00745 else if (Scopes[I].InDiag) 00746 ToScopesError.push_back(I); 00747 } 00748 00749 // Handle warnings. 00750 if (!ToScopesWarning.empty()) { 00751 S.Diag(DiagLoc, JumpDiagWarning); 00752 NoteJumpIntoScopes(ToScopesWarning); 00753 } 00754 00755 // Handle errors. 00756 if (!ToScopesError.empty()) { 00757 S.Diag(DiagLoc, JumpDiagError); 00758 NoteJumpIntoScopes(ToScopesError); 00759 } 00760 00761 // Handle -Wc++98-compat warnings if the jump is well-formed. 00762 if (ToScopesError.empty() && !ToScopesCXX98Compat.empty()) { 00763 S.Diag(DiagLoc, JumpDiagCXX98Compat); 00764 NoteJumpIntoScopes(ToScopesCXX98Compat); 00765 } 00766 } 00767 00768 void Sema::DiagnoseInvalidJumps(Stmt *Body) { 00769 (void)JumpScopeChecker(Body, *this); 00770 }