Index: cfe/trunk/lib/CodeGen/CodeGenFunction.cpp =================================================================== --- cfe/trunk/lib/CodeGen/CodeGenFunction.cpp +++ cfe/trunk/lib/CodeGen/CodeGenFunction.cpp @@ -789,6 +789,15 @@ return true; } +/// Return the UBSan prologue signature for \p FD if one is available. +static llvm::Constant *getPrologueSignature(CodeGenModule &CGM, + const FunctionDecl *FD) { + if (const auto *MD = dyn_cast(FD)) + if (!MD->isStatic()) + return nullptr; + return CGM.getTargetCodeGenInfo().getUBSanFunctionSignature(CGM); +} + void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy, llvm::Function *Fn, @@ -908,8 +917,7 @@ // prologue data. if (getLangOpts().CPlusPlus && SanOpts.has(SanitizerKind::Function)) { if (const FunctionDecl *FD = dyn_cast_or_null(D)) { - if (llvm::Constant *PrologueSig = - CGM.getTargetCodeGenInfo().getUBSanFunctionSignature(CGM)) { + if (llvm::Constant *PrologueSig = getPrologueSignature(CGM, FD)) { llvm::Constant *FTRTTIConst = CGM.GetAddrOfRTTIDescriptor(FD->getType(), /*ForEH=*/true); llvm::Constant *FTRTTIConstEncoded = Index: cfe/trunk/test/CodeGenCXX/catch-undef-behavior.cpp =================================================================== --- cfe/trunk/test/CodeGenCXX/catch-undef-behavior.cpp +++ cfe/trunk/test/CodeGenCXX/catch-undef-behavior.cpp @@ -426,6 +426,66 @@ p(42); } +namespace FunctionSanitizerVirtualCalls { +struct A { + virtual void f() {} + virtual void g() {} + void h() {} +}; + +struct B : virtual A { + virtual void b() {} + virtual void f(); + void g() final {} + static void q() {} +}; + +void B::f() {} + +void force_irgen() { + A a; + a.g(); + a.h(); + + B b; + b.f(); + b.b(); + b.g(); + B::q(); +} + +// CHECK-LABEL: define void @_ZN29FunctionSanitizerVirtualCalls1B1fEv +// CHECK-NOT: prologue +// +// CHECK-LABEL: define void @_ZTv0_n24_N29FunctionSanitizerVirtualCalls1B1fEv +// CHECK-NOT: prologue +// +// CHECK-LABEL: define void @_ZN29FunctionSanitizerVirtualCalls11force_irgenEv() +// CHECK: prologue +// +// CHECK-LABEL: define linkonce_odr void @_ZN29FunctionSanitizerVirtualCalls1AC1Ev +// CHECK-NOT: prologue +// +// CHECK-LABEL: define linkonce_odr void @_ZN29FunctionSanitizerVirtualCalls1A1gEv +// CHECK-NOT: prologue +// +// CHECK-LABEL: define linkonce_odr void @_ZN29FunctionSanitizerVirtualCalls1A1hEv +// CHECK-NOT: prologue +// +// CHECK-LABEL: define linkonce_odr void @_ZN29FunctionSanitizerVirtualCalls1BC1Ev +// CHECK-NOT: prologue +// +// CHECK-LABEL: define linkonce_odr void @_ZN29FunctionSanitizerVirtualCalls1B1bEv +// CHECK-NOT: prologue +// +// CHECK-LABEL: define linkonce_odr void @_ZN29FunctionSanitizerVirtualCalls1B1gEv +// CHECK-NOT: prologue +// +// CHECK-LABEL: define linkonce_odr void @_ZN29FunctionSanitizerVirtualCalls1B1qEv +// CHECK: prologue + +} + namespace UpcastPointerTest { struct S {}; struct T : S { double d; };