
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 8a) Memory Management 9) CodeView Reader Full details: https://discourse.llvm.org/t/llvm-dev-rfc-llvm-dva-debug-information-visual-analyzer/62570 This patch: This is a high level summary of the changes in this patch. Memory Management - Use Bump allocators for memory management. As the logical elements are only allocated in one pass (debuginfo parsing) and they are never manipulated/created/destroyed later, use the SpecificBumpPtrAllocator for the memory management. Reviewed By: dblaikie, Orlando Differential Revision: https://reviews.llvm.org/D137933
566 lines
18 KiB
C++
566 lines
18 KiB
C++
//===- 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 : public LVLocation {
|
|
public:
|
|
bool validateRanges();
|
|
};
|
|
|
|
// 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 {
|
|
#define CREATE(VARIABLE, CREATE_FUNCTION) \
|
|
VARIABLE = CREATE_FUNCTION(); \
|
|
EXPECT_NE(VARIABLE, nullptr);
|
|
|
|
#define CREATE_CUSTOM(VARIABLE, CREATE_FUNCTION) \
|
|
VARIABLE = CREATE_FUNCTION(); \
|
|
EXPECT_NE(VARIABLE, nullptr);
|
|
|
|
// 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;
|
|
|
|
llvm::SpecificBumpPtrAllocator<MyLocation> AllocatedLocations;
|
|
|
|
protected:
|
|
MyLocation *createCustomLocation() {
|
|
return new (AllocatedLocations.Allocate()) MyLocation();
|
|
}
|
|
|
|
void add(LVSymbol *Symbol, LVLine *LowerLine, LVLine *UpperLine);
|
|
void add(LVScope *Parent, LVElement *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);
|
|
|
|
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();
|
|
};
|
|
|
|
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.
|
|
CREATE(IntegerType, createType);
|
|
|
|
// Create the logical scopes.
|
|
CREATE(NestedScope, createScope);
|
|
CREATE(CompileUnit, createScopeCompileUnit);
|
|
CREATE(Function, createScopeFunction);
|
|
|
|
// Create the logical symbols.
|
|
CREATE(LocalVariable, createSymbol);
|
|
CREATE(NestedVariable, createSymbol);
|
|
CREATE(Parameter, createSymbol);
|
|
|
|
// Create the logical lines.
|
|
CREATE(LineOne, createLine);
|
|
CREATE(LineTwo, createLine);
|
|
CREATE(LineThree, createLine);
|
|
CREATE(LineFour, createLine);
|
|
CREATE(LineFive, createLine);
|
|
CREATE(LineSix, createLine);
|
|
|
|
// Create the logical locations.
|
|
CREATE_CUSTOM(LocationOne, createCustomLocation);
|
|
CREATE_CUSTOM(LocationTwo, createCustomLocation);
|
|
CREATE_CUSTOM(LocationThree, createCustomLocation);
|
|
CREATE_CUSTOM(LocationFour, createCustomLocation);
|
|
CREATE_CUSTOM(LocationFive, createCustomLocation);
|
|
CREATE_CUSTOM(LocationSix, createCustomLocation);
|
|
}
|
|
|
|
// 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
|