diff --git a/clang/lib/CodeGen/CGCleanup.cpp b/clang/lib/CodeGen/CGCleanup.cpp --- a/clang/lib/CodeGen/CGCleanup.cpp +++ b/clang/lib/CodeGen/CGCleanup.cpp @@ -207,8 +207,13 @@ Scope->setLifetimeMarker(); // With Windows -EHa, Invoke llvm.seh.scope.begin() for EHCleanup + // If exceptions are disabled/ignored and SEH is not in use, then there is no + // invoke destination. SEH "works" even if exceptions are off. In practice, + // this means that C++ destructors and other EH cleanups don't run, which is + // consistent with MSVC's behavior, except in the presence of -EHa. + // Check getInvokeDest() to generate llvm.seh.scope.begin() as needed. if (CGF->getLangOpts().EHAsynch && IsEHCleanup && !IsLifetimeMarker && - CGF->getTarget().getCXXABI().isMicrosoft()) + CGF->getTarget().getCXXABI().isMicrosoft() && CGF->getInvokeDest()) CGF->EmitSehCppScopeBegin(); return Scope->getCleanupBuffer(); diff --git a/clang/test/CodeGen/windows-seh-async-exceptions.cpp b/clang/test/CodeGen/windows-seh-async-exceptions.cpp new file mode 100644 --- /dev/null +++ b/clang/test/CodeGen/windows-seh-async-exceptions.cpp @@ -0,0 +1,23 @@ +// RUN: %clang_cc1 -triple x86_64-windows -fasync-exceptions -x c++ \ +// RUN: -emit-llvm %s -o -| FileCheck %s + + +extern "C" int printf(const char*,...); +class PrintfArg +{ +public: + PrintfArg(); + PrintfArg(const char* s); + + // compiler crash fixed if this destructor removed + ~PrintfArg() {int x; printf("ddd\n"); } +}; + +void devif_Warning(const char* fmt, PrintfArg arg1 = PrintfArg()); +// CHECK-NOT: invoke void @llvm.seh.scope.begin() +// CHECK-NOT: invoke void @llvm.seh.scope.end() +unsigned myfunc(unsigned index) +{ + devif_Warning(""); + return 0; +}