#include "llvm/DebugInfo/LogicalView/Core/LVObject.h"
#include "llvm/DebugInfo/LogicalView/Core/LVStringPool.h"
#include "llvm/Support/Casting.h"
+#include <map>
#include <set>
+#include <vector>
namespace llvm {
namespace logicalview {
enum class LVElementKind { Discarded, Global, Optimized, LastEntry };
using LVElementKindSet = std::set<LVElementKind>;
+using LVElementDispatch = std::map<LVElementKind, LVElementGetFunction>;
+using LVElementRequest = std::vector<LVElementGetFunction>;
class LVElement : public LVObject {
enum class Property {
};
// Typed bitvector with properties for this element.
LVProperties<Property> Properties;
+ static LVElementDispatch Dispatch;
/// RTTI.
const LVSubclassID SubclassID;
virtual void resolveName();
virtual void resolveReferences() {}
void resolveParents();
+
+public:
+ static LVElementDispatch &getDispatch() { return Dispatch; }
};
} // end namespace logicalview
LastEntry
};
using LVLineKindSet = std::set<LVLineKind>;
+using LVLineDispatch = std::map<LVLineKind, LVLineGetFunction>;
+using LVLineRequest = std::vector<LVLineGetFunction>;
// Class to represent a logical line.
class LVLine : public LVElement {
// Typed bitvector with kinds for this line.
LVProperties<LVLineKind> Kinds;
+ static LVLineDispatch Dispatch;
public:
LVLine() : LVElement(LVSubclassID::LV_LINE) {
return lineAsString(getLineNumber(), getDiscriminator(), ShowZero);
}
+ static LVLineDispatch &getDispatch() { return Dispatch; }
+
void print(raw_ostream &OS, bool Full = true) const override;
void printExtra(raw_ostream &OS, bool Full = true) const override {}
#include "llvm/ADT/StringSet.h"
#include "llvm/DebugInfo/LogicalView/Core/LVLine.h"
-#include "llvm/DebugInfo/LogicalView/Core/LVOptions.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/Regex.h"
#include <set>
#include <string>
inline LVOptions &options() { return (*LVOptions::getOptions()); }
inline void setOptions(LVOptions *Options) { LVOptions::setOptions(Options); }
+class LVPatterns final {
+ // Pattern Mode.
+ enum class LVMatchMode {
+ None = 0, // No given pattern.
+ Match, // Perfect match.
+ NoCase, // Ignore case.
+ Regex // Regular expression.
+ };
+
+ // Keep the search pattern information.
+ struct LVMatch {
+ std::string Pattern; // Normal pattern.
+ std::shared_ptr<Regex> RE; // Regular Expression Pattern.
+ LVMatchMode Mode = LVMatchMode::None; // Match mode.
+ };
+
+ using LVMatchInfo = std::vector<LVMatch>;
+ LVMatchInfo GenericMatchInfo;
+ using LVMatchOffsets = std::vector<uint64_t>;
+ LVMatchOffsets OffsetMatchInfo;
+
+ // Element selection.
+ LVElementDispatch ElementDispatch;
+ LVLineDispatch LineDispatch;
+ LVScopeDispatch ScopeDispatch;
+ LVSymbolDispatch SymbolDispatch;
+ LVTypeDispatch TypeDispatch;
+
+ // Element selection request.
+ LVElementRequest ElementRequest;
+ LVLineRequest LineRequest;
+ LVScopeRequest ScopeRequest;
+ LVSymbolRequest SymbolRequest;
+ LVTypeRequest TypeRequest;
+
+ // Check an element printing Request.
+ template <typename T, typename U>
+ bool checkElementRequest(const T *Element, const U &Requests) const {
+ assert(Element && "Element must not be nullptr");
+ for (const auto &Request : Requests)
+ if ((Element->*Request)())
+ return true;
+ // Check generic element requests.
+ for (const LVElementGetFunction &Request : ElementRequest)
+ if ((Element->*Request)())
+ return true;
+ return false;
+ }
+
+ // Add an element printing request based on its kind.
+ template <typename T, typename U, typename V>
+ void addRequest(const T &Selection, const U &Dispatch, V &Request) const {
+ for (const auto &Entry : Selection) {
+ // Find target function to fullfit request.
+ typename U::const_iterator Iter = Dispatch.find(Entry);
+ if (Iter != Dispatch.end())
+ Request.push_back(Iter->second);
+ }
+ }
+
+ void addElement(LVElement *Element);
+
+ template <typename T, typename U>
+ void resolveGenericPatternMatch(T *Element, const U &Requests) {
+ assert(Element && "Element must not be nullptr");
+ auto CheckPattern = [=]() -> bool {
+ return Element->isNamed() &&
+ (matchGenericPattern(Element->getName()) ||
+ matchGenericPattern(Element->getTypeName()));
+ };
+ auto CheckOffset = [=]() -> bool {
+ return matchOffsetPattern(Element->getOffset());
+ };
+ if ((options().getSelectGenericPattern() && CheckPattern()) ||
+ (options().getSelectOffsetPattern() && CheckOffset()) ||
+ ((Requests.size() || ElementRequest.size()) &&
+ checkElementRequest(Element, Requests)))
+ addElement(Element);
+ }
+
+ template <typename U>
+ void resolveGenericPatternMatch(LVLine *Line, const U &Requests) {
+ assert(Line && "Line must not be nullptr");
+ auto CheckPattern = [=]() -> bool {
+ return matchGenericPattern(Line->lineNumberAsStringStripped()) ||
+ matchGenericPattern(Line->getName()) ||
+ matchGenericPattern(Line->getPathname());
+ };
+ auto CheckOffset = [=]() -> bool {
+ return matchOffsetPattern(Line->getAddress());
+ };
+ if ((options().getSelectGenericPattern() && CheckPattern()) ||
+ (options().getSelectOffsetPattern() && CheckOffset()) ||
+ (Requests.size() && checkElementRequest(Line, Requests)))
+ addElement(Line);
+ }
+
+ Error createMatchEntry(LVMatchInfo &Filters, StringRef Pattern,
+ bool IgnoreCase, bool UseRegex);
+
+public:
+ static LVPatterns *getPatterns();
+
+ LVPatterns() {
+ ElementDispatch = LVElement::getDispatch();
+ LineDispatch = LVLine::getDispatch();
+ ScopeDispatch = LVScope::getDispatch();
+ SymbolDispatch = LVSymbol::getDispatch();
+ TypeDispatch = LVType::getDispatch();
+ }
+ LVPatterns(const LVPatterns &) = delete;
+ LVPatterns &operator=(const LVPatterns &) = delete;
+ ~LVPatterns() = default;
+
+ // Clear any existing patterns.
+ void clear() {
+ GenericMatchInfo.clear();
+ OffsetMatchInfo.clear();
+ ElementRequest.clear();
+ LineRequest.clear();
+ ScopeRequest.clear();
+ SymbolRequest.clear();
+ TypeRequest.clear();
+
+ options().resetSelectGenericKind();
+ options().resetSelectGenericPattern();
+ options().resetSelectOffsetPattern();
+ }
+
+ void addRequest(LVElementKindSet &Selection) {
+ addRequest(Selection, ElementDispatch, ElementRequest);
+ }
+ void addRequest(LVLineKindSet &Selection) {
+ addRequest(Selection, LineDispatch, LineRequest);
+ }
+ void addRequest(LVScopeKindSet &Selection) {
+ addRequest(Selection, ScopeDispatch, ScopeRequest);
+ }
+ void addRequest(LVSymbolKindSet &Selection) {
+ addRequest(Selection, SymbolDispatch, SymbolRequest);
+ }
+ void addRequest(LVTypeKindSelection &Selection) {
+ addRequest(Selection, TypeDispatch, TypeRequest);
+ }
+
+ void updateReportOptions();
+
+ bool matchPattern(StringRef Input, const LVMatchInfo &MatchInfo);
+ // Match a pattern (--select='pattern').
+ bool matchGenericPattern(StringRef Input) {
+ return matchPattern(Input, GenericMatchInfo);
+ }
+ bool matchOffsetPattern(LVOffset Offset) {
+ return std::find(OffsetMatchInfo.begin(), OffsetMatchInfo.end(), Offset) !=
+ OffsetMatchInfo.end();
+ }
+
+ void resolvePatternMatch(LVLine *Line) {
+ resolveGenericPatternMatch(Line, LineRequest);
+ }
+
+ void resolvePatternMatch(LVScope *Scope) {
+ resolveGenericPatternMatch(Scope, ScopeRequest);
+ }
+
+ void resolvePatternMatch(LVSymbol *Symbol) {
+ resolveGenericPatternMatch(Symbol, SymbolRequest);
+ }
+
+ void resolvePatternMatch(LVType *Type) {
+ resolveGenericPatternMatch(Type, TypeRequest);
+ }
+
+ void addPatterns(StringSet<> &Patterns, LVMatchInfo &Filters);
+
+ // Add generic and offset patterns info.
+ void addGenericPatterns(StringSet<> &Patterns);
+ void addOffsetPatterns(const LVOffsetSet &Patterns);
+
+ // Conditions to print an object.
+ bool printElement(const LVLine *Line) const;
+ bool printObject(const LVLocation *Location) const;
+ bool printElement(const LVScope *Scope) const;
+ bool printElement(const LVSymbol *Symbol) const;
+ bool printElement(const LVType *Type) const;
+
+ void print(raw_ostream &OS) const;
+
+#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
+ void dump() const { print(dbgs()); }
+#endif
+};
+
+inline LVPatterns &patterns() { return *LVPatterns::getPatterns(); }
+
} // namespace logicalview
} // namespace llvm
LVSplitContext &getSplitContext() { return SplitContext; }
// Conditions to print an object.
- bool doPrintLine(const LVLine *Line) const { return true; }
- bool doPrintLocation(const LVLocation *Location) const { return true; }
- bool doPrintScope(const LVScope *Scope) const { return true; }
- bool doPrintSymbol(const LVSymbol *Symbol) const { return true; }
- bool doPrintType(const LVType *Type) const { return true; }
+ bool doPrintLine(const LVLine *Line) const {
+ return patterns().printElement(Line);
+ }
+ bool doPrintLocation(const LVLocation *Location) const {
+ return patterns().printObject(Location);
+ }
+ bool doPrintScope(const LVScope *Scope) const {
+ return patterns().printElement(Scope);
+ }
+ bool doPrintSymbol(const LVSymbol *Symbol) const {
+ return patterns().printElement(Symbol);
+ }
+ bool doPrintType(const LVType *Type) const {
+ return patterns().printElement(Type);
+ }
static LVReader &getInstance();
static void setInstance(LVReader *Reader);
LastEntry
};
using LVScopeKindSet = std::set<LVScopeKind>;
+using LVScopeDispatch = std::map<LVScopeKind, LVScopeGetFunction>;
+using LVScopeRequest = std::vector<LVScopeGetFunction>;
using LVOffsetElementMap = std::map<LVOffset, LVElement *>;
// Typed bitvector with kinds and properties for this scope.
LVProperties<LVScopeKind> Kinds;
LVProperties<Property> Properties;
+ static LVScopeDispatch Dispatch;
// Coverage factor in units (bytes).
unsigned CoverageFactor = 0;
void printEncodedArgs(raw_ostream &OS, bool Full) const;
void printActiveRanges(raw_ostream &OS, bool Full = true) const;
- virtual void printSizes(raw_ostream &OS) const {};
- virtual void printSummary(raw_ostream &OS) const {};
+ virtual void printSizes(raw_ostream &OS) const {}
+ virtual void printSummary(raw_ostream &OS) const {}
// Encoded template arguments.
virtual StringRef getEncodedArgs() const { return StringRef(); }
void resolveElements();
+ static LVScopeDispatch &getDispatch() { return Dispatch; }
+
void print(raw_ostream &OS, bool Full = true) const override;
void printExtra(raw_ostream &OS, bool Full = true) const override;
virtual void printMatchedElements(raw_ostream &OS, bool UseMatchedElements) {}
LVScopeCompileUnit &operator=(const LVScopeCompileUnit &) = delete;
~LVScopeCompileUnit() = default;
+ LVScope *getCompileUnitParent() const override {
+ return static_cast<LVScope *>(const_cast<LVScopeCompileUnit *>(this));
+ }
+
// Get the line located at the given address.
LVLine *lineLowerBound(LVAddress Address) const;
LVLine *lineUpperBound(LVAddress Address) const;
void processRangeLocationCoverage(
LVValidLocation ValidLocation = &LVLocation::validateRanges);
+ // Add matched element.
+ void addMatched(LVElement *Element) { MatchedElements.push_back(Element); }
+ void addMatched(LVScope *Scope) { MatchedScopes.push_back(Scope); }
+ void propagatePatternMatch();
+
+ const LVElements &getMatchedElements() const { return MatchedElements; }
+ const LVScopes &getMatchedScopes() const { return MatchedScopes; }
+
void printLocalNames(raw_ostream &OS, bool Full = true) const;
void printSummary(raw_ostream &OS, const LVCounter &Counter,
const char *Header) const;
LastEntry
};
using LVSymbolKindSet = std::set<LVSymbolKind>;
+using LVSymbolDispatch = std::map<LVSymbolKind, LVSymbolGetFunction>;
+using LVSymbolRequest = std::vector<LVSymbolGetFunction>;
class LVSymbol final : public LVElement {
enum class Property { HasLocation, FillGaps, LastEntry };
// Typed bitvector with kinds and properties for this symbol.
LVProperties<LVSymbolKind> Kinds;
LVProperties<Property> Properties;
+ static LVSymbolDispatch Dispatch;
// CodeView symbol Linkage name.
size_t LinkageNameIndex = 0;
void resolveName() override;
void resolveReferences() override;
+ static LVSymbolDispatch &getDispatch() { return Dispatch; }
+
void print(raw_ostream &OS, bool Full = true) const override;
void printExtra(raw_ostream &OS, bool Full = true) const override;
LastEntry
};
using LVTypeKindSelection = std::set<LVTypeKind>;
+using LVTypeDispatch = std::map<LVTypeKind, LVTypeGetFunction>;
+using LVTypeRequest = std::vector<LVTypeGetFunction>;
// Class to represent a DWARF Type.
class LVType : public LVElement {
// Typed bitvector with kinds and properties for this type.
LVProperties<LVTypeKind> Kinds;
LVProperties<Property> Properties;
+ static LVTypeDispatch Dispatch;
public:
LVType() : LVElement(LVSubclassID::LV_TYPE) { setIsType(); }
void resolveName() override;
void resolveReferences() override;
+ static LVTypeDispatch &getDispatch() { return Dispatch; }
+
void print(raw_ostream &OS, bool Full = true) const override;
void printExtra(raw_ostream &OS, bool Full = true) const override;
#define DEBUG_TYPE "Element"
+LVElementDispatch LVElement::Dispatch = {
+ {LVElementKind::Discarded, &LVElement::getIsDiscarded},
+ {LVElementKind::Global, &LVElement::getIsGlobalReference},
+ {LVElementKind::Optimized, &LVElement::getIsOptimized}};
+
LVType *LVElement::getTypeAsType() const {
return ElementType && ElementType->getIsType()
? static_cast<LVType *>(ElementType)
return Kind;
}
+LVLineDispatch LVLine::Dispatch = {
+ {LVLineKind::IsBasicBlock, &LVLine::getIsBasicBlock},
+ {LVLineKind::IsDiscriminator, &LVLine::getIsDiscriminator},
+ {LVLineKind::IsEndSequence, &LVLine::getIsEndSequence},
+ {LVLineKind::IsLineDebug, &LVLine::getIsLineDebug},
+ {LVLineKind::IsLineAssembler, &LVLine::getIsLineAssembler},
+ {LVLineKind::IsNewStatement, &LVLine::getIsNewStatement},
+ {LVLineKind::IsEpilogueBegin, &LVLine::getIsEpilogueBegin},
+ {LVLineKind::IsPrologueEnd, &LVLine::getIsPrologueEnd},
+ {LVLineKind::IsAlwaysStepInto, &LVLine::getIsAlwaysStepInto},
+ {LVLineKind::IsNeverStepInto, &LVLine::getIsNeverStepInto}};
+
// String used as padding for printing elements with no line number.
std::string LVLine::noLineAsString(bool ShowZero) const {
return (ShowZero || options().getAttributeZero()) ? (" 0 ")
//===----------------------------------------------------------------------===//
#include "llvm/DebugInfo/LogicalView/Core/LVOptions.h"
+#include "llvm/DebugInfo/LogicalView/Core/LVReader.h"
+#include "llvm/Support/Errc.h"
using namespace llvm;
using namespace llvm::logicalview;
<< "Tag: " << Options.getInternalTag() << "\n"
<< "\n";
}
+
+//===----------------------------------------------------------------------===//
+// Logical element selection using patterns.
+//===----------------------------------------------------------------------===//
+LVPatterns *LVPatterns::getPatterns() {
+ static LVPatterns Patterns;
+ return &Patterns;
+}
+
+Error LVPatterns::createMatchEntry(LVMatchInfo &Filters, StringRef Pattern,
+ bool IgnoreCase, bool UseRegex) {
+ LVMatch Match;
+ // Process pattern as regular expression.
+ if (UseRegex) {
+ Match.Pattern = std::string(Pattern);
+ if (Pattern.size()) {
+ Match.RE = std::make_shared<Regex>(Pattern, IgnoreCase ? Regex::IgnoreCase
+ : Regex::NoFlags);
+ std::string Error;
+ if (!Match.RE->isValid(Error))
+ return createStringError(errc::invalid_argument,
+ "Error in regular expression: %s",
+ Error.c_str());
+
+ Match.Mode = LVMatchMode::Regex;
+ Filters.push_back(Match);
+ return Error::success();
+ }
+ }
+
+ // Process pattern as an exact string match, depending on the case.
+ Match.Pattern = std::string(Pattern);
+ if (Match.Pattern.size()) {
+ Match.Mode = IgnoreCase ? LVMatchMode::NoCase : LVMatchMode::Match;
+ Filters.push_back(Match);
+ }
+
+ return Error::success();
+}
+
+void LVPatterns::addGenericPatterns(StringSet<> &Patterns) {
+ addPatterns(Patterns, GenericMatchInfo);
+ if (GenericMatchInfo.size()) {
+ options().setSelectGenericPattern();
+ options().setSelectExecute();
+ }
+}
+
+void LVPatterns::addOffsetPatterns(const LVOffsetSet &Patterns) {
+ for (const LVOffset &Entry : Patterns)
+ OffsetMatchInfo.push_back(Entry);
+ if (OffsetMatchInfo.size()) {
+ options().setSelectOffsetPattern();
+ options().setSelectExecute();
+ }
+}
+
+void LVPatterns::addPatterns(StringSet<> &Patterns, LVMatchInfo &Filters) {
+ bool IgnoreCase = options().getSelectIgnoreCase();
+ bool UseRegex = options().getSelectUseRegex();
+ for (const StringSet<>::value_type &Entry : Patterns) {
+ StringRef Pattern = Entry.first();
+ if (Error Err = createMatchEntry(Filters, Pattern, IgnoreCase, UseRegex))
+ consumeError(std::move(Err));
+ }
+
+ LLVM_DEBUG({
+ dbgs() << "\nPattern Information:\n";
+ for (LVMatch &Match : Filters)
+ dbgs() << "Mode: "
+ << (Match.Mode == LVMatchMode::Match ? "Match" : "Regex")
+ << " Pattern: '" << Match.Pattern << "'\n";
+ });
+}
+
+void LVPatterns::addElement(LVElement *Element) {
+ // Mark any element that matches a given pattern.
+ Element->setIsMatched();
+ options().setSelectExecute();
+ if (options().getReportList())
+ getReaderCompileUnit()->addMatched(Element);
+ if (options().getReportAnyView()) {
+ getReaderCompileUnit()->addMatched(Element->getIsScope()
+ ? static_cast<LVScope *>(Element)
+ : Element->getParentScope());
+ // Mark element as matched.
+ if (!Element->getIsScope())
+ Element->setHasPattern();
+ }
+}
+
+void LVPatterns::updateReportOptions() {
+ if (ElementRequest.size() || LineRequest.size() || ScopeRequest.size() ||
+ SymbolRequest.size() || TypeRequest.size()) {
+ options().setSelectGenericKind();
+ options().setSelectExecute();
+ }
+
+ // If we have selected requests and there are no specified report options,
+ // assume the 'details' option.
+ if (options().getSelectExecute() && !options().getReportExecute()) {
+ options().setReportExecute();
+ options().setReportList();
+ }
+}
+
+// Match a general pattern.
+bool LVPatterns::matchPattern(StringRef Input, const LVMatchInfo &MatchInfo) {
+ bool Matched = false;
+ // Traverse all match specifications.
+ for (const LVMatch &Match : MatchInfo) {
+ switch (Match.Mode) {
+ case LVMatchMode::Match:
+ Matched = Input.equals(Match.Pattern);
+ break;
+ case LVMatchMode::NoCase:
+ Matched = Input.equals_insensitive(Match.Pattern);
+ break;
+ case LVMatchMode::Regex:
+ Matched = Match.RE->match(Input);
+ break;
+ default:
+ break;
+ }
+ // Return if we have a match.
+ if (Matched)
+ return true;
+ }
+ return Matched;
+}
+
+bool LVPatterns::printElement(const LVLine *Line) const {
+ return (options().getPrintLines() && Line->getIsLineDebug()) ||
+ (options().getPrintInstructions() && Line->getIsLineAssembler());
+}
+
+bool LVPatterns::printObject(const LVLocation *Location) const {
+ if (options().getAttributeAll())
+ return true;
+ bool DoPrint = options().getAttributeAnyLocation();
+ // Consider the case of filler locations.
+ if (DoPrint && Location && Location->getIsGapEntry())
+ DoPrint = options().getAttributeGaps();
+ return DoPrint;
+}
+
+bool LVPatterns::printElement(const LVScope *Scope) const {
+ // A scope will be printed depending on the following rules:
+ // - Request to print scopes.
+ // - Request to print any of its children.
+ // - If the scope is Root or CompileUnit:
+ // Request to print summary, sizes or warnings.
+ return options().getPrintScopes() ||
+ (options().getPrintSymbols() && Scope->getHasSymbols()) ||
+ (options().getPrintAnyLine() && Scope->getHasLines()) ||
+ (options().getPrintTypes() && Scope->getHasTypes()) ||
+ ((options().getPrintSizesSummary() || options().getPrintWarnings()) &&
+ (Scope->getIsRoot() || Scope->getIsCompileUnit()));
+}
+
+bool LVPatterns::printElement(const LVSymbol *Symbol) const {
+ // Print compiler generated symbols only if command line option.
+ if (Symbol->getIsArtificial())
+ return options().getAttributeGenerated() && options().getPrintSymbols();
+ return options().getPrintSymbols();
+}
+
+bool LVPatterns::printElement(const LVType *Type) const {
+ // Print array subranges only if print types is requested.
+ if (Type->getIsSubrange())
+ return options().getAttributeSubrange() && options().getPrintTypes();
+ return options().getPrintTypes();
+}
+
+void LVPatterns::print(raw_ostream &OS) const {
+ OS << "LVPatterns\n";
+ LLVM_DEBUG(dbgs() << "Print Patterns\n");
+}
// Set current Reader instance.
setInstance(this);
+ // Before any scopes creation, process any pattern specified by the
+ // --select and --select-offsets options.
+ patterns().addGenericPatterns(options().Select.Generic);
+ patterns().addOffsetPatterns(options().Select.Offsets);
+
+ // Add any specific element printing requests based on the element kind.
+ patterns().addRequest(options().Select.Elements);
+ patterns().addRequest(options().Select.Lines);
+ patterns().addRequest(options().Select.Scopes);
+ patterns().addRequest(options().Select.Symbols);
+ patterns().addRequest(options().Select.Types);
+
+ // Once we have processed the requests for any particular kind of elements,
+ // we need to update the report options, in order to have a default value.
+ patterns().updateReportOptions();
+
// Delegate the scope tree creation to the specific reader.
if (Error Err = createScopes())
return Err;
// Set current Reader instance.
setInstance(this);
+ // Check for any '--report' request.
+ if (options().getReportExecute()) {
+ // Requested details.
+ if (options().getReportList())
+ if (Error Err = printMatchedElements(/*UseMatchedElements=*/true))
+ return Err;
+ // Requested only children.
+ if (options().getReportChildren() && !options().getReportParents())
+ if (Error Err = printMatchedElements(/*UseMatchedElements=*/false))
+ return Err;
+ // Requested (parents) or (parents and children).
+ if (options().getReportParents() || options().getReportView())
+ if (Error Err = printScopes())
+ return Err;
+
+ return Error::success();
+ }
+
return printScopes();
}
return Err;
// Start printing from the root.
- bool DoMatch = false;
+ bool DoMatch = options().getSelectGenericPattern() ||
+ options().getSelectGenericKind() ||
+ options().getSelectOffsetPattern();
return Root->doPrint(OutputSplit, DoMatch, DoPrint, OS);
}
return Kind;
}
+LVScopeDispatch LVScope::Dispatch = {
+ {LVScopeKind::IsAggregate, &LVScope::getIsAggregate},
+ {LVScopeKind::IsArray, &LVScope::getIsArray},
+ {LVScopeKind::IsBlock, &LVScope::getIsBlock},
+ {LVScopeKind::IsCallSite, &LVScope::getIsCallSite},
+ {LVScopeKind::IsCatchBlock, &LVScope::getIsCatchBlock},
+ {LVScopeKind::IsClass, &LVScope::getIsClass},
+ {LVScopeKind::IsCompileUnit, &LVScope::getIsCompileUnit},
+ {LVScopeKind::IsEntryPoint, &LVScope::getIsEntryPoint},
+ {LVScopeKind::IsEnumeration, &LVScope::getIsEnumeration},
+ {LVScopeKind::IsFunction, &LVScope::getIsFunction},
+ {LVScopeKind::IsFunctionType, &LVScope::getIsFunctionType},
+ {LVScopeKind::IsInlinedFunction, &LVScope::getIsInlinedFunction},
+ {LVScopeKind::IsLabel, &LVScope::getIsLabel},
+ {LVScopeKind::IsLexicalBlock, &LVScope::getIsLexicalBlock},
+ {LVScopeKind::IsNamespace, &LVScope::getIsNamespace},
+ {LVScopeKind::IsRoot, &LVScope::getIsRoot},
+ {LVScopeKind::IsStructure, &LVScope::getIsStructure},
+ {LVScopeKind::IsTemplate, &LVScope::getIsTemplate},
+ {LVScopeKind::IsTemplateAlias, &LVScope::getIsTemplateAlias},
+ {LVScopeKind::IsTemplatePack, &LVScope::getIsTemplatePack},
+ {LVScopeKind::IsTryBlock, &LVScope::getIsTryBlock},
+ {LVScopeKind::IsUnion, &LVScope::getIsUnion}};
+
void LVScope::addToChildren(LVElement *Element) {
if (!Children)
Children = new LVElements();
}
LVElement::resolveName();
+
+ // Resolve any given pattern.
+ patterns().resolvePatternMatch(this);
}
void LVScope::resolveReferences() {
LVScopeCompileUnit *CompileUnit = static_cast<LVScopeCompileUnit *>(Scope);
getReader().setCompileUnit(CompileUnit);
CompileUnit->resolve();
+ // Propagate any matching information into the scopes tree.
+ CompileUnit->propagatePatternMatch();
}
}
}
bool LVScope::resolvePrinting() const {
+ // 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.
+ if (options().getSelectExecute()) {
+ return getIsRoot() || getIsCompileUnit() || getHasPattern();
+ }
+
bool Globals = options().getAttributeGlobal();
bool Locals = options().getAttributeLocal();
if ((Globals && Locals) || (!Globals && !Locals)) {
void LVScope::print(raw_ostream &OS, bool Full) const {
if (getIncludeInPrint() && getReader().doPrintScope(this)) {
// For a summary (printed elements), do not count the scope root.
- if (!(getIsRoot()))
+ // For a summary (selected elements) do not count a compile unit.
+ if (!(getIsRoot() || (getIsCompileUnit() && options().getSelectExecute())))
getReaderCompileUnit()->incrementPrintedScopes();
LVElement::print(OS, Full);
printExtra(OS, Full);
CUContributionSize = Size;
}
+// Update parents and children with pattern information.
+void LVScopeCompileUnit::propagatePatternMatch() {
+ // At this stage, we have finished creating the Scopes tree and we have
+ // a list of elements that match the pattern specified in the command line.
+ // The pattern corresponds to a scope or element; mark parents and/or
+ // children as having that pattern, before any printing is done.
+ if (!options().getSelectExecute())
+ return;
+
+ if (MatchedScopes.size()) {
+ for (LVScope *Scope : MatchedScopes)
+ Scope->traverseParentsAndChildren(&LVScope::getHasPattern,
+ &LVScope::setHasPattern);
+ } else {
+ // Mark the compile unit as having a pattern to enable any requests to
+ // print sizes and summary as that information is recorded at that level.
+ setHasPattern();
+ }
+}
+
void LVScopeCompileUnit::processRangeLocationCoverage(
LVValidLocation ValidLocation) {
-
if (options().getAttributeRange()) {
// Traverse the scopes to get scopes that have invalid ranges.
LVLocations Locations;
return getStringPool().getString(Filenames[Index - 1]);
}
-void LVScopeCompileUnit::incrementPrintedLines() { ++Printed.Lines; }
-void LVScopeCompileUnit::incrementPrintedScopes() { ++Printed.Scopes; }
-void LVScopeCompileUnit::incrementPrintedSymbols() { ++Printed.Symbols; }
-void LVScopeCompileUnit::incrementPrintedTypes() { ++Printed.Types; }
+void LVScopeCompileUnit::incrementPrintedLines() {
+ options().getSelectExecute() ? ++Found.Lines : ++Printed.Lines;
+}
+void LVScopeCompileUnit::incrementPrintedScopes() {
+ options().getSelectExecute() ? ++Found.Scopes : ++Printed.Scopes;
+}
+void LVScopeCompileUnit::incrementPrintedSymbols() {
+ options().getSelectExecute() ? ++Found.Symbols : ++Printed.Symbols;
+}
+void LVScopeCompileUnit::incrementPrintedTypes() {
+ options().getSelectExecute() ? ++Found.Types : ++Printed.Types;
+}
// Values are used by '--summary' option (allocated).
void LVScopeCompileUnit::increment(LVLine *Line) {
// Recursively print the contributions for each scope.
std::function<void(const LVScope *Scope)> PrintScope =
[&](const LVScope *Scope) {
+ // If we have selection criteria, then use only the selected scopes.
+ if (options().getSelectExecute() && options().getReportAnyView()) {
+ for (const LVScope *Scope : MatchedScopes)
+ if (Scope->getLevel() < options().getOutputLevel())
+ printScopeSize(Scope, OS);
+ return;
+ }
if (Scope->getLevel() < options().getOutputLevel()) {
if (const LVScopes *Scopes = Scope->getScopes())
for (const LVScope *Scope : *Scopes) {
}
void LVScopeCompileUnit::printSummary(raw_ostream &OS) const {
- printSummary(OS, Printed, "Printed");
+ printSummary(OS, options().getSelectExecute() ? Found : Printed, "Printed");
}
// Print summary details for the scopes tree.
return Kind;
}
+LVSymbolDispatch LVSymbol::Dispatch = {
+ {LVSymbolKind::IsCallSiteParameter, &LVSymbol::getIsCallSiteParameter},
+ {LVSymbolKind::IsConstant, &LVSymbol::getIsConstant},
+ {LVSymbolKind::IsInheritance, &LVSymbol::getIsInheritance},
+ {LVSymbolKind::IsMember, &LVSymbol::getIsMember},
+ {LVSymbolKind::IsParameter, &LVSymbol::getIsParameter},
+ {LVSymbolKind::IsUnspecified, &LVSymbol::getIsUnspecified},
+ {LVSymbolKind::IsVariable, &LVSymbol::getIsVariable}};
+
// Add a Location Entry.
void LVSymbol::addLocation(dwarf::Attribute Attr, LVAddress LowPC,
LVAddress HighPC, LVUnsigned SectionOffset,
setIsResolvedName();
LVElement::resolveName();
+
+ // Resolve any given pattern.
+ patterns().resolvePatternMatch(this);
}
void LVSymbol::resolveReferences() {
return Kind;
}
+LVTypeDispatch LVType::Dispatch = {
+ {LVTypeKind::IsBase, &LVType::getIsBase},
+ {LVTypeKind::IsConst, &LVType::getIsConst},
+ {LVTypeKind::IsEnumerator, &LVType::getIsEnumerator},
+ {LVTypeKind::IsImport, &LVType::getIsImport},
+ {LVTypeKind::IsImportDeclaration, &LVType::getIsImportDeclaration},
+ {LVTypeKind::IsImportModule, &LVType::getIsImportModule},
+ {LVTypeKind::IsPointer, &LVType::getIsPointer},
+ {LVTypeKind::IsPointerMember, &LVType::getIsPointerMember},
+ {LVTypeKind::IsReference, &LVType::getIsReference},
+ {LVTypeKind::IsRestrict, &LVType::getIsRestrict},
+ {LVTypeKind::IsRvalueReference, &LVType::getIsRvalueReference},
+ {LVTypeKind::IsSubrange, &LVType::getIsSubrange},
+ {LVTypeKind::IsTemplateParam, &LVType::getIsTemplateParam},
+ {LVTypeKind::IsTemplateTemplateParam, &LVType::getIsTemplateTemplateParam},
+ {LVTypeKind::IsTemplateTypeParam, &LVType::getIsTemplateTypeParam},
+ {LVTypeKind::IsTemplateValueParam, &LVType::getIsTemplateValueParam},
+ {LVTypeKind::IsTypedef, &LVType::getIsTypedef},
+ {LVTypeKind::IsUnaligned, &LVType::getIsUnaligned},
+ {LVTypeKind::IsUnspecified, &LVType::getIsUnspecified},
+ {LVTypeKind::IsVolatile, &LVType::getIsVolatile}};
+
void LVType::resolveReferences() {
// Some DWARF tags are the representation of types. However, we associate
// some of them to scopes. The ones associated with types, do not have
generateName();
LVElement::resolveName();
+
+ // Resolve any given pattern.
+ patterns().resolvePatternMatch(this);
}
StringRef LVType::resolveReferencesChain() {
add_llvm_unittest(DebugInfoLogicalViewTests
CommandLineOptionsTest.cpp
+ SelectElementsTest.cpp
LocationRangesTest.cpp
LogicalElementsTest.cpp
StringPoolTest.cpp
--- /dev/null
+//===- llvm/unittest/DebugInfo/LogicalView/SelectElementsTest.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 ReaderTestSelection : public LVReader {
+ // Types.
+ LVType *IntegerType = nullptr;
+
+ // Scopes.
+ LVScope *NestedScope = nullptr;
+ LVScopeAggregate *Aggregate = nullptr;
+ LVScopeFunction *Function = nullptr;
+ LVScopeNamespace *Namespace = nullptr;
+
+ // Symbols.
+ LVSymbol *ClassMember = nullptr;
+ 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;
+
+protected:
+ void add(LVScope *Parent, LVElement *Element);
+ template <typename T, typename F> T *create(F Function) {
+ // 'Function' will update a specific kind of the logical element to
+ // have the ability of kind selection.
+ T *Element = new (std::nothrow) T();
+ EXPECT_NE(Element, nullptr);
+ (Element->*Function)();
+ return Element;
+ }
+ void set(LVElement *Element, StringRef Name, LVOffset Offset,
+ uint32_t LineNumber = 0, LVElement *Type = nullptr);
+
+public:
+ ReaderTestSelection(ScopedPrinter &W) : LVReader("", "", W) {
+ setInstance(this);
+ }
+
+ Error createScopes() { return LVReader::createScopes(); }
+
+ void createElements();
+ void addElements();
+ void initElements();
+ void resolvePatterns(LVPatterns &Patterns);
+ void checkFlexiblePatterns();
+ void checkGenericPatterns();
+ void checkKindPatterns();
+};
+
+// Helper function to add a logical element to a given scope.
+void ReaderTestSelection::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 ReaderTestSelection::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);
+}
+
+// Create the logical elements.
+void ReaderTestSelection::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, LVTypeSetFunction>(&LVType::setIsBase);
+
+ // Create the logical scopes.
+ CompileUnit = create<LVScopeCompileUnit, LVScopeSetFunction>(
+ &LVScope::setIsCompileUnit);
+ Function =
+ create<LVScopeFunction, LVScopeSetFunction>(&LVScope::setIsFunction);
+ NestedScope =
+ create<LVScope, LVScopeSetFunction>(&LVScope::setIsLexicalBlock);
+ Namespace =
+ create<LVScopeNamespace, LVScopeSetFunction>(&LVScope::setIsNamespace);
+ Aggregate =
+ create<LVScopeAggregate, LVScopeSetFunction>(&LVScope::setIsAggregate);
+
+ // Create the logical symbols.
+ ClassMember = create<LVSymbol, LVSymbolSetFunction>(&LVSymbol::setIsMember);
+ LocalVariable =
+ create<LVSymbol, LVSymbolSetFunction>(&LVSymbol::setIsVariable);
+ NestedVariable =
+ create<LVSymbol, LVSymbolSetFunction>(&LVSymbol::setIsVariable);
+ Parameter = create<LVSymbol, LVSymbolSetFunction>(&LVSymbol::setIsParameter);
+
+ // Create the logical lines.
+ LineOne = create<LVLine, LVLineSetFunction>(&LVLine::setIsLineDebug);
+ LineTwo = create<LVLine, LVLineSetFunction>(&LVLine::setIsBasicBlock);
+ LineThree = create<LVLine, LVLineSetFunction>(&LVLine::setIsNewStatement);
+ LineFour = create<LVLine, LVLineSetFunction>(&LVLine::setIsPrologueEnd);
+ LineFive = create<LVLine, LVLineSetFunction>(&LVLine::setIsLineAssembler);
+}
+
+// Create the logical view adding the created logical elements.
+void ReaderTestSelection::addElements() {
+ setCompileUnit(CompileUnit);
+
+ // Root
+ // CompileUnit
+ // IntegerType
+ // Namespace
+ // Aggregate
+ // ClassMember
+ // Function
+ // Parameter
+ // LocalVariable
+ // LineOne
+ // LineTwo
+ // NestedScope
+ // NestedVariable
+ // LineThree
+ // LineFour
+ // LineFive
+
+ // Add elements to Root.
+ add(Root, CompileUnit);
+
+ // Add elements to CompileUnit.
+ add(CompileUnit, IntegerType);
+ add(CompileUnit, Namespace);
+ add(CompileUnit, Function);
+
+ // Add elements to Namespace.
+ add(Namespace, Aggregate);
+
+ // Add elements to Function.
+ add(Function, Parameter);
+ add(Function, LocalVariable);
+ add(Function, LineOne);
+ add(Function, LineTwo);
+ add(Function, LineFive);
+ add(Function, NestedScope);
+
+ // Add elements to Aggregate.
+ add(Aggregate, ClassMember);
+
+ // Add elements to NestedScope.
+ add(NestedScope, NestedVariable);
+ add(NestedScope, LineThree);
+ add(NestedScope, LineFour);
+}
+
+void ReaderTestSelection::resolvePatterns(LVPatterns &Patterns) {
+ // Traverse the given scope and its children applying the pattern match.
+ // Before applying the pattern, reset previous matched state.
+ std::function<void(LVScope * Parent)> TraverseScope = [&](LVScope *Parent) {
+ auto Traverse = [&](const auto *Set) {
+ if (Set)
+ for (const auto &Entry : *Set) {
+ Entry->resetIsMatched();
+ Patterns.resolvePatternMatch(Entry);
+ }
+ };
+
+ Parent->resetIsMatched();
+ Patterns.resolvePatternMatch(Parent);
+
+ Traverse(Parent->getSymbols());
+ Traverse(Parent->getTypes());
+ Traverse(Parent->getLines());
+
+ if (const LVScopes *Scopes = Parent->getScopes())
+ for (LVScope *Scope : *Scopes) {
+ Scope->resetIsMatched();
+ Patterns.resolvePatternMatch(Scope);
+ TraverseScope(Scope);
+ }
+ };
+
+ // Start traversing the scopes root and apply any matching pattern.
+ TraverseScope(Root);
+}
+
+// Set initial values to logical elements.
+void ReaderTestSelection::initElements() {
+ // Types.
+ set(IntegerType, "int", 0x1000);
+
+ // Scopes.
+ set(CompileUnit, "test.cpp", 0x2000);
+ set(Namespace, "anyNamespace", 0x3000, 300);
+ set(Aggregate, "anyClass", 0x4000, 400);
+ set(Function, "anyFunction", 0x5000, 500, IntegerType);
+ set(NestedScope, "", 0x6000, 600);
+
+ // Symbols.
+ set(Parameter, "Param", 0x5100, 510, IntegerType);
+ set(LocalVariable, "LocalVariable", 0x5200, 520, IntegerType);
+ set(NestedVariable, "NestedVariable", 0x6200, 620, IntegerType);
+
+ // Lines.
+ set(LineOne, "", 0x5110, 511);
+ set(LineTwo, "", 0x5210, 521);
+ set(LineThree, "", 0x6110, 611);
+ set(LineFour, "", 0x6210, 621);
+ set(LineFive, "", 0x7110, 711);
+}
+
+// Check logical elements kind patterns.
+void ReaderTestSelection::checkKindPatterns() {
+ // Add patterns.
+ LVPatterns &Patterns = patterns();
+ Patterns.clear();
+
+ LVElementKindSet KindElements; // --select-elements=<Kind>
+ LVLineKindSet KindLines; // --select-lines=<Kind>
+ LVScopeKindSet KindScopes; // --select-scopes=<Kind>
+ LVSymbolKindSet KindSymbols; // --select-symbols=<Kind>
+ LVTypeKindSelection KindTypes; // --select-types=<Kind>
+
+ KindElements.insert(LVElementKind::Global);
+ KindLines.insert(LVLineKind::IsLineDebug);
+ KindLines.insert(LVLineKind::IsNewStatement);
+ KindLines.insert(LVLineKind::IsLineAssembler);
+ KindScopes.insert(LVScopeKind::IsLexicalBlock);
+ KindSymbols.insert(LVSymbolKind::IsMember);
+ KindSymbols.insert(LVSymbolKind::IsParameter);
+ KindTypes.insert(LVTypeKind::IsBase);
+
+ // Add requests based on the element kind.
+ Patterns.addRequest(KindElements);
+ Patterns.addRequest(KindLines);
+ Patterns.addRequest(KindScopes);
+ Patterns.addRequest(KindSymbols);
+ Patterns.addRequest(KindTypes);
+
+ // Apply the collected patterns.
+ resolvePatterns(Patterns);
+
+ EXPECT_FALSE(CompileUnit->getIsMatched());
+ EXPECT_FALSE(Namespace->getIsMatched());
+ EXPECT_FALSE(Aggregate->getIsMatched());
+ EXPECT_FALSE(Function->getIsMatched());
+ EXPECT_TRUE(NestedScope->getIsMatched());
+
+ EXPECT_TRUE(IntegerType->getIsMatched());
+
+ EXPECT_TRUE(ClassMember->getIsMatched());
+ EXPECT_TRUE(Parameter->getIsMatched());
+ EXPECT_FALSE(LocalVariable->getIsMatched());
+ EXPECT_FALSE(NestedVariable->getIsMatched());
+
+ EXPECT_TRUE(LineOne->getIsMatched());
+ EXPECT_FALSE(LineTwo->getIsMatched());
+ EXPECT_TRUE(LineThree->getIsMatched());
+ EXPECT_FALSE(LineFour->getIsMatched());
+ EXPECT_TRUE(LineFive->getIsMatched());
+}
+
+// Check logical elements generic patterns (Case sensitive).
+void ReaderTestSelection::checkGenericPatterns() {
+ // Add patterns.
+ LVPatterns &Patterns = patterns();
+ Patterns.clear();
+
+ StringSet<> Generic; // --select=<Pattern>
+ Generic.insert(Function->getName()); // anyFunction
+ Generic.insert(Namespace->getName()); // anyNamespace
+ Generic.insert(LocalVariable->getName()); // LocalVariable
+
+ LVOffsetSet Offsets; // --select-offset=<Offset>
+ Offsets.insert(IntegerType->getOffset());
+ Offsets.insert(LineOne->getOffset());
+ Offsets.insert(LineTwo->getOffset());
+
+ // Add requests based on the generic string and offset.
+ Patterns.addGenericPatterns(Generic);
+ Patterns.addOffsetPatterns(Offsets);
+
+ // Apply the collected patterns.
+ resolvePatterns(Patterns);
+
+ EXPECT_FALSE(CompileUnit->getIsMatched());
+ EXPECT_TRUE(Namespace->getIsMatched());
+ EXPECT_FALSE(Aggregate->getIsMatched());
+ EXPECT_TRUE(Function->getIsMatched());
+ EXPECT_FALSE(NestedScope->getIsMatched());
+
+ EXPECT_TRUE(IntegerType->getIsMatched());
+
+ EXPECT_FALSE(ClassMember->getIsMatched());
+ EXPECT_FALSE(Parameter->getIsMatched());
+ EXPECT_TRUE(LocalVariable->getIsMatched());
+ EXPECT_FALSE(NestedVariable->getIsMatched());
+
+ EXPECT_TRUE(LineOne->getIsMatched());
+ EXPECT_TRUE(LineTwo->getIsMatched());
+ EXPECT_FALSE(LineThree->getIsMatched());
+ EXPECT_FALSE(LineFour->getIsMatched());
+ EXPECT_FALSE(LineFive->getIsMatched());
+}
+
+// Check logical elements flexible patterns (case insensitive, RegEx).
+void ReaderTestSelection::checkFlexiblePatterns() {
+ options().setSelectIgnoreCase();
+ options().setSelectUseRegex();
+
+ // Add patterns.
+ LVPatterns &Patterns = patterns();
+ Patterns.clear();
+
+ StringSet<> Generic; // --select=<Pattern>
+ Generic.insert("function");
+ Generic.insert("NaMeSpAcE");
+ Generic.insert("[a-z]*Variable");
+ Generic.insert("[0-9]21");
+
+ // Add requests based on the flexible string.
+ Patterns.addGenericPatterns(Generic);
+
+ // Apply the collected patterns.
+ resolvePatterns(Patterns);
+
+ EXPECT_FALSE(CompileUnit->getIsMatched());
+ EXPECT_TRUE(Namespace->getIsMatched()); // anyNamespace
+ EXPECT_FALSE(Aggregate->getIsMatched());
+ EXPECT_TRUE(Function->getIsMatched()); // anyFunction
+ EXPECT_FALSE(NestedScope->getIsMatched());
+
+ EXPECT_FALSE(IntegerType->getIsMatched());
+
+ EXPECT_FALSE(ClassMember->getIsMatched());
+ EXPECT_FALSE(Parameter->getIsMatched());
+ EXPECT_TRUE(LocalVariable->getIsMatched()); // LocalVariable
+ EXPECT_TRUE(NestedVariable->getIsMatched()); // NestedVariable
+
+ EXPECT_FALSE(LineOne->getIsMatched());
+ EXPECT_TRUE(LineTwo->getIsMatched()); // 521
+ EXPECT_FALSE(LineThree->getIsMatched());
+ EXPECT_TRUE(LineFour->getIsMatched()); // 621
+ EXPECT_FALSE(LineFive->getIsMatched());
+}
+
+TEST(LogicalViewTest, SelectElements) {
+ ScopedPrinter W(outs());
+ ReaderTestSelection Reader(W);
+
+ // Reader options.
+ LVOptions ReaderOptions;
+ ReaderOptions.setAttributeOffset();
+ ReaderOptions.setPrintAll();
+ ReaderOptions.setReportList();
+ ReaderOptions.setReportAnyView();
+
+ ReaderOptions.resolveDependencies();
+ options().setOptions(&ReaderOptions);
+
+ Reader.createElements();
+ Reader.addElements();
+ Reader.initElements();
+ Reader.checkKindPatterns();
+ Reader.checkGenericPatterns();
+ Reader.checkFlexiblePatterns();
+}
+
+} // namespace