forked from OSchip/llvm-project
[Coverage] Do not visit artificial stmts in defaulted methods (PR39822)
There is no reason to emit coverage mappings for artificial statements contained within defaulted methods, as these statements are not visible to users. Only emit a mapping for the body of the defaulted method (clang treats the text of the "default" keyword as the body when reporting locations). This allows users to see how often the default method is called, but trims down the coverage mapping by skipping visitation of the children of the method. The immediate motivation for this change is that the lexer's getPreciseTokenLocEnd API cannot return the correct location when given an artificial statement (with a somewhat made-up location) as an input. Test by Orivej Desh! Fixes llvm.org/PR39822. llvm-svn: 347803
This commit is contained in:
parent
1742eced55
commit
7225a26176
|
@ -656,12 +656,15 @@ struct CounterCoverageMappingBuilder
|
||||||
return RegionStack.back();
|
return RegionStack.back();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Propagate counts through the children of \c S.
|
/// Propagate counts through the children of \p S if \p VisitChildren is true.
|
||||||
Counter propagateCounts(Counter TopCount, const Stmt *S) {
|
/// Otherwise, only emit a count for \p S itself.
|
||||||
|
Counter propagateCounts(Counter TopCount, const Stmt *S,
|
||||||
|
bool VisitChildren = true) {
|
||||||
SourceLocation StartLoc = getStart(S);
|
SourceLocation StartLoc = getStart(S);
|
||||||
SourceLocation EndLoc = getEnd(S);
|
SourceLocation EndLoc = getEnd(S);
|
||||||
size_t Index = pushRegion(TopCount, StartLoc, EndLoc);
|
size_t Index = pushRegion(TopCount, StartLoc, EndLoc);
|
||||||
Visit(S);
|
if (VisitChildren)
|
||||||
|
Visit(S);
|
||||||
Counter ExitCount = getRegion().getCounter();
|
Counter ExitCount = getRegion().getCounter();
|
||||||
popRegions(Index);
|
popRegions(Index);
|
||||||
|
|
||||||
|
@ -874,7 +877,16 @@ struct CounterCoverageMappingBuilder
|
||||||
if (Body && SM.isInSystemHeader(SM.getSpellingLoc(getStart(Body))))
|
if (Body && SM.isInSystemHeader(SM.getSpellingLoc(getStart(Body))))
|
||||||
return;
|
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");
|
assert(RegionStack.empty() && "Regions entered but never exited");
|
||||||
|
|
||||||
// Discard the last uncompleted deferred region in a decl, if one exists.
|
// Discard the last uncompleted deferred region in a decl, if one exists.
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue