diff options
-rw-r--r-- | lib/CodeGen/CoverageMappingGen.cpp | 20 | ||||
-rw-r--r-- | test/CoverageMapping/default-method.cpp | 17 |
2 files changed, 33 insertions, 4 deletions
diff --git a/lib/CodeGen/CoverageMappingGen.cpp b/lib/CodeGen/CoverageMappingGen.cpp index 732ecd05ab..35962c73d9 100644 --- a/lib/CodeGen/CoverageMappingGen.cpp +++ b/lib/CodeGen/CoverageMappingGen.cpp @@ -656,12 +656,15 @@ struct CounterCoverageMappingBuilder return RegionStack.back(); } - /// Propagate counts through the children of \c S. - Counter propagateCounts(Counter TopCount, const Stmt *S) { + /// Propagate counts through the children of \p S if \p VisitChildren is true. + /// Otherwise, only emit a count for \p S itself. + Counter propagateCounts(Counter TopCount, const Stmt *S, + bool VisitChildren = true) { SourceLocation StartLoc = getStart(S); SourceLocation EndLoc = getEnd(S); size_t Index = pushRegion(TopCount, StartLoc, EndLoc); - Visit(S); + if (VisitChildren) + Visit(S); Counter ExitCount = getRegion().getCounter(); popRegions(Index); @@ -874,7 +877,16 @@ struct CounterCoverageMappingBuilder if (Body && SM.isInSystemHeader(SM.getSpellingLoc(getStart(Body)))) return; - propagateCounts(getRegionCounter(Body), Body); + // Do not visit the artificial children nodes of defaulted methods. The + // lexer may not be able to report back precise token end locations for + // these children nodes (llvm.org/PR39822), and moreover users will not be + // able to see coverage for them. + bool Defaulted = false; + if (auto *Method = dyn_cast<CXXMethodDecl>(D)) + Defaulted = Method->isDefaulted(); + + propagateCounts(getRegionCounter(Body), Body, + /*VisitChildren=*/!Defaulted); assert(RegionStack.empty() && "Regions entered but never exited"); // Discard the last uncompleted deferred region in a decl, if one exists. diff --git a/test/CoverageMapping/default-method.cpp b/test/CoverageMapping/default-method.cpp new file mode 100644 index 0000000000..e097a168bb --- /dev/null +++ b/test/CoverageMapping/default-method.cpp @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -std=c++17 -fprofile-instrument=clang -fcoverage-mapping -dump-coverage-mapping -emit-llvm-only -main-file-name default-method.cpp -w %s | FileCheck %s -implicit-check-not="->" + +namespace PR39822 { + struct unique_ptr { + unique_ptr &operator=(unique_ptr &); + }; + + class foo { + foo &operator=(foo &); + unique_ptr convertable_values_[2]; + }; + + // CHECK: _ZN7PR398223fooaSERS0_: + // CHECK-NEXT: File 0, [[@LINE+1]]:28 -> [[@LINE+1]]:29 = #0 + foo &foo::operator=(foo &) = default; +} // namespace PR39822 + |