From 94d384e4231e5e1e511873e421fdb63b175d64f0 Mon Sep 17 00:00:00 2001 From: Justin Bogner Date: Tue, 18 Nov 2014 00:34:46 +0000 Subject: [PATCH] InstrProf: Don't emit coverage for uninstantiated templates We include unused functions and methods in -fcoverage-mapping so that we can differentiate between uninstrumented and unused. This can cause problems for uninstantiated templates though, since they may involve an incomplete type that can't be mangled. This shows up in things like libc++'s and makes coverage unusable. Avoid the issue by skipping uninstantiated methods of a templated class. llvm-svn: 222204 --- clang/lib/CodeGen/ModuleBuilder.cpp | 8 +++++--- clang/test/CoverageMapping/classtemplate.cpp | 28 ++++++++++++++++++++++++---- 2 files changed, 29 insertions(+), 7 deletions(-) diff --git a/clang/lib/CodeGen/ModuleBuilder.cpp b/clang/lib/CodeGen/ModuleBuilder.cpp index 6c60b4e..ee6f6f9 100644 --- a/clang/lib/CodeGen/ModuleBuilder.cpp +++ b/clang/lib/CodeGen/ModuleBuilder.cpp @@ -145,9 +145,11 @@ namespace { // } A; DeferredInlineMethodDefinitions.push_back(D); - // Always provide some coverage mapping - // even for the methods that aren't emitted. - Builder->AddDeferredUnusedCoverageMapping(D); + // Provide some coverage mapping even for methods that aren't emitted. + // Don't do this for templated classes though, as they may not be + // instantiable. + if (!D->getParent()->getDescribedClassTemplate()) + Builder->AddDeferredUnusedCoverageMapping(D); } /// HandleTagDeclDefinition - This callback is invoked each time a TagDecl diff --git a/clang/test/CoverageMapping/classtemplate.cpp b/clang/test/CoverageMapping/classtemplate.cpp index e6938d6..6062266 100644 --- a/clang/test/CoverageMapping/classtemplate.cpp +++ b/clang/test/CoverageMapping/classtemplate.cpp @@ -12,18 +12,38 @@ public: const static int BaseCount = 4; double bases[BaseCount]; - // CHECK-CONSTRUCTOR: Test + // CHECK-CONSTRUCTOR: _ZN4TestIjEC Test() { } // CHECK-CONSTRUCTOR: File 0, [[@LINE]]:10 -> [[@LINE]]:13 = #0 (HasCodeBefore = 0) - // CHECK-GETTER: get - double get(TT position) const { // CHECK-GETTER: File 0, [[@LINE]]:33 -> [[@LINE+2]]:4 = 0 (HasCodeBefore = 0) + + // FIXME: It would be nice to emit no-coverage for get, but trying to do this + // runs afoul of cases like Test3::unmangleable below. + // FIXME-GETTER: _ZNK4TestIjE3get + double get(TT position) const { // FIXME-GETTER: File 0, [[@LINE]]:33 -> [[@LINE+2]]:4 = 0 (HasCodeBefore = 0) return bases[position]; } - // CHECK-SETTER: set + // CHECK-SETTER: _ZN4TestIjE3set void set(TT position, double value) { // CHECK-SETTER: File 0, [[@LINE]]:39 -> [[@LINE+2]]:4 = #0 (HasCodeBefore = 0) bases[position] = value; } }; +class Test2 { + // CHECK-CONSTRUCTOR: _ZN5Test2C + Test2() { } // CHECK-CONSTRUCTOR: File 0, [[@LINE]]:11 -> [[@LINE]]:14 = 0 (HasCodeBefore = 0) + // CHECK-GETTER: _ZNK5Test23get + double get(unsigned position) const { // CHECK-GETTER: File 0, [[@LINE]]:39 -> [[@LINE+2]]:4 = 0 (HasCodeBefore = 0) + return 0.0; + } +}; + +// Test3::unmangleable can't be mangled, since there isn't a complete type for +// the __is_final type trait expression. This would cause errors if we try to +// emit a no-coverage mapping for the method. +template class UninstantiatedClassWithTraits {}; +template class Test3 { + void unmangleable(UninstantiatedClassWithTraits x) {} +}; + int main() { Test t; t.set(Test::A, 5.5); -- 2.7.4