[cfe-commits] r107757 - in /cfe/trunk: lib/CodeGen/CGClass.cpp lib/CodeGen/CGException.cpp lib/CodeGen/CodeGenFunction.h test/CodeGenCXX/eh.cpp

John McCall rjmccall at apple.com
Tue Jul 6 23:56:46 PDT 2010


Author: rjmccall
Date: Wed Jul  7 01:56:46 2010
New Revision: 107757

URL: http://llvm.org/viewvc/llvm-project?rev=107757&view=rev
Log:
Teach function-try-blocks on constructors and destructors to implicitly
rethrow.  Fixes rdar://problem/7696603


Modified:
    cfe/trunk/lib/CodeGen/CGClass.cpp
    cfe/trunk/lib/CodeGen/CGException.cpp
    cfe/trunk/lib/CodeGen/CodeGenFunction.h
    cfe/trunk/test/CodeGenCXX/eh.cpp

Modified: cfe/trunk/lib/CodeGen/CGClass.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGClass.cpp?rev=107757&r1=107756&r2=107757&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGClass.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGClass.cpp Wed Jul  7 01:56:46 2010
@@ -606,11 +606,9 @@
 
   // Enter the function-try-block before the constructor prologue if
   // applicable.
-  CXXTryStmtInfo TryInfo;
   bool IsTryBody = (Body && isa<CXXTryStmt>(Body));
-
   if (IsTryBody)
-    TryInfo = EnterCXXTryStmt(*cast<CXXTryStmt>(Body));
+    EnterCXXTryStmt(*cast<CXXTryStmt>(Body), true);
 
   EHScopeStack::stable_iterator CleanupDepth = EHStack.stable_begin();
 
@@ -631,7 +629,7 @@
   PopCleanupBlocks(CleanupDepth);
 
   if (IsTryBody)
-    ExitCXXTryStmt(*cast<CXXTryStmt>(Body), TryInfo);
+    ExitCXXTryStmt(*cast<CXXTryStmt>(Body), true);
 }
 
 /// EmitCtorPrologue - This routine generates necessary code to initialize
@@ -671,11 +669,10 @@
   // anything else --- unless we're in a deleting destructor, in which
   // case we're just going to call the complete destructor and then
   // call operator delete() on the way out.
-  CXXTryStmtInfo TryInfo;
   bool isTryBody = (DtorType != Dtor_Deleting &&
                     Body && isa<CXXTryStmt>(Body));
   if (isTryBody)
-    TryInfo = EnterCXXTryStmt(*cast<CXXTryStmt>(Body));
+    EnterCXXTryStmt(*cast<CXXTryStmt>(Body), true);
 
   // Emit the destructor epilogue now.  If this is a complete
   // destructor with a function-try-block, perform the base epilogue
@@ -742,7 +739,7 @@
 
   // Exit the try if applicable.
   if (isTryBody)
-    ExitCXXTryStmt(*cast<CXXTryStmt>(Body), TryInfo);
+    ExitCXXTryStmt(*cast<CXXTryStmt>(Body), true);
 }
 
 /// EmitDtorEpilogue - Emit all code that comes at the end of class's

Modified: cfe/trunk/lib/CodeGen/CGException.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGException.cpp?rev=107757&r1=107756&r2=107757&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGException.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGException.cpp Wed Jul  7 01:56:46 2010
@@ -563,13 +563,12 @@
 }
 
 void CodeGenFunction::EmitCXXTryStmt(const CXXTryStmt &S) {
-  CXXTryStmtInfo Info = EnterCXXTryStmt(S);
+  EnterCXXTryStmt(S);
   EmitStmt(S.getTryBlock());
-  ExitCXXTryStmt(S, Info);
+  ExitCXXTryStmt(S);
 }
 
-CodeGenFunction::CXXTryStmtInfo
-CodeGenFunction::EnterCXXTryStmt(const CXXTryStmt &S) {
+void CodeGenFunction::EnterCXXTryStmt(const CXXTryStmt &S, bool IsFnTryBlock) {
   unsigned NumHandlers = S.getNumHandlers();
   EHCatchScope *CatchScope = EHStack.pushCatch(NumHandlers);
 
@@ -593,8 +592,6 @@
       CatchScope->setCatchAllHandler(I, Handler);
     }
   }
-  
-  return CXXTryStmtInfo();
 }
 
 /// Check whether this is a non-EH scope, i.e. a scope which doesn't
@@ -1103,8 +1100,7 @@
   CGF.EmitLocalBlockVarDecl(*CatchParam, &InitCatchParam);
 }
 
-void CodeGenFunction::ExitCXXTryStmt(const CXXTryStmt &S,
-                                     CXXTryStmtInfo TryInfo) {
+void CodeGenFunction::ExitCXXTryStmt(const CXXTryStmt &S, bool IsFnTryBlock) {
   unsigned NumHandlers = S.getNumHandlers();
   EHCatchScope &CatchScope = cast<EHCatchScope>(*EHStack.begin());
   assert(CatchScope.getNumHandlers() == NumHandlers);
@@ -1123,6 +1119,12 @@
   if (HaveInsertPoint())
     Builder.CreateBr(ContBB);
 
+  // Determine if we need an implicit rethrow for all these catch handlers.
+  bool ImplicitRethrow = false;
+  if (IsFnTryBlock)
+    ImplicitRethrow = isa<CXXDestructorDecl>(CurCodeDecl) ||
+                      isa<CXXConstructorDecl>(CurCodeDecl);
+
   for (unsigned I = 0; I != NumHandlers; ++I) {
     llvm::BasicBlock *CatchBlock = Handlers[I].Block;
     EmitBlock(CatchBlock);
@@ -1137,6 +1139,14 @@
     // Initialize the catch variable and set up the cleanups.
     BeginCatch(*this, C);
 
+    // If there's an implicit rethrow, push a normal "cleanup" to call
+    // _cxa_rethrow.  This needs to happen before _cxa_end_catch is
+    // called.
+    if (ImplicitRethrow) {
+      CleanupBlock Rethrow(*this, NormalCleanup);
+      EmitCallOrInvoke(getReThrowFn(*this), 0, 0);
+    }
+
     // Perform the body of the catch.
     EmitStmt(C->getHandlerBlock());
 

Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=107757&r1=107756&r2=107757&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Wed Jul  7 01:56:46 2010
@@ -1102,9 +1102,8 @@
   void EmitObjCAtSynchronizedStmt(const ObjCAtSynchronizedStmt &S);
 
   llvm::Constant *getUnwindResumeOrRethrowFn();
-  struct CXXTryStmtInfo {};
-  CXXTryStmtInfo EnterCXXTryStmt(const CXXTryStmt &S);
-  void ExitCXXTryStmt(const CXXTryStmt &S, CXXTryStmtInfo Info);
+  void EnterCXXTryStmt(const CXXTryStmt &S, bool IsFnTryBlock = false);
+  void ExitCXXTryStmt(const CXXTryStmt &S, bool IsFnTryBlock = false);
 
   void EmitCXXTryStmt(const CXXTryStmt &S);
   

Modified: cfe/trunk/test/CodeGenCXX/eh.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/eh.cpp?rev=107757&r1=107756&r2=107757&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/eh.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/eh.cpp Wed Jul  7 01:56:46 2010
@@ -193,3 +193,30 @@
     }
   }
 }
+
+// Constructor function-try-block must rethrow on fallthrough.
+// rdar://problem/7696603
+namespace test9 {
+  void opaque();
+
+  struct A { A(); };
+
+  // CHECK:      define void @_ZN5test91AC1Ev
+  // CHECK:      call void @_ZN5test91AC2Ev
+  // CHECK-NEXT: ret void
+
+  // CHECK: define void @_ZN5test91AC2Ev(
+  A::A() try {
+  // CHECK:      invoke void @_ZN5test96opaqueEv()
+    opaque();
+  } catch (int x) {
+  // CHECK:      call i8* @__cxa_begin_catch
+  // CHECK:      invoke void @_ZN5test96opaqueEv()
+  // CHECK:      invoke void @__cxa_rethrow()
+    opaque();
+  }
+
+  // landing pad from first call to invoke
+  // CHECK:      call i8* @llvm.eh.exception
+  // CHECK:      call i32 (i8*, i8*, ...)* @llvm.eh.selector(i8* {{.*}}, i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*), i8* bitcast (i8** @_ZTIi to i8*), i8* null)
+}





More information about the cfe-commits mailing list