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