[cfe-commits] r117539 - in /cfe/trunk: include/clang/AST/Stmt.h include/clang/Basic/DiagnosticSemaKinds.td lib/AST/Stmt.cpp lib/CodeGen/CGStmt.cpp lib/Sema/JumpDiagnostics.cpp test/Sema/scope-check.c test/SemaCXX/scope-check.cpp

John McCall rjmccall at apple.com
Thu Oct 28 01:53:48 PDT 2010


Author: rjmccall
Date: Thu Oct 28 03:53:48 2010
New Revision: 117539

URL: http://llvm.org/viewvc/llvm-project?rev=117539&view=rev
Log:
Implement an indirect-goto optimization for goto *&&lbl and respect this
in the scope checker.  With that done, turn an indirect goto into a
protected scope into a hard error;  otherwise IR generation has to start
worrying about declarations not dominating their scopes, as exemplified
in PR8473.

If this really affects anyone, I can probably adjust this to only hard-error
on possible indirect gotos into VLA scopes rather than arbitrary scopes.
But we'll see how people cope with the aggressive change on the marginal
feature.


Modified:
    cfe/trunk/include/clang/AST/Stmt.h
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/lib/AST/Stmt.cpp
    cfe/trunk/lib/CodeGen/CGStmt.cpp
    cfe/trunk/lib/Sema/JumpDiagnostics.cpp
    cfe/trunk/test/Sema/scope-check.c
    cfe/trunk/test/SemaCXX/scope-check.cpp

Modified: cfe/trunk/include/clang/AST/Stmt.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Stmt.h?rev=117539&r1=117538&r2=117539&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Stmt.h (original)
+++ cfe/trunk/include/clang/AST/Stmt.h Thu Oct 28 03:53:48 2010
@@ -1005,10 +1005,17 @@
   void setStarLoc(SourceLocation L) { StarLoc = L; }
   SourceLocation getStarLoc() const { return StarLoc; }
 
-  Expr *getTarget();
-  const Expr *getTarget() const;
+  Expr *getTarget() { return reinterpret_cast<Expr*>(Target); }
+  const Expr *getTarget() const {return reinterpret_cast<const Expr*>(Target);}
   void setTarget(Expr *E) { Target = reinterpret_cast<Stmt*>(E); }
 
+  /// getConstantTarget - Returns the fixed target of this indirect
+  /// goto, if one exists.
+  LabelStmt *getConstantTarget();
+  const LabelStmt *getConstantTarget() const {
+    return const_cast<IndirectGotoStmt*>(this)->getConstantTarget();
+  }
+
   virtual SourceRange getSourceRange() const {
     return SourceRange(GotoLoc, Target->getLocEnd());
   }

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=117539&r1=117538&r2=117539&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Thu Oct 28 03:53:48 2010
@@ -1980,9 +1980,8 @@
   "switch case is in protected scope">;
 def err_indirect_goto_without_addrlabel : Error<
   "indirect goto in function with no address-of-label expressions">;
-def warn_indirect_goto_in_protected_scope : Warning<
-  "indirect goto might cross protected scopes">,
-  InGroup<DiagGroup<"label-address-scope">>;
+def err_indirect_goto_in_protected_scope : Error<
+  "indirect goto might cross protected scopes">;
 def note_indirect_goto_target : Note<"possible target of indirect goto">;
 def note_protected_by_variable_init : Note<
   "jump bypasses variable initialization">;

Modified: cfe/trunk/lib/AST/Stmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Stmt.cpp?rev=117539&r1=117538&r2=117539&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Stmt.cpp (original)
+++ cfe/trunk/lib/AST/Stmt.cpp Thu Oct 28 03:53:48 2010
@@ -669,8 +669,12 @@
 Stmt::child_iterator GotoStmt::child_end() { return child_iterator(); }
 
 // IndirectGotoStmt
-Expr* IndirectGotoStmt::getTarget() { return cast<Expr>(Target); }
-const Expr* IndirectGotoStmt::getTarget() const { return cast<Expr>(Target); }
+LabelStmt *IndirectGotoStmt::getConstantTarget() {
+  if (AddrLabelExpr *E =
+        dyn_cast<AddrLabelExpr>(getTarget()->IgnoreParenImpCasts()))
+    return E->getLabel();
+  return 0;
+}
 
 Stmt::child_iterator IndirectGotoStmt::child_begin() { return &Target; }
 Stmt::child_iterator IndirectGotoStmt::child_end() { return &Target+1; }

Modified: cfe/trunk/lib/CodeGen/CGStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGStmt.cpp?rev=117539&r1=117538&r2=117539&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGStmt.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGStmt.cpp Thu Oct 28 03:53:48 2010
@@ -297,6 +297,11 @@
 
 
 void CodeGenFunction::EmitIndirectGotoStmt(const IndirectGotoStmt &S) {
+  if (const LabelStmt *Target = S.getConstantTarget()) {
+    EmitBranchThroughCleanup(getJumpDestForLabel(Target));
+    return;
+  }
+
   // Ensure that we have an i8* for our PHI node.
   llvm::Value *V = Builder.CreateBitCast(EmitScalarExpr(S.getTarget()),
                                          llvm::Type::getInt8PtrTy(VMContext),

Modified: cfe/trunk/lib/Sema/JumpDiagnostics.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/JumpDiagnostics.cpp?rev=117539&r1=117538&r2=117539&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/JumpDiagnostics.cpp (original)
+++ cfe/trunk/lib/Sema/JumpDiagnostics.cpp Thu Oct 28 03:53:48 2010
@@ -186,6 +186,17 @@
     break;
 
   case Stmt::IndirectGotoStmtClass:
+    // "goto *&&lbl;" is a special case which we treat as equivalent
+    // to a normal goto.  In addition, we don't calculate scope in the
+    // operand (to avoid recording the address-of-label use), which
+    // works only because of the restricted set of expressions which
+    // we detect as constant targets.
+    if (cast<IndirectGotoStmt>(S)->getConstantTarget()) {
+      LabelAndGotoScopes[S] = ParentScope;
+      Jumps.push_back(S);
+      return;
+    }
+
     LabelAndGotoScopes[S] = ParentScope;
     IndirectJumps.push_back(cast<IndirectGotoStmt>(S));
     break;
@@ -341,6 +352,14 @@
       continue;
     }
 
+    // We only get indirect gotos here when they have a constant target.
+    if (IndirectGotoStmt *IGS = dyn_cast<IndirectGotoStmt>(Jump)) {
+      LabelStmt *Target = IGS->getConstantTarget();
+      CheckJump(IGS, Target, IGS->getGotoLoc(),
+                diag::err_goto_into_protected_scope);
+      continue;
+    }
+
     SwitchStmt *SS = cast<SwitchStmt>(Jump);
     for (SwitchCase *SC = SS->getSwitchCaseList(); SC;
          SC = SC->getNextSwitchCase()) {
@@ -497,7 +516,7 @@
                                             unsigned TargetScope) {
   assert(JumpScope != TargetScope);
 
-  S.Diag(Jump->getGotoLoc(), diag::warn_indirect_goto_in_protected_scope);
+  S.Diag(Jump->getGotoLoc(), diag::err_indirect_goto_in_protected_scope);
   S.Diag(Target->getIdentLoc(), diag::note_indirect_goto_target);
 
   unsigned Common = GetDeepestCommonScope(JumpScope, TargetScope);

Modified: cfe/trunk/test/Sema/scope-check.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/scope-check.c?rev=117539&r1=117538&r2=117539&view=diff
==============================================================================
--- cfe/trunk/test/Sema/scope-check.c (original)
+++ cfe/trunk/test/Sema/scope-check.c Thu Oct 28 03:53:48 2010
@@ -133,7 +133,7 @@
 void test9(int n, void *P) {
   int Y;
   int Z = 4;
-  goto *P;  // expected-warning {{indirect goto might cross protected scopes}}
+  goto *P;  // expected-error {{indirect goto might cross protected scopes}}
 
 L2: ;
   int a[n]; // expected-note {{jump bypasses initialization of variable length array}}
@@ -199,3 +199,33 @@
  a0: ;
   static void *ps[] = { &&a0 };
 }
+
+int test14(int n) {
+  static void *ps[] = { &&a0, &&a1 };
+  if (n < 0)
+    goto *&&a0;
+
+  if (n > 0) {
+    int vla[n];
+   a1:
+    vla[n-1] = 0;
+  }
+ a0:
+  return 0;
+}
+
+
+// PR8473: IR gen can't deal with indirect gotos past VLA
+// initialization, so that really needs to be a hard error.
+void test15(int n, void *pc) {
+  static const void *addrs[] = { &&L1, &&L2 };
+
+  goto *pc; // expected-error {{indirect goto might cross protected scope}}
+
+ L1:
+  {
+    char vla[n]; // expected-note {{jump bypasses initialization}}
+   L2: // expected-note {{possible target}}
+    vla[0] = 'a';
+  }
+}

Modified: cfe/trunk/test/SemaCXX/scope-check.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/scope-check.cpp?rev=117539&r1=117538&r2=117539&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/scope-check.cpp (original)
+++ cfe/trunk/test/SemaCXX/scope-check.cpp Thu Oct 28 03:53:48 2010
@@ -66,7 +66,7 @@
 
     C c0;
 
-    goto *ip; // expected-warning {{indirect goto might cross protected scopes}}
+    goto *ip; // expected-error {{indirect goto might cross protected scopes}}
     C c1; // expected-note {{jump bypasses variable initialization}}
   lbl1: // expected-note {{possible target of indirect goto}}
     return 0;
@@ -90,7 +90,7 @@
     if (ip[1]) {
       D d; // expected-note {{jump exits scope of variable with non-trivial destructor}}
       ip += 2;
-      goto *ip; // expected-warning {{indirect goto might cross protected scopes}}
+      goto *ip; // expected-error {{indirect goto might cross protected scopes}}
     }
     return 1;
   }





More information about the cfe-commits mailing list