The following simple test should terminate (calling std::terminate), but it catches the exception thrown in the copy constructor due to incorrect code generated by clang:
include
struct C
{
C() { }
C(const C&) { throw 0; }
};
int main()
{
try
{
C cc;
throw cc; // should call std::terminate()
}
catch(int) {puts("caught int");}
catch(C) {puts("caught C");}
}
Here is llvm bitcode corresponding to throwing exception:
Extended Description
The following simple test should terminate (calling std::terminate), but it catches the exception thrown in the copy constructor due to incorrect code generated by clang:
include
struct C { C() { } C(const C&) { throw 0; } };
int main() { try { C cc; throw cc; // should call std::terminate() } catch(int) {puts("caught int");} catch(C) {puts("caught C");} }
Here is llvm bitcode corresponding to throwing exception:
invoke.cont: ; preds = %entry %exception = call i8 @__cxa_allocate_exception(i64 1) nounwind %2 = bitcast i8 %exception to %struct.C invoke void @ZN1CC1ERKS(%struct.C %2, %struct.C* %cc) to label %invoke.cont2 unwind label %lpad1
invoke.cont2: ; preds = %invoke.cont invoke void @__cxa_throw(i8 %exception, i8 bitcast ({ i8, i8 } @_ZTI1C to i8), i8* null) noreturn to label %unreachable unwind label %lpad
lpad: ; preds = %invoke.cont2, %entry %3 = landingpad { i8, i32 } personality i8 bitcast (i32 (...) @__gxx_personality_v0 to i8) catch i8* bitcast (i8 @_ZTIi to i8) catch i8 bitcast ({ i8, i8 } @_ZTI1C to i8) %4 = extractvalue { i8, i32 } %3, 0 store i8 %4, i8 %exn.slot %5 = extractvalue { i8, i32 } %3, 1 store i32 %5, i32 %ehselector.slot br label %catch.dispatch
lpad1: ; preds = %invoke.cont %6 = landingpad { i8, i32 } personality i8 bitcast (i32 (...) @__gxx_personality_v0 to i8) cleanup catch i8* bitcast (i8 @_ZTIi to i8) catch i8 bitcast ({ i8, i8 } @_ZTI1C to i8) %7 = extractvalue { i8, i32 } %6, 0 store i8 %7, i8 %exn.slot %8 = extractvalue { i8, i32 } %6, 1 store i32 %8, i32 %ehselector.slot call void @__cxa_free_exception(i8* %exception) nounwind br label %catch.dispatch
A call to copy constructor should be in a terminate context, but it's not (unwind edge points to the incorrect landingpad %lpad1).
Alexey Bataev Software Engineer Intel Compiler Team Intel Corp.