FlameTop created this revision. FlameTop added a reviewer: rsmith. FlameTop added a subscriber: cfe-commits.
The provided test shows a case where enabling coverage instrumentation causes a link error during building. Normally the all the base class items (vtable, ctors and dtors) would be removed in an optimized build. But when building with coverage instrumentation the ctors and dtors are always issued and access the vtable. However, the vtable remains with external linkage. As nobody ever instantiates the base class the vtable remains undefined and causes a link error. This patch changes the behavior when deciding the vtable linkage when generating coverage instrumentation. vtables are always generated as local linkonce objects. This is slightly wasteful of link time and target storage but the profile instrumentation is performed too early (as far as I can see) to not instrument ctors/dtors that will later be discarded. https://reviews.llvm.org/D27410 Files: llvm/tools/clang/lib/CodeGen/CGVTables.cpp llvm/tools/clang/test/CodeGenCXX/vtable-coverage-gen.cpp 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 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<CXXMethodDecl>(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 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<CXXMethodDecl>(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())
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits