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,7 +477,10 @@ return; ExceptionSpecificationType EST = Proto->getExceptionSpecType(); - if (isNoexceptExceptionSpec(EST) && Proto->canThrow() == CT_Cannot) { + // In C++17 and later, 'throw()' aka EST_DynamicNone is treated the same way + // as noexcept. In earlier standards, it is handled separately, below. + if ((getLangOpts().CPlusPlus17 || EST != EST_DynamicNone) && + Proto->canThrow() == CT_Cannot) { // noexcept functions are simple terminate scopes. if (!getLangOpts().EHAsynch) // -EHa: HW exception still can occur EHStack.pushTerminate(); @@ -580,7 +583,8 @@ return; ExceptionSpecificationType EST = Proto->getExceptionSpecType(); - if (isNoexceptExceptionSpec(EST) && Proto->canThrow() == CT_Cannot && + if ((getLangOpts().CPlusPlus17 || EST != EST_DynamicNone) && + Proto->canThrow() == CT_Cannot && !EHStack.empty() /* possible empty when under async exceptions */) { EHStack.popTerminate(); } else if (EST == EST_Dynamic || EST == EST_DynamicNone) { 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(); +}