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