ClangASTImporter.h revision 309124
1//===-- ClangASTImporter.h --------------------------------------*- 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#ifndef liblldb_ClangASTImporter_h_ 11#define liblldb_ClangASTImporter_h_ 12 13// C Includes 14// C++ Includes 15#include <map> 16#include <memory> 17#include <set> 18#include <vector> 19 20// Other libraries and framework includes 21#include "clang/AST/ASTImporter.h" 22#include "clang/AST/CharUnits.h" 23#include "clang/AST/Decl.h" 24#include "clang/AST/DeclCXX.h" 25#include "clang/Basic/FileManager.h" 26#include "clang/Basic/FileSystemOptions.h" 27 28// Project includes 29#include "lldb/lldb-types.h" 30#include "lldb/Symbol/CompilerDeclContext.h" 31 32#include "llvm/ADT/DenseMap.h" 33 34namespace lldb_private { 35 36class ClangASTMetrics 37{ 38public: 39 static void DumpCounters (Log *log); 40 static void ClearLocalCounters () 41 { 42 local_counters = { 0, 0, 0, 0, 0, 0 }; 43 } 44 45 static void RegisterVisibleQuery () 46 { 47 ++global_counters.m_visible_query_count; 48 ++local_counters.m_visible_query_count; 49 } 50 51 static void RegisterLexicalQuery () 52 { 53 ++global_counters.m_lexical_query_count; 54 ++local_counters.m_lexical_query_count; 55 } 56 57 static void RegisterLLDBImport () 58 { 59 ++global_counters.m_lldb_import_count; 60 ++local_counters.m_lldb_import_count; 61 } 62 63 static void RegisterClangImport () 64 { 65 ++global_counters.m_clang_import_count; 66 ++local_counters.m_clang_import_count; 67 } 68 69 static void RegisterDeclCompletion () 70 { 71 ++global_counters.m_decls_completed_count; 72 ++local_counters.m_decls_completed_count; 73 } 74 75 static void RegisterRecordLayout () 76 { 77 ++global_counters.m_record_layout_count; 78 ++local_counters.m_record_layout_count; 79 } 80 81private: 82 struct Counters 83 { 84 uint64_t m_visible_query_count; 85 uint64_t m_lexical_query_count; 86 uint64_t m_lldb_import_count; 87 uint64_t m_clang_import_count; 88 uint64_t m_decls_completed_count; 89 uint64_t m_record_layout_count; 90 }; 91 92 static Counters global_counters; 93 static Counters local_counters; 94 95 static void DumpCounters (Log *log, Counters &counters); 96}; 97 98class ClangASTImporter 99{ 100public: 101 struct LayoutInfo 102 { 103 LayoutInfo() : bit_size(0), alignment(0), field_offsets(), base_offsets(), vbase_offsets() {} 104 uint64_t bit_size; 105 uint64_t alignment; 106 llvm::DenseMap<const clang::FieldDecl *, uint64_t> field_offsets; 107 llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> base_offsets; 108 llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> vbase_offsets; 109 }; 110 111 ClangASTImporter () : 112 m_file_manager(clang::FileSystemOptions()) 113 { 114 } 115 116 clang::QualType 117 CopyType (clang::ASTContext *dst_ctx, 118 clang::ASTContext *src_ctx, 119 clang::QualType type); 120 121 lldb::opaque_compiler_type_t 122 CopyType (clang::ASTContext *dst_ctx, 123 clang::ASTContext *src_ctx, 124 lldb::opaque_compiler_type_t type); 125 126 CompilerType 127 CopyType (ClangASTContext &dst, 128 const CompilerType &src_type); 129 130 clang::Decl * 131 CopyDecl (clang::ASTContext *dst_ctx, 132 clang::ASTContext *src_ctx, 133 clang::Decl *decl); 134 135 lldb::opaque_compiler_type_t 136 DeportType (clang::ASTContext *dst_ctx, 137 clang::ASTContext *src_ctx, 138 lldb::opaque_compiler_type_t type); 139 140 clang::Decl * 141 DeportDecl (clang::ASTContext *dst_ctx, 142 clang::ASTContext *src_ctx, 143 clang::Decl *decl); 144 145 void 146 InsertRecordDecl(clang::RecordDecl *decl, const LayoutInfo &layout); 147 148 bool 149 LayoutRecordType(const clang::RecordDecl *record_decl, uint64_t &bit_size, uint64_t &alignment, 150 llvm::DenseMap<const clang::FieldDecl *, uint64_t> &field_offsets, 151 llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &base_offsets, 152 llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &vbase_offsets); 153 154 bool 155 CanImport(const CompilerType &type); 156 157 bool 158 Import(const CompilerType &type); 159 160 bool 161 CompleteType(const CompilerType &compiler_type); 162 163 void 164 CompleteDecl(clang::Decl *decl); 165 166 bool 167 CompleteTagDecl (clang::TagDecl *decl); 168 169 bool 170 CompleteTagDeclWithOrigin (clang::TagDecl *decl, clang::TagDecl *origin); 171 172 bool 173 CompleteObjCInterfaceDecl (clang::ObjCInterfaceDecl *interface_decl); 174 175 bool 176 CompleteAndFetchChildren (clang::QualType type); 177 178 bool 179 RequireCompleteType (clang::QualType type); 180 181 bool 182 ResolveDeclOrigin (const clang::Decl *decl, clang::Decl **original_decl, clang::ASTContext **original_ctx) 183 { 184 DeclOrigin origin = GetDeclOrigin(decl); 185 186 if (original_decl) 187 *original_decl = origin.decl; 188 189 if (original_ctx) 190 *original_ctx = origin.ctx; 191 192 return origin.Valid(); 193 } 194 195 void 196 SetDeclOrigin (const clang::Decl *decl, clang::Decl *original_decl); 197 198 ClangASTMetadata * 199 GetDeclMetadata (const clang::Decl *decl); 200 201 // 202 // Namespace maps 203 // 204 205 typedef std::vector < std::pair<lldb::ModuleSP, CompilerDeclContext> > NamespaceMap; 206 typedef std::shared_ptr<NamespaceMap> NamespaceMapSP; 207 208 void RegisterNamespaceMap (const clang::NamespaceDecl *decl, 209 NamespaceMapSP &namespace_map); 210 211 NamespaceMapSP GetNamespaceMap (const clang::NamespaceDecl *decl); 212 213 void BuildNamespaceMap (const clang::NamespaceDecl *decl); 214 215 // 216 // Completers for maps 217 // 218 219 class MapCompleter 220 { 221 public: 222 virtual ~MapCompleter (); 223 224 virtual void CompleteNamespaceMap (NamespaceMapSP &namespace_map, 225 const ConstString &name, 226 NamespaceMapSP &parent_map) const = 0; 227 }; 228 229 void InstallMapCompleter (clang::ASTContext *dst_ctx, MapCompleter &completer) 230 { 231 ASTContextMetadataSP context_md; 232 ContextMetadataMap::iterator context_md_iter = m_metadata_map.find(dst_ctx); 233 234 if (context_md_iter == m_metadata_map.end()) 235 { 236 context_md = ASTContextMetadataSP(new ASTContextMetadata(dst_ctx)); 237 m_metadata_map[dst_ctx] = context_md; 238 } 239 else 240 { 241 context_md = context_md_iter->second; 242 } 243 244 context_md->m_map_completer = &completer; 245 } 246 247 void ForgetDestination (clang::ASTContext *dst_ctx); 248 void ForgetSource (clang::ASTContext *dst_ctx, clang::ASTContext *src_ctx); 249 250private: 251 struct DeclOrigin 252 { 253 DeclOrigin () : 254 ctx(nullptr), 255 decl(nullptr) 256 { 257 } 258 259 DeclOrigin (clang::ASTContext *_ctx, 260 clang::Decl *_decl) : 261 ctx(_ctx), 262 decl(_decl) 263 { 264 } 265 266 DeclOrigin (const DeclOrigin &rhs) 267 { 268 ctx = rhs.ctx; 269 decl = rhs.decl; 270 } 271 272 void operator= (const DeclOrigin &rhs) 273 { 274 ctx = rhs.ctx; 275 decl = rhs.decl; 276 } 277 278 bool 279 Valid () 280 { 281 return (ctx != nullptr || decl != nullptr); 282 } 283 284 clang::ASTContext *ctx; 285 clang::Decl *decl; 286 }; 287 288 typedef std::map<const clang::Decl *, DeclOrigin> OriginMap; 289 290 class Minion : public clang::ASTImporter 291 { 292 public: 293 Minion (ClangASTImporter &master, 294 clang::ASTContext *target_ctx, 295 clang::ASTContext *source_ctx) : 296 clang::ASTImporter(*target_ctx, 297 master.m_file_manager, 298 *source_ctx, 299 master.m_file_manager, 300 true /*minimal*/), 301 m_decls_to_deport(nullptr), 302 m_decls_already_deported(nullptr), 303 m_master(master), 304 m_source_ctx(source_ctx) 305 { 306 } 307 308 // A call to "InitDeportWorkQueues" puts the minion into deport mode. 309 // In deport mode, every copied Decl that could require completion is 310 // recorded and placed into the decls_to_deport set. 311 // 312 // A call to "ExecuteDeportWorkQueues" completes all the Decls that 313 // are in decls_to_deport, adding any Decls it sees along the way that 314 // it hasn't already deported. It proceeds until decls_to_deport is 315 // empty. 316 // 317 // These calls must be paired. Leaving a minion in deport mode or 318 // trying to start deport minion with a new pair of queues will result 319 // in an assertion failure. 320 321 void InitDeportWorkQueues (std::set<clang::NamedDecl *> *decls_to_deport, 322 std::set<clang::NamedDecl *> *decls_already_deported); 323 void ExecuteDeportWorkQueues (); 324 325 void ImportDefinitionTo (clang::Decl *to, clang::Decl *from); 326 327 clang::Decl *Imported(clang::Decl *from, clang::Decl *to) override; 328 329 clang::Decl *GetOriginalDecl(clang::Decl *To) override; 330 331 std::set<clang::NamedDecl *> *m_decls_to_deport; 332 std::set<clang::NamedDecl *> *m_decls_already_deported; 333 ClangASTImporter &m_master; 334 clang::ASTContext *m_source_ctx; 335 }; 336 337 typedef std::shared_ptr<Minion> MinionSP; 338 typedef std::map<clang::ASTContext *, MinionSP> MinionMap; 339 typedef std::map<const clang::NamespaceDecl *, NamespaceMapSP> NamespaceMetaMap; 340 341 struct ASTContextMetadata 342 { 343 ASTContextMetadata(clang::ASTContext *dst_ctx) : 344 m_dst_ctx (dst_ctx), 345 m_minions (), 346 m_origins (), 347 m_namespace_maps (), 348 m_map_completer (nullptr) 349 { 350 } 351 352 clang::ASTContext *m_dst_ctx; 353 MinionMap m_minions; 354 OriginMap m_origins; 355 356 NamespaceMetaMap m_namespace_maps; 357 MapCompleter *m_map_completer; 358 }; 359 360 typedef std::shared_ptr<ASTContextMetadata> ASTContextMetadataSP; 361 typedef std::map<const clang::ASTContext *, ASTContextMetadataSP> ContextMetadataMap; 362 363 ContextMetadataMap m_metadata_map; 364 365 ASTContextMetadataSP 366 GetContextMetadata (clang::ASTContext *dst_ctx) 367 { 368 ContextMetadataMap::iterator context_md_iter = m_metadata_map.find(dst_ctx); 369 370 if (context_md_iter == m_metadata_map.end()) 371 { 372 ASTContextMetadataSP context_md = ASTContextMetadataSP(new ASTContextMetadata(dst_ctx)); 373 m_metadata_map[dst_ctx] = context_md; 374 return context_md; 375 } 376 else 377 { 378 return context_md_iter->second; 379 } 380 } 381 382 ASTContextMetadataSP 383 MaybeGetContextMetadata (clang::ASTContext *dst_ctx) 384 { 385 ContextMetadataMap::iterator context_md_iter = m_metadata_map.find(dst_ctx); 386 387 if (context_md_iter != m_metadata_map.end()) 388 return context_md_iter->second; 389 else 390 return ASTContextMetadataSP(); 391 } 392 393 MinionSP 394 GetMinion (clang::ASTContext *dst_ctx, clang::ASTContext *src_ctx) 395 { 396 ASTContextMetadataSP context_md = GetContextMetadata(dst_ctx); 397 398 MinionMap &minions = context_md->m_minions; 399 MinionMap::iterator minion_iter = minions.find(src_ctx); 400 401 if (minion_iter == minions.end()) 402 { 403 MinionSP minion = MinionSP(new Minion(*this, dst_ctx, src_ctx)); 404 minions[src_ctx] = minion; 405 return minion; 406 } 407 else 408 { 409 return minion_iter->second; 410 } 411 } 412 413 DeclOrigin 414 GetDeclOrigin (const clang::Decl *decl); 415 416 clang::FileManager m_file_manager; 417 typedef llvm::DenseMap<const clang::RecordDecl *, LayoutInfo> RecordDeclToLayoutMap; 418 419 RecordDeclToLayoutMap m_record_decl_to_layout_map; 420}; 421 422} // namespace lldb_private 423 424#endif // liblldb_ClangASTImporter_h_ 425