[llvm] 2c155d3 - [llvm-debuginfo-analyzer] (06/09) - Warning and internal options

Carlos Alberto Enciso via llvm-commits llvm-commits at lists.llvm.org
Sun Oct 23 21:13:54 PDT 2022


Author: Carlos Alberto Enciso
Date: 2022-10-24T05:12:57+01:00
New Revision: 2c155d37996066af4b392aab435884ee919ade8d

URL: https://github.com/llvm/llvm-project/commit/2c155d37996066af4b392aab435884ee919ade8d
DIFF: https://github.com/llvm/llvm-project/commit/2c155d37996066af4b392aab435884ee919ade8d.diff

LOG: [llvm-debuginfo-analyzer] (06/09) - Warning and internal options

llvm-debuginfo-analyzer is a command line tool that processes debug
info contained in a binary file and produces a debug information
format agnostic “Logical View”, which is a high-level semantic
representation of the debug info, independent of the low-level
format.

The code has been divided into the following patches:

1) Interval tree
2) Driver and documentation
3) Logical elements
4) Locations and ranges
5) Select elements
6) Warning and internal options
7) Compare elements
8) ELF Reader
9) CodeView Reader

Full details:
https://discourse.llvm.org/t/llvm-dev-rfc-llvm-dva-debug-information-visual-analyzer/62570

This patch:

Warning and internal options
- Support for '--warning' options.
- Support for '--internal' options.

Reviewed By: psamolysov, probinson

Differential Revision: https://reviews.llvm.org/D125781

Added: 
    llvm/unittests/DebugInfo/LogicalView/WarningInternalTest.cpp

Modified: 
    llvm/include/llvm/DebugInfo/LogicalView/Core/LVElement.h
    llvm/include/llvm/DebugInfo/LogicalView/Core/LVObject.h
    llvm/include/llvm/DebugInfo/LogicalView/Core/LVReader.h
    llvm/include/llvm/DebugInfo/LogicalView/Core/LVScope.h
    llvm/include/llvm/DebugInfo/LogicalView/Core/LVSupport.h
    llvm/lib/DebugInfo/LogicalView/Core/LVLine.cpp
    llvm/lib/DebugInfo/LogicalView/Core/LVObject.cpp
    llvm/lib/DebugInfo/LogicalView/Core/LVReader.cpp
    llvm/lib/DebugInfo/LogicalView/Core/LVScope.cpp
    llvm/lib/DebugInfo/LogicalView/Core/LVSymbol.cpp
    llvm/unittests/DebugInfo/LogicalView/CMakeLists.txt

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVElement.h b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVElement.h
index 7bac7a31f5a41..bde8f670ac7c0 100644
--- a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVElement.h
+++ b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVElement.h
@@ -336,7 +336,6 @@ class LVElement : public LVObject {
   virtual void resolveReferences() {}
   void resolveParents();
 
-public:
   static LVElementDispatch &getDispatch() { return Dispatch; }
 };
 

diff  --git a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVObject.h b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVObject.h
index b44b706d6128b..e08111828a5c5 100644
--- a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVObject.h
+++ b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVObject.h
@@ -168,6 +168,9 @@ class LVObject {
   // copy constructor to create that object; it is used to print a reference
   // to another object and in the case of templates, to print its encoded args.
   LVObject(const LVObject &Object) {
+#ifndef NDEBUG
+    incID();
+#endif
     Properties = Object.Properties;
     Offset = Object.Offset;
     LineNumber = Object.LineNumber;
@@ -176,6 +179,19 @@ class LVObject {
     Parent = Object.Parent;
   }
 
+#ifndef NDEBUG
+  // This is an internal ID used for debugging logical elements. It is used
+  // for cases where an unique offset within the binary input file is not
+  // available.
+  static uint64_t GID;
+  uint64_t ID = 0;
+
+  void incID() {
+    ++GID;
+    ID = GID;
+  }
+#endif
+
 protected:
   // Get a string representation for the given number and discriminator.
   std::string lineAsString(uint32_t LineNumber, LVHalf Discriminator,
@@ -190,7 +206,11 @@ class LVObject {
   virtual void printFileIndex(raw_ostream &OS, bool Full = true) const {}
 
 public:
-  LVObject() = default;
+  LVObject() {
+#ifndef NDEBUG
+    incID();
+#endif
+  };
   LVObject &operator=(const LVObject &) = delete;
   virtual ~LVObject() = default;
 
@@ -308,6 +328,15 @@ class LVObject {
 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
   virtual void dump() const { print(dbgs()); }
 #endif
+
+  uint64_t getID() const {
+    return
+#ifndef NDEBUG
+        ID;
+#else
+        0;
+#endif
+  }
 };
 
 } // end namespace logicalview

diff  --git a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVReader.h b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVReader.h
index 1a1ee19f31900..c5d71867282dc 100644
--- a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVReader.h
+++ b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVReader.h
@@ -161,6 +161,7 @@ class LVReader {
   static void setInstance(LVReader *Reader);
 
   void print(raw_ostream &OS) const;
+  virtual void printRecords(raw_ostream &OS) const {}
 
 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
   void dump() const { print(dbgs()); }

diff  --git a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVScope.h b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVScope.h
index 860ed3c2e5012..a3268d260cf7f 100644
--- a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVScope.h
+++ b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVScope.h
@@ -17,6 +17,7 @@
 #include "llvm/DebugInfo/LogicalView/Core/LVElement.h"
 #include "llvm/DebugInfo/LogicalView/Core/LVLocation.h"
 #include "llvm/DebugInfo/LogicalView/Core/LVSort.h"
+#include <list>
 #include <map>
 #include <set>
 
@@ -56,7 +57,12 @@ using LVScopeKindSet = std::set<LVScopeKind>;
 using LVScopeDispatch = std::map<LVScopeKind, LVScopeGetFunction>;
 using LVScopeRequest = std::vector<LVScopeGetFunction>;
 
+using LVOffsetList = std::list<LVOffset>;
 using LVOffsetElementMap = std::map<LVOffset, LVElement *>;
+using LVOffsetLinesMap = std::map<LVOffset, LVLines *>;
+using LVOffsetLocationsMap = std::map<LVOffset, LVLocations *>;
+using LVOffsetSymbolMap = std::map<LVOffset, LVSymbol *>;
+using LVTagOffsetsMap = std::map<dwarf::Tag, LVOffsetList *>;
 
 // Class to represent a DWARF Scope.
 class LVScope : public LVElement {
@@ -266,6 +272,7 @@ class LVScope : public LVElement {
 
   void print(raw_ostream &OS, bool Full = true) const override;
   void printExtra(raw_ostream &OS, bool Full = true) const override;
+  virtual void printWarnings(raw_ostream &OS, bool Full = true) const {}
   virtual void printMatchedElements(raw_ostream &OS, bool UseMatchedElements) {}
 
 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
@@ -358,11 +365,39 @@ class LVScopeCompileUnit final : public LVScope {
   using LVAddressToLine = std::map<LVAddress, LVLine *>;
   LVAddressToLine AddressToLine;
 
+  // DWARF Tags (Tag, Element list).
+  LVTagOffsetsMap DebugTags;
+
+  // Offsets associated with objects being flagged as having invalid data
+  // (ranges, locations, lines zero or coverages).
+  LVOffsetElementMap WarningOffsets;
+
+  // Symbols with invalid locations. (Symbol, Location List).
+  LVOffsetLocationsMap InvalidLocations;
+
+  // Symbols with invalid coverage values.
+  LVOffsetSymbolMap InvalidCoverages;
+
+  // Scopes with invalid ranges (Scope, Range list).
+  LVOffsetLocationsMap InvalidRanges;
+
+  // Scopes with lines zero (Scope, Line list).
+  LVOffsetLinesMap LinesZero;
+
   // Record scopes contribution in bytes to the debug information.
   using LVSizesMap = std::map<const LVScope *, LVOffset>;
   LVSizesMap Sizes;
   LVOffset CUContributionSize = 0;
 
+  // Helper function to add an invalid location/range.
+  void addInvalidLocationOrRange(LVLocation *Location, LVElement *Element,
+                                 LVOffsetLocationsMap *Map) {
+    LVOffset Offset = Element->getOffset();
+    addInvalidOffset(Offset, Element);
+    addItem<LVOffsetLocationsMap, LVLocations, LVOffset, LVLocation *>(
+        Map, Offset, Location);
+  }
+
   // Record scope sizes indexed by lexical level.
   // Setting an initial size that will cover a very deep nested scopes.
   const size_t TotalInitialSize = 8;
@@ -388,7 +423,12 @@ class LVScopeCompileUnit final : public LVScope {
   }
   LVScopeCompileUnit(const LVScopeCompileUnit &) = delete;
   LVScopeCompileUnit &operator=(const LVScopeCompileUnit &) = delete;
-  ~LVScopeCompileUnit() = default;
+  ~LVScopeCompileUnit() {
+    deleteList<LVTagOffsetsMap>(DebugTags);
+    deleteList<LVOffsetLocationsMap>(InvalidLocations);
+    deleteList<LVOffsetLocationsMap>(InvalidRanges);
+    deleteList<LVOffsetLinesMap>(LinesZero);
+  }
 
   LVScope *getCompileUnitParent() const override {
     return static_cast<LVScope *>(const_cast<LVScopeCompileUnit *>(this));
@@ -417,6 +457,30 @@ class LVScopeCompileUnit final : public LVScope {
     ProducerIndex = getStringPool().getIndex(ProducerName);
   }
 
+  // Record DWARF tags.
+  void addDebugTag(dwarf::Tag Target, LVOffset Offset);
+  // Record elements with invalid offsets.
+  void addInvalidOffset(LVOffset Offset, LVElement *Element);
+  // Record symbols with invalid coverage values.
+  void addInvalidCoverage(LVSymbol *Symbol);
+  // Record symbols with invalid locations.
+  void addInvalidLocation(LVLocation *Location);
+  // Record scopes with invalid ranges.
+  void addInvalidRange(LVLocation *Location);
+  // Record line zero.
+  void addLineZero(LVLine *Line);
+
+  const LVTagOffsetsMap getDebugTags() const { return DebugTags; }
+  const LVOffsetElementMap getWarningOffsets() const { return WarningOffsets; }
+  const LVOffsetLocationsMap getInvalidLocations() const {
+    return InvalidLocations;
+  }
+  const LVOffsetSymbolMap getInvalidCoverages() const {
+    return InvalidCoverages;
+  }
+  const LVOffsetLocationsMap getInvalidRanges() const { return InvalidRanges; }
+  const LVOffsetLinesMap getLinesZero() const { return LinesZero; }
+
   // Process ranges, locations and calculate coverage.
   void processRangeLocationCoverage(
       LVValidLocation ValidLocation = &LVLocation::validateRanges);
@@ -456,6 +520,7 @@ class LVScopeCompileUnit final : public LVScope {
 
   void print(raw_ostream &OS, bool Full = true) const override;
   void printExtra(raw_ostream &OS, bool Full = true) const override;
+  void printWarnings(raw_ostream &OS, bool Full = true) const override;
   void printMatchedElements(raw_ostream &OS, bool UseMatchedElements) override;
 };
 

diff  --git a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVSupport.h b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVSupport.h
index cfa0c7ca2209d..15caa8f6e44ed 100644
--- a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVSupport.h
+++ b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVSupport.h
@@ -142,6 +142,27 @@ std::string formatAttributes(const StringRef First, Args... Others) {
   return Stream.str();
 }
 
+// Add an item to a map with second being a list.
+template <typename MapType, typename ListType, typename KeyType,
+          typename ValueType>
+void addItem(MapType *Map, KeyType Key, ValueType Value) {
+  ListType *List = nullptr;
+  typename MapType::const_iterator Iter = Map->find(Key);
+  if (Iter != Map->end())
+    List = Iter->second;
+  else {
+    List = new ListType();
+    Map->emplace(Key, List);
+  }
+  List->push_back(Value);
+}
+
+// Delete the map contained list.
+template <typename MapType> void deleteList(MapType &Map) {
+  for (typename MapType::const_reference Entry : Map)
+    delete Entry.second;
+}
+
 // Unified and flattened pathnames.
 std::string transformPath(StringRef Path);
 std::string flattenedFilePath(StringRef Path);

diff  --git a/llvm/lib/DebugInfo/LogicalView/Core/LVLine.cpp b/llvm/lib/DebugInfo/LogicalView/Core/LVLine.cpp
index cc36e6d28c0ba..ace1cefcbbc3d 100644
--- a/llvm/lib/DebugInfo/LogicalView/Core/LVLine.cpp
+++ b/llvm/lib/DebugInfo/LogicalView/Core/LVLine.cpp
@@ -59,6 +59,8 @@ LVLineDispatch LVLine::Dispatch = {
 
 // String used as padding for printing elements with no line number.
 std::string LVLine::noLineAsString(bool ShowZero) const {
+  if (options().getInternalNone())
+    return LVObject::noLineAsString(ShowZero);
   return (ShowZero || options().getAttributeZero()) ? ("    0   ")
                                                     : ("    -   ");
 }

diff  --git a/llvm/lib/DebugInfo/LogicalView/Core/LVObject.cpp b/llvm/lib/DebugInfo/LogicalView/Core/LVObject.cpp
index 79eea66c94d05..e312ad46ba480 100644
--- a/llvm/lib/DebugInfo/LogicalView/Core/LVObject.cpp
+++ b/llvm/lib/DebugInfo/LogicalView/Core/LVObject.cpp
@@ -21,6 +21,10 @@ using namespace llvm::logicalview;
 
 #define DEBUG_TYPE "Object"
 
+#ifndef NDEBUG
+uint64_t LVObject::GID = 0;
+#endif
+
 StringRef llvm::logicalview::typeNone() { return StringRef(); }
 StringRef llvm::logicalview::typeVoid() { return "void"; }
 StringRef llvm::logicalview::typeInt() { return "int"; }
@@ -61,6 +65,9 @@ std::string LVObject::lineAsString(uint32_t LineNumber, LVHalf Discriminator,
   } else
     Stream << noLineAsString(ShowZero);
 
+  if (options().getInternalNone())
+    Stream.str(noLineAsString(ShowZero));
+
   return Stream.str();
 }
 
@@ -118,6 +125,10 @@ void LVObject::printAttributes(raw_ostream &OS, bool Full, StringRef Name,
 }
 
 void LVObject::printAttributes(raw_ostream &OS, bool Full) const {
+#ifndef NDEBUG
+  if (options().getInternalID())
+    OS << hexSquareString(getID());
+#endif
   if (options().getAttributeOffset())
     OS << hexSquareString(getOffset());
   if (options().getAttributeLevel()) {

diff  --git a/llvm/lib/DebugInfo/LogicalView/Core/LVReader.cpp b/llvm/lib/DebugInfo/LogicalView/Core/LVReader.cpp
index 52098239598cd..5d7401393a8fc 100644
--- a/llvm/lib/DebugInfo/LogicalView/Core/LVReader.cpp
+++ b/llvm/lib/DebugInfo/LogicalView/Core/LVReader.cpp
@@ -23,6 +23,90 @@ using namespace llvm::logicalview;
 
 #define DEBUG_TYPE "Reader"
 
+// Detect elements that are inserted more than once at 
diff erent scopes,
+// causing a crash on the reader destruction, as the element is already
+// deleted from other scope. Helper for CodeView reader.
+bool checkIntegrityScopesTree(LVScope *Root) {
+  using LVDuplicateEntry = std::tuple<LVElement *, LVScope *, LVScope *>;
+  using LVDuplicate = std::vector<LVDuplicateEntry>;
+  LVDuplicate Duplicate;
+
+  using LVIntegrity = std::map<LVElement *, LVScope *>;
+  LVIntegrity Integrity;
+
+  // Add the given element to the integrity map.
+  auto AddElement = [&](LVElement *Element, LVScope *Scope) {
+    LVIntegrity::iterator Iter = Integrity.find(Element);
+    if (Iter == Integrity.end())
+      Integrity.emplace(Element, Scope);
+    else
+      // We found a duplicate.
+      Duplicate.emplace_back(Element, Scope, Iter->second);
+  };
+
+  // Recursively add all the elements in the scope.
+  std::function<void(LVScope * Parent)> TraverseScope = [&](LVScope *Parent) {
+    auto Traverse = [&](const auto *Set) {
+      if (Set)
+        for (const auto &Entry : *Set)
+          AddElement(Entry, Parent);
+    };
+    if (const LVScopes *Scopes = Parent->getScopes()) {
+      for (LVScope *Scope : *Scopes) {
+        AddElement(Scope, Parent);
+        TraverseScope(Scope);
+      }
+    }
+    Traverse(Parent->getSymbols());
+    Traverse(Parent->getTypes());
+    Traverse(Parent->getLines());
+  };
+
+  // Start traversing the scopes root and print any duplicates.
+  TraverseScope(Root);
+  bool PassIntegrity = true;
+  if (Duplicate.size()) {
+    std::stable_sort(begin(Duplicate), end(Duplicate),
+                     [](const auto &l, const auto &r) {
+                       return std::get<0>(l)->getID() < std::get<0>(r)->getID();
+                     });
+
+    auto PrintIndex = [](unsigned Index) {
+      if (Index)
+        dbgs() << format("%8d: ", Index);
+      else
+        dbgs() << format("%8c: ", ' ');
+    };
+    auto PrintElement = [&](LVElement *Element, unsigned Index = 0) {
+      PrintIndex(Index);
+      std::string ElementName(Element->getName());
+      dbgs() << format("%15s ID=0x%08x '%s'\n", Element->kind(),
+                       Element->getID(), ElementName.c_str());
+    };
+
+    std::string RootName(Root->getName());
+    dbgs() << formatv("{0}\n", fmt_repeat('=', 72));
+    dbgs() << format("Root: '%s'\nDuplicated elements: %d\n", RootName.c_str(),
+                     Duplicate.size());
+    dbgs() << formatv("{0}\n", fmt_repeat('=', 72));
+
+    unsigned Index = 0;
+    for (const LVDuplicateEntry &Entry : Duplicate) {
+      LVElement *Element;
+      LVScope *First;
+      LVScope *Second;
+      std::tie(Element, First, Second) = Entry;
+      dbgs() << formatv("\n{0}\n", fmt_repeat('-', 72));
+      PrintElement(Element, ++Index);
+      PrintElement(First);
+      PrintElement(Second);
+      dbgs() << formatv("{0}\n", fmt_repeat('-', 72));
+    }
+    PassIntegrity = false;
+  }
+  return PassIntegrity;
+}
+
 //===----------------------------------------------------------------------===//
 // Class to represent a split context.
 //===----------------------------------------------------------------------===//
@@ -149,6 +233,10 @@ Error LVReader::doLoad() {
   if (Error Err = createScopes())
     return Err;
 
+  if (options().getInternalIntegrity() && !checkIntegrityScopesTree(Root))
+    return llvm::make_error<StringError>("Duplicated elements in Scopes Tree",
+                                         inconvertibleErrorCode());
+
   // Calculate symbol coverage and detect invalid debug locations and ranges.
   Root->processRangeInformation();
 

diff  --git a/llvm/lib/DebugInfo/LogicalView/Core/LVScope.cpp b/llvm/lib/DebugInfo/LogicalView/Core/LVScope.cpp
index 0228be7664111..56d5740afbd43 100644
--- a/llvm/lib/DebugInfo/LogicalView/Core/LVScope.cpp
+++ b/llvm/lib/DebugInfo/LogicalView/Core/LVScope.cpp
@@ -559,6 +559,12 @@ void LVScope::encodeTemplateArguments(std::string &Name,
 }
 
 bool LVScope::resolvePrinting() const {
+  // The warnings collected during the scope creation as per compile unit.
+  // If there is a request for printing warnings, always print its associate
+  // Compile Unit.
+  if (options().getPrintWarnings() && (getIsRoot() || getIsCompileUnit()))
+    return true;
+
   // In selection mode, always print the root scope regardless of the
   // number of matched elements. If no matches, the root by itself will
   // indicate no matches.
@@ -650,6 +656,10 @@ Error LVScope::doPrint(bool Split, bool Match, bool Print, raw_ostream &OS,
                   Line->doPrint(Split, Match, Print, *StreamSplit, Full))
             return Err;
         }
+
+      // Print the warnings.
+      if (options().getPrintWarnings())
+        printWarnings(*StreamSplit, Full);
     }
   }
 
@@ -666,6 +676,10 @@ Error LVScope::doPrint(bool Split, bool Match, bool Print, raw_ostream &OS,
     }
   }
 
+  if (getIsRoot() && options().getPrintWarnings()) {
+    getReader().printRecords(*StreamSplit);
+  }
+
   return Error::success();
 }
 
@@ -1001,15 +1015,25 @@ void LVScopeCompileUnit::processRangeLocationCoverage(
   if (options().getAttributeRange()) {
     // Traverse the scopes to get scopes that have invalid ranges.
     LVLocations Locations;
-    bool RecordInvalid = false;
+    bool RecordInvalid = options().getWarningRanges();
     getRanges(Locations, ValidLocation, RecordInvalid);
+
+    // Validate ranges associated with scopes.
+    if (RecordInvalid)
+      for (LVLocation *Location : Locations)
+        addInvalidRange(Location);
   }
 
   if (options().getAttributeLocation()) {
     // Traverse the scopes to get locations that have invalid ranges.
     LVLocations Locations;
-    bool RecordInvalid = false;
+    bool RecordInvalid = options().getWarningLocations();
     getLocations(Locations, ValidLocation, RecordInvalid);
+
+    // Validate ranges associated with locations.
+    if (RecordInvalid)
+      for (LVLocation *Location : Locations)
+        addInvalidLocation(Location);
   }
 }
 
@@ -1019,10 +1043,12 @@ LVLine *LVScopeCompileUnit::lineLowerBound(LVAddress Address) const {
 }
 
 LVLine *LVScopeCompileUnit::lineUpperBound(LVAddress Address) const {
+  if (AddressToLine.empty())
+    return nullptr;
   LVAddressToLine::const_iterator Iter = AddressToLine.upper_bound(Address);
   if (Iter != AddressToLine.begin())
     Iter = std::prev(Iter);
-  return (Iter != AddressToLine.end()) ? Iter->second : nullptr;
+  return Iter->second;
 }
 
 StringRef LVScopeCompileUnit::getFilename(size_t Index) const {
@@ -1069,6 +1095,46 @@ void LVScopeCompileUnit::addedElement(LVScope *Scope) { increment(Scope); }
 void LVScopeCompileUnit::addedElement(LVSymbol *Symbol) { increment(Symbol); }
 void LVScopeCompileUnit::addedElement(LVType *Type) { increment(Type); }
 
+// Record unsuported DWARF tags.
+void LVScopeCompileUnit::addDebugTag(dwarf::Tag Target, LVOffset Offset) {
+  addItem<LVTagOffsetsMap, LVOffsetList, dwarf::Tag, LVOffset>(&DebugTags,
+                                                               Target, Offset);
+}
+
+// Record elements with invalid offsets.
+void LVScopeCompileUnit::addInvalidOffset(LVOffset Offset, LVElement *Element) {
+  if (WarningOffsets.find(Offset) == WarningOffsets.end())
+    WarningOffsets.emplace(Offset, Element);
+}
+
+// Record symbols with invalid coverage values.
+void LVScopeCompileUnit::addInvalidCoverage(LVSymbol *Symbol) {
+  LVOffset Offset = Symbol->getOffset();
+  if (InvalidCoverages.find(Offset) == InvalidCoverages.end())
+    InvalidCoverages.emplace(Offset, Symbol);
+}
+
+// Record symbols with invalid locations.
+void LVScopeCompileUnit::addInvalidLocation(LVLocation *Location) {
+  addInvalidLocationOrRange(Location, Location->getParentSymbol(),
+                            &InvalidLocations);
+}
+
+// Record scopes with invalid ranges.
+void LVScopeCompileUnit::addInvalidRange(LVLocation *Location) {
+  addInvalidLocationOrRange(Location, Location->getParentScope(),
+                            &InvalidRanges);
+}
+
+// Record line zero.
+void LVScopeCompileUnit::addLineZero(LVLine *Line) {
+  LVScope *Scope = Line->getParentScope();
+  LVOffset Offset = Scope->getOffset();
+  addInvalidOffset(Offset, Scope);
+  addItem<LVOffsetLinesMap, LVLines, LVOffset, LVLine *>(&LinesZero, Offset,
+                                                         Line);
+}
+
 void LVScopeCompileUnit::printLocalNames(raw_ostream &OS, bool Full) const {
   if (!options().getPrintFormatting())
     return;
@@ -1104,6 +1170,86 @@ void LVScopeCompileUnit::printLocalNames(raw_ostream &OS, bool Full) const {
     PrintNames(Option::File);
 }
 
+void LVScopeCompileUnit::printWarnings(raw_ostream &OS, bool Full) const {
+  auto PrintHeader = [&](const char *Header) { OS << "\n" << Header << ":\n"; };
+  auto PrintFooter = [&](auto &Set) {
+    if (Set.empty())
+      OS << "None\n";
+  };
+  auto PrintOffset = [&](unsigned &Count, LVOffset Offset) {
+    if (Count == 5) {
+      Count = 0;
+      OS << "\n";
+    }
+    ++Count;
+    OS << hexSquareString(Offset) << " ";
+  };
+  auto PrintElement = [&](const LVOffsetElementMap &Map, LVOffset Offset) {
+    LVOffsetElementMap::const_iterator Iter = Map.find(Offset);
+    LVElement *Element = Iter != Map.end() ? Iter->second : nullptr;
+    OS << "[" << hexString(Offset) << "]";
+    if (Element)
+      OS << " " << formattedKind(Element->kind()) << " "
+         << formattedName(Element->getName());
+    OS << "\n";
+  };
+  auto PrintInvalidLocations = [&](const LVOffsetLocationsMap &Map,
+                                   const char *Header) {
+    PrintHeader(Header);
+    for (LVOffsetLocationsMap::const_reference Entry : Map) {
+      PrintElement(WarningOffsets, Entry.first);
+      for (const LVLocation *Location : *Entry.second)
+        OS << hexSquareString(Location->getOffset()) << " "
+           << Location->getIntervalInfo() << "\n";
+    }
+    PrintFooter(Map);
+  };
+
+  if (options().getInternalTag() && getReader().isBinaryTypeELF()) {
+    PrintHeader("Unsupported DWARF Tags");
+    for (LVTagOffsetsMap::const_reference Entry : DebugTags) {
+      OS << format("\n0x%02x", (unsigned)Entry.first) << ", "
+         << dwarf::TagString(Entry.first) << "\n";
+      unsigned Count = 0;
+      for (const LVOffset &Offset : *Entry.second)
+        PrintOffset(Count, Offset);
+      OS << "\n";
+    }
+    PrintFooter(DebugTags);
+  }
+
+  if (options().getWarningCoverages()) {
+    PrintHeader("Symbols Invalid Coverages");
+    for (LVOffsetSymbolMap::const_reference Entry : InvalidCoverages) {
+      // Symbol basic information.
+      LVSymbol *Symbol = Entry.second;
+      OS << hexSquareString(Entry.first) << " {Coverage} "
+         << format("%.2f%%", Symbol->getCoveragePercentage()) << " "
+         << formattedKind(Symbol->kind()) << " "
+         << formattedName(Symbol->getName()) << "\n";
+    }
+    PrintFooter(InvalidCoverages);
+  }
+
+  if (options().getWarningLines()) {
+    PrintHeader("Lines Zero References");
+    for (LVOffsetLinesMap::const_reference Entry : LinesZero) {
+      PrintElement(WarningOffsets, Entry.first);
+      unsigned Count = 0;
+      for (const LVLine *Line : *Entry.second)
+        PrintOffset(Count, Line->getOffset());
+      OS << "\n";
+    }
+    PrintFooter(LinesZero);
+  }
+
+  if (options().getWarningLocations())
+    PrintInvalidLocations(InvalidLocations, "Invalid Location Ranges");
+
+  if (options().getWarningRanges())
+    PrintInvalidLocations(InvalidRanges, "Invalid Code Ranges");
+}
+
 void LVScopeCompileUnit::printTotals(raw_ostream &OS) const {
   OS << "\nTotals by lexical level:\n";
   for (size_t Index = 1; Index <= MaxSeenLevel; ++Index)

diff  --git a/llvm/lib/DebugInfo/LogicalView/Core/LVSymbol.cpp b/llvm/lib/DebugInfo/LogicalView/Core/LVSymbol.cpp
index 05d6b845b78e4..a467b3dd79463 100644
--- a/llvm/lib/DebugInfo/LogicalView/Core/LVSymbol.cpp
+++ b/llvm/lib/DebugInfo/LogicalView/Core/LVSymbol.cpp
@@ -212,6 +212,9 @@ void LVSymbol::calculateCoverage() {
             ? rint((double(CoverageFactor) / CoverageParent) * 100.0 * 100.0) /
                   100.0
             : 0;
+    // Record invalid coverage entry.
+    if (options().getWarningCoverages() && CoveragePercentage > 100)
+      getReaderCompileUnit()->addInvalidCoverage(this);
   }
 }
 

diff  --git a/llvm/unittests/DebugInfo/LogicalView/CMakeLists.txt b/llvm/unittests/DebugInfo/LogicalView/CMakeLists.txt
index 1b66e05922f15..8512fd1a868d8 100644
--- a/llvm/unittests/DebugInfo/LogicalView/CMakeLists.txt
+++ b/llvm/unittests/DebugInfo/LogicalView/CMakeLists.txt
@@ -8,6 +8,7 @@ add_llvm_unittest(DebugInfoLogicalViewTests
   LocationRangesTest.cpp
   LogicalElementsTest.cpp
   StringPoolTest.cpp
+  WarningInternalTest.cpp
   )
 
 target_link_libraries(DebugInfoLogicalViewTests PRIVATE LLVMTestingSupport)

diff  --git a/llvm/unittests/DebugInfo/LogicalView/WarningInternalTest.cpp b/llvm/unittests/DebugInfo/LogicalView/WarningInternalTest.cpp
new file mode 100644
index 0000000000000..e2444e36a6887
--- /dev/null
+++ b/llvm/unittests/DebugInfo/LogicalView/WarningInternalTest.cpp
@@ -0,0 +1,558 @@
+//===- llvm/unittest/DebugInfo/LogicalView/WarningInternalTest.cpp --------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/LogicalView/Core/LVLine.h"
+#include "llvm/DebugInfo/LogicalView/Core/LVReader.h"
+#include "llvm/DebugInfo/LogicalView/Core/LVScope.h"
+#include "llvm/DebugInfo/LogicalView/Core/LVSymbol.h"
+#include "llvm/DebugInfo/LogicalView/Core/LVType.h"
+#include "llvm/Support/ScopedPrinter.h"
+#include "llvm/Support/ToolOutputFile.h"
+#include "llvm/Testing/Support/Error.h"
+
+#include "gtest/gtest.h"
+
+using namespace llvm;
+using namespace llvm::logicalview;
+
+namespace {
+
+class MyLocation;
+
+// This code emulates the work done by the Readers when processing the
+// binary files and the creation of the AddressToLine mapping is done
+// automatically, using the text sections.
+class MyAddressToLine {
+  using LVAddressToLine = std::map<LVAddress, LVLine *>;
+  LVAddressToLine AddressToLineData;
+
+public:
+  MyAddressToLine() = default;
+
+  void insert(LVLine *Line) {
+    AddressToLineData.emplace(Line->getOffset(), Line);
+  }
+
+  LVLine *lineLowerBound(LVAddress Address);
+  LVLine *lineUpperBound(LVAddress Address);
+};
+
+LVLine *MyAddressToLine::lineLowerBound(LVAddress Address) {
+  LVAddressToLine::const_iterator Iter = AddressToLineData.lower_bound(Address);
+  return (Iter != AddressToLineData.end()) ? Iter->second : nullptr;
+}
+
+LVLine *MyAddressToLine::lineUpperBound(LVAddress Address) {
+  if (AddressToLineData.empty())
+    return nullptr;
+  LVAddressToLine::const_iterator Iter = AddressToLineData.upper_bound(Address);
+  if (Iter != AddressToLineData.begin())
+    Iter = std::prev(Iter);
+  return Iter->second;
+}
+
+MyAddressToLine AddressToLine;
+
+class ReaderTestWarningInternal : public LVReader {
+  // Types.
+  LVType *IntegerType = nullptr;
+
+  // Scopes.
+  LVScope *NestedScope = nullptr;
+  LVScopeFunction *Function = nullptr;
+
+  // Symbols.
+  LVSymbol *LocalVariable = nullptr;
+  LVSymbol *NestedVariable = nullptr;
+  LVSymbol *Parameter = nullptr;
+
+  // Lines.
+  LVLine *LineOne = nullptr;
+  LVLine *LineTwo = nullptr;
+  LVLine *LineThree = nullptr;
+  LVLine *LineFour = nullptr;
+  LVLine *LineFive = nullptr;
+  LVLine *LineSix = nullptr;
+
+  // Locations.
+  MyLocation *LocationOne = nullptr;
+  MyLocation *LocationTwo = nullptr;
+  MyLocation *LocationThree = nullptr;
+  MyLocation *LocationFour = nullptr;
+  MyLocation *LocationFive = nullptr;
+  MyLocation *LocationSix = nullptr;
+
+protected:
+  void add(LVScope *Parent, LVElement *Element);
+  template <typename T> T *create() {
+    T *Element = new (std::nothrow) T();
+    EXPECT_NE(Element, nullptr);
+    return Element;
+  }
+  void set(LVElement *Element, StringRef Name, LVOffset Offset,
+           uint32_t LineNumber = 0, LVElement *Type = nullptr);
+  void set(MyLocation *Location, LVLine *LowerLine, LVLine *UpperLine,
+           LVAddress LowerAddress, LVAddress UpperAddress);
+  void add(LVSymbol *Symbol, LVLine *LowerLine, LVLine *UpperLine);
+
+public:
+  ReaderTestWarningInternal(ScopedPrinter &W) : LVReader("", "", W) {
+    setInstance(this);
+  }
+
+  Error createScopes() { return LVReader::createScopes(); }
+
+  void setMapping();
+  void createElements();
+  void addElements();
+  void initElements();
+  void resolveElements();
+  void checkWarnings();
+};
+
+class MyLocation : public LVLocation {
+public:
+  bool validateRanges();
+};
+
+bool MyLocation::validateRanges() {
+  // Traverse the locations and validate them against the address to line
+  // mapping in the current compile unit. Record those invalid ranges.
+  // A valid range must meet the following conditions:
+  // a) line(lopc) <= line(hipc)
+  // b) line(lopc) and line(hipc) are valid.
+
+  LVLine *LowLine = AddressToLine.lineLowerBound(getLowerAddress());
+  LVLine *HighLine = AddressToLine.lineUpperBound(getUpperAddress());
+  if (LowLine)
+    setLowerLine(LowLine);
+  else {
+    setIsInvalidLower();
+    return false;
+  }
+  if (HighLine)
+    setUpperLine(HighLine);
+  else {
+    setIsInvalidUpper();
+    return false;
+  }
+  // Check for a valid interval.
+  if (LowLine->getLineNumber() > HighLine->getLineNumber()) {
+    setIsInvalidRange();
+    return false;
+  }
+
+  return true;
+}
+
+// Map all logical lines with their addresses.
+void ReaderTestWarningInternal::setMapping() {
+  AddressToLine.insert(LineOne);
+  AddressToLine.insert(LineTwo);
+  AddressToLine.insert(LineThree);
+  AddressToLine.insert(LineFour);
+  AddressToLine.insert(LineFive);
+  AddressToLine.insert(LineSix);
+}
+
+// Helper function to add a logical element to a given scope.
+void ReaderTestWarningInternal::add(LVScope *Parent, LVElement *Child) {
+  Parent->addElement(Child);
+  EXPECT_EQ(Child->getParent(), Parent);
+  EXPECT_EQ(Child->getLevel(), Parent->getLevel() + 1);
+}
+
+// Helper function to set the initial values for a given logical element.
+void ReaderTestWarningInternal::set(LVElement *Element, StringRef Name,
+                                    LVOffset Offset, uint32_t LineNumber,
+                                    LVElement *Type) {
+  Element->setName(Name);
+  Element->setOffset(Offset);
+  Element->setLineNumber(LineNumber);
+  Element->setType(Type);
+  EXPECT_EQ(Element->getName(), Name);
+  EXPECT_EQ(Element->getOffset(), Offset);
+  EXPECT_EQ(Element->getLineNumber(), LineNumber);
+  EXPECT_EQ(Element->getType(), Type);
+}
+
+// Helper function to set the initial values for a given logical location.
+void ReaderTestWarningInternal::set(MyLocation *Location, LVLine *LowerLine,
+                                    LVLine *UpperLine, LVAddress LowerAddress,
+                                    LVAddress UpperAddress) {
+  Location->setLowerLine(LowerLine);
+  Location->setUpperLine(UpperLine);
+  Location->setLowerAddress(LowerAddress);
+  Location->setUpperAddress(UpperAddress);
+  EXPECT_EQ(Location->getLowerLine(), LowerLine);
+  EXPECT_EQ(Location->getUpperLine(), UpperLine);
+  EXPECT_EQ(Location->getLowerAddress(), LowerAddress);
+  EXPECT_EQ(Location->getUpperAddress(), UpperAddress);
+}
+
+// Helper function to add a logical location to a logical symbol.
+void ReaderTestWarningInternal::add(LVSymbol *Symbol, LVLine *LowerLine,
+                                    LVLine *UpperLine) {
+  dwarf::Attribute Attr = dwarf::DW_AT_location;
+
+  Symbol->addLocation(Attr, LowerLine->getAddress(), UpperLine->getAddress(),
+                      /*SectionOffset=*/0, /*LocDesOffset=*/0);
+}
+
+// Create the logical elements.
+void ReaderTestWarningInternal::createElements() {
+  // Create scope root.
+  Error Err = createScopes();
+  ASSERT_THAT_ERROR(std::move(Err), Succeeded());
+  Root = getScopesRoot();
+  EXPECT_NE(Root, nullptr);
+
+  // Create the logical types.
+  IntegerType = create<LVType>();
+
+  // Create the logical scopes.
+  NestedScope = create<LVScope>();
+  CompileUnit = create<LVScopeCompileUnit>();
+  Function = create<LVScopeFunction>();
+
+  // Create the logical symbols.
+  LocalVariable = create<LVSymbol>();
+  NestedVariable = create<LVSymbol>();
+  Parameter = create<LVSymbol>();
+
+  // Create the logical lines.
+  LineOne = create<LVLine>();
+  LineTwo = create<LVLine>();
+  LineThree = create<LVLine>();
+  LineFour = create<LVLine>();
+  LineFive = create<LVLine>();
+  LineSix = create<LVLine>();
+
+  // Create the logical locations.
+  LocationOne = create<MyLocation>();
+  LocationTwo = create<MyLocation>();
+  LocationThree = create<MyLocation>();
+  LocationFour = create<MyLocation>();
+  LocationFive = create<MyLocation>();
+  LocationSix = create<MyLocation>();
+}
+
+// Create the logical view adding the created logical elements.
+void ReaderTestWarningInternal::addElements() {
+  setCompileUnit(CompileUnit);
+
+  // Root
+  //   CompileUnit
+  //     IntegerType
+  //     Function
+  //       LocationOne
+  //       LocationTwo
+  //       LocationFive
+  //       LocationSix
+  //       Parameter
+  //       LocalVariable
+  //       LineOne
+  //       LineTwo
+  //       NestedScope
+  //         LocationThree
+  //         LocationFour
+  //         NestedVariable
+  //         LineThree
+  //         LineFour
+  //       LineFive
+  //       LineSix
+
+  // Add elements to Root.
+  add(Root, CompileUnit);
+
+  // Add elements to CompileUnit.
+  add(CompileUnit, IntegerType);
+  add(CompileUnit, Function);
+
+  // Add elements to Function.
+  add(Function, Parameter);
+  add(Function, LocalVariable);
+  add(Function, LineOne);
+  add(Function, LineTwo);
+  add(Function, LineFive);
+  add(Function, LineSix);
+  add(Function, NestedScope);
+
+  // Add elements to NestedScope.
+  add(NestedScope, NestedVariable);
+  add(NestedScope, LineThree);
+  add(NestedScope, LineFour);
+}
+
+void ReaderTestWarningInternal::resolveElements() {
+  // Traverse the given scope and its children checking for any warnings.
+  std::function<void(LVScope * Parent)> TraverseScope = [&](LVScope *Parent) {
+    auto Warnings = [&](auto *Entry) {
+      if (Entry->getIsLine()) {
+        LVLine *Line = (LVLine *)Entry;
+        if (options().getWarningLines() && Line->getIsLineDebug() &&
+            !Line->getLineNumber())
+          CompileUnit->addLineZero(Line);
+      }
+    };
+    auto Traverse = [&](const auto *Set) {
+      if (Set)
+        for (const auto &Entry : *Set) {
+          Warnings(Entry);
+        }
+    };
+
+    Warnings(Parent);
+
+    Traverse(Parent->getSymbols());
+    Traverse(Parent->getTypes());
+    Traverse(Parent->getLines());
+
+    if (const LVScopes *Scopes = Parent->getScopes())
+      for (LVScope *Scope : *Scopes) {
+        Warnings(Scope);
+        TraverseScope(Scope);
+      }
+  };
+
+  // Start traversing the scopes root and resolve the elements.
+  TraverseScope(Root);
+}
+
+// Set initial values to logical elements.
+void ReaderTestWarningInternal::initElements() {
+  // Types.
+  set(IntegerType, "int", 0x1000);
+
+  // Scopes.
+  set(CompileUnit, "foo.cpp", 0x2000);
+  set(Function, "foo", 0x2010, 100, IntegerType);
+  set(NestedScope, "", 0x2020, 300);
+
+  // Symbols.
+  set(Parameter, "Param", 0x3000, 110, IntegerType);
+  set(LocalVariable, "LocalVariable", 0x3020, 120, IntegerType);
+  set(NestedVariable, "NestedVariable", 0x3010, 310, IntegerType);
+
+  // Lines.
+  set(LineOne, "", 0x5000, 100);
+  LineOne->setIsLineDebug();
+  set(LineTwo, "", 0x5200, 000);
+  LineTwo->setIsLineDebug();
+  set(LineThree, "", 0x5400, 300);
+  LineThree->setIsLineDebug();
+  set(LineFour, "", 0x5600, 000);
+  LineFour->setIsLineDebug();
+  set(LineFive, "", 0x5800, 500);
+  LineOne->setIsLineDebug();
+  set(LineSix, "", 0x6000, 600);
+  LineSix->setIsLineDebug();
+
+  // Locations.
+  set(LocationOne, LineOne, LineOne, 0x5000, 0x5100);
+  EXPECT_STREQ(LocationOne->getIntervalInfo().c_str(),
+               " Lines 100:100 [0x0000005000:0x0000005100]");
+
+  // Uses a Line zero.
+  set(LocationTwo, LineTwo, LineTwo, 0x5200, 0x5300);
+  EXPECT_STREQ(LocationTwo->getIntervalInfo().c_str(),
+               " Lines -:- [0x0000005200:0x0000005300]");
+
+  set(LocationThree, LineThree, LineThree, 0x5400, 0x5500);
+  EXPECT_STREQ(LocationThree->getIntervalInfo().c_str(),
+               " Lines 300:300 [0x0000005400:0x0000005500]");
+
+  // Uses a Line zero.
+  set(LocationFour, LineFour, LineFour, 0x5600, 0x5700);
+  LocationFour->setIsAddressRange();
+  EXPECT_STREQ(LocationFour->getIntervalInfo().c_str(),
+               "{Range} Lines -:- [0x0000005600:0x0000005700]");
+
+  // Invalid range.
+  set(LocationFive, LineFive, LineFive, 0x7800, 0x5900);
+  LocationFive->setIsAddressRange();
+  EXPECT_STREQ(LocationFive->getIntervalInfo().c_str(),
+               "{Range} Lines 500:500 [0x0000007800:0x0000005900]");
+
+  set(LocationSix, LineSix, LineSix, 0x6000, 0x6100);
+  LocationSix->setIsAddressRange();
+  EXPECT_STREQ(LocationSix->getIntervalInfo().c_str(),
+               "{Range} Lines 600:600 [0x0000006000:0x0000006100]");
+
+  // Add ranges to Function.
+  // Function: LocationOne, LocationTwo, LocationFive, LocationSix
+  Function->addObject(LocationOne);
+  Function->addObject(LocationTwo);
+  Function->addObject(LocationFive);
+  Function->addObject(LocationSix);
+  EXPECT_EQ(Function->rangeCount(), 4u);
+
+  // Add ranges to NestedScope.
+  // NestedScope: LocationThree, LocationFour
+  NestedScope->addObject(LocationThree);
+  NestedScope->addObject(LocationFour);
+  EXPECT_EQ(NestedScope->rangeCount(), 2u);
+
+  // Get all ranges.
+  LVRange Ranges;
+  CompileUnit->getRanges(Ranges);
+  Ranges.startSearch();
+  EXPECT_EQ(Ranges.getEntry(0x4000), nullptr);
+
+  EXPECT_EQ(Ranges.getEntry(0x5060), Function);
+  EXPECT_EQ(Ranges.getEntry(0x5850), nullptr);
+  EXPECT_EQ(Ranges.getEntry(0x5010, 0x5090), Function);
+  EXPECT_EQ(Ranges.getEntry(0x5210, 0x5290), Function);
+  EXPECT_EQ(Ranges.getEntry(0x5810, 0x5890), nullptr);
+  EXPECT_EQ(Ranges.getEntry(0x6010, 0x6090), Function);
+
+  EXPECT_EQ(Ranges.getEntry(0x5400), NestedScope);
+  EXPECT_EQ(Ranges.getEntry(0x5650), NestedScope);
+  EXPECT_EQ(Ranges.getEntry(0x5410, 0x5490), NestedScope);
+  EXPECT_EQ(Ranges.getEntry(0x5610, 0x5690), NestedScope);
+
+  EXPECT_EQ(Ranges.getEntry(0x8000), nullptr);
+  Ranges.endSearch();
+
+  // Add locations to symbols.
+  // Parameter:       [LineOne, LineSix]
+  // LocalVariable:   [LineTwo, LineSix], [LineFour, LineFive]
+  // NestedVariable:  [LineThree, LineFour]
+  add(Parameter, LineOne, LineSix);
+  add(LocalVariable, LineTwo, LineSix);
+  add(LocalVariable, LineFour, LineFive);
+  add(NestedVariable, LineThree, LineFour);
+  add(NestedVariable, LineOne, LineSix);
+}
+
+// Check logical elements warnigs.
+void ReaderTestWarningInternal::checkWarnings() {
+  // Map all lines with their addresses.
+  setMapping();
+
+  // Check for lines with line zero.
+  resolveElements();
+
+  // Check invalid locations and ranges using a customized validation.
+  CompileUnit->processRangeLocationCoverage(
+      (LVValidLocation)(&MyLocation::validateRanges));
+
+  // Get lines with line zero. [Parent, Line]
+  //   Function, LineTwo
+  //   NestedScope, LineFour
+  LVOffsetLinesMap LinesZero = CompileUnit->getLinesZero();
+  ASSERT_EQ(LinesZero.size(), 2u);
+
+  LVOffsetLinesMap::iterator IterZero = LinesZero.begin();
+  EXPECT_EQ(IterZero->first, Function->getOffset());
+  LVLines *Lines = IterZero->second;
+  EXPECT_NE(Lines, nullptr);
+  ASSERT_EQ(Lines->size(), 1u);
+  LVLine *Line = *(Lines->begin());
+  EXPECT_NE(Line, nullptr);
+  EXPECT_EQ(Line, LineTwo);
+
+  ++IterZero;
+  EXPECT_EQ(IterZero->first, NestedScope->getOffset());
+  Lines = IterZero->second;
+  EXPECT_NE(Lines, nullptr);
+  ASSERT_EQ(Lines->size(), 1u);
+  Line = *(Lines->begin());
+  EXPECT_NE(Line, nullptr);
+  EXPECT_EQ(Line, LineFour);
+
+  // Elements with invalid offsets.
+  //   Function (line zero)
+  //   NestedScope (line zero)
+  //   NestedVariable (invalid location)
+  LVOffsetElementMap InvalidOffsets = CompileUnit->getWarningOffsets();
+  ASSERT_EQ(InvalidOffsets.size(), 3u);
+
+  LVOffsetElementMap::iterator IterOffset = InvalidOffsets.begin();
+  EXPECT_EQ(IterOffset->second, Function);
+  ++IterOffset;
+  EXPECT_EQ(IterOffset->second, NestedScope);
+  ++IterOffset;
+  EXPECT_EQ(IterOffset->second, NestedVariable);
+
+  // Invalid ranges.
+  //   Function
+  LVOffsetLocationsMap InvalidRanges = CompileUnit->getInvalidRanges();
+  ASSERT_EQ(InvalidRanges.size(), 1u);
+
+  LVOffsetLocationsMap::iterator IterRange = InvalidRanges.begin();
+  EXPECT_EQ(IterRange->first, Function->getOffset());
+  LVLocations *Locations = IterRange->second;
+  EXPECT_NE(Locations, nullptr);
+  ASSERT_EQ(Locations->size(), 1u);
+  LVLocation *Location = *(Locations->begin());
+  EXPECT_NE(Location, nullptr);
+  EXPECT_EQ(Location, LocationFive);
+
+  // Invalid location.
+  //   NestedVariable
+  LVOffsetLocationsMap InvalidLocations = CompileUnit->getInvalidLocations();
+  ASSERT_EQ(InvalidLocations.size(), 1u);
+
+  LVOffsetLocationsMap::iterator IterLocations = InvalidLocations.begin();
+  EXPECT_EQ(IterLocations->first, NestedVariable->getOffset());
+  Locations = IterLocations->second;
+  EXPECT_NE(Locations, nullptr);
+  ASSERT_EQ(Locations->size(), 1u);
+  Location = *(Locations->begin());
+  EXPECT_NE(Location, nullptr);
+  EXPECT_EQ(Location->getLowerAddress(), LocationThree->getLowerAddress());
+  EXPECT_EQ(Location->getUpperAddress(), LocationFour->getLowerAddress());
+  EXPECT_EQ(Location->getLowerLine()->getLineNumber(),
+            LineThree->getLineNumber());
+  EXPECT_EQ(Location->getUpperLine()->getLineNumber(), 0u);
+
+  // Invalid coverages.
+  //   NestedVariable
+  LVOffsetSymbolMap InvalidCoverages = CompileUnit->getInvalidCoverages();
+  ASSERT_EQ(InvalidCoverages.size(), 1u);
+
+  LVOffsetSymbolMap::iterator IterCoverages = InvalidCoverages.begin();
+  EXPECT_EQ(IterCoverages->first, NestedVariable->getOffset());
+  EXPECT_EQ(IterCoverages->second, NestedVariable);
+  EXPECT_GE((int)NestedVariable->getCoveragePercentage(), 100);
+  EXPECT_EQ((int)NestedVariable->getCoveragePercentage(), 900);
+  EXPECT_EQ(NestedVariable->getCoverageFactor(), 0x1200u);
+
+  EXPECT_EQ((unsigned)Parameter->getCoveragePercentage(), 100u);
+  EXPECT_EQ(Parameter->getCoverageFactor(), 100u);
+
+  EXPECT_EQ((unsigned)LocalVariable->getCoveragePercentage(), 47u);
+  EXPECT_EQ(LocalVariable->getCoverageFactor(),
+            LineSix->getAddress() - LineOne->getAddress());
+}
+
+TEST(LogicalViewTest, WarningInternal) {
+  ScopedPrinter W(outs());
+  ReaderTestWarningInternal Reader(W);
+
+  // Reader options.
+  LVOptions ReaderOptions;
+  ReaderOptions.setAttributeOffset();
+  ReaderOptions.setAttributeRange();
+  ReaderOptions.setAttributeLocation();
+  ReaderOptions.setPrintAll();
+  ReaderOptions.setWarningCoverages();
+  ReaderOptions.setWarningLines();
+  ReaderOptions.setWarningLocations();
+  ReaderOptions.setWarningRanges();
+  ReaderOptions.resolveDependencies();
+  options().setOptions(&ReaderOptions);
+
+  Reader.createElements();
+  Reader.addElements();
+  Reader.initElements();
+  Reader.checkWarnings();
+}
+
+} // namespace


        


More information about the llvm-commits mailing list