diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -4841,6 +4841,10 @@ } else { // Otherwise, nounwind call sites will never throw. CannotThrow = Attrs.hasFnAttribute(llvm::Attribute::NoUnwind); + + if (auto *FPtr = dyn_cast(CalleePtr)) + if (FPtr->hasFnAttribute(llvm::Attribute::NoUnwind)) + CannotThrow = true; } // If we made a temporary, be sure to clean up after ourselves. Note that we diff --git a/clang/test/CodeGenCXX/debug-info-class.cpp b/clang/test/CodeGenCXX/debug-info-class.cpp --- a/clang/test/CodeGenCXX/debug-info-class.cpp +++ b/clang/test/CodeGenCXX/debug-info-class.cpp @@ -13,7 +13,7 @@ virtual ~B(); }; -B::~B() { +B::~B() { extern void mayThrow(); mayThrow(); } struct C { diff --git a/clang/test/CodeGenObjCXX/arc-list-init-destruct.mm b/clang/test/CodeGenObjCXX/arc-list-init-destruct.mm --- a/clang/test/CodeGenObjCXX/arc-list-init-destruct.mm +++ b/clang/test/CodeGenObjCXX/arc-list-init-destruct.mm @@ -16,6 +16,8 @@ }; bool getBool() { + extern void mayThrow(); + mayThrow(); return false; } diff --git a/clang/test/CodeGenObjCXX/os_log.mm b/clang/test/CodeGenObjCXX/os_log.mm --- a/clang/test/CodeGenObjCXX/os_log.mm +++ b/clang/test/CodeGenObjCXX/os_log.mm @@ -6,13 +6,14 @@ void release(int *lock); // CHECK-LABEL: define {{.*}} @_ZN13no_eh_cleanup3logERiPcS1_( + // CHECK: call void @__os_log_helper_1_2_2_4_0_8_34( + void log(int &i, char *data, char *buf) { int lock __attribute__((cleanup(release))); __builtin_os_log_format(buf, "%d %{public}s", i, data); } - // An `invoke` of a `nounwind` callee is simplified to a direct - // call by an optimization in llvm. Just check that we emit `nounwind`. + // Check that the os_log_helper is marked `nounwind`. // CHECK: define {{.*}} @__os_log_helper_1_2_2_4_0_8_34({{.*}} [[NUW:#[0-9]+]] } diff --git a/clang/test/OpenMP/atomic_codegen.cpp b/clang/test/OpenMP/atomic_codegen.cpp --- a/clang/test/OpenMP/atomic_codegen.cpp +++ b/clang/test/OpenMP/atomic_codegen.cpp @@ -82,7 +82,7 @@ } } -int &foo() { return a; } +int &foo() { extern void mayThrow(); mayThrow(); return a; } // TERM_DEBUG-LABEL: parallel_atomic void parallel_atomic() { diff --git a/clang/test/OpenMP/critical_codegen.cpp b/clang/test/OpenMP/critical_codegen.cpp --- a/clang/test/OpenMP/critical_codegen.cpp +++ b/clang/test/OpenMP/critical_codegen.cpp @@ -22,7 +22,7 @@ // ALL: define {{.*}}void [[FOO:@.+]]() -void foo() {} +void foo() { extern void mayThrow(); mayThrow(); } // ALL-LABEL: @main // TERM_DEBUG-LABEL: @main diff --git a/clang/test/OpenMP/distribute_parallel_for_num_threads_codegen.cpp b/clang/test/OpenMP/distribute_parallel_for_num_threads_codegen.cpp --- a/clang/test/OpenMP/distribute_parallel_for_num_threads_codegen.cpp +++ b/clang/test/OpenMP/distribute_parallel_for_num_threads_codegen.cpp @@ -22,7 +22,7 @@ struct S { intptr_t a, b, c; S(intptr_t a) : a(a) {} - operator char() { return a; } + operator char() { extern void mayThrow(); mayThrow(); return a; } ~S() {} }; diff --git a/clang/test/OpenMP/distribute_parallel_for_simd_num_threads_codegen.cpp b/clang/test/OpenMP/distribute_parallel_for_simd_num_threads_codegen.cpp --- a/clang/test/OpenMP/distribute_parallel_for_simd_num_threads_codegen.cpp +++ b/clang/test/OpenMP/distribute_parallel_for_simd_num_threads_codegen.cpp @@ -22,7 +22,7 @@ struct S { intptr_t a, b, c; S(intptr_t a) : a(a) {} - operator char() { return a; } + operator char() { extern void mayThrow(); mayThrow(); return a; } ~S() {} }; diff --git a/clang/test/OpenMP/for_codegen.cpp b/clang/test/OpenMP/for_codegen.cpp --- a/clang/test/OpenMP/for_codegen.cpp +++ b/clang/test/OpenMP/for_codegen.cpp @@ -536,7 +536,7 @@ } // TERM_DEBUG-LABEL: foo -int foo() {return 0;}; +int foo() { extern void mayThrow(); mayThrow(); return 0;}; // TERM_DEBUG-LABEL: parallel_for void parallel_for(float *a) { diff --git a/clang/test/OpenMP/for_simd_codegen.cpp b/clang/test/OpenMP/for_simd_codegen.cpp --- a/clang/test/OpenMP/for_simd_codegen.cpp +++ b/clang/test/OpenMP/for_simd_codegen.cpp @@ -20,7 +20,7 @@ #ifndef HEADER #define HEADER -long long get_val() { return 0; } +long long get_val() { extern void mayThrow(); mayThrow(); return 0; } double *g_ptr; // CHECK-LABEL: define {{.*void}} @{{.*}}simple{{.*}}(float* {{.+}}, float* {{.+}}, float* {{.+}}, float* {{.+}}) @@ -785,7 +785,7 @@ } // TERM_DEBUG-LABEL: bar -int bar() {return 0;}; +int bar() { extern void mayThrow(); mayThrow(); return 0; }; // TERM_DEBUG-LABEL: parallel_simd void parallel_simd(float *a) { diff --git a/clang/test/OpenMP/master_codegen.cpp b/clang/test/OpenMP/master_codegen.cpp --- a/clang/test/OpenMP/master_codegen.cpp +++ b/clang/test/OpenMP/master_codegen.cpp @@ -19,7 +19,7 @@ // ALL: define {{.*}}void [[FOO:@.+]]() -void foo() {} +void foo() { extern void mayThrow(); mayThrow(); } // ALL-LABEL: @main // TERM_DEBUG-LABEL: @main diff --git a/clang/test/OpenMP/parallel_for_codegen.cpp b/clang/test/OpenMP/parallel_for_codegen.cpp --- a/clang/test/OpenMP/parallel_for_codegen.cpp +++ b/clang/test/OpenMP/parallel_for_codegen.cpp @@ -372,7 +372,7 @@ } // TERM_DEBUG-LABEL: foo -int foo() {return 0;}; +int foo() { extern void mayThrow(); mayThrow(); return 0; }; // TERM_DEBUG-LABEL: parallel_for // CLEANUP: parallel_for diff --git a/clang/test/OpenMP/parallel_for_simd_codegen.cpp b/clang/test/OpenMP/parallel_for_simd_codegen.cpp --- a/clang/test/OpenMP/parallel_for_simd_codegen.cpp +++ b/clang/test/OpenMP/parallel_for_simd_codegen.cpp @@ -22,7 +22,7 @@ #ifndef HEADER #define HEADER -long long get_val() { return 0; } +long long get_val() { extern void mayThrow(); mayThrow(); return 0; } double *g_ptr; // CHECK-LABEL: define {{.*void}} @{{.*}}simple{{.*}}(float* {{.+}}, float* {{.+}}, float* {{.+}}, float* {{.+}}) @@ -801,7 +801,7 @@ // OMP50-DAG: ![[NOVM]] = !{!"llvm.loop.vectorize.enable", i1 false} // TERM_DEBUG-LABEL: bar -int bar() {return 0;}; +int bar() { extern void mayThrow(); mayThrow(); return 0; }; // TERM_DEBUG-LABEL: parallel_simd void parallel_simd(float *a) { diff --git a/clang/test/OpenMP/parallel_master_codegen.cpp b/clang/test/OpenMP/parallel_master_codegen.cpp --- a/clang/test/OpenMP/parallel_master_codegen.cpp +++ b/clang/test/OpenMP/parallel_master_codegen.cpp @@ -18,7 +18,7 @@ // CK1-DAG: [[DEF_LOC:@.+]] = private unnamed_addr global %struct.ident_t { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* [[STR]], i32 0, i32 0) } // CK1-LABEL: foo -void foo() {} +void foo() { extern void mayThrow(); mayThrow(); } void parallel_master() { #pragma omp parallel master diff --git a/clang/test/OpenMP/parallel_num_threads_codegen.cpp b/clang/test/OpenMP/parallel_num_threads_codegen.cpp --- a/clang/test/OpenMP/parallel_num_threads_codegen.cpp +++ b/clang/test/OpenMP/parallel_num_threads_codegen.cpp @@ -22,7 +22,7 @@ struct S { intptr_t a, b, c; S(intptr_t a) : a(a) {} - operator char() { return a; } + operator char() { extern void mayThrow(); mayThrow(); return a; } ~S() {} }; diff --git a/clang/test/OpenMP/parallel_sections_codegen.cpp b/clang/test/OpenMP/parallel_sections_codegen.cpp --- a/clang/test/OpenMP/parallel_sections_codegen.cpp +++ b/clang/test/OpenMP/parallel_sections_codegen.cpp @@ -10,9 +10,9 @@ #ifndef HEADER #define HEADER // CHECK-LABEL: foo -void foo() {}; +void foo() { extern void mayThrow(); mayThrow(); }; // CHECK-LABEL: bar -void bar() {}; +void bar() { extern void mayThrow(); mayThrow(); }; template T tmain() { diff --git a/clang/test/OpenMP/sections_codegen.cpp b/clang/test/OpenMP/sections_codegen.cpp --- a/clang/test/OpenMP/sections_codegen.cpp +++ b/clang/test/OpenMP/sections_codegen.cpp @@ -12,9 +12,9 @@ // CHECK-DAG: [[IMPLICIT_BARRIER_SECTIONS_LOC:@.+]] = private unnamed_addr global %{{.+}} { i32 0, i32 194, i32 0, i32 0, i8* // CHECK-DAG: [[SECTIONS_LOC:@.+]] = private unnamed_addr global %{{.+}} { i32 0, i32 1026, i32 0, i32 0, i8* // CHECK-LABEL: foo -void foo() {}; +void foo() { extern void mayThrow(); mayThrow(); }; // CHECK-LABEL: bar -void bar() {}; +void bar() { extern void mayThrow(); mayThrow(); }; template T tmain() { diff --git a/clang/test/OpenMP/simd_codegen.cpp b/clang/test/OpenMP/simd_codegen.cpp --- a/clang/test/OpenMP/simd_codegen.cpp +++ b/clang/test/OpenMP/simd_codegen.cpp @@ -26,7 +26,7 @@ // OMP50-DAG: [[LAST_IV:@.+]] = {{.*}}common global i64 0 // OMP50-DAG: [[LAST_A:@.+]] = {{.*}}common global i32 0 -long long get_val() { return 0; } +long long get_val() { extern void mayThrow(); mayThrow(); return 0; } double *g_ptr; struct S { @@ -798,7 +798,7 @@ #endif // OMP5 // TERM_DEBUG-LABEL: bar -int bar() {return 0;}; +int bar() { extern void mayThrow(); mayThrow(); return 0; }; // TERM_DEBUG-LABEL: parallel_simd void parallel_simd(float *a) { diff --git a/clang/test/OpenMP/single_codegen.cpp b/clang/test/OpenMP/single_codegen.cpp --- a/clang/test/OpenMP/single_codegen.cpp +++ b/clang/test/OpenMP/single_codegen.cpp @@ -42,7 +42,7 @@ TestClass tc2[2]; #pragma omp threadprivate(tc, tc2) -void foo() {} +void foo() { extern void mayThrow(); mayThrow(); } struct SS { int a; diff --git a/clang/test/OpenMP/taskgroup_codegen.cpp b/clang/test/OpenMP/taskgroup_codegen.cpp --- a/clang/test/OpenMP/taskgroup_codegen.cpp +++ b/clang/test/OpenMP/taskgroup_codegen.cpp @@ -16,7 +16,7 @@ // CHECK: define {{.*}}void [[FOO:@.+]]() -void foo() {} +void foo() { extern void mayThrow(); mayThrow(); } // CHECK-LABEL: @main // TERM_DEBUG-LABEL: @main