1254721Semaste//===-- TypeList.cpp --------------------------------------------*- C++ -*-===// 2254721Semaste// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6254721Semaste// 7254721Semaste//===----------------------------------------------------------------------===// 8254721Semaste 9254721Semaste#include <vector> 10254721Semaste 11254721Semaste#include "llvm/Support/FormattedStream.h" 12254721Semaste#include "llvm/Support/raw_ostream.h" 13254721Semaste 14254721Semaste#include "lldb/Symbol/SymbolFile.h" 15254721Semaste#include "lldb/Symbol/SymbolVendor.h" 16254721Semaste#include "lldb/Symbol/Type.h" 17254721Semaste#include "lldb/Symbol/TypeList.h" 18254721Semaste 19254721Semasteusing namespace lldb; 20254721Semasteusing namespace lldb_private; 21254721Semaste 22314564SdimTypeList::TypeList() : m_types() {} 23254721Semaste 24254721Semaste// Destructor 25314564SdimTypeList::~TypeList() {} 26254721Semaste 27314564Sdimvoid TypeList::Insert(const TypeSP &type_sp) { 28341825Sdim // Just push each type on the back for now. We will worry about uniquing 29341825Sdim // later 30314564Sdim if (type_sp) 31314564Sdim m_types.push_back(type_sp); 32254721Semaste} 33254721Semaste 34254721Semaste// Find a base type by its unique ID. 35314564Sdim// TypeSP 36314564Sdim// TypeList::FindType(lldb::user_id_t uid) 37254721Semaste//{ 38254721Semaste// iterator pos = m_types.find(uid); 39254721Semaste// if (pos != m_types.end()) 40254721Semaste// return pos->second; 41254721Semaste// return TypeSP(); 42254721Semaste//} 43254721Semaste 44254721Semaste// Find a type by name. 45314564Sdim// TypeList 46353358Sdim// TypeList::FindTypes (ConstString name) 47254721Semaste//{ 48254721Semaste// // Do we ever need to make a lookup by name map? Here we are doing 49254721Semaste// // a linear search which isn't going to be fast. 50254721Semaste// TypeList types(m_ast.getTargetInfo()->getTriple().getTriple().c_str()); 51254721Semaste// iterator pos, end; 52254721Semaste// for (pos = m_types.begin(), end = m_types.end(); pos != end; ++pos) 53254721Semaste// if (pos->second->GetName() == name) 54254721Semaste// types.Insert (pos->second); 55254721Semaste// return types; 56254721Semaste//} 57254721Semaste 58314564Sdimvoid TypeList::Clear() { m_types.clear(); } 59254721Semaste 60314564Sdimuint32_t TypeList::GetSize() const { return m_types.size(); } 61254721Semaste 62254721Semaste// GetTypeAtIndex isn't used a lot for large type lists, currently only for 63254721Semaste// type lists that are returned for "image dump -t TYPENAME" commands and other 64254721Semaste// simple symbol queries that grab the first result... 65254721Semaste 66314564SdimTypeSP TypeList::GetTypeAtIndex(uint32_t idx) { 67314564Sdim iterator pos, end; 68314564Sdim uint32_t i = idx; 69341825Sdim assert(i < GetSize() && "Accessing past the end of a TypeList"); 70314564Sdim for (pos = m_types.begin(), end = m_types.end(); pos != end; ++pos) { 71314564Sdim if (i == 0) 72314564Sdim return *pos; 73314564Sdim --i; 74314564Sdim } 75314564Sdim return TypeSP(); 76254721Semaste} 77254721Semaste 78314564Sdimvoid TypeList::ForEach( 79314564Sdim std::function<bool(const lldb::TypeSP &type_sp)> const &callback) const { 80314564Sdim for (auto pos = m_types.begin(), end = m_types.end(); pos != end; ++pos) { 81314564Sdim if (!callback(*pos)) 82314564Sdim break; 83314564Sdim } 84254721Semaste} 85254721Semaste 86314564Sdimvoid TypeList::ForEach( 87314564Sdim std::function<bool(lldb::TypeSP &type_sp)> const &callback) { 88314564Sdim for (auto pos = m_types.begin(), end = m_types.end(); pos != end; ++pos) { 89314564Sdim if (!callback(*pos)) 90314564Sdim break; 91314564Sdim } 92254721Semaste} 93254721Semaste 94314564Sdimvoid TypeList::Dump(Stream *s, bool show_context) { 95314564Sdim for (iterator pos = m_types.begin(), end = m_types.end(); pos != end; ++pos) { 96314564Sdim pos->get()->Dump(s, show_context); 97314564Sdim } 98254721Semaste} 99254721Semaste 100314564Sdimvoid TypeList::RemoveMismatchedTypes(const char *qualified_typename, 101314564Sdim bool exact_match) { 102314564Sdim llvm::StringRef type_scope; 103314564Sdim llvm::StringRef type_basename; 104314564Sdim TypeClass type_class = eTypeClassAny; 105314564Sdim if (!Type::GetTypeScopeAndBasename(qualified_typename, type_scope, 106314564Sdim type_basename, type_class)) { 107314564Sdim type_basename = qualified_typename; 108314564Sdim type_scope = ""; 109314564Sdim } 110314564Sdim return RemoveMismatchedTypes(type_scope, type_basename, type_class, 111314564Sdim exact_match); 112254721Semaste} 113254721Semaste 114314564Sdimvoid TypeList::RemoveMismatchedTypes(const std::string &type_scope, 115314564Sdim const std::string &type_basename, 116314564Sdim TypeClass type_class, bool exact_match) { 117341825Sdim // Our "collection" type currently is a std::map which doesn't have any good 118341825Sdim // way to iterate and remove items from the map so we currently just make a 119341825Sdim // new list and add all of the matching types to it, and then swap it into 120341825Sdim // m_types at the end 121314564Sdim collection matching_types; 122254721Semaste 123314564Sdim iterator pos, end = m_types.end(); 124254721Semaste 125314564Sdim for (pos = m_types.begin(); pos != end; ++pos) { 126314564Sdim Type *the_type = pos->get(); 127314564Sdim bool keep_match = false; 128314564Sdim TypeClass match_type_class = eTypeClassAny; 129254721Semaste 130314564Sdim if (type_class != eTypeClassAny) { 131314564Sdim match_type_class = the_type->GetForwardCompilerType().GetTypeClass(); 132314564Sdim if ((match_type_class & type_class) == 0) 133314564Sdim continue; 134314564Sdim } 135314564Sdim 136314564Sdim ConstString match_type_name_const_str(the_type->GetQualifiedName()); 137314564Sdim if (match_type_name_const_str) { 138314564Sdim const char *match_type_name = match_type_name_const_str.GetCString(); 139314564Sdim llvm::StringRef match_type_scope; 140314564Sdim llvm::StringRef match_type_basename; 141314564Sdim if (Type::GetTypeScopeAndBasename(match_type_name, match_type_scope, 142314564Sdim match_type_basename, 143314564Sdim match_type_class)) { 144314564Sdim if (match_type_basename == type_basename) { 145314564Sdim const size_t type_scope_size = type_scope.size(); 146314564Sdim const size_t match_type_scope_size = match_type_scope.size(); 147314564Sdim if (exact_match || (type_scope_size == match_type_scope_size)) { 148314564Sdim keep_match = match_type_scope == type_scope; 149314564Sdim } else { 150314564Sdim if (match_type_scope_size > type_scope_size) { 151314564Sdim const size_t type_scope_pos = match_type_scope.rfind(type_scope); 152314564Sdim if (type_scope_pos == match_type_scope_size - type_scope_size) { 153314564Sdim if (type_scope_pos >= 2) { 154314564Sdim // Our match scope ends with the type scope we were looking 155341825Sdim // for, but we need to make sure what comes before the 156341825Sdim // matching type scope is a namespace boundary in case we are 157341825Sdim // trying to match: type_basename = "d" type_scope = "b::c::" 158314564Sdim // We want to match: 159314564Sdim // match_type_scope "a::b::c::" 160314564Sdim // But not: 161314564Sdim // match_type_scope "a::bb::c::" 162314564Sdim // So below we make sure what comes before "b::c::" in 163341825Sdim // match_type_scope is "::", or the namespace boundary 164314564Sdim if (match_type_scope[type_scope_pos - 1] == ':' && 165314564Sdim match_type_scope[type_scope_pos - 2] == ':') { 166314564Sdim keep_match = true; 167314564Sdim } 168254721Semaste } 169314564Sdim } 170254721Semaste } 171314564Sdim } 172254721Semaste } 173314564Sdim } else { 174341825Sdim // The type we are currently looking at doesn't exists in a namespace 175341825Sdim // or class, so it only matches if there is no type scope... 176344779Sdim keep_match = type_scope.empty() && type_basename == match_type_name; 177314564Sdim } 178254721Semaste } 179314564Sdim 180314564Sdim if (keep_match) { 181314564Sdim matching_types.push_back(*pos); 182314564Sdim } 183314564Sdim } 184314564Sdim m_types.swap(matching_types); 185254721Semaste} 186254721Semaste 187314564Sdimvoid TypeList::RemoveMismatchedTypes(TypeClass type_class) { 188314564Sdim if (type_class == eTypeClassAny) 189314564Sdim return; 190254721Semaste 191341825Sdim // Our "collection" type currently is a std::map which doesn't have any good 192341825Sdim // way to iterate and remove items from the map so we currently just make a 193341825Sdim // new list and add all of the matching types to it, and then swap it into 194341825Sdim // m_types at the end 195314564Sdim collection matching_types; 196314564Sdim 197314564Sdim iterator pos, end = m_types.end(); 198314564Sdim 199314564Sdim for (pos = m_types.begin(); pos != end; ++pos) { 200314564Sdim Type *the_type = pos->get(); 201314564Sdim TypeClass match_type_class = 202314564Sdim the_type->GetForwardCompilerType().GetTypeClass(); 203314564Sdim if (match_type_class & type_class) 204314564Sdim matching_types.push_back(*pos); 205314564Sdim } 206314564Sdim m_types.swap(matching_types); 207254721Semaste} 208