1; RUN: opt -lint -disable-output < %s 2>&1 | FileCheck %s 2 3; This test is meant to prove that the Verifier is able to identify a variety 4; of errors with the llvm.eh.begincatch and llvm.eh.endcatch intrinsics. 5; See cppeh-catch-intrinsics-clean for correct uses. 6 7target triple = "x86_64-pc-windows-msvc" 8 9declare void @llvm.eh.begincatch(i8*, i8*) 10 11declare void @llvm.eh.endcatch() 12 13@_ZTIi = external constant i8* 14 15; Function Attrs: uwtable 16define void @test_missing_endcatch() { 17; CHECK: Some paths from llvm.eh.begincatch may not reach llvm.eh.endcatch 18; CHECK-NEXT: call void @llvm.eh.begincatch(i8* %exn, i8* null) 19entry: 20 invoke void @_Z9may_throwv() 21 to label %try.cont unwind label %lpad 22 23lpad: ; preds = %entry 24 %0 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) 25 catch i8* bitcast (i8** @_ZTIi to i8*) 26 %exn = extractvalue { i8*, i32 } %0, 0 27 %sel = extractvalue { i8*, i32 } %0, 1 28 %1 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*)) 29 %matches = icmp eq i32 %sel, %1 30 br i1 %matches, label %catch, label %eh.resume 31 32catch: ; preds = %lpad 33 call void @llvm.eh.begincatch(i8* %exn, i8* null) 34 call void @_Z10handle_intv() 35 br label %invoke.cont2 36 37invoke.cont2: ; preds = %catch 38 br label %try.cont 39 40try.cont: ; preds = %invoke.cont2, %entry 41 ret void 42 43eh.resume: ; preds = %catch.dispatch 44 resume { i8*, i32 } %0 45} 46 47; Function Attrs: uwtable 48define void @test_missing_begincatch() { 49; CHECK: llvm.eh.endcatch may be reachable without passing llvm.eh.begincatch 50; CHECK-NEXT: call void @llvm.eh.endcatch() 51entry: 52 invoke void @_Z9may_throwv() 53 to label %try.cont unwind label %lpad 54 55lpad: ; preds = %entry 56 %0 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) 57 catch i8* bitcast (i8** @_ZTIi to i8*) 58 %exn = extractvalue { i8*, i32 } %0, 0 59 %sel = extractvalue { i8*, i32 } %0, 1 60 %1 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*)) 61 %matches = icmp eq i32 %sel, %1 62 br i1 %matches, label %catch, label %eh.resume 63 64catch: ; preds = %lpad 65 call void @_Z10handle_intv() 66 br label %invoke.cont2 67 68invoke.cont2: ; preds = %catch 69 call void @llvm.eh.endcatch() 70 br label %try.cont 71 72try.cont: ; preds = %invoke.cont2, %entry 73 ret void 74 75eh.resume: ; preds = %catch.dispatch 76 resume { i8*, i32 } %0 77} 78 79; Function Attrs: uwtable 80define void @test_multiple_begin() { 81; CHECK: llvm.eh.begincatch may be called a second time before llvm.eh.endcatch 82; CHECK-NEXT: call void @llvm.eh.begincatch(i8* %exn, i8* null) 83; CHECK-NEXT: call void @llvm.eh.begincatch(i8* %exn, i8* null) 84entry: 85 invoke void @_Z9may_throwv() 86 to label %try.cont unwind label %lpad 87 88lpad: ; preds = %entry 89 %0 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) 90 catch i8* bitcast (i8** @_ZTIi to i8*) 91 %exn = extractvalue { i8*, i32 } %0, 0 92 %sel = extractvalue { i8*, i32 } %0, 1 93 %1 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*)) 94 %matches = icmp eq i32 %sel, %1 95 br i1 %matches, label %catch, label %eh.resume 96 97catch: ; preds = %lpad 98 call void @llvm.eh.begincatch(i8* %exn, i8* null) 99 call void @_Z10handle_intv() 100 br label %invoke.cont2 101 102invoke.cont2: ; preds = %catch 103 call void @llvm.eh.begincatch(i8* %exn, i8* null) 104 call void @llvm.eh.endcatch() 105 br label %try.cont 106 107try.cont: ; preds = %invoke.cont2, %entry 108 ret void 109 110eh.resume: ; preds = %catch.dispatch 111 resume { i8*, i32 } %0 112} 113 114; Function Attrs: uwtable 115define void @test_multiple_end() { 116; CHECK: llvm.eh.endcatch may be called a second time after llvm.eh.begincatch 117; CHECK-NEXT: call void @llvm.eh.endcatch() 118; CHECK-NEXT: call void @llvm.eh.endcatch() 119entry: 120 invoke void @_Z9may_throwv() 121 to label %try.cont unwind label %lpad 122 123lpad: ; preds = %entry 124 %0 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) 125 catch i8* bitcast (i8** @_ZTIi to i8*) 126 %exn = extractvalue { i8*, i32 } %0, 0 127 %sel = extractvalue { i8*, i32 } %0, 1 128 %1 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*)) 129 %matches = icmp eq i32 %sel, %1 130 br i1 %matches, label %catch, label %eh.resume 131 132catch: ; preds = %lpad 133 call void @llvm.eh.begincatch(i8* %exn, i8* null) 134 call void @_Z10handle_intv() 135 call void @llvm.eh.endcatch() 136 br label %invoke.cont2 137 138invoke.cont2: ; preds = %catch 139 call void @llvm.eh.endcatch() 140 br label %try.cont 141 142try.cont: ; preds = %invoke.cont2, %entry 143 ret void 144 145eh.resume: ; preds = %catch.dispatch 146 resume { i8*, i32 } %0 147} 148 149 150; Function Attrs: uwtable 151define void @test_begincatch_without_lpad() { 152; CHECK: llvm.eh.begincatch may be reachable without passing a landingpad 153; CHECK-NEXT: call void @llvm.eh.begincatch(i8* %exn, i8* null) 154entry: 155 %exn = alloca i8 156 call void @llvm.eh.begincatch(i8* %exn, i8* null) 157 call void @_Z10handle_intv() 158 br label %invoke.cont2 159 160invoke.cont2: ; preds = %catch 161 call void @llvm.eh.endcatch() 162 br label %try.cont 163 164try.cont: ; preds = %invoke.cont2, %entry 165 ret void 166} 167 168; Function Attrs: uwtable 169define void @test_branch_to_begincatch_with_no_lpad(i32 %fake.sel) { 170; CHECK: llvm.eh.begincatch may be reachable without passing a landingpad 171; CHECK-NEXT: call void @llvm.eh.begincatch(i8* %exn2, i8* null) 172entry: 173 %fake.exn = alloca i8 174 invoke void @_Z9may_throwv() 175 to label %catch unwind label %lpad 176 177lpad: ; preds = %entry 178 %0 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) 179 catch i8* bitcast (i8** @_ZTIi to i8*) 180 %exn = extractvalue { i8*, i32 } %0, 0 181 %sel = extractvalue { i8*, i32 } %0, 1 182 %1 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*)) 183 %matches = icmp eq i32 %sel, %1 184 br i1 %matches, label %catch, label %eh.resume 185 186 invoke void @_Z9may_throwv() 187 to label %try.cont unwind label %lpad 188 189catch: ; preds = %lpad, %entry 190 %exn2 = phi i8* [%exn, %lpad], [%fake.exn, %entry] 191 %sel2 = phi i32 [%sel, %lpad], [%fake.sel, %entry] 192 call void @llvm.eh.begincatch(i8* %exn2, i8* null) 193 call void @_Z10handle_intv() 194 %matches1 = icmp eq i32 %sel2, 0 195 br i1 %matches1, label %invoke.cont2, label %invoke.cont3 196 197invoke.cont2: ; preds = %catch 198 call void @llvm.eh.endcatch() 199 br label %try.cont 200 201invoke.cont3: ; preds = %catch 202 call void @llvm.eh.endcatch() 203 br label %eh.resume 204 205try.cont: ; preds = %invoke.cont2 206 ret void 207 208eh.resume: ; preds = %catch.dispatch 209 %lpad.val = insertvalue { i8*, i32 } undef, i32 0, 1 210 resume { i8*, i32 } %lpad.val 211} 212 213; Function Attrs: uwtable 214define void @test_branch_missing_endcatch() { 215; CHECK: Some paths from llvm.eh.begincatch may not reach llvm.eh.endcatch 216; CHECK-NEXT: call void @llvm.eh.begincatch(i8* %exn2, i8* null) 217entry: 218 invoke void @_Z9may_throwv() 219 to label %invoke.cont unwind label %lpad 220 221invoke.cont: 222 invoke void @_Z9may_throwv() 223 to label %invoke.cont unwind label %lpad1 224 225lpad: ; preds = %entry 226 %0 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) 227 catch i8* bitcast (i8** @_ZTIi to i8*) 228 %exn = extractvalue { i8*, i32 } %0, 0 229 %sel = extractvalue { i8*, i32 } %0, 1 230 %1 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*)) 231 %matches = icmp eq i32 %sel, %1 232 br i1 %matches, label %catch, label %eh.resume 233 234 invoke void @_Z9may_throwv() 235 to label %try.cont unwind label %lpad 236 237lpad1: ; preds = %entry 238 %l1.0 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) 239 cleanup 240 catch i8* bitcast (i8** @_ZTIi to i8*) 241 %exn1 = extractvalue { i8*, i32 } %l1.0, 0 242 %sel1 = extractvalue { i8*, i32 } %l1.0, 1 243 %l1.1 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*)) 244 %matchesl1 = icmp eq i32 %sel1, %l1.1 245 br i1 %matchesl1, label %catch, label %eh.resume 246 247catch: ; preds = %lpad, %lpad1 248 %exn2 = phi i8* [%exn, %lpad], [%exn1, %lpad1] 249 %sel2 = phi i32 [%sel, %lpad], [%sel1, %lpad1] 250 call void @llvm.eh.begincatch(i8* %exn2, i8* null) 251 call void @_Z10handle_intv() 252 %matches1 = icmp eq i32 %sel2, 0 253 br i1 %matches1, label %invoke.cont2, label %invoke.cont3 254 255invoke.cont2: ; preds = %catch 256 call void @llvm.eh.endcatch() 257 br label %try.cont 258 259invoke.cont3: ; preds = %catch 260 br label %eh.resume 261 262try.cont: ; preds = %invoke.cont2, %entry 263 ret void 264 265eh.resume: ; preds = %catch.dispatch 266 %lpad.val = insertvalue { i8*, i32 } undef, i32 0, 1 267 resume { i8*, i32 } %lpad.val 268} 269 270declare void @_Z9may_throwv() 271 272declare i32 @__CxxFrameHandler3(...) 273 274; Function Attrs: nounwind readnone 275declare i32 @llvm.eh.typeid.for(i8*) 276 277declare void @_Z10handle_intv() 278 279