<div dir="ltr">Would've been good to land the move separately from the behavior change…</div><div class="gmail_extra"><br><div class="gmail_quote">On Tue, Mar 3, 2015 at 11:21 AM, Reid Kleckner <span dir="ltr"><<a href="mailto:reid@kleckner.net" target="_blank">reid@kleckner.net</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: rnk<br>
Date: Tue Mar  3 13:21:04 2015<br>
New Revision: 231105<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=231105&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=231105&view=rev</a><br>
Log:<br>
Split catch IRgen into ItaniumCXXABI and MicrosoftCXXABI<br>
<br>
Use llvm.eh.begincatch for Microsoft-style catches.<br>
<br>
This moves lots of CGException code into ItaniumCXXABI. Sorry for the<br>
blame pain.<br>
<br>
Added:<br>
    cfe/trunk/test/CodeGenCXX/microsoft-abi-eh-catch.cpp<br>
    cfe/trunk/test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp<br>
      - copied, changed from r231098, cfe/trunk/test/CodeGenCXX/microsoft-abi-exceptions.cpp<br>
Removed:<br>
    cfe/trunk/test/CodeGenCXX/microsoft-abi-exceptions.cpp<br>
Modified:<br>
    cfe/trunk/lib/CodeGen/CGCXXABI.cpp<br>
    cfe/trunk/lib/CodeGen/CGCXXABI.h<br>
    cfe/trunk/lib/CodeGen/CGException.cpp<br>
    cfe/trunk/lib/CodeGen/CodeGenModule.h<br>
    cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp<br>
    cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp<br>
    cfe/trunk/test/CodeGenCXX/microsoft-abi-try-throw.cpp<br>
<br>
Modified: cfe/trunk/lib/CodeGen/CGCXXABI.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCXXABI.cpp?rev=231105&r1=231104&r2=231105&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCXXABI.cpp?rev=231105&r1=231104&r2=231105&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/CodeGen/CGCXXABI.cpp (original)<br>
+++ cfe/trunk/lib/CodeGen/CGCXXABI.cpp Tue Mar  3 13:21:04 2015<br>
@@ -302,3 +302,10 @@ CGCXXABI::EmitCtorCompleteObjectHandler(<br>
 bool CGCXXABI::NeedsVTTParameter(GlobalDecl GD) {<br>
   return false;<br>
 }<br>
+<br>
+llvm::CallInst *<br>
+CGCXXABI::emitTerminateForUnexpectedException(CodeGenFunction &CGF,<br>
+                                              llvm::Value *Exn) {<br>
+  // Just call std::terminate and ignore the violating exception.<br>
+  return CGF.EmitNounwindRuntimeCall(CGF.CGM.getTerminateFn());<br>
+}<br>
<br>
Modified: cfe/trunk/lib/CodeGen/CGCXXABI.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCXXABI.h?rev=231105&r1=231104&r2=231105&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCXXABI.h?rev=231105&r1=231104&r2=231105&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/CodeGen/CGCXXABI.h (original)<br>
+++ cfe/trunk/lib/CodeGen/CGCXXABI.h Tue Mar  3 13:21:04 2015<br>
@@ -22,6 +22,7 @@ namespace llvm {<br>
 class Constant;<br>
 class Type;<br>
 class Value;<br>
+class CallInst;<br>
 }<br>
<br>
 namespace clang {<br>
@@ -215,6 +216,12 @@ public:<br>
                                        const CXXDestructorDecl *Dtor) = 0;<br>
   virtual void emitRethrow(CodeGenFunction &CGF, bool isNoReturn) = 0;<br>
<br>
+  virtual void emitBeginCatch(CodeGenFunction &CGF, const CXXCatchStmt *C) = 0;<br>
+<br>
+  virtual llvm::CallInst *<br>
+  emitTerminateForUnexpectedException(CodeGenFunction &CGF,<br>
+                                      llvm::Value *Exn);<br>
+<br>
   virtual llvm::Constant *getAddrOfRTTIDescriptor(QualType Ty) = 0;<br>
<br>
   virtual bool shouldTypeidBeNullChecked(bool IsDeref,<br>
<br>
Modified: cfe/trunk/lib/CodeGen/CGException.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGException.cpp?rev=231105&r1=231104&r2=231105&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGException.cpp?rev=231105&r1=231104&r2=231105&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/CodeGen/CGException.cpp (original)<br>
+++ cfe/trunk/lib/CodeGen/CGException.cpp Tue Mar  3 13:21:04 2015<br>
@@ -54,39 +54,6 @@ static llvm::Constant *getThrowFn(CodeGe<br>
   return CGM.CreateRuntimeFunction(FTy, "__cxa_throw");<br>
 }<br>
<br>
-static llvm::Constant *getGetExceptionPtrFn(CodeGenModule &CGM) {<br>
-  // void *__cxa_get_exception_ptr(void*);<br>
-<br>
-  llvm::FunctionType *FTy =<br>
-    llvm::FunctionType::get(CGM.Int8PtrTy, CGM.Int8PtrTy, /*IsVarArgs=*/false);<br>
-<br>
-  return CGM.CreateRuntimeFunction(FTy, "__cxa_get_exception_ptr");<br>
-}<br>
-<br>
-static llvm::Constant *getBeginCatchFn(CodeGenModule &CGM) {<br>
-  if (CGM.getTarget().getCXXABI().isMicrosoft())<br>
-    return CGM.getIntrinsic(llvm::Intrinsic::eh_begincatch);<br>
-<br>
-  // void *__cxa_begin_catch(void*);<br>
-<br>
-  llvm::FunctionType *FTy =<br>
-    llvm::FunctionType::get(CGM.Int8PtrTy, CGM.Int8PtrTy, /*IsVarArgs=*/false);<br>
-<br>
-  return CGM.CreateRuntimeFunction(FTy, "__cxa_begin_catch");<br>
-}<br>
-<br>
-static llvm::Constant *getEndCatchFn(CodeGenModule &CGM) {<br>
-  if (CGM.getTarget().getCXXABI().isMicrosoft())<br>
-    return CGM.getIntrinsic(llvm::Intrinsic::eh_endcatch);<br>
-<br>
-  // void __cxa_end_catch();<br>
-<br>
-  llvm::FunctionType *FTy =<br>
-    llvm::FunctionType::get(CGM.VoidTy, /*IsVarArgs=*/false);<br>
-<br>
-  return CGM.CreateRuntimeFunction(FTy, "__cxa_end_catch");<br>
-}<br>
-<br>
 static llvm::Constant *getUnexpectedFn(CodeGenModule &CGM) {<br>
   // void __cxa_call_unexpected(void *thrown_exception);<br>
<br>
@@ -96,27 +63,27 @@ static llvm::Constant *getUnexpectedFn(C<br>
   return CGM.CreateRuntimeFunction(FTy, "__cxa_call_unexpected");<br>
 }<br>
<br>
-static llvm::Constant *getTerminateFn(CodeGenModule &CGM) {<br>
+llvm::Constant *CodeGenModule::getTerminateFn() {<br>
   // void __terminate();<br>
<br>
   llvm::FunctionType *FTy =<br>
-    llvm::FunctionType::get(CGM.VoidTy, /*IsVarArgs=*/false);<br>
+    llvm::FunctionType::get(VoidTy, /*IsVarArgs=*/false);<br>
<br>
   StringRef name;<br>
<br>
   // In C++, use std::terminate().<br>
-  if (CGM.getLangOpts().CPlusPlus &&<br>
-      CGM.getTarget().getCXXABI().isItaniumFamily()) {<br>
+  if (getLangOpts().CPlusPlus &&<br>
+      getTarget().getCXXABI().isItaniumFamily()) {<br>
     name = "_ZSt9terminatev";<br>
-  } else if (CGM.getLangOpts().CPlusPlus &&<br>
-             CGM.getTarget().getCXXABI().isMicrosoft()) {<br>
+  } else if (getLangOpts().CPlusPlus &&<br>
+             getTarget().getCXXABI().isMicrosoft()) {<br>
     name = "\01?terminate@@YAXXZ";<br>
-  } else if (CGM.getLangOpts().ObjC1 &&<br>
-             CGM.getLangOpts().ObjCRuntime.hasTerminate())<br>
+  } else if (getLangOpts().ObjC1 &&<br>
+             getLangOpts().ObjCRuntime.hasTerminate())<br>
     name = "objc_terminate";<br>
   else<br>
     name = "abort";<br>
-  return CGM.CreateRuntimeFunction(FTy, name);<br>
+  return CreateRuntimeFunction(FTy, name);<br>
 }<br>
<br>
 static llvm::Constant *getCatchallRethrowFn(CodeGenModule &CGM,<br>
@@ -482,7 +449,7 @@ void CodeGenFunction::EmitCXXThrowExpr(c<br>
<br>
   if (CGM.getTarget().getTriple().isKnownWindowsMSVCEnvironment()) {<br>
     // Call std::terminate().<br>
-    llvm::CallInst *TermCall = EmitNounwindRuntimeCall(getTerminateFn(CGM));<br>
+    llvm::CallInst *TermCall = EmitNounwindRuntimeCall(CGM.getTerminateFn());<br>
     TermCall->setDoesNotReturn();<br>
<br>
     // throw is an expression, and the expression emitters expect us<br>
@@ -920,263 +887,6 @@ llvm::BasicBlock *CodeGenFunction::EmitL<br>
   return lpad;<br>
 }<br>
<br>
-namespace {<br>
-  /// A cleanup to call __cxa_end_catch.  In many cases, the caught<br>
-  /// exception type lets us state definitively that the thrown exception<br>
-  /// type does not have a destructor.  In particular:<br>
-  ///   - Catch-alls tell us nothing, so we have to conservatively<br>
-  ///     assume that the thrown exception might have a destructor.<br>
-  ///   - Catches by reference behave according to their base types.<br>
-  ///   - Catches of non-record types will only trigger for exceptions<br>
-  ///     of non-record types, which never have destructors.<br>
-  ///   - Catches of record types can trigger for arbitrary subclasses<br>
-  ///     of the caught type, so we have to assume the actual thrown<br>
-  ///     exception type might have a throwing destructor, even if the<br>
-  ///     caught type's destructor is trivial or nothrow.<br>
-  struct CallEndCatch : EHScopeStack::Cleanup {<br>
-    CallEndCatch(bool MightThrow) : MightThrow(MightThrow) {}<br>
-    bool MightThrow;<br>
-<br>
-    void Emit(CodeGenFunction &CGF, Flags flags) override {<br>
-      if (!MightThrow) {<br>
-        CGF.EmitNounwindRuntimeCall(getEndCatchFn(CGF.CGM));<br>
-        return;<br>
-      }<br>
-<br>
-      CGF.EmitRuntimeCallOrInvoke(getEndCatchFn(CGF.CGM));<br>
-    }<br>
-  };<br>
-}<br>
-<br>
-/// Emits a call to __cxa_begin_catch and enters a cleanup to call<br>
-/// __cxa_end_catch.<br>
-///<br>
-/// \param EndMightThrow - true if __cxa_end_catch might throw<br>
-static llvm::Value *CallBeginCatch(CodeGenFunction &CGF,<br>
-                                   llvm::Value *Exn,<br>
-                                   bool EndMightThrow) {<br>
-  llvm::CallInst *call =<br>
-    CGF.EmitNounwindRuntimeCall(getBeginCatchFn(CGF.CGM), Exn);<br>
-<br>
-  CGF.EHStack.pushCleanup<CallEndCatch>(NormalAndEHCleanup, EndMightThrow);<br>
-<br>
-  return call;<br>
-}<br>
-<br>
-/// A "special initializer" callback for initializing a catch<br>
-/// parameter during catch initialization.<br>
-static void InitCatchParam(CodeGenFunction &CGF,<br>
-                           const VarDecl &CatchParam,<br>
-                           llvm::Value *ParamAddr,<br>
-                           SourceLocation Loc) {<br>
-  // Load the exception from where the landing pad saved it.<br>
-  llvm::Value *Exn = CGF.getExceptionFromSlot();<br>
-<br>
-  CanQualType CatchType =<br>
-    CGF.CGM.getContext().getCanonicalType(CatchParam.getType());<br>
-  llvm::Type *LLVMCatchTy = CGF.ConvertTypeForMem(CatchType);<br>
-<br>
-  // If we're catching by reference, we can just cast the object<br>
-  // pointer to the appropriate pointer.<br>
-  if (isa<ReferenceType>(CatchType)) {<br>
-    QualType CaughtType = cast<ReferenceType>(CatchType)->getPointeeType();<br>
-    bool EndCatchMightThrow = CaughtType->isRecordType();<br>
-<br>
-    // __cxa_begin_catch returns the adjusted object pointer.<br>
-    llvm::Value *AdjustedExn = CallBeginCatch(CGF, Exn, EndCatchMightThrow);<br>
-<br>
-    // We have no way to tell the personality function that we're<br>
-    // catching by reference, so if we're catching a pointer,<br>
-    // __cxa_begin_catch will actually return that pointer by value.<br>
-    if (const PointerType *PT = dyn_cast<PointerType>(CaughtType)) {<br>
-      QualType PointeeType = PT->getPointeeType();<br>
-<br>
-      // When catching by reference, generally we should just ignore<br>
-      // this by-value pointer and use the exception object instead.<br>
-      if (!PointeeType->isRecordType()) {<br>
-<br>
-        // Exn points to the struct _Unwind_Exception header, which<br>
-        // we have to skip past in order to reach the exception data.<br>
-        unsigned HeaderSize =<br>
-          CGF.CGM.getTargetCodeGenInfo().getSizeOfUnwindException();<br>
-        AdjustedExn = CGF.Builder.CreateConstGEP1_32(Exn, HeaderSize);<br>
-<br>
-      // However, if we're catching a pointer-to-record type that won't<br>
-      // work, because the personality function might have adjusted<br>
-      // the pointer.  There's actually no way for us to fully satisfy<br>
-      // the language/ABI contract here:  we can't use Exn because it<br>
-      // might have the wrong adjustment, but we can't use the by-value<br>
-      // pointer because it's off by a level of abstraction.<br>
-      //<br>
-      // The current solution is to dump the adjusted pointer into an<br>
-      // alloca, which breaks language semantics (because changing the<br>
-      // pointer doesn't change the exception) but at least works.<br>
-      // The better solution would be to filter out non-exact matches<br>
-      // and rethrow them, but this is tricky because the rethrow<br>
-      // really needs to be catchable by other sites at this landing<br>
-      // pad.  The best solution is to fix the personality function.<br>
-      } else {<br>
-        // Pull the pointer for the reference type off.<br>
-        llvm::Type *PtrTy =<br>
-          cast<llvm::PointerType>(LLVMCatchTy)->getElementType();<br>
-<br>
-        // Create the temporary and write the adjusted pointer into it.<br>
-        llvm::Value *ExnPtrTmp = CGF.CreateTempAlloca(PtrTy, "exn.byref.tmp");<br>
-        llvm::Value *Casted = CGF.Builder.CreateBitCast(AdjustedExn, PtrTy);<br>
-        CGF.Builder.CreateStore(Casted, ExnPtrTmp);<br>
-<br>
-        // Bind the reference to the temporary.<br>
-        AdjustedExn = ExnPtrTmp;<br>
-      }<br>
-    }<br>
-<br>
-    llvm::Value *ExnCast =<br>
-      CGF.Builder.CreateBitCast(AdjustedExn, LLVMCatchTy, "exn.byref");<br>
-    CGF.Builder.CreateStore(ExnCast, ParamAddr);<br>
-    return;<br>
-  }<br>
-<br>
-  // Scalars and complexes.<br>
-  TypeEvaluationKind TEK = CGF.getEvaluationKind(CatchType);<br>
-  if (TEK != TEK_Aggregate) {<br>
-    llvm::Value *AdjustedExn = CallBeginCatch(CGF, Exn, false);<br>
-<br>
-    // If the catch type is a pointer type, __cxa_begin_catch returns<br>
-    // the pointer by value.<br>
-    if (CatchType->hasPointerRepresentation()) {<br>
-      llvm::Value *CastExn =<br>
-        CGF.Builder.CreateBitCast(AdjustedExn, LLVMCatchTy, "exn.casted");<br>
-<br>
-      switch (CatchType.getQualifiers().getObjCLifetime()) {<br>
-      case Qualifiers::OCL_Strong:<br>
-        CastExn = CGF.EmitARCRetainNonBlock(CastExn);<br>
-        // fallthrough<br>
-<br>
-      case Qualifiers::OCL_None:<br>
-      case Qualifiers::OCL_ExplicitNone:<br>
-      case Qualifiers::OCL_Autoreleasing:<br>
-        CGF.Builder.CreateStore(CastExn, ParamAddr);<br>
-        return;<br>
-<br>
-      case Qualifiers::OCL_Weak:<br>
-        CGF.EmitARCInitWeak(ParamAddr, CastExn);<br>
-        return;<br>
-      }<br>
-      llvm_unreachable("bad ownership qualifier!");<br>
-    }<br>
-<br>
-    // Otherwise, it returns a pointer into the exception object.<br>
-<br>
-    llvm::Type *PtrTy = LLVMCatchTy->getPointerTo(0); // addrspace 0 ok<br>
-    llvm::Value *Cast = CGF.Builder.CreateBitCast(AdjustedExn, PtrTy);<br>
-<br>
-    LValue srcLV = CGF.MakeNaturalAlignAddrLValue(Cast, CatchType);<br>
-    LValue destLV = CGF.MakeAddrLValue(ParamAddr, CatchType,<br>
-                                  CGF.getContext().getDeclAlign(&CatchParam));<br>
-    switch (TEK) {<br>
-    case TEK_Complex:<br>
-      CGF.EmitStoreOfComplex(CGF.EmitLoadOfComplex(srcLV, Loc), destLV,<br>
-                             /*init*/ true);<br>
-      return;<br>
-    case TEK_Scalar: {<br>
-      llvm::Value *ExnLoad = CGF.EmitLoadOfScalar(srcLV, Loc);<br>
-      CGF.EmitStoreOfScalar(ExnLoad, destLV, /*init*/ true);<br>
-      return;<br>
-    }<br>
-    case TEK_Aggregate:<br>
-      llvm_unreachable("evaluation kind filtered out!");<br>
-    }<br>
-    llvm_unreachable("bad evaluation kind");<br>
-  }<br>
-<br>
-  assert(isa<RecordType>(CatchType) && "unexpected catch type!");<br>
-<br>
-  llvm::Type *PtrTy = LLVMCatchTy->getPointerTo(0); // addrspace 0 ok<br>
-<br>
-  // Check for a copy expression.  If we don't have a copy expression,<br>
-  // that means a trivial copy is okay.<br>
-  const Expr *copyExpr = CatchParam.getInit();<br>
-  if (!copyExpr) {<br>
-    llvm::Value *rawAdjustedExn = CallBeginCatch(CGF, Exn, true);<br>
-    llvm::Value *adjustedExn = CGF.Builder.CreateBitCast(rawAdjustedExn, PtrTy);<br>
-    CGF.EmitAggregateCopy(ParamAddr, adjustedExn, CatchType);<br>
-    return;<br>
-  }<br>
-<br>
-  // We have to call __cxa_get_exception_ptr to get the adjusted<br>
-  // pointer before copying.<br>
-  llvm::CallInst *rawAdjustedExn =<br>
-    CGF.EmitNounwindRuntimeCall(getGetExceptionPtrFn(CGF.CGM), Exn);<br>
-<br>
-  // Cast that to the appropriate type.<br>
-  llvm::Value *adjustedExn = CGF.Builder.CreateBitCast(rawAdjustedExn, PtrTy);<br>
-<br>
-  // The copy expression is defined in terms of an OpaqueValueExpr.<br>
-  // Find it and map it to the adjusted expression.<br>
-  CodeGenFunction::OpaqueValueMapping<br>
-    opaque(CGF, OpaqueValueExpr::findInCopyConstruct(copyExpr),<br>
-           CGF.MakeAddrLValue(adjustedExn, CatchParam.getType()));<br>
-<br>
-  // Call the copy ctor in a terminate scope.<br>
-  CGF.EHStack.pushTerminate();<br>
-<br>
-  // Perform the copy construction.<br>
-  CharUnits Alignment = CGF.getContext().getDeclAlign(&CatchParam);<br>
-  CGF.EmitAggExpr(copyExpr,<br>
-                  AggValueSlot::forAddr(ParamAddr, Alignment, Qualifiers(),<br>
-                                        AggValueSlot::IsNotDestructed,<br>
-                                        AggValueSlot::DoesNotNeedGCBarriers,<br>
-                                        AggValueSlot::IsNotAliased));<br>
-<br>
-  // Leave the terminate scope.<br>
-  CGF.EHStack.popTerminate();<br>
-<br>
-  // Undo the opaque value mapping.<br>
-  opaque.pop();<br>
-<br>
-  // Finally we can call __cxa_begin_catch.<br>
-  CallBeginCatch(CGF, Exn, true);<br>
-}<br>
-<br>
-/// Begins a catch statement by initializing the catch variable and<br>
-/// calling __cxa_begin_catch.<br>
-static void BeginCatch(CodeGenFunction &CGF, const CXXCatchStmt *S) {<br>
-  // We have to be very careful with the ordering of cleanups here:<br>
-  //   C++ [except.throw]p4:<br>
-  //     The destruction [of the exception temporary] occurs<br>
-  //     immediately after the destruction of the object declared in<br>
-  //     the exception-declaration in the handler.<br>
-  //<br>
-  // So the precise ordering is:<br>
-  //   1.  Construct catch variable.<br>
-  //   2.  __cxa_begin_catch<br>
-  //   3.  Enter __cxa_end_catch cleanup<br>
-  //   4.  Enter dtor cleanup<br>
-  //<br>
-  // We do this by using a slightly abnormal initialization process.<br>
-  // Delegation sequence:<br>
-  //   - ExitCXXTryStmt opens a RunCleanupsScope<br>
-  //     - EmitAutoVarAlloca creates the variable and debug info<br>
-  //       - InitCatchParam initializes the variable from the exception<br>
-  //       - CallBeginCatch calls __cxa_begin_catch<br>
-  //       - CallBeginCatch enters the __cxa_end_catch cleanup<br>
-  //     - EmitAutoVarCleanups enters the variable destructor cleanup<br>
-  //   - EmitCXXTryStmt emits the code for the catch body<br>
-  //   - EmitCXXTryStmt close the RunCleanupsScope<br>
-<br>
-  VarDecl *CatchParam = S->getExceptionDecl();<br>
-  if (!CatchParam) {<br>
-    llvm::Value *Exn = CGF.getExceptionFromSlot();<br>
-    CallBeginCatch(CGF, Exn, true);<br>
-    return;<br>
-  }<br>
-<br>
-  // Emit the local.<br>
-  CodeGenFunction::AutoVarEmission var = CGF.EmitAutoVarAlloca(*CatchParam);<br>
-  InitCatchParam(CGF, *CatchParam, var.getObjectAddress(CGF), S->getLocStart());<br>
-  CGF.EmitAutoVarCleanups(var);<br>
-}<br>
-<br>
 /// Emit the structure of the dispatch block for the given catch scope.<br>
 /// It is an invariant that the dispatch block already exists.<br>
 static void emitCatchDispatchBlock(CodeGenFunction &CGF,<br>
@@ -1315,7 +1025,7 @@ void CodeGenFunction::ExitCXXTryStmt(con<br>
     RunCleanupsScope CatchScope(*this);<br>
<br>
     // Initialize the catch variable and set up the cleanups.<br>
-    BeginCatch(*this, C);<br>
+    CGM.getCXXABI().emitBeginCatch(*this, C);<br>
<br>
     // Emit the PGO counter increment.<br>
     RegionCounter CatchCnt = getPGORegionCounter(C);<br>
@@ -1543,70 +1253,6 @@ void CodeGenFunction::FinallyInfo::exit(<br>
   CGF.PopCleanupBlock();<br>
 }<br>
<br>
-/// In a terminate landing pad, should we use __clang__call_terminate<br>
-/// or just a naked call to std::terminate?<br>
-///<br>
-/// __clang_call_terminate calls __cxa_begin_catch, which then allows<br>
-/// std::terminate to usefully report something about the<br>
-/// violating exception.<br>
-static bool useClangCallTerminate(CodeGenModule &CGM) {<br>
-  // Only do this for Itanium-family ABIs in C++ mode.<br>
-  return (CGM.getLangOpts().CPlusPlus &&<br>
-          CGM.getTarget().getCXXABI().isItaniumFamily());<br>
-}<br>
-<br>
-/// Get or define the following function:<br>
-///   void @__clang_call_terminate(i8* %exn) nounwind noreturn<br>
-/// This code is used only in C++.<br>
-static llvm::Constant *getClangCallTerminateFn(CodeGenModule &CGM) {<br>
-  llvm::FunctionType *fnTy =<br>
-    llvm::FunctionType::get(CGM.VoidTy, CGM.Int8PtrTy, /*IsVarArgs=*/false);<br>
-  llvm::Constant *fnRef =<br>
-    CGM.CreateRuntimeFunction(fnTy, "__clang_call_terminate");<br>
-<br>
-  llvm::Function *fn = dyn_cast<llvm::Function>(fnRef);<br>
-  if (fn && fn->empty()) {<br>
-    fn->setDoesNotThrow();<br>
-    fn->setDoesNotReturn();<br>
-<br>
-    // What we really want is to massively penalize inlining without<br>
-    // forbidding it completely.  The difference between that and<br>
-    // 'noinline' is negligible.<br>
-    fn->addFnAttr(llvm::Attribute::NoInline);<br>
-<br>
-    // Allow this function to be shared across translation units, but<br>
-    // we don't want it to turn into an exported symbol.<br>
-    fn->setLinkage(llvm::Function::LinkOnceODRLinkage);<br>
-    fn->setVisibility(llvm::Function::HiddenVisibility);<br>
-    if (CGM.supportsCOMDAT())<br>
-      fn->setComdat(CGM.getModule().getOrInsertComdat(fn->getName()));<br>
-<br>
-    // Set up the function.<br>
-    llvm::BasicBlock *entry =<br>
-      llvm::BasicBlock::Create(CGM.getLLVMContext(), "", fn);<br>
-    CGBuilderTy builder(entry);<br>
-<br>
-    // Pull the exception pointer out of the parameter list.<br>
-    llvm::Value *exn = &*fn->arg_begin();<br>
-<br>
-    // Call __cxa_begin_catch(exn).<br>
-    llvm::CallInst *catchCall = builder.CreateCall(getBeginCatchFn(CGM), exn);<br>
-    catchCall->setDoesNotThrow();<br>
-    catchCall->setCallingConv(CGM.getRuntimeCC());<br>
-<br>
-    // Call std::terminate().<br>
-    llvm::CallInst *termCall = builder.CreateCall(getTerminateFn(CGM));<br>
-    termCall->setDoesNotThrow();<br>
-    termCall->setDoesNotReturn();<br>
-    termCall->setCallingConv(CGM.getRuntimeCC());<br>
-<br>
-    // std::terminate cannot return.<br>
-    builder.CreateUnreachable();<br>
-  }<br>
-<br>
-  return fnRef;<br>
-}<br>
-<br>
 llvm::BasicBlock *CodeGenFunction::getTerminateLandingPad() {<br>
   if (TerminateLandingPad)<br>
     return TerminateLandingPad;<br>
@@ -1624,14 +1270,11 @@ llvm::BasicBlock *CodeGenFunction::getTe<br>
                              getOpaquePersonalityFn(CGM, Personality), 0);<br>
   LPadInst->addClause(getCatchAllValue(*this));<br>
<br>
-  llvm::CallInst *terminateCall;<br>
-  if (useClangCallTerminate(CGM)) {<br>
-    // Extract out the exception pointer.<br>
-    llvm::Value *exn = Builder.CreateExtractValue(LPadInst, 0);<br>
-    terminateCall = EmitNounwindRuntimeCall(getClangCallTerminateFn(CGM), exn);<br>
-  } else {<br>
-    terminateCall = EmitNounwindRuntimeCall(getTerminateFn(CGM));<br>
-  }<br>
+  llvm::Value *Exn = 0;<br>
+  if (getLangOpts().CPlusPlus)<br>
+    Exn = Builder.CreateExtractValue(LPadInst, 0);<br>
+  llvm::CallInst *terminateCall =<br>
+      CGM.getCXXABI().emitTerminateForUnexpectedException(*this, Exn);<br>
   terminateCall->setDoesNotReturn();<br>
   Builder.CreateUnreachable();<br>
<br>
@@ -1651,14 +1294,11 @@ llvm::BasicBlock *CodeGenFunction::getTe<br>
   // end of the function by FinishFunction.<br>
   TerminateHandler = createBasicBlock("terminate.handler");<br>
   Builder.SetInsertPoint(TerminateHandler);<br>
-  llvm::CallInst *terminateCall;<br>
-  if (useClangCallTerminate(CGM)) {<br>
-    // Load the exception pointer.<br>
-    llvm::Value *exn = getExceptionFromSlot();<br>
-    terminateCall = EmitNounwindRuntimeCall(getClangCallTerminateFn(CGM), exn);<br>
-  } else {<br>
-    terminateCall = EmitNounwindRuntimeCall(getTerminateFn(CGM));<br>
-  }<br>
+  llvm::Value *Exn = 0;<br>
+  if (getLangOpts().CPlusPlus)<br>
+    Exn = getExceptionFromSlot();<br>
+  llvm::CallInst *terminateCall =<br>
+      CGM.getCXXABI().emitTerminateForUnexpectedException(*this, Exn);<br>
   terminateCall->setDoesNotReturn();<br>
   Builder.CreateUnreachable();<br>
<br>
<br>
Modified: cfe/trunk/lib/CodeGen/CodeGenModule.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.h?rev=231105&r1=231104&r2=231105&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.h?rev=231105&r1=231104&r2=231105&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/CodeGen/CodeGenModule.h (original)<br>
+++ cfe/trunk/lib/CodeGen/CodeGenModule.h Tue Mar  3 13:21:04 2015<br>
@@ -1108,6 +1108,9 @@ public:<br>
   void EmitVTableBitSetEntries(llvm::GlobalVariable *VTable,<br>
                                const VTableLayout &VTLayout);<br>
<br>
+  /// \breif Get the declaration of std::terminate for the platform.<br>
+  llvm::Constant *getTerminateFn();<br>
+<br>
 private:<br>
   llvm::Constant *<br>
   GetOrCreateLLVMFunction(StringRef MangledName, llvm::Type *Ty, GlobalDecl D,<br>
<br>
Modified: cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp?rev=231105&r1=231104&r2=231105&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp?rev=231105&r1=231104&r2=231105&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp (original)<br>
+++ cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp Tue Mar  3 13:21:04 2015<br>
@@ -19,14 +19,18 @@<br>
 //===----------------------------------------------------------------------===//<br>
<br>
 #include "CGCXXABI.h"<br>
+#include "CGCleanup.h"<br>
 #include "CGRecordLayout.h"<br>
 #include "CGVTables.h"<br>
 #include "CodeGenFunction.h"<br>
 #include "CodeGenModule.h"<br>
+#include "TargetInfo.h"<br>
 #include "clang/AST/Mangle.h"<br>
 #include "clang/AST/Type.h"<br>
+#include "clang/AST/StmtCXX.h"<br>
 #include "llvm/IR/CallSite.h"<br>
 #include "llvm/IR/DataLayout.h"<br>
+#include "llvm/IR/Instructions.h"<br>
 #include "llvm/IR/Intrinsics.h"<br>
 #include "llvm/IR/Value.h"<br>
<br>
@@ -112,6 +116,12 @@ public:<br>
<br>
   void emitRethrow(CodeGenFunction &CGF, bool isNoReturn) override;<br>
<br>
+  void emitBeginCatch(CodeGenFunction &CGF, const CXXCatchStmt *C) override;<br>
+<br>
+  llvm::CallInst *<br>
+  emitTerminateForUnexpectedException(CodeGenFunction &CGF,<br>
+                                      llvm::Value *Exn) override;<br>
+<br>
   void EmitFundamentalRTTIDescriptor(QualType Type);<br>
   void EmitFundamentalRTTIDescriptors();<br>
   llvm::Constant *getAddrOfRTTIDescriptor(QualType Ty) override;<br>
@@ -3220,3 +3230,348 @@ void ItaniumCXXABI::emitCXXStructor(cons<br>
     CGM.maybeSetTrivialComdat(*MD, *Fn);<br>
   }<br>
 }<br>
+<br>
+static llvm::Constant *getBeginCatchFn(CodeGenModule &CGM) {<br>
+  // void *__cxa_begin_catch(void*);<br>
+  llvm::FunctionType *FTy = llvm::FunctionType::get(<br>
+      CGM.Int8PtrTy, CGM.Int8PtrTy, /*IsVarArgs=*/false);<br>
+<br>
+  return CGM.CreateRuntimeFunction(FTy, "__cxa_begin_catch");<br>
+}<br>
+<br>
+static llvm::Constant *getEndCatchFn(CodeGenModule &CGM) {<br>
+  // void __cxa_end_catch();<br>
+  llvm::FunctionType *FTy =<br>
+      llvm::FunctionType::get(CGM.VoidTy, /*IsVarArgs=*/false);<br>
+<br>
+  return CGM.CreateRuntimeFunction(FTy, "__cxa_end_catch");<br>
+}<br>
+<br>
+static llvm::Constant *getGetExceptionPtrFn(CodeGenModule &CGM) {<br>
+  // void *__cxa_get_exception_ptr(void*);<br>
+  llvm::FunctionType *FTy = llvm::FunctionType::get(<br>
+      CGM.Int8PtrTy, CGM.Int8PtrTy, /*IsVarArgs=*/false);<br>
+<br>
+  return CGM.CreateRuntimeFunction(FTy, "__cxa_get_exception_ptr");<br>
+}<br>
+<br>
+namespace {<br>
+  /// A cleanup to call __cxa_end_catch.  In many cases, the caught<br>
+  /// exception type lets us state definitively that the thrown exception<br>
+  /// type does not have a destructor.  In particular:<br>
+  ///   - Catch-alls tell us nothing, so we have to conservatively<br>
+  ///     assume that the thrown exception might have a destructor.<br>
+  ///   - Catches by reference behave according to their base types.<br>
+  ///   - Catches of non-record types will only trigger for exceptions<br>
+  ///     of non-record types, which never have destructors.<br>
+  ///   - Catches of record types can trigger for arbitrary subclasses<br>
+  ///     of the caught type, so we have to assume the actual thrown<br>
+  ///     exception type might have a throwing destructor, even if the<br>
+  ///     caught type's destructor is trivial or nothrow.<br>
+  struct CallEndCatch : EHScopeStack::Cleanup {<br>
+    CallEndCatch(bool MightThrow) : MightThrow(MightThrow) {}<br>
+    bool MightThrow;<br>
+<br>
+    void Emit(CodeGenFunction &CGF, Flags flags) override {<br>
+      if (!MightThrow) {<br>
+        CGF.EmitNounwindRuntimeCall(getEndCatchFn(CGF.CGM));<br>
+        return;<br>
+      }<br>
+<br>
+      CGF.EmitRuntimeCallOrInvoke(getEndCatchFn(CGF.CGM));<br>
+    }<br>
+  };<br>
+}<br>
+<br>
+/// Emits a call to __cxa_begin_catch and enters a cleanup to call<br>
+/// __cxa_end_catch.<br>
+///<br>
+/// \param EndMightThrow - true if __cxa_end_catch might throw<br>
+static llvm::Value *CallBeginCatch(CodeGenFunction &CGF,<br>
+                                   llvm::Value *Exn,<br>
+                                   bool EndMightThrow) {<br>
+  llvm::CallInst *call =<br>
+    CGF.EmitNounwindRuntimeCall(getBeginCatchFn(CGF.CGM), Exn);<br>
+<br>
+  CGF.EHStack.pushCleanup<CallEndCatch>(NormalAndEHCleanup, EndMightThrow);<br>
+<br>
+  return call;<br>
+}<br>
+<br>
+/// A "special initializer" callback for initializing a catch<br>
+/// parameter during catch initialization.<br>
+static void InitCatchParam(CodeGenFunction &CGF,<br>
+                           const VarDecl &CatchParam,<br>
+                           llvm::Value *ParamAddr,<br>
+                           SourceLocation Loc) {<br>
+  // Load the exception from where the landing pad saved it.<br>
+  llvm::Value *Exn = CGF.getExceptionFromSlot();<br>
+<br>
+  CanQualType CatchType =<br>
+    CGF.CGM.getContext().getCanonicalType(CatchParam.getType());<br>
+  llvm::Type *LLVMCatchTy = CGF.ConvertTypeForMem(CatchType);<br>
+<br>
+  // If we're catching by reference, we can just cast the object<br>
+  // pointer to the appropriate pointer.<br>
+  if (isa<ReferenceType>(CatchType)) {<br>
+    QualType CaughtType = cast<ReferenceType>(CatchType)->getPointeeType();<br>
+    bool EndCatchMightThrow = CaughtType->isRecordType();<br>
+<br>
+    // __cxa_begin_catch returns the adjusted object pointer.<br>
+    llvm::Value *AdjustedExn = CallBeginCatch(CGF, Exn, EndCatchMightThrow);<br>
+<br>
+    // We have no way to tell the personality function that we're<br>
+    // catching by reference, so if we're catching a pointer,<br>
+    // __cxa_begin_catch will actually return that pointer by value.<br>
+    if (const PointerType *PT = dyn_cast<PointerType>(CaughtType)) {<br>
+      QualType PointeeType = PT->getPointeeType();<br>
+<br>
+      // When catching by reference, generally we should just ignore<br>
+      // this by-value pointer and use the exception object instead.<br>
+      if (!PointeeType->isRecordType()) {<br>
+<br>
+        // Exn points to the struct _Unwind_Exception header, which<br>
+        // we have to skip past in order to reach the exception data.<br>
+        unsigned HeaderSize =<br>
+          CGF.CGM.getTargetCodeGenInfo().getSizeOfUnwindException();<br>
+        AdjustedExn = CGF.Builder.CreateConstGEP1_32(Exn, HeaderSize);<br>
+<br>
+      // However, if we're catching a pointer-to-record type that won't<br>
+      // work, because the personality function might have adjusted<br>
+      // the pointer.  There's actually no way for us to fully satisfy<br>
+      // the language/ABI contract here:  we can't use Exn because it<br>
+      // might have the wrong adjustment, but we can't use the by-value<br>
+      // pointer because it's off by a level of abstraction.<br>
+      //<br>
+      // The current solution is to dump the adjusted pointer into an<br>
+      // alloca, which breaks language semantics (because changing the<br>
+      // pointer doesn't change the exception) but at least works.<br>
+      // The better solution would be to filter out non-exact matches<br>
+      // and rethrow them, but this is tricky because the rethrow<br>
+      // really needs to be catchable by other sites at this landing<br>
+      // pad.  The best solution is to fix the personality function.<br>
+      } else {<br>
+        // Pull the pointer for the reference type off.<br>
+        llvm::Type *PtrTy =<br>
+          cast<llvm::PointerType>(LLVMCatchTy)->getElementType();<br>
+<br>
+        // Create the temporary and write the adjusted pointer into it.<br>
+        llvm::Value *ExnPtrTmp = CGF.CreateTempAlloca(PtrTy, "exn.byref.tmp");<br>
+        llvm::Value *Casted = CGF.Builder.CreateBitCast(AdjustedExn, PtrTy);<br>
+        CGF.Builder.CreateStore(Casted, ExnPtrTmp);<br>
+<br>
+        // Bind the reference to the temporary.<br>
+        AdjustedExn = ExnPtrTmp;<br>
+      }<br>
+    }<br>
+<br>
+    llvm::Value *ExnCast =<br>
+      CGF.Builder.CreateBitCast(AdjustedExn, LLVMCatchTy, "exn.byref");<br>
+    CGF.Builder.CreateStore(ExnCast, ParamAddr);<br>
+    return;<br>
+  }<br>
+<br>
+  // Scalars and complexes.<br>
+  TypeEvaluationKind TEK = CGF.getEvaluationKind(CatchType);<br>
+  if (TEK != TEK_Aggregate) {<br>
+    llvm::Value *AdjustedExn = CallBeginCatch(CGF, Exn, false);<br>
+<br>
+    // If the catch type is a pointer type, __cxa_begin_catch returns<br>
+    // the pointer by value.<br>
+    if (CatchType->hasPointerRepresentation()) {<br>
+      llvm::Value *CastExn =<br>
+        CGF.Builder.CreateBitCast(AdjustedExn, LLVMCatchTy, "exn.casted");<br>
+<br>
+      switch (CatchType.getQualifiers().getObjCLifetime()) {<br>
+      case Qualifiers::OCL_Strong:<br>
+        CastExn = CGF.EmitARCRetainNonBlock(CastExn);<br>
+        // fallthrough<br>
+<br>
+      case Qualifiers::OCL_None:<br>
+      case Qualifiers::OCL_ExplicitNone:<br>
+      case Qualifiers::OCL_Autoreleasing:<br>
+        CGF.Builder.CreateStore(CastExn, ParamAddr);<br>
+        return;<br>
+<br>
+      case Qualifiers::OCL_Weak:<br>
+        CGF.EmitARCInitWeak(ParamAddr, CastExn);<br>
+        return;<br>
+      }<br>
+      llvm_unreachable("bad ownership qualifier!");<br>
+    }<br>
+<br>
+    // Otherwise, it returns a pointer into the exception object.<br>
+<br>
+    llvm::Type *PtrTy = LLVMCatchTy->getPointerTo(0); // addrspace 0 ok<br>
+    llvm::Value *Cast = CGF.Builder.CreateBitCast(AdjustedExn, PtrTy);<br>
+<br>
+    LValue srcLV = CGF.MakeNaturalAlignAddrLValue(Cast, CatchType);<br>
+    LValue destLV = CGF.MakeAddrLValue(ParamAddr, CatchType,<br>
+                                  CGF.getContext().getDeclAlign(&CatchParam));<br>
+    switch (TEK) {<br>
+    case TEK_Complex:<br>
+      CGF.EmitStoreOfComplex(CGF.EmitLoadOfComplex(srcLV, Loc), destLV,<br>
+                             /*init*/ true);<br>
+      return;<br>
+    case TEK_Scalar: {<br>
+      llvm::Value *ExnLoad = CGF.EmitLoadOfScalar(srcLV, Loc);<br>
+      CGF.EmitStoreOfScalar(ExnLoad, destLV, /*init*/ true);<br>
+      return;<br>
+    }<br>
+    case TEK_Aggregate:<br>
+      llvm_unreachable("evaluation kind filtered out!");<br>
+    }<br>
+    llvm_unreachable("bad evaluation kind");<br>
+  }<br>
+<br>
+  assert(isa<RecordType>(CatchType) && "unexpected catch type!");<br>
+<br>
+  llvm::Type *PtrTy = LLVMCatchTy->getPointerTo(0); // addrspace 0 ok<br>
+<br>
+  // Check for a copy expression.  If we don't have a copy expression,<br>
+  // that means a trivial copy is okay.<br>
+  const Expr *copyExpr = CatchParam.getInit();<br>
+  if (!copyExpr) {<br>
+    llvm::Value *rawAdjustedExn = CallBeginCatch(CGF, Exn, true);<br>
+    llvm::Value *adjustedExn = CGF.Builder.CreateBitCast(rawAdjustedExn, PtrTy);<br>
+    CGF.EmitAggregateCopy(ParamAddr, adjustedExn, CatchType);<br>
+    return;<br>
+  }<br>
+<br>
+  // We have to call __cxa_get_exception_ptr to get the adjusted<br>
+  // pointer before copying.<br>
+  llvm::CallInst *rawAdjustedExn =<br>
+    CGF.EmitNounwindRuntimeCall(getGetExceptionPtrFn(CGF.CGM), Exn);<br>
+<br>
+  // Cast that to the appropriate type.<br>
+  llvm::Value *adjustedExn = CGF.Builder.CreateBitCast(rawAdjustedExn, PtrTy);<br>
+<br>
+  // The copy expression is defined in terms of an OpaqueValueExpr.<br>
+  // Find it and map it to the adjusted expression.<br>
+  CodeGenFunction::OpaqueValueMapping<br>
+    opaque(CGF, OpaqueValueExpr::findInCopyConstruct(copyExpr),<br>
+           CGF.MakeAddrLValue(adjustedExn, CatchParam.getType()));<br>
+<br>
+  // Call the copy ctor in a terminate scope.<br>
+  CGF.EHStack.pushTerminate();<br>
+<br>
+  // Perform the copy construction.<br>
+  CharUnits Alignment = CGF.getContext().getDeclAlign(&CatchParam);<br>
+  CGF.EmitAggExpr(copyExpr,<br>
+                  AggValueSlot::forAddr(ParamAddr, Alignment, Qualifiers(),<br>
+                                        AggValueSlot::IsNotDestructed,<br>
+                                        AggValueSlot::DoesNotNeedGCBarriers,<br>
+                                        AggValueSlot::IsNotAliased));<br>
+<br>
+  // Leave the terminate scope.<br>
+  CGF.EHStack.popTerminate();<br>
+<br>
+  // Undo the opaque value mapping.<br>
+  opaque.pop();<br>
+<br>
+  // Finally we can call __cxa_begin_catch.<br>
+  CallBeginCatch(CGF, Exn, true);<br>
+}<br>
+<br>
+/// Begins a catch statement by initializing the catch variable and<br>
+/// calling __cxa_begin_catch.<br>
+void ItaniumCXXABI::emitBeginCatch(CodeGenFunction &CGF,<br>
+                                   const CXXCatchStmt *S) {<br>
+  // We have to be very careful with the ordering of cleanups here:<br>
+  //   C++ [except.throw]p4:<br>
+  //     The destruction [of the exception temporary] occurs<br>
+  //     immediately after the destruction of the object declared in<br>
+  //     the exception-declaration in the handler.<br>
+  //<br>
+  // So the precise ordering is:<br>
+  //   1.  Construct catch variable.<br>
+  //   2.  __cxa_begin_catch<br>
+  //   3.  Enter __cxa_end_catch cleanup<br>
+  //   4.  Enter dtor cleanup<br>
+  //<br>
+  // We do this by using a slightly abnormal initialization process.<br>
+  // Delegation sequence:<br>
+  //   - ExitCXXTryStmt opens a RunCleanupsScope<br>
+  //     - EmitAutoVarAlloca creates the variable and debug info<br>
+  //       - InitCatchParam initializes the variable from the exception<br>
+  //       - CallBeginCatch calls __cxa_begin_catch<br>
+  //       - CallBeginCatch enters the __cxa_end_catch cleanup<br>
+  //     - EmitAutoVarCleanups enters the variable destructor cleanup<br>
+  //   - EmitCXXTryStmt emits the code for the catch body<br>
+  //   - EmitCXXTryStmt close the RunCleanupsScope<br>
+<br>
+  VarDecl *CatchParam = S->getExceptionDecl();<br>
+  if (!CatchParam) {<br>
+    llvm::Value *Exn = CGF.getExceptionFromSlot();<br>
+    CallBeginCatch(CGF, Exn, true);<br>
+    return;<br>
+  }<br>
+<br>
+  // Emit the local.<br>
+  CodeGenFunction::AutoVarEmission var = CGF.EmitAutoVarAlloca(*CatchParam);<br>
+  InitCatchParam(CGF, *CatchParam, var.getObjectAddress(CGF), S->getLocStart());<br>
+  CGF.EmitAutoVarCleanups(var);<br>
+}<br>
+<br>
+/// Get or define the following function:<br>
+///   void @__clang_call_terminate(i8* %exn) nounwind noreturn<br>
+/// This code is used only in C++.<br>
+static llvm::Constant *getClangCallTerminateFn(CodeGenModule &CGM) {<br>
+  llvm::FunctionType *fnTy =<br>
+    llvm::FunctionType::get(CGM.VoidTy, CGM.Int8PtrTy, /*IsVarArgs=*/false);<br>
+  llvm::Constant *fnRef =<br>
+    CGM.CreateRuntimeFunction(fnTy, "__clang_call_terminate");<br>
+<br>
+  llvm::Function *fn = dyn_cast<llvm::Function>(fnRef);<br>
+  if (fn && fn->empty()) {<br>
+    fn->setDoesNotThrow();<br>
+    fn->setDoesNotReturn();<br>
+<br>
+    // What we really want is to massively penalize inlining without<br>
+    // forbidding it completely.  The difference between that and<br>
+    // 'noinline' is negligible.<br>
+    fn->addFnAttr(llvm::Attribute::NoInline);<br>
+<br>
+    // Allow this function to be shared across translation units, but<br>
+    // we don't want it to turn into an exported symbol.<br>
+    fn->setLinkage(llvm::Function::LinkOnceODRLinkage);<br>
+    fn->setVisibility(llvm::Function::HiddenVisibility);<br>
+    if (CGM.supportsCOMDAT())<br>
+      fn->setComdat(CGM.getModule().getOrInsertComdat(fn->getName()));<br>
+<br>
+    // Set up the function.<br>
+    llvm::BasicBlock *entry =<br>
+      llvm::BasicBlock::Create(CGM.getLLVMContext(), "", fn);<br>
+    CGBuilderTy builder(entry);<br>
+<br>
+    // Pull the exception pointer out of the parameter list.<br>
+    llvm::Value *exn = &*fn->arg_begin();<br>
+<br>
+    // Call __cxa_begin_catch(exn).<br>
+    llvm::CallInst *catchCall = builder.CreateCall(getBeginCatchFn(CGM), exn);<br>
+    catchCall->setDoesNotThrow();<br>
+    catchCall->setCallingConv(CGM.getRuntimeCC());<br>
+<br>
+    // Call std::terminate().<br>
+    llvm::CallInst *termCall = builder.CreateCall(CGM.getTerminateFn());<br>
+    termCall->setDoesNotThrow();<br>
+    termCall->setDoesNotReturn();<br>
+    termCall->setCallingConv(CGM.getRuntimeCC());<br>
+<br>
+    // std::terminate cannot return.<br>
+    builder.CreateUnreachable();<br>
+  }<br>
+<br>
+  return fnRef;<br>
+}<br>
+<br>
+llvm::CallInst *<br>
+ItaniumCXXABI::emitTerminateForUnexpectedException(CodeGenFunction &CGF,<br>
+                                                   llvm::Value *Exn) {<br>
+  // In C++, we want to call __cxa_begin_catch() before terminating.<br>
+  if (Exn) {<br>
+    assert(CGF.CGM.getLangOpts().CPlusPlus);<br>
+    return CGF.EmitNounwindRuntimeCall(getClangCallTerminateFn(CGF.CGM), Exn);<br>
+  }<br>
+  return CGF.EmitNounwindRuntimeCall(CGF.CGM.getTerminateFn());<br>
+}<br>
<br>
Modified: cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp?rev=231105&r1=231104&r2=231105&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp?rev=231105&r1=231104&r2=231105&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp (original)<br>
+++ cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp Tue Mar  3 13:21:04 2015<br>
@@ -17,12 +17,15 @@<br>
 #include "CGCXXABI.h"<br>
 #include "CGVTables.h"<br>
 #include "CodeGenModule.h"<br>
+#include "TargetInfo.h"<br>
 #include "clang/AST/Decl.h"<br>
 #include "clang/AST/DeclCXX.h"<br>
+#include "clang/AST/StmtCXX.h"<br>
 #include "clang/AST/VTableBuilder.h"<br>
 #include "llvm/ADT/StringExtras.h"<br>
 #include "llvm/ADT/StringSet.h"<br>
 #include "llvm/IR/CallSite.h"<br>
+#include "llvm/IR/Intrinsics.h"<br>
<br>
 using namespace clang;<br>
 using namespace CodeGen;<br>
@@ -72,6 +75,8 @@ public:<br>
<br>
   void emitRethrow(CodeGenFunction &CGF, bool isNoReturn) override;<br>
<br>
+  void emitBeginCatch(CodeGenFunction &CGF, const CXXCatchStmt *C) override;<br>
+<br>
   llvm::GlobalVariable *getMSCompleteObjectLocator(const CXXRecordDecl *RD,<br>
                                                    const VPtrInfo *Info);<br>
<br>
@@ -695,6 +700,42 @@ void MicrosoftCXXABI::emitRethrow(CodeGe<br>
     CGF.EmitRuntimeCallOrInvoke(Fn, Args);<br>
 }<br>
<br>
+namespace {<br>
+struct CallEndCatchMSVC : EHScopeStack::Cleanup {<br>
+  CallEndCatchMSVC() {}<br>
+  void Emit(CodeGenFunction &CGF, Flags flags) override {<br>
+    CGF.EmitNounwindRuntimeCall(<br>
+        CGF.CGM.getIntrinsic(llvm::Intrinsic::eh_endcatch));<br>
+  }<br>
+};<br>
+}<br>
+<br>
+void MicrosoftCXXABI::emitBeginCatch(CodeGenFunction &CGF,<br>
+                                     const CXXCatchStmt *S) {<br>
+  // In the MS ABI, the runtime handles the copy, and the catch handler is<br>
+  // responsible for destruction.<br>
+  VarDecl *CatchParam = S->getExceptionDecl();<br>
+  llvm::Value *Exn = CGF.getExceptionFromSlot();<br>
+  llvm::Function *BeginCatch =<br>
+      CGF.CGM.getIntrinsic(llvm::Intrinsic::eh_begincatch);<br>
+<br>
+  if (!CatchParam) {<br>
+    llvm::Value *Args[2] = {Exn, llvm::Constant::getNullValue(CGF.Int8PtrTy)};<br>
+    CGF.EmitNounwindRuntimeCall(BeginCatch, Args);<br>
+    CGF.EHStack.pushCleanup<CallEndCatchMSVC>(NormalAndEHCleanup);<br>
+    return;<br>
+  }<br>
+<br>
+  CodeGenFunction::AutoVarEmission var = CGF.EmitAutoVarAlloca(*CatchParam);<br>
+  llvm::Value *ParamAddr =<br>
+      CGF.Builder.CreateBitCast(var.getObjectAddress(CGF), CGF.Int8PtrTy);<br>
+  llvm::Value *Args[2] = {Exn, ParamAddr};<br>
+  CGF.EmitNounwindRuntimeCall(BeginCatch, Args);<br>
+  // FIXME: Do we really need exceptional endcatch cleanups?<br>
+  CGF.EHStack.pushCleanup<CallEndCatchMSVC>(NormalAndEHCleanup);<br>
+  CGF.EmitAutoVarCleanups(var);<br>
+}<br>
+<br>
 std::pair<llvm::Value *, llvm::Value *><br>
 MicrosoftCXXABI::performBaseAdjustment(CodeGenFunction &CGF, llvm::Value *Value,<br>
                                        QualType SrcRecordTy) {<br>
<br>
Added: cfe/trunk/test/CodeGenCXX/microsoft-abi-eh-catch.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/microsoft-abi-eh-catch.cpp?rev=231105&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/microsoft-abi-eh-catch.cpp?rev=231105&view=auto</a><br>
==============================================================================<br>
--- cfe/trunk/test/CodeGenCXX/microsoft-abi-eh-catch.cpp (added)<br>
+++ cfe/trunk/test/CodeGenCXX/microsoft-abi-eh-catch.cpp Tue Mar  3 13:21:04 2015<br>
@@ -0,0 +1,98 @@<br>
+// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -triple=x86_64-pc-windows-msvc -mconstructor-aliases -fexceptions -fcxx-exceptions | FileCheck -check-prefix WIN64 %s<br>
+<br>
+extern "C" void might_throw();<br>
+<br>
+// Simplify the generated IR with noexcept.<br>
+extern "C" void recover() noexcept(true);<br>
+extern "C" void handle_exception(void *e) noexcept(true);<br>
+<br>
+extern "C" void catch_all() {<br>
+  try {<br>
+    might_throw();<br>
+  } catch (...) {<br>
+    recover();<br>
+  }<br>
+}<br>
+<br>
+// WIN64-LABEL: define void @catch_all()<br>
+// WIN64: invoke void @might_throw()<br>
+// WIN64-NEXT: to label %[[cont:[^ ]*]] unwind label %[[lpad:[^ ]*]]<br>
+//<br>
+// WIN64: [[cont]]<br>
+// WIN64: br label %[[ret:[^ ]*]]<br>
+//<br>
+// WIN64: [[lpad]]<br>
+// WIN64: landingpad { i8*, i32 }<br>
+// WIN64-NEXT: catch i8* null<br>
+// WIN64: call void @llvm.eh.begincatch(i8* %{{[^,]*}}, i8* null)<br>
+// WIN64: call void @recover()<br>
+// WIN64: call void @llvm.eh.endcatch()<br>
+// WIN64: br label %[[ret]]<br>
+//<br>
+// WIN64: [[ret]]<br>
+// WIN64: ret void<br>
+<br>
+extern "C" void catch_int() {<br>
+  try {<br>
+    might_throw();<br>
+  } catch (int e) {<br>
+    handle_exception(&e);<br>
+  }<br>
+}<br>
+<br>
+// WIN64-LABEL: define void @catch_int()<br>
+// WIN64: landingpad { i8*, i32 }<br>
+// WIN64: %[[e_i8:[^ ]*]] = bitcast i32* %[[e_addr:[^ ]*]] to i8*<br>
+// WIN64: call void @llvm.eh.begincatch(i8* %{{.*}}, i8* %[[e_i8]])<br>
+// WIN64: %[[e_i8:[^ ]*]] = bitcast i32* %[[e_addr]] to i8*<br>
+// WIN64: call void @handle_exception(i8* %[[e_i8]])<br>
+// WIN64: call void @llvm.eh.endcatch()<br>
+<br>
+struct A {<br>
+  A();<br>
+  A(const A &o);<br>
+  ~A();<br>
+  int a;<br>
+};<br>
+<br>
+struct B : A {<br>
+  B();<br>
+  B(const B &o);<br>
+  ~B();<br>
+  int b;<br>
+};<br>
+<br>
+extern "C" void catch_a_byval() {<br>
+  try {<br>
+    might_throw();<br>
+  } catch (A e) {<br>
+    handle_exception(&e);<br>
+  }<br>
+}<br>
+<br>
+// WIN64-LABEL: define void @catch_a_byval()<br>
+// WIN64: %[[e_addr:[^ ]*]] = alloca %struct.A<br>
+// WIN64: landingpad { i8*, i32 }<br>
+// WIN64: %[[e_i8:[^ ]*]] = bitcast %struct.A* %[[e_addr]] to i8*<br>
+// WIN64: call void @llvm.eh.begincatch(i8* %{{.*}}, i8* %[[e_i8]])<br>
+// WIN64: %[[e_i8:[^ ]*]] = bitcast %struct.A* %[[e_addr]] to i8*<br>
+// WIN64: call void @handle_exception(i8* %[[e_i8]])<br>
+// WIN64: call void @llvm.eh.endcatch()<br>
+<br>
+extern "C" void catch_a_ref() {<br>
+  try {<br>
+    might_throw();<br>
+  } catch (A &e) {<br>
+    handle_exception(&e);<br>
+  }<br>
+}<br>
+<br>
+// WIN64-LABEL: define void @catch_a_ref()<br>
+// WIN64: %[[e_addr:[^ ]*]] = alloca %struct.A*<br>
+// WIN64: landingpad { i8*, i32 }<br>
+// WIN64: %[[e_i8:[^ ]*]] = bitcast %struct.A** %[[e_addr]] to i8*<br>
+// WIN64: call void @llvm.eh.begincatch(i8* %{{.*}}, i8* %[[e_i8]])<br>
+// WIN64: %[[eptr:[^ ]*]] = load %struct.A*, %struct.A** %[[e_addr]]<br>
+// WIN64: %[[eptr_i8:[^ ]*]] = bitcast %struct.A* %[[eptr]] to i8*<br>
+// WIN64: call void @handle_exception(i8* %[[eptr_i8]])<br>
+// WIN64: call void @llvm.eh.endcatch()<br>
<br>
Copied: cfe/trunk/test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp (from r231098, cfe/trunk/test/CodeGenCXX/microsoft-abi-exceptions.cpp)<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp?p2=cfe/trunk/test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp&p1=cfe/trunk/test/CodeGenCXX/microsoft-abi-exceptions.cpp&r1=231098&r2=231105&rev=231105&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp?p2=cfe/trunk/test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp&p1=cfe/trunk/test/CodeGenCXX/microsoft-abi-exceptions.cpp&r1=231098&r2=231105&rev=231105&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/test/CodeGenCXX/microsoft-abi-exceptions.cpp (original)<br>
+++ cfe/trunk/test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp Tue Mar  3 13:21:04 2015<br>
@@ -1,4 +1,4 @@<br>
-// RUN: %clang_cc1 -emit-llvm %s -o - -triple=i386-pc-win32 -mconstructor-aliases -fexceptions -fno-rtti | FileCheck -check-prefix WIN32 %s<br>
+// RUN: %clang_cc1 -emit-llvm %s -o - -triple=i386-pc-win32 -mconstructor-aliases -fexceptions -fcxx-exceptions -fno-rtti | FileCheck -check-prefix WIN32 %s<br>
<br>
 struct A {<br>
   A();<br>
<br>
Removed: cfe/trunk/test/CodeGenCXX/microsoft-abi-exceptions.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/microsoft-abi-exceptions.cpp?rev=231104&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/microsoft-abi-exceptions.cpp?rev=231104&view=auto</a><br>
==============================================================================<br>
--- cfe/trunk/test/CodeGenCXX/microsoft-abi-exceptions.cpp (original)<br>
+++ cfe/trunk/test/CodeGenCXX/microsoft-abi-exceptions.cpp (removed)<br>
@@ -1,170 +0,0 @@<br>
-// RUN: %clang_cc1 -emit-llvm %s -o - -triple=i386-pc-win32 -mconstructor-aliases -fexceptions -fno-rtti | FileCheck -check-prefix WIN32 %s<br>
-<br>
-struct A {<br>
-  A();<br>
-  ~A();<br>
-  int a;<br>
-};<br>
-<br>
-A getA();<br>
-<br>
-int TakesTwo(A a, A b);<br>
-void HasEHCleanup() {<br>
-  TakesTwo(getA(), getA());<br>
-}<br>
-<br>
-// With exceptions, we need to clean up at least one of these temporaries.<br>
-// WIN32-LABEL: define void @"\01?HasEHCleanup@@YAXXZ"() {{.*}} {<br>
-// WIN32:   %[[base:.*]] = call i8* @llvm.stacksave()<br>
-//    If this call throws, we have to restore the stack.<br>
-// WIN32:   invoke void @"\01?getA@@YA?AUA@@XZ"(%struct.A* sret %{{.*}})<br>
-//    If this call throws, we have to cleanup the first temporary.<br>
-// WIN32:   invoke void @"\01?getA@@YA?AUA@@XZ"(%struct.A* sret %{{.*}})<br>
-//    If this call throws, we have to cleanup the stacksave.<br>
-// WIN32:   invoke i32 @"\01?TakesTwo@@YAHUA@@0@Z"<br>
-// WIN32:   call void @llvm.stackrestore(i8* %[[base]])<br>
-// WIN32:   ret void<br>
-//<br>
-//    There should be one dtor call for unwinding from the second getA.<br>
-// WIN32:   invoke x86_thiscallcc void @"\01??1A@@QAE@XZ"<br>
-// WIN32-NOT: @"\01??1A@@QAE@XZ"<br>
-// WIN32:   call void @llvm.stackrestore<br>
-// WIN32: }<br>
-<br>
-void TakeRef(const A &a);<br>
-int HasDeactivatedCleanups() {<br>
-  return TakesTwo((TakeRef(A()), A()), (TakeRef(A()), A()));<br>
-}<br>
-<br>
-// WIN32-LABEL: define i32 @"\01?HasDeactivatedCleanups@@YAHXZ"() {{.*}} {<br>
-// WIN32:   %[[isactive:.*]] = alloca i1<br>
-// WIN32:   call i8* @llvm.stacksave()<br>
-// WIN32:   %[[argmem:.*]] = alloca inalloca [[argmem_ty:<{ %struct.A, %struct.A }>]]<br>
-// WIN32:   %[[arg1:.*]] = getelementptr inbounds [[argmem_ty]], [[argmem_ty]]* %[[argmem]], i32 0, i32 1<br>
-// WIN32:   invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"<br>
-// WIN32:   invoke void @"\01?TakeRef@@YAXABUA@@@Z"<br>
-//<br>
-// WIN32:   invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"(%struct.A* %[[arg1]])<br>
-// WIN32:   store i1 true, i1* %[[isactive]]<br>
-//<br>
-// WIN32:   %[[arg0:.*]] = getelementptr inbounds [[argmem_ty]], [[argmem_ty]]* %[[argmem]], i32 0, i32 0<br>
-// WIN32:   invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"<br>
-// WIN32:   invoke void @"\01?TakeRef@@YAXABUA@@@Z"<br>
-// WIN32:   invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"<br>
-// WIN32:   store i1 false, i1* %[[isactive]]<br>
-//<br>
-// WIN32:   invoke i32 @"\01?TakesTwo@@YAHUA@@0@Z"([[argmem_ty]]* inalloca %[[argmem]])<br>
-// WIN32:   call void @llvm.stackrestore<br>
-//        Destroy the two const ref temporaries.<br>
-// WIN32:   invoke x86_thiscallcc void @"\01??1A@@QAE@XZ"<br>
-// WIN32:   invoke x86_thiscallcc void @"\01??1A@@QAE@XZ"<br>
-// WIN32:   ret i32<br>
-//<br>
-//        Conditionally destroy arg1.<br>
-// WIN32:   %[[cond:.*]] = load i1, i1* %[[isactive]]<br>
-// WIN32:   br i1 %[[cond]]<br>
-// WIN32:   invoke x86_thiscallcc void @"\01??1A@@QAE@XZ"(%struct.A* %[[arg1]])<br>
-// WIN32: }<br>
-<br>
-// Test putting the cleanups inside a conditional.<br>
-int CouldThrow();<br>
-int HasConditionalCleanup(bool cond) {<br>
-  return (cond ? TakesTwo(A(), A()) : CouldThrow());<br>
-}<br>
-<br>
-// WIN32-LABEL: define i32 @"\01?HasConditionalCleanup@@YAH_N@Z"(i1 zeroext %{{.*}}) {{.*}} {<br>
-// WIN32:   store i1 false<br>
-// WIN32:   br i1<br>
-// WIN32:   call i8* @llvm.stacksave()<br>
-// WIN32:   invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"(%struct.A* %{{.*}})<br>
-// WIN32:   store i1 true<br>
-// WIN32:   invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"(%struct.A* %{{.*}})<br>
-// WIN32:   invoke i32 @"\01?TakesTwo@@YAHUA@@0@Z"<br>
-// WIN32:   call void @llvm.stackrestore<br>
-//<br>
-// WIN32:   call i32 @"\01?CouldThrow@@YAHXZ"()<br>
-//<br>
-//        Only one dtor in the invoke for arg1<br>
-// WIN32:   invoke x86_thiscallcc void @"\01??1A@@QAE@XZ"({{.*}})<br>
-// WIN32-NOT: invoke x86_thiscallcc void @"\01??1A@@QAE@XZ"<br>
-// WIN32:   call void @llvm.stackrestore<br>
-// WIN32: }<br>
-<br>
-// Now test both.<br>
-int HasConditionalDeactivatedCleanups(bool cond) {<br>
-  return (cond ? TakesTwo((TakeRef(A()), A()), (TakeRef(A()), A())) : CouldThrow());<br>
-}<br>
-<br>
-// WIN32-LABEL: define i32 @"\01?HasConditionalDeactivatedCleanups@@YAH_N@Z"{{.*}} {<br>
-// WIN32:   alloca i1<br>
-// WIN32:   %[[arg1_cond:.*]] = alloca i1<br>
-//        Start all four cleanups as deactivated.<br>
-// WIN32:   store i1 false<br>
-// WIN32:   store i1 false<br>
-// WIN32:   store i1 false<br>
-// WIN32:   store i1 false<br>
-// WIN32:   br i1<br>
-//        True condition.<br>
-// WIN32:   invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"<br>
-// WIN32:   store i1 true<br>
-// WIN32:   invoke void @"\01?TakeRef@@YAXABUA@@@Z"<br>
-// WIN32:   invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"<br>
-// WIN32:   store i1 true, i1* %[[arg1_cond]]<br>
-// WIN32:   invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"<br>
-// WIN32:   store i1 true<br>
-// WIN32:   invoke void @"\01?TakeRef@@YAXABUA@@@Z"<br>
-// WIN32:   invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"<br>
-// WIN32:   store i1 true<br>
-// WIN32:   store i1 false, i1* %[[arg1_cond]]<br>
-// WIN32:   invoke i32 @"\01?TakesTwo@@YAHUA@@0@Z"<br>
-//        False condition.<br>
-// WIN32:   invoke i32 @"\01?CouldThrow@@YAHXZ"()<br>
-//        Two normal cleanups for TakeRef args.<br>
-// WIN32:   invoke x86_thiscallcc void @"\01??1A@@QAE@XZ"<br>
-// WIN32:   invoke x86_thiscallcc void @"\01??1A@@QAE@XZ"<br>
-// WIN32:   ret i32<br>
-//<br>
-//        Somewhere in the landing pad soup, we conditionally destroy arg1.<br>
-// WIN32:   %[[isactive:.*]] = load i1, i1* %[[arg1_cond]]<br>
-// WIN32:   br i1 %[[isactive]]<br>
-// WIN32:   invoke x86_thiscallcc void @"\01??1A@@QAE@XZ"<br>
-// WIN32: }<br>
-<br>
-namespace crash_on_partial_destroy {<br>
-struct A {<br>
-  virtual ~A();<br>
-};<br>
-<br>
-struct B : virtual A {<br>
-  // Has an implicit destructor.<br>
-};<br>
-<br>
-struct C : B {<br>
-  C();<br>
-};<br>
-<br>
-void foo();<br>
-// We used to crash when emitting this.<br>
-C::C() { foo(); }<br>
-<br>
-// Verify that we don't bother with a vbtable lookup when adjusting the this<br>
-// pointer to call a base destructor from a constructor while unwinding.<br>
-// WIN32-LABEL: define {{.*}} @"\01??0C@crash_on_partial_destroy@@QAE@XZ"{{.*}} {<br>
-// WIN32:      landingpad<br>
-//<br>
-//        We shouldn't do any vbptr loads, just constant GEPs.<br>
-// WIN32-NOT:  load<br>
-// WIN32:      getelementptr i8, i8* %{{.*}}, i32 4<br>
-// WIN32-NOT:  load<br>
-// WIN32:      bitcast i8* %{{.*}} to %"struct.crash_on_partial_destroy::B"*<br>
-// WIN32:      invoke x86_thiscallcc void @"\01??1B@crash_on_partial_destroy@@UAE@XZ"<br>
-//<br>
-// WIN32-NOT:  load<br>
-// WIN32:      bitcast %"struct.crash_on_partial_destroy::C"* %{{.*}} to i8*<br>
-// WIN32-NOT:  load<br>
-// WIN32:      getelementptr inbounds i8, i8* %{{.*}}, i64 4<br>
-// WIN32-NOT:  load<br>
-// WIN32:      bitcast i8* %{{.*}} to %"struct.crash_on_partial_destroy::A"*<br>
-// WIN32:      invoke x86_thiscallcc void @"\01??1A@crash_on_partial_destroy@@UAE@XZ"<br>
-// WIN32: }<br>
-}<br>
<br>
Modified: cfe/trunk/test/CodeGenCXX/microsoft-abi-try-throw.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/microsoft-abi-try-throw.cpp?rev=231105&r1=231104&r2=231105&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/microsoft-abi-try-throw.cpp?rev=231105&r1=231104&r2=231105&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/test/CodeGenCXX/microsoft-abi-try-throw.cpp (original)<br>
+++ cfe/trunk/test/CodeGenCXX/microsoft-abi-try-throw.cpp Tue Mar  3 13:21:04 2015<br>
@@ -1,5 +1,4 @@<br>
-// FIXME: Disabled until catch IRgen change lands.<br>
-// RUNX: %clang_cc1 -emit-llvm %s -o - -triple=i386-pc-win32 -mconstructor-aliases -fcxx-exceptions -fexceptions -fno-rtti -DTRY   | FileCheck %s -check-prefix=TRY<br>
+// RUN: %clang_cc1 -emit-llvm %s -o - -triple=i386-pc-win32 -mconstructor-aliases -fcxx-exceptions -fexceptions -fno-rtti -DTRY   | FileCheck %s -check-prefix=TRY<br>
 // RUN: %clang_cc1 -emit-llvm %s -o - -triple=i386-pc-win32 -mconstructor-aliases -fcxx-exceptions -fexceptions -fno-rtti -DTHROW | FileCheck %s -check-prefix=THROW<br>
<br>
 void external();<br>
@@ -15,8 +14,8 @@ int main() {<br>
     external(); // TRY: invoke void @"\01?external@@YAXXZ"<br>
   } catch (int) {<br>
     rv = 1;<br>
-    // TRY: call i8* @llvm.eh.begincatch<br>
-    // TRY: call void @llvm.eh.endcatch<br>
+    // TRY: call void @llvm.eh.begincatch(i8* %{{.*}}, i8* %{{.*}})<br>
+    // TRY: call void @llvm.eh.endcatch()<br>
   }<br>
 #endif<br>
 #ifdef THROW<br>
<br>
<br>
_______________________________________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@cs.uiuc.edu">cfe-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits</a><br>
</blockquote></div><br></div>