diff --git a/clang/lib/CodeGen/CGException.cpp b/clang/lib/CodeGen/CGException.cpp --- a/clang/lib/CodeGen/CGException.cpp +++ b/clang/lib/CodeGen/CGException.cpp @@ -477,11 +477,11 @@ return; ExceptionSpecificationType EST = Proto->getExceptionSpecType(); - if (isNoexceptExceptionSpec(EST) && Proto->canThrow() == CT_Cannot) { - // noexcept functions are simple terminate scopes. - if (!getLangOpts().EHAsynch) // -EHa: HW exception still can occur - EHStack.pushTerminate(); - } else if (EST == EST_Dynamic || EST == EST_DynamicNone) { + // In C++17 and later, 'throw()' aka EST_DynamicNone is treated the same way + // as noexcept. In earlier standards, it is handled in this block, along with + // 'throw(X...)'. + if (EST == EST_Dynamic || + (EST == EST_DynamicNone && !getLangOpts().CPlusPlus17)) { // TODO: Revisit exception specifications for the MS ABI. There is a way to // encode these in an object file but MSVC doesn't do anything with it. if (getTarget().getCXXABI().isMicrosoft()) @@ -521,6 +521,10 @@ /*ForEH=*/true); Filter->setFilter(I, EHType); } + } else if (Proto->canThrow() == CT_Cannot) { + // noexcept functions are simple terminate scopes. + if (!getLangOpts().EHAsynch) // -EHa: HW exception still can occur + EHStack.pushTerminate(); } } @@ -580,10 +584,8 @@ return; ExceptionSpecificationType EST = Proto->getExceptionSpecType(); - if (isNoexceptExceptionSpec(EST) && Proto->canThrow() == CT_Cannot && - !EHStack.empty() /* possible empty when under async exceptions */) { - EHStack.popTerminate(); - } else if (EST == EST_Dynamic || EST == EST_DynamicNone) { + if (EST == EST_Dynamic || + (EST == EST_DynamicNone && !getLangOpts().CPlusPlus17)) { // TODO: Revisit exception specifications for the MS ABI. There is a way to // encode these in an object file but MSVC doesn't do anything with it. if (getTarget().getCXXABI().isMicrosoft()) @@ -599,6 +601,10 @@ EHFilterScope &filterScope = cast(*EHStack.begin()); emitFilterDispatchBlock(*this, filterScope); EHStack.popFilter(); + } else if (Proto->canThrow() == CT_Cannot && + /* possible empty when under async exceptions */ + !EHStack.empty()) { + EHStack.popTerminate(); } } diff --git a/clang/test/CXX/except/except.spec/p9-dynamic.cpp b/clang/test/CXX/except/except.spec/p9-dynamic.cpp --- a/clang/test/CXX/except/except.spec/p9-dynamic.cpp +++ b/clang/test/CXX/except/except.spec/p9-dynamic.cpp @@ -1,12 +1,26 @@ -// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm -o - -fcxx-exceptions -fexceptions | FileCheck %s +// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm -o - -fcxx-exceptions -fexceptions | FileCheck %s --check-prefixes=CHECK,CHECK-PRE17 +// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -std=c++17 -Wno-dynamic-exception-spec -emit-llvm -o - -fcxx-exceptions -fexceptions | FileCheck %s --check-prefixes=CHECK,CHECK-17 void external(); +// CHECK-LABEL: _Z6targetv( +// CHECK: invoke void @_Z8externalv() +// CHECK: landingpad { i8*, i32 } +// CHECK-NEXT: filter [1 x i8*] [i8* bitcast (i8** @_ZTIi to i8*)] +// CHECK: call void @__cxa_call_unexpected void target() throw(int) { - // CHECK: invoke void @_Z8externalv() external(); } -// CHECK: landingpad { i8*, i32 } -// CHECK-NEXT: filter [1 x i8*] [i8* bitcast (i8** @_ZTIi to i8*)] -// CHECK: call void @__cxa_call_unexpected + +// CHECK-LABEL: _Z7target2v( +// CHECK: invoke void @_Z8externalv() +// CHECK: landingpad { i8*, i32 } +// CHECK-PRE17-NEXT: filter [0 x i8*] zeroinitializer +// CHECK-17-NEXT: catch i8* null +// CHECK-PRE17: call void @__cxa_call_unexpected +// CHECK-17: call void @__clang_call_terminate +void target2() throw() +{ + external(); +}