TypeList.cpp revision a8b56238ce138e70433a0ce0b4218c9257beae38
1//===-- TypeList.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/TypeList.h" 36 37using namespace lldb; 38using namespace lldb_private; 39using namespace clang; 40 41TypeList::TypeList() : 42 m_types () 43{ 44} 45 46//---------------------------------------------------------------------- 47// Destructor 48//---------------------------------------------------------------------- 49TypeList::~TypeList() 50{ 51} 52 53void 54TypeList::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 62bool 63TypeList::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//TypeList::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//TypeList 96//TypeList::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// TypeList 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 108void 109TypeList::Clear() 110{ 111 m_types.clear(); 112} 113 114uint32_t 115TypeList::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 124TypeSP 125TypeList::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 138void 139TypeList::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 148void 149TypeList::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 159bool 160TypeList::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 173void 174TypeList::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// depending on implementation details, type lookup might fail because of 183// embedded spurious namespace:: prefixes. this call strips them, paying 184// attention to the fact that a type might have namespace'd type names as 185// arguments to templates, and those must not be stripped off 186static bool 187GetTypeScopeAndBasename(const char* name_cstr, std::string &scope, std::string &basename, bool *exact_ptr) 188{ 189 // Protect against null c string. 190 191 if (name_cstr && name_cstr[0]) 192 { 193 const char *basename_cstr = name_cstr; 194 const char* namespace_separator = ::strstr (basename_cstr, "::"); 195 if (namespace_separator) 196 { 197 const char* template_arg_char = ::strchr (basename_cstr, '<'); 198 while (namespace_separator != NULL) 199 { 200 if (template_arg_char && namespace_separator > template_arg_char) // but namespace'd template arguments are still good to go 201 break; 202 basename_cstr = namespace_separator + 2; 203 namespace_separator = strstr(basename_cstr, "::"); 204 } 205 if (basename_cstr > name_cstr) 206 { 207 scope.assign (name_cstr, basename_cstr - name_cstr); 208 if (scope.size() >= 2 && scope[0] == ':' && scope[1] == ':') 209 { 210 // The typename passed in started with "::" so make sure we only do exact matches 211 if (exact_ptr) 212 *exact_ptr = true; 213 // Strip the leading "::" as this won't ever show in qualified typenames we get 214 // from clang. 215 scope.erase(0,2); 216 } 217 basename.assign (basename_cstr); 218 return true; 219 } 220 } 221 } 222 return false; 223} 224 225void 226TypeList::RemoveMismatchedTypes (const char *qualified_typename, 227 bool exact_match) 228{ 229 std::string type_scope; 230 std::string type_basename; 231 TypeClass type_class = eTypeClassAny; 232 if (!Type::GetTypeScopeAndBasename (qualified_typename, type_scope, type_basename, type_class)) 233 { 234 type_basename = qualified_typename; 235 type_scope.clear(); 236 } 237 return RemoveMismatchedTypes (type_scope, type_basename, type_class, exact_match); 238} 239 240void 241TypeList::RemoveMismatchedTypes (const std::string &type_scope, 242 const std::string &type_basename, 243 TypeClass type_class, 244 bool exact_match) 245{ 246 // Our "collection" type currently is a std::map which doesn't 247 // have any good way to iterate and remove items from the map 248 // so we currently just make a new list and add all of the matching 249 // types to it, and then swap it into m_types at the end 250 collection matching_types; 251 252 iterator pos, end = m_types.end(); 253 254 for (pos = m_types.begin(); pos != end; ++pos) 255 { 256 Type* the_type = pos->second.get(); 257 bool keep_match = false; 258 TypeClass match_type_class = eTypeClassAny; 259 260 if (type_class != eTypeClassAny) 261 { 262 match_type_class = ClangASTType::GetTypeClass (the_type->GetClangAST(), 263 the_type->GetClangForwardType()); 264 if ((match_type_class & type_class) == 0) 265 continue; 266 } 267 268 ConstString match_type_name_const_str (the_type->GetQualifiedName()); 269 if (match_type_name_const_str) 270 { 271 const char *match_type_name = match_type_name_const_str.GetCString(); 272 std::string match_type_scope; 273 std::string match_type_basename; 274 if (Type::GetTypeScopeAndBasename (match_type_name, 275 match_type_scope, 276 match_type_basename, 277 match_type_class)) 278 { 279 if (match_type_basename == type_basename) 280 { 281 const size_t type_scope_size = type_scope.size(); 282 const size_t match_type_scope_size = match_type_scope.size(); 283 if (exact_match || (type_scope_size == match_type_scope_size)) 284 { 285 keep_match = match_type_scope == type_scope; 286 } 287 else 288 { 289 if (match_type_scope_size > type_scope_size) 290 { 291 const size_t type_scope_pos = match_type_scope.rfind(type_scope); 292 if (type_scope_pos == match_type_scope_size - type_scope_size) 293 { 294 if (type_scope_pos >= 2) 295 { 296 // Our match scope ends with the type scope we were lookikng for, 297 // but we need to make sure what comes before the matching 298 // type scope is a namepace boundary in case we are trying to match: 299 // type_basename = "d" 300 // type_scope = "b::c::" 301 // We want to match: 302 // match_type_scope "a::b::c::" 303 // But not: 304 // match_type_scope "a::bb::c::" 305 // So below we make sure what comes before "b::c::" in match_type_scope 306 // is "::", or the namespace boundary 307 if (match_type_scope[type_scope_pos - 1] == ':' && 308 match_type_scope[type_scope_pos - 2] == ':') 309 { 310 keep_match = true; 311 } 312 } 313 } 314 } 315 } 316 } 317 } 318 else 319 { 320 // The type we are currently looking at doesn't exists 321 // in a namespace or class, so it only matches if there 322 // is no type scope... 323 keep_match = type_scope.empty() && type_basename.compare(match_type_name) == 0; 324 } 325 } 326 327 if (keep_match) 328 { 329 matching_types.insert (*pos); 330 } 331 } 332 m_types.swap(matching_types); 333} 334 335void 336TypeList::RemoveMismatchedTypes (TypeClass type_class) 337{ 338 if (type_class == eTypeClassAny) 339 return; 340 341 // Our "collection" type currently is a std::map which doesn't 342 // have any good way to iterate and remove items from the map 343 // so we currently just make a new list and add all of the matching 344 // types to it, and then swap it into m_types at the end 345 collection matching_types; 346 347 iterator pos, end = m_types.end(); 348 349 for (pos = m_types.begin(); pos != end; ++pos) 350 { 351 Type* the_type = pos->second.get(); 352 TypeClass match_type_class = ClangASTType::GetTypeClass (the_type->GetClangAST(), 353 the_type->GetClangForwardType()); 354 if (match_type_class & type_class) 355 matching_types.insert (*pos); 356 } 357 m_types.swap(matching_types); 358} 359 360//void * 361//TypeList::CreateClangPointerType (Type *type) 362//{ 363// assert(type); 364// return m_ast.CreatePointerType(type->GetClangForwardType()); 365//} 366// 367//void * 368//TypeList::CreateClangTypedefType (Type *typedef_type, Type *base_type) 369//{ 370// assert(typedef_type && base_type); 371// return m_ast.CreateTypedefType (typedef_type->GetName().AsCString(), 372// base_type->GetClangForwardType(), 373// typedef_type->GetSymbolFile()->GetClangDeclContextForTypeUID(typedef_type->GetID())); 374//} 375// 376//void * 377//TypeList::CreateClangLValueReferenceType (Type *type) 378//{ 379// assert(type); 380// return m_ast.CreateLValueReferenceType(type->GetClangForwardType()); 381//} 382// 383//void * 384//TypeList::CreateClangRValueReferenceType (Type *type) 385//{ 386// assert(type); 387// return m_ast.CreateRValueReferenceType (type->GetClangForwardType()); 388//} 389// 390 391 392