Index: include/llvm/IR/DebugInfoMetadata.h =================================================================== --- include/llvm/IR/DebugInfoMetadata.h +++ include/llvm/IR/DebugInfoMetadata.h @@ -1371,6 +1371,8 @@ friend class LLVMContextImpl; friend class MDNode; + bool Covered = true; + DILocation(LLVMContext &C, StorageType Storage, unsigned Line, unsigned Column, ArrayRef MDs); ~DILocation() { dropAllReferences(); } @@ -1440,6 +1442,12 @@ return cast_or_null(getRawInlinedAt()); } + /// Check if the line must be covered + bool isCovered() const { return Covered; } + + /// Set if the line must be covered + void setCovered(bool Covered) { this->Covered = Covered; } + DIFile *getFile() const { return getScope()->getFile(); } StringRef getFilename() const { return getScope()->getFilename(); } StringRef getDirectory() const { return getScope()->getDirectory(); } Index: include/llvm/IR/DebugLoc.h =================================================================== --- include/llvm/IR/DebugLoc.h +++ include/llvm/IR/DebugLoc.h @@ -78,7 +78,7 @@ /// /// FIXME: Remove this. Users should use DILocation::get(). static DebugLoc get(unsigned Line, unsigned Col, const MDNode *Scope, - const MDNode *InlinedAt = nullptr); + const MDNode *InlinedAt = nullptr, bool Covered = true); enum { ReplaceLastInlinedAt = true }; /// Rebuild the entire inlined-at chain for this instruction so that the top of @@ -112,6 +112,10 @@ /// Return \c this as a bar \a MDNode. MDNode *getAsMDNode() const { return Loc; } + /// Check if the DebugLoc must have coverage information + bool isCovered() const; + void setCovered(bool Covered); + bool operator==(const DebugLoc &DL) const { return Loc == DL.Loc; } bool operator!=(const DebugLoc &DL) const { return Loc != DL.Loc; } Index: lib/IR/DebugLoc.cpp =================================================================== --- lib/IR/DebugLoc.cpp +++ lib/IR/DebugLoc.cpp @@ -56,15 +56,31 @@ return DebugLoc(); } +bool DebugLoc::isCovered() const { + if (DILocation * Loc = get()) { + return Loc->isCovered(); + } + return true; +} + +void DebugLoc::setCovered(bool Covered) { + if (DILocation * Loc = get()) { + Loc->setCovered(Covered); + } +} + DebugLoc DebugLoc::get(unsigned Line, unsigned Col, const MDNode *Scope, - const MDNode *InlinedAt) { + const MDNode *InlinedAt, bool Covered) { // If no scope is available, this is an unknown location. if (!Scope) return DebugLoc(); - return DILocation::get(Scope->getContext(), Line, Col, + DILocation *Loc = DILocation::get(Scope->getContext(), Line, Col, const_cast(Scope), const_cast(InlinedAt)); + Loc->setCovered(Covered); + + return Loc; } DebugLoc DebugLoc::appendInlinedAt(DebugLoc DL, DILocation *InlinedAt, Index: lib/Transforms/Instrumentation/GCOVProfiling.cpp =================================================================== --- lib/Transforms/Instrumentation/GCOVProfiling.cpp +++ lib/Transforms/Instrumentation/GCOVProfiling.cpp @@ -605,13 +605,12 @@ continue; // Artificial lines such as calls to the global constructors. - if (Loc.getLine() == 0) continue; + if (Loc.getLine() == 0 || !Loc.isCovered()) continue; if (Line == Loc.getLine()) continue; Line = Loc.getLine(); if (SP != getDISubprogram(Loc.getScope())) continue; - GCOVLines &Lines = Block.getFile(SP->getFilename()); Lines.addLine(Loc.getLine()); }