Index: llvm/tools/clang/lib/CodeGen/CGVTables.cpp =================================================================== --- llvm/tools/clang/lib/CodeGen/CGVTables.cpp +++ llvm/tools/clang/lib/CodeGen/CGVTables.cpp @@ -715,9 +715,17 @@ const FunctionDecl *def = nullptr; if (keyFunction->hasBody(def)) keyFunction = cast(def); - switch (keyFunction->getTemplateSpecializationKind()) { case TSK_Undeclared: + // if we are generating profile instrumentation ensure + // vtables are always issued locally as the constructors + // and destructors are always issued. + if (CodeGenOpts.hasProfileClangInstr() || + CodeGenOpts.hasProfileIRInstr()) + return !Context.getLangOpts().AppleKext ? + llvm::GlobalVariable::LinkOnceODRLinkage : + llvm::Function::InternalLinkage; + LLVM_FALLTHROUGH; case TSK_ExplicitSpecialization: assert((def || CodeGenOpts.OptimizationLevel > 0) && "Shouldn't query vtable linkage without key function or " @@ -821,6 +829,12 @@ bool CodeGenVTables::isVTableExternal(const CXXRecordDecl *RD) { assert(RD->isDynamicClass() && "Non-dynamic classes have no VTable."); + // if we are generating profile instrumentation, issue the vtables locally as + // the constructors and destructors will always be issued. + if (CGM.getCodeGenOpts().hasProfileClangInstr() || + CGM.getCodeGenOpts().hasProfileIRInstr()) + return false; + // We always synthesize vtables if they are needed in the MS ABI. MSVC doesn't // emit them even if there is an explicit template instantiation. if (CGM.getTarget().getCXXABI().isMicrosoft()) Index: llvm/tools/clang/test/CodeGenCXX/vtable-coverage-gen.cpp =================================================================== --- /dev/null +++ llvm/tools/clang/test/CodeGenCXX/vtable-coverage-gen.cpp @@ -0,0 +1,51 @@ +// RUN: %clang_cc1 -O2 -fprofile-instrument=clang -fcoverage-mapping %s -emit-llvm -o %t +// RUN: FileCheck %s < %t +// CHECK: @_ZTV8Category = linkonce_odr unnamed_addr constant {{.*}}, comdat, + +class Category +{ + public: + Category() {} + virtual ~Category() {} + + static const Category *Get(int source); + + + protected: + const char *const ITEM_KEY_CONSOLE_ID = "consoleId"; + +}; + + + +class CategoryAboutMe : public Category +{ + public: + CategoryAboutMe() {} + virtual ~CategoryAboutMe() {} + + protected: +}; + + +//static +const Category * +Category::Get(int source) +{ + static CategoryAboutMe s_categoryAboutMe; + + switch (source) { + case 0: + return &s_categoryAboutMe; + default: + return __null; + } + return 0; +} + + +int main(int argc, char const *argv[]) +{ + /* code */ + return 0; +} \ No newline at end of file