> On Oct 13, 2017, at 4:08 PM, Peter Collingbourne <pe...@pcc.me.uk> wrote: > > On Fri, Oct 13, 2017 at 4:06 PM, Peter Collingbourne <pe...@pcc.me.uk > <mailto:pe...@pcc.me.uk>> wrote: > Here's a small reproducer. > > struct A { > virtual void f(...); > }; > > struct B : virtual A { > virtual void b(); > virtual void f(...); > }; > > void B::f(...) {} > > $ clang++ -fsanitize=function fsan.cpp -ffunction-sections -fdata-sections -c > -o /dev/null > fatal error: error in backend: Cannot represent a difference across sections > > Looking at the IR I see this function definition: > define void @_ZTv0_n24_N1B1fEz(%struct.B* %this, ...) unnamed_addr #0 align 2 > prologue <{ i32, i32 }> <{ i32 846595819, i32 trunc (i64 sub (i64 ptrtoint > (i8** @0 to i64), i64 ptrtoint (void (%struct.B*, ...)* @_ZN1B1fEz to i64)) > to i32) }> { > which appears to cause the error. > > I get basically the same IR if I use a Darwin target triple, so this isn't a > Linux-specific issue. (On Darwin we end up successfully creating an object > file, but the embedded offset in the text section will presumably be > incorrect.) > > Note that we're emitting prologue data on virtual functions, which is > unnecessary because -fsanitize=function only checks indirect calls via > function pointers. So I imagine that one way to solve the problem would be to > turn off prologue data emission on non-virtual functions. > > Sorry, I meant "limit prologue data emission to non-virtual functions".
That's independently a great idea :). I don't see a problem in the IR you've showed above, however. Why do you expect the embedded offset to be incorrect? This program links and runs fine on Darwin: --- struct A { virtual void f(...) {} }; struct B : virtual A { virtual void b() {} virtual void f(...); }; void B::f(...) {} int main() { A a; a.f(); B b; b.f(); b.b(); return 0; } --- The "Cannot represent difference..." error appears limited to ELF and Wasm, afaik. vedant > > Peter > > On Fri, Oct 13, 2017 at 3:06 PM, Vedant Kumar <v...@apple.com > <mailto:v...@apple.com>> wrote: > >> On Oct 13, 2017, at 2:52 PM, Eric Christopher <echri...@gmail.com >> <mailto:echri...@gmail.com>> wrote: >> >> >> >> On Fri, Oct 13, 2017 at 2:50 PM Vedant Kumar <v...@apple.com >> <mailto:v...@apple.com>> wrote: >>> On Oct 13, 2017, at 1:44 PM, Eric Christopher <echri...@gmail.com >>> <mailto:echri...@gmail.com>> wrote: >>> >>> >>> >>> On Fri, Oct 13, 2017 at 1:42 PM Vedant Kumar <v...@apple.com >>> <mailto:v...@apple.com>> wrote: >>>> On Oct 13, 2017, at 1:39 PM, Vedant Kumar <v...@apple.com >>>> <mailto:v...@apple.com>> wrote: >>>> >>>> Hey Eric, >>>> >>>> I'm sorry for the breakage. I made sure to check the run-time tests in >>>> compiler-rt but we could have missing coverage there. >>>> >>>> The original version of this patch restricted the prologue data changes to >>>> Darwin only. We can switch back to that easily, just let me know. >>> >>> Actually I'll go ahead and work a patch up. >>> >>> >>> Appreciated :) >>> >>> Basically we were getting an error of: >>> >>> error: Cannot represent a difference across sections >>> >>> trying to compile things with the current code. >> >> Oh I see.. well, we started using a difference between the address of a >> function and the address of a global, so the error makes sense. >> >> I'd be interested in any factors that could narrow the problem down (e.g >> using a specific linker, using -ffunction-sections, using data-sections, >> etc). Basically I'm not sure why this would work on some Linux setups but >> not others. >> >> >> Definitely using the latter two options and gold as a linker. I'll see what >> Han can come up with. > > Gotcha. Well, -ffunction-sections appears to be untested in > compiler-rt/test/ubsan, at least. > > There's a test somewhere in there called function.cpp -- it would be great if > we could cover the *-sections options there. I'm not sure whether that's what > caused the failure, but the extra coverage couldn't hurt :). I would do it > myself but I don't have a Linux machine to test on. > > vedant > >> >> While we figure that out here's a patch to limit the impact on non-Darwin >> platforms: >> https://reviews.llvm.org/D38903 <https://reviews.llvm.org/D38903> >> >> *goes a looking* >> >> Thanks! >> >> -eric >> >> vedant >> >>> >>> Thanks! >>> >>> -eric >>> >>> vedant >>> >>>> >>>> vedant >>>> >>>> >>>>> On Oct 13, 2017, at 1:33 PM, Eric Christopher <echri...@gmail.com >>>>> <mailto:echri...@gmail.com>> wrote: >>>>> >>>>> Hi Vedant, >>>>> >>>>> So this actually broke -fsanitize=function on linux. Han is working up a >>>>> testcase for it, but letting you know for now that we'll probably need >>>>> some change here. >>>>> >>>>> -eric >>>>> >>>>> On Tue, Sep 12, 2017 at 5:05 PM Vedant Kumar via cfe-commits >>>>> <cfe-commits@lists.llvm.org <mailto:cfe-commits@lists.llvm.org>> wrote: >>>>> Author: vedantk >>>>> Date: Tue Sep 12 17:04:35 2017 >>>>> New Revision: 313096 >>>>> >>>>> URL: http://llvm.org/viewvc/llvm-project?rev=313096&view=rev >>>>> <http://llvm.org/viewvc/llvm-project?rev=313096&view=rev> >>>>> Log: >>>>> [ubsan] Function Sanitizer: Don't require writable text segments >>>>> >>>>> This change will make it possible to use -fsanitize=function on Darwin and >>>>> possibly on other platforms. It fixes an issue with the way RTTI is >>>>> stored into >>>>> function prologue data. >>>>> >>>>> On Darwin, addresses stored in prologue data can't require run-time >>>>> fixups and >>>>> must be PC-relative. Run-time fixups are undesirable because they >>>>> necessitate >>>>> writable text segments, which can lead to security issues. And absolute >>>>> addresses are undesirable because they break PIE mode. >>>>> >>>>> The fix is to create a private global which points to the RTTI, and then >>>>> to >>>>> encode a PC-relative reference to the global into prologue data. >>>>> >>>>> Differential Revision: https://reviews.llvm.org/D37597 >>>>> <https://reviews.llvm.org/D37597> >>>>> >>>>> Modified: >>>>> cfe/trunk/lib/CodeGen/CGExpr.cpp >>>>> cfe/trunk/lib/CodeGen/CodeGenFunction.cpp >>>>> cfe/trunk/lib/CodeGen/CodeGenFunction.h >>>>> cfe/trunk/lib/CodeGen/TargetInfo.cpp >>>>> cfe/trunk/test/CodeGenCXX/catch-undef-behavior.cpp >>>>> >>>>> Modified: cfe/trunk/lib/CodeGen/CGExpr.cpp >>>>> URL: >>>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExpr.cpp?rev=313096&r1=313095&r2=313096&view=diff >>>>> >>>>> <http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExpr.cpp?rev=313096&r1=313095&r2=313096&view=diff> >>>>> ============================================================================== >>>>> --- cfe/trunk/lib/CodeGen/CGExpr.cpp (original) >>>>> +++ cfe/trunk/lib/CodeGen/CGExpr.cpp Tue Sep 12 17:04:35 2017 >>>>> @@ -4409,10 +4409,7 @@ RValue CodeGenFunction::EmitCall(QualTyp >>>>> SanitizerScope SanScope(this); >>>>> llvm::Constant *FTRTTIConst = >>>>> CGM.GetAddrOfRTTIDescriptor(QualType(FnType, 0), >>>>> /*ForEH=*/true); >>>>> - llvm::Type *PrefixStructTyElems[] = { >>>>> - PrefixSig->getType(), >>>>> - FTRTTIConst->getType() >>>>> - }; >>>>> + llvm::Type *PrefixStructTyElems[] = {PrefixSig->getType(), >>>>> Int32Ty}; >>>>> llvm::StructType *PrefixStructTy = llvm::StructType::get( >>>>> CGM.getLLVMContext(), PrefixStructTyElems, /*isPacked=*/true); >>>>> >>>>> @@ -4433,8 +4430,10 @@ RValue CodeGenFunction::EmitCall(QualTyp >>>>> EmitBlock(TypeCheck); >>>>> llvm::Value *CalleeRTTIPtr = >>>>> Builder.CreateConstGEP2_32(PrefixStructTy, CalleePrefixStruct, >>>>> 0, 1); >>>>> - llvm::Value *CalleeRTTI = >>>>> + llvm::Value *CalleeRTTIEncoded = >>>>> Builder.CreateAlignedLoad(CalleeRTTIPtr, getPointerAlign()); >>>>> + llvm::Value *CalleeRTTI = >>>>> + DecodeAddrUsedInPrologue(CalleePtr, CalleeRTTIEncoded); >>>>> llvm::Value *CalleeRTTIMatch = >>>>> Builder.CreateICmpEQ(CalleeRTTI, FTRTTIConst); >>>>> llvm::Constant *StaticData[] = { >>>>> >>>>> Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.cpp >>>>> URL: >>>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.cpp?rev=313096&r1=313095&r2=313096&view=diff >>>>> >>>>> <http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.cpp?rev=313096&r1=313095&r2=313096&view=diff> >>>>> ============================================================================== >>>>> --- cfe/trunk/lib/CodeGen/CodeGenFunction.cpp (original) >>>>> +++ cfe/trunk/lib/CodeGen/CodeGenFunction.cpp Tue Sep 12 17:04:35 2017 >>>>> @@ -429,6 +429,43 @@ bool CodeGenFunction::ShouldXRayInstrume >>>>> return CGM.getCodeGenOpts().XRayInstrumentFunctions; >>>>> } >>>>> >>>>> +llvm::Constant * >>>>> +CodeGenFunction::EncodeAddrForUseInPrologue(llvm::Function *F, >>>>> + llvm::Constant *Addr) { >>>>> + // Addresses stored in prologue data can't require run-time fixups and >>>>> must >>>>> + // be PC-relative. Run-time fixups are undesirable because they >>>>> necessitate >>>>> + // writable text segments, which are unsafe. And absolute addresses are >>>>> + // undesirable because they break PIE mode. >>>>> + >>>>> + // Add a layer of indirection through a private global. Taking its >>>>> address >>>>> + // won't result in a run-time fixup, even if Addr has linkonce_odr >>>>> linkage. >>>>> + auto *GV = new llvm::GlobalVariable(CGM.getModule(), Addr->getType(), >>>>> + /*isConstant=*/true, >>>>> + llvm::GlobalValue::PrivateLinkage, >>>>> Addr); >>>>> + >>>>> + // Create a PC-relative address. >>>>> + auto *GOTAsInt = llvm::ConstantExpr::getPtrToInt(GV, IntPtrTy); >>>>> + auto *FuncAsInt = llvm::ConstantExpr::getPtrToInt(F, IntPtrTy); >>>>> + auto *PCRelAsInt = llvm::ConstantExpr::getSub(GOTAsInt, FuncAsInt); >>>>> + return (IntPtrTy == Int32Ty) >>>>> + ? PCRelAsInt >>>>> + : llvm::ConstantExpr::getTrunc(PCRelAsInt, Int32Ty); >>>>> +} >>>>> + >>>>> +llvm::Value * >>>>> +CodeGenFunction::DecodeAddrUsedInPrologue(llvm::Value *F, >>>>> + llvm::Value *EncodedAddr) { >>>>> + // Reconstruct the address of the global. >>>>> + auto *PCRelAsInt = Builder.CreateSExt(EncodedAddr, IntPtrTy); >>>>> + auto *FuncAsInt = Builder.CreatePtrToInt(F, IntPtrTy, "func_addr.int >>>>> <http://func_addr.int/>"); >>>>> + auto *GOTAsInt = Builder.CreateAdd(PCRelAsInt, FuncAsInt, >>>>> "global_addr.int <http://global_addr.int/>"); >>>>> + auto *GOTAddr = Builder.CreateIntToPtr(GOTAsInt, Int8PtrPtrTy, >>>>> "global_addr"); >>>>> + >>>>> + // Load the original pointer through the global. >>>>> + return Builder.CreateLoad(Address(GOTAddr, getPointerAlign()), >>>>> + "decoded_addr"); >>>>> +} >>>>> + >>>>> /// EmitFunctionInstrumentation - Emit LLVM code to call the specified >>>>> /// instrumentation function with the current function and the call >>>>> site, if >>>>> /// function instrumentation is enabled. >>>>> @@ -856,7 +893,10 @@ void CodeGenFunction::StartFunction(Glob >>>>> CGM.getTargetCodeGenInfo().getUBSanFunctionSignature(CGM)) >>>>> { >>>>> llvm::Constant *FTRTTIConst = >>>>> CGM.GetAddrOfRTTIDescriptor(FD->getType(), /*ForEH=*/true); >>>>> - llvm::Constant *PrologueStructElems[] = { PrologueSig, >>>>> FTRTTIConst }; >>>>> + llvm::Constant *FTRTTIConstEncoded = >>>>> + EncodeAddrForUseInPrologue(Fn, FTRTTIConst); >>>>> + llvm::Constant *PrologueStructElems[] = {PrologueSig, >>>>> + FTRTTIConstEncoded}; >>>>> llvm::Constant *PrologueStructConst = >>>>> llvm::ConstantStruct::getAnon(PrologueStructElems, >>>>> /*Packed=*/true); >>>>> Fn->setPrologueData(PrologueStructConst); >>>>> >>>>> Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.h >>>>> URL: >>>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=313096&r1=313095&r2=313096&view=diff >>>>> >>>>> <http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=313096&r1=313095&r2=313096&view=diff> >>>>> ============================================================================== >>>>> --- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original) >>>>> +++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Tue Sep 12 17:04:35 2017 >>>>> @@ -1776,6 +1776,15 @@ public: >>>>> /// EmitMCountInstrumentation - Emit call to .mcount. >>>>> void EmitMCountInstrumentation(); >>>>> >>>>> + /// Encode an address into a form suitable for use in a function >>>>> prologue. >>>>> + llvm::Constant *EncodeAddrForUseInPrologue(llvm::Function *F, >>>>> + llvm::Constant *Addr); >>>>> + >>>>> + /// Decode an address used in a function prologue, encoded by \c >>>>> + /// EncodeAddrForUseInPrologue. >>>>> + llvm::Value *DecodeAddrUsedInPrologue(llvm::Value *F, >>>>> + llvm::Value *EncodedAddr); >>>>> + >>>>> /// EmitFunctionProlog - Emit the target specific LLVM code to load the >>>>> /// arguments for the given function. This is also responsible for >>>>> naming the >>>>> /// LLVM function arguments. >>>>> >>>>> Modified: cfe/trunk/lib/CodeGen/TargetInfo.cpp >>>>> URL: >>>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/TargetInfo.cpp?rev=313096&r1=313095&r2=313096&view=diff >>>>> >>>>> <http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/TargetInfo.cpp?rev=313096&r1=313095&r2=313096&view=diff> >>>>> ============================================================================== >>>>> --- cfe/trunk/lib/CodeGen/TargetInfo.cpp (original) >>>>> +++ cfe/trunk/lib/CodeGen/TargetInfo.cpp Tue Sep 12 17:04:35 2017 >>>>> @@ -1086,8 +1086,8 @@ public: >>>>> getUBSanFunctionSignature(CodeGen::CodeGenModule &CGM) const override { >>>>> unsigned Sig = (0xeb << 0) | // jmp rel8 >>>>> (0x06 << 8) | // .+0x08 >>>>> - ('F' << 16) | >>>>> - ('T' << 24); >>>>> + ('v' << 16) | >>>>> + ('2' << 24); >>>>> return llvm::ConstantInt::get(CGM.Int32Ty, Sig); >>>>> } >>>>> >>>>> @@ -2277,17 +2277,10 @@ public: >>>>> >>>>> llvm::Constant * >>>>> getUBSanFunctionSignature(CodeGen::CodeGenModule &CGM) const override { >>>>> - unsigned Sig; >>>>> - if (getABIInfo().has64BitPointers()) >>>>> - Sig = (0xeb << 0) | // jmp rel8 >>>>> - (0x0a << 8) | // .+0x0c >>>>> - ('F' << 16) | >>>>> - ('T' << 24); >>>>> - else >>>>> - Sig = (0xeb << 0) | // jmp rel8 >>>>> - (0x06 << 8) | // .+0x08 >>>>> - ('F' << 16) | >>>>> - ('T' << 24); >>>>> + unsigned Sig = (0xeb << 0) | // jmp rel8 >>>>> + (0x06 << 8) | // .+0x08 >>>>> + ('v' << 16) | >>>>> + ('2' << 24); >>>>> return llvm::ConstantInt::get(CGM.Int32Ty, Sig); >>>>> } >>>>> >>>>> >>>>> Modified: cfe/trunk/test/CodeGenCXX/catch-undef-behavior.cpp >>>>> URL: >>>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/catch-undef-behavior.cpp?rev=313096&r1=313095&r2=313096&view=diff >>>>> >>>>> <http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/catch-undef-behavior.cpp?rev=313096&r1=313095&r2=313096&view=diff> >>>>> ============================================================================== >>>>> --- cfe/trunk/test/CodeGenCXX/catch-undef-behavior.cpp (original) >>>>> +++ cfe/trunk/test/CodeGenCXX/catch-undef-behavior.cpp Tue Sep 12 >>>>> 17:04:35 2017 >>>>> @@ -16,6 +16,10 @@ struct S { >>>>> // Check that type mismatch handler is not modified by ASan. >>>>> // CHECK-ASAN: private unnamed_addr global { { [{{.*}} x i8]*, i32, i32 >>>>> }, { i16, i16, [4 x i8] }*, i8*, i8 } { {{.*}}, { i16, i16, [4 x i8] }* >>>>> [[TYPE_DESCR]], {{.*}} } >>>>> >>>>> +// CHECK: [[IndirectRTTI_ZTIFvPFviEE:@.+]] = private constant i8* >>>>> bitcast ({ i8*, i8* }* @_ZTIFvPFviEE to i8*) >>>>> +// CHECK-X86: [[IndirectRTTI_ZTIFvPFviEE:@.+]] = private constant i8* >>>>> bitcast ({ i8*, i8* }* @_ZTIFvPFviEE to i8*) >>>>> +// CHECK-X32: [[IndirectRTTI_ZTIFvPFviEE:@.+]] = private constant i8* >>>>> bitcast ({ i8*, i8* }* @_ZTIFvPFviEE to i8*) >>>>> + >>>>> struct T : S {}; >>>>> >>>>> // CHECK-LABEL: @_Z17reference_binding >>>>> @@ -395,23 +399,30 @@ void downcast_reference(B &b) { >>>>> // CHECK-NEXT: br i1 [[AND]] >>>>> } >>>>> >>>>> -// CHECK-LABEL: @_Z22indirect_function_callPFviE({{.*}} prologue <{ i32, >>>>> i8* }> <{ i32 1413876459, i8* bitcast ({ i8*, i8* }* @_ZTIFvPFviEE to >>>>> i8*) }> >>>>> -// CHECK-X32: @_Z22indirect_function_callPFviE({{.*}} prologue <{ i32, >>>>> i8* }> <{ i32 1413875435, i8* bitcast ({ i8*, i8* }* @_ZTIFvPFviEE to >>>>> i8*) }> >>>>> -// CHECK-X86: @_Z22indirect_function_callPFviE({{.*}} prologue <{ i32, >>>>> i8* }> <{ i32 1413875435, i8* bitcast ({ i8*, i8* }* @_ZTIFvPFviEE to >>>>> i8*) }> >>>>> +// >>>>> +// CHECK-LABEL: @_Z22indirect_function_callPFviE({{.*}} prologue <{ i32, >>>>> i32 }> <{ i32 846595819, i32 trunc (i64 sub (i64 ptrtoint (i8** {{.*}} to >>>>> i64), i64 ptrtoint (void (void (i32)*)* @_Z22indirect_function_callPFviE >>>>> to i64)) to i32) }> >>>>> +// CHECK-X32: @_Z22indirect_function_callPFviE({{.*}} prologue <{ i32, >>>>> i32 }> <{ i32 846595819, i32 sub (i32 ptrtoint (i8** >>>>> [[IndirectRTTI_ZTIFvPFviEE]] to i32), i32 ptrtoint (void (void (i32)*)* >>>>> @_Z22indirect_function_callPFviE to i32)) }> >>>>> +// CHECK-X86: @_Z22indirect_function_callPFviE({{.*}} prologue <{ i32, >>>>> i32 }> <{ i32 846595819, i32 sub (i32 ptrtoint (i8** >>>>> [[IndirectRTTI_ZTIFvPFviEE]] to i32), i32 ptrtoint (void (void (i32)*)* >>>>> @_Z22indirect_function_callPFviE to i32)) }> >>>>> void indirect_function_call(void (*p)(int)) { >>>>> - // CHECK: [[PTR:%.+]] = bitcast void (i32)* {{.*}} to <{ i32, i8* }>* >>>>> + // CHECK: [[PTR:%.+]] = bitcast void (i32)* {{.*}} to <{ i32, i32 }>* >>>>> >>>>> // Signature check >>>>> - // CHECK-NEXT: [[SIGPTR:%.+]] = getelementptr <{ i32, i8* }>, <{ i32, >>>>> i8* }>* [[PTR]], i32 0, i32 0 >>>>> + // CHECK-NEXT: [[SIGPTR:%.+]] = getelementptr <{ i32, i32 }>, <{ i32, >>>>> i32 }>* [[PTR]], i32 0, i32 0 >>>>> // CHECK-NEXT: [[SIG:%.+]] = load i32, i32* [[SIGPTR]] >>>>> - // CHECK-NEXT: [[SIGCMP:%.+]] = icmp eq i32 [[SIG]], 1413876459 >>>>> + // CHECK-NEXT: [[SIGCMP:%.+]] = icmp eq i32 [[SIG]], 846595819 >>>>> // CHECK-NEXT: br i1 [[SIGCMP]] >>>>> >>>>> // RTTI pointer check >>>>> - // CHECK: [[RTTIPTR:%.+]] = getelementptr <{ i32, i8* }>, <{ i32, i8* >>>>> }>* [[PTR]], i32 0, i32 1 >>>>> - // CHECK-NEXT: [[RTTI:%.+]] = load i8*, i8** [[RTTIPTR]] >>>>> + // CHECK: [[RTTIPTR:%.+]] = getelementptr <{ i32, i32 }>, <{ i32, i32 >>>>> }>* [[PTR]], i32 0, i32 1 >>>>> + // CHECK-NEXT: [[RTTIEncIntTrunc:%.+]] = load i32, i32* [[RTTIPTR]] >>>>> + // CHECK-NEXT: [[RTTIEncInt:%.+]] = sext i32 [[RTTIEncIntTrunc]] to i64 >>>>> + // CHECK-NEXT: [[FuncAddrInt:%.+]] = ptrtoint void (i32)* {{.*}} to i64 >>>>> + // CHECK-NEXT: [[IndirectGVInt:%.+]] = add i64 [[RTTIEncInt]], >>>>> [[FuncAddrInt]] >>>>> + // CHECK-NEXT: [[IndirectGV:%.+]] = inttoptr i64 [[IndirectGVInt]] to >>>>> i8** >>>>> + // CHECK-NEXT: [[RTTI:%.+]] = load i8*, i8** [[IndirectGV]], align 8 >>>>> // CHECK-NEXT: [[RTTICMP:%.+]] = icmp eq i8* [[RTTI]], bitcast ({ i8*, >>>>> i8* }* @_ZTIFviE to i8*) >>>>> // CHECK-NEXT: br i1 [[RTTICMP]] >>>>> + >>>>> p(42); >>>>> } >>>>> >>>>> >>>>> >>>>> _______________________________________________ >>>>> cfe-commits mailing list >>>>> cfe-commits@lists.llvm.org <mailto:cfe-commits@lists.llvm.org> >>>>> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits >>>>> <http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits> > > > > -- > -- > Peter > > > > -- > -- > Peter
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits