} else {
// Otherwise, nounwind call sites will never throw.
CannotThrow = Attrs.hasFnAttribute(llvm::Attribute::NoUnwind);
+
+ if (auto *FPtr = dyn_cast<llvm::Function>(CalleePtr))
+ if (FPtr->hasFnAttribute(llvm::Attribute::NoUnwind))
+ CannotThrow = true;
}
// If we made a temporary, be sure to clean up after ourselves. Note that we
virtual ~B();
};
-B::~B() {
+B::~B() { extern void mayThrow(); mayThrow();
}
struct C {
};
bool getBool() {
+ extern void mayThrow();
+ mayThrow();
return false;
}
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]+]]
}
}
}
-int &foo() { return a; }
+int &foo() { extern void mayThrow(); mayThrow(); return a; }
// TERM_DEBUG-LABEL: parallel_atomic
void parallel_atomic() {
// ALL: define {{.*}}void [[FOO:@.+]]()
-void foo() {}
+void foo() { extern void mayThrow(); mayThrow(); }
// ALL-LABEL: @main
// TERM_DEBUG-LABEL: @main
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() {}
};
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() {}
};
}
// 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) {
#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* {{.+}})
}
// 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) {
// ALL: define {{.*}}void [[FOO:@.+]]()
-void foo() {}
+void foo() { extern void mayThrow(); mayThrow(); }
// ALL-LABEL: @main
// TERM_DEBUG-LABEL: @main
}
// TERM_DEBUG-LABEL: foo
-int foo() {return 0;};
+int foo() { extern void mayThrow(); mayThrow(); return 0; };
// TERM_DEBUG-LABEL: parallel_for
// CLEANUP: parallel_for
#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* {{.+}})
// 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) {
// 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
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() {}
};
#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 <class T>
T tmain() {
// 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 <class T>
T tmain() {
// 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 {
#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) {
TestClass tc2[2];
#pragma omp threadprivate(tc, tc2)
-void foo() {}
+void foo() { extern void mayThrow(); mayThrow(); }
struct SS {
int a;
// CHECK: define {{.*}}void [[FOO:@.+]]()
-void foo() {}
+void foo() { extern void mayThrow(); mayThrow(); }
// CHECK-LABEL: @main
// TERM_DEBUG-LABEL: @main