1254721Semaste//===-- TypeList.cpp --------------------------------------------*- C++ -*-===// 2254721Semaste// 3254721Semaste// The LLVM Compiler Infrastructure 4254721Semaste// 5254721Semaste// This file is distributed under the University of Illinois Open Source 6254721Semaste// License. See LICENSE.TXT for details. 7254721Semaste// 8254721Semaste//===----------------------------------------------------------------------===// 9254721Semaste 10254721Semaste 11254721Semaste// C Includes 12254721Semaste// C++ Includes 13254721Semaste#include <vector> 14254721Semaste 15254721Semaste// Other libraries and framework includes 16254721Semaste#include "clang/AST/ASTConsumer.h" 17254721Semaste#include "clang/AST/ASTContext.h" 18254721Semaste#include "clang/AST/Decl.h" 19254721Semaste#include "clang/AST/DeclCXX.h" 20254721Semaste#include "clang/AST/DeclGroup.h" 21254721Semaste 22254721Semaste#include "clang/Basic/Builtins.h" 23254721Semaste#include "clang/Basic/IdentifierTable.h" 24254721Semaste#include "clang/Basic/LangOptions.h" 25254721Semaste#include "clang/Basic/SourceManager.h" 26254721Semaste#include "clang/Basic/TargetInfo.h" 27254721Semaste 28254721Semaste#include "llvm/Support/FormattedStream.h" 29254721Semaste#include "llvm/Support/raw_ostream.h" 30254721Semaste 31254721Semaste// Project includes 32254721Semaste#include "lldb/Symbol/SymbolFile.h" 33254721Semaste#include "lldb/Symbol/SymbolVendor.h" 34254721Semaste#include "lldb/Symbol/Type.h" 35254721Semaste#include "lldb/Symbol/TypeList.h" 36254721Semaste 37254721Semasteusing namespace lldb; 38254721Semasteusing namespace lldb_private; 39254721Semasteusing namespace clang; 40254721Semaste 41254721SemasteTypeList::TypeList() : 42254721Semaste m_types () 43254721Semaste{ 44254721Semaste} 45254721Semaste 46254721Semaste//---------------------------------------------------------------------- 47254721Semaste// Destructor 48254721Semaste//---------------------------------------------------------------------- 49254721SemasteTypeList::~TypeList() 50254721Semaste{ 51254721Semaste} 52254721Semaste 53254721Semastevoid 54254721SemasteTypeList::Insert (const TypeSP& type_sp) 55254721Semaste{ 56254721Semaste // Just push each type on the back for now. We will worry about uniquing later 57254721Semaste if (type_sp) 58254721Semaste m_types.insert(std::make_pair(type_sp->GetID(), type_sp)); 59254721Semaste} 60254721Semaste 61254721Semaste 62254721Semastebool 63254721SemasteTypeList::InsertUnique (const TypeSP& type_sp) 64254721Semaste{ 65254721Semaste if (type_sp) 66254721Semaste { 67254721Semaste user_id_t type_uid = type_sp->GetID(); 68254721Semaste iterator pos, end = m_types.end(); 69254721Semaste 70254721Semaste for (pos = m_types.find(type_uid); pos != end && pos->second->GetID() == type_uid; ++pos) 71254721Semaste { 72254721Semaste if (pos->second.get() == type_sp.get()) 73254721Semaste return false; 74254721Semaste } 75254721Semaste } 76254721Semaste Insert (type_sp); 77254721Semaste return true; 78254721Semaste} 79254721Semaste 80254721Semaste//---------------------------------------------------------------------- 81254721Semaste// Find a base type by its unique ID. 82254721Semaste//---------------------------------------------------------------------- 83254721Semaste//TypeSP 84254721Semaste//TypeList::FindType(lldb::user_id_t uid) 85254721Semaste//{ 86254721Semaste// iterator pos = m_types.find(uid); 87254721Semaste// if (pos != m_types.end()) 88254721Semaste// return pos->second; 89254721Semaste// return TypeSP(); 90254721Semaste//} 91254721Semaste 92254721Semaste//---------------------------------------------------------------------- 93254721Semaste// Find a type by name. 94254721Semaste//---------------------------------------------------------------------- 95254721Semaste//TypeList 96254721Semaste//TypeList::FindTypes (const ConstString &name) 97254721Semaste//{ 98254721Semaste// // Do we ever need to make a lookup by name map? Here we are doing 99254721Semaste// // a linear search which isn't going to be fast. 100254721Semaste// TypeList types(m_ast.getTargetInfo()->getTriple().getTriple().c_str()); 101254721Semaste// iterator pos, end; 102254721Semaste// for (pos = m_types.begin(), end = m_types.end(); pos != end; ++pos) 103254721Semaste// if (pos->second->GetName() == name) 104254721Semaste// types.Insert (pos->second); 105254721Semaste// return types; 106254721Semaste//} 107254721Semaste 108254721Semastevoid 109254721SemasteTypeList::Clear() 110254721Semaste{ 111254721Semaste m_types.clear(); 112254721Semaste} 113254721Semaste 114254721Semasteuint32_t 115254721SemasteTypeList::GetSize() const 116254721Semaste{ 117254721Semaste return m_types.size(); 118254721Semaste} 119254721Semaste 120254721Semaste// GetTypeAtIndex isn't used a lot for large type lists, currently only for 121254721Semaste// type lists that are returned for "image dump -t TYPENAME" commands and other 122254721Semaste// simple symbol queries that grab the first result... 123254721Semaste 124254721SemasteTypeSP 125254721SemasteTypeList::GetTypeAtIndex(uint32_t idx) 126254721Semaste{ 127254721Semaste iterator pos, end; 128254721Semaste uint32_t i = idx; 129254721Semaste for (pos = m_types.begin(), end = m_types.end(); pos != end; ++pos) 130254721Semaste { 131254721Semaste if (i == 0) 132254721Semaste return pos->second; 133254721Semaste --i; 134254721Semaste } 135254721Semaste return TypeSP(); 136254721Semaste} 137254721Semaste 138254721Semastevoid 139254721SemasteTypeList::ForEach (std::function <bool(const lldb::TypeSP &type_sp)> const &callback) const 140254721Semaste{ 141254721Semaste for (auto pos = m_types.begin(), end = m_types.end(); pos != end; ++pos) 142254721Semaste { 143254721Semaste if (!callback(pos->second)) 144254721Semaste break; 145254721Semaste } 146254721Semaste} 147254721Semaste 148254721Semastevoid 149254721SemasteTypeList::ForEach (std::function <bool(lldb::TypeSP &type_sp)> const &callback) 150254721Semaste{ 151254721Semaste for (auto pos = m_types.begin(), end = m_types.end(); pos != end; ++pos) 152254721Semaste { 153254721Semaste if (!callback(pos->second)) 154254721Semaste break; 155254721Semaste } 156254721Semaste} 157254721Semaste 158254721Semaste 159254721Semastebool 160254721SemasteTypeList::RemoveTypeWithUID (user_id_t uid) 161254721Semaste{ 162254721Semaste iterator pos = m_types.find(uid); 163254721Semaste 164254721Semaste if (pos != m_types.end()) 165254721Semaste { 166254721Semaste m_types.erase(pos); 167254721Semaste return true; 168254721Semaste } 169254721Semaste return false; 170254721Semaste} 171254721Semaste 172254721Semaste 173254721Semastevoid 174254721SemasteTypeList::Dump(Stream *s, bool show_context) 175254721Semaste{ 176254721Semaste for (iterator pos = m_types.begin(), end = m_types.end(); pos != end; ++pos) 177254721Semaste { 178254721Semaste pos->second->Dump(s, show_context); 179254721Semaste } 180254721Semaste} 181254721Semaste 182254721Semaste// depending on implementation details, type lookup might fail because of 183254721Semaste// embedded spurious namespace:: prefixes. this call strips them, paying 184254721Semaste// attention to the fact that a type might have namespace'd type names as 185254721Semaste// arguments to templates, and those must not be stripped off 186254721Semastestatic bool 187254721SemasteGetTypeScopeAndBasename(const char* name_cstr, std::string &scope, std::string &basename, bool *exact_ptr) 188254721Semaste{ 189254721Semaste // Protect against null c string. 190254721Semaste 191254721Semaste if (name_cstr && name_cstr[0]) 192254721Semaste { 193254721Semaste const char *basename_cstr = name_cstr; 194254721Semaste const char* namespace_separator = ::strstr (basename_cstr, "::"); 195254721Semaste if (namespace_separator) 196254721Semaste { 197254721Semaste const char* template_arg_char = ::strchr (basename_cstr, '<'); 198254721Semaste while (namespace_separator != NULL) 199254721Semaste { 200254721Semaste if (template_arg_char && namespace_separator > template_arg_char) // but namespace'd template arguments are still good to go 201254721Semaste break; 202254721Semaste basename_cstr = namespace_separator + 2; 203254721Semaste namespace_separator = strstr(basename_cstr, "::"); 204254721Semaste } 205254721Semaste if (basename_cstr > name_cstr) 206254721Semaste { 207254721Semaste scope.assign (name_cstr, basename_cstr - name_cstr); 208254721Semaste if (scope.size() >= 2 && scope[0] == ':' && scope[1] == ':') 209254721Semaste { 210254721Semaste // The typename passed in started with "::" so make sure we only do exact matches 211254721Semaste if (exact_ptr) 212254721Semaste *exact_ptr = true; 213254721Semaste // Strip the leading "::" as this won't ever show in qualified typenames we get 214254721Semaste // from clang. 215254721Semaste scope.erase(0,2); 216254721Semaste } 217254721Semaste basename.assign (basename_cstr); 218254721Semaste return true; 219254721Semaste } 220254721Semaste } 221254721Semaste } 222254721Semaste return false; 223254721Semaste} 224254721Semaste 225254721Semastevoid 226254721SemasteTypeList::RemoveMismatchedTypes (const char *qualified_typename, 227254721Semaste bool exact_match) 228254721Semaste{ 229254721Semaste std::string type_scope; 230254721Semaste std::string type_basename; 231254721Semaste TypeClass type_class = eTypeClassAny; 232254721Semaste if (!Type::GetTypeScopeAndBasename (qualified_typename, type_scope, type_basename, type_class)) 233254721Semaste { 234254721Semaste type_basename = qualified_typename; 235254721Semaste type_scope.clear(); 236254721Semaste } 237254721Semaste return RemoveMismatchedTypes (type_scope, type_basename, type_class, exact_match); 238254721Semaste} 239254721Semaste 240254721Semastevoid 241254721SemasteTypeList::RemoveMismatchedTypes (const std::string &type_scope, 242254721Semaste const std::string &type_basename, 243254721Semaste TypeClass type_class, 244254721Semaste bool exact_match) 245254721Semaste{ 246254721Semaste // Our "collection" type currently is a std::map which doesn't 247254721Semaste // have any good way to iterate and remove items from the map 248254721Semaste // so we currently just make a new list and add all of the matching 249254721Semaste // types to it, and then swap it into m_types at the end 250254721Semaste collection matching_types; 251254721Semaste 252254721Semaste iterator pos, end = m_types.end(); 253254721Semaste 254254721Semaste for (pos = m_types.begin(); pos != end; ++pos) 255254721Semaste { 256254721Semaste Type* the_type = pos->second.get(); 257254721Semaste bool keep_match = false; 258254721Semaste TypeClass match_type_class = eTypeClassAny; 259254721Semaste 260254721Semaste if (type_class != eTypeClassAny) 261254721Semaste { 262254721Semaste match_type_class = the_type->GetClangForwardType().GetTypeClass (); 263254721Semaste if ((match_type_class & type_class) == 0) 264254721Semaste continue; 265254721Semaste } 266254721Semaste 267254721Semaste ConstString match_type_name_const_str (the_type->GetQualifiedName()); 268254721Semaste if (match_type_name_const_str) 269254721Semaste { 270254721Semaste const char *match_type_name = match_type_name_const_str.GetCString(); 271254721Semaste std::string match_type_scope; 272254721Semaste std::string match_type_basename; 273254721Semaste if (Type::GetTypeScopeAndBasename (match_type_name, 274254721Semaste match_type_scope, 275254721Semaste match_type_basename, 276254721Semaste match_type_class)) 277254721Semaste { 278254721Semaste if (match_type_basename == type_basename) 279254721Semaste { 280254721Semaste const size_t type_scope_size = type_scope.size(); 281254721Semaste const size_t match_type_scope_size = match_type_scope.size(); 282254721Semaste if (exact_match || (type_scope_size == match_type_scope_size)) 283254721Semaste { 284254721Semaste keep_match = match_type_scope == type_scope; 285254721Semaste } 286254721Semaste else 287254721Semaste { 288254721Semaste if (match_type_scope_size > type_scope_size) 289254721Semaste { 290254721Semaste const size_t type_scope_pos = match_type_scope.rfind(type_scope); 291254721Semaste if (type_scope_pos == match_type_scope_size - type_scope_size) 292254721Semaste { 293254721Semaste if (type_scope_pos >= 2) 294254721Semaste { 295254721Semaste // Our match scope ends with the type scope we were lookikng for, 296254721Semaste // but we need to make sure what comes before the matching 297254721Semaste // type scope is a namepace boundary in case we are trying to match: 298254721Semaste // type_basename = "d" 299254721Semaste // type_scope = "b::c::" 300254721Semaste // We want to match: 301254721Semaste // match_type_scope "a::b::c::" 302254721Semaste // But not: 303254721Semaste // match_type_scope "a::bb::c::" 304254721Semaste // So below we make sure what comes before "b::c::" in match_type_scope 305254721Semaste // is "::", or the namespace boundary 306254721Semaste if (match_type_scope[type_scope_pos - 1] == ':' && 307254721Semaste match_type_scope[type_scope_pos - 2] == ':') 308254721Semaste { 309254721Semaste keep_match = true; 310254721Semaste } 311254721Semaste } 312254721Semaste } 313254721Semaste } 314254721Semaste } 315254721Semaste } 316254721Semaste } 317254721Semaste else 318254721Semaste { 319254721Semaste // The type we are currently looking at doesn't exists 320254721Semaste // in a namespace or class, so it only matches if there 321254721Semaste // is no type scope... 322254721Semaste keep_match = type_scope.empty() && type_basename.compare(match_type_name) == 0; 323254721Semaste } 324254721Semaste } 325254721Semaste 326254721Semaste if (keep_match) 327254721Semaste { 328254721Semaste matching_types.insert (*pos); 329254721Semaste } 330254721Semaste } 331254721Semaste m_types.swap(matching_types); 332254721Semaste} 333254721Semaste 334254721Semastevoid 335254721SemasteTypeList::RemoveMismatchedTypes (TypeClass type_class) 336254721Semaste{ 337254721Semaste if (type_class == eTypeClassAny) 338254721Semaste return; 339254721Semaste 340254721Semaste // Our "collection" type currently is a std::map which doesn't 341254721Semaste // have any good way to iterate and remove items from the map 342254721Semaste // so we currently just make a new list and add all of the matching 343254721Semaste // types to it, and then swap it into m_types at the end 344254721Semaste collection matching_types; 345254721Semaste 346254721Semaste iterator pos, end = m_types.end(); 347254721Semaste 348254721Semaste for (pos = m_types.begin(); pos != end; ++pos) 349254721Semaste { 350254721Semaste Type* the_type = pos->second.get(); 351254721Semaste TypeClass match_type_class = the_type->GetClangForwardType().GetTypeClass (); 352254721Semaste if (match_type_class & type_class) 353254721Semaste matching_types.insert (*pos); 354254721Semaste } 355254721Semaste m_types.swap(matching_types); 356254721Semaste} 357