1 //===-- TypeMap.cpp --------------------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 // C Includes 11 // C++ Includes 12 #include <vector> 13 14 // Other libraries and framework includes 15 #include "clang/AST/ASTConsumer.h" 16 #include "clang/AST/ASTContext.h" 17 #include "clang/AST/Decl.h" 18 #include "clang/AST/DeclCXX.h" 19 #include "clang/AST/DeclGroup.h" 20 21 #include "clang/Basic/Builtins.h" 22 #include "clang/Basic/IdentifierTable.h" 23 #include "clang/Basic/LangOptions.h" 24 #include "clang/Basic/SourceManager.h" 25 #include "clang/Basic/TargetInfo.h" 26 27 #include "llvm/Support/FormattedStream.h" 28 #include "llvm/Support/raw_ostream.h" 29 30 // Project includes 31 #include "lldb/Symbol/SymbolFile.h" 32 #include "lldb/Symbol/SymbolVendor.h" 33 #include "lldb/Symbol/Type.h" 34 #include "lldb/Symbol/TypeMap.h" 35 36 using namespace lldb; 37 using namespace lldb_private; 38 using namespace clang; 39 40 TypeMap::TypeMap() : m_types() {} 41 42 //---------------------------------------------------------------------- 43 // Destructor 44 //---------------------------------------------------------------------- 45 TypeMap::~TypeMap() {} 46 47 void TypeMap::Insert(const TypeSP &type_sp) { 48 // Just push each type on the back for now. We will worry about uniquing later 49 if (type_sp) 50 m_types.insert(std::make_pair(type_sp->GetID(), type_sp)); 51 } 52 53 bool TypeMap::InsertUnique(const TypeSP &type_sp) { 54 if (type_sp) { 55 user_id_t type_uid = type_sp->GetID(); 56 iterator pos, end = m_types.end(); 57 58 for (pos = m_types.find(type_uid); 59 pos != end && pos->second->GetID() == type_uid; ++pos) { 60 if (pos->second.get() == type_sp.get()) 61 return false; 62 } 63 Insert(type_sp); 64 } 65 return true; 66 } 67 68 //---------------------------------------------------------------------- 69 // Find a base type by its unique ID. 70 //---------------------------------------------------------------------- 71 // TypeSP 72 // TypeMap::FindType(lldb::user_id_t uid) 73 //{ 74 // iterator pos = m_types.find(uid); 75 // if (pos != m_types.end()) 76 // return pos->second; 77 // return TypeSP(); 78 //} 79 80 //---------------------------------------------------------------------- 81 // Find a type by name. 82 //---------------------------------------------------------------------- 83 // TypeMap 84 // TypeMap::FindTypes (const ConstString &name) 85 //{ 86 // // Do we ever need to make a lookup by name map? Here we are doing 87 // // a linear search which isn't going to be fast. 88 // TypeMap types(m_ast.getTargetInfo()->getTriple().getTriple().c_str()); 89 // iterator pos, end; 90 // for (pos = m_types.begin(), end = m_types.end(); pos != end; ++pos) 91 // if (pos->second->GetName() == name) 92 // types.Insert (pos->second); 93 // return types; 94 //} 95 96 void TypeMap::Clear() { m_types.clear(); } 97 98 uint32_t TypeMap::GetSize() const { return m_types.size(); } 99 100 bool TypeMap::Empty() const { return m_types.empty(); } 101 102 // GetTypeAtIndex isn't used a lot for large type lists, currently only for 103 // type lists that are returned for "image dump -t TYPENAME" commands and other 104 // simple symbol queries that grab the first result... 105 106 TypeSP TypeMap::GetTypeAtIndex(uint32_t idx) { 107 iterator pos, end; 108 uint32_t i = idx; 109 for (pos = m_types.begin(), end = m_types.end(); pos != end; ++pos) { 110 if (i == 0) 111 return pos->second; 112 --i; 113 } 114 return TypeSP(); 115 } 116 117 void TypeMap::ForEach( 118 std::function<bool(const lldb::TypeSP &type_sp)> const &callback) const { 119 for (auto pos = m_types.begin(), end = m_types.end(); pos != end; ++pos) { 120 if (!callback(pos->second)) 121 break; 122 } 123 } 124 125 void TypeMap::ForEach( 126 std::function<bool(lldb::TypeSP &type_sp)> const &callback) { 127 for (auto pos = m_types.begin(), end = m_types.end(); pos != end; ++pos) { 128 if (!callback(pos->second)) 129 break; 130 } 131 } 132 133 bool TypeMap::Remove(const lldb::TypeSP &type_sp) { 134 if (type_sp) { 135 lldb::user_id_t uid = type_sp->GetID(); 136 for (iterator pos = m_types.find(uid), end = m_types.end(); 137 pos != end && pos->first == uid; ++pos) { 138 if (pos->second == type_sp) { 139 m_types.erase(pos); 140 return true; 141 } 142 } 143 } 144 return false; 145 } 146 147 void TypeMap::Dump(Stream *s, bool show_context) { 148 for (iterator pos = m_types.begin(), end = m_types.end(); pos != end; ++pos) { 149 pos->second->Dump(s, show_context); 150 } 151 } 152 153 void TypeMap::RemoveMismatchedTypes(const char *qualified_typename, 154 bool exact_match) { 155 std::string type_scope; 156 std::string type_basename; 157 TypeClass type_class = eTypeClassAny; 158 if (!Type::GetTypeScopeAndBasename(qualified_typename, type_scope, 159 type_basename, type_class)) { 160 type_basename = qualified_typename; 161 type_scope.clear(); 162 } 163 return RemoveMismatchedTypes(type_scope, type_basename, type_class, 164 exact_match); 165 } 166 167 void TypeMap::RemoveMismatchedTypes(const std::string &type_scope, 168 const std::string &type_basename, 169 TypeClass type_class, bool exact_match) { 170 // Our "collection" type currently is a std::map which doesn't 171 // have any good way to iterate and remove items from the map 172 // so we currently just make a new list and add all of the matching 173 // types to it, and then swap it into m_types at the end 174 collection matching_types; 175 176 iterator pos, end = m_types.end(); 177 178 for (pos = m_types.begin(); pos != end; ++pos) { 179 Type *the_type = pos->second.get(); 180 bool keep_match = false; 181 TypeClass match_type_class = eTypeClassAny; 182 183 if (type_class != eTypeClassAny) { 184 match_type_class = the_type->GetForwardCompilerType().GetTypeClass(); 185 if ((match_type_class & type_class) == 0) 186 continue; 187 } 188 189 ConstString match_type_name_const_str(the_type->GetQualifiedName()); 190 if (match_type_name_const_str) { 191 const char *match_type_name = match_type_name_const_str.GetCString(); 192 std::string match_type_scope; 193 std::string match_type_basename; 194 if (Type::GetTypeScopeAndBasename(match_type_name, match_type_scope, 195 match_type_basename, 196 match_type_class)) { 197 if (match_type_basename == type_basename) { 198 const size_t type_scope_size = type_scope.size(); 199 const size_t match_type_scope_size = match_type_scope.size(); 200 if (exact_match || (type_scope_size == match_type_scope_size)) { 201 keep_match = match_type_scope == type_scope; 202 } else { 203 if (match_type_scope_size > type_scope_size) { 204 const size_t type_scope_pos = match_type_scope.rfind(type_scope); 205 if (type_scope_pos == match_type_scope_size - type_scope_size) { 206 if (type_scope_pos >= 2) { 207 // Our match scope ends with the type scope we were looking 208 // for, 209 // but we need to make sure what comes before the matching 210 // type scope is a namespace boundary in case we are trying to 211 // match: 212 // type_basename = "d" 213 // type_scope = "b::c::" 214 // We want to match: 215 // match_type_scope "a::b::c::" 216 // But not: 217 // match_type_scope "a::bb::c::" 218 // So below we make sure what comes before "b::c::" in 219 // match_type_scope 220 // is "::", or the namespace boundary 221 if (match_type_scope[type_scope_pos - 1] == ':' && 222 match_type_scope[type_scope_pos - 2] == ':') { 223 keep_match = true; 224 } 225 } 226 } 227 } 228 } 229 } 230 } else { 231 // The type we are currently looking at doesn't exists 232 // in a namespace or class, so it only matches if there 233 // is no type scope... 234 keep_match = 235 type_scope.empty() && type_basename.compare(match_type_name) == 0; 236 } 237 } 238 239 if (keep_match) { 240 matching_types.insert(*pos); 241 } 242 } 243 m_types.swap(matching_types); 244 } 245 246 void TypeMap::RemoveMismatchedTypes(TypeClass type_class) { 247 if (type_class == eTypeClassAny) 248 return; 249 250 // Our "collection" type currently is a std::map which doesn't 251 // have any good way to iterate and remove items from the map 252 // so we currently just make a new list and add all of the matching 253 // types to it, and then swap it into m_types at the end 254 collection matching_types; 255 256 iterator pos, end = m_types.end(); 257 258 for (pos = m_types.begin(); pos != end; ++pos) { 259 Type *the_type = pos->second.get(); 260 TypeClass match_type_class = 261 the_type->GetForwardCompilerType().GetTypeClass(); 262 if (match_type_class & type_class) 263 matching_types.insert(*pos); 264 } 265 m_types.swap(matching_types); 266 } 267