]> granicus.if.org Git - clang/commitdiff
Only run the jump-checker if there's a branch-protected scope *and* there's
authorJohn McCall <rjmccall@apple.com>
Sun, 1 Aug 2010 00:26:45 +0000 (00:26 +0000)
committerJohn McCall <rjmccall@apple.com>
Sun, 1 Aug 2010 00:26:45 +0000 (00:26 +0000)
a switch or goto somewhere in the function.  Indirect gotos trigger the
jump-checker regardless, because the conditions there are slightly more
elaborate and it's too marginal a case to be worth optimizing.

Turns off the jump-checker in a lot of cases in C++.  rdar://problem/7702918

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@109962 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/Sema.cpp
lib/Sema/Sema.h
lib/Sema/SemaDecl.cpp
lib/Sema/SemaStmt.cpp
test/Analysis/misc-ps.m
test/CodeGen/statements.c

index 815eba051f7f14454b88d1d6af8ffea255ad6a99..a9a4f5290cf9330f48a7be646b18e683888ca857 100644 (file)
@@ -31,7 +31,10 @@ using namespace clang;
 FunctionScopeInfo::~FunctionScopeInfo() { }
 
 void FunctionScopeInfo::Clear(unsigned NumErrors) {
-  NeedsScopeChecking = false;
+  HasBranchProtectedScope = false;
+  HasBranchIntoScope = false;
+  HasIndirectGoto = false;
+  
   LabelMap.clear();
   SwitchStack.clear();
   Returns.clear();
index b0b777073c7eccd9fcaa8d11d698d367cf4401ec..ecd167d9a0752105825c89d47577ad2a7b7fc1ed 100644 (file)
@@ -116,11 +116,15 @@ struct FunctionScopeInfo {
   /// a block.
   bool IsBlockInfo;
 
-  /// \brief Set true when a function, method contains a VLA or ObjC try block,
-  /// which introduce scopes that need to be checked for goto conditions.  If a
-  /// function does not contain this, then it need not have the jump checker run
-  /// on it.
-  bool NeedsScopeChecking;
+  /// \brief Whether this function contains a VLA, @try, try, C++
+  /// initializer, or anything else that can't be jumped past.
+  bool HasBranchProtectedScope;
+
+  /// \brief Whether this function contains any switches or direct gotos.
+  bool HasBranchIntoScope;
+
+  /// \brief Whether this function contains any indirect gotos.
+  bool HasIndirectGoto;
 
   /// \brief The number of errors that had occurred before starting this
   /// function or block.
@@ -139,9 +143,17 @@ struct FunctionScopeInfo {
   /// block, if there is any chance of applying the named return value
   /// optimization.
   llvm::SmallVector<ReturnStmt *, 4> Returns;
+
+  bool NeedsScopeChecking() const {
+    return HasIndirectGoto ||
+          (HasBranchProtectedScope && HasBranchIntoScope);
+  }
   
   FunctionScopeInfo(unsigned NumErrors)
-    : IsBlockInfo(false), NeedsScopeChecking(false),
+    : IsBlockInfo(false),
+      HasBranchProtectedScope(false),
+      HasBranchIntoScope(false),
+      HasIndirectGoto(false),
       NumErrorsAtStartOfFunction(NumErrors) { }
 
   virtual ~FunctionScopeInfo();
@@ -706,13 +718,28 @@ public:
 
   /// \brief Determine whether the current function or block needs scope
   /// checking.
-  bool &FunctionNeedsScopeChecking() {
-    if (FunctionScopes.empty())
-      return TopFunctionScope.NeedsScopeChecking;
+  bool FunctionNeedsScopeChecking() {
+    if (!FunctionScopes.empty())
+      return FunctionScopes.back()->NeedsScopeChecking();
+    return false;
+  }
 
-    return FunctionScopes.back()->NeedsScopeChecking;
+  void setFunctionHasBranchIntoScope() {
+    if (!FunctionScopes.empty())
+      FunctionScopes.back()->HasBranchIntoScope = true;
   }
 
+  void setFunctionHasBranchProtectedScope() {
+    if (!FunctionScopes.empty())
+      FunctionScopes.back()->HasBranchProtectedScope = true;
+  }
+
+  void setFunctionHasIndirectGoto() {
+    if (!FunctionScopes.empty())
+      FunctionScopes.back()->HasIndirectGoto = true;
+  }
+  
+
   bool hasAnyErrorsInThisFunction() const;
 
   /// \brief Retrieve the current block, if any.
index d6d13384b2c425d1a7e450b168f78ad4cf605c08..a6ba359972f9d83e765d0fe91e0c04fdb017e665 100644 (file)
@@ -2380,7 +2380,7 @@ Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC,
   // then it shall have block scope.
   QualType T = NewTD->getUnderlyingType();
   if (T->isVariablyModifiedType()) {
-    FunctionNeedsScopeChecking() = true;
+    setFunctionHasBranchProtectedScope();
 
     if (S->getFnParent() == 0) {
       bool SizeIsNegative;
@@ -2794,12 +2794,8 @@ void Sema::CheckVariableDeclaration(VarDecl *NewVD,
   bool isVM = T->isVariablyModifiedType();
   if (isVM || NewVD->hasAttr<CleanupAttr>() ||
       NewVD->hasAttr<BlocksAttr>() ||
-      // FIXME: We need to diagnose jumps passed initialized variables in C++.
-      // However, this turns on the scope checker for everything with a variable
-      // which may impact compile time.  See if we can find a better solution
-      // to this, perhaps only checking functions that contain gotos in C++?
       (LangOpts.CPlusPlus && NewVD->hasLocalStorage()))
-    FunctionNeedsScopeChecking() = true;
+    setFunctionHasBranchProtectedScope();
 
   if ((isVM && NewVD->hasLinkage()) ||
       (T->isVariableArrayType() && NewVD->hasGlobalStorage())) {
index b4d207eab1138fee2c6792ce956456ca50bccbb5..c3adb6c8017be192af0c49ac5b70027df993f3ac 100644 (file)
@@ -441,6 +441,8 @@ Sema::ActOnStartOfSwitchStmt(SourceLocation SwitchLoc, ExprArg Cond,
     if (!CondExpr)
       return StmtError();
   }
+
+  setFunctionHasBranchIntoScope();
     
   SwitchStmt *SS = new (Context) SwitchStmt(Context, ConditionVar, CondExpr);
   getSwitchStack().push_back(SS);
@@ -962,6 +964,8 @@ Sema::ActOnGotoStmt(SourceLocation GotoLoc, SourceLocation LabelLoc,
   // Look up the record for this label identifier.
   LabelStmt *&LabelDecl = getLabelMap()[LabelII];
 
+  setFunctionHasBranchIntoScope();
+
   // If we haven't seen this label yet, create a forward reference.
   if (LabelDecl == 0)
     LabelDecl = new (Context) LabelStmt(LabelLoc, LabelII, 0);
@@ -982,6 +986,9 @@ Sema::ActOnIndirectGotoStmt(SourceLocation GotoLoc, SourceLocation StarLoc,
     if (DiagnoseAssignmentResult(ConvTy, StarLoc, DestTy, ETy, E, AA_Passing))
       return StmtError();
   }
+
+  setFunctionHasIndirectGoto();
+
   return Owned(new (Context) IndirectGotoStmt(GotoLoc, StarLoc, E));
 }
 
@@ -1504,7 +1511,7 @@ Sema::ActOnObjCAtFinallyStmt(SourceLocation AtLoc, StmtArg Body) {
 Action::OwningStmtResult
 Sema::ActOnObjCAtTryStmt(SourceLocation AtLoc, StmtArg Try, 
                          MultiStmtArg CatchStmts, StmtArg Finally) {
-  FunctionNeedsScopeChecking() = true;
+  setFunctionHasBranchProtectedScope();
   unsigned NumCatchStmts = CatchStmts.size();
   return Owned(ObjCAtTryStmt::Create(Context, AtLoc, Try.takeAs<Stmt>(),
                                      (Stmt **)CatchStmts.release(),
@@ -1549,7 +1556,7 @@ Sema::ActOnObjCAtThrowStmt(SourceLocation AtLoc, ExprArg Throw,
 Action::OwningStmtResult
 Sema::ActOnObjCAtSynchronizedStmt(SourceLocation AtLoc, ExprArg SynchExpr,
                                   StmtArg SynchBody) {
-  FunctionNeedsScopeChecking() = true;
+  setFunctionHasBranchProtectedScope();
 
   // Make sure the expression type is an ObjC pointer or "void *".
   Expr *SyncExpr = static_cast<Expr*>(SynchExpr.get());
@@ -1658,13 +1665,14 @@ Sema::ActOnCXXTryBlock(SourceLocation TryLoc, StmtArg TryBlock,
     }
   }
 
+  setFunctionHasBranchProtectedScope();
+
   // FIXME: We should detect handlers that cannot catch anything because an
   // earlier handler catches a superclass. Need to find a method that is not
   // quadratic for this.
   // Neither of these are explicitly forbidden, but every compiler detects them
   // and warns.
 
-  FunctionNeedsScopeChecking() = true;
   RawHandlers.release();
   return Owned(CXXTryStmt::Create(Context, TryLoc,
                                   static_cast<Stmt*>(TryBlock.release()),
index be7f450de6d85185811870818b7a67d76015207a..a362211049243a954fa822b5999b074cd5b44ce8 100644 (file)
@@ -298,6 +298,7 @@ void rdar_6777209(char *p) {
 typedef void *Opcode;
 Opcode pr_4033_getOpcode();
 void pr_4033(void) {
+  void *lbl = &&next_opcode;
 next_opcode:
   {
     Opcode op = pr_4033_getOpcode();
index 7ed82add69b0a9f488cf72a4528b3fafea36eca8..76983cc4935dced12b48f77ec49e195885075b94 100644 (file)
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -Wreturn-type %s -emit-llvm
+// RUN: %clang_cc1 -Wreturn-type %s -emit-llvm
 
 void test1(int x) {
 switch (x) {
@@ -31,5 +31,10 @@ static long y = &&baz;
 }
 
 // PR3869
-int test5(long long b) { goto *b; }
+int test5(long long b) {
+  static void *lbls[] = { &&lbl };
+  goto *b;
+ lbl:
+  return 0;
+}