clang  6.0.0svn
JumpDiagnostics.cpp
Go to the documentation of this file.
1 //===--- JumpDiagnostics.cpp - Protected scope jump analysis ------*- C++ -*-=//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file implements the JumpScopeChecker class, which is used to diagnose
11 // jumps that enter a protected scope in an invalid way.
12 //
13 //===----------------------------------------------------------------------===//
14 
16 #include "clang/AST/DeclCXX.h"
17 #include "clang/AST/Expr.h"
18 #include "clang/AST/ExprCXX.h"
19 #include "clang/AST/StmtCXX.h"
20 #include "clang/AST/StmtObjC.h"
21 #include "llvm/ADT/BitVector.h"
22 using namespace clang;
23 
24 namespace {
25 
26 /// JumpScopeChecker - This object is used by Sema to diagnose invalid jumps
27 /// into VLA and other protected scopes. For example, this rejects:
28 /// goto L;
29 /// int a[n];
30 /// L:
31 ///
32 class JumpScopeChecker {
33  Sema &S;
34 
35  /// Permissive - True when recovering from errors, in which case precautions
36  /// are taken to handle incomplete scope information.
37  const bool Permissive;
38 
39  /// GotoScope - This is a record that we use to keep track of all of the
40  /// scopes that are introduced by VLAs and other things that scope jumps like
41  /// gotos. This scope tree has nothing to do with the source scope tree,
42  /// because you can have multiple VLA scopes per compound statement, and most
43  /// compound statements don't introduce any scopes.
44  struct GotoScope {
45  /// ParentScope - The index in ScopeMap of the parent scope. This is 0 for
46  /// the parent scope is the function body.
47  unsigned ParentScope;
48 
49  /// InDiag - The note to emit if there is a jump into this scope.
50  unsigned InDiag;
51 
52  /// OutDiag - The note to emit if there is an indirect jump out
53  /// of this scope. Direct jumps always clean up their current scope
54  /// in an orderly way.
55  unsigned OutDiag;
56 
57  /// Loc - Location to emit the diagnostic.
58  SourceLocation Loc;
59 
60  GotoScope(unsigned parentScope, unsigned InDiag, unsigned OutDiag,
62  : ParentScope(parentScope), InDiag(InDiag), OutDiag(OutDiag), Loc(L) {}
63  };
64 
66  llvm::DenseMap<Stmt*, unsigned> LabelAndGotoScopes;
68 
70  SmallVector<LabelDecl*, 4> IndirectJumpTargets;
71 public:
72  JumpScopeChecker(Stmt *Body, Sema &S);
73 private:
74  void BuildScopeInformation(Decl *D, unsigned &ParentScope);
75  void BuildScopeInformation(VarDecl *D, const BlockDecl *BDecl,
76  unsigned &ParentScope);
77  void BuildScopeInformation(Stmt *S, unsigned &origParentScope);
78 
79  void VerifyJumps();
80  void VerifyIndirectJumps();
81  void NoteJumpIntoScopes(ArrayRef<unsigned> ToScopes);
82  void DiagnoseIndirectJump(IndirectGotoStmt *IG, unsigned IGScope,
83  LabelDecl *Target, unsigned TargetScope);
84  void CheckJump(Stmt *From, Stmt *To, SourceLocation DiagLoc,
85  unsigned JumpDiag, unsigned JumpDiagWarning,
86  unsigned JumpDiagCXX98Compat);
87  void CheckGotoStmt(GotoStmt *GS);
88 
89  unsigned GetDeepestCommonScope(unsigned A, unsigned B);
90 };
91 } // end anonymous namespace
92 
93 #define CHECK_PERMISSIVE(x) (assert(Permissive || !(x)), (Permissive && (x)))
94 
95 JumpScopeChecker::JumpScopeChecker(Stmt *Body, Sema &s)
96  : S(s), Permissive(s.hasAnyUnrecoverableErrorsInThisFunction()) {
97  // Add a scope entry for function scope.
98  Scopes.push_back(GotoScope(~0U, ~0U, ~0U, SourceLocation()));
99 
100  // Build information for the top level compound statement, so that we have a
101  // defined scope record for every "goto" and label.
102  unsigned BodyParentScope = 0;
103  BuildScopeInformation(Body, BodyParentScope);
104 
105  // Check that all jumps we saw are kosher.
106  VerifyJumps();
107  VerifyIndirectJumps();
108 }
109 
110 /// GetDeepestCommonScope - Finds the innermost scope enclosing the
111 /// two scopes.
112 unsigned JumpScopeChecker::GetDeepestCommonScope(unsigned A, unsigned B) {
113  while (A != B) {
114  // Inner scopes are created after outer scopes and therefore have
115  // higher indices.
116  if (A < B) {
117  assert(Scopes[B].ParentScope < B);
118  B = Scopes[B].ParentScope;
119  } else {
120  assert(Scopes[A].ParentScope < A);
121  A = Scopes[A].ParentScope;
122  }
123  }
124  return A;
125 }
126 
127 typedef std::pair<unsigned,unsigned> ScopePair;
128 
129 /// GetDiagForGotoScopeDecl - If this decl induces a new goto scope, return a
130 /// diagnostic that should be emitted if control goes over it. If not, return 0.
132  if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
133  unsigned InDiag = 0;
134  unsigned OutDiag = 0;
135 
136  if (VD->getType()->isVariablyModifiedType())
137  InDiag = diag::note_protected_by_vla;
138 
139  if (VD->hasAttr<BlocksAttr>())
140  return ScopePair(diag::note_protected_by___block,
141  diag::note_exits___block);
142 
143  if (VD->hasAttr<CleanupAttr>())
144  return ScopePair(diag::note_protected_by_cleanup,
145  diag::note_exits_cleanup);
146 
147  if (VD->hasLocalStorage()) {
148  switch (VD->getType().isDestructedType()) {
149  case QualType::DK_objc_strong_lifetime:
150  return ScopePair(diag::note_protected_by_objc_strong_init,
151  diag::note_exits_objc_strong);
152 
153  case QualType::DK_objc_weak_lifetime:
154  return ScopePair(diag::note_protected_by_objc_weak_init,
155  diag::note_exits_objc_weak);
156 
157  case QualType::DK_cxx_destructor:
158  OutDiag = diag::note_exits_dtor;
159  break;
160 
161  case QualType::DK_none:
162  break;
163  }
164  }
165 
166  const Expr *Init = VD->getInit();
167  if (S.Context.getLangOpts().CPlusPlus && VD->hasLocalStorage() && Init) {
168  // C++11 [stmt.dcl]p3:
169  // A program that jumps from a point where a variable with automatic
170  // storage duration is not in scope to a point where it is in scope
171  // is ill-formed unless the variable has scalar type, class type with
172  // a trivial default constructor and a trivial destructor, a
173  // cv-qualified version of one of these types, or an array of one of
174  // the preceding types and is declared without an initializer.
175 
176  // C++03 [stmt.dcl.p3:
177  // A program that jumps from a point where a local variable
178  // with automatic storage duration is not in scope to a point
179  // where it is in scope is ill-formed unless the variable has
180  // POD type and is declared without an initializer.
181 
182  InDiag = diag::note_protected_by_variable_init;
183 
184  // For a variable of (array of) class type declared without an
185  // initializer, we will have call-style initialization and the initializer
186  // will be the CXXConstructExpr with no intervening nodes.
187  if (const CXXConstructExpr *CCE = dyn_cast<CXXConstructExpr>(Init)) {
188  const CXXConstructorDecl *Ctor = CCE->getConstructor();
189  if (Ctor->isTrivial() && Ctor->isDefaultConstructor() &&
190  VD->getInitStyle() == VarDecl::CallInit) {
191  if (OutDiag)
192  InDiag = diag::note_protected_by_variable_nontriv_destructor;
193  else if (!Ctor->getParent()->isPOD())
194  InDiag = diag::note_protected_by_variable_non_pod;
195  else
196  InDiag = 0;
197  }
198  }
199  }
200 
201  return ScopePair(InDiag, OutDiag);
202  }
203 
204  if (const TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) {
205  if (TD->getUnderlyingType()->isVariablyModifiedType())
206  return ScopePair(isa<TypedefDecl>(TD)
207  ? diag::note_protected_by_vla_typedef
208  : diag::note_protected_by_vla_type_alias,
209  0);
210  }
211 
212  return ScopePair(0U, 0U);
213 }
214 
215 /// \brief Build scope information for a declaration that is part of a DeclStmt.
216 void JumpScopeChecker::BuildScopeInformation(Decl *D, unsigned &ParentScope) {
217  // If this decl causes a new scope, push and switch to it.
218  std::pair<unsigned,unsigned> Diags = GetDiagForGotoScopeDecl(S, D);
219  if (Diags.first || Diags.second) {
220  Scopes.push_back(GotoScope(ParentScope, Diags.first, Diags.second,
221  D->getLocation()));
222  ParentScope = Scopes.size()-1;
223  }
224 
225  // If the decl has an initializer, walk it with the potentially new
226  // scope we just installed.
227  if (VarDecl *VD = dyn_cast<VarDecl>(D))
228  if (Expr *Init = VD->getInit())
229  BuildScopeInformation(Init, ParentScope);
230 }
231 
232 /// \brief Build scope information for a captured block literal variables.
233 void JumpScopeChecker::BuildScopeInformation(VarDecl *D,
234  const BlockDecl *BDecl,
235  unsigned &ParentScope) {
236  // exclude captured __block variables; there's no destructor
237  // associated with the block literal for them.
238  if (D->hasAttr<BlocksAttr>())
239  return;
240  QualType T = D->getType();
241  QualType::DestructionKind destructKind = T.isDestructedType();
242  if (destructKind != QualType::DK_none) {
243  std::pair<unsigned,unsigned> Diags;
244  switch (destructKind) {
245  case QualType::DK_cxx_destructor:
246  Diags = ScopePair(diag::note_enters_block_captures_cxx_obj,
247  diag::note_exits_block_captures_cxx_obj);
248  break;
249  case QualType::DK_objc_strong_lifetime:
250  Diags = ScopePair(diag::note_enters_block_captures_strong,
251  diag::note_exits_block_captures_strong);
252  break;
253  case QualType::DK_objc_weak_lifetime:
254  Diags = ScopePair(diag::note_enters_block_captures_weak,
255  diag::note_exits_block_captures_weak);
256  break;
257  case QualType::DK_none:
258  llvm_unreachable("non-lifetime captured variable");
259  }
260  SourceLocation Loc = D->getLocation();
261  if (Loc.isInvalid())
262  Loc = BDecl->getLocation();
263  Scopes.push_back(GotoScope(ParentScope,
264  Diags.first, Diags.second, Loc));
265  ParentScope = Scopes.size()-1;
266  }
267 }
268 
269 /// BuildScopeInformation - The statements from CI to CE are known to form a
270 /// coherent VLA scope with a specified parent node. Walk through the
271 /// statements, adding any labels or gotos to LabelAndGotoScopes and recursively
272 /// walking the AST as needed.
273 void JumpScopeChecker::BuildScopeInformation(Stmt *S,
274  unsigned &origParentScope) {
275  // If this is a statement, rather than an expression, scopes within it don't
276  // propagate out into the enclosing scope. Otherwise we have to worry
277  // about block literals, which have the lifetime of their enclosing statement.
278  unsigned independentParentScope = origParentScope;
279  unsigned &ParentScope = ((isa<Expr>(S) && !isa<StmtExpr>(S))
280  ? origParentScope : independentParentScope);
281 
282  unsigned StmtsToSkip = 0u;
283 
284  // If we found a label, remember that it is in ParentScope scope.
285  switch (S->getStmtClass()) {
286  case Stmt::AddrLabelExprClass:
287  IndirectJumpTargets.push_back(cast<AddrLabelExpr>(S)->getLabel());
288  break;
289 
290  case Stmt::ObjCForCollectionStmtClass: {
291  auto *CS = cast<ObjCForCollectionStmt>(S);
292  unsigned Diag = diag::note_protected_by_objc_fast_enumeration;
293  unsigned NewParentScope = Scopes.size();
294  Scopes.push_back(GotoScope(ParentScope, Diag, 0, S->getLocStart()));
295  BuildScopeInformation(CS->getBody(), NewParentScope);
296  return;
297  }
298 
299  case Stmt::IndirectGotoStmtClass:
300  // "goto *&&lbl;" is a special case which we treat as equivalent
301  // to a normal goto. In addition, we don't calculate scope in the
302  // operand (to avoid recording the address-of-label use), which
303  // works only because of the restricted set of expressions which
304  // we detect as constant targets.
305  if (cast<IndirectGotoStmt>(S)->getConstantTarget()) {
306  LabelAndGotoScopes[S] = ParentScope;
307  Jumps.push_back(S);
308  return;
309  }
310 
311  LabelAndGotoScopes[S] = ParentScope;
312  IndirectJumps.push_back(cast<IndirectGotoStmt>(S));
313  break;
314 
315  case Stmt::SwitchStmtClass:
316  // Evaluate the C++17 init stmt and condition variable
317  // before entering the scope of the switch statement.
318  if (Stmt *Init = cast<SwitchStmt>(S)->getInit()) {
319  BuildScopeInformation(Init, ParentScope);
320  ++StmtsToSkip;
321  }
322  if (VarDecl *Var = cast<SwitchStmt>(S)->getConditionVariable()) {
323  BuildScopeInformation(Var, ParentScope);
324  ++StmtsToSkip;
325  }
326  // Fall through
327 
328  case Stmt::GotoStmtClass:
329  // Remember both what scope a goto is in as well as the fact that we have
330  // it. This makes the second scan not have to walk the AST again.
331  LabelAndGotoScopes[S] = ParentScope;
332  Jumps.push_back(S);
333  break;
334 
335  case Stmt::IfStmtClass: {
336  IfStmt *IS = cast<IfStmt>(S);
337  if (!(IS->isConstexpr() || IS->isObjCAvailabilityCheck()))
338  break;
339 
340  unsigned Diag = IS->isConstexpr() ? diag::note_protected_by_constexpr_if
341  : diag::note_protected_by_if_available;
342 
343  if (VarDecl *Var = IS->getConditionVariable())
344  BuildScopeInformation(Var, ParentScope);
345 
346  // Cannot jump into the middle of the condition.
347  unsigned NewParentScope = Scopes.size();
348  Scopes.push_back(GotoScope(ParentScope, Diag, 0, IS->getLocStart()));
349  BuildScopeInformation(IS->getCond(), NewParentScope);
350 
351  // Jumps into either arm of an 'if constexpr' are not allowed.
352  NewParentScope = Scopes.size();
353  Scopes.push_back(GotoScope(ParentScope, Diag, 0, IS->getLocStart()));
354  BuildScopeInformation(IS->getThen(), NewParentScope);
355  if (Stmt *Else = IS->getElse()) {
356  NewParentScope = Scopes.size();
357  Scopes.push_back(GotoScope(ParentScope, Diag, 0, IS->getLocStart()));
358  BuildScopeInformation(Else, NewParentScope);
359  }
360  return;
361  }
362 
363  case Stmt::CXXTryStmtClass: {
364  CXXTryStmt *TS = cast<CXXTryStmt>(S);
365  {
366  unsigned NewParentScope = Scopes.size();
367  Scopes.push_back(GotoScope(ParentScope,
368  diag::note_protected_by_cxx_try,
369  diag::note_exits_cxx_try,
370  TS->getSourceRange().getBegin()));
371  if (Stmt *TryBlock = TS->getTryBlock())
372  BuildScopeInformation(TryBlock, NewParentScope);
373  }
374 
375  // Jump from the catch into the try is not allowed either.
376  for (unsigned I = 0, E = TS->getNumHandlers(); I != E; ++I) {
377  CXXCatchStmt *CS = TS->getHandler(I);
378  unsigned NewParentScope = Scopes.size();
379  Scopes.push_back(GotoScope(ParentScope,
380  diag::note_protected_by_cxx_catch,
381  diag::note_exits_cxx_catch,
382  CS->getSourceRange().getBegin()));
383  BuildScopeInformation(CS->getHandlerBlock(), NewParentScope);
384  }
385  return;
386  }
387 
388  case Stmt::SEHTryStmtClass: {
389  SEHTryStmt *TS = cast<SEHTryStmt>(S);
390  {
391  unsigned NewParentScope = Scopes.size();
392  Scopes.push_back(GotoScope(ParentScope,
393  diag::note_protected_by_seh_try,
394  diag::note_exits_seh_try,
395  TS->getSourceRange().getBegin()));
396  if (Stmt *TryBlock = TS->getTryBlock())
397  BuildScopeInformation(TryBlock, NewParentScope);
398  }
399 
400  // Jump from __except or __finally into the __try are not allowed either.
401  if (SEHExceptStmt *Except = TS->getExceptHandler()) {
402  unsigned NewParentScope = Scopes.size();
403  Scopes.push_back(GotoScope(ParentScope,
404  diag::note_protected_by_seh_except,
405  diag::note_exits_seh_except,
406  Except->getSourceRange().getBegin()));
407  BuildScopeInformation(Except->getBlock(), NewParentScope);
408  } else if (SEHFinallyStmt *Finally = TS->getFinallyHandler()) {
409  unsigned NewParentScope = Scopes.size();
410  Scopes.push_back(GotoScope(ParentScope,
411  diag::note_protected_by_seh_finally,
412  diag::note_exits_seh_finally,
413  Finally->getSourceRange().getBegin()));
414  BuildScopeInformation(Finally->getBlock(), NewParentScope);
415  }
416 
417  return;
418  }
419 
420  case Stmt::DeclStmtClass: {
421  // If this is a declstmt with a VLA definition, it defines a scope from here
422  // to the end of the containing context.
423  DeclStmt *DS = cast<DeclStmt>(S);
424  // The decl statement creates a scope if any of the decls in it are VLAs
425  // or have the cleanup attribute.
426  for (auto *I : DS->decls())
427  BuildScopeInformation(I, origParentScope);
428  return;
429  }
430 
431  case Stmt::ObjCAtTryStmtClass: {
432  // Disallow jumps into any part of an @try statement by pushing a scope and
433  // walking all sub-stmts in that scope.
434  ObjCAtTryStmt *AT = cast<ObjCAtTryStmt>(S);
435  // Recursively walk the AST for the @try part.
436  {
437  unsigned NewParentScope = Scopes.size();
438  Scopes.push_back(GotoScope(ParentScope,
439  diag::note_protected_by_objc_try,
440  diag::note_exits_objc_try,
441  AT->getAtTryLoc()));
442  if (Stmt *TryPart = AT->getTryBody())
443  BuildScopeInformation(TryPart, NewParentScope);
444  }
445 
446  // Jump from the catch to the finally or try is not valid.
447  for (unsigned I = 0, N = AT->getNumCatchStmts(); I != N; ++I) {
448  ObjCAtCatchStmt *AC = AT->getCatchStmt(I);
449  unsigned NewParentScope = Scopes.size();
450  Scopes.push_back(GotoScope(ParentScope,
451  diag::note_protected_by_objc_catch,
452  diag::note_exits_objc_catch,
453  AC->getAtCatchLoc()));
454  // @catches are nested and it isn't
455  BuildScopeInformation(AC->getCatchBody(), NewParentScope);
456  }
457 
458  // Jump from the finally to the try or catch is not valid.
459  if (ObjCAtFinallyStmt *AF = AT->getFinallyStmt()) {
460  unsigned NewParentScope = Scopes.size();
461  Scopes.push_back(GotoScope(ParentScope,
462  diag::note_protected_by_objc_finally,
463  diag::note_exits_objc_finally,
464  AF->getAtFinallyLoc()));
465  BuildScopeInformation(AF, NewParentScope);
466  }
467 
468  return;
469  }
470 
471  case Stmt::ObjCAtSynchronizedStmtClass: {
472  // Disallow jumps into the protected statement of an @synchronized, but
473  // allow jumps into the object expression it protects.
474  ObjCAtSynchronizedStmt *AS = cast<ObjCAtSynchronizedStmt>(S);
475  // Recursively walk the AST for the @synchronized object expr, it is
476  // evaluated in the normal scope.
477  BuildScopeInformation(AS->getSynchExpr(), ParentScope);
478 
479  // Recursively walk the AST for the @synchronized part, protected by a new
480  // scope.
481  unsigned NewParentScope = Scopes.size();
482  Scopes.push_back(GotoScope(ParentScope,
483  diag::note_protected_by_objc_synchronized,
484  diag::note_exits_objc_synchronized,
485  AS->getAtSynchronizedLoc()));
486  BuildScopeInformation(AS->getSynchBody(), NewParentScope);
487  return;
488  }
489 
490  case Stmt::ObjCAutoreleasePoolStmtClass: {
491  // Disallow jumps into the protected statement of an @autoreleasepool.
492  ObjCAutoreleasePoolStmt *AS = cast<ObjCAutoreleasePoolStmt>(S);
493  // Recursively walk the AST for the @autoreleasepool part, protected by a
494  // new scope.
495  unsigned NewParentScope = Scopes.size();
496  Scopes.push_back(GotoScope(ParentScope,
497  diag::note_protected_by_objc_autoreleasepool,
498  diag::note_exits_objc_autoreleasepool,
499  AS->getAtLoc()));
500  BuildScopeInformation(AS->getSubStmt(), NewParentScope);
501  return;
502  }
503 
504  case Stmt::ExprWithCleanupsClass: {
505  // Disallow jumps past full-expressions that use blocks with
506  // non-trivial cleanups of their captures. This is theoretically
507  // implementable but a lot of work which we haven't felt up to doing.
508  ExprWithCleanups *EWC = cast<ExprWithCleanups>(S);
509  for (unsigned i = 0, e = EWC->getNumObjects(); i != e; ++i) {
510  const BlockDecl *BDecl = EWC->getObject(i);
511  for (const auto &CI : BDecl->captures()) {
512  VarDecl *variable = CI.getVariable();
513  BuildScopeInformation(variable, BDecl, origParentScope);
514  }
515  }
516  break;
517  }
518 
519  case Stmt::MaterializeTemporaryExprClass: {
520  // Disallow jumps out of scopes containing temporaries lifetime-extended to
521  // automatic storage duration.
522  MaterializeTemporaryExpr *MTE = cast<MaterializeTemporaryExpr>(S);
523  if (MTE->getStorageDuration() == SD_Automatic) {
526  const Expr *ExtendedObject =
528  CommaLHS, Adjustments);
529  if (ExtendedObject->getType().isDestructedType()) {
530  Scopes.push_back(GotoScope(ParentScope, 0,
531  diag::note_exits_temporary_dtor,
532  ExtendedObject->getExprLoc()));
533  origParentScope = Scopes.size()-1;
534  }
535  }
536  break;
537  }
538 
539  case Stmt::CaseStmtClass:
540  case Stmt::DefaultStmtClass:
541  case Stmt::LabelStmtClass:
542  LabelAndGotoScopes[S] = ParentScope;
543  break;
544 
545  default:
546  break;
547  }
548 
549  for (Stmt *SubStmt : S->children()) {
550  if (!SubStmt)
551  continue;
552  if (StmtsToSkip) {
553  --StmtsToSkip;
554  continue;
555  }
556 
557  // Cases, labels, and defaults aren't "scope parents". It's also
558  // important to handle these iteratively instead of recursively in
559  // order to avoid blowing out the stack.
560  while (true) {
561  Stmt *Next;
562  if (SwitchCase *SC = dyn_cast<SwitchCase>(SubStmt))
563  Next = SC->getSubStmt();
564  else if (LabelStmt *LS = dyn_cast<LabelStmt>(SubStmt))
565  Next = LS->getSubStmt();
566  else
567  break;
568 
569  LabelAndGotoScopes[SubStmt] = ParentScope;
570  SubStmt = Next;
571  }
572 
573  // Recursively walk the AST.
574  BuildScopeInformation(SubStmt, ParentScope);
575  }
576 }
577 
578 /// VerifyJumps - Verify each element of the Jumps array to see if they are
579 /// valid, emitting diagnostics if not.
580 void JumpScopeChecker::VerifyJumps() {
581  while (!Jumps.empty()) {
582  Stmt *Jump = Jumps.pop_back_val();
583 
584  // With a goto,
585  if (GotoStmt *GS = dyn_cast<GotoStmt>(Jump)) {
586  // The label may not have a statement if it's coming from inline MS ASM.
587  if (GS->getLabel()->getStmt()) {
588  CheckJump(GS, GS->getLabel()->getStmt(), GS->getGotoLoc(),
589  diag::err_goto_into_protected_scope,
590  diag::ext_goto_into_protected_scope,
591  diag::warn_cxx98_compat_goto_into_protected_scope);
592  }
593  CheckGotoStmt(GS);
594  continue;
595  }
596 
597  // We only get indirect gotos here when they have a constant target.
598  if (IndirectGotoStmt *IGS = dyn_cast<IndirectGotoStmt>(Jump)) {
599  LabelDecl *Target = IGS->getConstantTarget();
600  CheckJump(IGS, Target->getStmt(), IGS->getGotoLoc(),
601  diag::err_goto_into_protected_scope,
602  diag::ext_goto_into_protected_scope,
603  diag::warn_cxx98_compat_goto_into_protected_scope);
604  continue;
605  }
606 
607  SwitchStmt *SS = cast<SwitchStmt>(Jump);
608  for (SwitchCase *SC = SS->getSwitchCaseList(); SC;
609  SC = SC->getNextSwitchCase()) {
610  if (CHECK_PERMISSIVE(!LabelAndGotoScopes.count(SC)))
611  continue;
612  SourceLocation Loc;
613  if (CaseStmt *CS = dyn_cast<CaseStmt>(SC))
614  Loc = CS->getLocStart();
615  else if (DefaultStmt *DS = dyn_cast<DefaultStmt>(SC))
616  Loc = DS->getLocStart();
617  else
618  Loc = SC->getLocStart();
619  CheckJump(SS, SC, Loc, diag::err_switch_into_protected_scope, 0,
620  diag::warn_cxx98_compat_switch_into_protected_scope);
621  }
622  }
623 }
624 
625 /// VerifyIndirectJumps - Verify whether any possible indirect jump
626 /// might cross a protection boundary. Unlike direct jumps, indirect
627 /// jumps count cleanups as protection boundaries: since there's no
628 /// way to know where the jump is going, we can't implicitly run the
629 /// right cleanups the way we can with direct jumps.
630 ///
631 /// Thus, an indirect jump is "trivial" if it bypasses no
632 /// initializations and no teardowns. More formally, an indirect jump
633 /// from A to B is trivial if the path out from A to DCA(A,B) is
634 /// trivial and the path in from DCA(A,B) to B is trivial, where
635 /// DCA(A,B) is the deepest common ancestor of A and B.
636 /// Jump-triviality is transitive but asymmetric.
637 ///
638 /// A path in is trivial if none of the entered scopes have an InDiag.
639 /// A path out is trivial is none of the exited scopes have an OutDiag.
640 ///
641 /// Under these definitions, this function checks that the indirect
642 /// jump between A and B is trivial for every indirect goto statement A
643 /// and every label B whose address was taken in the function.
644 void JumpScopeChecker::VerifyIndirectJumps() {
645  if (IndirectJumps.empty()) return;
646 
647  // If there aren't any address-of-label expressions in this function,
648  // complain about the first indirect goto.
649  if (IndirectJumpTargets.empty()) {
650  S.Diag(IndirectJumps[0]->getGotoLoc(),
651  diag::err_indirect_goto_without_addrlabel);
652  return;
653  }
654 
655  // Collect a single representative of every scope containing an
656  // indirect goto. For most code bases, this substantially cuts
657  // down on the number of jump sites we'll have to consider later.
658  typedef std::pair<unsigned, IndirectGotoStmt*> JumpScope;
659  SmallVector<JumpScope, 32> JumpScopes;
660  {
661  llvm::DenseMap<unsigned, IndirectGotoStmt*> JumpScopesMap;
663  I = IndirectJumps.begin(), E = IndirectJumps.end(); I != E; ++I) {
664  IndirectGotoStmt *IG = *I;
665  if (CHECK_PERMISSIVE(!LabelAndGotoScopes.count(IG)))
666  continue;
667  unsigned IGScope = LabelAndGotoScopes[IG];
668  IndirectGotoStmt *&Entry = JumpScopesMap[IGScope];
669  if (!Entry) Entry = IG;
670  }
671  JumpScopes.reserve(JumpScopesMap.size());
672  for (llvm::DenseMap<unsigned, IndirectGotoStmt*>::iterator
673  I = JumpScopesMap.begin(), E = JumpScopesMap.end(); I != E; ++I)
674  JumpScopes.push_back(*I);
675  }
676 
677  // Collect a single representative of every scope containing a
678  // label whose address was taken somewhere in the function.
679  // For most code bases, there will be only one such scope.
680  llvm::DenseMap<unsigned, LabelDecl*> TargetScopes;
682  I = IndirectJumpTargets.begin(), E = IndirectJumpTargets.end();
683  I != E; ++I) {
684  LabelDecl *TheLabel = *I;
685  if (CHECK_PERMISSIVE(!LabelAndGotoScopes.count(TheLabel->getStmt())))
686  continue;
687  unsigned LabelScope = LabelAndGotoScopes[TheLabel->getStmt()];
688  LabelDecl *&Target = TargetScopes[LabelScope];
689  if (!Target) Target = TheLabel;
690  }
691 
692  // For each target scope, make sure it's trivially reachable from
693  // every scope containing a jump site.
694  //
695  // A path between scopes always consists of exitting zero or more
696  // scopes, then entering zero or more scopes. We build a set of
697  // of scopes S from which the target scope can be trivially
698  // entered, then verify that every jump scope can be trivially
699  // exitted to reach a scope in S.
700  llvm::BitVector Reachable(Scopes.size(), false);
701  for (llvm::DenseMap<unsigned,LabelDecl*>::iterator
702  TI = TargetScopes.begin(), TE = TargetScopes.end(); TI != TE; ++TI) {
703  unsigned TargetScope = TI->first;
704  LabelDecl *TargetLabel = TI->second;
705 
706  Reachable.reset();
707 
708  // Mark all the enclosing scopes from which you can safely jump
709  // into the target scope. 'Min' will end up being the index of
710  // the shallowest such scope.
711  unsigned Min = TargetScope;
712  while (true) {
713  Reachable.set(Min);
714 
715  // Don't go beyond the outermost scope.
716  if (Min == 0) break;
717 
718  // Stop if we can't trivially enter the current scope.
719  if (Scopes[Min].InDiag) break;
720 
721  Min = Scopes[Min].ParentScope;
722  }
723 
724  // Walk through all the jump sites, checking that they can trivially
725  // reach this label scope.
727  I = JumpScopes.begin(), E = JumpScopes.end(); I != E; ++I) {
728  unsigned Scope = I->first;
729 
730  // Walk out the "scope chain" for this scope, looking for a scope
731  // we've marked reachable. For well-formed code this amortizes
732  // to O(JumpScopes.size() / Scopes.size()): we only iterate
733  // when we see something unmarked, and in well-formed code we
734  // mark everything we iterate past.
735  bool IsReachable = false;
736  while (true) {
737  if (Reachable.test(Scope)) {
738  // If we find something reachable, mark all the scopes we just
739  // walked through as reachable.
740  for (unsigned S = I->first; S != Scope; S = Scopes[S].ParentScope)
741  Reachable.set(S);
742  IsReachable = true;
743  break;
744  }
745 
746  // Don't walk out if we've reached the top-level scope or we've
747  // gotten shallower than the shallowest reachable scope.
748  if (Scope == 0 || Scope < Min) break;
749 
750  // Don't walk out through an out-diagnostic.
751  if (Scopes[Scope].OutDiag) break;
752 
753  Scope = Scopes[Scope].ParentScope;
754  }
755 
756  // Only diagnose if we didn't find something.
757  if (IsReachable) continue;
758 
759  DiagnoseIndirectJump(I->second, I->first, TargetLabel, TargetScope);
760  }
761  }
762 }
763 
764 /// Return true if a particular error+note combination must be downgraded to a
765 /// warning in Microsoft mode.
766 static bool IsMicrosoftJumpWarning(unsigned JumpDiag, unsigned InDiagNote) {
767  return (JumpDiag == diag::err_goto_into_protected_scope &&
768  (InDiagNote == diag::note_protected_by_variable_init ||
769  InDiagNote == diag::note_protected_by_variable_nontriv_destructor));
770 }
771 
772 /// Return true if a particular note should be downgraded to a compatibility
773 /// warning in C++11 mode.
774 static bool IsCXX98CompatWarning(Sema &S, unsigned InDiagNote) {
775  return S.getLangOpts().CPlusPlus11 &&
776  InDiagNote == diag::note_protected_by_variable_non_pod;
777 }
778 
779 /// Produce primary diagnostic for an indirect jump statement.
781  LabelDecl *Target, bool &Diagnosed) {
782  if (Diagnosed)
783  return;
784  S.Diag(Jump->getGotoLoc(), diag::err_indirect_goto_in_protected_scope);
785  S.Diag(Target->getStmt()->getIdentLoc(), diag::note_indirect_goto_target);
786  Diagnosed = true;
787 }
788 
789 /// Produce note diagnostics for a jump into a protected scope.
790 void JumpScopeChecker::NoteJumpIntoScopes(ArrayRef<unsigned> ToScopes) {
791  if (CHECK_PERMISSIVE(ToScopes.empty()))
792  return;
793  for (unsigned I = 0, E = ToScopes.size(); I != E; ++I)
794  if (Scopes[ToScopes[I]].InDiag)
795  S.Diag(Scopes[ToScopes[I]].Loc, Scopes[ToScopes[I]].InDiag);
796 }
797 
798 /// Diagnose an indirect jump which is known to cross scopes.
799 void JumpScopeChecker::DiagnoseIndirectJump(IndirectGotoStmt *Jump,
800  unsigned JumpScope,
801  LabelDecl *Target,
802  unsigned TargetScope) {
803  if (CHECK_PERMISSIVE(JumpScope == TargetScope))
804  return;
805 
806  unsigned Common = GetDeepestCommonScope(JumpScope, TargetScope);
807  bool Diagnosed = false;
808 
809  // Walk out the scope chain until we reach the common ancestor.
810  for (unsigned I = JumpScope; I != Common; I = Scopes[I].ParentScope)
811  if (Scopes[I].OutDiag) {
812  DiagnoseIndirectJumpStmt(S, Jump, Target, Diagnosed);
813  S.Diag(Scopes[I].Loc, Scopes[I].OutDiag);
814  }
815 
816  SmallVector<unsigned, 10> ToScopesCXX98Compat;
817 
818  // Now walk into the scopes containing the label whose address was taken.
819  for (unsigned I = TargetScope; I != Common; I = Scopes[I].ParentScope)
820  if (IsCXX98CompatWarning(S, Scopes[I].InDiag))
821  ToScopesCXX98Compat.push_back(I);
822  else if (Scopes[I].InDiag) {
823  DiagnoseIndirectJumpStmt(S, Jump, Target, Diagnosed);
824  S.Diag(Scopes[I].Loc, Scopes[I].InDiag);
825  }
826 
827  // Diagnose this jump if it would be ill-formed in C++98.
828  if (!Diagnosed && !ToScopesCXX98Compat.empty()) {
829  S.Diag(Jump->getGotoLoc(),
830  diag::warn_cxx98_compat_indirect_goto_in_protected_scope);
831  S.Diag(Target->getStmt()->getIdentLoc(), diag::note_indirect_goto_target);
832  NoteJumpIntoScopes(ToScopesCXX98Compat);
833  }
834 }
835 
836 /// CheckJump - Validate that the specified jump statement is valid: that it is
837 /// jumping within or out of its current scope, not into a deeper one.
838 void JumpScopeChecker::CheckJump(Stmt *From, Stmt *To, SourceLocation DiagLoc,
839  unsigned JumpDiagError, unsigned JumpDiagWarning,
840  unsigned JumpDiagCXX98Compat) {
841  if (CHECK_PERMISSIVE(!LabelAndGotoScopes.count(From)))
842  return;
843  if (CHECK_PERMISSIVE(!LabelAndGotoScopes.count(To)))
844  return;
845 
846  unsigned FromScope = LabelAndGotoScopes[From];
847  unsigned ToScope = LabelAndGotoScopes[To];
848 
849  // Common case: exactly the same scope, which is fine.
850  if (FromScope == ToScope) return;
851 
852  // Warn on gotos out of __finally blocks.
853  if (isa<GotoStmt>(From) || isa<IndirectGotoStmt>(From)) {
854  // If FromScope > ToScope, FromScope is more nested and the jump goes to a
855  // less nested scope. Check if it crosses a __finally along the way.
856  for (unsigned I = FromScope; I > ToScope; I = Scopes[I].ParentScope) {
857  if (Scopes[I].InDiag == diag::note_protected_by_seh_finally) {
858  S.Diag(From->getLocStart(), diag::warn_jump_out_of_seh_finally);
859  break;
860  }
861  }
862  }
863 
864  unsigned CommonScope = GetDeepestCommonScope(FromScope, ToScope);
865 
866  // It's okay to jump out from a nested scope.
867  if (CommonScope == ToScope) return;
868 
869  // Pull out (and reverse) any scopes we might need to diagnose skipping.
870  SmallVector<unsigned, 10> ToScopesCXX98Compat;
871  SmallVector<unsigned, 10> ToScopesError;
872  SmallVector<unsigned, 10> ToScopesWarning;
873  for (unsigned I = ToScope; I != CommonScope; I = Scopes[I].ParentScope) {
874  if (S.getLangOpts().MSVCCompat && JumpDiagWarning != 0 &&
875  IsMicrosoftJumpWarning(JumpDiagError, Scopes[I].InDiag))
876  ToScopesWarning.push_back(I);
877  else if (IsCXX98CompatWarning(S, Scopes[I].InDiag))
878  ToScopesCXX98Compat.push_back(I);
879  else if (Scopes[I].InDiag)
880  ToScopesError.push_back(I);
881  }
882 
883  // Handle warnings.
884  if (!ToScopesWarning.empty()) {
885  S.Diag(DiagLoc, JumpDiagWarning);
886  NoteJumpIntoScopes(ToScopesWarning);
887  }
888 
889  // Handle errors.
890  if (!ToScopesError.empty()) {
891  S.Diag(DiagLoc, JumpDiagError);
892  NoteJumpIntoScopes(ToScopesError);
893  }
894 
895  // Handle -Wc++98-compat warnings if the jump is well-formed.
896  if (ToScopesError.empty() && !ToScopesCXX98Compat.empty()) {
897  S.Diag(DiagLoc, JumpDiagCXX98Compat);
898  NoteJumpIntoScopes(ToScopesCXX98Compat);
899  }
900 }
901 
902 void JumpScopeChecker::CheckGotoStmt(GotoStmt *GS) {
903  if (GS->getLabel()->isMSAsmLabel()) {
904  S.Diag(GS->getGotoLoc(), diag::err_goto_ms_asm_label)
905  << GS->getLabel()->getIdentifier();
906  S.Diag(GS->getLabel()->getLocation(), diag::note_goto_ms_asm_label)
907  << GS->getLabel()->getIdentifier();
908  }
909 }
910 
911 void Sema::DiagnoseInvalidJumps(Stmt *Body) {
912  (void)JumpScopeChecker(Body, *this);
913 }
static DiagnosticBuilder Diag(DiagnosticsEngine *Diags, const LangOptions &Features, FullSourceLoc TokLoc, const char *TokBegin, const char *TokRangeBegin, const char *TokRangeEnd, unsigned DiagID)
Produce a diagnostic highlighting some portion of a literal.
const Stmt * getElse() const
Definition: Stmt.h:945
A (possibly-)qualified type.
Definition: Type.h:614
const Expr * skipRValueSubobjectAdjustments(SmallVectorImpl< const Expr *> &CommaLHS, SmallVectorImpl< SubobjectAdjustment > &Adjustments) const
Walk outwards from an expression we want to bind a reference to and find the expression whose lifetim...
Definition: Expr.cpp:77
Stmt - This represents one statement.
Definition: Stmt.h:60
const ObjCAtFinallyStmt * getFinallyStmt() const
Retrieve the @finally statement, if any.
Definition: StmtObjC.h:224
CXXCatchStmt * getHandler(unsigned i)
Definition: StmtCXX.h:104
IfStmt - This represents an if/then/else.
Definition: Stmt.h:905
static bool IsMicrosoftJumpWarning(unsigned JumpDiag, unsigned InDiagNote)
Return true if a particular error+note combination must be downgraded to a warning in Microsoft mode...
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID)
Emit a diagnostic.
Definition: Sema.h:1270
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:81
Stmt * getHandlerBlock() const
Definition: StmtCXX.h:52
bool isPOD() const
Whether this class is a POD-type (C++ [class]p4)
Definition: DeclCXX.h:1221
SourceLocation getIdentLoc() const
Definition: Stmt.h:829
Represents a call to a C++ constructor.
Definition: ExprCXX.h:1177
SourceLocation getGotoLoc() const
Definition: Stmt.h:1299
Represents a C++ constructor within a class.
Definition: DeclCXX.h:2354
Represents a prvalue temporary that is written into memory so that a reference can bind to it...
Definition: ExprCXX.h:3951
bool isDefaultConstructor() const
Whether this constructor is a default constructor (C++ [class.ctor]p5), which can be used to default-...
Definition: DeclCXX.cpp:2077
VarDecl - An instance of this class is created to represent a variable declaration or definition...
Definition: Decl.h:771
#define CHECK_PERMISSIVE(x)
Defines the Objective-C statement AST node classes.
Represents an expression – generally a full-expression – that introduces cleanups to be run at the ...
Definition: ExprCXX.h:2920
Defines the clang::Expr interface and subclasses for C++ expressions.
const Stmt * getSubStmt() const
Definition: StmtObjC.h:356
IdentifierInfo * getIdentifier() const
getIdentifier - Get the identifier that names this declaration, if there is one.
Definition: Decl.h:232
LabelStmt - Represents a label, which has a substatement.
Definition: Stmt.h:813
Expr * GetTemporaryExpr() const
Retrieve the temporary-generating subexpression whose value will be materialized into a glvalue...
Definition: ExprCXX.h:3992
Represents Objective-C&#39;s @catch statement.
Definition: StmtObjC.h:74
IndirectGotoStmt - This represents an indirect goto.
Definition: Stmt.h:1284
child_range children()
Definition: Stmt.cpp:208
Scope - A scope is a transient data structure that is used while parsing the program.
Definition: Scope.h:39
const LangOptions & getLangOpts() const
Definition: Sema.h:1193
const ObjCAtCatchStmt * getCatchStmt(unsigned I) const
Retrieve a @catch statement.
Definition: StmtObjC.h:206
bool hasAttr() const
Definition: DeclBase.h:521
Sema - This implements semantic analysis and AST building for C.
Definition: Sema.h:274
SourceLocation getLocStart() const LLVM_READONLY
Definition: Stmt.h:962
bool isConstexpr() const
Definition: Stmt.h:957
BlockDecl - This represents a block literal declaration, which is like an unnamed FunctionDecl...
Definition: Decl.h:3595
Expr - This represents one expression.
Definition: Expr.h:106
const FunctionProtoType * T
const Stmt * getThen() const
Definition: Stmt.h:943
const CompoundStmt * getSynchBody() const
Definition: StmtObjC.h:282
Represents Objective-C&#39;s @synchronized statement.
Definition: StmtObjC.h:262
CXXTryStmt - A C++ try block, including all handlers.
Definition: StmtCXX.h:65
SourceLocation getAtTryLoc() const
Retrieve the location of the @ in the @try.
Definition: StmtObjC.h:193
QualType getType() const
Definition: Expr.h:128
LabelDecl * getLabel() const
Definition: Stmt.h:1261
StorageDuration getStorageDuration() const
Retrieve the storage duration for the materialized temporary.
Definition: ExprCXX.h:3995
const Stmt * getTryBody() const
Retrieve the @try body.
Definition: StmtObjC.h:197
std::pair< unsigned, unsigned > ScopePair
SourceLocation getAtLoc() const
Definition: StmtObjC.h:363
bool isTrivial() const
Whether this function is "trivial" in some specialized C++ senses.
Definition: Decl.h:1930
Encodes a location in the source.
const Stmt * getCatchBody() const
Definition: StmtObjC.h:90
unsigned getNumHandlers() const
Definition: StmtCXX.h:103
const SwitchCase * getSwitchCaseList() const
Definition: Stmt.h:1022
DeclStmt - Adaptor class for mixing declarations with statements and expressions. ...
Definition: Stmt.h:467
LabelDecl - Represents the declaration of a label.
Definition: Decl.h:427
SourceLocation getGotoLoc() const
Definition: Stmt.h:1264
bool isMSAsmLabel() const
Definition: Decl.h:462
DestructionKind isDestructedType() const
Returns a nonzero value if objects of this type require non-trivial work to clean up after...
Definition: Type.h:1052
SourceLocation getAtCatchLoc() const
Definition: StmtObjC.h:102
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Definition: Expr.cpp:216
Base class for declarations which introduce a typedef-name.
Definition: Decl.h:2720
LabelStmt * getStmt() const
Definition: Decl.h:452
VarDecl * getConditionVariable() const
Retrieve the variable declared in this "if" statement, if any.
Definition: Stmt.cpp:780
Dataflow Directional Tag Classes.
ArrayRef< Capture > captures() const
Definition: Decl.h:3720
StmtClass getStmtClass() const
Definition: Stmt.h:361
const CXXRecordDecl * getParent() const
Returns the parent of this method declaration, which is the class in which this method is defined...
Definition: DeclCXX.h:2043
SEHExceptStmt * getExceptHandler() const
Returns 0 if not defined.
Definition: Stmt.cpp:930
const Expr * getSynchExpr() const
Definition: StmtObjC.h:290
bool isObjCAvailabilityCheck() const
Definition: Stmt.cpp:799
SwitchStmt - This represents a &#39;switch&#39; stmt.
Definition: Stmt.h:983
unsigned getNumObjects() const
Definition: ExprCXX.h:2953
decl_range decls()
Definition: Stmt.h:515
Represents Objective-C&#39;s @finally statement.
Definition: StmtObjC.h:120
SEHFinallyStmt * getFinallyHandler() const
Definition: Stmt.cpp:934
GotoStmt - This represents a direct goto.
Definition: Stmt.h:1250
const SwitchCase * getNextSwitchCase() const
Definition: Stmt.h:688
static ScopePair GetDiagForGotoScopeDecl(Sema &S, const Decl *D)
GetDiagForGotoScopeDecl - If this decl induces a new goto scope, return a diagnostic that should be e...
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate.h) and friends (in DeclFriend.h).
static void DiagnoseIndirectJumpStmt(Sema &S, IndirectGotoStmt *Jump, LabelDecl *Target, bool &Diagnosed)
Produce primary diagnostic for an indirect jump statement.
CXXCatchStmt - This represents a C++ catch block.
Definition: StmtCXX.h:29
CleanupObject getObject(unsigned i) const
Definition: ExprCXX.h:2955
SourceLocation getAtSynchronizedLoc() const
Definition: StmtObjC.h:279
CompoundStmt * getTryBlock()
Definition: StmtCXX.h:96
Represents Objective-C&#39;s @try ... @catch ... @finally statement.
Definition: StmtObjC.h:154
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition: Stmt.cpp:245
unsigned getNumCatchStmts() const
Retrieve the number of @catch statements in this try-catch-finally block.
Definition: StmtObjC.h:203
QualType getType() const
Definition: Decl.h:602
const Expr * getCond() const
Definition: Stmt.h:941
ASTContext & Context
Definition: Sema.h:316
Automatic storage duration (most local variables).
Definition: Specifiers.h:275
SourceLocation getLocStart() const LLVM_READONLY
Definition: Stmt.cpp:257
SourceLocation getBegin() const
const LangOptions & getLangOpts() const
Definition: ASTContext.h:661
Represents Objective-C&#39;s @autoreleasepool Statement.
Definition: StmtObjC.h:345
CompoundStmt * getTryBlock() const
Definition: Stmt.h:1977
SourceLocation getLocation() const
Definition: DeclBase.h:407
static bool IsCXX98CompatWarning(Sema &S, unsigned InDiagNote)
Return true if a particular note should be downgraded to a compatibility warning in C++11 mode...