[cfe-commits] r65678 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.def lib/Sema/Sema.h lib/Sema/SemaDecl.cpp test/Sema/scope-check.c

Eli Friedman eli.friedman at gmail.com
Fri Feb 27 21:41:14 PST 2009


Author: efriedma
Date: Fri Feb 27 23:41:13 2009
New Revision: 65678

URL: http://llvm.org/viewvc/llvm-project?rev=65678&view=rev
Log:
Start of checking for gotos which jump to an illegal destination.  
As far as I know, this catches all cases of jumping into the scope of a 
variable with a variably modified type (excluding statement 
expressions) in C.  This is missing some stuff we probably want to check
(other kinds of variably modified declarations, statement expressions, 
indirect gotos/addresses of labels in a scope, ObjC @try/@finally, cleanup 
attribute), the diagnostics aren't very good, and it's not particularly 
efficient, but it's a decent start.

This patch is a slightly modified version of the patch I attached to
PR3259, and it fixes that bug.  I was sort of planning on improving 
it, but I think it's okay as-is, especially since it looks like CodeGen 
doesn't have any use for this sort of data structure.  The only 
significant change I can think of from the version I attached to PR3259 
is that this version skips running the checking code when a function 
doesn't contain any labels.

This patch doesn't cover case statements, which also need similar 
checking; I'm not sure how we should deal with that. Extending the goto 
checking to also check case statements wouldn't be too hard; it's just a 
matter of keeping track of the scope of the closest switch and checking that
the scope of every case is the same as the scope of the switch.  That said, 
it would likely be a performance hit to run this check on every 
function (it's an extra pass over the entire function), so we probably want
some other solution.


Added:
    cfe/trunk/test/Sema/scope-check.c
Modified:
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaDecl.cpp

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def?rev=65678&r1=65677&r2=65678&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def Fri Feb 27 23:41:13 2009
@@ -744,6 +744,9 @@
 DIAG(err_undeclared_label_use, ERROR,
      "use of undeclared label '%0'")
 
+DIAG(err_goto_into_scope, ERROR,
+     "illegal jump (scoping violation)")
+
 DIAG(ext_implicit_function_decl, EXTENSION,
      "implicit declaration of function %0 is invalid in C99")
 

Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=65678&r1=65677&r2=65678&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Fri Feb 27 23:41:13 2009
@@ -383,6 +383,19 @@
     return IdResolver.isDeclInScope(D, Ctx, Context, S);
   }
 
+
+  void RecursiveCalcJumpScopes(llvm::DenseMap<Stmt*, void*>& LabelScopeMap,
+                               llvm::DenseMap<void*, Stmt*>& PopScopeMap,
+                               llvm::DenseMap<Stmt*, void*>& GotoScopeMap,
+                               std::vector<void*>& ScopeStack,
+                               Stmt* CurStmt);
+
+  void RecursiveCalcLabelScopes(llvm::DenseMap<Stmt*, void*>& LabelScopeMap,
+                                llvm::DenseMap<void*, Stmt*>& PopScopeMap,
+                                std::vector<void*>& ScopeStack,
+                                Stmt* CurStmt,
+                                Stmt* ParentCompoundStmt);
+
   /// Subroutines of ActOnDeclarator().
   TypedefDecl *ParseTypedefDecl(Scope *S, Declarator &D, QualType T,
                                 Decl *LastDecl);

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=65678&r1=65677&r2=65678&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Fri Feb 27 23:41:13 2009
@@ -2496,6 +2496,79 @@
   return FD;
 }
 
+static bool StatementCreatesScope(Stmt* S) {
+  bool result = false;
+  if (DeclStmt* DS = dyn_cast<DeclStmt>(S)) {
+    for (DeclStmt::decl_iterator i = DS->decl_begin();
+         i != DS->decl_end(); ++i) {
+      if (VarDecl* D = dyn_cast<VarDecl>(*i)) {
+        result |= D->getType()->isVariablyModifiedType();
+      }
+    }
+  }
+
+  return result;
+}
+
+void Sema::RecursiveCalcLabelScopes(llvm::DenseMap<Stmt*, void*>& LabelScopeMap,
+                                    llvm::DenseMap<void*, Stmt*>& PopScopeMap,
+                                    std::vector<void*>& ScopeStack,
+                                    Stmt* CurStmt,
+                                    Stmt* ParentCompoundStmt) {
+  for (Stmt::child_iterator i = CurStmt->child_begin();
+       i != CurStmt->child_end(); ++i) {
+    if (!*i) continue;
+    if (StatementCreatesScope(*i))  {
+      ScopeStack.push_back(*i);
+      PopScopeMap[*i] = ParentCompoundStmt;
+    } else if (isa<LabelStmt>(CurStmt)) {
+      LabelScopeMap[CurStmt] = ScopeStack.size() ? ScopeStack.back() : 0;
+    }
+    if (isa<DeclStmt>(*i)) continue;
+    Stmt* CurCompound = isa<CompoundStmt>(*i) ? *i : ParentCompoundStmt;
+    RecursiveCalcLabelScopes(LabelScopeMap, PopScopeMap, ScopeStack,
+                             *i, CurCompound);
+  }
+
+  while (ScopeStack.size() && PopScopeMap[ScopeStack.back()] == CurStmt) {
+    ScopeStack.pop_back();
+  }
+}
+
+void Sema::RecursiveCalcJumpScopes(llvm::DenseMap<Stmt*, void*>& LabelScopeMap,
+                                   llvm::DenseMap<void*, Stmt*>& PopScopeMap,
+                                   llvm::DenseMap<Stmt*, void*>& GotoScopeMap,
+                                   std::vector<void*>& ScopeStack,
+                                   Stmt* CurStmt) {
+  for (Stmt::child_iterator i = CurStmt->child_begin();
+       i != CurStmt->child_end(); ++i) {
+    if (!*i) continue;
+    if (StatementCreatesScope(*i))  {
+      ScopeStack.push_back(*i);
+    } else if (GotoStmt* GS = dyn_cast<GotoStmt>(*i)) {
+      void* LScope = LabelScopeMap[GS->getLabel()];
+      if (LScope) {
+        bool foundScopeInStack = false;
+        for (unsigned i = ScopeStack.size(); i > 0; --i) {
+          if (LScope == ScopeStack[i-1]) {
+            foundScopeInStack = true;
+            break;
+          }
+        }
+        if (!foundScopeInStack) {
+          Diag(GS->getSourceRange().getBegin(), diag::err_goto_into_scope);
+        }
+      }
+    }
+    if (isa<DeclStmt>(*i)) continue;
+    RecursiveCalcJumpScopes(LabelScopeMap, PopScopeMap, GotoScopeMap, ScopeStack, *i);
+  }
+
+  while (ScopeStack.size() && PopScopeMap[ScopeStack.back()] == CurStmt) {
+    ScopeStack.pop_back();
+  }
+}
+
 Sema::DeclTy *Sema::ActOnFinishFunctionBody(DeclTy *D, StmtArg BodyArg) {
   Decl *dcl = static_cast<Decl *>(D);
   Stmt *Body = static_cast<Stmt*>(BodyArg.release());
@@ -2511,7 +2584,8 @@
   }
   PopDeclContext();
   // Verify and clean out per-function state.
-  
+
+  bool HaveLabels = !LabelMap.empty();
   // Check goto/label use.
   for (llvm::DenseMap<IdentifierInfo*, LabelStmt*>::iterator
        I = LabelMap.begin(), E = LabelMap.end(); I != E; ++I) {
@@ -2542,7 +2616,18 @@
     }
   }
   LabelMap.clear();
-  
+
+  if (!Body) return D;
+
+  if (HaveLabels) {
+    llvm::DenseMap<Stmt*, void*> LabelScopeMap;
+    llvm::DenseMap<void*, Stmt*> PopScopeMap;
+    llvm::DenseMap<Stmt*, void*> GotoScopeMap;
+    std::vector<void*> ScopeStack;
+    RecursiveCalcLabelScopes(LabelScopeMap, PopScopeMap, ScopeStack, Body, Body);
+    RecursiveCalcJumpScopes(LabelScopeMap, PopScopeMap, GotoScopeMap, ScopeStack, Body);
+  }
+
   return D;
 }
 

Added: cfe/trunk/test/Sema/scope-check.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/scope-check.c?rev=65678&view=auto

==============================================================================
--- cfe/trunk/test/Sema/scope-check.c (added)
+++ cfe/trunk/test/Sema/scope-check.c Fri Feb 27 23:41:13 2009
@@ -0,0 +1,8 @@
+// RUN: clang -fsyntax-only -verify %s
+
+int test1(int x) {
+  goto L; // expected-error{{illegal jump}}
+  int a[x];
+  L:
+  return sizeof a;
+}





More information about the cfe-commits mailing list