[lldb] Move clang-based files out of Symbol
authorAlex Langford <apl@fb.com>
Wed, 29 Jan 2020 19:59:28 +0000 (11:59 -0800)
committerAlex Langford <apl@fb.com>
Fri, 31 Jan 2020 20:20:10 +0000 (12:20 -0800)
Summary:
This change represents the move of ClangASTImporter, ClangASTMetadata,
ClangExternalASTSourceCallbacks, ClangUtil, CxxModuleHandler, and
TypeSystemClang from lldbSource to lldbPluginExpressionParserClang.h

This explicitly removes knowledge of clang internals from lldbSymbol,
moving towards a more generic core implementation of lldb.

Reviewers: JDevlieghere, davide, aprantl, teemperor, clayborg, labath, jingham, shafik

Subscribers: emaste, mgorny, arphaman, jfb, usaxena95, lldb-commits

Tags: #lldb

Differential Revision: https://reviews.llvm.org/D73661

115 files changed:
lldb/include/lldb/Symbol/ClangASTImporter.h [deleted file]
lldb/include/lldb/Symbol/ClangASTMetadata.h [deleted file]
lldb/include/lldb/Symbol/ClangExternalASTSourceCallbacks.h [deleted file]
lldb/include/lldb/Symbol/ClangUtil.h [deleted file]
lldb/include/lldb/Symbol/CxxModuleHandler.h [deleted file]
lldb/include/lldb/Symbol/TypeSystemClang.h [deleted file]
lldb/source/API/SystemInitializerFull.cpp
lldb/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.cpp
lldb/source/Plugins/ABI/SysV-ppc64/CMakeLists.txt
lldb/source/Plugins/CMakeLists.txt
lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/CMakeLists.txt
lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp
lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOS.cpp
lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp
lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp
lldb/source/Plugins/ExpressionParser/Clang/CMakeLists.txt
lldb/source/Plugins/ExpressionParser/Clang/ClangASTImporter.cpp [new file with mode: 0644]
lldb/source/Plugins/ExpressionParser/Clang/ClangASTImporter.h [new file with mode: 0644]
lldb/source/Plugins/ExpressionParser/Clang/ClangASTMetadata.cpp [new file with mode: 0644]
lldb/source/Plugins/ExpressionParser/Clang/ClangASTMetadata.h [new file with mode: 0644]
lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp
lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.h
lldb/source/Plugins/ExpressionParser/Clang/ClangDeclVendor.cpp
lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp
lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp
lldb/source/Plugins/ExpressionParser/Clang/ClangExternalASTSourceCallbacks.cpp [new file with mode: 0644]
lldb/source/Plugins/ExpressionParser/Clang/ClangExternalASTSourceCallbacks.h [new file with mode: 0644]
lldb/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.cpp
lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp
lldb/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.cpp
lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp
lldb/source/Plugins/ExpressionParser/Clang/ClangUtil.cpp [new file with mode: 0644]
lldb/source/Plugins/ExpressionParser/Clang/ClangUtil.h [new file with mode: 0644]
lldb/source/Plugins/ExpressionParser/Clang/CxxModuleHandler.cpp [new file with mode: 0644]
lldb/source/Plugins/ExpressionParser/Clang/CxxModuleHandler.h [new file with mode: 0644]
lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp
lldb/source/Plugins/Language/CPlusPlus/BlockPointer.cpp
lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt
lldb/source/Plugins/Language/CPlusPlus/CxxStringTypes.cpp
lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp
lldb/source/Plugins/Language/CPlusPlus/LibCxxBitset.cpp
lldb/source/Plugins/Language/CPlusPlus/LibCxxList.cpp
lldb/source/Plugins/Language/CPlusPlus/LibCxxMap.cpp
lldb/source/Plugins/Language/CPlusPlus/LibCxxUnorderedMap.cpp
lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp
lldb/source/Plugins/Language/ObjC/CF.cpp
lldb/source/Plugins/Language/ObjC/CMakeLists.txt
lldb/source/Plugins/Language/ObjC/Cocoa.cpp
lldb/source/Plugins/Language/ObjC/NSArray.cpp
lldb/source/Plugins/Language/ObjC/NSDictionary.cpp
lldb/source/Plugins/Language/ObjC/NSError.cpp
lldb/source/Plugins/Language/ObjC/NSException.cpp
lldb/source/Plugins/Language/ObjC/NSIndexPath.cpp
lldb/source/Plugins/Language/ObjC/NSSet.cpp
lldb/source/Plugins/Language/ObjC/NSString.cpp
lldb/source/Plugins/Language/ObjC/ObjCLanguage.cpp
lldb/source/Plugins/LanguageRuntime/CPlusPlus/CMakeLists.txt
lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp
lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/CMakeLists.txt
lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp
lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp
lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.h
lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp
lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp
lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp
lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp
lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/CMakeLists.txt
lldb/source/Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.cpp
lldb/source/Plugins/Platform/POSIX/CMakeLists.txt
lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp
lldb/source/Plugins/SymbolFile/DWARF/CMakeLists.txt
lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h
lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
lldb/source/Plugins/SymbolFile/NativePDB/CMakeLists.txt
lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp
lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.h
lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp
lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.h
lldb/source/Plugins/SymbolFile/PDB/CMakeLists.txt
lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp
lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.h
lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp
lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetItemInfoHandler.cpp
lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetPendingItemsHandler.cpp
lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetQueuesHandler.cpp
lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetThreadItemInfoHandler.cpp
lldb/source/Plugins/SystemRuntime/MacOSX/CMakeLists.txt
lldb/source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.cpp
lldb/source/Plugins/TypeSystem/CMakeLists.txt [new file with mode: 0644]
lldb/source/Plugins/TypeSystem/Clang/CMakeLists.txt [new file with mode: 0644]
lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp [new file with mode: 0644]
lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h [new file with mode: 0644]
lldb/source/Symbol/CMakeLists.txt
lldb/source/Symbol/ClangASTImporter.cpp [deleted file]
lldb/source/Symbol/ClangASTMetadata.cpp [deleted file]
lldb/source/Symbol/ClangExternalASTSourceCallbacks.cpp [deleted file]
lldb/source/Symbol/ClangUtil.cpp [deleted file]
lldb/source/Symbol/CxxModuleHandler.cpp [deleted file]
lldb/source/Symbol/TypeSystemClang.cpp [deleted file]
lldb/tools/lldb-test/SystemInitializerTest.cpp
lldb/tools/lldb-test/lldb-test.cpp
lldb/unittests/Expression/CMakeLists.txt
lldb/unittests/Expression/ClangExpressionDeclMapTest.cpp
lldb/unittests/Symbol/CMakeLists.txt
lldb/unittests/Symbol/TestClangASTImporter.cpp
lldb/unittests/Symbol/TestLineEntry.cpp
lldb/unittests/Symbol/TestTypeSystemClang.cpp
lldb/unittests/SymbolFile/DWARF/CMakeLists.txt
lldb/unittests/SymbolFile/DWARF/SymbolFileDWARFTests.cpp
lldb/unittests/SymbolFile/PDB/CMakeLists.txt
lldb/unittests/SymbolFile/PDB/SymbolFilePDBTests.cpp
lldb/unittests/TestingSupport/Symbol/ClangTestUtils.h

diff --git a/lldb/include/lldb/Symbol/ClangASTImporter.h b/lldb/include/lldb/Symbol/ClangASTImporter.h
deleted file mode 100644 (file)
index fed49d3..0000000
+++ /dev/null
@@ -1,326 +0,0 @@
-//===-- ClangASTImporter.h --------------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef liblldb_ClangASTImporter_h_
-#define liblldb_ClangASTImporter_h_
-
-#include <map>
-#include <memory>
-#include <set>
-#include <vector>
-
-#include "clang/AST/ASTImporter.h"
-#include "clang/AST/CharUnits.h"
-#include "clang/AST/Decl.h"
-#include "clang/AST/DeclCXX.h"
-#include "clang/Basic/FileManager.h"
-#include "clang/Basic/FileSystemOptions.h"
-
-#include "lldb/Host/FileSystem.h"
-#include "lldb/Symbol/CompilerDeclContext.h"
-#include "lldb/Symbol/CxxModuleHandler.h"
-#include "lldb/lldb-types.h"
-
-#include "llvm/ADT/DenseMap.h"
-
-namespace lldb_private {
-
-class ClangASTImporter {
-public:
-  struct LayoutInfo {
-    LayoutInfo() = default;
-    typedef llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits>
-        OffsetMap;
-
-    uint64_t bit_size = 0;
-    uint64_t alignment = 0;
-    llvm::DenseMap<const clang::FieldDecl *, uint64_t> field_offsets;
-    OffsetMap base_offsets;
-    OffsetMap vbase_offsets;
-  };
-
-  ClangASTImporter()
-      : m_file_manager(clang::FileSystemOptions(),
-                       FileSystem::Instance().GetVirtualFileSystem()) {}
-
-  CompilerType CopyType(TypeSystemClang &dst, const CompilerType &src_type);
-
-  clang::Decl *CopyDecl(clang::ASTContext *dst_ctx, clang::Decl *decl);
-
-  CompilerType DeportType(TypeSystemClang &dst, const CompilerType &src_type);
-
-  clang::Decl *DeportDecl(clang::ASTContext *dst_ctx, clang::Decl *decl);
-
-  /// Sets the layout for the given RecordDecl. The layout will later be
-  /// used by Clang's during code generation. Not calling this function for
-  /// a RecordDecl will cause that Clang's codegen tries to layout the
-  /// record by itself.
-  ///
-  /// \param decl The RecordDecl to set the layout for.
-  /// \param layout The layout for the record.
-  void SetRecordLayout(clang::RecordDecl *decl, const LayoutInfo &layout);
-
-  bool LayoutRecordType(
-      const clang::RecordDecl *record_decl, uint64_t &bit_size,
-      uint64_t &alignment,
-      llvm::DenseMap<const clang::FieldDecl *, uint64_t> &field_offsets,
-      llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits>
-          &base_offsets,
-      llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits>
-          &vbase_offsets);
-
-  bool CanImport(const CompilerType &type);
-
-  bool Import(const CompilerType &type);
-
-  bool CompleteType(const CompilerType &compiler_type);
-
-  bool CompleteTagDecl(clang::TagDecl *decl);
-
-  bool CompleteTagDeclWithOrigin(clang::TagDecl *decl, clang::TagDecl *origin);
-
-  bool CompleteObjCInterfaceDecl(clang::ObjCInterfaceDecl *interface_decl);
-
-  bool CompleteAndFetchChildren(clang::QualType type);
-
-  bool RequireCompleteType(clang::QualType type);
-
-  void SetDeclOrigin(const clang::Decl *decl, clang::Decl *original_decl);
-
-  ClangASTMetadata *GetDeclMetadata(const clang::Decl *decl);
-
-  //
-  // Namespace maps
-  //
-
-  typedef std::vector<std::pair<lldb::ModuleSP, CompilerDeclContext>>
-      NamespaceMap;
-  typedef std::shared_ptr<NamespaceMap> NamespaceMapSP;
-
-  void RegisterNamespaceMap(const clang::NamespaceDecl *decl,
-                            NamespaceMapSP &namespace_map);
-
-  NamespaceMapSP GetNamespaceMap(const clang::NamespaceDecl *decl);
-
-  void BuildNamespaceMap(const clang::NamespaceDecl *decl);
-
-  //
-  // Completers for maps
-  //
-
-  class MapCompleter {
-  public:
-    virtual ~MapCompleter();
-
-    virtual void CompleteNamespaceMap(NamespaceMapSP &namespace_map,
-                                      ConstString name,
-                                      NamespaceMapSP &parent_map) const = 0;
-  };
-
-  void InstallMapCompleter(clang::ASTContext *dst_ctx,
-                           MapCompleter &completer) {
-    ASTContextMetadataSP context_md;
-    ContextMetadataMap::iterator context_md_iter = m_metadata_map.find(dst_ctx);
-
-    if (context_md_iter == m_metadata_map.end()) {
-      context_md = ASTContextMetadataSP(new ASTContextMetadata(dst_ctx));
-      m_metadata_map[dst_ctx] = context_md;
-    } else {
-      context_md = context_md_iter->second;
-    }
-
-    context_md->m_map_completer = &completer;
-  }
-
-  void ForgetDestination(clang::ASTContext *dst_ctx);
-  void ForgetSource(clang::ASTContext *dst_ctx, clang::ASTContext *src_ctx);
-
-public:
-  struct DeclOrigin {
-    DeclOrigin() : ctx(nullptr), decl(nullptr) {}
-
-    DeclOrigin(clang::ASTContext *_ctx, clang::Decl *_decl)
-        : ctx(_ctx), decl(_decl) {}
-
-    DeclOrigin(const DeclOrigin &rhs) {
-      ctx = rhs.ctx;
-      decl = rhs.decl;
-    }
-
-    void operator=(const DeclOrigin &rhs) {
-      ctx = rhs.ctx;
-      decl = rhs.decl;
-    }
-
-    bool Valid() { return (ctx != nullptr || decl != nullptr); }
-
-    clang::ASTContext *ctx;
-    clang::Decl *decl;
-  };
-
-  typedef llvm::DenseMap<const clang::Decl *, DeclOrigin> OriginMap;
-
-  /// Listener interface used by the ASTImporterDelegate to inform other code
-  /// about decls that have been imported the first time.
-  struct NewDeclListener {
-    virtual ~NewDeclListener() = default;
-    /// A decl has been imported for the first time.
-    virtual void NewDeclImported(clang::Decl *from, clang::Decl *to) = 0;
-  };
-
-  /// ASTImporter that intercepts and records the import process of the
-  /// underlying ASTImporter.
-  ///
-  /// This class updates the map from declarations to their original
-  /// declarations and can record declarations that have been imported in a
-  /// certain interval.
-  ///
-  /// When intercepting a declaration import, the ASTImporterDelegate uses the
-  /// CxxModuleHandler to replace any missing or malformed declarations with
-  /// their counterpart from a C++ module.
-  struct ASTImporterDelegate : public clang::ASTImporter {
-    ASTImporterDelegate(ClangASTImporter &master, clang::ASTContext *target_ctx,
-                        clang::ASTContext *source_ctx)
-        : clang::ASTImporter(*target_ctx, master.m_file_manager, *source_ctx,
-                             master.m_file_manager, true /*minimal*/),
-          m_master(master), m_source_ctx(source_ctx) {
-      setODRHandling(clang::ASTImporter::ODRHandlingType::Liberal);
-    }
-
-    /// Scope guard that attaches a CxxModuleHandler to an ASTImporterDelegate
-    /// and deattaches it at the end of the scope. Supports being used multiple
-    /// times on the same ASTImporterDelegate instance in nested scopes.
-    class CxxModuleScope {
-      /// The handler we attach to the ASTImporterDelegate.
-      CxxModuleHandler m_handler;
-      /// The ASTImporterDelegate we are supposed to attach the handler to.
-      ASTImporterDelegate &m_delegate;
-      /// True iff we attached the handler to the ASTImporterDelegate.
-      bool m_valid = false;
-
-    public:
-      CxxModuleScope(ASTImporterDelegate &delegate, clang::ASTContext *dst_ctx)
-          : m_delegate(delegate) {
-        // If the delegate doesn't have a CxxModuleHandler yet, create one
-        // and attach it.
-        if (!delegate.m_std_handler) {
-          m_handler = CxxModuleHandler(delegate, dst_ctx);
-          m_valid = true;
-          delegate.m_std_handler = &m_handler;
-        }
-      }
-      ~CxxModuleScope() {
-        if (m_valid) {
-          // Make sure no one messed with the handler we placed.
-          assert(m_delegate.m_std_handler == &m_handler);
-          m_delegate.m_std_handler = nullptr;
-        }
-      }
-    };
-
-    void ImportDefinitionTo(clang::Decl *to, clang::Decl *from);
-
-    void Imported(clang::Decl *from, clang::Decl *to) override;
-
-    clang::Decl *GetOriginalDecl(clang::Decl *To) override;
-
-    void SetImportListener(NewDeclListener *listener) {
-      assert(m_new_decl_listener == nullptr && "Already attached a listener?");
-      m_new_decl_listener = listener;
-    }
-    void RemoveImportListener() { m_new_decl_listener = nullptr; }
-
-  protected:
-    llvm::Expected<clang::Decl *> ImportImpl(clang::Decl *From) override;
-
-  private:
-    /// Decls we should ignore when mapping decls back to their original
-    /// ASTContext. Used by the CxxModuleHandler to mark declarations that
-    /// were created from the 'std' C++ module to prevent that the Importer
-    /// tries to sync them with the broken equivalent in the debug info AST.
-    llvm::SmallPtrSet<clang::Decl *, 16> m_decls_to_ignore;
-    ClangASTImporter &m_master;
-    clang::ASTContext *m_source_ctx;
-    CxxModuleHandler *m_std_handler = nullptr;
-    /// The currently attached listener.
-    NewDeclListener *m_new_decl_listener = nullptr;
-  };
-
-  typedef std::shared_ptr<ASTImporterDelegate> ImporterDelegateSP;
-  typedef llvm::DenseMap<clang::ASTContext *, ImporterDelegateSP> DelegateMap;
-  typedef llvm::DenseMap<const clang::NamespaceDecl *, NamespaceMapSP>
-      NamespaceMetaMap;
-
-  struct ASTContextMetadata {
-    ASTContextMetadata(clang::ASTContext *dst_ctx)
-        : m_dst_ctx(dst_ctx), m_delegates(), m_origins(), m_namespace_maps(),
-          m_map_completer(nullptr) {}
-
-    clang::ASTContext *m_dst_ctx;
-    DelegateMap m_delegates;
-    OriginMap m_origins;
-
-    NamespaceMetaMap m_namespace_maps;
-    MapCompleter *m_map_completer;
-  };
-
-  typedef std::shared_ptr<ASTContextMetadata> ASTContextMetadataSP;
-  typedef llvm::DenseMap<const clang::ASTContext *, ASTContextMetadataSP>
-      ContextMetadataMap;
-
-  ContextMetadataMap m_metadata_map;
-
-  ASTContextMetadataSP GetContextMetadata(clang::ASTContext *dst_ctx) {
-    ContextMetadataMap::iterator context_md_iter = m_metadata_map.find(dst_ctx);
-
-    if (context_md_iter == m_metadata_map.end()) {
-      ASTContextMetadataSP context_md =
-          ASTContextMetadataSP(new ASTContextMetadata(dst_ctx));
-      m_metadata_map[dst_ctx] = context_md;
-      return context_md;
-    }
-    return context_md_iter->second;
-  }
-
-  ASTContextMetadataSP MaybeGetContextMetadata(clang::ASTContext *dst_ctx) {
-    ContextMetadataMap::iterator context_md_iter = m_metadata_map.find(dst_ctx);
-
-    if (context_md_iter != m_metadata_map.end())
-      return context_md_iter->second;
-    return ASTContextMetadataSP();
-  }
-
-  ImporterDelegateSP GetDelegate(clang::ASTContext *dst_ctx,
-                                 clang::ASTContext *src_ctx) {
-    ASTContextMetadataSP context_md = GetContextMetadata(dst_ctx);
-
-    DelegateMap &delegates = context_md->m_delegates;
-    DelegateMap::iterator delegate_iter = delegates.find(src_ctx);
-
-    if (delegate_iter == delegates.end()) {
-      ImporterDelegateSP delegate =
-          ImporterDelegateSP(new ASTImporterDelegate(*this, dst_ctx, src_ctx));
-      delegates[src_ctx] = delegate;
-      return delegate;
-    }
-    return delegate_iter->second;
-  }
-
-public:
-  DeclOrigin GetDeclOrigin(const clang::Decl *decl);
-
-  clang::FileManager m_file_manager;
-  typedef llvm::DenseMap<const clang::RecordDecl *, LayoutInfo>
-      RecordDeclToLayoutMap;
-
-  RecordDeclToLayoutMap m_record_decl_to_layout_map;
-};
-
-} // namespace lldb_private
-
-#endif // liblldb_ClangASTImporter_h_
diff --git a/lldb/include/lldb/Symbol/ClangASTMetadata.h b/lldb/include/lldb/Symbol/ClangASTMetadata.h
deleted file mode 100644 (file)
index fdf4388..0000000
+++ /dev/null
@@ -1,100 +0,0 @@
-//===-- ClangASTMetadata.h --------------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef liblldb_ClangASTMetadata_h
-#define liblldb_ClangASTMetadata_h
-
-#include "lldb/Core/dwarf.h"
-#include "lldb/lldb-defines.h"
-#include "lldb/lldb-enumerations.h"
-
-namespace lldb_private {
-
-class ClangASTMetadata {
-public:
-  ClangASTMetadata()
-      : m_user_id(0), m_union_is_user_id(false), m_union_is_isa_ptr(false),
-        m_has_object_ptr(false), m_is_self(false), m_is_dynamic_cxx(true) {}
-
-  bool GetIsDynamicCXXType() const { return m_is_dynamic_cxx; }
-
-  void SetIsDynamicCXXType(bool b) { m_is_dynamic_cxx = b; }
-
-  void SetUserID(lldb::user_id_t user_id) {
-    m_user_id = user_id;
-    m_union_is_user_id = true;
-    m_union_is_isa_ptr = false;
-  }
-
-  lldb::user_id_t GetUserID() const {
-    if (m_union_is_user_id)
-      return m_user_id;
-    else
-      return LLDB_INVALID_UID;
-  }
-
-  void SetISAPtr(uint64_t isa_ptr) {
-    m_isa_ptr = isa_ptr;
-    m_union_is_user_id = false;
-    m_union_is_isa_ptr = true;
-  }
-
-  uint64_t GetISAPtr() const {
-    if (m_union_is_isa_ptr)
-      return m_isa_ptr;
-    else
-      return 0;
-  }
-
-  void SetObjectPtrName(const char *name) {
-    m_has_object_ptr = true;
-    if (strcmp(name, "self") == 0)
-      m_is_self = true;
-    else if (strcmp(name, "this") == 0)
-      m_is_self = false;
-    else
-      m_has_object_ptr = false;
-  }
-
-  lldb::LanguageType GetObjectPtrLanguage() const {
-    if (m_has_object_ptr) {
-      if (m_is_self)
-        return lldb::eLanguageTypeObjC;
-      else
-        return lldb::eLanguageTypeC_plus_plus;
-    }
-    return lldb::eLanguageTypeUnknown;
-  }
-
-  const char *GetObjectPtrName() const {
-    if (m_has_object_ptr) {
-      if (m_is_self)
-        return "self";
-      else
-        return "this";
-    } else
-      return nullptr;
-  }
-
-  bool HasObjectPtr() const { return m_has_object_ptr; }
-
-  void Dump(Stream *s);
-
-private:
-  union {
-    lldb::user_id_t m_user_id;
-    uint64_t m_isa_ptr;
-  };
-
-  bool m_union_is_user_id : 1, m_union_is_isa_ptr : 1, m_has_object_ptr : 1,
-      m_is_self : 1, m_is_dynamic_cxx : 1;
-};
-
-} // namespace lldb_private
-
-#endif // liblldb_ClangASTMetadata_h
diff --git a/lldb/include/lldb/Symbol/ClangExternalASTSourceCallbacks.h b/lldb/include/lldb/Symbol/ClangExternalASTSourceCallbacks.h
deleted file mode 100644 (file)
index 49bc30c..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-//===-- ClangExternalASTSourceCallbacks.h -----------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef liblldb_ClangExternalASTSourceCallbacks_h_
-#define liblldb_ClangExternalASTSourceCallbacks_h_
-
-#include "lldb/Symbol/TypeSystemClang.h"
-#include "clang/AST/ExternalASTSource.h"
-
-namespace lldb_private {
-
-class TypeSystemClang;
-
-class ClangExternalASTSourceCallbacks : public clang::ExternalASTSource {
-public:
-  ClangExternalASTSourceCallbacks(TypeSystemClang &ast) : m_ast(ast) {}
-
-  void FindExternalLexicalDecls(
-      const clang::DeclContext *DC,
-      llvm::function_ref<bool(clang::Decl::Kind)> IsKindWeWant,
-      llvm::SmallVectorImpl<clang::Decl *> &Result) override;
-
-  void CompleteType(clang::TagDecl *tag_decl) override;
-
-  void CompleteType(clang::ObjCInterfaceDecl *objc_decl) override;
-
-  bool layoutRecordType(
-      const clang::RecordDecl *Record, uint64_t &Size, uint64_t &Alignment,
-      llvm::DenseMap<const clang::FieldDecl *, uint64_t> &FieldOffsets,
-      llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits>
-          &BaseOffsets,
-      llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits>
-          &VirtualBaseOffsets) override;
-
-private:
-  TypeSystemClang &m_ast;
-};
-
-} // namespace lldb_private
-
-#endif // liblldb_ClangExternalASTSourceCallbacks_h_
diff --git a/lldb/include/lldb/Symbol/ClangUtil.h b/lldb/include/lldb/Symbol/ClangUtil.h
deleted file mode 100644 (file)
index 31e86ca..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-//===-- ClangUtil.h ---------------------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-// A collection of helper methods and data structures for manipulating clang
-// types and decls.
-//===----------------------------------------------------------------------===//
-
-#ifndef LLDB_SYMBOL_CLANGUTIL_H
-#define LLDB_SYMBOL_CLANGUTIL_H
-
-#include "clang/AST/DeclBase.h"
-#include "clang/AST/Type.h"
-
-#include "lldb/Symbol/CompilerType.h"
-
-namespace clang {
-class TagDecl;
-}
-
-namespace lldb_private {
-struct ClangUtil {
-  static bool IsClangType(const CompilerType &ct);
-
-  /// Returns the clang::Decl of the given CompilerDecl.
-  /// CompilerDecl has to be valid and represent a clang::Decl.
-  static clang::Decl *GetDecl(const CompilerDecl &decl);
-
-  static clang::QualType GetQualType(const CompilerType &ct);
-
-  static clang::QualType GetCanonicalQualType(const CompilerType &ct);
-
-  static CompilerType RemoveFastQualifiers(const CompilerType &ct);
-
-  static clang::TagDecl *GetAsTagDecl(const CompilerType &type);
-
-  /// Returns a textual representation of the given Decl's AST. Does not
-  /// deserialize any child nodes.
-  static std::string DumpDecl(const clang::Decl *d);
-  /// Returns a textual representation of the given type.
-  static std::string ToString(const clang::Type *t);
-  /// Returns a textual representation of the given CompilerType (assuming
-  /// its underlying type is a Clang type).
-  static std::string ToString(const CompilerType &c);
-};
-}
-
-#endif
diff --git a/lldb/include/lldb/Symbol/CxxModuleHandler.h b/lldb/include/lldb/Symbol/CxxModuleHandler.h
deleted file mode 100644 (file)
index f4aef36..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-//===-- CxxModuleHandler.h --------------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef liblldb_CxxModuleHandler_h_
-#define liblldb_CxxModuleHandler_h_
-
-#include "clang/AST/ASTImporter.h"
-#include "clang/Sema/Sema.h"
-#include "llvm/ADT/StringSet.h"
-
-namespace lldb_private {
-
-/// Handles importing decls into an ASTContext with an attached C++ module.
-///
-/// This class searches a C++ module (which must be attached to the target
-/// ASTContext) for an equivalent decl to the one that should be imported.
-/// If the decl that is found in the module is a suitable replacement
-/// for the decl that should be imported, the module decl will be treated as
-/// the result of the import process.
-///
-/// If the Decl that should be imported is a template specialization
-/// that doesn't exist yet in the target ASTContext (e.g. `std::vector<int>`),
-/// then this class tries to create the template specialization in the target
-/// ASTContext. This is only possible if the CxxModuleHandler can determine
-/// that instantiating this template is safe to do, e.g. because the target
-/// decl is a container class from the STL.
-class CxxModuleHandler {
-  /// The ASTImporter that should be used to import any Decls which aren't
-  /// directly handled by this class itself.
-  clang::ASTImporter *m_importer = nullptr;
-
-  /// The Sema instance of the target ASTContext.
-  clang::Sema *m_sema = nullptr;
-
-  /// List of template names this class currently supports. These are the
-  /// template names inside the 'std' namespace such as 'vector' or 'list'.
-  llvm::StringSet<> m_supported_templates;
-
-  /// Tries to manually instantiate the given foreign template in the target
-  /// context (designated by m_sema).
-  llvm::Optional<clang::Decl *> tryInstantiateStdTemplate(clang::Decl *d);
-
-public:
-  CxxModuleHandler() = default;
-  CxxModuleHandler(clang::ASTImporter &importer, clang::ASTContext *target);
-
-  /// Attempts to import the given decl into the target ASTContext by
-  /// deserializing it from the 'std' module. This function returns a Decl if a
-  /// Decl has been deserialized from the 'std' module. Otherwise this function
-  /// returns nothing.
-  llvm::Optional<clang::Decl *> Import(clang::Decl *d);
-
-  /// Returns true iff this instance is capable of importing any declarations
-  /// in the target ASTContext.
-  bool isValid() const { return m_sema != nullptr; }
-};
-
-} // namespace lldb_private
-
-#endif // liblldb_CxxModuleHandler_h_
diff --git a/lldb/include/lldb/Symbol/TypeSystemClang.h b/lldb/include/lldb/Symbol/TypeSystemClang.h
deleted file mode 100644 (file)
index fd8276d..0000000
+++ /dev/null
@@ -1,1029 +0,0 @@
-//===-- TypeSystemClang.h ---------------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef liblldb_TypeSystemClang_h_
-#define liblldb_TypeSystemClang_h_
-
-#include <stdint.h>
-
-#include <functional>
-#include <initializer_list>
-#include <map>
-#include <memory>
-#include <set>
-#include <string>
-#include <utility>
-#include <vector>
-
-#include "clang/AST/ASTContext.h"
-#include "clang/AST/ASTFwd.h"
-#include "clang/AST/TemplateBase.h"
-#include "llvm/ADT/APSInt.h"
-#include "llvm/ADT/SmallVector.h"
-
-#include "Plugins/ExpressionParser/Clang/ClangPersistentVariables.h"
-#include "lldb/Core/ClangForward.h"
-#include "lldb/Expression/ExpressionVariable.h"
-#include "lldb/Symbol/CompilerType.h"
-#include "lldb/Symbol/TypeSystem.h"
-#include "lldb/Target/Target.h"
-#include "lldb/Utility/ConstString.h"
-#include "lldb/Utility/Log.h"
-#include "lldb/Utility/Logging.h"
-#include "lldb/lldb-enumerations.h"
-
-class DWARFASTParserClang;
-class PDBASTParser;
-
-namespace lldb_private {
-
-class Declaration;
-
-class TypeSystemClang : public TypeSystem {
-  // LLVM RTTI support
-  static char ID;
-
-public:
-  typedef void (*CompleteTagDeclCallback)(void *baton, clang::TagDecl *);
-  typedef void (*CompleteObjCInterfaceDeclCallback)(void *baton,
-                                                    clang::ObjCInterfaceDecl *);
-
-  // llvm casting support
-  bool isA(const void *ClassID) const override { return ClassID == &ID; }
-  static bool classof(const TypeSystem *ts) { return ts->isA(&ID); }
-
-  /// Constructs a TypeSystemClang with an ASTContext using the given triple.
-  ///
-  /// \param name The name for the TypeSystemClang (for logging purposes)
-  /// \param triple The llvm::Triple used for the ASTContext. The triple defines
-  ///               certain characteristics of the ASTContext and its types
-  ///               (e.g., whether certain primitive types exist or what their
-  ///               signedness is).
-  explicit TypeSystemClang(llvm::StringRef name, llvm::Triple triple);
-
-  /// Constructs a TypeSystemClang that uses an existing ASTContext internally.
-  /// Useful when having an existing ASTContext created by Clang.
-  ///
-  /// \param name The name for the TypeSystemClang (for logging purposes)
-  /// \param existing_ctxt An existing ASTContext.
-  explicit TypeSystemClang(llvm::StringRef name,
-                           clang::ASTContext &existing_ctxt);
-
-  ~TypeSystemClang() override;
-
-  void Finalize() override;
-
-  // PluginInterface functions
-  ConstString GetPluginName() override;
-
-  uint32_t GetPluginVersion() override;
-
-  static ConstString GetPluginNameStatic();
-
-  static lldb::TypeSystemSP CreateInstance(lldb::LanguageType language,
-                                           Module *module, Target *target);
-
-  static LanguageSet GetSupportedLanguagesForTypes();
-  static LanguageSet GetSupportedLanguagesForExpressions();
-
-  static void Initialize();
-
-  static void Terminate();
-
-  static TypeSystemClang *GetASTContext(clang::ASTContext *ast_ctx);
-
-  static TypeSystemClang *GetScratch(Target &target,
-                                     bool create_on_demand = true) {
-    auto type_system_or_err = target.GetScratchTypeSystemForLanguage(
-        lldb::eLanguageTypeC, create_on_demand);
-    if (auto err = type_system_or_err.takeError()) {
-      LLDB_LOG_ERROR(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_TARGET),
-                     std::move(err), "Couldn't get scratch TypeSystemClang");
-      return nullptr;
-    }
-    return llvm::dyn_cast<TypeSystemClang>(&type_system_or_err.get());
-  }
-
-  /// Returns the display name of this TypeSystemClang that indicates what
-  /// purpose it serves in LLDB. Used for example in logs.
-  llvm::StringRef getDisplayName() const { return m_display_name; }
-
-  clang::ASTContext &getASTContext();
-
-  clang::MangleContext *getMangleContext();
-
-  std::shared_ptr<clang::TargetOptions> &getTargetOptions();
-
-  clang::TargetInfo *getTargetInfo();
-
-  void setSema(clang::Sema *s);
-  clang::Sema *getSema() { return m_sema; }
-
-  const char *GetTargetTriple();
-
-  void SetExternalSource(
-      llvm::IntrusiveRefCntPtr<clang::ExternalASTSource> &ast_source_up);
-
-  bool GetCompleteDecl(clang::Decl *decl) {
-    return TypeSystemClang::GetCompleteDecl(&getASTContext(), decl);
-  }
-
-  static void DumpDeclHiearchy(clang::Decl *decl);
-
-  static void DumpDeclContextHiearchy(clang::DeclContext *decl_ctx);
-
-  static bool DeclsAreEquivalent(clang::Decl *lhs_decl, clang::Decl *rhs_decl);
-
-  static bool GetCompleteDecl(clang::ASTContext *ast, clang::Decl *decl);
-
-  void SetMetadataAsUserID(const clang::Decl *decl, lldb::user_id_t user_id);
-  void SetMetadataAsUserID(const clang::Type *type, lldb::user_id_t user_id);
-
-  void SetMetadata(const clang::Decl *object, ClangASTMetadata &meta_data);
-
-  void SetMetadata(const clang::Type *object, ClangASTMetadata &meta_data);
-  ClangASTMetadata *GetMetadata(const clang::Decl *object);
-  ClangASTMetadata *GetMetadata(const clang::Type *object);
-
-  // Basic Types
-  CompilerType GetBuiltinTypeForEncodingAndBitSize(lldb::Encoding encoding,
-                                                   size_t bit_size) override;
-
-  CompilerType GetBasicType(lldb::BasicType type);
-
-  static lldb::BasicType GetBasicTypeEnumeration(ConstString name);
-
-  CompilerType
-  GetBuiltinTypeForDWARFEncodingAndBitSize(llvm::StringRef type_name,
-                                           uint32_t dw_ate, uint32_t bit_size);
-
-  CompilerType GetCStringType(bool is_const);
-
-  static clang::DeclContext *GetDeclContextForType(clang::QualType type);
-
-  static clang::DeclContext *GetDeclContextForType(const CompilerType &type);
-
-  uint32_t GetPointerByteSize() override;
-
-  clang::TranslationUnitDecl *GetTranslationUnitDecl() {
-    return getASTContext().getTranslationUnitDecl();
-  }
-
-  static bool AreTypesSame(CompilerType type1, CompilerType type2,
-                           bool ignore_qualifiers = false);
-
-  /// Creates a CompilerType form the given QualType with the current
-  /// TypeSystemClang instance as the CompilerType's typesystem.
-  /// \param qt The QualType for a type that belongs to the ASTContext of this
-  ///           TypeSystemClang.
-  /// \return The CompilerType representing the given QualType. If the
-  ///         QualType's type pointer is a nullptr then the function returns an
-  ///         invalid CompilerType.
-  CompilerType GetType(clang::QualType qt) {
-    if (qt.getTypePtrOrNull() == nullptr)
-      return CompilerType();
-    // Check that the type actually belongs to this TypeSystemClang.
-    assert(qt->getAsTagDecl() == nullptr ||
-           &qt->getAsTagDecl()->getASTContext() == &getASTContext());
-    return CompilerType(this, qt.getAsOpaquePtr());
-  }
-
-  CompilerType GetTypeForDecl(clang::NamedDecl *decl);
-
-  CompilerType GetTypeForDecl(clang::TagDecl *decl);
-
-  CompilerType GetTypeForDecl(clang::ObjCInterfaceDecl *objc_decl);
-
-  template <typename RecordDeclType>
-  CompilerType
-  GetTypeForIdentifier(ConstString type_name,
-                       clang::DeclContext *decl_context = nullptr) {
-    CompilerType compiler_type;
-
-    if (type_name.GetLength()) {
-      clang::ASTContext &ast = getASTContext();
-      if (!decl_context)
-        decl_context = ast.getTranslationUnitDecl();
-
-      clang::IdentifierInfo &myIdent = ast.Idents.get(type_name.GetCString());
-      clang::DeclarationName myName =
-          ast.DeclarationNames.getIdentifier(&myIdent);
-
-      clang::DeclContext::lookup_result result = decl_context->lookup(myName);
-
-      if (!result.empty()) {
-        clang::NamedDecl *named_decl = result[0];
-        if (const RecordDeclType *record_decl =
-                llvm::dyn_cast<RecordDeclType>(named_decl))
-          compiler_type.SetCompilerType(
-              this, clang::QualType(record_decl->getTypeForDecl(), 0)
-                        .getAsOpaquePtr());
-      }
-    }
-
-    return compiler_type;
-  }
-
-  CompilerType CreateStructForIdentifier(
-      ConstString type_name,
-      const std::initializer_list<std::pair<const char *, CompilerType>>
-          &type_fields,
-      bool packed = false);
-
-  CompilerType GetOrCreateStructForIdentifier(
-      ConstString type_name,
-      const std::initializer_list<std::pair<const char *, CompilerType>>
-          &type_fields,
-      bool packed = false);
-
-  static bool IsOperator(llvm::StringRef name,
-                         clang::OverloadedOperatorKind &op_kind);
-
-  // Structure, Unions, Classes
-
-  static clang::AccessSpecifier
-  ConvertAccessTypeToAccessSpecifier(lldb::AccessType access);
-
-  static clang::AccessSpecifier
-  UnifyAccessSpecifiers(clang::AccessSpecifier lhs, clang::AccessSpecifier rhs);
-
-  static uint32_t GetNumBaseClasses(const clang::CXXRecordDecl *cxx_record_decl,
-                                    bool omit_empty_base_classes);
-
-  CompilerType CreateRecordType(clang::DeclContext *decl_ctx,
-                                lldb::AccessType access_type,
-                                llvm::StringRef name, int kind,
-                                lldb::LanguageType language,
-                                ClangASTMetadata *metadata = nullptr,
-                                bool exports_symbols = false);
-
-  class TemplateParameterInfos {
-  public:
-    bool IsValid() const {
-      if (args.empty())
-        return false;
-      return args.size() == names.size() &&
-        ((bool)pack_name == (bool)packed_args) &&
-        (!packed_args || !packed_args->packed_args);
-    }
-
-    llvm::SmallVector<const char *, 2> names;
-    llvm::SmallVector<clang::TemplateArgument, 2> args;
-    
-    const char * pack_name = nullptr;
-    std::unique_ptr<TemplateParameterInfos> packed_args;
-  };
-
-  clang::FunctionTemplateDecl *
-  CreateFunctionTemplateDecl(clang::DeclContext *decl_ctx,
-                             clang::FunctionDecl *func_decl, const char *name,
-                             const TemplateParameterInfos &infos);
-
-  void CreateFunctionTemplateSpecializationInfo(
-      clang::FunctionDecl *func_decl, clang::FunctionTemplateDecl *Template,
-      const TemplateParameterInfos &infos);
-
-  clang::ClassTemplateDecl *
-  CreateClassTemplateDecl(clang::DeclContext *decl_ctx,
-                          lldb::AccessType access_type, const char *class_name,
-                          int kind, const TemplateParameterInfos &infos);
-
-  clang::TemplateTemplateParmDecl *
-  CreateTemplateTemplateParmDecl(const char *template_name);
-
-  clang::ClassTemplateSpecializationDecl *CreateClassTemplateSpecializationDecl(
-      clang::DeclContext *decl_ctx,
-      clang::ClassTemplateDecl *class_template_decl, int kind,
-      const TemplateParameterInfos &infos);
-
-  CompilerType
-  CreateClassTemplateSpecializationType(clang::ClassTemplateSpecializationDecl *
-                                            class_template_specialization_decl);
-
-  static clang::DeclContext *
-  GetAsDeclContext(clang::FunctionDecl *function_decl);
-
-  static bool CheckOverloadedOperatorKindParameterCount(
-      bool is_method, clang::OverloadedOperatorKind op_kind,
-      uint32_t num_params);
-
-  bool FieldIsBitfield(clang::FieldDecl *field, uint32_t &bitfield_bit_size);
-
-  static bool RecordHasFields(const clang::RecordDecl *record_decl);
-
-  CompilerType CreateObjCClass(llvm::StringRef name,
-                               clang::DeclContext *decl_ctx, bool isForwardDecl,
-                               bool isInternal,
-                               ClangASTMetadata *metadata = nullptr);
-
-  bool SetTagTypeKind(clang::QualType type, int kind) const;
-
-  bool SetDefaultAccessForRecordFields(clang::RecordDecl *record_decl,
-                                       int default_accessibility,
-                                       int *assigned_accessibilities,
-                                       size_t num_assigned_accessibilities);
-
-  // Returns a mask containing bits from the TypeSystemClang::eTypeXXX
-  // enumerations
-
-  // Namespace Declarations
-
-  clang::NamespaceDecl *
-  GetUniqueNamespaceDeclaration(const char *name, clang::DeclContext *decl_ctx,
-                                bool is_inline = false);
-
-  // Function Types
-
-  clang::FunctionDecl *
-  CreateFunctionDeclaration(clang::DeclContext *decl_ctx, const char *name,
-                            const CompilerType &function_Type, int storage,
-                            bool is_inline);
-
-  CompilerType CreateFunctionType(const CompilerType &result_type,
-                                  const CompilerType *args, unsigned num_args,
-                                  bool is_variadic, unsigned type_quals,
-                                  clang::CallingConv cc);
-
-  CompilerType CreateFunctionType(const CompilerType &result_type,
-                                  const CompilerType *args, unsigned num_args,
-                                  bool is_variadic, unsigned type_quals) {
-    return CreateFunctionType(result_type, args, num_args, is_variadic,
-                              type_quals, clang::CC_C);
-  }
-
-  clang::ParmVarDecl *CreateParameterDeclaration(clang::DeclContext *decl_ctx,
-                                                 const char *name,
-                                                 const CompilerType &param_type,
-                                                 int storage,
-                                                 bool add_decl=false);
-
-  void SetFunctionParameters(clang::FunctionDecl *function_decl,
-                             clang::ParmVarDecl **params, unsigned num_params);
-
-  CompilerType CreateBlockPointerType(const CompilerType &function_type);
-
-  // Array Types
-
-  CompilerType CreateArrayType(const CompilerType &element_type,
-                               size_t element_count, bool is_vector);
-
-  // Enumeration Types
-  CompilerType CreateEnumerationType(const char *name,
-                                     clang::DeclContext *decl_ctx,
-                                     const Declaration &decl,
-                                     const CompilerType &integer_qual_type,
-                                     bool is_scoped);
-
-  // Integer type functions
-
-  CompilerType GetIntTypeFromBitSize(size_t bit_size, bool is_signed);
-
-  CompilerType GetPointerSizedIntType(bool is_signed);
-
-  // Floating point functions
-
-  static CompilerType GetFloatTypeFromBitSize(clang::ASTContext *ast,
-                                              size_t bit_size);
-
-  // TypeSystem methods
-  DWARFASTParser *GetDWARFParser() override;
-  PDBASTParser *GetPDBParser() override;
-
-  // TypeSystemClang callbacks for external source lookups.
-  void CompleteTagDecl(clang::TagDecl *);
-
-  void CompleteObjCInterfaceDecl(clang::ObjCInterfaceDecl *);
-
-  bool LayoutRecordType(
-      const clang::RecordDecl *record_decl, uint64_t &size, uint64_t &alignment,
-      llvm::DenseMap<const clang::FieldDecl *, uint64_t> &field_offsets,
-      llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits>
-          &base_offsets,
-      llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits>
-          &vbase_offsets);
-
-  /// Creates a CompilerDecl from the given Decl with the current
-  /// TypeSystemClang instance as its typesystem.
-  /// The Decl has to come from the ASTContext of this
-  /// TypeSystemClang.
-  CompilerDecl GetCompilerDecl(clang::Decl *decl) {
-    assert(&decl->getASTContext() == &getASTContext() &&
-           "CreateCompilerDecl for Decl from wrong ASTContext?");
-    return CompilerDecl(this, decl);
-  }
-
-  // CompilerDecl override functions
-  ConstString DeclGetName(void *opaque_decl) override;
-
-  ConstString DeclGetMangledName(void *opaque_decl) override;
-
-  CompilerDeclContext DeclGetDeclContext(void *opaque_decl) override;
-
-  CompilerType DeclGetFunctionReturnType(void *opaque_decl) override;
-
-  size_t DeclGetFunctionNumArguments(void *opaque_decl) override;
-
-  CompilerType DeclGetFunctionArgumentType(void *opaque_decl,
-                                           size_t arg_idx) override;
-
-  CompilerType GetTypeForDecl(void *opaque_decl) override;
-
-  // CompilerDeclContext override functions
-
-  /// Creates a CompilerDeclContext from the given DeclContext
-  /// with the current TypeSystemClang instance as its typesystem.
-  /// The DeclContext has to come from the ASTContext of this
-  /// TypeSystemClang.
-  CompilerDeclContext CreateDeclContext(clang::DeclContext *ctx);
-
-  std::vector<CompilerDecl>
-  DeclContextFindDeclByName(void *opaque_decl_ctx, ConstString name,
-                            const bool ignore_using_decls) override;
-
-  ConstString DeclContextGetName(void *opaque_decl_ctx) override;
-
-  ConstString DeclContextGetScopeQualifiedName(void *opaque_decl_ctx) override;
-
-  bool DeclContextIsClassMethod(void *opaque_decl_ctx,
-                                lldb::LanguageType *language_ptr,
-                                bool *is_instance_method_ptr,
-                                ConstString *language_object_name_ptr) override;
-
-  bool DeclContextIsContainedInLookup(void *opaque_decl_ctx,
-                                      void *other_opaque_decl_ctx) override;
-
-  // Clang specific clang::DeclContext functions
-
-  static clang::DeclContext *
-  DeclContextGetAsDeclContext(const CompilerDeclContext &dc);
-
-  static clang::ObjCMethodDecl *
-  DeclContextGetAsObjCMethodDecl(const CompilerDeclContext &dc);
-
-  static clang::CXXMethodDecl *
-  DeclContextGetAsCXXMethodDecl(const CompilerDeclContext &dc);
-
-  static clang::FunctionDecl *
-  DeclContextGetAsFunctionDecl(const CompilerDeclContext &dc);
-
-  static clang::NamespaceDecl *
-  DeclContextGetAsNamespaceDecl(const CompilerDeclContext &dc);
-
-  static ClangASTMetadata *DeclContextGetMetaData(const CompilerDeclContext &dc,
-                                                  const clang::Decl *object);
-
-  static clang::ASTContext *
-  DeclContextGetTypeSystemClang(const CompilerDeclContext &dc);
-
-  // Tests
-
-  bool IsArrayType(lldb::opaque_compiler_type_t type,
-                   CompilerType *element_type, uint64_t *size,
-                   bool *is_incomplete) override;
-
-  bool IsVectorType(lldb::opaque_compiler_type_t type,
-                    CompilerType *element_type, uint64_t *size) override;
-
-  bool IsAggregateType(lldb::opaque_compiler_type_t type) override;
-
-  bool IsAnonymousType(lldb::opaque_compiler_type_t type) override;
-
-  bool IsBeingDefined(lldb::opaque_compiler_type_t type) override;
-
-  bool IsCharType(lldb::opaque_compiler_type_t type) override;
-
-  bool IsCompleteType(lldb::opaque_compiler_type_t type) override;
-
-  bool IsConst(lldb::opaque_compiler_type_t type) override;
-
-  bool IsCStringType(lldb::opaque_compiler_type_t type,
-                     uint32_t &length) override;
-
-  static bool IsCXXClassType(const CompilerType &type);
-
-  bool IsDefined(lldb::opaque_compiler_type_t type) override;
-
-  bool IsFloatingPointType(lldb::opaque_compiler_type_t type, uint32_t &count,
-                           bool &is_complex) override;
-
-  bool IsFunctionType(lldb::opaque_compiler_type_t type,
-                      bool *is_variadic_ptr) override;
-
-  uint32_t IsHomogeneousAggregate(lldb::opaque_compiler_type_t type,
-                                  CompilerType *base_type_ptr) override;
-
-  size_t
-  GetNumberOfFunctionArguments(lldb::opaque_compiler_type_t type) override;
-
-  CompilerType GetFunctionArgumentAtIndex(lldb::opaque_compiler_type_t type,
-                                          const size_t index) override;
-
-  bool IsFunctionPointerType(lldb::opaque_compiler_type_t type) override;
-
-  bool IsBlockPointerType(lldb::opaque_compiler_type_t type,
-                          CompilerType *function_pointer_type_ptr) override;
-
-  bool IsIntegerType(lldb::opaque_compiler_type_t type,
-                     bool &is_signed) override;
-
-  bool IsEnumerationType(lldb::opaque_compiler_type_t type,
-                         bool &is_signed) override;
-
-  static bool IsObjCClassType(const CompilerType &type);
-
-  static bool IsObjCClassTypeAndHasIVars(const CompilerType &type,
-                                         bool check_superclass);
-
-  static bool IsObjCObjectOrInterfaceType(const CompilerType &type);
-
-  static bool IsObjCObjectPointerType(const CompilerType &type,
-                                      CompilerType *target_type = nullptr);
-
-  bool IsPolymorphicClass(lldb::opaque_compiler_type_t type) override;
-
-  static bool IsClassType(lldb::opaque_compiler_type_t type);
-
-  static bool IsEnumType(lldb::opaque_compiler_type_t type);
-
-  bool IsPossibleDynamicType(lldb::opaque_compiler_type_t type,
-                             CompilerType *target_type, // Can pass nullptr
-                             bool check_cplusplus, bool check_objc) override;
-
-  bool IsRuntimeGeneratedType(lldb::opaque_compiler_type_t type) override;
-
-  bool IsPointerType(lldb::opaque_compiler_type_t type,
-                     CompilerType *pointee_type) override;
-
-  bool IsPointerOrReferenceType(lldb::opaque_compiler_type_t type,
-                                CompilerType *pointee_type) override;
-
-  bool IsReferenceType(lldb::opaque_compiler_type_t type,
-                       CompilerType *pointee_type, bool *is_rvalue) override;
-
-  bool IsScalarType(lldb::opaque_compiler_type_t type) override;
-
-  bool IsTypedefType(lldb::opaque_compiler_type_t type) override;
-
-  bool IsVoidType(lldb::opaque_compiler_type_t type) override;
-
-  bool CanPassInRegisters(const CompilerType &type) override;
-
-  bool SupportsLanguage(lldb::LanguageType language) override;
-
-  static llvm::Optional<std::string> GetCXXClassName(const CompilerType &type);
-
-  // Type Completion
-
-  bool GetCompleteType(lldb::opaque_compiler_type_t type) override;
-
-  // Accessors
-
-  ConstString GetTypeName(lldb::opaque_compiler_type_t type) override;
-
-  uint32_t GetTypeInfo(lldb::opaque_compiler_type_t type,
-                       CompilerType *pointee_or_element_compiler_type) override;
-
-  lldb::LanguageType
-  GetMinimumLanguage(lldb::opaque_compiler_type_t type) override;
-
-  lldb::TypeClass GetTypeClass(lldb::opaque_compiler_type_t type) override;
-
-  unsigned GetTypeQualifiers(lldb::opaque_compiler_type_t type) override;
-
-  // Creating related types
-
-  // Using the current type, create a new typedef to that type using
-  // "typedef_name" as the name and "decl_ctx" as the decl context.
-  static CompilerType
-  CreateTypedefType(const CompilerType &type, const char *typedef_name,
-                    const CompilerDeclContext &compiler_decl_ctx);
-
-  CompilerType GetArrayElementType(lldb::opaque_compiler_type_t type,
-                                   uint64_t *stride) override;
-
-  CompilerType GetArrayType(lldb::opaque_compiler_type_t type,
-                            uint64_t size) override;
-
-  CompilerType GetCanonicalType(lldb::opaque_compiler_type_t type) override;
-
-  CompilerType
-  GetFullyUnqualifiedType(lldb::opaque_compiler_type_t type) override;
-
-  // Returns -1 if this isn't a function of if the function doesn't have a
-  // prototype Returns a value >= 0 if there is a prototype.
-  int GetFunctionArgumentCount(lldb::opaque_compiler_type_t type) override;
-
-  CompilerType GetFunctionArgumentTypeAtIndex(lldb::opaque_compiler_type_t type,
-                                              size_t idx) override;
-
-  CompilerType
-  GetFunctionReturnType(lldb::opaque_compiler_type_t type) override;
-
-  size_t GetNumMemberFunctions(lldb::opaque_compiler_type_t type) override;
-
-  TypeMemberFunctionImpl
-  GetMemberFunctionAtIndex(lldb::opaque_compiler_type_t type,
-                           size_t idx) override;
-
-  CompilerType GetNonReferenceType(lldb::opaque_compiler_type_t type) override;
-
-  CompilerType GetPointeeType(lldb::opaque_compiler_type_t type) override;
-
-  CompilerType GetPointerType(lldb::opaque_compiler_type_t type) override;
-
-  CompilerType
-  GetLValueReferenceType(lldb::opaque_compiler_type_t type) override;
-
-  CompilerType
-  GetRValueReferenceType(lldb::opaque_compiler_type_t type) override;
-
-  CompilerType GetAtomicType(lldb::opaque_compiler_type_t type) override;
-
-  CompilerType AddConstModifier(lldb::opaque_compiler_type_t type) override;
-
-  CompilerType AddVolatileModifier(lldb::opaque_compiler_type_t type) override;
-
-  CompilerType AddRestrictModifier(lldb::opaque_compiler_type_t type) override;
-
-  CompilerType CreateTypedef(lldb::opaque_compiler_type_t type,
-                             const char *name,
-                             const CompilerDeclContext &decl_ctx) override;
-
-  // If the current object represents a typedef type, get the underlying type
-  CompilerType GetTypedefedType(lldb::opaque_compiler_type_t type) override;
-
-  // Create related types using the current type's AST
-  CompilerType GetBasicTypeFromAST(lldb::BasicType basic_type) override;
-
-  // Exploring the type
-
-  const llvm::fltSemantics &GetFloatTypeSemantics(size_t byte_size) override;
-
-  llvm::Optional<uint64_t> GetByteSize(lldb::opaque_compiler_type_t type,
-                       ExecutionContextScope *exe_scope) {
-    if (llvm::Optional<uint64_t> bit_size = GetBitSize(type, exe_scope))
-      return (*bit_size + 7) / 8;
-    return llvm::None;
-  }
-
-  llvm::Optional<uint64_t>
-  GetBitSize(lldb::opaque_compiler_type_t type,
-             ExecutionContextScope *exe_scope) override;
-
-  lldb::Encoding GetEncoding(lldb::opaque_compiler_type_t type,
-                             uint64_t &count) override;
-
-  lldb::Format GetFormat(lldb::opaque_compiler_type_t type) override;
-
-  llvm::Optional<size_t>
-  GetTypeBitAlign(lldb::opaque_compiler_type_t type,
-                  ExecutionContextScope *exe_scope) override;
-
-  uint32_t GetNumChildren(lldb::opaque_compiler_type_t type,
-                          bool omit_empty_base_classes,
-                          const ExecutionContext *exe_ctx) override;
-
-  CompilerType GetBuiltinTypeByName(ConstString name) override;
-
-  lldb::BasicType
-  GetBasicTypeEnumeration(lldb::opaque_compiler_type_t type) override;
-
-  static lldb::BasicType
-  GetBasicTypeEnumeration(lldb::opaque_compiler_type_t type,
-                          ConstString name);
-
-  void ForEachEnumerator(
-      lldb::opaque_compiler_type_t type,
-      std::function<bool(const CompilerType &integer_type,
-                         ConstString name,
-                         const llvm::APSInt &value)> const &callback) override;
-
-  uint32_t GetNumFields(lldb::opaque_compiler_type_t type) override;
-
-  CompilerType GetFieldAtIndex(lldb::opaque_compiler_type_t type, size_t idx,
-                               std::string &name, uint64_t *bit_offset_ptr,
-                               uint32_t *bitfield_bit_size_ptr,
-                               bool *is_bitfield_ptr) override;
-
-  uint32_t GetNumDirectBaseClasses(lldb::opaque_compiler_type_t type) override;
-
-  uint32_t GetNumVirtualBaseClasses(lldb::opaque_compiler_type_t type) override;
-
-  CompilerType GetDirectBaseClassAtIndex(lldb::opaque_compiler_type_t type,
-                                         size_t idx,
-                                         uint32_t *bit_offset_ptr) override;
-
-  CompilerType GetVirtualBaseClassAtIndex(lldb::opaque_compiler_type_t type,
-                                          size_t idx,
-                                          uint32_t *bit_offset_ptr) override;
-
-  static uint32_t GetNumPointeeChildren(clang::QualType type);
-
-  CompilerType GetChildCompilerTypeAtIndex(
-      lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx, size_t idx,
-      bool transparent_pointers, bool omit_empty_base_classes,
-      bool ignore_array_bounds, std::string &child_name,
-      uint32_t &child_byte_size, int32_t &child_byte_offset,
-      uint32_t &child_bitfield_bit_size, uint32_t &child_bitfield_bit_offset,
-      bool &child_is_base_class, bool &child_is_deref_of_parent,
-      ValueObject *valobj, uint64_t &language_flags) override;
-
-  // Lookup a child given a name. This function will match base class names and
-  // member member names in "clang_type" only, not descendants.
-  uint32_t GetIndexOfChildWithName(lldb::opaque_compiler_type_t type,
-                                   const char *name,
-                                   bool omit_empty_base_classes) override;
-
-  // Lookup a child member given a name. This function will match member names
-  // only and will descend into "clang_type" children in search for the first
-  // member in this class, or any base class that matches "name".
-  // TODO: Return all matches for a given name by returning a
-  // vector<vector<uint32_t>>
-  // so we catch all names that match a given child name, not just the first.
-  size_t
-  GetIndexOfChildMemberWithName(lldb::opaque_compiler_type_t type,
-                                const char *name, bool omit_empty_base_classes,
-                                std::vector<uint32_t> &child_indexes) override;
-
-  size_t GetNumTemplateArguments(lldb::opaque_compiler_type_t type) override;
-
-  lldb::TemplateArgumentKind
-  GetTemplateArgumentKind(lldb::opaque_compiler_type_t type,
-                          size_t idx) override;
-  CompilerType GetTypeTemplateArgument(lldb::opaque_compiler_type_t type,
-                                       size_t idx) override;
-  llvm::Optional<CompilerType::IntegralTemplateArgument>
-  GetIntegralTemplateArgument(lldb::opaque_compiler_type_t type,
-                              size_t idx) override;
-
-  CompilerType GetTypeForFormatters(void *type) override;
-
-#define LLDB_INVALID_DECL_LEVEL UINT32_MAX
-  // LLDB_INVALID_DECL_LEVEL is returned by CountDeclLevels if child_decl_ctx
-  // could not be found in decl_ctx.
-  uint32_t CountDeclLevels(clang::DeclContext *frame_decl_ctx,
-                           clang::DeclContext *child_decl_ctx,
-                           ConstString *child_name = nullptr,
-                           CompilerType *child_type = nullptr);
-
-  // Modifying RecordType
-  static clang::FieldDecl *AddFieldToRecordType(const CompilerType &type,
-                                                llvm::StringRef name,
-                                                const CompilerType &field_type,
-                                                lldb::AccessType access,
-                                                uint32_t bitfield_bit_size);
-
-  static void BuildIndirectFields(const CompilerType &type);
-
-  static void SetIsPacked(const CompilerType &type);
-
-  static clang::VarDecl *AddVariableToRecordType(const CompilerType &type,
-                                                 llvm::StringRef name,
-                                                 const CompilerType &var_type,
-                                                 lldb::AccessType access);
-
-  clang::CXXMethodDecl *AddMethodToCXXRecordType(
-      lldb::opaque_compiler_type_t type, llvm::StringRef name,
-      const char *mangled_name, const CompilerType &method_type,
-      lldb::AccessType access, bool is_virtual, bool is_static, bool is_inline,
-      bool is_explicit, bool is_attr_used, bool is_artificial);
-
-  void AddMethodOverridesForCXXRecordType(lldb::opaque_compiler_type_t type);
-
-  // C++ Base Classes
-  std::unique_ptr<clang::CXXBaseSpecifier>
-  CreateBaseClassSpecifier(lldb::opaque_compiler_type_t type,
-                           lldb::AccessType access, bool is_virtual,
-                           bool base_of_class);
-
-  bool TransferBaseClasses(
-      lldb::opaque_compiler_type_t type,
-      std::vector<std::unique_ptr<clang::CXXBaseSpecifier>> bases);
-
-  static bool SetObjCSuperClass(const CompilerType &type,
-                                const CompilerType &superclass_compiler_type);
-
-  static bool AddObjCClassProperty(const CompilerType &type,
-                                   const char *property_name,
-                                   const CompilerType &property_compiler_type,
-                                   clang::ObjCIvarDecl *ivar_decl,
-                                   const char *property_setter_name,
-                                   const char *property_getter_name,
-                                   uint32_t property_attributes,
-                                   ClangASTMetadata *metadata);
-
-  static clang::ObjCMethodDecl *AddMethodToObjCObjectType(
-      const CompilerType &type,
-      const char *name, // the full symbol name as seen in the symbol table
-                        // (lldb::opaque_compiler_type_t type, "-[NString
-                        // stringWithCString:]")
-      const CompilerType &method_compiler_type, lldb::AccessType access,
-      bool is_artificial, bool is_variadic, bool is_objc_direct_call);
-
-  static bool SetHasExternalStorage(lldb::opaque_compiler_type_t type,
-                                    bool has_extern);
-
-  // Tag Declarations
-  static bool StartTagDeclarationDefinition(const CompilerType &type);
-
-  static bool CompleteTagDeclarationDefinition(const CompilerType &type);
-
-  // Modifying Enumeration types
-  clang::EnumConstantDecl *AddEnumerationValueToEnumerationType(
-      const CompilerType &enum_type, const Declaration &decl, const char *name,
-      int64_t enum_value, uint32_t enum_value_bit_size);
-  clang::EnumConstantDecl *AddEnumerationValueToEnumerationType(
-      const CompilerType &enum_type, const Declaration &decl, const char *name,
-      const llvm::APSInt &value);
-
-  CompilerType GetEnumerationIntegerType(lldb::opaque_compiler_type_t type);
-
-  // Pointers & References
-
-  // Call this function using the class type when you want to make a member
-  // pointer type to pointee_type.
-  static CompilerType CreateMemberPointerType(const CompilerType &type,
-                                              const CompilerType &pointee_type);
-
-  // Dumping types
-#ifndef NDEBUG
-  /// Convenience LLVM-style dump method for use in the debugger only.
-  /// In contrast to the other \p Dump() methods this directly invokes
-  /// \p clang::QualType::dump().
-  LLVM_DUMP_METHOD void dump(lldb::opaque_compiler_type_t type) const override;
-#endif
-
-  void Dump(Stream &s);
-
-  /// Dump clang AST types from the symbol file.
-  ///
-  /// \param[in] s
-  ///       A stream to send the dumped AST node(s) to
-  /// \param[in] symbol_name
-  ///       The name of the symbol to dump, if it is empty dump all the symbols
-  void DumpFromSymbolFile(Stream &s, llvm::StringRef symbol_name);
-
-  void DumpValue(lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx,
-                 Stream *s, lldb::Format format, const DataExtractor &data,
-                 lldb::offset_t data_offset, size_t data_byte_size,
-                 uint32_t bitfield_bit_size, uint32_t bitfield_bit_offset,
-                 bool show_types, bool show_summary, bool verbose,
-                 uint32_t depth) override;
-
-  bool DumpTypeValue(lldb::opaque_compiler_type_t type, Stream *s,
-                     lldb::Format format, const DataExtractor &data,
-                     lldb::offset_t data_offset, size_t data_byte_size,
-                     uint32_t bitfield_bit_size, uint32_t bitfield_bit_offset,
-                     ExecutionContextScope *exe_scope) override;
-
-  void DumpSummary(lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx,
-                   Stream *s, const DataExtractor &data,
-                   lldb::offset_t data_offset, size_t data_byte_size) override;
-
-  void DumpTypeDescription(
-      lldb::opaque_compiler_type_t type) override; // Dump to stdout
-
-  void DumpTypeDescription(lldb::opaque_compiler_type_t type,
-                           Stream *s) override;
-
-  static void DumpTypeName(const CompilerType &type);
-
-  static clang::EnumDecl *GetAsEnumDecl(const CompilerType &type);
-
-  static clang::RecordDecl *GetAsRecordDecl(const CompilerType &type);
-
-  static clang::TagDecl *GetAsTagDecl(const CompilerType &type);
-
-  static clang::TypedefNameDecl *GetAsTypedefDecl(const CompilerType &type);
-
-  static clang::CXXRecordDecl *
-  GetAsCXXRecordDecl(lldb::opaque_compiler_type_t type);
-
-  static clang::ObjCInterfaceDecl *
-  GetAsObjCInterfaceDecl(const CompilerType &type);
-
-  clang::ClassTemplateDecl *ParseClassTemplateDecl(
-      clang::DeclContext *decl_ctx, lldb::AccessType access_type,
-      const char *parent_name, int tag_decl_kind,
-      const TypeSystemClang::TemplateParameterInfos &template_param_infos);
-
-  clang::BlockDecl *CreateBlockDeclaration(clang::DeclContext *ctx);
-
-  clang::UsingDirectiveDecl *
-  CreateUsingDirectiveDeclaration(clang::DeclContext *decl_ctx,
-                                  clang::NamespaceDecl *ns_decl);
-
-  clang::UsingDecl *CreateUsingDeclaration(clang::DeclContext *current_decl_ctx,
-                                           clang::NamedDecl *target);
-
-  clang::VarDecl *CreateVariableDeclaration(clang::DeclContext *decl_context,
-                                            const char *name,
-                                            clang::QualType type);
-
-  static lldb::opaque_compiler_type_t
-  GetOpaqueCompilerType(clang::ASTContext *ast, lldb::BasicType basic_type);
-
-  static clang::QualType GetQualType(lldb::opaque_compiler_type_t type) {
-    if (type)
-      return clang::QualType::getFromOpaquePtr(type);
-    return clang::QualType();
-  }
-
-  static clang::QualType
-  GetCanonicalQualType(lldb::opaque_compiler_type_t type) {
-    if (type)
-      return clang::QualType::getFromOpaquePtr(type).getCanonicalType();
-    return clang::QualType();
-  }
-
-  clang::DeclarationName
-  GetDeclarationName(const char *name, const CompilerType &function_clang_type);
-
-private:
-  const clang::ClassTemplateSpecializationDecl *
-  GetAsTemplateSpecialization(lldb::opaque_compiler_type_t type);
-
-  // Classes that inherit from TypeSystemClang can see and modify these
-  std::string m_target_triple;
-  std::unique_ptr<clang::ASTContext> m_ast_up;
-  std::unique_ptr<clang::LangOptions> m_language_options_up;
-  std::unique_ptr<clang::FileManager> m_file_manager_up;
-  std::unique_ptr<clang::SourceManager> m_source_manager_up;
-  std::unique_ptr<clang::DiagnosticsEngine> m_diagnostics_engine_up;
-  std::unique_ptr<clang::DiagnosticConsumer> m_diagnostic_consumer_up;
-  std::shared_ptr<clang::TargetOptions> m_target_options_rp;
-  std::unique_ptr<clang::TargetInfo> m_target_info_up;
-  std::unique_ptr<clang::IdentifierTable> m_identifier_table_up;
-  std::unique_ptr<clang::SelectorTable> m_selector_table_up;
-  std::unique_ptr<clang::Builtin::Context> m_builtins_up;
-  std::unique_ptr<DWARFASTParserClang> m_dwarf_ast_parser_up;
-  std::unique_ptr<PDBASTParser> m_pdb_ast_parser_up;
-  std::unique_ptr<clang::MangleContext> m_mangle_ctx_up;
-  uint32_t m_pointer_byte_size = 0;
-  bool m_ast_owned = false;
-  /// A string describing what this TypeSystemClang represents (e.g.,
-  /// AST for debug information, an expression, some other utility ClangAST).
-  /// Useful for logging and debugging.
-  std::string m_display_name;
-
-  typedef llvm::DenseMap<const clang::Decl *, ClangASTMetadata> DeclMetadataMap;
-  /// Maps Decls to their associated ClangASTMetadata.
-  DeclMetadataMap m_decl_metadata;
-
-  typedef llvm::DenseMap<const clang::Type *, ClangASTMetadata> TypeMetadataMap;
-  /// Maps Types to their associated ClangASTMetadata.
-  TypeMetadataMap m_type_metadata;
-
-  /// The sema associated that is currently used to build this ASTContext.
-  /// May be null if we are already done parsing this ASTContext or the
-  /// ASTContext wasn't created by parsing source code.
-  clang::Sema *m_sema = nullptr;
-
-  // For TypeSystemClang only
-  TypeSystemClang(const TypeSystemClang &);
-  const TypeSystemClang &operator=(const TypeSystemClang &);
-  /// Creates the internal ASTContext.
-  void CreateASTContext();
-  void SetTargetTriple(llvm::StringRef target_triple);
-};
-
-class TypeSystemClangForExpressions : public TypeSystemClang {
-public:
-  TypeSystemClangForExpressions(Target &target, llvm::Triple triple);
-
-  ~TypeSystemClangForExpressions() override = default;
-
-  void Finalize() override;
-
-  UserExpression *
-  GetUserExpression(llvm::StringRef expr, llvm::StringRef prefix,
-                    lldb::LanguageType language,
-                    Expression::ResultType desired_type,
-                    const EvaluateExpressionOptions &options,
-                    ValueObject *ctx_obj) override;
-
-  FunctionCaller *GetFunctionCaller(const CompilerType &return_type,
-                                    const Address &function_address,
-                                    const ValueList &arg_value_list,
-                                    const char *name) override;
-
-  UtilityFunction *GetUtilityFunction(const char *text,
-                                      const char *name) override;
-
-  PersistentExpressionState *GetPersistentExpressionState() override;
-private:
-  lldb::TargetWP m_target_wp;
-  std::unique_ptr<ClangPersistentVariables>
-      m_persistent_variables; // These are the persistent variables associated
-                              // with this process for the expression parser
-  std::unique_ptr<ClangASTSource> m_scratch_ast_source_up;
-};
-
-} // namespace lldb_private
-
-#endif // liblldb_TypeSystemClang_h_
index 9d566b51f4a05d9fae1a357225fdb5f875f9faca..d518c577c7d18266cd3b6458c407c00542d4d7fd 100644 (file)
@@ -22,7 +22,6 @@
 #include "lldb/Host/Host.h"
 #include "lldb/Initialization/SystemInitializerCommon.h"
 #include "lldb/Interpreter/CommandInterpreter.h"
-#include "lldb/Symbol/TypeSystemClang.h"
 #include "lldb/Utility/Timer.h"
 
 #include "Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.h"
@@ -96,6 +95,7 @@
 #include "Plugins/SymbolVendor/ELF/SymbolVendorELF.h"
 #include "Plugins/SymbolVendor/wasm/SymbolVendorWasm.h"
 #include "Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.h"
+#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
 #include "Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.h"
 #include "Plugins/UnwindAssembly/x86/UnwindAssembly-x86.h"
 
index 0680a764637a8eca08970e60c9de23c7565bb702..16e54988347af692af85cec5b252ee1de6e253b7 100644 (file)
@@ -11,6 +11,7 @@
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/Triple.h"
 
+#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
 #include "Utility/PPC64LE_DWARF_Registers.h"
 #include "Utility/PPC64_DWARF_Registers.h"
 #include "lldb/Core/Module.h"
@@ -19,7 +20,6 @@
 #include "lldb/Core/ValueObjectConstResult.h"
 #include "lldb/Core/ValueObjectMemory.h"
 #include "lldb/Core/ValueObjectRegister.h"
-#include "lldb/Symbol/TypeSystemClang.h"
 #include "lldb/Symbol/UnwindPlan.h"
 #include "lldb/Target/Process.h"
 #include "lldb/Target/RegisterContext.h"
index b31182dd0f78edba92bf98a149662e56b6f22dad..0a0bb7b8623d9ff276428af97b3de602868e5e36 100644 (file)
@@ -5,6 +5,7 @@ add_lldb_library(lldbPluginABISysV_ppc64 PLUGIN
     lldbCore
     lldbSymbol
     lldbTarget
+    lldbPluginTypeSystemClang
   LINK_COMPONENTS
     Support
   )
index 5092b210a12cfe763aa5124ca706a057e8e07c6a..08817baec14ca1572d50beba917476d529ed23cb 100644 (file)
@@ -19,4 +19,5 @@ add_subdirectory(StructuredData)
 add_subdirectory(SymbolFile)
 add_subdirectory(SystemRuntime)
 add_subdirectory(SymbolVendor)
+add_subdirectory(TypeSystem)
 add_subdirectory(UnwindAssembly)
index 515c82dcaca97f686ecb9190074a8de5905cd2b1..c470bc6e8339f30a66ed8ce548d367de421e184b 100644 (file)
@@ -11,6 +11,7 @@ add_lldb_library(lldbPluginDynamicLoaderMacOSXDYLD PLUGIN
     lldbSymbol
     lldbTarget
     lldbUtility
+    lldbPluginTypeSystemClang
   LINK_COMPONENTS
     Support
   )
index 20c60a44ce0665cd5c2558860e7af73f8684e53d..324a0d07c125b05208dc3d6a6b8870eaad7235c0 100644 (file)
@@ -16,7 +16,6 @@
 #include "lldb/Core/Section.h"
 #include "lldb/Expression/DiagnosticManager.h"
 #include "lldb/Host/FileSystem.h"
-#include "lldb/Symbol/TypeSystemClang.h"
 #include "lldb/Symbol/Function.h"
 #include "lldb/Symbol/ObjectFile.h"
 #include "lldb/Target/ABI.h"
@@ -32,6 +31,7 @@
 #include "lldb/Utility/State.h"
 
 #include "Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.h"
+#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
 
 //#define ENABLE_DEBUG_PRINTF // COMMENT THIS LINE OUT PRIOR TO CHECKIN
 #ifdef ENABLE_DEBUG_PRINTF
index a9e674e7ac2455e1983b13cd03faa8090a167b2d..7bc14061ffe05d07c3fc2e503cdb75e95f19404b 100644 (file)
@@ -11,7 +11,6 @@
 #include "lldb/Core/Module.h"
 #include "lldb/Core/PluginManager.h"
 #include "lldb/Core/Section.h"
-#include "lldb/Symbol/TypeSystemClang.h"
 #include "lldb/Symbol/ObjectFile.h"
 #include "lldb/Symbol/SymbolVendor.h"
 #include "lldb/Target/ABI.h"
@@ -24,6 +23,8 @@
 #include "DynamicLoaderDarwin.h"
 #include "DynamicLoaderMacOS.h"
 
+#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
+
 using namespace lldb;
 using namespace lldb_private;
 
index ce0132d96c3db32f4123bf0a6c64d3255e4b0d14..c3f3643cfe701fd5e77d66a1bf6a97bf82321138 100644 (file)
@@ -12,7 +12,6 @@
 #include "lldb/Core/ModuleSpec.h"
 #include "lldb/Core/PluginManager.h"
 #include "lldb/Core/Section.h"
-#include "lldb/Symbol/TypeSystemClang.h"
 #include "lldb/Symbol/Function.h"
 #include "lldb/Symbol/ObjectFile.h"
 #include "lldb/Target/ABI.h"
@@ -30,6 +29,7 @@
 #include "DynamicLoaderMacOSXDYLD.h"
 
 #include "Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.h"
+#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
 
 //#define ENABLE_DEBUG_PRINTF // COMMENT THIS LINE OUT PRIOR TO CHECKIN
 #ifdef ENABLE_DEBUG_PRINTF
index 7b2acb483abdc2d6f139cf6ee1fcbf1dfb4a9663..f0e1b5dd1d022010cdc8403885b23685350067e1 100644 (file)
@@ -8,10 +8,10 @@
 
 #include "ASTResultSynthesizer.h"
 
+#include "ClangASTImporter.h"
 #include "ClangPersistentVariables.h"
 
-#include "lldb/Symbol/TypeSystemClang.h"
-#include "lldb/Symbol/ClangASTImporter.h"
+#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
 #include "lldb/Target/Target.h"
 #include "lldb/Utility/LLDBAssert.h"
 #include "lldb/Utility/Log.h"
index e92d089cab1084a052a237bf43f4528a2bfdc744..3bb120a48e90bda292ddd5b9fd523a336f428fb4 100644 (file)
@@ -6,19 +6,24 @@ add_lldb_library(lldbPluginExpressionParserClang PLUGIN
   ASTResultSynthesizer.cpp
   ASTStructExtractor.cpp
   ASTUtils.cpp
+  ClangASTImporter.cpp
+  ClangASTMetadata.cpp
   ClangASTSource.cpp
   ClangDeclVendor.cpp
   ClangExpressionDeclMap.cpp
   ClangExpressionParser.cpp
   ClangExpressionSourceCode.cpp
   ClangExpressionVariable.cpp
+  ClangExternalASTSourceCallbacks.cpp
   ClangFunctionCaller.cpp
   ClangHost.cpp
   ClangModulesDeclVendor.cpp
   ClangPersistentVariables.cpp
   ClangUserExpression.cpp
+  ClangUtil.cpp
   ClangUtilityFunction.cpp
   CppModuleConfiguration.cpp
+  CxxModuleHandler.cpp
   IRForTarget.cpp
   IRDynamicChecks.cpp
 
@@ -35,6 +40,8 @@ add_lldb_library(lldbPluginExpressionParserClang PLUGIN
     lldbUtility
     lldbPluginCPlusPlusLanguage
     lldbPluginCPPRuntime
+    lldbPluginObjCRuntime
+    lldbPluginTypeSystemClang
   CLANG_LIBS
     clangAST
     clangCodeGen
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangASTImporter.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangASTImporter.cpp
new file mode 100644 (file)
index 0000000..479cb64
--- /dev/null
@@ -0,0 +1,1152 @@
+//===-- ClangASTImporter.cpp ----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Core/Module.h"
+#include "lldb/Utility/LLDBAssert.h"
+#include "lldb/Utility/Log.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/Sema/Lookup.h"
+#include "clang/Sema/Sema.h"
+#include "llvm/Support/raw_ostream.h"
+
+#include "Plugins/ExpressionParser/Clang/ClangASTImporter.h"
+#include "Plugins/ExpressionParser/Clang/ClangASTMetadata.h"
+#include "Plugins/ExpressionParser/Clang/ClangUtil.h"
+#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
+
+#include <memory>
+
+using namespace lldb_private;
+using namespace clang;
+
+CompilerType ClangASTImporter::CopyType(TypeSystemClang &dst_ast,
+                                        const CompilerType &src_type) {
+  clang::ASTContext &dst_clang_ast = dst_ast.getASTContext();
+
+  TypeSystemClang *src_ast =
+      llvm::dyn_cast_or_null<TypeSystemClang>(src_type.GetTypeSystem());
+  if (!src_ast)
+    return CompilerType();
+
+  clang::ASTContext &src_clang_ast = src_ast->getASTContext();
+
+  clang::QualType src_qual_type = ClangUtil::GetQualType(src_type);
+
+  ImporterDelegateSP delegate_sp(GetDelegate(&dst_clang_ast, &src_clang_ast));
+  if (!delegate_sp)
+    return CompilerType();
+
+  ASTImporterDelegate::CxxModuleScope std_scope(*delegate_sp, &dst_clang_ast);
+
+  llvm::Expected<QualType> ret_or_error = delegate_sp->Import(src_qual_type);
+  if (!ret_or_error) {
+    Log *log =
+      lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS);
+    LLDB_LOG_ERROR(log, ret_or_error.takeError(),
+        "Couldn't import type: {0}");
+    return CompilerType();
+  }
+
+  lldb::opaque_compiler_type_t dst_clang_type = ret_or_error->getAsOpaquePtr();
+
+  if (dst_clang_type)
+    return CompilerType(&dst_ast, dst_clang_type);
+  return CompilerType();
+}
+
+clang::Decl *ClangASTImporter::CopyDecl(clang::ASTContext *dst_ast,
+                                        clang::Decl *decl) {
+  ImporterDelegateSP delegate_sp;
+
+  clang::ASTContext *src_ast = &decl->getASTContext();
+  delegate_sp = GetDelegate(dst_ast, src_ast);
+
+  ASTImporterDelegate::CxxModuleScope std_scope(*delegate_sp, dst_ast);
+
+  if (!delegate_sp)
+    return nullptr;
+
+  llvm::Expected<clang::Decl *> result = delegate_sp->Import(decl);
+  if (!result) {
+    Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
+    LLDB_LOG_ERROR(log, result.takeError(), "Couldn't import decl: {0}");
+    if (log) {
+      lldb::user_id_t user_id = LLDB_INVALID_UID;
+      ClangASTMetadata *metadata = GetDeclMetadata(decl);
+      if (metadata)
+        user_id = metadata->GetUserID();
+
+      if (NamedDecl *named_decl = dyn_cast<NamedDecl>(decl))
+        LLDB_LOG(log,
+                 "  [ClangASTImporter] WARNING: Failed to import a {0} "
+                 "'{1}', metadata {2}",
+                 decl->getDeclKindName(), named_decl->getNameAsString(),
+                 user_id);
+      else
+        LLDB_LOG(log,
+                 "  [ClangASTImporter] WARNING: Failed to import a {0}, "
+                 "metadata {1}",
+                 decl->getDeclKindName(), user_id);
+    }
+    return nullptr;
+  }
+
+  return *result;
+}
+
+class DeclContextOverride {
+private:
+  struct Backup {
+    clang::DeclContext *decl_context;
+    clang::DeclContext *lexical_decl_context;
+  };
+
+  llvm::DenseMap<clang::Decl *, Backup> m_backups;
+
+  void OverrideOne(clang::Decl *decl) {
+    if (m_backups.find(decl) != m_backups.end()) {
+      return;
+    }
+
+    m_backups[decl] = {decl->getDeclContext(), decl->getLexicalDeclContext()};
+
+    decl->setDeclContext(decl->getASTContext().getTranslationUnitDecl());
+    decl->setLexicalDeclContext(decl->getASTContext().getTranslationUnitDecl());
+  }
+
+  bool ChainPassesThrough(
+      clang::Decl *decl, clang::DeclContext *base,
+      clang::DeclContext *(clang::Decl::*contextFromDecl)(),
+      clang::DeclContext *(clang::DeclContext::*contextFromContext)()) {
+    for (DeclContext *decl_ctx = (decl->*contextFromDecl)(); decl_ctx;
+         decl_ctx = (decl_ctx->*contextFromContext)()) {
+      if (decl_ctx == base) {
+        return true;
+      }
+    }
+
+    return false;
+  }
+
+  clang::Decl *GetEscapedChild(clang::Decl *decl,
+                               clang::DeclContext *base = nullptr) {
+    if (base) {
+      // decl's DeclContext chains must pass through base.
+
+      if (!ChainPassesThrough(decl, base, &clang::Decl::getDeclContext,
+                              &clang::DeclContext::getParent) ||
+          !ChainPassesThrough(decl, base, &clang::Decl::getLexicalDeclContext,
+                              &clang::DeclContext::getLexicalParent)) {
+        return decl;
+      }
+    } else {
+      base = clang::dyn_cast<clang::DeclContext>(decl);
+
+      if (!base) {
+        return nullptr;
+      }
+    }
+
+    if (clang::DeclContext *context =
+            clang::dyn_cast<clang::DeclContext>(decl)) {
+      for (clang::Decl *decl : context->decls()) {
+        if (clang::Decl *escaped_child = GetEscapedChild(decl)) {
+          return escaped_child;
+        }
+      }
+    }
+
+    return nullptr;
+  }
+
+  void Override(clang::Decl *decl) {
+    if (clang::Decl *escaped_child = GetEscapedChild(decl)) {
+      Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
+
+      LLDB_LOG(log,
+               "    [ClangASTImporter] DeclContextOverride couldn't "
+               "override ({0}Decl*){1} - its child ({2}Decl*){3} escapes",
+               decl->getDeclKindName(), decl, escaped_child->getDeclKindName(),
+               escaped_child);
+      lldbassert(0 && "Couldn't override!");
+    }
+
+    OverrideOne(decl);
+  }
+
+public:
+  DeclContextOverride() {}
+
+  void OverrideAllDeclsFromContainingFunction(clang::Decl *decl) {
+    for (DeclContext *decl_context = decl->getLexicalDeclContext();
+         decl_context; decl_context = decl_context->getLexicalParent()) {
+      DeclContext *redecl_context = decl_context->getRedeclContext();
+
+      if (llvm::isa<FunctionDecl>(redecl_context) &&
+          llvm::isa<TranslationUnitDecl>(redecl_context->getLexicalParent())) {
+        for (clang::Decl *child_decl : decl_context->decls()) {
+          Override(child_decl);
+        }
+      }
+    }
+  }
+
+  ~DeclContextOverride() {
+    for (const std::pair<clang::Decl *, Backup> &backup : m_backups) {
+      backup.first->setDeclContext(backup.second.decl_context);
+      backup.first->setLexicalDeclContext(backup.second.lexical_decl_context);
+    }
+  }
+};
+
+namespace {
+/// Completes all imported TagDecls at the end of the scope.
+///
+/// While in a CompleteTagDeclsScope, every decl that could be completed will
+/// be completed at the end of the scope (including all Decls that are
+/// imported while completing the original Decls).
+class CompleteTagDeclsScope : public ClangASTImporter::NewDeclListener {
+  ClangASTImporter::ImporterDelegateSP m_delegate;
+  llvm::SmallVector<NamedDecl *, 32> m_decls_to_complete;
+  llvm::SmallPtrSet<NamedDecl *, 32> m_decls_already_completed;
+  clang::ASTContext *m_dst_ctx;
+  clang::ASTContext *m_src_ctx;
+  ClangASTImporter &importer;
+
+public:
+  /// Constructs a CompleteTagDeclsScope.
+  /// \param importer The ClangASTImporter that we should observe.
+  /// \param dst_ctx The ASTContext to which Decls are imported.
+  /// \param src_ctx The ASTContext from which Decls are imported.
+  explicit CompleteTagDeclsScope(ClangASTImporter &importer,
+                            clang::ASTContext *dst_ctx,
+                            clang::ASTContext *src_ctx)
+      : m_delegate(importer.GetDelegate(dst_ctx, src_ctx)), m_dst_ctx(dst_ctx),
+        m_src_ctx(src_ctx), importer(importer) {
+    m_delegate->SetImportListener(this);
+  }
+
+  virtual ~CompleteTagDeclsScope() {
+    ClangASTImporter::ASTContextMetadataSP to_context_md =
+        importer.GetContextMetadata(m_dst_ctx);
+
+    // Complete all decls we collected until now.
+    while (!m_decls_to_complete.empty()) {
+      NamedDecl *decl = m_decls_to_complete.pop_back_val();
+      m_decls_already_completed.insert(decl);
+
+      // We should only complete decls coming from the source context.
+      assert(to_context_md->m_origins[decl].ctx == m_src_ctx);
+
+      Decl *original_decl = to_context_md->m_origins[decl].decl;
+
+      // Complete the decl now.
+      TypeSystemClang::GetCompleteDecl(m_src_ctx, original_decl);
+      if (auto *tag_decl = dyn_cast<TagDecl>(decl)) {
+        if (auto *original_tag_decl = dyn_cast<TagDecl>(original_decl)) {
+          if (original_tag_decl->isCompleteDefinition()) {
+            m_delegate->ImportDefinitionTo(tag_decl, original_tag_decl);
+            tag_decl->setCompleteDefinition(true);
+          }
+        }
+
+        tag_decl->setHasExternalLexicalStorage(false);
+        tag_decl->setHasExternalVisibleStorage(false);
+      } else if (auto *container_decl = dyn_cast<ObjCContainerDecl>(decl)) {
+        container_decl->setHasExternalLexicalStorage(false);
+        container_decl->setHasExternalVisibleStorage(false);
+      }
+
+      to_context_md->m_origins.erase(decl);
+    }
+
+    // Stop listening to imported decls. We do this after clearing the
+    // Decls we needed to import to catch all Decls they might have pulled in.
+    m_delegate->RemoveImportListener();
+  }
+
+  void NewDeclImported(clang::Decl *from, clang::Decl *to) override {
+    // Filter out decls that we can't complete later.
+    if (!isa<TagDecl>(to) && !isa<ObjCInterfaceDecl>(to))
+      return;
+    RecordDecl *from_record_decl = dyn_cast<RecordDecl>(from);
+    // We don't need to complete injected class name decls.
+    if (from_record_decl && from_record_decl->isInjectedClassName())
+      return;
+
+    NamedDecl *to_named_decl = dyn_cast<NamedDecl>(to);
+    // Check if we already completed this type.
+    if (m_decls_already_completed.count(to_named_decl) != 0)
+      return;
+    m_decls_to_complete.push_back(to_named_decl);
+  }
+};
+} // namespace
+
+CompilerType ClangASTImporter::DeportType(TypeSystemClang &dst,
+                                          const CompilerType &src_type) {
+  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
+
+  TypeSystemClang *src_ctxt =
+      llvm::cast<TypeSystemClang>(src_type.GetTypeSystem());
+
+  LLDB_LOG(log,
+           "    [ClangASTImporter] DeportType called on ({0}Type*){1} "
+           "from (ASTContext*){2} to (ASTContext*){3}",
+           src_type.GetTypeName(), src_type.GetOpaqueQualType(),
+           &src_ctxt->getASTContext(), &dst.getASTContext());
+
+  DeclContextOverride decl_context_override;
+
+  if (auto *t = ClangUtil::GetQualType(src_type)->getAs<TagType>())
+    decl_context_override.OverrideAllDeclsFromContainingFunction(t->getDecl());
+
+  CompleteTagDeclsScope complete_scope(*this, &dst.getASTContext(),
+                                       &src_ctxt->getASTContext());
+  return CopyType(dst, src_type);
+}
+
+clang::Decl *ClangASTImporter::DeportDecl(clang::ASTContext *dst_ctx,
+                                          clang::Decl *decl) {
+  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
+
+  clang::ASTContext *src_ctx = &decl->getASTContext();
+  LLDB_LOG(log,
+           "    [ClangASTImporter] DeportDecl called on ({0}Decl*){1} from "
+           "(ASTContext*){2} to (ASTContext*){3}",
+           decl->getDeclKindName(), decl, src_ctx, dst_ctx);
+
+  DeclContextOverride decl_context_override;
+
+  decl_context_override.OverrideAllDeclsFromContainingFunction(decl);
+
+  clang::Decl *result;
+  {
+    CompleteTagDeclsScope complete_scope(*this, dst_ctx, src_ctx);
+    result = CopyDecl(dst_ctx, decl);
+  }
+
+  if (!result)
+    return nullptr;
+
+  LLDB_LOG(log,
+           "    [ClangASTImporter] DeportDecl deported ({0}Decl*){1} to "
+           "({2}Decl*){3}",
+           decl->getDeclKindName(), decl, result->getDeclKindName(), result);
+
+  return result;
+}
+
+bool ClangASTImporter::CanImport(const CompilerType &type) {
+  if (!ClangUtil::IsClangType(type))
+    return false;
+
+  // TODO: remove external completion BOOL
+  // CompleteAndFetchChildren should get the Decl out and check for the
+
+  clang::QualType qual_type(
+      ClangUtil::GetCanonicalQualType(ClangUtil::RemoveFastQualifiers(type)));
+
+  const clang::Type::TypeClass type_class = qual_type->getTypeClass();
+  switch (type_class) {
+  case clang::Type::Record: {
+    const clang::CXXRecordDecl *cxx_record_decl =
+        qual_type->getAsCXXRecordDecl();
+    if (cxx_record_decl) {
+      if (GetDeclOrigin(cxx_record_decl).Valid())
+        return true;
+    }
+  } break;
+
+  case clang::Type::Enum: {
+    clang::EnumDecl *enum_decl =
+        llvm::cast<clang::EnumType>(qual_type)->getDecl();
+    if (enum_decl) {
+      if (GetDeclOrigin(enum_decl).Valid())
+        return true;
+    }
+  } break;
+
+  case clang::Type::ObjCObject:
+  case clang::Type::ObjCInterface: {
+    const clang::ObjCObjectType *objc_class_type =
+        llvm::dyn_cast<clang::ObjCObjectType>(qual_type);
+    if (objc_class_type) {
+      clang::ObjCInterfaceDecl *class_interface_decl =
+          objc_class_type->getInterface();
+      // We currently can't complete objective C types through the newly added
+      // ASTContext because it only supports TagDecl objects right now...
+      if (class_interface_decl) {
+        if (GetDeclOrigin(class_interface_decl).Valid())
+          return true;
+      }
+    }
+  } break;
+
+  case clang::Type::Typedef:
+    return CanImport(CompilerType(type.GetTypeSystem(),
+                                  llvm::cast<clang::TypedefType>(qual_type)
+                                      ->getDecl()
+                                      ->getUnderlyingType()
+                                      .getAsOpaquePtr()));
+
+  case clang::Type::Auto:
+    return CanImport(CompilerType(type.GetTypeSystem(),
+                                  llvm::cast<clang::AutoType>(qual_type)
+                                      ->getDeducedType()
+                                      .getAsOpaquePtr()));
+
+  case clang::Type::Elaborated:
+    return CanImport(CompilerType(type.GetTypeSystem(),
+                                  llvm::cast<clang::ElaboratedType>(qual_type)
+                                      ->getNamedType()
+                                      .getAsOpaquePtr()));
+
+  case clang::Type::Paren:
+    return CanImport(CompilerType(
+        type.GetTypeSystem(),
+        llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr()));
+
+  default:
+    break;
+  }
+
+  return false;
+}
+
+bool ClangASTImporter::Import(const CompilerType &type) {
+  if (!ClangUtil::IsClangType(type))
+    return false;
+  // TODO: remove external completion BOOL
+  // CompleteAndFetchChildren should get the Decl out and check for the
+
+  clang::QualType qual_type(
+      ClangUtil::GetCanonicalQualType(ClangUtil::RemoveFastQualifiers(type)));
+
+  const clang::Type::TypeClass type_class = qual_type->getTypeClass();
+  switch (type_class) {
+  case clang::Type::Record: {
+    const clang::CXXRecordDecl *cxx_record_decl =
+        qual_type->getAsCXXRecordDecl();
+    if (cxx_record_decl) {
+      if (GetDeclOrigin(cxx_record_decl).Valid())
+        return CompleteAndFetchChildren(qual_type);
+    }
+  } break;
+
+  case clang::Type::Enum: {
+    clang::EnumDecl *enum_decl =
+        llvm::cast<clang::EnumType>(qual_type)->getDecl();
+    if (enum_decl) {
+      if (GetDeclOrigin(enum_decl).Valid())
+        return CompleteAndFetchChildren(qual_type);
+    }
+  } break;
+
+  case clang::Type::ObjCObject:
+  case clang::Type::ObjCInterface: {
+    const clang::ObjCObjectType *objc_class_type =
+        llvm::dyn_cast<clang::ObjCObjectType>(qual_type);
+    if (objc_class_type) {
+      clang::ObjCInterfaceDecl *class_interface_decl =
+          objc_class_type->getInterface();
+      // We currently can't complete objective C types through the newly added
+      // ASTContext because it only supports TagDecl objects right now...
+      if (class_interface_decl) {
+        if (GetDeclOrigin(class_interface_decl).Valid())
+          return CompleteAndFetchChildren(qual_type);
+      }
+    }
+  } break;
+
+  case clang::Type::Typedef:
+    return Import(CompilerType(type.GetTypeSystem(),
+                               llvm::cast<clang::TypedefType>(qual_type)
+                                   ->getDecl()
+                                   ->getUnderlyingType()
+                                   .getAsOpaquePtr()));
+
+  case clang::Type::Auto:
+    return Import(CompilerType(type.GetTypeSystem(),
+                               llvm::cast<clang::AutoType>(qual_type)
+                                   ->getDeducedType()
+                                   .getAsOpaquePtr()));
+
+  case clang::Type::Elaborated:
+    return Import(CompilerType(type.GetTypeSystem(),
+                               llvm::cast<clang::ElaboratedType>(qual_type)
+                                   ->getNamedType()
+                                   .getAsOpaquePtr()));
+
+  case clang::Type::Paren:
+    return Import(CompilerType(
+        type.GetTypeSystem(),
+        llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr()));
+
+  default:
+    break;
+  }
+  return false;
+}
+
+bool ClangASTImporter::CompleteType(const CompilerType &compiler_type) {
+  if (!CanImport(compiler_type))
+    return false;
+
+  if (Import(compiler_type)) {
+    TypeSystemClang::CompleteTagDeclarationDefinition(compiler_type);
+    return true;
+  }
+
+  TypeSystemClang::SetHasExternalStorage(compiler_type.GetOpaqueQualType(),
+                                         false);
+  return false;
+}
+
+bool ClangASTImporter::LayoutRecordType(
+    const clang::RecordDecl *record_decl, uint64_t &bit_size,
+    uint64_t &alignment,
+    llvm::DenseMap<const clang::FieldDecl *, uint64_t> &field_offsets,
+    llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits>
+        &base_offsets,
+    llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits>
+        &vbase_offsets) {
+  RecordDeclToLayoutMap::iterator pos =
+      m_record_decl_to_layout_map.find(record_decl);
+  bool success = false;
+  base_offsets.clear();
+  vbase_offsets.clear();
+  if (pos != m_record_decl_to_layout_map.end()) {
+    bit_size = pos->second.bit_size;
+    alignment = pos->second.alignment;
+    field_offsets.swap(pos->second.field_offsets);
+    base_offsets.swap(pos->second.base_offsets);
+    vbase_offsets.swap(pos->second.vbase_offsets);
+    m_record_decl_to_layout_map.erase(pos);
+    success = true;
+  } else {
+    bit_size = 0;
+    alignment = 0;
+    field_offsets.clear();
+  }
+  return success;
+}
+
+void ClangASTImporter::SetRecordLayout(clang::RecordDecl *decl,
+                                        const LayoutInfo &layout) {
+  m_record_decl_to_layout_map.insert(std::make_pair(decl, layout));
+}
+
+bool ClangASTImporter::CompleteTagDecl(clang::TagDecl *decl) {
+  DeclOrigin decl_origin = GetDeclOrigin(decl);
+
+  if (!decl_origin.Valid())
+    return false;
+
+  if (!TypeSystemClang::GetCompleteDecl(decl_origin.ctx, decl_origin.decl))
+    return false;
+
+  ImporterDelegateSP delegate_sp(
+      GetDelegate(&decl->getASTContext(), decl_origin.ctx));
+
+  ASTImporterDelegate::CxxModuleScope std_scope(*delegate_sp,
+                                                &decl->getASTContext());
+  if (delegate_sp)
+    delegate_sp->ImportDefinitionTo(decl, decl_origin.decl);
+
+  return true;
+}
+
+bool ClangASTImporter::CompleteTagDeclWithOrigin(clang::TagDecl *decl,
+                                                 clang::TagDecl *origin_decl) {
+  clang::ASTContext *origin_ast_ctx = &origin_decl->getASTContext();
+
+  if (!TypeSystemClang::GetCompleteDecl(origin_ast_ctx, origin_decl))
+    return false;
+
+  ImporterDelegateSP delegate_sp(
+      GetDelegate(&decl->getASTContext(), origin_ast_ctx));
+
+  if (delegate_sp)
+    delegate_sp->ImportDefinitionTo(decl, origin_decl);
+
+  ASTContextMetadataSP context_md = GetContextMetadata(&decl->getASTContext());
+
+  OriginMap &origins = context_md->m_origins;
+
+  origins[decl] = DeclOrigin(origin_ast_ctx, origin_decl);
+
+  return true;
+}
+
+bool ClangASTImporter::CompleteObjCInterfaceDecl(
+    clang::ObjCInterfaceDecl *interface_decl) {
+  DeclOrigin decl_origin = GetDeclOrigin(interface_decl);
+
+  if (!decl_origin.Valid())
+    return false;
+
+  if (!TypeSystemClang::GetCompleteDecl(decl_origin.ctx, decl_origin.decl))
+    return false;
+
+  ImporterDelegateSP delegate_sp(
+      GetDelegate(&interface_decl->getASTContext(), decl_origin.ctx));
+
+  if (delegate_sp)
+    delegate_sp->ImportDefinitionTo(interface_decl, decl_origin.decl);
+
+  if (ObjCInterfaceDecl *super_class = interface_decl->getSuperClass())
+    RequireCompleteType(clang::QualType(super_class->getTypeForDecl(), 0));
+
+  return true;
+}
+
+bool ClangASTImporter::CompleteAndFetchChildren(clang::QualType type) {
+  if (!RequireCompleteType(type))
+    return false;
+
+  Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS);
+
+  if (const TagType *tag_type = type->getAs<TagType>()) {
+    TagDecl *tag_decl = tag_type->getDecl();
+
+    DeclOrigin decl_origin = GetDeclOrigin(tag_decl);
+
+    if (!decl_origin.Valid())
+      return false;
+
+    ImporterDelegateSP delegate_sp(
+        GetDelegate(&tag_decl->getASTContext(), decl_origin.ctx));
+
+    ASTImporterDelegate::CxxModuleScope std_scope(*delegate_sp,
+                                                  &tag_decl->getASTContext());
+
+    TagDecl *origin_tag_decl = llvm::dyn_cast<TagDecl>(decl_origin.decl);
+
+    for (Decl *origin_child_decl : origin_tag_decl->decls()) {
+      llvm::Expected<Decl *> imported_or_err =
+          delegate_sp->Import(origin_child_decl);
+      if (!imported_or_err) {
+        LLDB_LOG_ERROR(log, imported_or_err.takeError(),
+                       "Couldn't import decl: {0}");
+        return false;
+      }
+    }
+
+    if (RecordDecl *record_decl = dyn_cast<RecordDecl>(origin_tag_decl))
+      record_decl->setHasLoadedFieldsFromExternalStorage(true);
+
+    return true;
+  }
+
+  if (const ObjCObjectType *objc_object_type = type->getAs<ObjCObjectType>()) {
+    if (ObjCInterfaceDecl *objc_interface_decl =
+            objc_object_type->getInterface()) {
+      DeclOrigin decl_origin = GetDeclOrigin(objc_interface_decl);
+
+      if (!decl_origin.Valid())
+        return false;
+
+      ImporterDelegateSP delegate_sp(
+          GetDelegate(&objc_interface_decl->getASTContext(), decl_origin.ctx));
+
+      ObjCInterfaceDecl *origin_interface_decl =
+          llvm::dyn_cast<ObjCInterfaceDecl>(decl_origin.decl);
+
+      for (Decl *origin_child_decl : origin_interface_decl->decls()) {
+        llvm::Expected<Decl *> imported_or_err =
+            delegate_sp->Import(origin_child_decl);
+        if (!imported_or_err) {
+          LLDB_LOG_ERROR(log, imported_or_err.takeError(),
+                         "Couldn't import decl: {0}");
+          return false;
+        }
+      }
+
+      return true;
+    }
+    return false;
+  }
+
+  return true;
+}
+
+bool ClangASTImporter::RequireCompleteType(clang::QualType type) {
+  if (type.isNull())
+    return false;
+
+  if (const TagType *tag_type = type->getAs<TagType>()) {
+    TagDecl *tag_decl = tag_type->getDecl();
+
+    if (tag_decl->getDefinition() || tag_decl->isBeingDefined())
+      return true;
+
+    return CompleteTagDecl(tag_decl);
+  }
+  if (const ObjCObjectType *objc_object_type = type->getAs<ObjCObjectType>()) {
+    if (ObjCInterfaceDecl *objc_interface_decl =
+            objc_object_type->getInterface())
+      return CompleteObjCInterfaceDecl(objc_interface_decl);
+    return false;
+  }
+  if (const ArrayType *array_type = type->getAsArrayTypeUnsafe())
+    return RequireCompleteType(array_type->getElementType());
+  if (const AtomicType *atomic_type = type->getAs<AtomicType>())
+    return RequireCompleteType(atomic_type->getPointeeType());
+
+  return true;
+}
+
+ClangASTMetadata *ClangASTImporter::GetDeclMetadata(const clang::Decl *decl) {
+  DeclOrigin decl_origin = GetDeclOrigin(decl);
+
+  if (decl_origin.Valid()) {
+    TypeSystemClang *ast = TypeSystemClang::GetASTContext(decl_origin.ctx);
+    return ast->GetMetadata(decl_origin.decl);
+  }
+  TypeSystemClang *ast = TypeSystemClang::GetASTContext(&decl->getASTContext());
+  return ast->GetMetadata(decl);
+}
+
+ClangASTImporter::DeclOrigin
+ClangASTImporter::GetDeclOrigin(const clang::Decl *decl) {
+  ASTContextMetadataSP context_md = GetContextMetadata(&decl->getASTContext());
+
+  OriginMap &origins = context_md->m_origins;
+
+  OriginMap::iterator iter = origins.find(decl);
+
+  if (iter != origins.end())
+    return iter->second;
+  return DeclOrigin();
+}
+
+void ClangASTImporter::SetDeclOrigin(const clang::Decl *decl,
+                                     clang::Decl *original_decl) {
+  ASTContextMetadataSP context_md = GetContextMetadata(&decl->getASTContext());
+
+  OriginMap &origins = context_md->m_origins;
+
+  OriginMap::iterator iter = origins.find(decl);
+
+  if (iter != origins.end()) {
+    iter->second.decl = original_decl;
+    iter->second.ctx = &original_decl->getASTContext();
+    return;
+  }
+  origins[decl] = DeclOrigin(&original_decl->getASTContext(), original_decl);
+}
+
+void ClangASTImporter::RegisterNamespaceMap(const clang::NamespaceDecl *decl,
+                                            NamespaceMapSP &namespace_map) {
+  ASTContextMetadataSP context_md = GetContextMetadata(&decl->getASTContext());
+
+  context_md->m_namespace_maps[decl] = namespace_map;
+}
+
+ClangASTImporter::NamespaceMapSP
+ClangASTImporter::GetNamespaceMap(const clang::NamespaceDecl *decl) {
+  ASTContextMetadataSP context_md = GetContextMetadata(&decl->getASTContext());
+
+  NamespaceMetaMap &namespace_maps = context_md->m_namespace_maps;
+
+  NamespaceMetaMap::iterator iter = namespace_maps.find(decl);
+
+  if (iter != namespace_maps.end())
+    return iter->second;
+  return NamespaceMapSP();
+}
+
+void ClangASTImporter::BuildNamespaceMap(const clang::NamespaceDecl *decl) {
+  assert(decl);
+  ASTContextMetadataSP context_md = GetContextMetadata(&decl->getASTContext());
+
+  const DeclContext *parent_context = decl->getDeclContext();
+  const NamespaceDecl *parent_namespace =
+      dyn_cast<NamespaceDecl>(parent_context);
+  NamespaceMapSP parent_map;
+
+  if (parent_namespace)
+    parent_map = GetNamespaceMap(parent_namespace);
+
+  NamespaceMapSP new_map;
+
+  new_map = std::make_shared<NamespaceMap>();
+
+  if (context_md->m_map_completer) {
+    std::string namespace_string = decl->getDeclName().getAsString();
+
+    context_md->m_map_completer->CompleteNamespaceMap(
+        new_map, ConstString(namespace_string.c_str()), parent_map);
+  }
+
+  context_md->m_namespace_maps[decl] = new_map;
+}
+
+void ClangASTImporter::ForgetDestination(clang::ASTContext *dst_ast) {
+  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
+
+  LLDB_LOG(log,
+           "    [ClangASTImporter] Forgetting destination (ASTContext*){0}",
+           dst_ast);
+
+  m_metadata_map.erase(dst_ast);
+}
+
+void ClangASTImporter::ForgetSource(clang::ASTContext *dst_ast,
+                                    clang::ASTContext *src_ast) {
+  ASTContextMetadataSP md = MaybeGetContextMetadata(dst_ast);
+
+  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
+
+  LLDB_LOG(log,
+           "    [ClangASTImporter] Forgetting source->dest "
+           "(ASTContext*){0}->(ASTContext*){1}",
+           src_ast, dst_ast);
+
+  if (!md)
+    return;
+
+  md->m_delegates.erase(src_ast);
+
+  for (OriginMap::iterator iter = md->m_origins.begin();
+       iter != md->m_origins.end();) {
+    if (iter->second.ctx == src_ast)
+      md->m_origins.erase(iter++);
+    else
+      ++iter;
+  }
+}
+
+ClangASTImporter::MapCompleter::~MapCompleter() { return; }
+
+llvm::Expected<Decl *>
+ClangASTImporter::ASTImporterDelegate::ImportImpl(Decl *From) {
+  if (m_std_handler) {
+    llvm::Optional<Decl *> D = m_std_handler->Import(From);
+    if (D) {
+      // Make sure we don't use this decl later to map it back to it's original
+      // decl. The decl the CxxModuleHandler created has nothing to do with
+      // the one from debug info, and linking those two would just cause the
+      // ASTImporter to try 'updating' the module decl with the minimal one from
+      // the debug info.
+      m_decls_to_ignore.insert(*D);
+      return *D;
+    }
+  }
+
+  // Check which ASTContext this declaration originally came from.
+  DeclOrigin origin = m_master.GetDeclOrigin(From);
+  // If it originally came from the target ASTContext then we can just
+  // pretend that the original is the one we imported. This can happen for
+  // example when inspecting a persistent declaration from the scratch
+  // ASTContext (which will provide the declaration when parsing the
+  // expression and then we later try to copy the declaration back to the
+  // scratch ASTContext to store the result).
+  // Without this check we would ask the ASTImporter to import a declaration
+  // into the same ASTContext where it came from (which doesn't make a lot of
+  // sense).
+  if (origin.Valid() && origin.ctx == &getToContext()) {
+    RegisterImportedDecl(From, origin.decl);
+    return origin.decl;
+  }
+
+  // This declaration came originally from another ASTContext. Instead of
+  // copying our potentially incomplete 'From' Decl we instead go to the
+  // original ASTContext and copy the original to the target. This is not
+  // only faster than first completing our current decl and then copying it
+  // to the target, but it also prevents that indirectly copying the same
+  // declaration to the same target requires the ASTImporter to merge all
+  // the different decls that appear to come from different ASTContexts (even
+  // though all these different source ASTContexts just got a copy from
+  // one source AST).
+  if (origin.Valid()) {
+    auto R = m_master.CopyDecl(&getToContext(), origin.decl);
+    if (R) {
+      RegisterImportedDecl(From, R);
+      return R;
+    }
+  }
+
+  return ASTImporter::ImportImpl(From);
+}
+
+void ClangASTImporter::ASTImporterDelegate::ImportDefinitionTo(
+    clang::Decl *to, clang::Decl *from) {
+  // We might have a forward declaration from a shared library that we
+  // gave external lexical storage so that Clang asks us about the full
+  // definition when it needs it. In this case the ASTImporter isn't aware
+  // that the forward decl from the shared library is the actual import
+  // target but would create a second declaration that would then be defined.
+  // We want that 'to' is actually complete after this function so let's
+  // tell the ASTImporter that 'to' was imported from 'from'.
+  MapImported(from, to);
+  ASTImporter::Imported(from, to);
+
+  /*
+  if (to_objc_interface)
+      to_objc_interface->startDefinition();
+
+  CXXRecordDecl *to_cxx_record = dyn_cast<CXXRecordDecl>(to);
+
+  if (to_cxx_record)
+      to_cxx_record->startDefinition();
+  */
+
+  Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS);
+
+  if (llvm::Error err = ImportDefinition(from)) {
+    LLDB_LOG_ERROR(log, std::move(err),
+                   "[ClangASTImporter] Error during importing definition: {0}");
+    return;
+  }
+
+  if (clang::TagDecl *to_tag = dyn_cast<clang::TagDecl>(to)) {
+    if (clang::TagDecl *from_tag = dyn_cast<clang::TagDecl>(from)) {
+      to_tag->setCompleteDefinition(from_tag->isCompleteDefinition());
+
+      if (Log *log_ast =
+              lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_AST)) {
+        std::string name_string;
+        if (NamedDecl *from_named_decl = dyn_cast<clang::NamedDecl>(from)) {
+          llvm::raw_string_ostream name_stream(name_string);
+          from_named_decl->printName(name_stream);
+          name_stream.flush();
+        }
+        LLDB_LOG(log_ast, "==== [ClangASTImporter][TUDecl: {0}] Imported "
+                          "({1}Decl*){2}, named {3} (from "
+                          "(Decl*){4})",
+                 static_cast<void *>(to->getTranslationUnitDecl()),
+                 from->getDeclKindName(), static_cast<void *>(to), name_string,
+                 static_cast<void *>(from));
+
+        // Log the AST of the TU.
+        std::string ast_string;
+        llvm::raw_string_ostream ast_stream(ast_string);
+        to->getTranslationUnitDecl()->dump(ast_stream);
+        LLDB_LOG(log_ast, "{0}", ast_string);
+      }
+    }
+  }
+
+  // If we're dealing with an Objective-C class, ensure that the inheritance
+  // has been set up correctly.  The ASTImporter may not do this correctly if
+  // the class was originally sourced from symbols.
+
+  if (ObjCInterfaceDecl *to_objc_interface = dyn_cast<ObjCInterfaceDecl>(to)) {
+    do {
+      ObjCInterfaceDecl *to_superclass = to_objc_interface->getSuperClass();
+
+      if (to_superclass)
+        break; // we're not going to override it if it's set
+
+      ObjCInterfaceDecl *from_objc_interface =
+          dyn_cast<ObjCInterfaceDecl>(from);
+
+      if (!from_objc_interface)
+        break;
+
+      ObjCInterfaceDecl *from_superclass = from_objc_interface->getSuperClass();
+
+      if (!from_superclass)
+        break;
+
+      llvm::Expected<Decl *> imported_from_superclass_decl =
+          Import(from_superclass);
+
+      if (!imported_from_superclass_decl) {
+        LLDB_LOG_ERROR(log, imported_from_superclass_decl.takeError(),
+                       "Couldn't import decl: {0}");
+        break;
+      }
+
+      ObjCInterfaceDecl *imported_from_superclass =
+          dyn_cast<ObjCInterfaceDecl>(*imported_from_superclass_decl);
+
+      if (!imported_from_superclass)
+        break;
+
+      if (!to_objc_interface->hasDefinition())
+        to_objc_interface->startDefinition();
+
+      to_objc_interface->setSuperClass(m_source_ctx->getTrivialTypeSourceInfo(
+          m_source_ctx->getObjCInterfaceType(imported_from_superclass)));
+    } while (false);
+  }
+}
+
+/// Takes a CXXMethodDecl and completes the return type if necessary. This
+/// is currently only necessary for virtual functions with covariant return
+/// types where Clang's CodeGen expects that the underlying records are already
+/// completed.
+static void MaybeCompleteReturnType(ClangASTImporter &importer,
+                                        CXXMethodDecl *to_method) {
+  if (!to_method->isVirtual())
+    return;
+  QualType return_type = to_method->getReturnType();
+  if (!return_type->isPointerType() && !return_type->isReferenceType())
+    return;
+
+  clang::RecordDecl *rd = return_type->getPointeeType()->getAsRecordDecl();
+  if (!rd)
+    return;
+
+  importer.CompleteTagDecl(rd);
+}
+
+void ClangASTImporter::ASTImporterDelegate::Imported(clang::Decl *from,
+                                                     clang::Decl *to) {
+  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
+
+  // Some decls shouldn't be tracked here because they were not created by
+  // copying 'from' to 'to'. Just exit early for those.
+  if (m_decls_to_ignore.find(to) != m_decls_to_ignore.end())
+    return clang::ASTImporter::Imported(from, to);
+
+  lldb::user_id_t user_id = LLDB_INVALID_UID;
+  ClangASTMetadata *metadata = m_master.GetDeclMetadata(from);
+  if (metadata)
+    user_id = metadata->GetUserID();
+
+  if (log) {
+    if (NamedDecl *from_named_decl = dyn_cast<clang::NamedDecl>(from)) {
+      std::string name_string;
+      llvm::raw_string_ostream name_stream(name_string);
+      from_named_decl->printName(name_stream);
+      name_stream.flush();
+
+      LLDB_LOG(log,
+               "    [ClangASTImporter] Imported ({0}Decl*){1}, named {2} (from "
+               "(Decl*){3}), metadata {4}",
+               from->getDeclKindName(), to, name_string, from, user_id);
+    } else {
+      LLDB_LOG(log,
+               "    [ClangASTImporter] Imported ({0}Decl*){1} (from "
+               "(Decl*){2}), metadata {3}",
+               from->getDeclKindName(), to, from, user_id);
+    }
+  }
+
+  ASTContextMetadataSP to_context_md =
+      m_master.GetContextMetadata(&to->getASTContext());
+  ASTContextMetadataSP from_context_md =
+      m_master.MaybeGetContextMetadata(m_source_ctx);
+
+  if (from_context_md) {
+    OriginMap &origins = from_context_md->m_origins;
+
+    OriginMap::iterator origin_iter = origins.find(from);
+
+    if (origin_iter != origins.end()) {
+      if (to_context_md->m_origins.find(to) == to_context_md->m_origins.end() ||
+          user_id != LLDB_INVALID_UID) {
+        if (origin_iter->second.ctx != &to->getASTContext())
+          to_context_md->m_origins[to] = origin_iter->second;
+      }
+
+      ImporterDelegateSP direct_completer =
+          m_master.GetDelegate(&to->getASTContext(), origin_iter->second.ctx);
+
+      if (direct_completer.get() != this)
+        direct_completer->ASTImporter::Imported(origin_iter->second.decl, to);
+
+      LLDB_LOG(log,
+               "    [ClangASTImporter] Propagated origin "
+               "(Decl*){0}/(ASTContext*){1} from (ASTContext*){2} to "
+               "(ASTContext*){3}",
+               origin_iter->second.decl, origin_iter->second.ctx,
+               &from->getASTContext(), &to->getASTContext());
+    } else {
+      if (m_new_decl_listener)
+        m_new_decl_listener->NewDeclImported(from, to);
+
+      if (to_context_md->m_origins.find(to) == to_context_md->m_origins.end() ||
+          user_id != LLDB_INVALID_UID) {
+        to_context_md->m_origins[to] = DeclOrigin(m_source_ctx, from);
+      }
+
+      LLDB_LOG(log,
+               "    [ClangASTImporter] Decl has no origin information in "
+               "(ASTContext*){0}",
+               &from->getASTContext());
+    }
+
+    if (auto *to_namespace = dyn_cast<clang::NamespaceDecl>(to)) {
+      auto *from_namespace = cast<clang::NamespaceDecl>(from);
+
+      NamespaceMetaMap &namespace_maps = from_context_md->m_namespace_maps;
+
+      NamespaceMetaMap::iterator namespace_map_iter =
+          namespace_maps.find(from_namespace);
+
+      if (namespace_map_iter != namespace_maps.end())
+        to_context_md->m_namespace_maps[to_namespace] =
+            namespace_map_iter->second;
+    }
+  } else {
+    to_context_md->m_origins[to] = DeclOrigin(m_source_ctx, from);
+
+    LLDB_LOG(log,
+             "    [ClangASTImporter] Sourced origin "
+             "(Decl*){0}/(ASTContext*){1} into (ASTContext*){2}",
+             from, m_source_ctx, &to->getASTContext());
+  }
+
+  if (auto *to_tag_decl = dyn_cast<TagDecl>(to)) {
+    to_tag_decl->setHasExternalLexicalStorage();
+    to_tag_decl->getPrimaryContext()->setMustBuildLookupTable();
+    auto from_tag_decl = cast<TagDecl>(from);
+
+    LLDB_LOG(
+        log,
+        "    [ClangASTImporter] To is a TagDecl - attributes {0}{1} [{2}->{3}]",
+        (to_tag_decl->hasExternalLexicalStorage() ? " Lexical" : ""),
+        (to_tag_decl->hasExternalVisibleStorage() ? " Visible" : ""),
+        (from_tag_decl->isCompleteDefinition() ? "complete" : "incomplete"),
+        (to_tag_decl->isCompleteDefinition() ? "complete" : "incomplete"));
+  }
+
+  if (auto *to_namespace_decl = dyn_cast<NamespaceDecl>(to)) {
+    m_master.BuildNamespaceMap(to_namespace_decl);
+    to_namespace_decl->setHasExternalVisibleStorage();
+  }
+
+  if (auto *to_container_decl = dyn_cast<ObjCContainerDecl>(to)) {
+    to_container_decl->setHasExternalLexicalStorage();
+    to_container_decl->setHasExternalVisibleStorage();
+
+    if (log) {
+      if (ObjCInterfaceDecl *to_interface_decl =
+              llvm::dyn_cast<ObjCInterfaceDecl>(to_container_decl)) {
+        LLDB_LOG(
+            log,
+            "    [ClangASTImporter] To is an ObjCInterfaceDecl - attributes "
+            "{0}{1}{2}",
+            (to_interface_decl->hasExternalLexicalStorage() ? " Lexical" : ""),
+            (to_interface_decl->hasExternalVisibleStorage() ? " Visible" : ""),
+            (to_interface_decl->hasDefinition() ? " HasDefinition" : ""));
+      } else {
+        LLDB_LOG(
+            log, "    [ClangASTImporter] To is an {0}Decl - attributes {1}{2}",
+            ((Decl *)to_container_decl)->getDeclKindName(),
+            (to_container_decl->hasExternalLexicalStorage() ? " Lexical" : ""),
+            (to_container_decl->hasExternalVisibleStorage() ? " Visible" : ""));
+      }
+    }
+  }
+
+  if (clang::CXXMethodDecl *to_method = dyn_cast<CXXMethodDecl>(to))
+    MaybeCompleteReturnType(m_master, to_method);
+}
+
+clang::Decl *
+ClangASTImporter::ASTImporterDelegate::GetOriginalDecl(clang::Decl *To) {
+  return m_master.GetDeclOrigin(To).decl;
+}
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangASTImporter.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangASTImporter.h
new file mode 100644 (file)
index 0000000..b05a89c
--- /dev/null
@@ -0,0 +1,327 @@
+//===-- ClangASTImporter.h --------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_ClangASTImporter_h_
+#define liblldb_ClangASTImporter_h_
+
+#include <map>
+#include <memory>
+#include <set>
+#include <vector>
+
+#include "clang/AST/ASTImporter.h"
+#include "clang/AST/CharUnits.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/FileSystemOptions.h"
+
+#include "lldb/Host/FileSystem.h"
+#include "lldb/Symbol/CompilerDeclContext.h"
+#include "lldb/lldb-types.h"
+
+#include "Plugins/ExpressionParser/Clang/CxxModuleHandler.h"
+
+#include "llvm/ADT/DenseMap.h"
+
+namespace lldb_private {
+
+class ClangASTImporter {
+public:
+  struct LayoutInfo {
+    LayoutInfo() = default;
+    typedef llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits>
+        OffsetMap;
+
+    uint64_t bit_size = 0;
+    uint64_t alignment = 0;
+    llvm::DenseMap<const clang::FieldDecl *, uint64_t> field_offsets;
+    OffsetMap base_offsets;
+    OffsetMap vbase_offsets;
+  };
+
+  ClangASTImporter()
+      : m_file_manager(clang::FileSystemOptions(),
+                       FileSystem::Instance().GetVirtualFileSystem()) {}
+
+  CompilerType CopyType(TypeSystemClang &dst, const CompilerType &src_type);
+
+  clang::Decl *CopyDecl(clang::ASTContext *dst_ctx, clang::Decl *decl);
+
+  CompilerType DeportType(TypeSystemClang &dst, const CompilerType &src_type);
+
+  clang::Decl *DeportDecl(clang::ASTContext *dst_ctx, clang::Decl *decl);
+
+  /// Sets the layout for the given RecordDecl. The layout will later be
+  /// used by Clang's during code generation. Not calling this function for
+  /// a RecordDecl will cause that Clang's codegen tries to layout the
+  /// record by itself.
+  ///
+  /// \param decl The RecordDecl to set the layout for.
+  /// \param layout The layout for the record.
+  void SetRecordLayout(clang::RecordDecl *decl, const LayoutInfo &layout);
+
+  bool LayoutRecordType(
+      const clang::RecordDecl *record_decl, uint64_t &bit_size,
+      uint64_t &alignment,
+      llvm::DenseMap<const clang::FieldDecl *, uint64_t> &field_offsets,
+      llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits>
+          &base_offsets,
+      llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits>
+          &vbase_offsets);
+
+  bool CanImport(const CompilerType &type);
+
+  bool Import(const CompilerType &type);
+
+  bool CompleteType(const CompilerType &compiler_type);
+
+  bool CompleteTagDecl(clang::TagDecl *decl);
+
+  bool CompleteTagDeclWithOrigin(clang::TagDecl *decl, clang::TagDecl *origin);
+
+  bool CompleteObjCInterfaceDecl(clang::ObjCInterfaceDecl *interface_decl);
+
+  bool CompleteAndFetchChildren(clang::QualType type);
+
+  bool RequireCompleteType(clang::QualType type);
+
+  void SetDeclOrigin(const clang::Decl *decl, clang::Decl *original_decl);
+
+  ClangASTMetadata *GetDeclMetadata(const clang::Decl *decl);
+
+  //
+  // Namespace maps
+  //
+
+  typedef std::vector<std::pair<lldb::ModuleSP, CompilerDeclContext>>
+      NamespaceMap;
+  typedef std::shared_ptr<NamespaceMap> NamespaceMapSP;
+
+  void RegisterNamespaceMap(const clang::NamespaceDecl *decl,
+                            NamespaceMapSP &namespace_map);
+
+  NamespaceMapSP GetNamespaceMap(const clang::NamespaceDecl *decl);
+
+  void BuildNamespaceMap(const clang::NamespaceDecl *decl);
+
+  //
+  // Completers for maps
+  //
+
+  class MapCompleter {
+  public:
+    virtual ~MapCompleter();
+
+    virtual void CompleteNamespaceMap(NamespaceMapSP &namespace_map,
+                                      ConstString name,
+                                      NamespaceMapSP &parent_map) const = 0;
+  };
+
+  void InstallMapCompleter(clang::ASTContext *dst_ctx,
+                           MapCompleter &completer) {
+    ASTContextMetadataSP context_md;
+    ContextMetadataMap::iterator context_md_iter = m_metadata_map.find(dst_ctx);
+
+    if (context_md_iter == m_metadata_map.end()) {
+      context_md = ASTContextMetadataSP(new ASTContextMetadata(dst_ctx));
+      m_metadata_map[dst_ctx] = context_md;
+    } else {
+      context_md = context_md_iter->second;
+    }
+
+    context_md->m_map_completer = &completer;
+  }
+
+  void ForgetDestination(clang::ASTContext *dst_ctx);
+  void ForgetSource(clang::ASTContext *dst_ctx, clang::ASTContext *src_ctx);
+
+public:
+  struct DeclOrigin {
+    DeclOrigin() : ctx(nullptr), decl(nullptr) {}
+
+    DeclOrigin(clang::ASTContext *_ctx, clang::Decl *_decl)
+        : ctx(_ctx), decl(_decl) {}
+
+    DeclOrigin(const DeclOrigin &rhs) {
+      ctx = rhs.ctx;
+      decl = rhs.decl;
+    }
+
+    void operator=(const DeclOrigin &rhs) {
+      ctx = rhs.ctx;
+      decl = rhs.decl;
+    }
+
+    bool Valid() { return (ctx != nullptr || decl != nullptr); }
+
+    clang::ASTContext *ctx;
+    clang::Decl *decl;
+  };
+
+  typedef llvm::DenseMap<const clang::Decl *, DeclOrigin> OriginMap;
+
+  /// Listener interface used by the ASTImporterDelegate to inform other code
+  /// about decls that have been imported the first time.
+  struct NewDeclListener {
+    virtual ~NewDeclListener() = default;
+    /// A decl has been imported for the first time.
+    virtual void NewDeclImported(clang::Decl *from, clang::Decl *to) = 0;
+  };
+
+  /// ASTImporter that intercepts and records the import process of the
+  /// underlying ASTImporter.
+  ///
+  /// This class updates the map from declarations to their original
+  /// declarations and can record declarations that have been imported in a
+  /// certain interval.
+  ///
+  /// When intercepting a declaration import, the ASTImporterDelegate uses the
+  /// CxxModuleHandler to replace any missing or malformed declarations with
+  /// their counterpart from a C++ module.
+  struct ASTImporterDelegate : public clang::ASTImporter {
+    ASTImporterDelegate(ClangASTImporter &master, clang::ASTContext *target_ctx,
+                        clang::ASTContext *source_ctx)
+        : clang::ASTImporter(*target_ctx, master.m_file_manager, *source_ctx,
+                             master.m_file_manager, true /*minimal*/),
+          m_master(master), m_source_ctx(source_ctx) {
+      setODRHandling(clang::ASTImporter::ODRHandlingType::Liberal);
+    }
+
+    /// Scope guard that attaches a CxxModuleHandler to an ASTImporterDelegate
+    /// and deattaches it at the end of the scope. Supports being used multiple
+    /// times on the same ASTImporterDelegate instance in nested scopes.
+    class CxxModuleScope {
+      /// The handler we attach to the ASTImporterDelegate.
+      CxxModuleHandler m_handler;
+      /// The ASTImporterDelegate we are supposed to attach the handler to.
+      ASTImporterDelegate &m_delegate;
+      /// True iff we attached the handler to the ASTImporterDelegate.
+      bool m_valid = false;
+
+    public:
+      CxxModuleScope(ASTImporterDelegate &delegate, clang::ASTContext *dst_ctx)
+          : m_delegate(delegate) {
+        // If the delegate doesn't have a CxxModuleHandler yet, create one
+        // and attach it.
+        if (!delegate.m_std_handler) {
+          m_handler = CxxModuleHandler(delegate, dst_ctx);
+          m_valid = true;
+          delegate.m_std_handler = &m_handler;
+        }
+      }
+      ~CxxModuleScope() {
+        if (m_valid) {
+          // Make sure no one messed with the handler we placed.
+          assert(m_delegate.m_std_handler == &m_handler);
+          m_delegate.m_std_handler = nullptr;
+        }
+      }
+    };
+
+    void ImportDefinitionTo(clang::Decl *to, clang::Decl *from);
+
+    void Imported(clang::Decl *from, clang::Decl *to) override;
+
+    clang::Decl *GetOriginalDecl(clang::Decl *To) override;
+
+    void SetImportListener(NewDeclListener *listener) {
+      assert(m_new_decl_listener == nullptr && "Already attached a listener?");
+      m_new_decl_listener = listener;
+    }
+    void RemoveImportListener() { m_new_decl_listener = nullptr; }
+
+  protected:
+    llvm::Expected<clang::Decl *> ImportImpl(clang::Decl *From) override;
+
+  private:
+    /// Decls we should ignore when mapping decls back to their original
+    /// ASTContext. Used by the CxxModuleHandler to mark declarations that
+    /// were created from the 'std' C++ module to prevent that the Importer
+    /// tries to sync them with the broken equivalent in the debug info AST.
+    llvm::SmallPtrSet<clang::Decl *, 16> m_decls_to_ignore;
+    ClangASTImporter &m_master;
+    clang::ASTContext *m_source_ctx;
+    CxxModuleHandler *m_std_handler = nullptr;
+    /// The currently attached listener.
+    NewDeclListener *m_new_decl_listener = nullptr;
+  };
+
+  typedef std::shared_ptr<ASTImporterDelegate> ImporterDelegateSP;
+  typedef llvm::DenseMap<clang::ASTContext *, ImporterDelegateSP> DelegateMap;
+  typedef llvm::DenseMap<const clang::NamespaceDecl *, NamespaceMapSP>
+      NamespaceMetaMap;
+
+  struct ASTContextMetadata {
+    ASTContextMetadata(clang::ASTContext *dst_ctx)
+        : m_dst_ctx(dst_ctx), m_delegates(), m_origins(), m_namespace_maps(),
+          m_map_completer(nullptr) {}
+
+    clang::ASTContext *m_dst_ctx;
+    DelegateMap m_delegates;
+    OriginMap m_origins;
+
+    NamespaceMetaMap m_namespace_maps;
+    MapCompleter *m_map_completer;
+  };
+
+  typedef std::shared_ptr<ASTContextMetadata> ASTContextMetadataSP;
+  typedef llvm::DenseMap<const clang::ASTContext *, ASTContextMetadataSP>
+      ContextMetadataMap;
+
+  ContextMetadataMap m_metadata_map;
+
+  ASTContextMetadataSP GetContextMetadata(clang::ASTContext *dst_ctx) {
+    ContextMetadataMap::iterator context_md_iter = m_metadata_map.find(dst_ctx);
+
+    if (context_md_iter == m_metadata_map.end()) {
+      ASTContextMetadataSP context_md =
+          ASTContextMetadataSP(new ASTContextMetadata(dst_ctx));
+      m_metadata_map[dst_ctx] = context_md;
+      return context_md;
+    }
+    return context_md_iter->second;
+  }
+
+  ASTContextMetadataSP MaybeGetContextMetadata(clang::ASTContext *dst_ctx) {
+    ContextMetadataMap::iterator context_md_iter = m_metadata_map.find(dst_ctx);
+
+    if (context_md_iter != m_metadata_map.end())
+      return context_md_iter->second;
+    return ASTContextMetadataSP();
+  }
+
+  ImporterDelegateSP GetDelegate(clang::ASTContext *dst_ctx,
+                                 clang::ASTContext *src_ctx) {
+    ASTContextMetadataSP context_md = GetContextMetadata(dst_ctx);
+
+    DelegateMap &delegates = context_md->m_delegates;
+    DelegateMap::iterator delegate_iter = delegates.find(src_ctx);
+
+    if (delegate_iter == delegates.end()) {
+      ImporterDelegateSP delegate =
+          ImporterDelegateSP(new ASTImporterDelegate(*this, dst_ctx, src_ctx));
+      delegates[src_ctx] = delegate;
+      return delegate;
+    }
+    return delegate_iter->second;
+  }
+
+public:
+  DeclOrigin GetDeclOrigin(const clang::Decl *decl);
+
+  clang::FileManager m_file_manager;
+  typedef llvm::DenseMap<const clang::RecordDecl *, LayoutInfo>
+      RecordDeclToLayoutMap;
+
+  RecordDeclToLayoutMap m_record_decl_to_layout_map;
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_ClangASTImporter_h_
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangASTMetadata.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangASTMetadata.cpp
new file mode 100644 (file)
index 0000000..42933c7
--- /dev/null
@@ -0,0 +1,35 @@
+//===-- ClangASTMetadata.cpp ----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "Plugins/ExpressionParser/Clang/ClangASTMetadata.h"
+#include "lldb/Utility/Stream.h"
+
+using namespace lldb_private;
+
+void ClangASTMetadata::Dump(Stream *s) {
+  lldb::user_id_t uid = GetUserID();
+
+  if (uid != LLDB_INVALID_UID) {
+    s->Printf("uid=0x%" PRIx64, uid);
+  }
+
+  uint64_t isa_ptr = GetISAPtr();
+  if (isa_ptr != 0) {
+    s->Printf("isa_ptr=0x%" PRIx64, isa_ptr);
+  }
+
+  const char *obj_ptr_name = GetObjectPtrName();
+  if (obj_ptr_name) {
+    s->Printf("obj_ptr_name=\"%s\" ", obj_ptr_name);
+  }
+
+  if (m_is_dynamic_cxx) {
+    s->Printf("is_dynamic_cxx=%i ", m_is_dynamic_cxx);
+  }
+  s->EOL();
+}
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangASTMetadata.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangASTMetadata.h
new file mode 100644 (file)
index 0000000..fdf4388
--- /dev/null
@@ -0,0 +1,100 @@
+//===-- ClangASTMetadata.h --------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_ClangASTMetadata_h
+#define liblldb_ClangASTMetadata_h
+
+#include "lldb/Core/dwarf.h"
+#include "lldb/lldb-defines.h"
+#include "lldb/lldb-enumerations.h"
+
+namespace lldb_private {
+
+class ClangASTMetadata {
+public:
+  ClangASTMetadata()
+      : m_user_id(0), m_union_is_user_id(false), m_union_is_isa_ptr(false),
+        m_has_object_ptr(false), m_is_self(false), m_is_dynamic_cxx(true) {}
+
+  bool GetIsDynamicCXXType() const { return m_is_dynamic_cxx; }
+
+  void SetIsDynamicCXXType(bool b) { m_is_dynamic_cxx = b; }
+
+  void SetUserID(lldb::user_id_t user_id) {
+    m_user_id = user_id;
+    m_union_is_user_id = true;
+    m_union_is_isa_ptr = false;
+  }
+
+  lldb::user_id_t GetUserID() const {
+    if (m_union_is_user_id)
+      return m_user_id;
+    else
+      return LLDB_INVALID_UID;
+  }
+
+  void SetISAPtr(uint64_t isa_ptr) {
+    m_isa_ptr = isa_ptr;
+    m_union_is_user_id = false;
+    m_union_is_isa_ptr = true;
+  }
+
+  uint64_t GetISAPtr() const {
+    if (m_union_is_isa_ptr)
+      return m_isa_ptr;
+    else
+      return 0;
+  }
+
+  void SetObjectPtrName(const char *name) {
+    m_has_object_ptr = true;
+    if (strcmp(name, "self") == 0)
+      m_is_self = true;
+    else if (strcmp(name, "this") == 0)
+      m_is_self = false;
+    else
+      m_has_object_ptr = false;
+  }
+
+  lldb::LanguageType GetObjectPtrLanguage() const {
+    if (m_has_object_ptr) {
+      if (m_is_self)
+        return lldb::eLanguageTypeObjC;
+      else
+        return lldb::eLanguageTypeC_plus_plus;
+    }
+    return lldb::eLanguageTypeUnknown;
+  }
+
+  const char *GetObjectPtrName() const {
+    if (m_has_object_ptr) {
+      if (m_is_self)
+        return "self";
+      else
+        return "this";
+    } else
+      return nullptr;
+  }
+
+  bool HasObjectPtr() const { return m_has_object_ptr; }
+
+  void Dump(Stream *s);
+
+private:
+  union {
+    lldb::user_id_t m_user_id;
+    uint64_t m_isa_ptr;
+  };
+
+  bool m_union_is_user_id : 1, m_union_is_isa_ptr : 1, m_has_object_ptr : 1,
+      m_is_self : 1, m_is_dynamic_cxx : 1;
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_ClangASTMetadata_h
index 8fb0f40ea1d3a162159ba3c23d77859b9493fe0b..7362a00c76f275f5fe01db95009607599276b4c1 100644 (file)
@@ -13,8 +13,6 @@
 
 #include "lldb/Core/Module.h"
 #include "lldb/Core/ModuleList.h"
-#include "lldb/Symbol/TypeSystemClang.h"
-#include "lldb/Symbol/ClangUtil.h"
 #include "lldb/Symbol/CompilerDeclContext.h"
 #include "lldb/Symbol/Function.h"
 #include "lldb/Symbol/SymbolFile.h"
@@ -24,7 +22,9 @@
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/RecordLayout.h"
 
+#include "Plugins/ExpressionParser/Clang/ClangUtil.h"
 #include "Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.h"
+#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
 
 #include <memory>
 #include <vector>
index 2b711db7a5a5cf9da1ab7c3e936ae1e5ce1f120a..aeb06b3652f001da72455fa47addb3611fdee6ff 100644 (file)
@@ -11,7 +11,7 @@
 
 #include <set>
 
-#include "lldb/Symbol/ClangASTImporter.h"
+#include "Plugins/ExpressionParser/Clang/ClangASTImporter.h"
 #include "lldb/Symbol/CompilerType.h"
 #include "lldb/Target/Target.h"
 #include "clang/AST/ExternalASTSource.h"
index f5b0c216902a2a5bcc78656950f4df762023dd80..867d4ff0a907774fce93428d21bf5dab961db385 100644 (file)
@@ -7,9 +7,9 @@
 //===----------------------------------------------------------------------===//
 
 #include "Plugins/ExpressionParser/Clang/ClangDeclVendor.h"
+#include "Plugins/ExpressionParser/Clang/ClangUtil.h"
+#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
 
-#include "lldb/Symbol/ClangUtil.h"
-#include "lldb/Symbol/TypeSystemClang.h"
 #include "lldb/Utility/ConstString.h"
 
 using namespace lldb_private;
index 8f4c92e332784fb802f43dd627a7204f7ea9725a..58094e0252685922bde6c562feae3b23a369dcc6 100644 (file)
 #include "ClangASTSource.h"
 #include "ClangModulesDeclVendor.h"
 #include "ClangPersistentVariables.h"
+#include "ClangUtil.h"
 
+#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
 #include "lldb/Core/Address.h"
 #include "lldb/Core/Module.h"
 #include "lldb/Core/ModuleSpec.h"
 #include "lldb/Core/ValueObjectConstResult.h"
 #include "lldb/Core/ValueObjectVariable.h"
 #include "lldb/Expression/Materializer.h"
-#include "lldb/Symbol/TypeSystemClang.h"
-#include "lldb/Symbol/ClangUtil.h"
 #include "lldb/Symbol/CompileUnit.h"
 #include "lldb/Symbol/CompilerDecl.h"
 #include "lldb/Symbol/CompilerDeclContext.h"
index eeab419345813ad84e566da91b23705e592282a2..1516d5b0277b3cb6748e0383af03d0145e21fabb 100644 (file)
@@ -67,6 +67,7 @@
 #include "IRForTarget.h"
 #include "ModuleDependencyCollector.h"
 
+#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
 #include "lldb/Core/Debugger.h"
 #include "lldb/Core/Disassembler.h"
 #include "lldb/Core/Module.h"
@@ -75,7 +76,6 @@
 #include "lldb/Expression/IRInterpreter.h"
 #include "lldb/Host/File.h"
 #include "lldb/Host/HostInfo.h"
-#include "lldb/Symbol/TypeSystemClang.h"
 #include "lldb/Symbol/SymbolVendor.h"
 #include "lldb/Target/ExecutionContext.h"
 #include "lldb/Target/Language.h"
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExternalASTSourceCallbacks.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangExternalASTSourceCallbacks.cpp
new file mode 100644 (file)
index 0000000..26dc4d6
--- /dev/null
@@ -0,0 +1,45 @@
+//===-- ClangExternalASTSourceCallbacks.cpp -------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "Plugins/ExpressionParser/Clang/ClangExternalASTSourceCallbacks.h"
+#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
+
+#include "clang/AST/Decl.h"
+
+using namespace lldb_private;
+
+void ClangExternalASTSourceCallbacks::CompleteType(clang::TagDecl *tag_decl) {
+  m_ast.CompleteTagDecl(tag_decl);
+}
+
+void ClangExternalASTSourceCallbacks::CompleteType(
+    clang::ObjCInterfaceDecl *objc_decl) {
+  m_ast.CompleteObjCInterfaceDecl(objc_decl);
+}
+
+bool ClangExternalASTSourceCallbacks::layoutRecordType(
+    const clang::RecordDecl *Record, uint64_t &Size, uint64_t &Alignment,
+    llvm::DenseMap<const clang::FieldDecl *, uint64_t> &FieldOffsets,
+    llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &BaseOffsets,
+    llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits>
+        &VirtualBaseOffsets) {
+  return m_ast.LayoutRecordType(Record, Size, Alignment, FieldOffsets,
+                                BaseOffsets, VirtualBaseOffsets);
+}
+
+void ClangExternalASTSourceCallbacks::FindExternalLexicalDecls(
+    const clang::DeclContext *decl_ctx,
+    llvm::function_ref<bool(clang::Decl::Kind)> IsKindWeWant,
+    llvm::SmallVectorImpl<clang::Decl *> &decls) {
+  if (decl_ctx) {
+    clang::TagDecl *tag_decl = llvm::dyn_cast<clang::TagDecl>(
+        const_cast<clang::DeclContext *>(decl_ctx));
+    if (tag_decl)
+      CompleteType(tag_decl);
+  }
+}
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExternalASTSourceCallbacks.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangExternalASTSourceCallbacks.h
new file mode 100644 (file)
index 0000000..98e9f5a
--- /dev/null
@@ -0,0 +1,46 @@
+//===-- ClangExternalASTSourceCallbacks.h -----------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_ClangExternalASTSourceCallbacks_h_
+#define liblldb_ClangExternalASTSourceCallbacks_h_
+
+#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
+#include "clang/AST/ExternalASTSource.h"
+
+namespace lldb_private {
+
+class TypeSystemClang;
+
+class ClangExternalASTSourceCallbacks : public clang::ExternalASTSource {
+public:
+  ClangExternalASTSourceCallbacks(TypeSystemClang &ast) : m_ast(ast) {}
+
+  void FindExternalLexicalDecls(
+      const clang::DeclContext *DC,
+      llvm::function_ref<bool(clang::Decl::Kind)> IsKindWeWant,
+      llvm::SmallVectorImpl<clang::Decl *> &Result) override;
+
+  void CompleteType(clang::TagDecl *tag_decl) override;
+
+  void CompleteType(clang::ObjCInterfaceDecl *objc_decl) override;
+
+  bool layoutRecordType(
+      const clang::RecordDecl *Record, uint64_t &Size, uint64_t &Alignment,
+      llvm::DenseMap<const clang::FieldDecl *, uint64_t> &FieldOffsets,
+      llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits>
+          &BaseOffsets,
+      llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits>
+          &VirtualBaseOffsets) override;
+
+private:
+  TypeSystemClang &m_ast;
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_ClangExternalASTSourceCallbacks_h_
index d2a379e2a56350308876d028f1628f1cb2d6617d..ea56e429a9d50a5dc7d5a7ddd8f992f838cfdce4 100644 (file)
 #include "llvm/ExecutionEngine/ExecutionEngine.h"
 #include "llvm/IR/Module.h"
 
+#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
 #include "lldb/Core/Module.h"
 #include "lldb/Core/ValueObject.h"
 #include "lldb/Core/ValueObjectList.h"
 #include "lldb/Expression/IRExecutionUnit.h"
 #include "lldb/Interpreter/CommandReturnObject.h"
-#include "lldb/Symbol/TypeSystemClang.h"
 #include "lldb/Symbol/Function.h"
 #include "lldb/Symbol/Type.h"
 #include "lldb/Target/ExecutionContext.h"
index cc3b4ed0cd044b9bde88663d89c2379422407f97..4b0521aff411313ada642feddd21c7f74eaee8c0 100644 (file)
 #include "ClangModulesDeclVendor.h"
 #include "ModuleDependencyCollector.h"
 
+#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
 #include "lldb/Core/ModuleList.h"
 #include "lldb/Host/Host.h"
 #include "lldb/Host/HostInfo.h"
-#include "lldb/Symbol/TypeSystemClang.h"
 #include "lldb/Symbol/CompileUnit.h"
 #include "lldb/Symbol/SourceModule.h"
 #include "lldb/Target/Target.h"
index f847dc9404422d735c7da5b57cb128dcb2a306f3..da26c6a3d9a66685bfa52aadf02e020f83184f6b 100644 (file)
@@ -7,10 +7,10 @@
 //===----------------------------------------------------------------------===//
 
 #include "ClangPersistentVariables.h"
+#include "ClangASTImporter.h"
 
+#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
 #include "lldb/Core/Value.h"
-#include "lldb/Symbol/ClangASTImporter.h"
-#include "lldb/Symbol/TypeSystemClang.h"
 #include "lldb/Target/Target.h"
 #include "lldb/Utility/DataExtractor.h"
 #include "lldb/Utility/Log.h"
index 2fca5043e30c2ae0a0813fbdb4174e813606bfd2..492ab15d58f21cf5bc5f48bc553d0d4d84773c53 100644 (file)
@@ -20,6 +20,7 @@
 #include "ClangUserExpression.h"
 
 #include "ASTResultSynthesizer.h"
+#include "ClangASTMetadata.h"
 #include "ClangDiagnostic.h"
 #include "ClangExpressionDeclMap.h"
 #include "ClangExpressionParser.h"
@@ -27,6 +28,7 @@
 #include "ClangPersistentVariables.h"
 #include "CppModuleConfiguration.h"
 
+#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
 #include "lldb/Core/Debugger.h"
 #include "lldb/Core/Module.h"
 #include "lldb/Core/StreamFile.h"
@@ -37,8 +39,6 @@
 #include "lldb/Expression/Materializer.h"
 #include "lldb/Host/HostInfo.h"
 #include "lldb/Symbol/Block.h"
-#include "lldb/Symbol/TypeSystemClang.h"
-#include "lldb/Symbol/ClangASTMetadata.h"
 #include "lldb/Symbol/CompileUnit.h"
 #include "lldb/Symbol/Function.h"
 #include "lldb/Symbol/ObjectFile.h"
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangUtil.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangUtil.cpp
new file mode 100644 (file)
index 0000000..a7f5dce
--- /dev/null
@@ -0,0 +1,87 @@
+//===-- ClangUtil.cpp -----------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+// A collection of helper methods and data structures for manipulating clang
+// types and decls.
+//===----------------------------------------------------------------------===//
+
+#include "Plugins/ExpressionParser/Clang/ClangUtil.h"
+#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
+
+using namespace clang;
+using namespace lldb_private;
+
+bool ClangUtil::IsClangType(const CompilerType &ct) {
+  // Invalid types are never Clang types.
+  if (!ct)
+    return false;
+
+  if (llvm::dyn_cast_or_null<TypeSystemClang>(ct.GetTypeSystem()) == nullptr)
+    return false;
+
+  if (!ct.GetOpaqueQualType())
+    return false;
+
+  return true;
+}
+
+clang::Decl *ClangUtil::GetDecl(const CompilerDecl &decl) {
+  assert(llvm::isa<TypeSystemClang>(decl.GetTypeSystem()));
+  return static_cast<clang::Decl *>(decl.GetOpaqueDecl());
+}
+
+QualType ClangUtil::GetQualType(const CompilerType &ct) {
+  // Make sure we have a clang type before making a clang::QualType
+  if (!IsClangType(ct))
+    return QualType();
+
+  return QualType::getFromOpaquePtr(ct.GetOpaqueQualType());
+}
+
+QualType ClangUtil::GetCanonicalQualType(const CompilerType &ct) {
+  if (!IsClangType(ct))
+    return QualType();
+
+  return GetQualType(ct).getCanonicalType();
+}
+
+CompilerType ClangUtil::RemoveFastQualifiers(const CompilerType &ct) {
+  if (!IsClangType(ct))
+    return ct;
+
+  QualType qual_type(GetQualType(ct));
+  qual_type.removeLocalFastQualifiers();
+  return CompilerType(ct.GetTypeSystem(), qual_type.getAsOpaquePtr());
+}
+
+clang::TagDecl *ClangUtil::GetAsTagDecl(const CompilerType &type) {
+  clang::QualType qual_type = ClangUtil::GetCanonicalQualType(type);
+  if (qual_type.isNull())
+    return nullptr;
+
+  return qual_type->getAsTagDecl();
+}
+
+std::string ClangUtil::DumpDecl(const clang::Decl *d) {
+  if (!d)
+    return "nullptr";
+
+  std::string result;
+  llvm::raw_string_ostream stream(result);
+  bool deserialize = false;
+  d->dump(stream, deserialize);
+
+  stream.flush();
+  return result;
+}
+
+std::string ClangUtil::ToString(const clang::Type *t) {
+  return clang::QualType(t, 0).getAsString();
+}
+
+std::string ClangUtil::ToString(const CompilerType &c) {
+  return ClangUtil::GetQualType(c).getAsString();
+}
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangUtil.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangUtil.h
new file mode 100644 (file)
index 0000000..31e86ca
--- /dev/null
@@ -0,0 +1,50 @@
+//===-- ClangUtil.h ---------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+// A collection of helper methods and data structures for manipulating clang
+// types and decls.
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_SYMBOL_CLANGUTIL_H
+#define LLDB_SYMBOL_CLANGUTIL_H
+
+#include "clang/AST/DeclBase.h"
+#include "clang/AST/Type.h"
+
+#include "lldb/Symbol/CompilerType.h"
+
+namespace clang {
+class TagDecl;
+}
+
+namespace lldb_private {
+struct ClangUtil {
+  static bool IsClangType(const CompilerType &ct);
+
+  /// Returns the clang::Decl of the given CompilerDecl.
+  /// CompilerDecl has to be valid and represent a clang::Decl.
+  static clang::Decl *GetDecl(const CompilerDecl &decl);
+
+  static clang::QualType GetQualType(const CompilerType &ct);
+
+  static clang::QualType GetCanonicalQualType(const CompilerType &ct);
+
+  static CompilerType RemoveFastQualifiers(const CompilerType &ct);
+
+  static clang::TagDecl *GetAsTagDecl(const CompilerType &type);
+
+  /// Returns a textual representation of the given Decl's AST. Does not
+  /// deserialize any child nodes.
+  static std::string DumpDecl(const clang::Decl *d);
+  /// Returns a textual representation of the given type.
+  static std::string ToString(const clang::Type *t);
+  /// Returns a textual representation of the given CompilerType (assuming
+  /// its underlying type is a Clang type).
+  static std::string ToString(const CompilerType &c);
+};
+}
+
+#endif
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/CxxModuleHandler.cpp b/lldb/source/Plugins/ExpressionParser/Clang/CxxModuleHandler.cpp
new file mode 100644 (file)
index 0000000..ae2f074
--- /dev/null
@@ -0,0 +1,289 @@
+//===-- CxxModuleHandler.cpp ----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "Plugins/ExpressionParser/Clang/CxxModuleHandler.h"
+#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
+
+#include "lldb/Utility/Log.h"
+#include "clang/Sema/Lookup.h"
+#include "llvm/Support/Error.h"
+
+using namespace lldb_private;
+using namespace clang;
+
+CxxModuleHandler::CxxModuleHandler(ASTImporter &importer, ASTContext *target)
+    : m_importer(&importer),
+      m_sema(TypeSystemClang::GetASTContext(target)->getSema()) {
+
+  std::initializer_list<const char *> supported_names = {
+      // containers
+      "deque",
+      "forward_list",
+      "list",
+      "queue",
+      "stack",
+      "vector",
+      // pointers
+      "shared_ptr",
+      "unique_ptr",
+      "weak_ptr",
+      // utility
+      "allocator",
+  };
+  m_supported_templates.insert(supported_names.begin(), supported_names.end());
+}
+
+/// Builds a list of scopes that point into the given context.
+///
+/// \param sema The sema that will be using the scopes.
+/// \param ctxt The context that the scope should look into.
+/// \param result A list of scopes. The scopes need to be freed by the caller
+///               (except the TUScope which is owned by the sema).
+static void makeScopes(Sema &sema, DeclContext *ctxt,
+                       std::vector<Scope *> &result) {
+  // FIXME: The result should be a list of unique_ptrs, but the TUScope makes
+  // this currently impossible as it's owned by the Sema.
+
+  if (auto parent = ctxt->getParent()) {
+    makeScopes(sema, parent, result);
+
+    Scope *scope =
+        new Scope(result.back(), Scope::DeclScope, sema.getDiagnostics());
+    scope->setEntity(ctxt);
+    result.push_back(scope);
+  } else
+    result.push_back(sema.TUScope);
+}
+
+/// Uses the Sema to look up the given name in the given DeclContext.
+static std::unique_ptr<LookupResult>
+emulateLookupInCtxt(Sema &sema, llvm::StringRef name, DeclContext *ctxt) {
+  IdentifierInfo &ident = sema.getASTContext().Idents.get(name);
+
+  std::unique_ptr<LookupResult> lookup_result;
+  lookup_result.reset(new LookupResult(sema, DeclarationName(&ident),
+                                       SourceLocation(),
+                                       Sema::LookupOrdinaryName));
+
+  // Usually during parsing we already encountered the scopes we would use. But
+  // here don't have these scopes so we have to emulate the behavior of the
+  // Sema during parsing.
+  std::vector<Scope *> scopes;
+  makeScopes(sema, ctxt, scopes);
+
+  // Now actually perform the lookup with the sema.
+  sema.LookupName(*lookup_result, scopes.back());
+
+  // Delete all the allocated scopes beside the translation unit scope (which
+  // has depth 0).
+  for (Scope *s : scopes)
+    if (s->getDepth() != 0)
+      delete s;
+
+  return lookup_result;
+}
+
+/// Error class for handling problems when finding a certain DeclContext.
+struct MissingDeclContext : public llvm::ErrorInfo<MissingDeclContext> {
+
+  static char ID;
+
+  MissingDeclContext(DeclContext *context, std::string error)
+      : m_context(context), m_error(error) {}
+
+  DeclContext *m_context;
+  std::string m_error;
+
+  void log(llvm::raw_ostream &OS) const override {
+    OS << llvm::formatv("error when reconstructing context of kind {0}:{1}",
+                        m_context->getDeclKindName(), m_error);
+  }
+
+  std::error_code convertToErrorCode() const override {
+    return llvm::inconvertibleErrorCode();
+  }
+};
+
+char MissingDeclContext::ID = 0;
+
+/// Given a foreign decl context, this function finds the equivalent local
+/// decl context in the ASTContext of the given Sema. Potentially deserializes
+/// decls from the 'std' module if necessary.
+static llvm::Expected<DeclContext *>
+getEqualLocalDeclContext(Sema &sema, DeclContext *foreign_ctxt) {
+
+  // Inline namespaces don't matter for lookups, so let's skip them.
+  while (foreign_ctxt && foreign_ctxt->isInlineNamespace())
+    foreign_ctxt = foreign_ctxt->getParent();
+
+  // If the foreign context is the TU, we just return the local TU.
+  if (foreign_ctxt->isTranslationUnit())
+    return sema.getASTContext().getTranslationUnitDecl();
+
+  // Recursively find/build the parent DeclContext.
+  llvm::Expected<DeclContext *> parent =
+      getEqualLocalDeclContext(sema, foreign_ctxt->getParent());
+  if (!parent)
+    return parent;
+
+  // We currently only support building namespaces.
+  if (foreign_ctxt->isNamespace()) {
+    NamedDecl *ns = llvm::dyn_cast<NamedDecl>(foreign_ctxt);
+    llvm::StringRef ns_name = ns->getName();
+
+    auto lookup_result = emulateLookupInCtxt(sema, ns_name, *parent);
+    for (NamedDecl *named_decl : *lookup_result) {
+      if (DeclContext *DC = llvm::dyn_cast<DeclContext>(named_decl))
+        return DC->getPrimaryContext();
+    }
+    return llvm::make_error<MissingDeclContext>(
+        foreign_ctxt,
+        "Couldn't find namespace " + ns->getQualifiedNameAsString());
+  }
+
+  return llvm::make_error<MissingDeclContext>(foreign_ctxt, "Unknown context ");
+}
+
+/// Returns true iff tryInstantiateStdTemplate supports instantiating a template
+/// with the given template arguments.
+static bool templateArgsAreSupported(ArrayRef<TemplateArgument> a) {
+  for (const TemplateArgument &arg : a) {
+    switch (arg.getKind()) {
+    case TemplateArgument::Type:
+    case TemplateArgument::Integral:
+      break;
+    default:
+      // TemplateArgument kind hasn't been handled yet.
+      return false;
+    }
+  }
+  return true;
+}
+
+/// Constructor function for Clang declarations. Ensures that the created
+/// declaration is registered with the ASTImporter.
+template <typename T, typename... Args>
+T *createDecl(ASTImporter &importer, Decl *from_d, Args &&... args) {
+  T *to_d = T::Create(std::forward<Args>(args)...);
+  importer.RegisterImportedDecl(from_d, to_d);
+  return to_d;
+}
+
+llvm::Optional<Decl *> CxxModuleHandler::tryInstantiateStdTemplate(Decl *d) {
+  Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS);
+
+  // If we don't have a template to instiantiate, then there is nothing to do.
+  auto td = dyn_cast<ClassTemplateSpecializationDecl>(d);
+  if (!td)
+    return {};
+
+  // We only care about templates in the std namespace.
+  if (!td->getDeclContext()->isStdNamespace())
+    return {};
+
+  // We have a whitelist of supported template names.
+  if (m_supported_templates.find(td->getName()) == m_supported_templates.end())
+    return {};
+
+  // Early check if we even support instantiating this template. We do this
+  // before we import anything into the target AST.
+  auto &foreign_args = td->getTemplateInstantiationArgs();
+  if (!templateArgsAreSupported(foreign_args.asArray()))
+    return {};
+
+  // Find the local DeclContext that corresponds to the DeclContext of our
+  // decl we want to import.
+  llvm::Expected<DeclContext *> to_context =
+      getEqualLocalDeclContext(*m_sema, td->getDeclContext());
+  if (!to_context) {
+    LLDB_LOG_ERROR(log, to_context.takeError(),
+                   "Got error while searching equal local DeclContext for decl "
+                   "'{1}':\n{0}",
+                   td->getName());
+    return {};
+  }
+
+  // Look up the template in our local context.
+  std::unique_ptr<LookupResult> lookup =
+      emulateLookupInCtxt(*m_sema, td->getName(), *to_context);
+
+  ClassTemplateDecl *new_class_template = nullptr;
+  for (auto LD : *lookup) {
+    if ((new_class_template = dyn_cast<ClassTemplateDecl>(LD)))
+      break;
+  }
+  if (!new_class_template)
+    return {};
+
+  // Import the foreign template arguments.
+  llvm::SmallVector<TemplateArgument, 4> imported_args;
+
+  // If this logic is changed, also update templateArgsAreSupported.
+  for (const TemplateArgument &arg : foreign_args.asArray()) {
+    switch (arg.getKind()) {
+    case TemplateArgument::Type: {
+      llvm::Expected<QualType> type = m_importer->Import(arg.getAsType());
+      if (!type) {
+        LLDB_LOG_ERROR(log, type.takeError(), "Couldn't import type: {0}");
+        return {};
+      }
+      imported_args.push_back(TemplateArgument(*type));
+      break;
+    }
+    case TemplateArgument::Integral: {
+      llvm::APSInt integral = arg.getAsIntegral();
+      llvm::Expected<QualType> type =
+          m_importer->Import(arg.getIntegralType());
+      if (!type) {
+        LLDB_LOG_ERROR(log, type.takeError(), "Couldn't import type: {0}");
+        return {};
+      }
+      imported_args.push_back(
+          TemplateArgument(d->getASTContext(), integral, *type));
+      break;
+    }
+    default:
+      assert(false && "templateArgsAreSupported not updated?");
+    }
+  }
+
+  // Find the class template specialization declaration that
+  // corresponds to these arguments.
+  void *InsertPos = nullptr;
+  ClassTemplateSpecializationDecl *result =
+      new_class_template->findSpecialization(imported_args, InsertPos);
+
+  if (result) {
+    // We found an existing specialization in the module that fits our arguments
+    // so we can treat it as the result and register it with the ASTImporter.
+    m_importer->RegisterImportedDecl(d, result);
+    return result;
+  }
+
+  // Instantiate the template.
+  result = createDecl<ClassTemplateSpecializationDecl>(
+      *m_importer, d, m_sema->getASTContext(),
+      new_class_template->getTemplatedDecl()->getTagKind(),
+      new_class_template->getDeclContext(),
+      new_class_template->getTemplatedDecl()->getLocation(),
+      new_class_template->getLocation(), new_class_template, imported_args,
+      nullptr);
+
+  new_class_template->AddSpecialization(result, InsertPos);
+  if (new_class_template->isOutOfLine())
+    result->setLexicalDeclContext(
+        new_class_template->getLexicalDeclContext());
+  return result;
+}
+
+llvm::Optional<Decl *> CxxModuleHandler::Import(Decl *d) {
+  if (!isValid())
+    return {};
+
+  return tryInstantiateStdTemplate(d);
+}
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/CxxModuleHandler.h b/lldb/source/Plugins/ExpressionParser/Clang/CxxModuleHandler.h
new file mode 100644 (file)
index 0000000..f4aef36
--- /dev/null
@@ -0,0 +1,65 @@
+//===-- CxxModuleHandler.h --------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_CxxModuleHandler_h_
+#define liblldb_CxxModuleHandler_h_
+
+#include "clang/AST/ASTImporter.h"
+#include "clang/Sema/Sema.h"
+#include "llvm/ADT/StringSet.h"
+
+namespace lldb_private {
+
+/// Handles importing decls into an ASTContext with an attached C++ module.
+///
+/// This class searches a C++ module (which must be attached to the target
+/// ASTContext) for an equivalent decl to the one that should be imported.
+/// If the decl that is found in the module is a suitable replacement
+/// for the decl that should be imported, the module decl will be treated as
+/// the result of the import process.
+///
+/// If the Decl that should be imported is a template specialization
+/// that doesn't exist yet in the target ASTContext (e.g. `std::vector<int>`),
+/// then this class tries to create the template specialization in the target
+/// ASTContext. This is only possible if the CxxModuleHandler can determine
+/// that instantiating this template is safe to do, e.g. because the target
+/// decl is a container class from the STL.
+class CxxModuleHandler {
+  /// The ASTImporter that should be used to import any Decls which aren't
+  /// directly handled by this class itself.
+  clang::ASTImporter *m_importer = nullptr;
+
+  /// The Sema instance of the target ASTContext.
+  clang::Sema *m_sema = nullptr;
+
+  /// List of template names this class currently supports. These are the
+  /// template names inside the 'std' namespace such as 'vector' or 'list'.
+  llvm::StringSet<> m_supported_templates;
+
+  /// Tries to manually instantiate the given foreign template in the target
+  /// context (designated by m_sema).
+  llvm::Optional<clang::Decl *> tryInstantiateStdTemplate(clang::Decl *d);
+
+public:
+  CxxModuleHandler() = default;
+  CxxModuleHandler(clang::ASTImporter &importer, clang::ASTContext *target);
+
+  /// Attempts to import the given decl into the target ASTContext by
+  /// deserializing it from the 'std' module. This function returns a Decl if a
+  /// Decl has been deserialized from the 'std' module. Otherwise this function
+  /// returns nothing.
+  llvm::Optional<clang::Decl *> Import(clang::Decl *d);
+
+  /// Returns true iff this instance is capable of importing any declarations
+  /// in the target ASTContext.
+  bool isValid() const { return m_sema != nullptr; }
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_CxxModuleHandler_h_
index bcf13e5c877c28f7fb77626ead5a79b7703d7e68..e70ab1ce8d5aed68c405ceb991d8beb3d1120c7f 100644 (file)
@@ -9,7 +9,9 @@
 #include "IRForTarget.h"
 
 #include "ClangExpressionDeclMap.h"
+#include "ClangUtil.h"
 
+#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
 #include "llvm/IR/Constants.h"
 #include "llvm/IR/DataLayout.h"
 #include "llvm/IR/InstrTypes.h"
@@ -27,8 +29,6 @@
 #include "lldb/Core/dwarf.h"
 #include "lldb/Expression/IRExecutionUnit.h"
 #include "lldb/Expression/IRInterpreter.h"
-#include "lldb/Symbol/TypeSystemClang.h"
-#include "lldb/Symbol/ClangUtil.h"
 #include "lldb/Symbol/CompilerType.h"
 #include "lldb/Utility/ConstString.h"
 #include "lldb/Utility/DataBufferHeap.h"
index 43b2cadb19197d66132f321da529b1a945746c6b..e5f19a66f119805b79d8dc5f79e962fcb22aa397 100644 (file)
@@ -8,13 +8,13 @@
 
 #include "BlockPointer.h"
 
+#include "Plugins/ExpressionParser/Clang/ClangASTImporter.h"
 #include "Plugins/ExpressionParser/Clang/ClangPersistentVariables.h"
+#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
 #include "lldb/Core/ValueObject.h"
 #include "lldb/DataFormatters/FormattersHelpers.h"
-#include "lldb/Symbol/ClangASTImporter.h"
 #include "lldb/Symbol/CompilerType.h"
 #include "lldb/Symbol/TypeSystem.h"
-#include "lldb/Symbol/TypeSystemClang.h"
 #include "lldb/Target/Target.h"
 #include "lldb/Utility/LLDBAssert.h"
 #include "lldb/Utility/Log.h"
index ea36c7ec80dbeb7cbb7ed1429be224539cef31f5..2a541a9e528cd2d71f2b106f61cfa4704ee83e52 100644 (file)
@@ -29,6 +29,7 @@ add_lldb_library(lldbPluginCPlusPlusLanguage PLUGIN
     lldbUtility
     lldbPluginClangCommon
     lldbPluginCPPRuntime
+    lldbPluginTypeSystemClang
 
   LINK_COMPONENTS
     Support
index 4f0e061b29a394b838a27b3b18f26c32e97da2c0..41bbd2b01a1e7e92da128d0aab5c2120be0bfd8b 100644 (file)
 
 #include "llvm/Support/ConvertUTF.h"
 
+#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
 #include "lldb/Core/ValueObject.h"
 #include "lldb/Core/ValueObjectConstResult.h"
 #include "lldb/DataFormatters/FormattersHelpers.h"
 #include "lldb/DataFormatters/StringPrinter.h"
 #include "lldb/DataFormatters/TypeSummary.h"
 #include "lldb/Host/Time.h"
-#include "lldb/Symbol/TypeSystemClang.h"
 #include "lldb/Target/ProcessStructReader.h"
 #include "lldb/Target/SectionLoadList.h"
 #include "lldb/Target/Target.h"
index 240821a29e87c340c35838c43677ae8627a8ed42..b2b68b25eeee5415f8b7b529c121dc66878146f3 100644 (file)
@@ -17,7 +17,6 @@
 #include "lldb/DataFormatters/StringPrinter.h"
 #include "lldb/DataFormatters/TypeSummary.h"
 #include "lldb/DataFormatters/VectorIterator.h"
-#include "lldb/Symbol/TypeSystemClang.h"
 #include "lldb/Target/ProcessStructReader.h"
 #include "lldb/Target/SectionLoadList.h"
 #include "lldb/Target/Target.h"
@@ -27,6 +26,7 @@
 #include "lldb/Utility/Stream.h"
 
 #include "Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.h"
+#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
 
 using namespace lldb;
 using namespace lldb_private;
index b60e5294528f1fd64170873a4580b7b5a545dc80..6de4637a6a4ac8485cd86ccb45795530140519fc 100644 (file)
@@ -7,8 +7,8 @@
 //===----------------------------------------------------------------------===//
 
 #include "LibCxx.h"
+#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
 #include "lldb/DataFormatters/FormattersHelpers.h"
-#include "lldb/Symbol/TypeSystemClang.h"
 #include "lldb/Target/Target.h"
 
 using namespace lldb;
index 3f607c6facbacebef21a245e80393424523b60cf..4c5940a45766d3cd628c97576b75256a95c3298b 100644 (file)
@@ -8,10 +8,10 @@
 
 #include "LibCxx.h"
 
+#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
 #include "lldb/Core/ValueObject.h"
 #include "lldb/Core/ValueObjectConstResult.h"
 #include "lldb/DataFormatters/FormattersHelpers.h"
-#include "lldb/Symbol/TypeSystemClang.h"
 #include "lldb/Target/Target.h"
 #include "lldb/Utility/DataBufferHeap.h"
 #include "lldb/Utility/Endian.h"
index 44432957f0acfe6fbc12a04505247b1aed23baf2..64a199e24e4a5b2603a8669a04fcfb8403d94888 100644 (file)
@@ -8,10 +8,10 @@
 
 #include "LibCxx.h"
 
+#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
 #include "lldb/Core/ValueObject.h"
 #include "lldb/Core/ValueObjectConstResult.h"
 #include "lldb/DataFormatters/FormattersHelpers.h"
-#include "lldb/Symbol/TypeSystemClang.h"
 #include "lldb/Target/Target.h"
 #include "lldb/Utility/DataBufferHeap.h"
 #include "lldb/Utility/Endian.h"
index 2091c0b6b7400b7a5dafda3c4f177f3646cefd20..3a441973fc7318c28e07ca9e307f434ff03091fd 100644 (file)
@@ -8,10 +8,10 @@
 
 #include "LibCxx.h"
 
+#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
 #include "lldb/Core/ValueObject.h"
 #include "lldb/Core/ValueObjectConstResult.h"
 #include "lldb/DataFormatters/FormattersHelpers.h"
-#include "lldb/Symbol/TypeSystemClang.h"
 #include "lldb/Target/Target.h"
 #include "lldb/Utility/DataBufferHeap.h"
 #include "lldb/Utility/Endian.h"
index 75c9239410ef917fc5c44eeca8a333f123b29359..78f58754cc319cae6d485b6a7282f8d8dd908cd7 100644 (file)
@@ -8,11 +8,11 @@
 
 #include "LibStdcpp.h"
 
+#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
 #include "lldb/Core/ValueObject.h"
 #include "lldb/Core/ValueObjectConstResult.h"
 #include "lldb/DataFormatters/StringPrinter.h"
 #include "lldb/DataFormatters/VectorIterator.h"
-#include "lldb/Symbol/TypeSystemClang.h"
 #include "lldb/Target/Target.h"
 #include "lldb/Utility/DataBufferHeap.h"
 #include "lldb/Utility/Endian.h"
index 0ee2a73a23efe070a65acc236017f16fdada474c..9e4eb9d53d4774a50daf3f1381689784c10db7f6 100644 (file)
@@ -8,10 +8,10 @@
 
 #include "CF.h"
 
+#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
 #include "lldb/Core/ValueObject.h"
 #include "lldb/Core/ValueObjectConstResult.h"
 #include "lldb/DataFormatters/FormattersHelpers.h"
-#include "lldb/Symbol/TypeSystemClang.h"
 #include "lldb/Target/Language.h"
 #include "lldb/Target/StackFrame.h"
 #include "lldb/Target/Target.h"
index ebb96c299087de381c05c67a0a521584ad53460e..7b220e4c0c21dbd7ab8221aa4a7f5cb8a311cf21 100644 (file)
@@ -31,6 +31,7 @@ add_lldb_library(lldbPluginObjCLanguage PLUGIN
     lldbUtility
     lldbPluginAppleObjCRuntime
     lldbPluginClangCommon
+    lldbPluginTypeSystemClang
   CLANG_LIBS
     clangAST
 
index 67e11aeff61f6297213a34004b047517f5360c8b..8a44811dd36b9bfb7206a554b6d57a693b3711ed 100644 (file)
@@ -8,6 +8,7 @@
 
 #include "Cocoa.h"
 
+#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
 #include "lldb/Core/Mangled.h"
 #include "lldb/Core/ValueObject.h"
 #include "lldb/Core/ValueObjectConstResult.h"
@@ -15,7 +16,6 @@
 #include "lldb/DataFormatters/StringPrinter.h"
 #include "lldb/DataFormatters/TypeSummary.h"
 #include "lldb/Host/Time.h"
-#include "lldb/Symbol/TypeSystemClang.h"
 #include "lldb/Target/Language.h"
 #include "lldb/Target/Process.h"
 #include "lldb/Target/ProcessStructReader.h"
index 7557b87ad0470ec4ea0c4885f2fb162430f590fd..b3cc9d6cd462f2bc09eafa27f7b95bc5156e1e88 100644 (file)
 #include "Cocoa.h"
 
 #include "Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h"
+#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
 
 #include "lldb/Core/ValueObject.h"
 #include "lldb/Core/ValueObjectConstResult.h"
 #include "lldb/DataFormatters/FormattersHelpers.h"
 #include "lldb/Expression/FunctionCaller.h"
-#include "lldb/Symbol/TypeSystemClang.h"
 #include "lldb/Target/Language.h"
 #include "lldb/Target/Target.h"
 #include "lldb/Utility/DataBufferHeap.h"
index 98c0926d22f34f89f65e6fc388fb703d874ae10c..2b228850987c21bb741fa306789faa03b17463e1 100644 (file)
 #include "NSDictionary.h"
 
 #include "Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h"
+#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
 
 #include "lldb/Core/ValueObject.h"
 #include "lldb/Core/ValueObjectConstResult.h"
 #include "lldb/DataFormatters/FormattersHelpers.h"
-#include "lldb/Symbol/TypeSystemClang.h"
 #include "lldb/Target/Language.h"
 #include "lldb/Target/StackFrame.h"
 #include "lldb/Target/Target.h"
index ae0ea28d727fde32e38ceaf8519cb713e26ef68c..aa1103cb342cbb76382737991fdaba48a8946b47 100644 (file)
 
 #include "Cocoa.h"
 
+#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
 #include "lldb/Core/ValueObject.h"
 #include "lldb/Core/ValueObjectConstResult.h"
 #include "lldb/DataFormatters/FormattersHelpers.h"
-#include "lldb/Symbol/TypeSystemClang.h"
 #include "lldb/Target/ProcessStructReader.h"
 #include "lldb/Target/Target.h"
 #include "lldb/Utility/DataBufferHeap.h"
index 60486a4915df13ed37177dfd6cf7dc9feae2923b..c6bae5e1c0087afd792f279ef6fc92a20fdc3f9c 100644 (file)
@@ -13,7 +13,6 @@
 #include "lldb/Core/ValueObject.h"
 #include "lldb/Core/ValueObjectConstResult.h"
 #include "lldb/DataFormatters/FormattersHelpers.h"
-#include "lldb/Symbol/TypeSystemClang.h"
 #include "lldb/Target/ProcessStructReader.h"
 #include "lldb/Target/Target.h"
 #include "lldb/Utility/DataBufferHeap.h"
@@ -23,6 +22,7 @@
 
 #include "Plugins/Language/ObjC/NSString.h"
 #include "Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.h"
+#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
 
 using namespace lldb;
 using namespace lldb_private;
index 6b645d5e404acdd9e020b235e1cdb860314b009c..d962f39611b60deca42a5faafe65178b86f566bc 100644 (file)
@@ -8,11 +8,11 @@
 
 #include "Cocoa.h"
 
+#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
 #include "lldb/Core/ValueObject.h"
 #include "lldb/Core/ValueObjectConstResult.h"
 #include "lldb/DataFormatters/FormattersHelpers.h"
 #include "lldb/DataFormatters/TypeSynthetic.h"
-#include "lldb/Symbol/TypeSystemClang.h"
 #include "lldb/Target/Process.h"
 #include "lldb/Target/Target.h"
 
index a89556217f7968eedc99626659e816bf79d483ad..59597bed85b5f6a58bfd9d107ae9ea3eecdc28cd 100644 (file)
@@ -9,10 +9,10 @@
 #include "NSSet.h"
 
 #include "Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h"
+#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
 #include "lldb/Core/ValueObject.h"
 #include "lldb/Core/ValueObjectConstResult.h"
 #include "lldb/DataFormatters/FormattersHelpers.h"
-#include "lldb/Symbol/TypeSystemClang.h"
 #include "lldb/Target/Language.h"
 #include "lldb/Target/Target.h"
 #include "lldb/Utility/DataBufferHeap.h"
index bbe05afff39f659fbabdfeceae1c9a028f2adfe8..65256dc7acbdde86c479a72eee8ad3d2493b19c7 100644 (file)
@@ -8,11 +8,11 @@
 
 #include "NSString.h"
 
+#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
 #include "lldb/Core/ValueObject.h"
 #include "lldb/Core/ValueObjectConstResult.h"
 #include "lldb/DataFormatters/FormattersHelpers.h"
 #include "lldb/DataFormatters/StringPrinter.h"
-#include "lldb/Symbol/TypeSystemClang.h"
 #include "lldb/Target/Language.h"
 #include "lldb/Target/ProcessStructReader.h"
 #include "lldb/Target/Target.h"
index d3710435b8e7e7769ca782886777f0a544e77376..aa699649d942f7fc586a87e29318a30ac1fd64bb 100644 (file)
 
 #include "ObjCLanguage.h"
 
+#include "Plugins/ExpressionParser/Clang/ClangUtil.h"
+#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
 #include "lldb/Core/PluginManager.h"
 #include "lldb/Core/ValueObject.h"
 #include "lldb/DataFormatters/DataVisualization.h"
 #include "lldb/DataFormatters/FormattersHelpers.h"
-#include "lldb/Symbol/TypeSystemClang.h"
-#include "lldb/Symbol/ClangUtil.h"
 #include "lldb/Symbol/CompilerType.h"
 #include "lldb/Target/Target.h"
 #include "lldb/Utility/ConstString.h"
index 508a361aa6ddff6413c377f6ebb8f44ff0a03621..0260212266fbd5463fe20c86ea8e72b32d0c838c 100644 (file)
@@ -5,6 +5,7 @@ add_lldb_library(lldbPluginCPPRuntime PLUGIN
     lldbCore
     lldbSymbol
     lldbTarget
+    lldbPluginTypeSystemClang
 )
 
 add_subdirectory(ItaniumABI)
index f106b1439f8379b2ebc4068880112975023ede4f..64348840ccb8bbb94c1567c832b116d9a811f142 100644 (file)
@@ -18,9 +18,9 @@
 #include "lldb/Symbol/Variable.h"
 #include "lldb/Symbol/VariableList.h"
 
+#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
 #include "lldb/Core/PluginManager.h"
 #include "lldb/Core/UniqueCStringMap.h"
-#include "lldb/Symbol/TypeSystemClang.h"
 #include "lldb/Symbol/CompileUnit.h"
 #include "lldb/Target/ABI.h"
 #include "lldb/Target/ExecutionContext.h"
index 52c297d944b9f94079f45b8244a6e96a851eb557..5ab494414ac5bf6371072ce75025381d4922397f 100644 (file)
@@ -8,4 +8,5 @@ add_lldb_library(lldbPluginCXXItaniumABI PLUGIN
     lldbSymbol
     lldbTarget
     lldbPluginCPPRuntime
+    lldbPluginTypeSystemClang
   )
index eed1fb71805cc9c03830631d7c6b263a0ca368ca..097e5ee6fe166585ea6bc8082718ec81c660c6c6 100644 (file)
@@ -8,6 +8,7 @@
 
 #include "ItaniumABILanguageRuntime.h"
 
+#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
 #include "lldb/Breakpoint/BreakpointLocation.h"
 #include "lldb/Core/Mangled.h"
 #include "lldb/Core/Module.h"
@@ -20,7 +21,6 @@
 #include "lldb/Interpreter/CommandObject.h"
 #include "lldb/Interpreter/CommandObjectMultiword.h"
 #include "lldb/Interpreter/CommandReturnObject.h"
-#include "lldb/Symbol/TypeSystemClang.h"
 #include "lldb/Symbol/Symbol.h"
 #include "lldb/Symbol/SymbolFile.h"
 #include "lldb/Symbol/TypeList.h"
index 2701f5b3a45e313844729bc043a3cf6523daf243..0ac0c577e443b7ed25edfd364aad9331c16ae13f 100644 (file)
@@ -8,10 +8,10 @@
 
 #include "AppleObjCDeclVendor.h"
 
+#include "Plugins/ExpressionParser/Clang/ClangASTMetadata.h"
+#include "Plugins/ExpressionParser/Clang/ClangUtil.h"
 #include "Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.h"
 #include "lldb/Core/Module.h"
-#include "lldb/Symbol/ClangASTMetadata.h"
-#include "lldb/Symbol/ClangUtil.h"
 #include "lldb/Target/Process.h"
 #include "lldb/Target/Target.h"
 #include "lldb/Utility/Log.h"
index eee802766117c117068441ef8950c035226e7358..0d66cc781320f07851c20083bee0ef773d6dcee3 100644 (file)
@@ -9,11 +9,11 @@
 #ifndef liblldb_AppleObjCDeclVendor_h_
 #define liblldb_AppleObjCDeclVendor_h_
 
-#include "lldb/Symbol/TypeSystemClang.h"
 #include "lldb/lldb-private.h"
 
 #include "Plugins/ExpressionParser/Clang/ClangDeclVendor.h"
 #include "Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.h"
+#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
 
 namespace lldb_private {
 
index 686c2cf19aaed3da2dc3ce34b439c446fde751c8..f8f0d56836fd90ee106a0929984fe0020a95b012 100644 (file)
@@ -23,7 +23,6 @@
 #include "lldb/DataFormatters/FormattersHelpers.h"
 #include "lldb/Expression/DiagnosticManager.h"
 #include "lldb/Expression/FunctionCaller.h"
-#include "lldb/Symbol/TypeSystemClang.h"
 #include "lldb/Symbol/ObjectFile.h"
 #include "lldb/Target/ExecutionContext.h"
 #include "lldb/Target/Process.h"
@@ -38,6 +37,8 @@
 #include "lldb/Utility/StreamString.h"
 #include "clang/AST/Type.h"
 
+#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
+
 #include <vector>
 
 using namespace lldb;
index 73f1b08dc699d9a44765cf4952e4f07da2a48f8f..3d3c69a75f2bf327cf8d033bb8b58b916f2bd561 100644 (file)
 
 #include "clang/AST/Type.h"
 
+#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
 #include "lldb/Breakpoint/BreakpointLocation.h"
 #include "lldb/Core/Module.h"
 #include "lldb/Core/PluginManager.h"
 #include "lldb/Expression/FunctionCaller.h"
 #include "lldb/Expression/UtilityFunction.h"
-#include "lldb/Symbol/TypeSystemClang.h"
 #include "lldb/Symbol/Symbol.h"
 #include "lldb/Target/ExecutionContext.h"
 #include "lldb/Target/Process.h"
index e5c816d7eef5237f2fc22b66f2a8af2b1b615038..8b94234605eb13e27b051aa695d2e0b83fdafc97 100644 (file)
@@ -20,6 +20,7 @@
 #include "lldb/Symbol/CompilerType.h"
 #include "lldb/lldb-enumerations.h"
 
+#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
 #include "lldb/Core/ClangForward.h"
 #include "lldb/Core/Debugger.h"
 #include "lldb/Core/Module.h"
@@ -35,7 +36,6 @@
 #include "lldb/Interpreter/CommandReturnObject.h"
 #include "lldb/Interpreter/OptionArgParser.h"
 #include "lldb/Interpreter/OptionValueBoolean.h"
-#include "lldb/Symbol/TypeSystemClang.h"
 #include "lldb/Symbol/ObjectFile.h"
 #include "lldb/Symbol/Symbol.h"
 #include "lldb/Symbol/TypeList.h"
index 611f9b46655c418ed6ffd1db8f731d41d9d289c6..9b5e6777e9e14fd5a3fb4d4a969c1ba5b3b3bcf3 100644 (file)
@@ -9,6 +9,7 @@
 #include "AppleObjCTrampolineHandler.h"
 #include "AppleThreadPlanStepThroughObjCTrampoline.h"
 
+#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
 #include "lldb/Breakpoint/StoppointCallbackContext.h"
 #include "lldb/Core/Debugger.h"
 #include "lldb/Core/Module.h"
@@ -18,7 +19,6 @@
 #include "lldb/Expression/FunctionCaller.h"
 #include "lldb/Expression/UserExpression.h"
 #include "lldb/Expression/UtilityFunction.h"
-#include "lldb/Symbol/TypeSystemClang.h"
 #include "lldb/Symbol/Symbol.h"
 #include "lldb/Target/ABI.h"
 #include "lldb/Target/ExecutionContext.h"
index 7e72f94931b8649504228061fc3e1e913121f559..5f9bf5deb340ba4186929f2725a716fe003f92b9 100644 (file)
@@ -8,8 +8,8 @@
 
 #include "AppleObjCTypeEncodingParser.h"
 
-#include "lldb/Symbol/TypeSystemClang.h"
-#include "lldb/Symbol/ClangUtil.h"
+#include "Plugins/ExpressionParser/Clang/ClangUtil.h"
+#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
 #include "lldb/Symbol/CompilerType.h"
 #include "lldb/Target/Process.h"
 #include "lldb/Target/Target.h"
index bcf324023c221520ba73ac7d88ca95a13909b294..3789f56325980bb59ad5786c288e2ef86a761403 100644 (file)
@@ -19,6 +19,7 @@ add_lldb_library(lldbPluginAppleObjCRuntime PLUGIN
     lldbUtility
     lldbPluginExpressionParserClang
     lldbPluginCPPRuntime
+    lldbPluginTypeSystemClang
   CLANG_LIBS
     clangAST
   LINK_COMPONENTS
index 3ce672f9d6819b6673e2c9376a2d305e72f394dc..a9e48e2cabfe0ecc99c0dfaf6a4c54f3e542e42d 100644 (file)
@@ -9,11 +9,11 @@
 
 #include "ObjCLanguageRuntime.h"
 
+#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
 #include "lldb/Core/MappedHash.h"
 #include "lldb/Core/Module.h"
 #include "lldb/Core/PluginManager.h"
 #include "lldb/Core/ValueObject.h"
-#include "lldb/Symbol/TypeSystemClang.h"
 #include "lldb/Symbol/SymbolContext.h"
 #include "lldb/Symbol/SymbolFile.h"
 #include "lldb/Symbol/Type.h"
index 749407d63d5c97c37e643e6c60ae2f930109f5fb..c4c62e46add3d95a59cc7de84a56b7544059dc87 100644 (file)
@@ -7,4 +7,5 @@ add_lldb_library(lldbPluginPlatformPOSIX PLUGIN
     lldbHost
     lldbInterpreter
     lldbTarget
+    lldbPluginTypeSystemClang
   )
index 0185ba43b1150f8f28a5072f43225ac197a0cc56..4bd6509ec2ec342e2315be607ddbf76b5a8df364 100644 (file)
@@ -8,6 +8,7 @@
 
 #include "PlatformPOSIX.h"
 
+#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
 #include "lldb/Core/Debugger.h"
 #include "lldb/Core/Module.h"
 #include "lldb/Core/ModuleSpec.h"
@@ -22,7 +23,6 @@
 #include "lldb/Host/Host.h"
 #include "lldb/Host/HostInfo.h"
 #include "lldb/Host/ProcessLaunchInfo.h"
-#include "lldb/Symbol/TypeSystemClang.h"
 #include "lldb/Target/DynamicLoader.h"
 #include "lldb/Target/ExecutionContext.h"
 #include "lldb/Target/Process.h"
index 4a3bc81afa7d4e944985c81192442d8992eb3ab2..49de7df9c74ec025b5d200d0f99e5bc91fa0ee3e 100644 (file)
@@ -53,6 +53,7 @@ add_lldb_library(lldbPluginSymbolFileDWARF PLUGIN
     lldbPluginObjCLanguage
     lldbPluginCPlusPlusLanguage
     lldbPluginExpressionParserClang
+    lldbPluginTypeSystemClang
   CLANG_LIBS
     clangAST
     clangBasic
index db49010a846f3e606a7f4770bd645c0c8345c495..f86460a3adac895b884a2d291e7561968551d549 100644 (file)
 #include "SymbolFileDWARFDebugMap.h"
 #include "UniqueDWARFASTType.h"
 
+#include "Plugins/ExpressionParser/Clang/ClangASTImporter.h"
+#include "Plugins/ExpressionParser/Clang/ClangASTMetadata.h"
+#include "Plugins/ExpressionParser/Clang/ClangUtil.h"
 #include "Plugins/Language/ObjC/ObjCLanguage.h"
 #include "lldb/Core/Module.h"
 #include "lldb/Core/Value.h"
 #include "lldb/Host/Host.h"
-#include "lldb/Symbol/ClangASTImporter.h"
-#include "lldb/Symbol/ClangASTMetadata.h"
-#include "lldb/Symbol/ClangUtil.h"
 #include "lldb/Symbol/CompileUnit.h"
 #include "lldb/Symbol/Function.h"
 #include "lldb/Symbol/ObjectFile.h"
index 6cd2dc8bf55802e48ac7e108397e5fa3e1bd14d1..9282131301f5d230fe3658e18ba615ae8a78c273 100644 (file)
@@ -21,8 +21,9 @@
 #include "LogChannelDWARF.h"
 #include "lldb/Core/ClangForward.h"
 #include "lldb/Core/PluginInterface.h"
-#include "lldb/Symbol/TypeSystemClang.h"
-#include "lldb/Symbol/ClangASTImporter.h"
+
+#include "Plugins/ExpressionParser/Clang/ClangASTImporter.h"
+#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
 
 #include <vector>
 
index 5ef2dd3f04b362a809c23c44a9727fcac6dff896..2d7ffde8a54e5f987e97b900a3db992087715fb5 100644 (file)
@@ -34,9 +34,9 @@
 #include "lldb/Interpreter/OptionValueFileSpecList.h"
 #include "lldb/Interpreter/OptionValueProperties.h"
 
+#include "Plugins/ExpressionParser/Clang/ClangUtil.h"
+#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
 #include "lldb/Symbol/Block.h"
-#include "lldb/Symbol/TypeSystemClang.h"
-#include "lldb/Symbol/ClangUtil.h"
 #include "lldb/Symbol/CompileUnit.h"
 #include "lldb/Symbol/CompilerDecl.h"
 #include "lldb/Symbol/CompilerDeclContext.h"
index aaecec4765f57ec2530fbc1c4343344c2c43dead..4f19231c346ca516c6da145ff30a6136733ce619 100644 (file)
@@ -14,6 +14,7 @@ add_lldb_library(lldbPluginSymbolFileNativePDB PLUGIN
     lldbCore
     lldbSymbol
     lldbUtility
+    lldbPluginTypeSystemClang
   CLANG_LIBS
     clangAST
     clangLex
index aa9fff3e4acb3de2439be2cd7ccfdaa976fdf035..1e9c24e98e41adb0fdf23252e98dec8c82617458 100644 (file)
 #include "llvm/DebugInfo/PDB/Native/TpiStream.h"
 #include "llvm/Demangle/MicrosoftDemangle.h"
 
+#include "Plugins/ExpressionParser/Clang/ClangASTMetadata.h"
+#include "Plugins/ExpressionParser/Clang/ClangUtil.h"
 #include "Plugins/Language/CPlusPlus/MSVCUndecoratedNameParser.h"
+#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
 #include "lldb/Core/Module.h"
-#include "lldb/Symbol/TypeSystemClang.h"
-#include "lldb/Symbol/ClangASTMetadata.h"
-#include "lldb/Symbol/ClangUtil.h"
 #include "lldb/Symbol/ObjectFile.h"
 #include "lldb/Utility/LLDBAssert.h"
 
index 78f19b85c359c3a39e138b5b4673c4b2d64f3c12..f31eeb57cc5c00a70da0e6a26a92254bf6c3f82f 100644 (file)
@@ -12,7 +12,7 @@
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/StringRef.h"
 
-#include "lldb/Symbol/ClangASTImporter.h"
+#include "Plugins/ExpressionParser/Clang/ClangASTImporter.h"
 
 #include "PdbIndex.h"
 #include "PdbSymUid.h"
index 85ce87e61eaad0b612b7df526c890039ccfbe784..73dec53eda6aba162ccc35c0d7d64a0339d881de 100644 (file)
 #include "clang/AST/DeclCXX.h"
 #include "clang/AST/Type.h"
 
+#include "Plugins/ExpressionParser/Clang/ClangUtil.h"
 #include "Plugins/Language/CPlusPlus/MSVCUndecoratedNameParser.h"
+#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
 #include "lldb/Core/Module.h"
 #include "lldb/Core/PluginManager.h"
 #include "lldb/Core/StreamBuffer.h"
 #include "lldb/Core/StreamFile.h"
-#include "lldb/Symbol/TypeSystemClang.h"
-#include "lldb/Symbol/ClangUtil.h"
 #include "lldb/Symbol/CompileUnit.h"
 #include "lldb/Symbol/LineTable.h"
 #include "lldb/Symbol/ObjectFile.h"
index 9ecd4e2e144026512d0eba98fb752f965cb6b68e..308ba9e3dec0b2549bf3ea02c9d196f6a41218ac 100644 (file)
@@ -5,8 +5,8 @@
 #include "PdbSymUid.h"
 #include "PdbUtil.h"
 
-#include "lldb/Symbol/TypeSystemClang.h"
-#include "lldb/Symbol/ClangASTImporter.h"
+#include "Plugins/ExpressionParser/Clang/ClangASTImporter.h"
+#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
 #include "lldb/Symbol/Type.h"
 #include "lldb/Utility/LLDBAssert.h"
 #include "lldb/lldb-enumerations.h"
index 55397582209b89f085a1cec0d2b479d857b1ca28..1b082785764e282eca3fb41ed0d0063fb5920508 100644 (file)
@@ -9,7 +9,7 @@
 #ifndef LLDB_PLUGINS_SYMBOLFILE_NATIVEPDB_UDTRECORDCOMPLETER_H
 #define LLDB_PLUGINS_SYMBOLFILE_NATIVEPDB_UDTRECORDCOMPLETER_H
 
-#include "lldb/Symbol/ClangASTImporter.h"
+#include "Plugins/ExpressionParser/Clang/ClangASTImporter.h"
 #include "llvm/DebugInfo/CodeView/CVRecord.h"
 #include "llvm/DebugInfo/CodeView/TypeRecord.h"
 #include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
index 79bdce4277c75f2ff5f76f2bc666ea8172dec74a..ceeb173a99e1d61dfec57f046afadf3016751cc1 100644 (file)
@@ -8,6 +8,7 @@ add_lldb_library(lldbPluginSymbolFilePDB PLUGIN
     lldbPluginSymbolFileNativePDB
     lldbSymbol
     lldbUtility
+    lldbPluginTypeSystemClang
   CLANG_LIBS
     clangAST
     clangLex
index 010a9eaa76f5efeadb7639d5350cc2601a63ca9b..48bc57272c2a156301e9a918380518880f76d829 100644 (file)
 #include "clang/AST/Decl.h"
 #include "clang/AST/DeclCXX.h"
 
+#include "Plugins/ExpressionParser/Clang/ClangASTMetadata.h"
+#include "Plugins/ExpressionParser/Clang/ClangUtil.h"
+#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
 #include "lldb/Core/Module.h"
-#include "lldb/Symbol/TypeSystemClang.h"
-#include "lldb/Symbol/ClangASTMetadata.h"
-#include "lldb/Symbol/ClangUtil.h"
 #include "lldb/Symbol/Declaration.h"
 #include "lldb/Symbol/SymbolFile.h"
 #include "lldb/Symbol/TypeMap.h"
index 6ded624fa435f40d165b0c1b691297872e3ae471..06ae32c664c5e55efddf289fb1b1335707e36f77 100644 (file)
@@ -11,7 +11,7 @@
 
 #include "lldb/lldb-forward.h"
 
-#include "lldb/Symbol/ClangASTImporter.h"
+#include "Plugins/ExpressionParser/Clang/ClangASTImporter.h"
 
 class SymbolFilePDB;
 
index 04a9dae68358bdafb296b4b7f3f3cadeafcade24..5f1ff5d5ccc0858972ab45193feb8e237c09196d 100644 (file)
@@ -13,9 +13,9 @@
 
 #include "clang/Lex/Lexer.h"
 
+#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
 #include "lldb/Core/Module.h"
 #include "lldb/Core/PluginManager.h"
-#include "lldb/Symbol/TypeSystemClang.h"
 #include "lldb/Symbol/CompileUnit.h"
 #include "lldb/Symbol/LineTable.h"
 #include "lldb/Symbol/ObjectFile.h"
index cb7311cebf31d769b0bd2ba580e8ecbe31c29be3..fc5c5a65ce44c64370a9bdd3ca6fee69398f0f4f 100644 (file)
@@ -8,13 +8,12 @@
 
 #include "AppleGetItemInfoHandler.h"
 
-
+#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
 #include "lldb/Core/Module.h"
 #include "lldb/Core/Value.h"
 #include "lldb/Expression/DiagnosticManager.h"
 #include "lldb/Expression/FunctionCaller.h"
 #include "lldb/Expression/UtilityFunction.h"
-#include "lldb/Symbol/TypeSystemClang.h"
 #include "lldb/Symbol/Symbol.h"
 #include "lldb/Target/ExecutionContext.h"
 #include "lldb/Target/Process.h"
index 5cd426efb5f968e9360c950550bfe017a9561667..2c220357ce5678a87940a61f812e6b8365bbf383 100644 (file)
@@ -8,13 +8,12 @@
 
 #include "AppleGetPendingItemsHandler.h"
 
-
+#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
 #include "lldb/Core/Module.h"
 #include "lldb/Core/Value.h"
 #include "lldb/Expression/DiagnosticManager.h"
 #include "lldb/Expression/FunctionCaller.h"
 #include "lldb/Expression/UtilityFunction.h"
-#include "lldb/Symbol/TypeSystemClang.h"
 #include "lldb/Symbol/Symbol.h"
 #include "lldb/Target/ExecutionContext.h"
 #include "lldb/Target/Process.h"
index 2848851288505e5c046c9d2a077bef5fa957d6a0..574e3276002749ff63faf8732a276ba7970b0377 100644 (file)
@@ -8,12 +8,12 @@
 
 #include "AppleGetQueuesHandler.h"
 
+#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
 #include "lldb/Core/Module.h"
 #include "lldb/Core/Value.h"
 #include "lldb/Expression/DiagnosticManager.h"
 #include "lldb/Expression/FunctionCaller.h"
 #include "lldb/Expression/UtilityFunction.h"
-#include "lldb/Symbol/TypeSystemClang.h"
 #include "lldb/Symbol/Symbol.h"
 #include "lldb/Target/ExecutionContext.h"
 #include "lldb/Target/Process.h"
index af4f0b299537b064cd88f207212ce70aaa921d2e..c86d40655a0533cec79f4f40474660ad93cb3395 100644 (file)
@@ -8,14 +8,13 @@
 
 #include "AppleGetThreadItemInfoHandler.h"
 
-
+#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
 #include "lldb/Core/Module.h"
 #include "lldb/Core/Value.h"
 #include "lldb/Expression/DiagnosticManager.h"
 #include "lldb/Expression/Expression.h"
 #include "lldb/Expression/FunctionCaller.h"
 #include "lldb/Expression/UtilityFunction.h"
-#include "lldb/Symbol/TypeSystemClang.h"
 #include "lldb/Symbol/Symbol.h"
 #include "lldb/Target/ExecutionContext.h"
 #include "lldb/Target/Process.h"
index ac5781b98b09c4bb4817872dc988628977023fa5..04d30652ba4b405198d38373ad92636d18cbeda1 100644 (file)
@@ -14,4 +14,5 @@ add_lldb_library(lldbPluginSystemRuntimeMacOSX PLUGIN
     lldbTarget
     lldbUtility
     lldbPluginProcessUtility
+    lldbPluginTypeSystemClang
   )
index f96a7dcbbdcdd257a2a4671025c542b492b8ec56..726451178c1606918beec7cc10fc650e29d4aa9b 100644 (file)
@@ -7,12 +7,12 @@
 //===----------------------------------------------------------------------===//
 
 #include "Plugins/Process/Utility/HistoryThread.h"
+#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
 #include "lldb/Breakpoint/StoppointCallbackContext.h"
 #include "lldb/Core/Module.h"
 #include "lldb/Core/ModuleSpec.h"
 #include "lldb/Core/PluginManager.h"
 #include "lldb/Core/Section.h"
-#include "lldb/Symbol/TypeSystemClang.h"
 #include "lldb/Symbol/ObjectFile.h"
 #include "lldb/Symbol/SymbolContext.h"
 #include "lldb/Target/Process.h"
diff --git a/lldb/source/Plugins/TypeSystem/CMakeLists.txt b/lldb/source/Plugins/TypeSystem/CMakeLists.txt
new file mode 100644 (file)
index 0000000..17c40ae
--- /dev/null
@@ -0,0 +1 @@
+add_subdirectory(Clang)
diff --git a/lldb/source/Plugins/TypeSystem/Clang/CMakeLists.txt b/lldb/source/Plugins/TypeSystem/Clang/CMakeLists.txt
new file mode 100644 (file)
index 0000000..37a3142
--- /dev/null
@@ -0,0 +1,20 @@
+add_lldb_library(lldbPluginTypeSystemClang PLUGIN
+  TypeSystemClang.cpp
+
+  LINK_LIBS
+    lldbCore
+    lldbSymbol
+    lldbTarget
+    lldbUtility
+    lldbPluginExpressionParserClang
+    lldbPluginSymbolFileDWARF
+    lldbPluginSymbolFilePDB
+    lldbPluginObjCRuntime
+  CLANG_LIBS
+    clangAST
+    clangBasic
+    clangFrontend
+    clangSema
+  LINK_COMPONENTS
+    Support
+)
diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
new file mode 100644 (file)
index 0000000..ef5d376
--- /dev/null
@@ -0,0 +1,9318 @@
+//===-- TypeSystemClang.cpp -----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "TypeSystemClang.h"
+
+#include "llvm/Support/FormatAdapters.h"
+#include "llvm/Support/FormatVariadic.h"
+
+#include <mutex>
+#include <string>
+#include <vector>
+
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/ASTImporter.h"
+#include "clang/AST/Attr.h"
+#include "clang/AST/CXXInheritance.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/Mangle.h"
+#include "clang/AST/RecordLayout.h"
+#include "clang/AST/Type.h"
+#include "clang/AST/VTableBuilder.h"
+#include "clang/Basic/Builtins.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/FileSystemOptions.h"
+#include "clang/Basic/LangStandard.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/TargetOptions.h"
+#include "clang/Frontend/FrontendOptions.h"
+#include "clang/Sema/Sema.h"
+
+#include "llvm/Support/Signals.h"
+#include "llvm/Support/Threading.h"
+
+#include "Plugins/ExpressionParser/Clang/ClangASTImporter.h"
+#include "Plugins/ExpressionParser/Clang/ClangASTMetadata.h"
+#include "Plugins/ExpressionParser/Clang/ClangExternalASTSourceCallbacks.h"
+#include "Plugins/ExpressionParser/Clang/ClangFunctionCaller.h"
+#include "Plugins/ExpressionParser/Clang/ClangPersistentVariables.h"
+#include "Plugins/ExpressionParser/Clang/ClangUserExpression.h"
+#include "Plugins/ExpressionParser/Clang/ClangUtil.h"
+#include "Plugins/ExpressionParser/Clang/ClangUtilityFunction.h"
+#include "lldb/Utility/ArchSpec.h"
+#include "lldb/Utility/Flags.h"
+
+#include "lldb/Core/DumpDataExtractor.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/StreamFile.h"
+#include "lldb/Core/ThreadSafeDenseMap.h"
+#include "lldb/Core/UniqueCStringMap.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Symbol/SymbolFile.h"
+#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Target/Language.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Utility/DataExtractor.h"
+#include "lldb/Utility/LLDBAssert.h"
+#include "lldb/Utility/Log.h"
+#include "lldb/Utility/RegularExpression.h"
+#include "lldb/Utility/Scalar.h"
+
+#include "Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.h"
+#include "Plugins/SymbolFile/DWARF/DWARFASTParserClang.h"
+#include "Plugins/SymbolFile/PDB/PDBASTParser.h"
+
+#include <stdio.h>
+
+#include <mutex>
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace clang;
+using llvm::StringSwitch;
+
+namespace {
+#ifdef LLDB_CONFIGURATION_DEBUG
+static void VerifyDecl(clang::Decl *decl) {
+  assert(decl && "VerifyDecl called with nullptr?");
+  decl->getAccess();
+}
+#endif
+
+static inline bool
+TypeSystemClangSupportsLanguage(lldb::LanguageType language) {
+  return language == eLanguageTypeUnknown || // Clang is the default type system
+         lldb_private::Language::LanguageIsC(language) ||
+         lldb_private::Language::LanguageIsCPlusPlus(language) ||
+         lldb_private::Language::LanguageIsObjC(language) ||
+         lldb_private::Language::LanguageIsPascal(language) ||
+         // Use Clang for Rust until there is a proper language plugin for it
+         language == eLanguageTypeRust ||
+         language == eLanguageTypeExtRenderScript ||
+         // Use Clang for D until there is a proper language plugin for it
+         language == eLanguageTypeD ||
+         // Open Dylan compiler debug info is designed to be Clang-compatible
+         language == eLanguageTypeDylan;
+}
+
+// Checks whether m1 is an overload of m2 (as opposed to an override). This is
+// called by addOverridesForMethod to distinguish overrides (which share a
+// vtable entry) from overloads (which require distinct entries).
+bool isOverload(clang::CXXMethodDecl *m1, clang::CXXMethodDecl *m2) {
+  // FIXME: This should detect covariant return types, but currently doesn't.
+  lldbassert(&m1->getASTContext() == &m2->getASTContext() &&
+             "Methods should have the same AST context");
+  clang::ASTContext &context = m1->getASTContext();
+
+  const auto *m1Type = llvm::cast<clang::FunctionProtoType>(
+      context.getCanonicalType(m1->getType()));
+
+  const auto *m2Type = llvm::cast<clang::FunctionProtoType>(
+      context.getCanonicalType(m2->getType()));
+
+  auto compareArgTypes = [&context](const clang::QualType &m1p,
+                                    const clang::QualType &m2p) {
+    return context.hasSameType(m1p.getUnqualifiedType(),
+                               m2p.getUnqualifiedType());
+  };
+
+  // FIXME: In C++14 and later, we can just pass m2Type->param_type_end()
+  //        as a fourth parameter to std::equal().
+  return (m1->getNumParams() != m2->getNumParams()) ||
+         !std::equal(m1Type->param_type_begin(), m1Type->param_type_end(),
+                     m2Type->param_type_begin(), compareArgTypes);
+}
+
+// If decl is a virtual method, walk the base classes looking for methods that
+// decl overrides. This table of overridden methods is used by IRGen to
+// determine the vtable layout for decl's parent class.
+void addOverridesForMethod(clang::CXXMethodDecl *decl) {
+  if (!decl->isVirtual())
+    return;
+
+  clang::CXXBasePaths paths;
+
+  auto find_overridden_methods =
+      [decl](const clang::CXXBaseSpecifier *specifier,
+             clang::CXXBasePath &path) {
+        if (auto *base_record = llvm::dyn_cast<clang::CXXRecordDecl>(
+                specifier->getType()->getAs<clang::RecordType>()->getDecl())) {
+
+          clang::DeclarationName name = decl->getDeclName();
+
+          // If this is a destructor, check whether the base class destructor is
+          // virtual.
+          if (name.getNameKind() == clang::DeclarationName::CXXDestructorName)
+            if (auto *baseDtorDecl = base_record->getDestructor()) {
+              if (baseDtorDecl->isVirtual()) {
+                path.Decls = baseDtorDecl;
+                return true;
+              } else
+                return false;
+            }
+
+          // Otherwise, search for name in the base class.
+          for (path.Decls = base_record->lookup(name); !path.Decls.empty();
+               path.Decls = path.Decls.slice(1)) {
+            if (auto *method_decl =
+                    llvm::dyn_cast<clang::CXXMethodDecl>(path.Decls.front()))
+              if (method_decl->isVirtual() && !isOverload(decl, method_decl)) {
+                path.Decls = method_decl;
+                return true;
+              }
+          }
+        }
+
+        return false;
+      };
+
+  if (decl->getParent()->lookupInBases(find_overridden_methods, paths)) {
+    for (auto *overridden_decl : paths.found_decls())
+      decl->addOverriddenMethod(
+          llvm::cast<clang::CXXMethodDecl>(overridden_decl));
+  }
+}
+}
+
+static lldb::addr_t GetVTableAddress(Process &process,
+                                     VTableContextBase &vtable_ctx,
+                                     ValueObject &valobj,
+                                     const ASTRecordLayout &record_layout) {
+  // Retrieve type info
+  CompilerType pointee_type;
+  CompilerType this_type(valobj.GetCompilerType());
+  uint32_t type_info = this_type.GetTypeInfo(&pointee_type);
+  if (!type_info)
+    return LLDB_INVALID_ADDRESS;
+
+  // Check if it's a pointer or reference
+  bool ptr_or_ref = false;
+  if (type_info & (eTypeIsPointer | eTypeIsReference)) {
+    ptr_or_ref = true;
+    type_info = pointee_type.GetTypeInfo();
+  }
+
+  // We process only C++ classes
+  const uint32_t cpp_class = eTypeIsClass | eTypeIsCPlusPlus;
+  if ((type_info & cpp_class) != cpp_class)
+    return LLDB_INVALID_ADDRESS;
+
+  // Calculate offset to VTable pointer
+  lldb::offset_t vbtable_ptr_offset =
+      vtable_ctx.isMicrosoft() ? record_layout.getVBPtrOffset().getQuantity()
+                               : 0;
+
+  if (ptr_or_ref) {
+    // We have a pointer / ref to object, so read
+    // VTable pointer from process memory
+
+    if (valobj.GetAddressTypeOfChildren() != eAddressTypeLoad)
+      return LLDB_INVALID_ADDRESS;
+
+    auto vbtable_ptr_addr = valobj.GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
+    if (vbtable_ptr_addr == LLDB_INVALID_ADDRESS)
+      return LLDB_INVALID_ADDRESS;
+
+    vbtable_ptr_addr += vbtable_ptr_offset;
+
+    Status err;
+    return process.ReadPointerFromMemory(vbtable_ptr_addr, err);
+  }
+
+  // We have an object already read from process memory,
+  // so just extract VTable pointer from it
+
+  DataExtractor data;
+  Status err;
+  auto size = valobj.GetData(data, err);
+  if (err.Fail() || vbtable_ptr_offset + data.GetAddressByteSize() > size)
+    return LLDB_INVALID_ADDRESS;
+
+  return data.GetPointer(&vbtable_ptr_offset);
+}
+
+static int64_t ReadVBaseOffsetFromVTable(Process &process,
+                                         VTableContextBase &vtable_ctx,
+                                         lldb::addr_t vtable_ptr,
+                                         const CXXRecordDecl *cxx_record_decl,
+                                         const CXXRecordDecl *base_class_decl) {
+  if (vtable_ctx.isMicrosoft()) {
+    clang::MicrosoftVTableContext &msoft_vtable_ctx =
+        static_cast<clang::MicrosoftVTableContext &>(vtable_ctx);
+
+    // Get the index into the virtual base table. The
+    // index is the index in uint32_t from vbtable_ptr
+    const unsigned vbtable_index =
+        msoft_vtable_ctx.getVBTableIndex(cxx_record_decl, base_class_decl);
+    const lldb::addr_t base_offset_addr = vtable_ptr + vbtable_index * 4;
+    Status err;
+    return process.ReadSignedIntegerFromMemory(base_offset_addr, 4, INT64_MAX,
+                                               err);
+  }
+
+  clang::ItaniumVTableContext &itanium_vtable_ctx =
+      static_cast<clang::ItaniumVTableContext &>(vtable_ctx);
+
+  clang::CharUnits base_offset_offset =
+      itanium_vtable_ctx.getVirtualBaseOffsetOffset(cxx_record_decl,
+                                                    base_class_decl);
+  const lldb::addr_t base_offset_addr =
+      vtable_ptr + base_offset_offset.getQuantity();
+  const uint32_t base_offset_size = process.GetAddressByteSize();
+  Status err;
+  return process.ReadSignedIntegerFromMemory(base_offset_addr, base_offset_size,
+                                             INT64_MAX, err);
+}
+
+static bool GetVBaseBitOffset(VTableContextBase &vtable_ctx,
+                              ValueObject &valobj,
+                              const ASTRecordLayout &record_layout,
+                              const CXXRecordDecl *cxx_record_decl,
+                              const CXXRecordDecl *base_class_decl,
+                              int32_t &bit_offset) {
+  ExecutionContext exe_ctx(valobj.GetExecutionContextRef());
+  Process *process = exe_ctx.GetProcessPtr();
+  if (!process)
+    return false;
+
+  lldb::addr_t vtable_ptr =
+      GetVTableAddress(*process, vtable_ctx, valobj, record_layout);
+  if (vtable_ptr == LLDB_INVALID_ADDRESS)
+    return false;
+
+  auto base_offset = ReadVBaseOffsetFromVTable(
+      *process, vtable_ctx, vtable_ptr, cxx_record_decl, base_class_decl);
+  if (base_offset == INT64_MAX)
+    return false;
+
+  bit_offset = base_offset * 8;
+
+  return true;
+}
+
+typedef lldb_private::ThreadSafeDenseMap<clang::ASTContext *, TypeSystemClang *>
+    ClangASTMap;
+
+static ClangASTMap &GetASTMap() {
+  static ClangASTMap *g_map_ptr = nullptr;
+  static llvm::once_flag g_once_flag;
+  llvm::call_once(g_once_flag, []() {
+    g_map_ptr = new ClangASTMap(); // leaked on purpose to avoid spins
+  });
+  return *g_map_ptr;
+}
+
+char TypeSystemClang::ID;
+
+bool TypeSystemClang::IsOperator(llvm::StringRef name,
+                                 clang::OverloadedOperatorKind &op_kind) {
+  // All operators have to start with "operator".
+  if (!name.consume_front("operator"))
+    return false;
+
+  // Remember if there was a space after "operator". This is necessary to
+  // check for collisions with strangely named functions like "operatorint()".
+  bool space_after_operator = name.consume_front(" ");
+
+  op_kind = StringSwitch<clang::OverloadedOperatorKind>(name)
+                .Case("+", clang::OO_Plus)
+                .Case("+=", clang::OO_PlusEqual)
+                .Case("++", clang::OO_PlusPlus)
+                .Case("-", clang::OO_Minus)
+                .Case("-=", clang::OO_MinusEqual)
+                .Case("--", clang::OO_MinusMinus)
+                .Case("->", clang::OO_Arrow)
+                .Case("->*", clang::OO_ArrowStar)
+                .Case("*", clang::OO_Star)
+                .Case("*=", clang::OO_StarEqual)
+                .Case("/", clang::OO_Slash)
+                .Case("/=", clang::OO_SlashEqual)
+                .Case("%", clang::OO_Percent)
+                .Case("%=", clang::OO_PercentEqual)
+                .Case("^", clang::OO_Caret)
+                .Case("^=", clang::OO_CaretEqual)
+                .Case("&", clang::OO_Amp)
+                .Case("&=", clang::OO_AmpEqual)
+                .Case("&&", clang::OO_AmpAmp)
+                .Case("|", clang::OO_Pipe)
+                .Case("|=", clang::OO_PipeEqual)
+                .Case("||", clang::OO_PipePipe)
+                .Case("~", clang::OO_Tilde)
+                .Case("!", clang::OO_Exclaim)
+                .Case("!=", clang::OO_ExclaimEqual)
+                .Case("=", clang::OO_Equal)
+                .Case("==", clang::OO_EqualEqual)
+                .Case("<", clang::OO_Less)
+                .Case("<<", clang::OO_LessLess)
+                .Case("<<=", clang::OO_LessLessEqual)
+                .Case("<=", clang::OO_LessEqual)
+                .Case(">", clang::OO_Greater)
+                .Case(">>", clang::OO_GreaterGreater)
+                .Case(">>=", clang::OO_GreaterGreaterEqual)
+                .Case(">=", clang::OO_GreaterEqual)
+                .Case("()", clang::OO_Call)
+                .Case("[]", clang::OO_Subscript)
+                .Case(",", clang::OO_Comma)
+                .Default(clang::NUM_OVERLOADED_OPERATORS);
+
+  // We found a fitting operator, so we can exit now.
+  if (op_kind != clang::NUM_OVERLOADED_OPERATORS)
+    return true;
+
+  // After the "operator " or "operator" part is something unknown. This means
+  // it's either one of the named operators (new/delete), a conversion operator
+  // (e.g. operator bool) or a function which name starts with "operator"
+  // (e.g. void operatorbool).
+
+  // If it's a function that starts with operator it can't have a space after
+  // "operator" because identifiers can't contain spaces.
+  // E.g. "operator int" (conversion operator)
+  //  vs. "operatorint" (function with colliding name).
+  if (!space_after_operator)
+    return false; // not an operator.
+
+  // Now the operator is either one of the named operators or a conversion
+  // operator.
+  op_kind = StringSwitch<clang::OverloadedOperatorKind>(name)
+                .Case("new", clang::OO_New)
+                .Case("new[]", clang::OO_Array_New)
+                .Case("delete", clang::OO_Delete)
+                .Case("delete[]", clang::OO_Array_Delete)
+                // conversion operators hit this case.
+                .Default(clang::NUM_OVERLOADED_OPERATORS);
+
+  return true;
+}
+
+clang::AccessSpecifier
+TypeSystemClang::ConvertAccessTypeToAccessSpecifier(AccessType access) {
+  switch (access) {
+  default:
+    break;
+  case eAccessNone:
+    return AS_none;
+  case eAccessPublic:
+    return AS_public;
+  case eAccessPrivate:
+    return AS_private;
+  case eAccessProtected:
+    return AS_protected;
+  }
+  return AS_none;
+}
+
+static void ParseLangArgs(LangOptions &Opts, InputKind IK, const char *triple) {
+  // FIXME: Cleanup per-file based stuff.
+
+  // Set some properties which depend solely on the input kind; it would be
+  // nice to move these to the language standard, and have the driver resolve
+  // the input kind + language standard.
+  if (IK.getLanguage() == clang::Language::Asm) {
+    Opts.AsmPreprocessor = 1;
+  } else if (IK.isObjectiveC()) {
+    Opts.ObjC = 1;
+  }
+
+  LangStandard::Kind LangStd = LangStandard::lang_unspecified;
+
+  if (LangStd == LangStandard::lang_unspecified) {
+    // Based on the base language, pick one.
+    switch (IK.getLanguage()) {
+    case clang::Language::Unknown:
+    case clang::Language::LLVM_IR:
+    case clang::Language::RenderScript:
+      llvm_unreachable("Invalid input kind!");
+    case clang::Language::OpenCL:
+      LangStd = LangStandard::lang_opencl10;
+      break;
+    case clang::Language::CUDA:
+      LangStd = LangStandard::lang_cuda;
+      break;
+    case clang::Language::Asm:
+    case clang::Language::C:
+    case clang::Language::ObjC:
+      LangStd = LangStandard::lang_gnu99;
+      break;
+    case clang::Language::CXX:
+    case clang::Language::ObjCXX:
+      LangStd = LangStandard::lang_gnucxx98;
+      break;
+    case clang::Language::HIP:
+      LangStd = LangStandard::lang_hip;
+      break;
+    }
+  }
+
+  const LangStandard &Std = LangStandard::getLangStandardForKind(LangStd);
+  Opts.LineComment = Std.hasLineComments();
+  Opts.C99 = Std.isC99();
+  Opts.CPlusPlus = Std.isCPlusPlus();
+  Opts.CPlusPlus11 = Std.isCPlusPlus11();
+  Opts.Digraphs = Std.hasDigraphs();
+  Opts.GNUMode = Std.isGNUMode();
+  Opts.GNUInline = !Std.isC99();
+  Opts.HexFloats = Std.hasHexFloats();
+  Opts.ImplicitInt = Std.hasImplicitInt();
+
+  Opts.WChar = true;
+
+  // OpenCL has some additional defaults.
+  if (LangStd == LangStandard::lang_opencl10) {
+    Opts.OpenCL = 1;
+    Opts.AltiVec = 1;
+    Opts.CXXOperatorNames = 1;
+    Opts.setLaxVectorConversions(LangOptions::LaxVectorConversionKind::All);
+  }
+
+  // OpenCL and C++ both have bool, true, false keywords.
+  Opts.Bool = Opts.OpenCL || Opts.CPlusPlus;
+
+  Opts.setValueVisibilityMode(DefaultVisibility);
+
+  // Mimicing gcc's behavior, trigraphs are only enabled if -trigraphs is
+  // specified, or -std is set to a conforming mode.
+  Opts.Trigraphs = !Opts.GNUMode;
+  Opts.CharIsSigned = ArchSpec(triple).CharIsSignedByDefault();
+  Opts.OptimizeSize = 0;
+
+  // FIXME: Eliminate this dependency.
+  //    unsigned Opt =
+  //    Args.hasArg(OPT_Os) ? 2 : getLastArgIntValue(Args, OPT_O, 0, Diags);
+  //    Opts.Optimize = Opt != 0;
+  unsigned Opt = 0;
+
+  // This is the __NO_INLINE__ define, which just depends on things like the
+  // optimization level and -fno-inline, not actually whether the backend has
+  // inlining enabled.
+  //
+  // FIXME: This is affected by other options (-fno-inline).
+  Opts.NoInlineDefine = !Opt;
+}
+
+TypeSystemClang::TypeSystemClang(llvm::StringRef name,
+                                 llvm::Triple target_triple) {
+  m_display_name = name.str();
+  if (!target_triple.str().empty())
+    SetTargetTriple(target_triple.str());
+  // The caller didn't pass an ASTContext so create a new one for this
+  // TypeSystemClang.
+  CreateASTContext();
+}
+
+TypeSystemClang::TypeSystemClang(llvm::StringRef name,
+                                 ASTContext &existing_ctxt) {
+  m_display_name = name.str();
+  SetTargetTriple(existing_ctxt.getTargetInfo().getTriple().str());
+
+  m_ast_up.reset(&existing_ctxt);
+  GetASTMap().Insert(&existing_ctxt, this);
+}
+
+// Destructor
+TypeSystemClang::~TypeSystemClang() { Finalize(); }
+
+ConstString TypeSystemClang::GetPluginNameStatic() {
+  return ConstString("clang");
+}
+
+ConstString TypeSystemClang::GetPluginName() {
+  return TypeSystemClang::GetPluginNameStatic();
+}
+
+uint32_t TypeSystemClang::GetPluginVersion() { return 1; }
+
+lldb::TypeSystemSP TypeSystemClang::CreateInstance(lldb::LanguageType language,
+                                                   lldb_private::Module *module,
+                                                   Target *target) {
+  if (!TypeSystemClangSupportsLanguage(language))
+    return lldb::TypeSystemSP();
+  ArchSpec arch;
+  if (module)
+    arch = module->GetArchitecture();
+  else if (target)
+    arch = target->GetArchitecture();
+
+  if (!arch.IsValid())
+    return lldb::TypeSystemSP();
+
+  llvm::Triple triple = arch.GetTriple();
+  // LLVM wants this to be set to iOS or MacOSX; if we're working on
+  // a bare-boards type image, change the triple for llvm's benefit.
+  if (triple.getVendor() == llvm::Triple::Apple &&
+      triple.getOS() == llvm::Triple::UnknownOS) {
+    if (triple.getArch() == llvm::Triple::arm ||
+        triple.getArch() == llvm::Triple::aarch64 ||
+        triple.getArch() == llvm::Triple::aarch64_32 ||
+        triple.getArch() == llvm::Triple::thumb) {
+      triple.setOS(llvm::Triple::IOS);
+    } else {
+      triple.setOS(llvm::Triple::MacOSX);
+    }
+  }
+
+  if (module) {
+    std::string ast_name =
+        "ASTContext for '" + module->GetFileSpec().GetPath() + "'";
+    return std::make_shared<TypeSystemClang>(ast_name, triple);
+  } else if (target && target->IsValid())
+    return std::make_shared<TypeSystemClangForExpressions>(*target, triple);
+  return lldb::TypeSystemSP();
+}
+
+LanguageSet TypeSystemClang::GetSupportedLanguagesForTypes() {
+  LanguageSet languages;
+  languages.Insert(lldb::eLanguageTypeC89);
+  languages.Insert(lldb::eLanguageTypeC);
+  languages.Insert(lldb::eLanguageTypeC11);
+  languages.Insert(lldb::eLanguageTypeC_plus_plus);
+  languages.Insert(lldb::eLanguageTypeC99);
+  languages.Insert(lldb::eLanguageTypeObjC);
+  languages.Insert(lldb::eLanguageTypeObjC_plus_plus);
+  languages.Insert(lldb::eLanguageTypeC_plus_plus_03);
+  languages.Insert(lldb::eLanguageTypeC_plus_plus_11);
+  languages.Insert(lldb::eLanguageTypeC11);
+  languages.Insert(lldb::eLanguageTypeC_plus_plus_14);
+  return languages;
+}
+
+LanguageSet TypeSystemClang::GetSupportedLanguagesForExpressions() {
+  LanguageSet languages;
+  languages.Insert(lldb::eLanguageTypeC_plus_plus);
+  languages.Insert(lldb::eLanguageTypeObjC_plus_plus);
+  languages.Insert(lldb::eLanguageTypeC_plus_plus_03);
+  languages.Insert(lldb::eLanguageTypeC_plus_plus_11);
+  languages.Insert(lldb::eLanguageTypeC_plus_plus_14);
+  return languages;
+}
+
+void TypeSystemClang::Initialize() {
+  PluginManager::RegisterPlugin(
+      GetPluginNameStatic(), "clang base AST context plug-in", CreateInstance,
+      GetSupportedLanguagesForTypes(), GetSupportedLanguagesForExpressions());
+}
+
+void TypeSystemClang::Terminate() {
+  PluginManager::UnregisterPlugin(CreateInstance);
+}
+
+void TypeSystemClang::Finalize() {
+  assert(m_ast_up);
+  GetASTMap().Erase(m_ast_up.get());
+  if (!m_ast_owned)
+    m_ast_up.release();
+
+  m_builtins_up.reset();
+  m_selector_table_up.reset();
+  m_identifier_table_up.reset();
+  m_target_info_up.reset();
+  m_target_options_rp.reset();
+  m_diagnostics_engine_up.reset();
+  m_source_manager_up.reset();
+  m_language_options_up.reset();
+}
+
+void TypeSystemClang::setSema(Sema *s) {
+  // Ensure that the new sema actually belongs to our ASTContext.
+  assert(s == nullptr || &s->getASTContext() == m_ast_up.get());
+  m_sema = s;
+}
+
+const char *TypeSystemClang::GetTargetTriple() {
+  return m_target_triple.c_str();
+}
+
+void TypeSystemClang::SetTargetTriple(llvm::StringRef target_triple) {
+  m_target_triple = target_triple.str();
+}
+
+void TypeSystemClang::SetExternalSource(
+    llvm::IntrusiveRefCntPtr<ExternalASTSource> &ast_source_up) {
+  ASTContext &ast = getASTContext();
+  ast.setExternalSource(ast_source_up);
+  ast.getTranslationUnitDecl()->setHasExternalLexicalStorage(true);
+}
+
+ASTContext &TypeSystemClang::getASTContext() {
+  assert(m_ast_up);
+  return *m_ast_up;
+}
+
+class NullDiagnosticConsumer : public DiagnosticConsumer {
+public:
+  NullDiagnosticConsumer() {
+    m_log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS);
+  }
+
+  void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
+                        const clang::Diagnostic &info) override {
+    if (m_log) {
+      llvm::SmallVector<char, 32> diag_str(10);
+      info.FormatDiagnostic(diag_str);
+      diag_str.push_back('\0');
+      LLDB_LOGF(m_log, "Compiler diagnostic: %s\n", diag_str.data());
+    }
+  }
+
+  DiagnosticConsumer *clone(DiagnosticsEngine &Diags) const {
+    return new NullDiagnosticConsumer();
+  }
+
+private:
+  Log *m_log;
+};
+
+void TypeSystemClang::CreateASTContext() {
+  assert(!m_ast_up);
+  m_ast_owned = true;
+
+  m_language_options_up.reset(new LangOptions());
+  ParseLangArgs(*m_language_options_up, clang::Language::ObjCXX,
+                GetTargetTriple());
+
+  m_identifier_table_up.reset(
+      new IdentifierTable(*m_language_options_up, nullptr));
+  m_builtins_up.reset(new Builtin::Context());
+
+  m_selector_table_up.reset(new SelectorTable());
+
+  clang::FileSystemOptions file_system_options;
+  m_file_manager_up.reset(new clang::FileManager(
+      file_system_options, FileSystem::Instance().GetVirtualFileSystem()));
+
+  llvm::IntrusiveRefCntPtr<DiagnosticIDs> diag_id_sp(new DiagnosticIDs());
+  m_diagnostics_engine_up.reset(
+      new DiagnosticsEngine(diag_id_sp, new DiagnosticOptions()));
+
+  m_source_manager_up.reset(
+      new clang::SourceManager(*m_diagnostics_engine_up, *m_file_manager_up));
+  m_ast_up.reset(new ASTContext(*m_language_options_up, *m_source_manager_up,
+                                *m_identifier_table_up, *m_selector_table_up,
+                                *m_builtins_up));
+
+  m_diagnostic_consumer_up.reset(new NullDiagnosticConsumer);
+  m_ast_up->getDiagnostics().setClient(m_diagnostic_consumer_up.get(), false);
+
+  // This can be NULL if we don't know anything about the architecture or if
+  // the target for an architecture isn't enabled in the llvm/clang that we
+  // built
+  TargetInfo *target_info = getTargetInfo();
+  if (target_info)
+    m_ast_up->InitBuiltinTypes(*target_info);
+
+  GetASTMap().Insert(m_ast_up.get(), this);
+
+  llvm::IntrusiveRefCntPtr<clang::ExternalASTSource> ast_source_up(
+      new ClangExternalASTSourceCallbacks(*this));
+  SetExternalSource(ast_source_up);
+}
+
+TypeSystemClang *TypeSystemClang::GetASTContext(clang::ASTContext *ast) {
+  TypeSystemClang *clang_ast = GetASTMap().Lookup(ast);
+  return clang_ast;
+}
+
+clang::MangleContext *TypeSystemClang::getMangleContext() {
+  if (m_mangle_ctx_up == nullptr)
+    m_mangle_ctx_up.reset(getASTContext().createMangleContext());
+  return m_mangle_ctx_up.get();
+}
+
+std::shared_ptr<clang::TargetOptions> &TypeSystemClang::getTargetOptions() {
+  if (m_target_options_rp == nullptr && !m_target_triple.empty()) {
+    m_target_options_rp = std::make_shared<clang::TargetOptions>();
+    if (m_target_options_rp != nullptr)
+      m_target_options_rp->Triple = m_target_triple;
+  }
+  return m_target_options_rp;
+}
+
+TargetInfo *TypeSystemClang::getTargetInfo() {
+  // target_triple should be something like "x86_64-apple-macosx"
+  if (m_target_info_up == nullptr && !m_target_triple.empty())
+    m_target_info_up.reset(TargetInfo::CreateTargetInfo(
+        getASTContext().getDiagnostics(), getTargetOptions()));
+  return m_target_info_up.get();
+}
+
+#pragma mark Basic Types
+
+static inline bool QualTypeMatchesBitSize(const uint64_t bit_size,
+                                          ASTContext &ast, QualType qual_type) {
+  uint64_t qual_type_bit_size = ast.getTypeSize(qual_type);
+  return qual_type_bit_size == bit_size;
+}
+
+CompilerType
+TypeSystemClang::GetBuiltinTypeForEncodingAndBitSize(Encoding encoding,
+                                                     size_t bit_size) {
+  ASTContext &ast = getASTContext();
+  switch (encoding) {
+  case eEncodingInvalid:
+    if (QualTypeMatchesBitSize(bit_size, ast, ast.VoidPtrTy))
+      return GetType(ast.VoidPtrTy);
+    break;
+
+  case eEncodingUint:
+    if (QualTypeMatchesBitSize(bit_size, ast, ast.UnsignedCharTy))
+      return GetType(ast.UnsignedCharTy);
+    if (QualTypeMatchesBitSize(bit_size, ast, ast.UnsignedShortTy))
+      return GetType(ast.UnsignedShortTy);
+    if (QualTypeMatchesBitSize(bit_size, ast, ast.UnsignedIntTy))
+      return GetType(ast.UnsignedIntTy);
+    if (QualTypeMatchesBitSize(bit_size, ast, ast.UnsignedLongTy))
+      return GetType(ast.UnsignedLongTy);
+    if (QualTypeMatchesBitSize(bit_size, ast, ast.UnsignedLongLongTy))
+      return GetType(ast.UnsignedLongLongTy);
+    if (QualTypeMatchesBitSize(bit_size, ast, ast.UnsignedInt128Ty))
+      return GetType(ast.UnsignedInt128Ty);
+    break;
+
+  case eEncodingSint:
+    if (QualTypeMatchesBitSize(bit_size, ast, ast.SignedCharTy))
+      return GetType(ast.SignedCharTy);
+    if (QualTypeMatchesBitSize(bit_size, ast, ast.ShortTy))
+      return GetType(ast.ShortTy);
+    if (QualTypeMatchesBitSize(bit_size, ast, ast.IntTy))
+      return GetType(ast.IntTy);
+    if (QualTypeMatchesBitSize(bit_size, ast, ast.LongTy))
+      return GetType(ast.LongTy);
+    if (QualTypeMatchesBitSize(bit_size, ast, ast.LongLongTy))
+      return GetType(ast.LongLongTy);
+    if (QualTypeMatchesBitSize(bit_size, ast, ast.Int128Ty))
+      return GetType(ast.Int128Ty);
+    break;
+
+  case eEncodingIEEE754:
+    if (QualTypeMatchesBitSize(bit_size, ast, ast.FloatTy))
+      return GetType(ast.FloatTy);
+    if (QualTypeMatchesBitSize(bit_size, ast, ast.DoubleTy))
+      return GetType(ast.DoubleTy);
+    if (QualTypeMatchesBitSize(bit_size, ast, ast.LongDoubleTy))
+      return GetType(ast.LongDoubleTy);
+    if (QualTypeMatchesBitSize(bit_size, ast, ast.HalfTy))
+      return GetType(ast.HalfTy);
+    break;
+
+  case eEncodingVector:
+    // Sanity check that bit_size is a multiple of 8's.
+    if (bit_size && !(bit_size & 0x7u))
+      return GetType(ast.getExtVectorType(ast.UnsignedCharTy, bit_size / 8));
+    break;
+  }
+
+  return CompilerType();
+}
+
+lldb::BasicType
+TypeSystemClang::GetBasicTypeEnumeration(ConstString name) {
+  if (name) {
+    typedef UniqueCStringMap<lldb::BasicType> TypeNameToBasicTypeMap;
+    static TypeNameToBasicTypeMap g_type_map;
+    static llvm::once_flag g_once_flag;
+    llvm::call_once(g_once_flag, []() {
+      // "void"
+      g_type_map.Append(ConstString("void"), eBasicTypeVoid);
+
+      // "char"
+      g_type_map.Append(ConstString("char"), eBasicTypeChar);
+      g_type_map.Append(ConstString("signed char"), eBasicTypeSignedChar);
+      g_type_map.Append(ConstString("unsigned char"), eBasicTypeUnsignedChar);
+      g_type_map.Append(ConstString("wchar_t"), eBasicTypeWChar);
+      g_type_map.Append(ConstString("signed wchar_t"), eBasicTypeSignedWChar);
+      g_type_map.Append(ConstString("unsigned wchar_t"),
+                        eBasicTypeUnsignedWChar);
+      // "short"
+      g_type_map.Append(ConstString("short"), eBasicTypeShort);
+      g_type_map.Append(ConstString("short int"), eBasicTypeShort);
+      g_type_map.Append(ConstString("unsigned short"), eBasicTypeUnsignedShort);
+      g_type_map.Append(ConstString("unsigned short int"),
+                        eBasicTypeUnsignedShort);
+
+      // "int"
+      g_type_map.Append(ConstString("int"), eBasicTypeInt);
+      g_type_map.Append(ConstString("signed int"), eBasicTypeInt);
+      g_type_map.Append(ConstString("unsigned int"), eBasicTypeUnsignedInt);
+      g_type_map.Append(ConstString("unsigned"), eBasicTypeUnsignedInt);
+
+      // "long"
+      g_type_map.Append(ConstString("long"), eBasicTypeLong);
+      g_type_map.Append(ConstString("long int"), eBasicTypeLong);
+      g_type_map.Append(ConstString("unsigned long"), eBasicTypeUnsignedLong);
+      g_type_map.Append(ConstString("unsigned long int"),
+                        eBasicTypeUnsignedLong);
+
+      // "long long"
+      g_type_map.Append(ConstString("long long"), eBasicTypeLongLong);
+      g_type_map.Append(ConstString("long long int"), eBasicTypeLongLong);
+      g_type_map.Append(ConstString("unsigned long long"),
+                        eBasicTypeUnsignedLongLong);
+      g_type_map.Append(ConstString("unsigned long long int"),
+                        eBasicTypeUnsignedLongLong);
+
+      // "int128"
+      g_type_map.Append(ConstString("__int128_t"), eBasicTypeInt128);
+      g_type_map.Append(ConstString("__uint128_t"), eBasicTypeUnsignedInt128);
+
+      // Miscellaneous
+      g_type_map.Append(ConstString("bool"), eBasicTypeBool);
+      g_type_map.Append(ConstString("float"), eBasicTypeFloat);
+      g_type_map.Append(ConstString("double"), eBasicTypeDouble);
+      g_type_map.Append(ConstString("long double"), eBasicTypeLongDouble);
+      g_type_map.Append(ConstString("id"), eBasicTypeObjCID);
+      g_type_map.Append(ConstString("SEL"), eBasicTypeObjCSel);
+      g_type_map.Append(ConstString("nullptr"), eBasicTypeNullPtr);
+      g_type_map.Sort();
+    });
+
+    return g_type_map.Find(name, eBasicTypeInvalid);
+  }
+  return eBasicTypeInvalid;
+}
+
+uint32_t TypeSystemClang::GetPointerByteSize() {
+  if (m_pointer_byte_size == 0)
+    if (auto size = GetBasicType(lldb::eBasicTypeVoid)
+                        .GetPointerType()
+                        .GetByteSize(nullptr))
+      m_pointer_byte_size = *size;
+  return m_pointer_byte_size;
+}
+
+CompilerType TypeSystemClang::GetBasicType(lldb::BasicType basic_type) {
+  clang::ASTContext &ast = getASTContext();
+
+  lldb::opaque_compiler_type_t clang_type =
+      GetOpaqueCompilerType(&ast, basic_type);
+
+  if (clang_type)
+    return CompilerType(this, clang_type);
+  return CompilerType();
+}
+
+CompilerType TypeSystemClang::GetBuiltinTypeForDWARFEncodingAndBitSize(
+    llvm::StringRef type_name, uint32_t dw_ate, uint32_t bit_size) {
+  ASTContext &ast = getASTContext();
+
+  switch (dw_ate) {
+  default:
+    break;
+
+  case DW_ATE_address:
+    if (QualTypeMatchesBitSize(bit_size, ast, ast.VoidPtrTy))
+      return GetType(ast.VoidPtrTy);
+    break;
+
+  case DW_ATE_boolean:
+    if (QualTypeMatchesBitSize(bit_size, ast, ast.BoolTy))
+      return GetType(ast.BoolTy);
+    if (QualTypeMatchesBitSize(bit_size, ast, ast.UnsignedCharTy))
+      return GetType(ast.UnsignedCharTy);
+    if (QualTypeMatchesBitSize(bit_size, ast, ast.UnsignedShortTy))
+      return GetType(ast.UnsignedShortTy);
+    if (QualTypeMatchesBitSize(bit_size, ast, ast.UnsignedIntTy))
+      return GetType(ast.UnsignedIntTy);
+    break;
+
+  case DW_ATE_lo_user:
+    // This has been seen to mean DW_AT_complex_integer
+    if (type_name.contains("complex")) {
+      CompilerType complex_int_clang_type =
+          GetBuiltinTypeForDWARFEncodingAndBitSize("int", DW_ATE_signed,
+                                                   bit_size / 2);
+      return GetType(
+          ast.getComplexType(ClangUtil::GetQualType(complex_int_clang_type)));
+    }
+    break;
+
+  case DW_ATE_complex_float:
+    if (QualTypeMatchesBitSize(bit_size, ast, ast.FloatComplexTy))
+      return GetType(ast.FloatComplexTy);
+    else if (QualTypeMatchesBitSize(bit_size, ast, ast.DoubleComplexTy))
+      return GetType(ast.DoubleComplexTy);
+    else if (QualTypeMatchesBitSize(bit_size, ast, ast.LongDoubleComplexTy))
+      return GetType(ast.LongDoubleComplexTy);
+    else {
+      CompilerType complex_float_clang_type =
+          GetBuiltinTypeForDWARFEncodingAndBitSize("float", DW_ATE_float,
+                                                   bit_size / 2);
+      return GetType(
+          ast.getComplexType(ClangUtil::GetQualType(complex_float_clang_type)));
+    }
+    break;
+
+  case DW_ATE_float:
+    if (type_name == "float" &&
+        QualTypeMatchesBitSize(bit_size, ast, ast.FloatTy))
+      return GetType(ast.FloatTy);
+    if (type_name == "double" &&
+        QualTypeMatchesBitSize(bit_size, ast, ast.DoubleTy))
+      return GetType(ast.DoubleTy);
+    if (type_name == "long double" &&
+        QualTypeMatchesBitSize(bit_size, ast, ast.LongDoubleTy))
+      return GetType(ast.LongDoubleTy);
+    // Fall back to not requiring a name match
+    if (QualTypeMatchesBitSize(bit_size, ast, ast.FloatTy))
+      return GetType(ast.FloatTy);
+    if (QualTypeMatchesBitSize(bit_size, ast, ast.DoubleTy))
+      return GetType(ast.DoubleTy);
+    if (QualTypeMatchesBitSize(bit_size, ast, ast.LongDoubleTy))
+      return GetType(ast.LongDoubleTy);
+    if (QualTypeMatchesBitSize(bit_size, ast, ast.HalfTy))
+      return GetType(ast.HalfTy);
+    break;
+
+  case DW_ATE_signed:
+    if (!type_name.empty()) {
+      if (type_name == "wchar_t" &&
+          QualTypeMatchesBitSize(bit_size, ast, ast.WCharTy) &&
+          (getTargetInfo() &&
+           TargetInfo::isTypeSigned(getTargetInfo()->getWCharType())))
+        return GetType(ast.WCharTy);
+      if (type_name == "void" &&
+          QualTypeMatchesBitSize(bit_size, ast, ast.VoidTy))
+        return GetType(ast.VoidTy);
+      if (type_name.contains("long long") &&
+          QualTypeMatchesBitSize(bit_size, ast, ast.LongLongTy))
+        return GetType(ast.LongLongTy);
+      if (type_name.contains("long") &&
+          QualTypeMatchesBitSize(bit_size, ast, ast.LongTy))
+        return GetType(ast.LongTy);
+      if (type_name.contains("short") &&
+          QualTypeMatchesBitSize(bit_size, ast, ast.ShortTy))
+        return GetType(ast.ShortTy);
+      if (type_name.contains("char")) {
+        if (QualTypeMatchesBitSize(bit_size, ast, ast.CharTy))
+          return GetType(ast.CharTy);
+        if (QualTypeMatchesBitSize(bit_size, ast, ast.SignedCharTy))
+          return GetType(ast.SignedCharTy);
+      }
+      if (type_name.contains("int")) {
+        if (QualTypeMatchesBitSize(bit_size, ast, ast.IntTy))
+          return GetType(ast.IntTy);
+        if (QualTypeMatchesBitSize(bit_size, ast, ast.Int128Ty))
+          return GetType(ast.Int128Ty);
+      }
+    }
+    // We weren't able to match up a type name, just search by size
+    if (QualTypeMatchesBitSize(bit_size, ast, ast.CharTy))
+      return GetType(ast.CharTy);
+    if (QualTypeMatchesBitSize(bit_size, ast, ast.ShortTy))
+      return GetType(ast.ShortTy);
+    if (QualTypeMatchesBitSize(bit_size, ast, ast.IntTy))
+      return GetType(ast.IntTy);
+    if (QualTypeMatchesBitSize(bit_size, ast, ast.LongTy))
+      return GetType(ast.LongTy);
+    if (QualTypeMatchesBitSize(bit_size, ast, ast.LongLongTy))
+      return GetType(ast.LongLongTy);
+    if (QualTypeMatchesBitSize(bit_size, ast, ast.Int128Ty))
+      return GetType(ast.Int128Ty);
+    break;
+
+  case DW_ATE_signed_char:
+    if (ast.getLangOpts().CharIsSigned && type_name == "char") {
+      if (QualTypeMatchesBitSize(bit_size, ast, ast.CharTy))
+        return GetType(ast.CharTy);
+    }
+    if (QualTypeMatchesBitSize(bit_size, ast, ast.SignedCharTy))
+      return GetType(ast.SignedCharTy);
+    break;
+
+  case DW_ATE_unsigned:
+    if (!type_name.empty()) {
+      if (type_name == "wchar_t") {
+        if (QualTypeMatchesBitSize(bit_size, ast, ast.WCharTy)) {
+          if (!(getTargetInfo() &&
+                TargetInfo::isTypeSigned(getTargetInfo()->getWCharType())))
+            return GetType(ast.WCharTy);
+        }
+      }
+      if (type_name.contains("long long")) {
+        if (QualTypeMatchesBitSize(bit_size, ast, ast.UnsignedLongLongTy))
+          return GetType(ast.UnsignedLongLongTy);
+      } else if (type_name.contains("long")) {
+        if (QualTypeMatchesBitSize(bit_size, ast, ast.UnsignedLongTy))
+          return GetType(ast.UnsignedLongTy);
+      } else if (type_name.contains("short")) {
+        if (QualTypeMatchesBitSize(bit_size, ast, ast.UnsignedShortTy))
+          return GetType(ast.UnsignedShortTy);
+      } else if (type_name.contains("char")) {
+        if (QualTypeMatchesBitSize(bit_size, ast, ast.UnsignedCharTy))
+          return GetType(ast.UnsignedCharTy);
+      } else if (type_name.contains("int")) {
+        if (QualTypeMatchesBitSize(bit_size, ast, ast.UnsignedIntTy))
+          return GetType(ast.UnsignedIntTy);
+        if (QualTypeMatchesBitSize(bit_size, ast, ast.UnsignedInt128Ty))
+          return GetType(ast.UnsignedInt128Ty);
+      }
+    }
+    // We weren't able to match up a type name, just search by size
+    if (QualTypeMatchesBitSize(bit_size, ast, ast.UnsignedCharTy))
+      return GetType(ast.UnsignedCharTy);
+    if (QualTypeMatchesBitSize(bit_size, ast, ast.UnsignedShortTy))
+      return GetType(ast.UnsignedShortTy);
+    if (QualTypeMatchesBitSize(bit_size, ast, ast.UnsignedIntTy))
+      return GetType(ast.UnsignedIntTy);
+    if (QualTypeMatchesBitSize(bit_size, ast, ast.UnsignedLongTy))
+      return GetType(ast.UnsignedLongTy);
+    if (QualTypeMatchesBitSize(bit_size, ast, ast.UnsignedLongLongTy))
+      return GetType(ast.UnsignedLongLongTy);
+    if (QualTypeMatchesBitSize(bit_size, ast, ast.UnsignedInt128Ty))
+      return GetType(ast.UnsignedInt128Ty);
+    break;
+
+  case DW_ATE_unsigned_char:
+    if (!ast.getLangOpts().CharIsSigned && type_name == "char") {
+      if (QualTypeMatchesBitSize(bit_size, ast, ast.CharTy))
+        return GetType(ast.CharTy);
+    }
+    if (QualTypeMatchesBitSize(bit_size, ast, ast.UnsignedCharTy))
+      return GetType(ast.UnsignedCharTy);
+    if (QualTypeMatchesBitSize(bit_size, ast, ast.UnsignedShortTy))
+      return GetType(ast.UnsignedShortTy);
+    break;
+
+  case DW_ATE_imaginary_float:
+    break;
+
+  case DW_ATE_UTF:
+    if (!type_name.empty()) {
+      if (type_name == "char16_t")
+        return GetType(ast.Char16Ty);
+      if (type_name == "char32_t")
+        return GetType(ast.Char32Ty);
+      if (type_name == "char8_t")
+        return GetType(ast.Char8Ty);
+    }
+    break;
+  }
+  // This assert should fire for anything that we don't catch above so we know
+  // to fix any issues we run into.
+  if (!type_name.empty()) {
+    std::string type_name_str = type_name.str();
+    Host::SystemLog(Host::eSystemLogError,
+                    "error: need to add support for DW_TAG_base_type '%s' "
+                    "encoded with DW_ATE = 0x%x, bit_size = %u\n",
+                    type_name_str.c_str(), dw_ate, bit_size);
+  } else {
+    Host::SystemLog(Host::eSystemLogError, "error: need to add support for "
+                                           "DW_TAG_base_type encoded with "
+                                           "DW_ATE = 0x%x, bit_size = %u\n",
+                    dw_ate, bit_size);
+  }
+  return CompilerType();
+}
+
+CompilerType TypeSystemClang::GetCStringType(bool is_const) {
+  ASTContext &ast = getASTContext();
+  QualType char_type(ast.CharTy);
+
+  if (is_const)
+    char_type.addConst();
+
+  return GetType(ast.getPointerType(char_type));
+}
+
+bool TypeSystemClang::AreTypesSame(CompilerType type1, CompilerType type2,
+                                   bool ignore_qualifiers) {
+  TypeSystemClang *ast =
+      llvm::dyn_cast_or_null<TypeSystemClang>(type1.GetTypeSystem());
+  if (!ast || ast != type2.GetTypeSystem())
+    return false;
+
+  if (type1.GetOpaqueQualType() == type2.GetOpaqueQualType())
+    return true;
+
+  QualType type1_qual = ClangUtil::GetQualType(type1);
+  QualType type2_qual = ClangUtil::GetQualType(type2);
+
+  if (ignore_qualifiers) {
+    type1_qual = type1_qual.getUnqualifiedType();
+    type2_qual = type2_qual.getUnqualifiedType();
+  }
+
+  return ast->getASTContext().hasSameType(type1_qual, type2_qual);
+}
+
+CompilerType TypeSystemClang::GetTypeForDecl(void *opaque_decl) {
+  if (!opaque_decl)
+    return CompilerType();
+
+  clang::Decl *decl = static_cast<clang::Decl *>(opaque_decl);
+  if (auto *named_decl = llvm::dyn_cast<clang::NamedDecl>(decl))
+    return GetTypeForDecl(named_decl);
+  return CompilerType();
+}
+
+CompilerDeclContext TypeSystemClang::CreateDeclContext(DeclContext *ctx) {
+  // Check that the DeclContext actually belongs to this ASTContext.
+  assert(&ctx->getParentASTContext() == &getASTContext());
+  return CompilerDeclContext(this, ctx);
+}
+
+CompilerType TypeSystemClang::GetTypeForDecl(clang::NamedDecl *decl) {
+  if (clang::ObjCInterfaceDecl *interface_decl =
+      llvm::dyn_cast<clang::ObjCInterfaceDecl>(decl))
+    return GetTypeForDecl(interface_decl);
+  if (clang::TagDecl *tag_decl = llvm::dyn_cast<clang::TagDecl>(decl))
+    return GetTypeForDecl(tag_decl);
+  return CompilerType();
+}
+
+CompilerType TypeSystemClang::GetTypeForDecl(TagDecl *decl) {
+  return GetType(getASTContext().getTagDeclType(decl));
+}
+
+CompilerType TypeSystemClang::GetTypeForDecl(ObjCInterfaceDecl *decl) {
+  return GetType(getASTContext().getObjCInterfaceType(decl));
+}
+
+#pragma mark Structure, Unions, Classes
+
+CompilerType TypeSystemClang::CreateRecordType(DeclContext *decl_ctx,
+                                               AccessType access_type,
+                                               llvm::StringRef name, int kind,
+                                               LanguageType language,
+                                               ClangASTMetadata *metadata,
+                                               bool exports_symbols) {
+  ASTContext &ast = getASTContext();
+
+  if (decl_ctx == nullptr)
+    decl_ctx = ast.getTranslationUnitDecl();
+
+  if (language == eLanguageTypeObjC ||
+      language == eLanguageTypeObjC_plus_plus) {
+    bool isForwardDecl = true;
+    bool isInternal = false;
+    return CreateObjCClass(name, decl_ctx, isForwardDecl, isInternal, metadata);
+  }
+
+  // NOTE: Eventually CXXRecordDecl will be merged back into RecordDecl and
+  // we will need to update this code. I was told to currently always use the
+  // CXXRecordDecl class since we often don't know from debug information if
+  // something is struct or a class, so we default to always use the more
+  // complete definition just in case.
+
+  bool has_name = !name.empty();
+
+  CXXRecordDecl *decl = CXXRecordDecl::Create(
+      ast, (TagDecl::TagKind)kind, decl_ctx, SourceLocation(), SourceLocation(),
+      has_name ? &ast.Idents.get(name) : nullptr);
+
+  if (!has_name) {
+    // In C++ a lambda is also represented as an unnamed class. This is
+    // different from an *anonymous class* that the user wrote:
+    //
+    // struct A {
+    //  // anonymous class (GNU/MSVC extension)
+    //  struct {
+    //    int x;
+    //  };
+    //  // unnamed class within a class
+    //  struct {
+    //    int y;
+    //  } B;
+    // };
+    //
+    // void f() {
+    //    // unammed class outside of a class
+    //    struct {
+    //      int z;
+    //    } C;
+    // }
+    //
+    // Anonymous classes is a GNU/MSVC extension that clang supports. It
+    // requires the anonymous class be embedded within a class. So the new
+    // heuristic verifies this condition.
+    if (isa<CXXRecordDecl>(decl_ctx) && exports_symbols)
+      decl->setAnonymousStructOrUnion(true);
+  }
+
+  if (decl) {
+    if (metadata)
+      SetMetadata(decl, *metadata);
+
+    if (access_type != eAccessNone)
+      decl->setAccess(ConvertAccessTypeToAccessSpecifier(access_type));
+
+    if (decl_ctx)
+      decl_ctx->addDecl(decl);
+
+    return GetType(ast.getTagDeclType(decl));
+  }
+  return CompilerType();
+}
+
+namespace {
+  bool IsValueParam(const clang::TemplateArgument &argument) {
+    return argument.getKind() == TemplateArgument::Integral;
+  }
+}
+
+static TemplateParameterList *CreateTemplateParameterList(
+    ASTContext *ast,
+    const TypeSystemClang::TemplateParameterInfos &template_param_infos,
+    llvm::SmallVector<NamedDecl *, 8> &template_param_decls) {
+  const bool parameter_pack = false;
+  const bool is_typename = false;
+  const unsigned depth = 0;
+  const size_t num_template_params = template_param_infos.args.size();
+  DeclContext *const decl_context =
+      ast->getTranslationUnitDecl(); // Is this the right decl context?,
+  for (size_t i = 0; i < num_template_params; ++i) {
+    const char *name = template_param_infos.names[i];
+
+    IdentifierInfo *identifier_info = nullptr;
+    if (name && name[0])
+      identifier_info = &ast->Idents.get(name);
+    if (IsValueParam(template_param_infos.args[i])) {
+      template_param_decls.push_back(NonTypeTemplateParmDecl::Create(
+          *ast, decl_context,
+          SourceLocation(), SourceLocation(), depth, i, identifier_info,
+          template_param_infos.args[i].getIntegralType(), parameter_pack,
+          nullptr));
+
+    } else {
+      template_param_decls.push_back(TemplateTypeParmDecl::Create(
+          *ast, decl_context,
+          SourceLocation(), SourceLocation(), depth, i, identifier_info,
+          is_typename, parameter_pack));
+    }
+  }
+
+  if (template_param_infos.packed_args) {
+    IdentifierInfo *identifier_info = nullptr;
+    if (template_param_infos.pack_name && template_param_infos.pack_name[0])
+      identifier_info = &ast->Idents.get(template_param_infos.pack_name);
+    const bool parameter_pack_true = true;
+
+    if (!template_param_infos.packed_args->args.empty() &&
+        IsValueParam(template_param_infos.packed_args->args[0])) {
+      template_param_decls.push_back(NonTypeTemplateParmDecl::Create(
+          *ast, decl_context, SourceLocation(), SourceLocation(), depth,
+          num_template_params, identifier_info,
+          template_param_infos.packed_args->args[0].getIntegralType(),
+          parameter_pack_true, nullptr));
+    } else {
+      template_param_decls.push_back(TemplateTypeParmDecl::Create(
+          *ast, decl_context, SourceLocation(), SourceLocation(), depth,
+          num_template_params, identifier_info, is_typename,
+          parameter_pack_true));
+    }
+  }
+  clang::Expr *const requires_clause = nullptr; // TODO: Concepts
+  TemplateParameterList *template_param_list = TemplateParameterList::Create(
+      *ast, SourceLocation(), SourceLocation(), template_param_decls,
+      SourceLocation(), requires_clause);
+  return template_param_list;
+}
+
+clang::FunctionTemplateDecl *TypeSystemClang::CreateFunctionTemplateDecl(
+    clang::DeclContext *decl_ctx, clang::FunctionDecl *func_decl,
+    const char *name, const TemplateParameterInfos &template_param_infos) {
+  //    /// Create a function template node.
+  ASTContext &ast = getASTContext();
+
+  llvm::SmallVector<NamedDecl *, 8> template_param_decls;
+
+  TemplateParameterList *template_param_list = CreateTemplateParameterList(
+      &ast, template_param_infos, template_param_decls);
+  FunctionTemplateDecl *func_tmpl_decl = FunctionTemplateDecl::Create(
+      ast, decl_ctx, func_decl->getLocation(), func_decl->getDeclName(),
+      template_param_list, func_decl);
+
+  for (size_t i = 0, template_param_decl_count = template_param_decls.size();
+       i < template_param_decl_count; ++i) {
+    // TODO: verify which decl context we should put template_param_decls into..
+    template_param_decls[i]->setDeclContext(func_decl);
+  }
+  // Function templates inside a record need to have an access specifier.
+  // It doesn't matter what access specifier we give the template as LLDB
+  // anyway allows accessing everything inside a record.
+  if (decl_ctx->isRecord())
+    func_tmpl_decl->setAccess(clang::AccessSpecifier::AS_public);
+
+  return func_tmpl_decl;
+}
+
+void TypeSystemClang::CreateFunctionTemplateSpecializationInfo(
+    FunctionDecl *func_decl, clang::FunctionTemplateDecl *func_tmpl_decl,
+    const TemplateParameterInfos &infos) {
+  TemplateArgumentList *template_args_ptr =
+      TemplateArgumentList::CreateCopy(func_decl->getASTContext(), infos.args);
+
+  func_decl->setFunctionTemplateSpecialization(func_tmpl_decl,
+                                               template_args_ptr, nullptr);
+}
+
+ClassTemplateDecl *TypeSystemClang::CreateClassTemplateDecl(
+    DeclContext *decl_ctx, lldb::AccessType access_type, const char *class_name,
+    int kind, const TemplateParameterInfos &template_param_infos) {
+  ASTContext &ast = getASTContext();
+
+  ClassTemplateDecl *class_template_decl = nullptr;
+  if (decl_ctx == nullptr)
+    decl_ctx = ast.getTranslationUnitDecl();
+
+  IdentifierInfo &identifier_info = ast.Idents.get(class_name);
+  DeclarationName decl_name(&identifier_info);
+
+  clang::DeclContext::lookup_result result = decl_ctx->lookup(decl_name);
+
+  for (NamedDecl *decl : result) {
+    class_template_decl = dyn_cast<clang::ClassTemplateDecl>(decl);
+    if (class_template_decl)
+      return class_template_decl;
+  }
+
+  llvm::SmallVector<NamedDecl *, 8> template_param_decls;
+
+  TemplateParameterList *template_param_list = CreateTemplateParameterList(
+      &ast, template_param_infos, template_param_decls);
+
+  CXXRecordDecl *template_cxx_decl = CXXRecordDecl::Create(
+      ast, (TagDecl::TagKind)kind,
+      decl_ctx, // What decl context do we use here? TU? The actual decl
+                // context?
+      SourceLocation(), SourceLocation(), &identifier_info);
+
+  for (size_t i = 0, template_param_decl_count = template_param_decls.size();
+       i < template_param_decl_count; ++i) {
+    template_param_decls[i]->setDeclContext(template_cxx_decl);
+  }
+
+  // With templated classes, we say that a class is templated with
+  // specializations, but that the bare class has no functions.
+  // template_cxx_decl->startDefinition();
+  // template_cxx_decl->completeDefinition();
+
+  class_template_decl = ClassTemplateDecl::Create(
+      ast,
+      decl_ctx, // What decl context do we use here? TU? The actual decl
+                // context?
+      SourceLocation(), decl_name, template_param_list, template_cxx_decl);
+  template_cxx_decl->setDescribedClassTemplate(class_template_decl);
+
+  if (class_template_decl) {
+    if (access_type != eAccessNone)
+      class_template_decl->setAccess(
+          ConvertAccessTypeToAccessSpecifier(access_type));
+
+    // if (TagDecl *ctx_tag_decl = dyn_cast<TagDecl>(decl_ctx))
+    //    CompleteTagDeclarationDefinition(GetTypeForDecl(ctx_tag_decl));
+
+    decl_ctx->addDecl(class_template_decl);
+
+#ifdef LLDB_CONFIGURATION_DEBUG
+    VerifyDecl(class_template_decl);
+#endif
+  }
+
+  return class_template_decl;
+}
+
+TemplateTemplateParmDecl *
+TypeSystemClang::CreateTemplateTemplateParmDecl(const char *template_name) {
+  ASTContext &ast = getASTContext();
+
+  auto *decl_ctx = ast.getTranslationUnitDecl();
+
+  IdentifierInfo &identifier_info = ast.Idents.get(template_name);
+  llvm::SmallVector<NamedDecl *, 8> template_param_decls;
+
+  TypeSystemClang::TemplateParameterInfos template_param_infos;
+  TemplateParameterList *template_param_list = CreateTemplateParameterList(
+      &ast, template_param_infos, template_param_decls);
+
+  // LLDB needs to create those decls only to be able to display a
+  // type that includes a template template argument. Only the name matters for
+  // this purpose, so we use dummy values for the other characterisitcs of the
+  // type.
+  return TemplateTemplateParmDecl::Create(
+      ast, decl_ctx, SourceLocation(),
+      /*Depth*/ 0, /*Position*/ 0,
+      /*IsParameterPack*/ false, &identifier_info, template_param_list);
+}
+
+ClassTemplateSpecializationDecl *
+TypeSystemClang::CreateClassTemplateSpecializationDecl(
+    DeclContext *decl_ctx, ClassTemplateDecl *class_template_decl, int kind,
+    const TemplateParameterInfos &template_param_infos) {
+  ASTContext &ast = getASTContext();
+  llvm::SmallVector<clang::TemplateArgument, 2> args(
+      template_param_infos.args.size() +
+      (template_param_infos.packed_args ? 1 : 0));
+  std::copy(template_param_infos.args.begin(), template_param_infos.args.end(),
+            args.begin());
+  if (template_param_infos.packed_args) {
+    args[args.size() - 1] = TemplateArgument::CreatePackCopy(
+        ast, template_param_infos.packed_args->args);
+  }
+  ClassTemplateSpecializationDecl *class_template_specialization_decl =
+      ClassTemplateSpecializationDecl::Create(
+          ast, (TagDecl::TagKind)kind, decl_ctx, SourceLocation(),
+          SourceLocation(), class_template_decl, args, nullptr);
+
+  class_template_specialization_decl->setSpecializationKind(
+      TSK_ExplicitSpecialization);
+
+  return class_template_specialization_decl;
+}
+
+CompilerType TypeSystemClang::CreateClassTemplateSpecializationType(
+    ClassTemplateSpecializationDecl *class_template_specialization_decl) {
+  if (class_template_specialization_decl) {
+    ASTContext &ast = getASTContext();
+    return GetType(ast.getTagDeclType(class_template_specialization_decl));
+  }
+  return CompilerType();
+}
+
+static inline bool check_op_param(bool is_method,
+                                  clang::OverloadedOperatorKind op_kind,
+                                  bool unary, bool binary,
+                                  uint32_t num_params) {
+  // Special-case call since it can take any number of operands
+  if (op_kind == OO_Call)
+    return true;
+
+  // The parameter count doesn't include "this"
+  if (is_method)
+    ++num_params;
+  if (num_params == 1)
+    return unary;
+  if (num_params == 2)
+    return binary;
+  else
+    return false;
+}
+
+bool TypeSystemClang::CheckOverloadedOperatorKindParameterCount(
+    bool is_method, clang::OverloadedOperatorKind op_kind,
+    uint32_t num_params) {
+  switch (op_kind) {
+  default:
+    break;
+  // C++ standard allows any number of arguments to new/delete
+  case OO_New:
+  case OO_Array_New:
+  case OO_Delete:
+  case OO_Array_Delete:
+    return true;
+  }
+
+#define OVERLOADED_OPERATOR(Name, Spelling, Token, Unary, Binary, MemberOnly)  \
+  case OO_##Name:                                                              \
+    return check_op_param(is_method, op_kind, Unary, Binary, num_params);
+  switch (op_kind) {
+#include "clang/Basic/OperatorKinds.def"
+  default:
+    break;
+  }
+  return false;
+}
+
+clang::AccessSpecifier
+TypeSystemClang::UnifyAccessSpecifiers(clang::AccessSpecifier lhs,
+                                       clang::AccessSpecifier rhs) {
+  // Make the access equal to the stricter of the field and the nested field's
+  // access
+  if (lhs == AS_none || rhs == AS_none)
+    return AS_none;
+  if (lhs == AS_private || rhs == AS_private)
+    return AS_private;
+  if (lhs == AS_protected || rhs == AS_protected)
+    return AS_protected;
+  return AS_public;
+}
+
+bool TypeSystemClang::FieldIsBitfield(FieldDecl *field,
+                                      uint32_t &bitfield_bit_size) {
+  ASTContext &ast = getASTContext();
+  if (field == nullptr)
+    return false;
+
+  if (field->isBitField()) {
+    Expr *bit_width_expr = field->getBitWidth();
+    if (bit_width_expr) {
+      llvm::APSInt bit_width_apsint;
+      if (bit_width_expr->isIntegerConstantExpr(bit_width_apsint, ast)) {
+        bitfield_bit_size = bit_width_apsint.getLimitedValue(UINT32_MAX);
+        return true;
+      }
+    }
+  }
+  return false;
+}
+
+bool TypeSystemClang::RecordHasFields(const RecordDecl *record_decl) {
+  if (record_decl == nullptr)
+    return false;
+
+  if (!record_decl->field_empty())
+    return true;
+
+  // No fields, lets check this is a CXX record and check the base classes
+  const CXXRecordDecl *cxx_record_decl = dyn_cast<CXXRecordDecl>(record_decl);
+  if (cxx_record_decl) {
+    CXXRecordDecl::base_class_const_iterator base_class, base_class_end;
+    for (base_class = cxx_record_decl->bases_begin(),
+        base_class_end = cxx_record_decl->bases_end();
+         base_class != base_class_end; ++base_class) {
+      const CXXRecordDecl *base_class_decl = cast<CXXRecordDecl>(
+          base_class->getType()->getAs<RecordType>()->getDecl());
+      if (RecordHasFields(base_class_decl))
+        return true;
+    }
+  }
+  return false;
+}
+
+#pragma mark Objective-C Classes
+
+CompilerType TypeSystemClang::CreateObjCClass(llvm::StringRef name,
+                                              DeclContext *decl_ctx,
+                                              bool isForwardDecl,
+                                              bool isInternal,
+                                              ClangASTMetadata *metadata) {
+  ASTContext &ast = getASTContext();
+  assert(!name.empty());
+  if (decl_ctx == nullptr)
+    decl_ctx = ast.getTranslationUnitDecl();
+
+  ObjCInterfaceDecl *decl = ObjCInterfaceDecl::Create(
+      ast, decl_ctx, SourceLocation(), &ast.Idents.get(name), nullptr, nullptr,
+      SourceLocation(),
+      /*isForwardDecl,*/
+      isInternal);
+
+  if (decl && metadata)
+    SetMetadata(decl, *metadata);
+
+  return GetType(ast.getObjCInterfaceType(decl));
+}
+
+static inline bool BaseSpecifierIsEmpty(const CXXBaseSpecifier *b) {
+  return !TypeSystemClang::RecordHasFields(b->getType()->getAsCXXRecordDecl());
+}
+
+uint32_t
+TypeSystemClang::GetNumBaseClasses(const CXXRecordDecl *cxx_record_decl,
+                                   bool omit_empty_base_classes) {
+  uint32_t num_bases = 0;
+  if (cxx_record_decl) {
+    if (omit_empty_base_classes) {
+      CXXRecordDecl::base_class_const_iterator base_class, base_class_end;
+      for (base_class = cxx_record_decl->bases_begin(),
+          base_class_end = cxx_record_decl->bases_end();
+           base_class != base_class_end; ++base_class) {
+        // Skip empty base classes
+        if (omit_empty_base_classes) {
+          if (BaseSpecifierIsEmpty(base_class))
+            continue;
+        }
+        ++num_bases;
+      }
+    } else
+      num_bases = cxx_record_decl->getNumBases();
+  }
+  return num_bases;
+}
+
+#pragma mark Namespace Declarations
+
+NamespaceDecl *TypeSystemClang::GetUniqueNamespaceDeclaration(
+    const char *name, DeclContext *decl_ctx, bool is_inline) {
+  NamespaceDecl *namespace_decl = nullptr;
+  ASTContext &ast = getASTContext();
+  TranslationUnitDecl *translation_unit_decl = ast.getTranslationUnitDecl();
+  if (decl_ctx == nullptr)
+    decl_ctx = translation_unit_decl;
+
+  if (name) {
+    IdentifierInfo &identifier_info = ast.Idents.get(name);
+    DeclarationName decl_name(&identifier_info);
+    clang::DeclContext::lookup_result result = decl_ctx->lookup(decl_name);
+    for (NamedDecl *decl : result) {
+      namespace_decl = dyn_cast<clang::NamespaceDecl>(decl);
+      if (namespace_decl)
+        return namespace_decl;
+    }
+
+    namespace_decl =
+        NamespaceDecl::Create(ast, decl_ctx, is_inline, SourceLocation(),
+                              SourceLocation(), &identifier_info, nullptr);
+
+    decl_ctx->addDecl(namespace_decl);
+  } else {
+    if (decl_ctx == translation_unit_decl) {
+      namespace_decl = translation_unit_decl->getAnonymousNamespace();
+      if (namespace_decl)
+        return namespace_decl;
+
+      namespace_decl =
+          NamespaceDecl::Create(ast, decl_ctx, false, SourceLocation(),
+                                SourceLocation(), nullptr, nullptr);
+      translation_unit_decl->setAnonymousNamespace(namespace_decl);
+      translation_unit_decl->addDecl(namespace_decl);
+      assert(namespace_decl == translation_unit_decl->getAnonymousNamespace());
+    } else {
+      NamespaceDecl *parent_namespace_decl = cast<NamespaceDecl>(decl_ctx);
+      if (parent_namespace_decl) {
+        namespace_decl = parent_namespace_decl->getAnonymousNamespace();
+        if (namespace_decl)
+          return namespace_decl;
+        namespace_decl =
+            NamespaceDecl::Create(ast, decl_ctx, false, SourceLocation(),
+                                  SourceLocation(), nullptr, nullptr);
+        parent_namespace_decl->setAnonymousNamespace(namespace_decl);
+        parent_namespace_decl->addDecl(namespace_decl);
+        assert(namespace_decl ==
+               parent_namespace_decl->getAnonymousNamespace());
+      } else {
+        assert(false && "GetUniqueNamespaceDeclaration called with no name and "
+                        "no namespace as decl_ctx");
+      }
+    }
+  }
+#ifdef LLDB_CONFIGURATION_DEBUG
+  VerifyDecl(namespace_decl);
+#endif
+  return namespace_decl;
+}
+
+clang::BlockDecl *
+TypeSystemClang::CreateBlockDeclaration(clang::DeclContext *ctx) {
+  if (ctx != nullptr) {
+    clang::BlockDecl *decl =
+        clang::BlockDecl::Create(getASTContext(), ctx, clang::SourceLocation());
+    ctx->addDecl(decl);
+    return decl;
+  }
+  return nullptr;
+}
+
+clang::DeclContext *FindLCABetweenDecls(clang::DeclContext *left,
+                                        clang::DeclContext *right,
+                                        clang::DeclContext *root) {
+  if (root == nullptr)
+    return nullptr;
+
+  std::set<clang::DeclContext *> path_left;
+  for (clang::DeclContext *d = left; d != nullptr; d = d->getParent())
+    path_left.insert(d);
+
+  for (clang::DeclContext *d = right; d != nullptr; d = d->getParent())
+    if (path_left.find(d) != path_left.end())
+      return d;
+
+  return nullptr;
+}
+
+clang::UsingDirectiveDecl *TypeSystemClang::CreateUsingDirectiveDeclaration(
+    clang::DeclContext *decl_ctx, clang::NamespaceDecl *ns_decl) {
+  if (decl_ctx != nullptr && ns_decl != nullptr) {
+    auto *translation_unit = getASTContext().getTranslationUnitDecl();
+    clang::UsingDirectiveDecl *using_decl = clang::UsingDirectiveDecl::Create(
+        getASTContext(), decl_ctx, clang::SourceLocation(),
+        clang::SourceLocation(), clang::NestedNameSpecifierLoc(),
+        clang::SourceLocation(), ns_decl,
+        FindLCABetweenDecls(decl_ctx, ns_decl, translation_unit));
+    decl_ctx->addDecl(using_decl);
+    return using_decl;
+  }
+  return nullptr;
+}
+
+clang::UsingDecl *
+TypeSystemClang::CreateUsingDeclaration(clang::DeclContext *current_decl_ctx,
+                                        clang::NamedDecl *target) {
+  if (current_decl_ctx != nullptr && target != nullptr) {
+    clang::UsingDecl *using_decl = clang::UsingDecl::Create(
+        getASTContext(), current_decl_ctx, clang::SourceLocation(),
+        clang::NestedNameSpecifierLoc(), clang::DeclarationNameInfo(), false);
+    clang::UsingShadowDecl *shadow_decl = clang::UsingShadowDecl::Create(
+        getASTContext(), current_decl_ctx, clang::SourceLocation(), using_decl,
+        target);
+    using_decl->addShadowDecl(shadow_decl);
+    current_decl_ctx->addDecl(using_decl);
+    return using_decl;
+  }
+  return nullptr;
+}
+
+clang::VarDecl *TypeSystemClang::CreateVariableDeclaration(
+    clang::DeclContext *decl_context, const char *name, clang::QualType type) {
+  if (decl_context != nullptr) {
+    clang::VarDecl *var_decl = clang::VarDecl::Create(
+        getASTContext(), decl_context, clang::SourceLocation(),
+        clang::SourceLocation(),
+        name && name[0] ? &getASTContext().Idents.getOwn(name) : nullptr, type,
+        nullptr, clang::SC_None);
+    var_decl->setAccess(clang::AS_public);
+    decl_context->addDecl(var_decl);
+    return var_decl;
+  }
+  return nullptr;
+}
+
+lldb::opaque_compiler_type_t
+TypeSystemClang::GetOpaqueCompilerType(clang::ASTContext *ast,
+                                       lldb::BasicType basic_type) {
+  switch (basic_type) {
+  case eBasicTypeVoid:
+    return ast->VoidTy.getAsOpaquePtr();
+  case eBasicTypeChar:
+    return ast->CharTy.getAsOpaquePtr();
+  case eBasicTypeSignedChar:
+    return ast->SignedCharTy.getAsOpaquePtr();
+  case eBasicTypeUnsignedChar:
+    return ast->UnsignedCharTy.getAsOpaquePtr();
+  case eBasicTypeWChar:
+    return ast->getWCharType().getAsOpaquePtr();
+  case eBasicTypeSignedWChar:
+    return ast->getSignedWCharType().getAsOpaquePtr();
+  case eBasicTypeUnsignedWChar:
+    return ast->getUnsignedWCharType().getAsOpaquePtr();
+  case eBasicTypeChar16:
+    return ast->Char16Ty.getAsOpaquePtr();
+  case eBasicTypeChar32:
+    return ast->Char32Ty.getAsOpaquePtr();
+  case eBasicTypeShort:
+    return ast->ShortTy.getAsOpaquePtr();
+  case eBasicTypeUnsignedShort:
+    return ast->UnsignedShortTy.getAsOpaquePtr();
+  case eBasicTypeInt:
+    return ast->IntTy.getAsOpaquePtr();
+  case eBasicTypeUnsignedInt:
+    return ast->UnsignedIntTy.getAsOpaquePtr();
+  case eBasicTypeLong:
+    return ast->LongTy.getAsOpaquePtr();
+  case eBasicTypeUnsignedLong:
+    return ast->UnsignedLongTy.getAsOpaquePtr();
+  case eBasicTypeLongLong:
+    return ast->LongLongTy.getAsOpaquePtr();
+  case eBasicTypeUnsignedLongLong:
+    return ast->UnsignedLongLongTy.getAsOpaquePtr();
+  case eBasicTypeInt128:
+    return ast->Int128Ty.getAsOpaquePtr();
+  case eBasicTypeUnsignedInt128:
+    return ast->UnsignedInt128Ty.getAsOpaquePtr();
+  case eBasicTypeBool:
+    return ast->BoolTy.getAsOpaquePtr();
+  case eBasicTypeHalf:
+    return ast->HalfTy.getAsOpaquePtr();
+  case eBasicTypeFloat:
+    return ast->FloatTy.getAsOpaquePtr();
+  case eBasicTypeDouble:
+    return ast->DoubleTy.getAsOpaquePtr();
+  case eBasicTypeLongDouble:
+    return ast->LongDoubleTy.getAsOpaquePtr();
+  case eBasicTypeFloatComplex:
+    return ast->FloatComplexTy.getAsOpaquePtr();
+  case eBasicTypeDoubleComplex:
+    return ast->DoubleComplexTy.getAsOpaquePtr();
+  case eBasicTypeLongDoubleComplex:
+    return ast->LongDoubleComplexTy.getAsOpaquePtr();
+  case eBasicTypeObjCID:
+    return ast->getObjCIdType().getAsOpaquePtr();
+  case eBasicTypeObjCClass:
+    return ast->getObjCClassType().getAsOpaquePtr();
+  case eBasicTypeObjCSel:
+    return ast->getObjCSelType().getAsOpaquePtr();
+  case eBasicTypeNullPtr:
+    return ast->NullPtrTy.getAsOpaquePtr();
+  default:
+    return nullptr;
+  }
+}
+
+#pragma mark Function Types
+
+clang::DeclarationName
+TypeSystemClang::GetDeclarationName(const char *name,
+                                    const CompilerType &function_clang_type) {
+  if (!name || !name[0])
+    return clang::DeclarationName();
+
+  clang::OverloadedOperatorKind op_kind = clang::NUM_OVERLOADED_OPERATORS;
+  if (!IsOperator(name, op_kind) || op_kind == clang::NUM_OVERLOADED_OPERATORS)
+    return DeclarationName(&getASTContext().Idents.get(
+        name)); // Not operator, but a regular function.
+
+  // Check the number of operator parameters. Sometimes we have seen bad DWARF
+  // that doesn't correctly describe operators and if we try to create a method
+  // and add it to the class, clang will assert and crash, so we need to make
+  // sure things are acceptable.
+  clang::QualType method_qual_type(ClangUtil::GetQualType(function_clang_type));
+  const clang::FunctionProtoType *function_type =
+      llvm::dyn_cast<clang::FunctionProtoType>(method_qual_type.getTypePtr());
+  if (function_type == nullptr)
+    return clang::DeclarationName();
+
+  const bool is_method = false;
+  const unsigned int num_params = function_type->getNumParams();
+  if (!TypeSystemClang::CheckOverloadedOperatorKindParameterCount(
+          is_method, op_kind, num_params))
+    return clang::DeclarationName();
+
+  return getASTContext().DeclarationNames.getCXXOperatorName(op_kind);
+}
+
+FunctionDecl *TypeSystemClang::CreateFunctionDeclaration(
+    DeclContext *decl_ctx, const char *name,
+    const CompilerType &function_clang_type, int storage, bool is_inline) {
+  FunctionDecl *func_decl = nullptr;
+  ASTContext &ast = getASTContext();
+  if (decl_ctx == nullptr)
+    decl_ctx = ast.getTranslationUnitDecl();
+
+  const bool hasWrittenPrototype = true;
+  const bool isConstexprSpecified = false;
+
+  clang::DeclarationName declarationName =
+      GetDeclarationName(name, function_clang_type);
+  func_decl = FunctionDecl::Create(
+      ast, decl_ctx, SourceLocation(), SourceLocation(), declarationName,
+      ClangUtil::GetQualType(function_clang_type), nullptr,
+      (clang::StorageClass)storage, is_inline, hasWrittenPrototype,
+      isConstexprSpecified ? CSK_constexpr : CSK_unspecified);
+  if (func_decl)
+    decl_ctx->addDecl(func_decl);
+
+#ifdef LLDB_CONFIGURATION_DEBUG
+  VerifyDecl(func_decl);
+#endif
+
+  return func_decl;
+}
+
+CompilerType
+TypeSystemClang::CreateFunctionType(const CompilerType &result_type,
+                                    const CompilerType *args, unsigned num_args,
+                                    bool is_variadic, unsigned type_quals,
+                                    clang::CallingConv cc) {
+  if (!result_type || !ClangUtil::IsClangType(result_type))
+    return CompilerType(); // invalid return type
+
+  std::vector<QualType> qual_type_args;
+  if (num_args > 0 && args == nullptr)
+    return CompilerType(); // invalid argument array passed in
+
+  // Verify that all arguments are valid and the right type
+  for (unsigned i = 0; i < num_args; ++i) {
+    if (args[i]) {
+      // Make sure we have a clang type in args[i] and not a type from another
+      // language whose name might match
+      const bool is_clang_type = ClangUtil::IsClangType(args[i]);
+      lldbassert(is_clang_type);
+      if (is_clang_type)
+        qual_type_args.push_back(ClangUtil::GetQualType(args[i]));
+      else
+        return CompilerType(); //  invalid argument type (must be a clang type)
+    } else
+      return CompilerType(); // invalid argument type (empty)
+  }
+
+  // TODO: Detect calling convention in DWARF?
+  FunctionProtoType::ExtProtoInfo proto_info;
+  proto_info.ExtInfo = cc;
+  proto_info.Variadic = is_variadic;
+  proto_info.ExceptionSpec = EST_None;
+  proto_info.TypeQuals = clang::Qualifiers::fromFastMask(type_quals);
+  proto_info.RefQualifier = RQ_None;
+
+  return GetType(getASTContext().getFunctionType(
+      ClangUtil::GetQualType(result_type), qual_type_args, proto_info));
+}
+
+ParmVarDecl *TypeSystemClang::CreateParameterDeclaration(
+    clang::DeclContext *decl_ctx, const char *name,
+    const CompilerType &param_type, int storage, bool add_decl) {
+  ASTContext &ast = getASTContext();
+  auto *decl =
+      ParmVarDecl::Create(ast, decl_ctx, SourceLocation(), SourceLocation(),
+                          name && name[0] ? &ast.Idents.get(name) : nullptr,
+                          ClangUtil::GetQualType(param_type), nullptr,
+                          (clang::StorageClass)storage, nullptr);
+  if (add_decl)
+    decl_ctx->addDecl(decl);
+
+  return decl;
+}
+
+void TypeSystemClang::SetFunctionParameters(FunctionDecl *function_decl,
+                                            ParmVarDecl **params,
+                                            unsigned num_params) {
+  if (function_decl)
+    function_decl->setParams(ArrayRef<ParmVarDecl *>(params, num_params));
+}
+
+CompilerType
+TypeSystemClang::CreateBlockPointerType(const CompilerType &function_type) {
+  QualType block_type = m_ast_up->getBlockPointerType(
+      clang::QualType::getFromOpaquePtr(function_type.GetOpaqueQualType()));
+
+  return GetType(block_type);
+}
+
+#pragma mark Array Types
+
+CompilerType TypeSystemClang::CreateArrayType(const CompilerType &element_type,
+                                              size_t element_count,
+                                              bool is_vector) {
+  if (element_type.IsValid()) {
+    ASTContext &ast = getASTContext();
+
+    if (is_vector) {
+      return GetType(ast.getExtVectorType(ClangUtil::GetQualType(element_type),
+                                          element_count));
+    } else {
+
+      llvm::APInt ap_element_count(64, element_count);
+      if (element_count == 0) {
+        return GetType(ast.getIncompleteArrayType(
+            ClangUtil::GetQualType(element_type), clang::ArrayType::Normal, 0));
+      } else {
+        return GetType(ast.getConstantArrayType(
+            ClangUtil::GetQualType(element_type), ap_element_count, nullptr,
+            clang::ArrayType::Normal, 0));
+      }
+    }
+  }
+  return CompilerType();
+}
+
+CompilerType TypeSystemClang::CreateStructForIdentifier(
+    ConstString type_name,
+    const std::initializer_list<std::pair<const char *, CompilerType>>
+        &type_fields,
+    bool packed) {
+  CompilerType type;
+  if (!type_name.IsEmpty() &&
+      (type = GetTypeForIdentifier<clang::CXXRecordDecl>(type_name))
+          .IsValid()) {
+    lldbassert(0 && "Trying to create a type for an existing name");
+    return type;
+  }
+
+  type = CreateRecordType(nullptr, lldb::eAccessPublic, type_name.GetCString(),
+                          clang::TTK_Struct, lldb::eLanguageTypeC);
+  StartTagDeclarationDefinition(type);
+  for (const auto &field : type_fields)
+    AddFieldToRecordType(type, field.first, field.second, lldb::eAccessPublic,
+                         0);
+  if (packed)
+    SetIsPacked(type);
+  CompleteTagDeclarationDefinition(type);
+  return type;
+}
+
+CompilerType TypeSystemClang::GetOrCreateStructForIdentifier(
+    ConstString type_name,
+    const std::initializer_list<std::pair<const char *, CompilerType>>
+        &type_fields,
+    bool packed) {
+  CompilerType type;
+  if ((type = GetTypeForIdentifier<clang::CXXRecordDecl>(type_name)).IsValid())
+    return type;
+
+  return CreateStructForIdentifier(type_name, type_fields, packed);
+}
+
+#pragma mark Enumeration Types
+
+CompilerType
+TypeSystemClang::CreateEnumerationType(const char *name, DeclContext *decl_ctx,
+                                       const Declaration &decl,
+                                       const CompilerType &integer_clang_type,
+                                       bool is_scoped) {
+  // TODO: Do something intelligent with the Declaration object passed in
+  // like maybe filling in the SourceLocation with it...
+  ASTContext &ast = getASTContext();
+
+  // TODO: ask about these...
+  //    const bool IsFixed = false;
+
+  EnumDecl *enum_decl = EnumDecl::Create(
+      ast, decl_ctx, SourceLocation(), SourceLocation(),
+      name && name[0] ? &ast.Idents.get(name) : nullptr, nullptr,
+      is_scoped, // IsScoped
+      is_scoped, // IsScopedUsingClassTag
+      false);    // IsFixed
+
+  if (enum_decl) {
+    if (decl_ctx)
+      decl_ctx->addDecl(enum_decl);
+
+    // TODO: check if we should be setting the promotion type too?
+    enum_decl->setIntegerType(ClangUtil::GetQualType(integer_clang_type));
+
+    enum_decl->setAccess(AS_public); // TODO respect what's in the debug info
+
+    return GetType(ast.getTagDeclType(enum_decl));
+  }
+  return CompilerType();
+}
+
+CompilerType TypeSystemClang::GetIntTypeFromBitSize(size_t bit_size,
+                                                    bool is_signed) {
+  clang::ASTContext &ast = getASTContext();
+
+  if (is_signed) {
+    if (bit_size == ast.getTypeSize(ast.SignedCharTy))
+      return GetType(ast.SignedCharTy);
+
+    if (bit_size == ast.getTypeSize(ast.ShortTy))
+      return GetType(ast.ShortTy);
+
+    if (bit_size == ast.getTypeSize(ast.IntTy))
+      return GetType(ast.IntTy);
+
+    if (bit_size == ast.getTypeSize(ast.LongTy))
+      return GetType(ast.LongTy);
+
+    if (bit_size == ast.getTypeSize(ast.LongLongTy))
+      return GetType(ast.LongLongTy);
+
+    if (bit_size == ast.getTypeSize(ast.Int128Ty))
+      return GetType(ast.Int128Ty);
+  } else {
+    if (bit_size == ast.getTypeSize(ast.UnsignedCharTy))
+      return GetType(ast.UnsignedCharTy);
+
+    if (bit_size == ast.getTypeSize(ast.UnsignedShortTy))
+      return GetType(ast.UnsignedShortTy);
+
+    if (bit_size == ast.getTypeSize(ast.UnsignedIntTy))
+      return GetType(ast.UnsignedIntTy);
+
+    if (bit_size == ast.getTypeSize(ast.UnsignedLongTy))
+      return GetType(ast.UnsignedLongTy);
+
+    if (bit_size == ast.getTypeSize(ast.UnsignedLongLongTy))
+      return GetType(ast.UnsignedLongLongTy);
+
+    if (bit_size == ast.getTypeSize(ast.UnsignedInt128Ty))
+      return GetType(ast.UnsignedInt128Ty);
+  }
+  return CompilerType();
+}
+
+CompilerType TypeSystemClang::GetPointerSizedIntType(bool is_signed) {
+  return GetIntTypeFromBitSize(
+      getASTContext().getTypeSize(getASTContext().VoidPtrTy), is_signed);
+}
+
+void TypeSystemClang::DumpDeclContextHiearchy(clang::DeclContext *decl_ctx) {
+  if (decl_ctx) {
+    DumpDeclContextHiearchy(decl_ctx->getParent());
+
+    clang::NamedDecl *named_decl = llvm::dyn_cast<clang::NamedDecl>(decl_ctx);
+    if (named_decl) {
+      printf("%20s: %s\n", decl_ctx->getDeclKindName(),
+             named_decl->getDeclName().getAsString().c_str());
+    } else {
+      printf("%20s\n", decl_ctx->getDeclKindName());
+    }
+  }
+}
+
+void TypeSystemClang::DumpDeclHiearchy(clang::Decl *decl) {
+  if (decl == nullptr)
+    return;
+  DumpDeclContextHiearchy(decl->getDeclContext());
+
+  clang::RecordDecl *record_decl = llvm::dyn_cast<clang::RecordDecl>(decl);
+  if (record_decl) {
+    printf("%20s: %s%s\n", decl->getDeclKindName(),
+           record_decl->getDeclName().getAsString().c_str(),
+           record_decl->isInjectedClassName() ? " (injected class name)" : "");
+
+  } else {
+    clang::NamedDecl *named_decl = llvm::dyn_cast<clang::NamedDecl>(decl);
+    if (named_decl) {
+      printf("%20s: %s\n", decl->getDeclKindName(),
+             named_decl->getDeclName().getAsString().c_str());
+    } else {
+      printf("%20s\n", decl->getDeclKindName());
+    }
+  }
+}
+
+bool TypeSystemClang::DeclsAreEquivalent(clang::Decl *lhs_decl,
+                                         clang::Decl *rhs_decl) {
+  if (lhs_decl && rhs_decl) {
+    // Make sure the decl kinds match first
+    const clang::Decl::Kind lhs_decl_kind = lhs_decl->getKind();
+    const clang::Decl::Kind rhs_decl_kind = rhs_decl->getKind();
+
+    if (lhs_decl_kind == rhs_decl_kind) {
+      // Now check that the decl contexts kinds are all equivalent before we
+      // have to check any names of the decl contexts...
+      clang::DeclContext *lhs_decl_ctx = lhs_decl->getDeclContext();
+      clang::DeclContext *rhs_decl_ctx = rhs_decl->getDeclContext();
+      if (lhs_decl_ctx && rhs_decl_ctx) {
+        while (true) {
+          if (lhs_decl_ctx && rhs_decl_ctx) {
+            const clang::Decl::Kind lhs_decl_ctx_kind =
+                lhs_decl_ctx->getDeclKind();
+            const clang::Decl::Kind rhs_decl_ctx_kind =
+                rhs_decl_ctx->getDeclKind();
+            if (lhs_decl_ctx_kind == rhs_decl_ctx_kind) {
+              lhs_decl_ctx = lhs_decl_ctx->getParent();
+              rhs_decl_ctx = rhs_decl_ctx->getParent();
+
+              if (lhs_decl_ctx == nullptr && rhs_decl_ctx == nullptr)
+                break;
+            } else
+              return false;
+          } else
+            return false;
+        }
+
+        // Now make sure the name of the decls match
+        clang::NamedDecl *lhs_named_decl =
+            llvm::dyn_cast<clang::NamedDecl>(lhs_decl);
+        clang::NamedDecl *rhs_named_decl =
+            llvm::dyn_cast<clang::NamedDecl>(rhs_decl);
+        if (lhs_named_decl && rhs_named_decl) {
+          clang::DeclarationName lhs_decl_name = lhs_named_decl->getDeclName();
+          clang::DeclarationName rhs_decl_name = rhs_named_decl->getDeclName();
+          if (lhs_decl_name.getNameKind() == rhs_decl_name.getNameKind()) {
+            if (lhs_decl_name.getAsString() != rhs_decl_name.getAsString())
+              return false;
+          } else
+            return false;
+        } else
+          return false;
+
+        // We know that the decl context kinds all match, so now we need to
+        // make sure the names match as well
+        lhs_decl_ctx = lhs_decl->getDeclContext();
+        rhs_decl_ctx = rhs_decl->getDeclContext();
+        while (true) {
+          switch (lhs_decl_ctx->getDeclKind()) {
+          case clang::Decl::TranslationUnit:
+            // We don't care about the translation unit names
+            return true;
+          default: {
+            clang::NamedDecl *lhs_named_decl =
+                llvm::dyn_cast<clang::NamedDecl>(lhs_decl_ctx);
+            clang::NamedDecl *rhs_named_decl =
+                llvm::dyn_cast<clang::NamedDecl>(rhs_decl_ctx);
+            if (lhs_named_decl && rhs_named_decl) {
+              clang::DeclarationName lhs_decl_name =
+                  lhs_named_decl->getDeclName();
+              clang::DeclarationName rhs_decl_name =
+                  rhs_named_decl->getDeclName();
+              if (lhs_decl_name.getNameKind() == rhs_decl_name.getNameKind()) {
+                if (lhs_decl_name.getAsString() != rhs_decl_name.getAsString())
+                  return false;
+              } else
+                return false;
+            } else
+              return false;
+          } break;
+          }
+          lhs_decl_ctx = lhs_decl_ctx->getParent();
+          rhs_decl_ctx = rhs_decl_ctx->getParent();
+        }
+      }
+    }
+  }
+  return false;
+}
+bool TypeSystemClang::GetCompleteDecl(clang::ASTContext *ast,
+                                      clang::Decl *decl) {
+  if (!decl)
+    return false;
+
+  ExternalASTSource *ast_source = ast->getExternalSource();
+
+  if (!ast_source)
+    return false;
+
+  if (clang::TagDecl *tag_decl = llvm::dyn_cast<clang::TagDecl>(decl)) {
+    if (tag_decl->isCompleteDefinition())
+      return true;
+
+    if (!tag_decl->hasExternalLexicalStorage())
+      return false;
+
+    ast_source->CompleteType(tag_decl);
+
+    return !tag_decl->getTypeForDecl()->isIncompleteType();
+  } else if (clang::ObjCInterfaceDecl *objc_interface_decl =
+                 llvm::dyn_cast<clang::ObjCInterfaceDecl>(decl)) {
+    if (objc_interface_decl->getDefinition())
+      return true;
+
+    if (!objc_interface_decl->hasExternalLexicalStorage())
+      return false;
+
+    ast_source->CompleteType(objc_interface_decl);
+
+    return !objc_interface_decl->getTypeForDecl()->isIncompleteType();
+  } else {
+    return false;
+  }
+}
+
+void TypeSystemClang::SetMetadataAsUserID(const clang::Decl *decl,
+                                          user_id_t user_id) {
+  ClangASTMetadata meta_data;
+  meta_data.SetUserID(user_id);
+  SetMetadata(decl, meta_data);
+}
+
+void TypeSystemClang::SetMetadataAsUserID(const clang::Type *type,
+                                          user_id_t user_id) {
+  ClangASTMetadata meta_data;
+  meta_data.SetUserID(user_id);
+  SetMetadata(type, meta_data);
+}
+
+void TypeSystemClang::SetMetadata(const clang::Decl *object,
+                                  ClangASTMetadata &metadata) {
+  m_decl_metadata[object] = metadata;
+}
+
+void TypeSystemClang::SetMetadata(const clang::Type *object,
+                                  ClangASTMetadata &metadata) {
+  m_type_metadata[object] = metadata;
+}
+
+ClangASTMetadata *TypeSystemClang::GetMetadata(const clang::Decl *object) {
+  auto It = m_decl_metadata.find(object);
+  if (It != m_decl_metadata.end())
+    return &It->second;
+  return nullptr;
+}
+
+ClangASTMetadata *TypeSystemClang::GetMetadata(const clang::Type *object) {
+  auto It = m_type_metadata.find(object);
+  if (It != m_type_metadata.end())
+    return &It->second;
+  return nullptr;
+}
+
+bool TypeSystemClang::SetTagTypeKind(clang::QualType tag_qual_type,
+                                     int kind) const {
+  const clang::Type *clang_type = tag_qual_type.getTypePtr();
+  if (clang_type) {
+    const clang::TagType *tag_type = llvm::dyn_cast<clang::TagType>(clang_type);
+    if (tag_type) {
+      clang::TagDecl *tag_decl =
+          llvm::dyn_cast<clang::TagDecl>(tag_type->getDecl());
+      if (tag_decl) {
+        tag_decl->setTagKind((clang::TagDecl::TagKind)kind);
+        return true;
+      }
+    }
+  }
+  return false;
+}
+
+bool TypeSystemClang::SetDefaultAccessForRecordFields(
+    clang::RecordDecl *record_decl, int default_accessibility,
+    int *assigned_accessibilities, size_t num_assigned_accessibilities) {
+  if (record_decl) {
+    uint32_t field_idx;
+    clang::RecordDecl::field_iterator field, field_end;
+    for (field = record_decl->field_begin(),
+        field_end = record_decl->field_end(), field_idx = 0;
+         field != field_end; ++field, ++field_idx) {
+      // If no accessibility was assigned, assign the correct one
+      if (field_idx < num_assigned_accessibilities &&
+          assigned_accessibilities[field_idx] == clang::AS_none)
+        field->setAccess((clang::AccessSpecifier)default_accessibility);
+    }
+    return true;
+  }
+  return false;
+}
+
+clang::DeclContext *
+TypeSystemClang::GetDeclContextForType(const CompilerType &type) {
+  return GetDeclContextForType(ClangUtil::GetQualType(type));
+}
+
+/// Aggressively desugar the provided type, skipping past various kinds of
+/// syntactic sugar and other constructs one typically wants to ignore.
+/// The \p mask argument allows one to skip certain kinds of simplifications,
+/// when one wishes to handle a certain kind of type directly.
+static QualType
+RemoveWrappingTypes(QualType type, ArrayRef<clang::Type::TypeClass> mask = {}) {
+  while (true) {
+    if (find(mask, type->getTypeClass()) != mask.end())
+      return type;
+    switch (type->getTypeClass()) {
+    // This is not fully correct as _Atomic is more than sugar, but it is
+    // sufficient for the purposes we care about.
+    case clang::Type::Atomic:
+      type = cast<clang::AtomicType>(type)->getValueType();
+      break;
+    case clang::Type::Auto:
+    case clang::Type::Decltype:
+    case clang::Type::Elaborated:
+    case clang::Type::Paren:
+    case clang::Type::Typedef:
+    case clang::Type::TypeOf:
+    case clang::Type::TypeOfExpr:
+      type = type->getLocallyUnqualifiedSingleStepDesugaredType();
+      break;
+    default:
+      return type;
+    }
+  }
+}
+
+clang::DeclContext *
+TypeSystemClang::GetDeclContextForType(clang::QualType type) {
+  if (type.isNull())
+    return nullptr;
+
+  clang::QualType qual_type = RemoveWrappingTypes(type.getCanonicalType());
+  const clang::Type::TypeClass type_class = qual_type->getTypeClass();
+  switch (type_class) {
+  case clang::Type::ObjCInterface:
+    return llvm::cast<clang::ObjCObjectType>(qual_type.getTypePtr())
+        ->getInterface();
+  case clang::Type::ObjCObjectPointer:
+    return GetDeclContextForType(
+        llvm::cast<clang::ObjCObjectPointerType>(qual_type.getTypePtr())
+            ->getPointeeType());
+  case clang::Type::Record:
+    return llvm::cast<clang::RecordType>(qual_type)->getDecl();
+  case clang::Type::Enum:
+    return llvm::cast<clang::EnumType>(qual_type)->getDecl();
+  default:
+    break;
+  }
+  // No DeclContext in this type...
+  return nullptr;
+}
+
+static bool GetCompleteQualType(clang::ASTContext *ast,
+                                clang::QualType qual_type,
+                                bool allow_completion = true) {
+  qual_type = RemoveWrappingTypes(qual_type);
+  const clang::Type::TypeClass type_class = qual_type->getTypeClass();
+  switch (type_class) {
+  case clang::Type::ConstantArray:
+  case clang::Type::IncompleteArray:
+  case clang::Type::VariableArray: {
+    const clang::ArrayType *array_type =
+        llvm::dyn_cast<clang::ArrayType>(qual_type.getTypePtr());
+
+    if (array_type)
+      return GetCompleteQualType(ast, array_type->getElementType(),
+                                 allow_completion);
+  } break;
+  case clang::Type::Record: {
+    clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl();
+    if (cxx_record_decl) {
+      if (cxx_record_decl->hasExternalLexicalStorage()) {
+        const bool is_complete = cxx_record_decl->isCompleteDefinition();
+        const bool fields_loaded =
+            cxx_record_decl->hasLoadedFieldsFromExternalStorage();
+        if (is_complete && fields_loaded)
+          return true;
+
+        if (!allow_completion)
+          return false;
+
+        // Call the field_begin() accessor to for it to use the external source
+        // to load the fields...
+        clang::ExternalASTSource *external_ast_source =
+            ast->getExternalSource();
+        if (external_ast_source) {
+          external_ast_source->CompleteType(cxx_record_decl);
+          if (cxx_record_decl->isCompleteDefinition()) {
+            cxx_record_decl->field_begin();
+            cxx_record_decl->setHasLoadedFieldsFromExternalStorage(true);
+          }
+        }
+      }
+    }
+    const clang::TagType *tag_type =
+        llvm::cast<clang::TagType>(qual_type.getTypePtr());
+    return !tag_type->isIncompleteType();
+  } break;
+
+  case clang::Type::Enum: {
+    const clang::TagType *tag_type =
+        llvm::dyn_cast<clang::TagType>(qual_type.getTypePtr());
+    if (tag_type) {
+      clang::TagDecl *tag_decl = tag_type->getDecl();
+      if (tag_decl) {
+        if (tag_decl->getDefinition())
+          return true;
+
+        if (!allow_completion)
+          return false;
+
+        if (tag_decl->hasExternalLexicalStorage()) {
+          if (ast) {
+            clang::ExternalASTSource *external_ast_source =
+                ast->getExternalSource();
+            if (external_ast_source) {
+              external_ast_source->CompleteType(tag_decl);
+              return !tag_type->isIncompleteType();
+            }
+          }
+        }
+        return false;
+      }
+    }
+
+  } break;
+  case clang::Type::ObjCObject:
+  case clang::Type::ObjCInterface: {
+    const clang::ObjCObjectType *objc_class_type =
+        llvm::dyn_cast<clang::ObjCObjectType>(qual_type);
+    if (objc_class_type) {
+      clang::ObjCInterfaceDecl *class_interface_decl =
+          objc_class_type->getInterface();
+      // We currently can't complete objective C types through the newly added
+      // ASTContext because it only supports TagDecl objects right now...
+      if (class_interface_decl) {
+        if (class_interface_decl->getDefinition())
+          return true;
+
+        if (!allow_completion)
+          return false;
+
+        if (class_interface_decl->hasExternalLexicalStorage()) {
+          if (ast) {
+            clang::ExternalASTSource *external_ast_source =
+                ast->getExternalSource();
+            if (external_ast_source) {
+              external_ast_source->CompleteType(class_interface_decl);
+              return !objc_class_type->isIncompleteType();
+            }
+          }
+        }
+        return false;
+      }
+    }
+  } break;
+
+  case clang::Type::Attributed:
+    return GetCompleteQualType(
+        ast, llvm::cast<clang::AttributedType>(qual_type)->getModifiedType(),
+        allow_completion);
+
+  default:
+    break;
+  }
+
+  return true;
+}
+
+static clang::ObjCIvarDecl::AccessControl
+ConvertAccessTypeToObjCIvarAccessControl(AccessType access) {
+  switch (access) {
+  case eAccessNone:
+    return clang::ObjCIvarDecl::None;
+  case eAccessPublic:
+    return clang::ObjCIvarDecl::Public;
+  case eAccessPrivate:
+    return clang::ObjCIvarDecl::Private;
+  case eAccessProtected:
+    return clang::ObjCIvarDecl::Protected;
+  case eAccessPackage:
+    return clang::ObjCIvarDecl::Package;
+  }
+  return clang::ObjCIvarDecl::None;
+}
+
+// Tests
+
+bool TypeSystemClang::IsAggregateType(lldb::opaque_compiler_type_t type) {
+  clang::QualType qual_type(RemoveWrappingTypes(GetCanonicalQualType(type)));
+
+  const clang::Type::TypeClass type_class = qual_type->getTypeClass();
+  switch (type_class) {
+  case clang::Type::IncompleteArray:
+  case clang::Type::VariableArray:
+  case clang::Type::ConstantArray:
+  case clang::Type::ExtVector:
+  case clang::Type::Vector:
+  case clang::Type::Record:
+  case clang::Type::ObjCObject:
+  case clang::Type::ObjCInterface:
+    return true;
+  default:
+    break;
+  }
+  // The clang type does have a value
+  return false;
+}
+
+bool TypeSystemClang::IsAnonymousType(lldb::opaque_compiler_type_t type) {
+  clang::QualType qual_type(RemoveWrappingTypes(GetCanonicalQualType(type)));
+
+  const clang::Type::TypeClass type_class = qual_type->getTypeClass();
+  switch (type_class) {
+  case clang::Type::Record: {
+    if (const clang::RecordType *record_type =
+            llvm::dyn_cast_or_null<clang::RecordType>(
+                qual_type.getTypePtrOrNull())) {
+      if (const clang::RecordDecl *record_decl = record_type->getDecl()) {
+        return record_decl->isAnonymousStructOrUnion();
+      }
+    }
+    break;
+  }
+  default:
+    break;
+  }
+  // The clang type does have a value
+  return false;
+}
+
+bool TypeSystemClang::IsArrayType(lldb::opaque_compiler_type_t type,
+                                  CompilerType *element_type_ptr,
+                                  uint64_t *size, bool *is_incomplete) {
+  clang::QualType qual_type(RemoveWrappingTypes(GetCanonicalQualType(type)));
+
+  const clang::Type::TypeClass type_class = qual_type->getTypeClass();
+  switch (type_class) {
+  default:
+    break;
+
+  case clang::Type::ConstantArray:
+    if (element_type_ptr)
+      element_type_ptr->SetCompilerType(
+          this, llvm::cast<clang::ConstantArrayType>(qual_type)
+                    ->getElementType()
+                    .getAsOpaquePtr());
+    if (size)
+      *size = llvm::cast<clang::ConstantArrayType>(qual_type)
+                  ->getSize()
+                  .getLimitedValue(ULLONG_MAX);
+    if (is_incomplete)
+      *is_incomplete = false;
+    return true;
+
+  case clang::Type::IncompleteArray:
+    if (element_type_ptr)
+      element_type_ptr->SetCompilerType(
+          this, llvm::cast<clang::IncompleteArrayType>(qual_type)
+                    ->getElementType()
+                    .getAsOpaquePtr());
+    if (size)
+      *size = 0;
+    if (is_incomplete)
+      *is_incomplete = true;
+    return true;
+
+  case clang::Type::VariableArray:
+    if (element_type_ptr)
+      element_type_ptr->SetCompilerType(
+          this, llvm::cast<clang::VariableArrayType>(qual_type)
+                    ->getElementType()
+                    .getAsOpaquePtr());
+    if (size)
+      *size = 0;
+    if (is_incomplete)
+      *is_incomplete = false;
+    return true;
+
+  case clang::Type::DependentSizedArray:
+    if (element_type_ptr)
+      element_type_ptr->SetCompilerType(
+          this, llvm::cast<clang::DependentSizedArrayType>(qual_type)
+                    ->getElementType()
+                    .getAsOpaquePtr());
+    if (size)
+      *size = 0;
+    if (is_incomplete)
+      *is_incomplete = false;
+    return true;
+  }
+  if (element_type_ptr)
+    element_type_ptr->Clear();
+  if (size)
+    *size = 0;
+  if (is_incomplete)
+    *is_incomplete = false;
+  return false;
+}
+
+bool TypeSystemClang::IsVectorType(lldb::opaque_compiler_type_t type,
+                                   CompilerType *element_type, uint64_t *size) {
+  clang::QualType qual_type(GetCanonicalQualType(type));
+
+  const clang::Type::TypeClass type_class = qual_type->getTypeClass();
+  switch (type_class) {
+  case clang::Type::Vector: {
+    const clang::VectorType *vector_type =
+        qual_type->getAs<clang::VectorType>();
+    if (vector_type) {
+      if (size)
+        *size = vector_type->getNumElements();
+      if (element_type)
+        *element_type = GetType(vector_type->getElementType());
+    }
+    return true;
+  } break;
+  case clang::Type::ExtVector: {
+    const clang::ExtVectorType *ext_vector_type =
+        qual_type->getAs<clang::ExtVectorType>();
+    if (ext_vector_type) {
+      if (size)
+        *size = ext_vector_type->getNumElements();
+      if (element_type)
+        *element_type =
+            CompilerType(this, ext_vector_type->getElementType().getAsOpaquePtr());
+    }
+    return true;
+  }
+  default:
+    break;
+  }
+  return false;
+}
+
+bool TypeSystemClang::IsRuntimeGeneratedType(
+    lldb::opaque_compiler_type_t type) {
+  clang::DeclContext *decl_ctx = GetDeclContextForType(GetQualType(type));
+  if (!decl_ctx)
+    return false;
+
+  if (!llvm::isa<clang::ObjCInterfaceDecl>(decl_ctx))
+    return false;
+
+  clang::ObjCInterfaceDecl *result_iface_decl =
+      llvm::dyn_cast<clang::ObjCInterfaceDecl>(decl_ctx);
+
+  ClangASTMetadata *ast_metadata = GetMetadata(result_iface_decl);
+  if (!ast_metadata)
+    return false;
+  return (ast_metadata->GetISAPtr() != 0);
+}
+
+bool TypeSystemClang::IsCharType(lldb::opaque_compiler_type_t type) {
+  return GetQualType(type).getUnqualifiedType()->isCharType();
+}
+
+bool TypeSystemClang::IsCompleteType(lldb::opaque_compiler_type_t type) {
+  const bool allow_completion = false;
+  return GetCompleteQualType(&getASTContext(), GetQualType(type),
+                             allow_completion);
+}
+
+bool TypeSystemClang::IsConst(lldb::opaque_compiler_type_t type) {
+  return GetQualType(type).isConstQualified();
+}
+
+bool TypeSystemClang::IsCStringType(lldb::opaque_compiler_type_t type,
+                                    uint32_t &length) {
+  CompilerType pointee_or_element_clang_type;
+  length = 0;
+  Flags type_flags(GetTypeInfo(type, &pointee_or_element_clang_type));
+
+  if (!pointee_or_element_clang_type.IsValid())
+    return false;
+
+  if (type_flags.AnySet(eTypeIsArray | eTypeIsPointer)) {
+    if (pointee_or_element_clang_type.IsCharType()) {
+      if (type_flags.Test(eTypeIsArray)) {
+        // We know the size of the array and it could be a C string since it is
+        // an array of characters
+        length = llvm::cast<clang::ConstantArrayType>(
+                     GetCanonicalQualType(type).getTypePtr())
+                     ->getSize()
+                     .getLimitedValue();
+      }
+      return true;
+    }
+  }
+  return false;
+}
+
+bool TypeSystemClang::IsFunctionType(lldb::opaque_compiler_type_t type,
+                                     bool *is_variadic_ptr) {
+  if (type) {
+    clang::QualType qual_type = RemoveWrappingTypes(GetCanonicalQualType(type));
+
+    if (qual_type->isFunctionType()) {
+      if (is_variadic_ptr) {
+        const clang::FunctionProtoType *function_proto_type =
+            llvm::dyn_cast<clang::FunctionProtoType>(qual_type.getTypePtr());
+        if (function_proto_type)
+          *is_variadic_ptr = function_proto_type->isVariadic();
+        else
+          *is_variadic_ptr = false;
+      }
+      return true;
+    }
+
+    const clang::Type::TypeClass type_class = qual_type->getTypeClass();
+    switch (type_class) {
+    default:
+      break;
+    case clang::Type::LValueReference:
+    case clang::Type::RValueReference: {
+      const clang::ReferenceType *reference_type =
+          llvm::cast<clang::ReferenceType>(qual_type.getTypePtr());
+      if (reference_type)
+        return IsFunctionType(reference_type->getPointeeType().getAsOpaquePtr(),
+                              nullptr);
+    } break;
+    }
+  }
+  return false;
+}
+
+// Used to detect "Homogeneous Floating-point Aggregates"
+uint32_t
+TypeSystemClang::IsHomogeneousAggregate(lldb::opaque_compiler_type_t type,
+                                        CompilerType *base_type_ptr) {
+  if (!type)
+    return 0;
+
+  clang::QualType qual_type(RemoveWrappingTypes(GetCanonicalQualType(type)));
+  const clang::Type::TypeClass type_class = qual_type->getTypeClass();
+  switch (type_class) {
+  case clang::Type::Record:
+    if (GetCompleteType(type)) {
+      const clang::CXXRecordDecl *cxx_record_decl =
+          qual_type->getAsCXXRecordDecl();
+      if (cxx_record_decl) {
+        if (cxx_record_decl->getNumBases() || cxx_record_decl->isDynamicClass())
+          return 0;
+      }
+      const clang::RecordType *record_type =
+          llvm::cast<clang::RecordType>(qual_type.getTypePtr());
+      if (record_type) {
+        const clang::RecordDecl *record_decl = record_type->getDecl();
+        if (record_decl) {
+          // We are looking for a structure that contains only floating point
+          // types
+          clang::RecordDecl::field_iterator field_pos,
+              field_end = record_decl->field_end();
+          uint32_t num_fields = 0;
+          bool is_hva = false;
+          bool is_hfa = false;
+          clang::QualType base_qual_type;
+          uint64_t base_bitwidth = 0;
+          for (field_pos = record_decl->field_begin(); field_pos != field_end;
+               ++field_pos) {
+            clang::QualType field_qual_type = field_pos->getType();
+            uint64_t field_bitwidth = getASTContext().getTypeSize(qual_type);
+            if (field_qual_type->isFloatingType()) {
+              if (field_qual_type->isComplexType())
+                return 0;
+              else {
+                if (num_fields == 0)
+                  base_qual_type = field_qual_type;
+                else {
+                  if (is_hva)
+                    return 0;
+                  is_hfa = true;
+                  if (field_qual_type.getTypePtr() !=
+                      base_qual_type.getTypePtr())
+                    return 0;
+                }
+              }
+            } else if (field_qual_type->isVectorType() ||
+                       field_qual_type->isExtVectorType()) {
+              if (num_fields == 0) {
+                base_qual_type = field_qual_type;
+                base_bitwidth = field_bitwidth;
+              } else {
+                if (is_hfa)
+                  return 0;
+                is_hva = true;
+                if (base_bitwidth != field_bitwidth)
+                  return 0;
+                if (field_qual_type.getTypePtr() != base_qual_type.getTypePtr())
+                  return 0;
+              }
+            } else
+              return 0;
+            ++num_fields;
+          }
+          if (base_type_ptr)
+            *base_type_ptr = CompilerType(this, base_qual_type.getAsOpaquePtr());
+          return num_fields;
+        }
+      }
+    }
+    break;
+
+  default:
+    break;
+  }
+  return 0;
+}
+
+size_t TypeSystemClang::GetNumberOfFunctionArguments(
+    lldb::opaque_compiler_type_t type) {
+  if (type) {
+    clang::QualType qual_type(GetCanonicalQualType(type));
+    const clang::FunctionProtoType *func =
+        llvm::dyn_cast<clang::FunctionProtoType>(qual_type.getTypePtr());
+    if (func)
+      return func->getNumParams();
+  }
+  return 0;
+}
+
+CompilerType
+TypeSystemClang::GetFunctionArgumentAtIndex(lldb::opaque_compiler_type_t type,
+                                            const size_t index) {
+  if (type) {
+    clang::QualType qual_type(GetQualType(type));
+    const clang::FunctionProtoType *func =
+        llvm::dyn_cast<clang::FunctionProtoType>(qual_type.getTypePtr());
+    if (func) {
+      if (index < func->getNumParams())
+        return CompilerType(this, func->getParamType(index).getAsOpaquePtr());
+    }
+  }
+  return CompilerType();
+}
+
+bool TypeSystemClang::IsFunctionPointerType(lldb::opaque_compiler_type_t type) {
+  if (type) {
+    clang::QualType qual_type = RemoveWrappingTypes(GetCanonicalQualType(type));
+
+    if (qual_type->isFunctionPointerType())
+      return true;
+
+    const clang::Type::TypeClass type_class = qual_type->getTypeClass();
+    switch (type_class) {
+    default:
+      break;
+
+    case clang::Type::LValueReference:
+    case clang::Type::RValueReference: {
+      const clang::ReferenceType *reference_type =
+          llvm::cast<clang::ReferenceType>(qual_type.getTypePtr());
+      if (reference_type)
+        return IsFunctionPointerType(
+            reference_type->getPointeeType().getAsOpaquePtr());
+    } break;
+    }
+  }
+  return false;
+}
+
+bool TypeSystemClang::IsBlockPointerType(
+    lldb::opaque_compiler_type_t type,
+    CompilerType *function_pointer_type_ptr) {
+  if (type) {
+    clang::QualType qual_type = RemoveWrappingTypes(GetCanonicalQualType(type));
+
+    if (qual_type->isBlockPointerType()) {
+      if (function_pointer_type_ptr) {
+        const clang::BlockPointerType *block_pointer_type =
+            qual_type->getAs<clang::BlockPointerType>();
+        QualType pointee_type = block_pointer_type->getPointeeType();
+        QualType function_pointer_type = m_ast_up->getPointerType(pointee_type);
+        *function_pointer_type_ptr =
+            CompilerType(this, function_pointer_type.getAsOpaquePtr());
+      }
+      return true;
+    }
+
+    const clang::Type::TypeClass type_class = qual_type->getTypeClass();
+    switch (type_class) {
+    default:
+      break;
+
+    case clang::Type::LValueReference:
+    case clang::Type::RValueReference: {
+      const clang::ReferenceType *reference_type =
+          llvm::cast<clang::ReferenceType>(qual_type.getTypePtr());
+      if (reference_type)
+        return IsBlockPointerType(
+            reference_type->getPointeeType().getAsOpaquePtr(),
+            function_pointer_type_ptr);
+    } break;
+    }
+  }
+  return false;
+}
+
+bool TypeSystemClang::IsIntegerType(lldb::opaque_compiler_type_t type,
+                                    bool &is_signed) {
+  if (!type)
+    return false;
+
+  clang::QualType qual_type(GetCanonicalQualType(type));
+  const clang::BuiltinType *builtin_type =
+      llvm::dyn_cast<clang::BuiltinType>(qual_type->getCanonicalTypeInternal());
+
+  if (builtin_type) {
+    if (builtin_type->isInteger()) {
+      is_signed = builtin_type->isSignedInteger();
+      return true;
+    }
+  }
+
+  return false;
+}
+
+bool TypeSystemClang::IsEnumerationType(lldb::opaque_compiler_type_t type,
+                                        bool &is_signed) {
+  if (type) {
+    const clang::EnumType *enum_type = llvm::dyn_cast<clang::EnumType>(
+        GetCanonicalQualType(type)->getCanonicalTypeInternal());
+
+    if (enum_type) {
+      IsIntegerType(enum_type->getDecl()->getIntegerType().getAsOpaquePtr(),
+                    is_signed);
+      return true;
+    }
+  }
+
+  return false;
+}
+
+bool TypeSystemClang::IsPointerType(lldb::opaque_compiler_type_t type,
+                                    CompilerType *pointee_type) {
+  if (type) {
+    clang::QualType qual_type = RemoveWrappingTypes(GetCanonicalQualType(type));
+    const clang::Type::TypeClass type_class = qual_type->getTypeClass();
+    switch (type_class) {
+    case clang::Type::Builtin:
+      switch (llvm::cast<clang::BuiltinType>(qual_type)->getKind()) {
+      default:
+        break;
+      case clang::BuiltinType::ObjCId:
+      case clang::BuiltinType::ObjCClass:
+        return true;
+      }
+      return false;
+    case clang::Type::ObjCObjectPointer:
+      if (pointee_type)
+        pointee_type->SetCompilerType(
+            this, llvm::cast<clang::ObjCObjectPointerType>(qual_type)
+                      ->getPointeeType()
+                      .getAsOpaquePtr());
+      return true;
+    case clang::Type::BlockPointer:
+      if (pointee_type)
+        pointee_type->SetCompilerType(
+            this, llvm::cast<clang::BlockPointerType>(qual_type)
+                      ->getPointeeType()
+                      .getAsOpaquePtr());
+      return true;
+    case clang::Type::Pointer:
+      if (pointee_type)
+        pointee_type->SetCompilerType(this,
+                                      llvm::cast<clang::PointerType>(qual_type)
+                                          ->getPointeeType()
+                                          .getAsOpaquePtr());
+      return true;
+    case clang::Type::MemberPointer:
+      if (pointee_type)
+        pointee_type->SetCompilerType(
+            this, llvm::cast<clang::MemberPointerType>(qual_type)
+                      ->getPointeeType()
+                      .getAsOpaquePtr());
+      return true;
+    default:
+      break;
+    }
+  }
+  if (pointee_type)
+    pointee_type->Clear();
+  return false;
+}
+
+bool TypeSystemClang::IsPointerOrReferenceType(
+    lldb::opaque_compiler_type_t type, CompilerType *pointee_type) {
+  if (type) {
+    clang::QualType qual_type = RemoveWrappingTypes(GetCanonicalQualType(type));
+    const clang::Type::TypeClass type_class = qual_type->getTypeClass();
+    switch (type_class) {
+    case clang::Type::Builtin:
+      switch (llvm::cast<clang::BuiltinType>(qual_type)->getKind()) {
+      default:
+        break;
+      case clang::BuiltinType::ObjCId:
+      case clang::BuiltinType::ObjCClass:
+        return true;
+      }
+      return false;
+    case clang::Type::ObjCObjectPointer:
+      if (pointee_type)
+        pointee_type->SetCompilerType(
+            this, llvm::cast<clang::ObjCObjectPointerType>(qual_type)
+                                 ->getPointeeType().getAsOpaquePtr());
+      return true;
+    case clang::Type::BlockPointer:
+      if (pointee_type)
+        pointee_type->SetCompilerType(
+            this, llvm::cast<clang::BlockPointerType>(qual_type)
+                      ->getPointeeType()
+                      .getAsOpaquePtr());
+      return true;
+    case clang::Type::Pointer:
+      if (pointee_type)
+        pointee_type->SetCompilerType(this,
+                                      llvm::cast<clang::PointerType>(qual_type)
+                                          ->getPointeeType()
+                                          .getAsOpaquePtr());
+      return true;
+    case clang::Type::MemberPointer:
+      if (pointee_type)
+        pointee_type->SetCompilerType(
+            this, llvm::cast<clang::MemberPointerType>(qual_type)
+                      ->getPointeeType()
+                      .getAsOpaquePtr());
+      return true;
+    case clang::Type::LValueReference:
+      if (pointee_type)
+        pointee_type->SetCompilerType(
+            this, llvm::cast<clang::LValueReferenceType>(qual_type)
+                      ->desugar()
+                      .getAsOpaquePtr());
+      return true;
+    case clang::Type::RValueReference:
+      if (pointee_type)
+        pointee_type->SetCompilerType(
+            this, llvm::cast<clang::RValueReferenceType>(qual_type)
+                      ->desugar()
+                      .getAsOpaquePtr());
+      return true;
+    default:
+      break;
+    }
+  }
+  if (pointee_type)
+    pointee_type->Clear();
+  return false;
+}
+
+bool TypeSystemClang::IsReferenceType(lldb::opaque_compiler_type_t type,
+                                      CompilerType *pointee_type,
+                                      bool *is_rvalue) {
+  if (type) {
+    clang::QualType qual_type = RemoveWrappingTypes(GetCanonicalQualType(type));
+    const clang::Type::TypeClass type_class = qual_type->getTypeClass();
+
+    switch (type_class) {
+    case clang::Type::LValueReference:
+      if (pointee_type)
+        pointee_type->SetCompilerType(
+            this, llvm::cast<clang::LValueReferenceType>(qual_type)
+                      ->desugar()
+                      .getAsOpaquePtr());
+      if (is_rvalue)
+        *is_rvalue = false;
+      return true;
+    case clang::Type::RValueReference:
+      if (pointee_type)
+        pointee_type->SetCompilerType(
+            this, llvm::cast<clang::RValueReferenceType>(qual_type)
+                      ->desugar()
+                      .getAsOpaquePtr());
+      if (is_rvalue)
+        *is_rvalue = true;
+      return true;
+
+    default:
+      break;
+    }
+  }
+  if (pointee_type)
+    pointee_type->Clear();
+  return false;
+}
+
+bool TypeSystemClang::IsFloatingPointType(lldb::opaque_compiler_type_t type,
+                                          uint32_t &count, bool &is_complex) {
+  if (type) {
+    clang::QualType qual_type(GetCanonicalQualType(type));
+
+    if (const clang::BuiltinType *BT = llvm::dyn_cast<clang::BuiltinType>(
+            qual_type->getCanonicalTypeInternal())) {
+      clang::BuiltinType::Kind kind = BT->getKind();
+      if (kind >= clang::BuiltinType::Float &&
+          kind <= clang::BuiltinType::LongDouble) {
+        count = 1;
+        is_complex = false;
+        return true;
+      }
+    } else if (const clang::ComplexType *CT =
+                   llvm::dyn_cast<clang::ComplexType>(
+                       qual_type->getCanonicalTypeInternal())) {
+      if (IsFloatingPointType(CT->getElementType().getAsOpaquePtr(), count,
+                              is_complex)) {
+        count = 2;
+        is_complex = true;
+        return true;
+      }
+    } else if (const clang::VectorType *VT = llvm::dyn_cast<clang::VectorType>(
+                   qual_type->getCanonicalTypeInternal())) {
+      if (IsFloatingPointType(VT->getElementType().getAsOpaquePtr(), count,
+                              is_complex)) {
+        count = VT->getNumElements();
+        is_complex = false;
+        return true;
+      }
+    }
+  }
+  count = 0;
+  is_complex = false;
+  return false;
+}
+
+bool TypeSystemClang::IsDefined(lldb::opaque_compiler_type_t type) {
+  if (!type)
+    return false;
+
+  clang::QualType qual_type(GetQualType(type));
+  const clang::TagType *tag_type =
+      llvm::dyn_cast<clang::TagType>(qual_type.getTypePtr());
+  if (tag_type) {
+    clang::TagDecl *tag_decl = tag_type->getDecl();
+    if (tag_decl)
+      return tag_decl->isCompleteDefinition();
+    return false;
+  } else {
+    const clang::ObjCObjectType *objc_class_type =
+        llvm::dyn_cast<clang::ObjCObjectType>(qual_type);
+    if (objc_class_type) {
+      clang::ObjCInterfaceDecl *class_interface_decl =
+          objc_class_type->getInterface();
+      if (class_interface_decl)
+        return class_interface_decl->getDefinition() != nullptr;
+      return false;
+    }
+  }
+  return true;
+}
+
+bool TypeSystemClang::IsObjCClassType(const CompilerType &type) {
+  if (ClangUtil::IsClangType(type)) {
+    clang::QualType qual_type(ClangUtil::GetCanonicalQualType(type));
+
+    const clang::ObjCObjectPointerType *obj_pointer_type =
+        llvm::dyn_cast<clang::ObjCObjectPointerType>(qual_type);
+
+    if (obj_pointer_type)
+      return obj_pointer_type->isObjCClassType();
+  }
+  return false;
+}
+
+bool TypeSystemClang::IsObjCObjectOrInterfaceType(const CompilerType &type) {
+  if (ClangUtil::IsClangType(type))
+    return ClangUtil::GetCanonicalQualType(type)->isObjCObjectOrInterfaceType();
+  return false;
+}
+
+bool TypeSystemClang::IsClassType(lldb::opaque_compiler_type_t type) {
+  if (!type)
+    return false;
+  clang::QualType qual_type(GetCanonicalQualType(type));
+  const clang::Type::TypeClass type_class = qual_type->getTypeClass();
+  return (type_class == clang::Type::Record);
+}
+
+bool TypeSystemClang::IsEnumType(lldb::opaque_compiler_type_t type) {
+  if (!type)
+    return false;
+  clang::QualType qual_type(GetCanonicalQualType(type));
+  const clang::Type::TypeClass type_class = qual_type->getTypeClass();
+  return (type_class == clang::Type::Enum);
+}
+
+bool TypeSystemClang::IsPolymorphicClass(lldb::opaque_compiler_type_t type) {
+  if (type) {
+    clang::QualType qual_type(GetCanonicalQualType(type));
+    const clang::Type::TypeClass type_class = qual_type->getTypeClass();
+    switch (type_class) {
+    case clang::Type::Record:
+      if (GetCompleteType(type)) {
+        const clang::RecordType *record_type =
+            llvm::cast<clang::RecordType>(qual_type.getTypePtr());
+        const clang::RecordDecl *record_decl = record_type->getDecl();
+        if (record_decl) {
+          const clang::CXXRecordDecl *cxx_record_decl =
+              llvm::dyn_cast<clang::CXXRecordDecl>(record_decl);
+          if (cxx_record_decl)
+            return cxx_record_decl->isPolymorphic();
+        }
+      }
+      break;
+
+    default:
+      break;
+    }
+  }
+  return false;
+}
+
+bool TypeSystemClang::IsPossibleDynamicType(lldb::opaque_compiler_type_t type,
+                                            CompilerType *dynamic_pointee_type,
+                                            bool check_cplusplus,
+                                            bool check_objc) {
+  clang::QualType pointee_qual_type;
+  if (type) {
+    clang::QualType qual_type = RemoveWrappingTypes(GetCanonicalQualType(type));
+    bool success = false;
+    const clang::Type::TypeClass type_class = qual_type->getTypeClass();
+    switch (type_class) {
+    case clang::Type::Builtin:
+      if (check_objc &&
+          llvm::cast<clang::BuiltinType>(qual_type)->getKind() ==
+              clang::BuiltinType::ObjCId) {
+        if (dynamic_pointee_type)
+          dynamic_pointee_type->SetCompilerType(this, type);
+        return true;
+      }
+      break;
+
+    case clang::Type::ObjCObjectPointer:
+      if (check_objc) {
+        if (auto objc_pointee_type =
+                qual_type->getPointeeType().getTypePtrOrNull()) {
+          if (auto objc_object_type =
+                  llvm::dyn_cast_or_null<clang::ObjCObjectType>(
+                      objc_pointee_type)) {
+            if (objc_object_type->isObjCClass())
+              return false;
+          }
+        }
+        if (dynamic_pointee_type)
+          dynamic_pointee_type->SetCompilerType(
+              this, llvm::cast<clang::ObjCObjectPointerType>(qual_type)
+                        ->getPointeeType()
+                        .getAsOpaquePtr());
+        return true;
+      }
+      break;
+
+    case clang::Type::Pointer:
+      pointee_qual_type =
+          llvm::cast<clang::PointerType>(qual_type)->getPointeeType();
+      success = true;
+      break;
+
+    case clang::Type::LValueReference:
+    case clang::Type::RValueReference:
+      pointee_qual_type =
+          llvm::cast<clang::ReferenceType>(qual_type)->getPointeeType();
+      success = true;
+      break;
+
+    default:
+      break;
+    }
+
+    if (success) {
+      // Check to make sure what we are pointing too is a possible dynamic C++
+      // type We currently accept any "void *" (in case we have a class that
+      // has been watered down to an opaque pointer) and virtual C++ classes.
+      const clang::Type::TypeClass pointee_type_class =
+          pointee_qual_type.getCanonicalType()->getTypeClass();
+      switch (pointee_type_class) {
+      case clang::Type::Builtin:
+        switch (llvm::cast<clang::BuiltinType>(pointee_qual_type)->getKind()) {
+        case clang::BuiltinType::UnknownAny:
+        case clang::BuiltinType::Void:
+          if (dynamic_pointee_type)
+            dynamic_pointee_type->SetCompilerType(
+                this, pointee_qual_type.getAsOpaquePtr());
+          return true;
+        default:
+          break;
+        }
+        break;
+
+      case clang::Type::Record:
+        if (check_cplusplus) {
+          clang::CXXRecordDecl *cxx_record_decl =
+              pointee_qual_type->getAsCXXRecordDecl();
+          if (cxx_record_decl) {
+            bool is_complete = cxx_record_decl->isCompleteDefinition();
+
+            if (is_complete)
+              success = cxx_record_decl->isDynamicClass();
+            else {
+              ClangASTMetadata *metadata = GetMetadata(cxx_record_decl);
+              if (metadata)
+                success = metadata->GetIsDynamicCXXType();
+              else {
+                is_complete = GetType(pointee_qual_type).GetCompleteType();
+                if (is_complete)
+                  success = cxx_record_decl->isDynamicClass();
+                else
+                  success = false;
+              }
+            }
+
+            if (success) {
+              if (dynamic_pointee_type)
+                dynamic_pointee_type->SetCompilerType(
+                    this, pointee_qual_type.getAsOpaquePtr());
+              return true;
+            }
+          }
+        }
+        break;
+
+      case clang::Type::ObjCObject:
+      case clang::Type::ObjCInterface:
+        if (check_objc) {
+          if (dynamic_pointee_type)
+            dynamic_pointee_type->SetCompilerType(
+                this, pointee_qual_type.getAsOpaquePtr());
+          return true;
+        }
+        break;
+
+      default:
+        break;
+      }
+    }
+  }
+  if (dynamic_pointee_type)
+    dynamic_pointee_type->Clear();
+  return false;
+}
+
+bool TypeSystemClang::IsScalarType(lldb::opaque_compiler_type_t type) {
+  if (!type)
+    return false;
+
+  return (GetTypeInfo(type, nullptr) & eTypeIsScalar) != 0;
+}
+
+bool TypeSystemClang::IsTypedefType(lldb::opaque_compiler_type_t type) {
+  if (!type)
+    return false;
+  return GetQualType(type)->getTypeClass() == clang::Type::Typedef;
+}
+
+bool TypeSystemClang::IsVoidType(lldb::opaque_compiler_type_t type) {
+  if (!type)
+    return false;
+  return GetCanonicalQualType(type)->isVoidType();
+}
+
+bool TypeSystemClang::CanPassInRegisters(const CompilerType &type) {
+  if (auto *record_decl =
+      TypeSystemClang::GetAsRecordDecl(type)) {
+    return record_decl->canPassInRegisters();
+  }
+  return false;
+}
+
+bool TypeSystemClang::SupportsLanguage(lldb::LanguageType language) {
+  return TypeSystemClangSupportsLanguage(language);
+}
+
+Optional<std::string>
+TypeSystemClang::GetCXXClassName(const CompilerType &type) {
+  if (!type)
+    return llvm::None;
+
+  clang::QualType qual_type(ClangUtil::GetCanonicalQualType(type));
+  if (qual_type.isNull())
+    return llvm::None;
+
+  clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl();
+  if (!cxx_record_decl)
+    return llvm::None;
+
+  return std::string(cxx_record_decl->getIdentifier()->getNameStart());
+}
+
+bool TypeSystemClang::IsCXXClassType(const CompilerType &type) {
+  if (!type)
+    return false;
+
+  clang::QualType qual_type(ClangUtil::GetCanonicalQualType(type));
+  return !qual_type.isNull() && qual_type->getAsCXXRecordDecl() != nullptr;
+}
+
+bool TypeSystemClang::IsBeingDefined(lldb::opaque_compiler_type_t type) {
+  if (!type)
+    return false;
+  clang::QualType qual_type(GetCanonicalQualType(type));
+  const clang::TagType *tag_type = llvm::dyn_cast<clang::TagType>(qual_type);
+  if (tag_type)
+    return tag_type->isBeingDefined();
+  return false;
+}
+
+bool TypeSystemClang::IsObjCObjectPointerType(const CompilerType &type,
+                                              CompilerType *class_type_ptr) {
+  if (!ClangUtil::IsClangType(type))
+    return false;
+
+  clang::QualType qual_type(ClangUtil::GetCanonicalQualType(type));
+
+  if (!qual_type.isNull() && qual_type->isObjCObjectPointerType()) {
+    if (class_type_ptr) {
+      if (!qual_type->isObjCClassType() && !qual_type->isObjCIdType()) {
+        const clang::ObjCObjectPointerType *obj_pointer_type =
+            llvm::dyn_cast<clang::ObjCObjectPointerType>(qual_type);
+        if (obj_pointer_type == nullptr)
+          class_type_ptr->Clear();
+        else
+          class_type_ptr->SetCompilerType(
+              type.GetTypeSystem(),
+              clang::QualType(obj_pointer_type->getInterfaceType(), 0)
+                  .getAsOpaquePtr());
+      }
+    }
+    return true;
+  }
+  if (class_type_ptr)
+    class_type_ptr->Clear();
+  return false;
+}
+
+// Type Completion
+
+bool TypeSystemClang::GetCompleteType(lldb::opaque_compiler_type_t type) {
+  if (!type)
+    return false;
+  const bool allow_completion = true;
+  return GetCompleteQualType(&getASTContext(), GetQualType(type),
+                             allow_completion);
+}
+
+ConstString TypeSystemClang::GetTypeName(lldb::opaque_compiler_type_t type) {
+  std::string type_name;
+  if (type) {
+    clang::PrintingPolicy printing_policy(getASTContext().getPrintingPolicy());
+    clang::QualType qual_type(GetQualType(type));
+    printing_policy.SuppressTagKeyword = true;
+    const clang::TypedefType *typedef_type =
+        qual_type->getAs<clang::TypedefType>();
+    if (typedef_type) {
+      const clang::TypedefNameDecl *typedef_decl = typedef_type->getDecl();
+      type_name = typedef_decl->getQualifiedNameAsString();
+    } else {
+      type_name = qual_type.getAsString(printing_policy);
+    }
+  }
+  return ConstString(type_name);
+}
+
+uint32_t
+TypeSystemClang::GetTypeInfo(lldb::opaque_compiler_type_t type,
+                             CompilerType *pointee_or_element_clang_type) {
+  if (!type)
+    return 0;
+
+  if (pointee_or_element_clang_type)
+    pointee_or_element_clang_type->Clear();
+
+  clang::QualType qual_type =
+      RemoveWrappingTypes(GetQualType(type), {clang::Type::Typedef});
+
+  const clang::Type::TypeClass type_class = qual_type->getTypeClass();
+  switch (type_class) {
+  case clang::Type::Attributed:
+    return GetTypeInfo(
+        qual_type->getAs<clang::AttributedType>()
+            ->getModifiedType().getAsOpaquePtr(),
+        pointee_or_element_clang_type);
+  case clang::Type::Builtin: {
+    const clang::BuiltinType *builtin_type = llvm::dyn_cast<clang::BuiltinType>(
+        qual_type->getCanonicalTypeInternal());
+
+    uint32_t builtin_type_flags = eTypeIsBuiltIn | eTypeHasValue;
+    switch (builtin_type->getKind()) {
+    case clang::BuiltinType::ObjCId:
+    case clang::BuiltinType::ObjCClass:
+      if (pointee_or_element_clang_type)
+        pointee_or_element_clang_type->SetCompilerType(
+            this, getASTContext().ObjCBuiltinClassTy.getAsOpaquePtr());
+      builtin_type_flags |= eTypeIsPointer | eTypeIsObjC;
+      break;
+
+    case clang::BuiltinType::ObjCSel:
+      if (pointee_or_element_clang_type)
+        pointee_or_element_clang_type->SetCompilerType(
+            this, getASTContext().CharTy.getAsOpaquePtr());
+      builtin_type_flags |= eTypeIsPointer | eTypeIsObjC;
+      break;
+
+    case clang::BuiltinType::Bool:
+    case clang::BuiltinType::Char_U:
+    case clang::BuiltinType::UChar:
+    case clang::BuiltinType::WChar_U:
+    case clang::BuiltinType::Char16:
+    case clang::BuiltinType::Char32:
+    case clang::BuiltinType::UShort:
+    case clang::BuiltinType::UInt:
+    case clang::BuiltinType::ULong:
+    case clang::BuiltinType::ULongLong:
+    case clang::BuiltinType::UInt128:
+    case clang::BuiltinType::Char_S:
+    case clang::BuiltinType::SChar:
+    case clang::BuiltinType::WChar_S:
+    case clang::BuiltinType::Short:
+    case clang::BuiltinType::Int:
+    case clang::BuiltinType::Long:
+    case clang::BuiltinType::LongLong:
+    case clang::BuiltinType::Int128:
+    case clang::BuiltinType::Float:
+    case clang::BuiltinType::Double:
+    case clang::BuiltinType::LongDouble:
+      builtin_type_flags |= eTypeIsScalar;
+      if (builtin_type->isInteger()) {
+        builtin_type_flags |= eTypeIsInteger;
+        if (builtin_type->isSignedInteger())
+          builtin_type_flags |= eTypeIsSigned;
+      } else if (builtin_type->isFloatingPoint())
+        builtin_type_flags |= eTypeIsFloat;
+      break;
+    default:
+      break;
+    }
+    return builtin_type_flags;
+  }
+
+  case clang::Type::BlockPointer:
+    if (pointee_or_element_clang_type)
+      pointee_or_element_clang_type->SetCompilerType(
+          this, qual_type->getPointeeType().getAsOpaquePtr());
+    return eTypeIsPointer | eTypeHasChildren | eTypeIsBlock;
+
+  case clang::Type::Complex: {
+    uint32_t complex_type_flags =
+        eTypeIsBuiltIn | eTypeHasValue | eTypeIsComplex;
+    const clang::ComplexType *complex_type = llvm::dyn_cast<clang::ComplexType>(
+        qual_type->getCanonicalTypeInternal());
+    if (complex_type) {
+      clang::QualType complex_element_type(complex_type->getElementType());
+      if (complex_element_type->isIntegerType())
+        complex_type_flags |= eTypeIsFloat;
+      else if (complex_element_type->isFloatingType())
+        complex_type_flags |= eTypeIsInteger;
+    }
+    return complex_type_flags;
+  } break;
+
+  case clang::Type::ConstantArray:
+  case clang::Type::DependentSizedArray:
+  case clang::Type::IncompleteArray:
+  case clang::Type::VariableArray:
+    if (pointee_or_element_clang_type)
+      pointee_or_element_clang_type->SetCompilerType(
+          this, llvm::cast<clang::ArrayType>(qual_type.getTypePtr())
+                    ->getElementType()
+                    .getAsOpaquePtr());
+    return eTypeHasChildren | eTypeIsArray;
+
+  case clang::Type::DependentName:
+    return 0;
+  case clang::Type::DependentSizedExtVector:
+    return eTypeHasChildren | eTypeIsVector;
+  case clang::Type::DependentTemplateSpecialization:
+    return eTypeIsTemplate;
+
+  case clang::Type::Enum:
+    if (pointee_or_element_clang_type)
+      pointee_or_element_clang_type->SetCompilerType(
+          this, llvm::cast<clang::EnumType>(qual_type)
+                    ->getDecl()
+                    ->getIntegerType()
+                    .getAsOpaquePtr());
+    return eTypeIsEnumeration | eTypeHasValue;
+
+  case clang::Type::FunctionProto:
+    return eTypeIsFuncPrototype | eTypeHasValue;
+  case clang::Type::FunctionNoProto:
+    return eTypeIsFuncPrototype | eTypeHasValue;
+  case clang::Type::InjectedClassName:
+    return 0;
+
+  case clang::Type::LValueReference:
+  case clang::Type::RValueReference:
+    if (pointee_or_element_clang_type)
+      pointee_or_element_clang_type->SetCompilerType(
+          this, llvm::cast<clang::ReferenceType>(qual_type.getTypePtr())
+                    ->getPointeeType()
+                    .getAsOpaquePtr());
+    return eTypeHasChildren | eTypeIsReference | eTypeHasValue;
+
+  case clang::Type::MemberPointer:
+    return eTypeIsPointer | eTypeIsMember | eTypeHasValue;
+
+  case clang::Type::ObjCObjectPointer:
+    if (pointee_or_element_clang_type)
+      pointee_or_element_clang_type->SetCompilerType(
+          this, qual_type->getPointeeType().getAsOpaquePtr());
+    return eTypeHasChildren | eTypeIsObjC | eTypeIsClass | eTypeIsPointer |
+           eTypeHasValue;
+
+  case clang::Type::ObjCObject:
+    return eTypeHasChildren | eTypeIsObjC | eTypeIsClass;
+  case clang::Type::ObjCInterface:
+    return eTypeHasChildren | eTypeIsObjC | eTypeIsClass;
+
+  case clang::Type::Pointer:
+    if (pointee_or_element_clang_type)
+      pointee_or_element_clang_type->SetCompilerType(
+          this, qual_type->getPointeeType().getAsOpaquePtr());
+    return eTypeHasChildren | eTypeIsPointer | eTypeHasValue;
+
+  case clang::Type::Record:
+    if (qual_type->getAsCXXRecordDecl())
+      return eTypeHasChildren | eTypeIsClass | eTypeIsCPlusPlus;
+    else
+      return eTypeHasChildren | eTypeIsStructUnion;
+    break;
+  case clang::Type::SubstTemplateTypeParm:
+    return eTypeIsTemplate;
+  case clang::Type::TemplateTypeParm:
+    return eTypeIsTemplate;
+  case clang::Type::TemplateSpecialization:
+    return eTypeIsTemplate;
+
+  case clang::Type::Typedef:
+    return eTypeIsTypedef | GetType(llvm::cast<clang::TypedefType>(qual_type)
+                                        ->getDecl()
+                                        ->getUnderlyingType())
+                                .GetTypeInfo(pointee_or_element_clang_type);
+  case clang::Type::UnresolvedUsing:
+    return 0;
+
+  case clang::Type::ExtVector:
+  case clang::Type::Vector: {
+    uint32_t vector_type_flags = eTypeHasChildren | eTypeIsVector;
+    const clang::VectorType *vector_type = llvm::dyn_cast<clang::VectorType>(
+        qual_type->getCanonicalTypeInternal());
+    if (vector_type) {
+      if (vector_type->isIntegerType())
+        vector_type_flags |= eTypeIsFloat;
+      else if (vector_type->isFloatingType())
+        vector_type_flags |= eTypeIsInteger;
+    }
+    return vector_type_flags;
+  }
+  default:
+    return 0;
+  }
+  return 0;
+}
+
+lldb::LanguageType
+TypeSystemClang::GetMinimumLanguage(lldb::opaque_compiler_type_t type) {
+  if (!type)
+    return lldb::eLanguageTypeC;
+
+  // If the type is a reference, then resolve it to what it refers to first:
+  clang::QualType qual_type(GetCanonicalQualType(type).getNonReferenceType());
+  if (qual_type->isAnyPointerType()) {
+    if (qual_type->isObjCObjectPointerType())
+      return lldb::eLanguageTypeObjC;
+    if (qual_type->getPointeeCXXRecordDecl())
+      return lldb::eLanguageTypeC_plus_plus;
+
+    clang::QualType pointee_type(qual_type->getPointeeType());
+    if (pointee_type->getPointeeCXXRecordDecl())
+      return lldb::eLanguageTypeC_plus_plus;
+    if (pointee_type->isObjCObjectOrInterfaceType())
+      return lldb::eLanguageTypeObjC;
+    if (pointee_type->isObjCClassType())
+      return lldb::eLanguageTypeObjC;
+    if (pointee_type.getTypePtr() ==
+        getASTContext().ObjCBuiltinIdTy.getTypePtr())
+      return lldb::eLanguageTypeObjC;
+  } else {
+    if (qual_type->isObjCObjectOrInterfaceType())
+      return lldb::eLanguageTypeObjC;
+    if (qual_type->getAsCXXRecordDecl())
+      return lldb::eLanguageTypeC_plus_plus;
+    switch (qual_type->getTypeClass()) {
+    default:
+      break;
+    case clang::Type::Builtin:
+      switch (llvm::cast<clang::BuiltinType>(qual_type)->getKind()) {
+      default:
+      case clang::BuiltinType::Void:
+      case clang::BuiltinType::Bool:
+      case clang::BuiltinType::Char_U:
+      case clang::BuiltinType::UChar:
+      case clang::BuiltinType::WChar_U:
+      case clang::BuiltinType::Char16:
+      case clang::BuiltinType::Char32:
+      case clang::BuiltinType::UShort:
+      case clang::BuiltinType::UInt:
+      case clang::BuiltinType::ULong:
+      case clang::BuiltinType::ULongLong:
+      case clang::BuiltinType::UInt128:
+      case clang::BuiltinType::Char_S:
+      case clang::BuiltinType::SChar:
+      case clang::BuiltinType::WChar_S:
+      case clang::BuiltinType::Short:
+      case clang::BuiltinType::Int:
+      case clang::BuiltinType::Long:
+      case clang::BuiltinType::LongLong:
+      case clang::BuiltinType::Int128:
+      case clang::BuiltinType::Float:
+      case clang::BuiltinType::Double:
+      case clang::BuiltinType::LongDouble:
+        break;
+
+      case clang::BuiltinType::NullPtr:
+        return eLanguageTypeC_plus_plus;
+
+      case clang::BuiltinType::ObjCId:
+      case clang::BuiltinType::ObjCClass:
+      case clang::BuiltinType::ObjCSel:
+        return eLanguageTypeObjC;
+
+      case clang::BuiltinType::Dependent:
+      case clang::BuiltinType::Overload:
+      case clang::BuiltinType::BoundMember:
+      case clang::BuiltinType::UnknownAny:
+        break;
+      }
+      break;
+    case clang::Type::Typedef:
+      return GetType(llvm::cast<clang::TypedefType>(qual_type)
+                         ->getDecl()
+                         ->getUnderlyingType())
+          .GetMinimumLanguage();
+    }
+  }
+  return lldb::eLanguageTypeC;
+}
+
+lldb::TypeClass
+TypeSystemClang::GetTypeClass(lldb::opaque_compiler_type_t type) {
+  if (!type)
+    return lldb::eTypeClassInvalid;
+
+  clang::QualType qual_type =
+      RemoveWrappingTypes(GetQualType(type), {clang::Type::Typedef});
+
+  switch (qual_type->getTypeClass()) {
+  case clang::Type::Atomic:
+  case clang::Type::Auto:
+  case clang::Type::Decltype:
+  case clang::Type::Elaborated:
+  case clang::Type::Paren:
+  case clang::Type::TypeOf:
+  case clang::Type::TypeOfExpr:
+    llvm_unreachable("Handled in RemoveWrappingTypes!");
+  case clang::Type::UnaryTransform:
+    break;
+  case clang::Type::FunctionNoProto:
+    return lldb::eTypeClassFunction;
+  case clang::Type::FunctionProto:
+    return lldb::eTypeClassFunction;
+  case clang::Type::IncompleteArray:
+    return lldb::eTypeClassArray;
+  case clang::Type::VariableArray:
+    return lldb::eTypeClassArray;
+  case clang::Type::ConstantArray:
+    return lldb::eTypeClassArray;
+  case clang::Type::DependentSizedArray:
+    return lldb::eTypeClassArray;
+  case clang::Type::DependentSizedExtVector:
+    return lldb::eTypeClassVector;
+  case clang::Type::DependentVector:
+    return lldb::eTypeClassVector;
+  case clang::Type::ExtVector:
+    return lldb::eTypeClassVector;
+  case clang::Type::Vector:
+    return lldb::eTypeClassVector;
+  case clang::Type::Builtin:
+    return lldb::eTypeClassBuiltin;
+  case clang::Type::ObjCObjectPointer:
+    return lldb::eTypeClassObjCObjectPointer;
+  case clang::Type::BlockPointer:
+    return lldb::eTypeClassBlockPointer;
+  case clang::Type::Pointer:
+    return lldb::eTypeClassPointer;
+  case clang::Type::LValueReference:
+    return lldb::eTypeClassReference;
+  case clang::Type::RValueReference:
+    return lldb::eTypeClassReference;
+  case clang::Type::MemberPointer:
+    return lldb::eTypeClassMemberPointer;
+  case clang::Type::Complex:
+    if (qual_type->isComplexType())
+      return lldb::eTypeClassComplexFloat;
+    else
+      return lldb::eTypeClassComplexInteger;
+  case clang::Type::ObjCObject:
+    return lldb::eTypeClassObjCObject;
+  case clang::Type::ObjCInterface:
+    return lldb::eTypeClassObjCInterface;
+  case clang::Type::Record: {
+    const clang::RecordType *record_type =
+        llvm::cast<clang::RecordType>(qual_type.getTypePtr());
+    const clang::RecordDecl *record_decl = record_type->getDecl();
+    if (record_decl->isUnion())
+      return lldb::eTypeClassUnion;
+    else if (record_decl->isStruct())
+      return lldb::eTypeClassStruct;
+    else
+      return lldb::eTypeClassClass;
+  } break;
+  case clang::Type::Enum:
+    return lldb::eTypeClassEnumeration;
+  case clang::Type::Typedef:
+    return lldb::eTypeClassTypedef;
+  case clang::Type::UnresolvedUsing:
+    break;
+
+  case clang::Type::Attributed:
+    break;
+  case clang::Type::TemplateTypeParm:
+    break;
+  case clang::Type::SubstTemplateTypeParm:
+    break;
+  case clang::Type::SubstTemplateTypeParmPack:
+    break;
+  case clang::Type::InjectedClassName:
+    break;
+  case clang::Type::DependentName:
+    break;
+  case clang::Type::DependentTemplateSpecialization:
+    break;
+  case clang::Type::PackExpansion:
+    break;
+
+  case clang::Type::TemplateSpecialization:
+    break;
+  case clang::Type::DeducedTemplateSpecialization:
+    break;
+  case clang::Type::Pipe:
+    break;
+
+  // pointer type decayed from an array or function type.
+  case clang::Type::Decayed:
+    break;
+  case clang::Type::Adjusted:
+    break;
+  case clang::Type::ObjCTypeParam:
+    break;
+
+  case clang::Type::DependentAddressSpace:
+    break;
+  case clang::Type::MacroQualified:
+    break;
+  }
+  // We don't know hot to display this type...
+  return lldb::eTypeClassOther;
+}
+
+unsigned TypeSystemClang::GetTypeQualifiers(lldb::opaque_compiler_type_t type) {
+  if (type)
+    return GetQualType(type).getQualifiers().getCVRQualifiers();
+  return 0;
+}
+
+// Creating related types
+
+CompilerType
+TypeSystemClang::GetArrayElementType(lldb::opaque_compiler_type_t type,
+                                     uint64_t *stride) {
+  if (type) {
+    clang::QualType qual_type(GetQualType(type));
+
+    const clang::Type *array_eletype =
+        qual_type.getTypePtr()->getArrayElementTypeNoTypeQual();
+
+    if (!array_eletype)
+      return CompilerType();
+
+    CompilerType element_type = GetType(clang::QualType(array_eletype, 0));
+
+    // TODO: the real stride will be >= this value.. find the real one!
+    if (stride)
+      if (Optional<uint64_t> size = element_type.GetByteSize(nullptr))
+        *stride = *size;
+
+    return element_type;
+  }
+  return CompilerType();
+}
+
+CompilerType TypeSystemClang::GetArrayType(lldb::opaque_compiler_type_t type,
+                                           uint64_t size) {
+  if (type) {
+    clang::QualType qual_type(GetCanonicalQualType(type));
+    clang::ASTContext &ast_ctx = getASTContext();
+    if (size != 0)
+      return GetType(ast_ctx.getConstantArrayType(
+          qual_type, llvm::APInt(64, size), nullptr,
+          clang::ArrayType::ArraySizeModifier::Normal, 0));
+    else
+      return GetType(ast_ctx.getIncompleteArrayType(
+          qual_type, clang::ArrayType::ArraySizeModifier::Normal, 0));
+  }
+
+  return CompilerType();
+}
+
+CompilerType
+TypeSystemClang::GetCanonicalType(lldb::opaque_compiler_type_t type) {
+  if (type)
+    return GetType(GetCanonicalQualType(type));
+  return CompilerType();
+}
+
+static clang::QualType GetFullyUnqualifiedType_Impl(clang::ASTContext *ast,
+                                                    clang::QualType qual_type) {
+  if (qual_type->isPointerType())
+    qual_type = ast->getPointerType(
+        GetFullyUnqualifiedType_Impl(ast, qual_type->getPointeeType()));
+  else
+    qual_type = qual_type.getUnqualifiedType();
+  qual_type.removeLocalConst();
+  qual_type.removeLocalRestrict();
+  qual_type.removeLocalVolatile();
+  return qual_type;
+}
+
+CompilerType
+TypeSystemClang::GetFullyUnqualifiedType(lldb::opaque_compiler_type_t type) {
+  if (type)
+    return GetType(
+        GetFullyUnqualifiedType_Impl(&getASTContext(), GetQualType(type)));
+  return CompilerType();
+}
+
+int TypeSystemClang::GetFunctionArgumentCount(
+    lldb::opaque_compiler_type_t type) {
+  if (type) {
+    const clang::FunctionProtoType *func =
+        llvm::dyn_cast<clang::FunctionProtoType>(GetCanonicalQualType(type));
+    if (func)
+      return func->getNumParams();
+  }
+  return -1;
+}
+
+CompilerType TypeSystemClang::GetFunctionArgumentTypeAtIndex(
+    lldb::opaque_compiler_type_t type, size_t idx) {
+  if (type) {
+    const clang::FunctionProtoType *func =
+        llvm::dyn_cast<clang::FunctionProtoType>(GetQualType(type));
+    if (func) {
+      const uint32_t num_args = func->getNumParams();
+      if (idx < num_args)
+        return GetType(func->getParamType(idx));
+    }
+  }
+  return CompilerType();
+}
+
+CompilerType
+TypeSystemClang::GetFunctionReturnType(lldb::opaque_compiler_type_t type) {
+  if (type) {
+    clang::QualType qual_type(GetQualType(type));
+    const clang::FunctionProtoType *func =
+        llvm::dyn_cast<clang::FunctionProtoType>(qual_type.getTypePtr());
+    if (func)
+      return GetType(func->getReturnType());
+  }
+  return CompilerType();
+}
+
+size_t
+TypeSystemClang::GetNumMemberFunctions(lldb::opaque_compiler_type_t type) {
+  size_t num_functions = 0;
+  if (type) {
+    clang::QualType qual_type = RemoveWrappingTypes(GetCanonicalQualType(type));
+    switch (qual_type->getTypeClass()) {
+    case clang::Type::Record:
+      if (GetCompleteQualType(&getASTContext(), qual_type)) {
+        const clang::RecordType *record_type =
+            llvm::cast<clang::RecordType>(qual_type.getTypePtr());
+        const clang::RecordDecl *record_decl = record_type->getDecl();
+        assert(record_decl);
+        const clang::CXXRecordDecl *cxx_record_decl =
+            llvm::dyn_cast<clang::CXXRecordDecl>(record_decl);
+        if (cxx_record_decl)
+          num_functions = std::distance(cxx_record_decl->method_begin(),
+                                        cxx_record_decl->method_end());
+      }
+      break;
+
+    case clang::Type::ObjCObjectPointer: {
+      const clang::ObjCObjectPointerType *objc_class_type =
+          qual_type->getAs<clang::ObjCObjectPointerType>();
+      const clang::ObjCInterfaceType *objc_interface_type =
+          objc_class_type->getInterfaceType();
+      if (objc_interface_type &&
+          GetCompleteType(static_cast<lldb::opaque_compiler_type_t>(
+              const_cast<clang::ObjCInterfaceType *>(objc_interface_type)))) {
+        clang::ObjCInterfaceDecl *class_interface_decl =
+            objc_interface_type->getDecl();
+        if (class_interface_decl) {
+          num_functions = std::distance(class_interface_decl->meth_begin(),
+                                        class_interface_decl->meth_end());
+        }
+      }
+      break;
+    }
+
+    case clang::Type::ObjCObject:
+    case clang::Type::ObjCInterface:
+      if (GetCompleteType(type)) {
+        const clang::ObjCObjectType *objc_class_type =
+            llvm::dyn_cast<clang::ObjCObjectType>(qual_type.getTypePtr());
+        if (objc_class_type) {
+          clang::ObjCInterfaceDecl *class_interface_decl =
+              objc_class_type->getInterface();
+          if (class_interface_decl)
+            num_functions = std::distance(class_interface_decl->meth_begin(),
+                                          class_interface_decl->meth_end());
+        }
+      }
+      break;
+
+    default:
+      break;
+    }
+  }
+  return num_functions;
+}
+
+TypeMemberFunctionImpl
+TypeSystemClang::GetMemberFunctionAtIndex(lldb::opaque_compiler_type_t type,
+                                          size_t idx) {
+  std::string name;
+  MemberFunctionKind kind(MemberFunctionKind::eMemberFunctionKindUnknown);
+  CompilerType clang_type;
+  CompilerDecl clang_decl;
+  if (type) {
+    clang::QualType qual_type = RemoveWrappingTypes(GetCanonicalQualType(type));
+    switch (qual_type->getTypeClass()) {
+    case clang::Type::Record:
+      if (GetCompleteQualType(&getASTContext(), qual_type)) {
+        const clang::RecordType *record_type =
+            llvm::cast<clang::RecordType>(qual_type.getTypePtr());
+        const clang::RecordDecl *record_decl = record_type->getDecl();
+        assert(record_decl);
+        const clang::CXXRecordDecl *cxx_record_decl =
+            llvm::dyn_cast<clang::CXXRecordDecl>(record_decl);
+        if (cxx_record_decl) {
+          auto method_iter = cxx_record_decl->method_begin();
+          auto method_end = cxx_record_decl->method_end();
+          if (idx <
+              static_cast<size_t>(std::distance(method_iter, method_end))) {
+            std::advance(method_iter, idx);
+            clang::CXXMethodDecl *cxx_method_decl =
+                method_iter->getCanonicalDecl();
+            if (cxx_method_decl) {
+              name = cxx_method_decl->getDeclName().getAsString();
+              if (cxx_method_decl->isStatic())
+                kind = lldb::eMemberFunctionKindStaticMethod;
+              else if (llvm::isa<clang::CXXConstructorDecl>(cxx_method_decl))
+                kind = lldb::eMemberFunctionKindConstructor;
+              else if (llvm::isa<clang::CXXDestructorDecl>(cxx_method_decl))
+                kind = lldb::eMemberFunctionKindDestructor;
+              else
+                kind = lldb::eMemberFunctionKindInstanceMethod;
+              clang_type = GetType(cxx_method_decl->getType());
+              clang_decl = GetCompilerDecl(cxx_method_decl);
+            }
+          }
+        }
+      }
+      break;
+
+    case clang::Type::ObjCObjectPointer: {
+      const clang::ObjCObjectPointerType *objc_class_type =
+          qual_type->getAs<clang::ObjCObjectPointerType>();
+      const clang::ObjCInterfaceType *objc_interface_type =
+          objc_class_type->getInterfaceType();
+      if (objc_interface_type &&
+          GetCompleteType(static_cast<lldb::opaque_compiler_type_t>(
+              const_cast<clang::ObjCInterfaceType *>(objc_interface_type)))) {
+        clang::ObjCInterfaceDecl *class_interface_decl =
+            objc_interface_type->getDecl();
+        if (class_interface_decl) {
+          auto method_iter = class_interface_decl->meth_begin();
+          auto method_end = class_interface_decl->meth_end();
+          if (idx <
+              static_cast<size_t>(std::distance(method_iter, method_end))) {
+            std::advance(method_iter, idx);
+            clang::ObjCMethodDecl *objc_method_decl =
+                method_iter->getCanonicalDecl();
+            if (objc_method_decl) {
+              clang_decl = GetCompilerDecl(objc_method_decl);
+              name = objc_method_decl->getSelector().getAsString();
+              if (objc_method_decl->isClassMethod())
+                kind = lldb::eMemberFunctionKindStaticMethod;
+              else
+                kind = lldb::eMemberFunctionKindInstanceMethod;
+            }
+          }
+        }
+      }
+      break;
+    }
+
+    case clang::Type::ObjCObject:
+    case clang::Type::ObjCInterface:
+      if (GetCompleteType(type)) {
+        const clang::ObjCObjectType *objc_class_type =
+            llvm::dyn_cast<clang::ObjCObjectType>(qual_type.getTypePtr());
+        if (objc_class_type) {
+          clang::ObjCInterfaceDecl *class_interface_decl =
+              objc_class_type->getInterface();
+          if (class_interface_decl) {
+            auto method_iter = class_interface_decl->meth_begin();
+            auto method_end = class_interface_decl->meth_end();
+            if (idx <
+                static_cast<size_t>(std::distance(method_iter, method_end))) {
+              std::advance(method_iter, idx);
+              clang::ObjCMethodDecl *objc_method_decl =
+                  method_iter->getCanonicalDecl();
+              if (objc_method_decl) {
+                clang_decl = GetCompilerDecl(objc_method_decl);
+                name = objc_method_decl->getSelector().getAsString();
+                if (objc_method_decl->isClassMethod())
+                  kind = lldb::eMemberFunctionKindStaticMethod;
+                else
+                  kind = lldb::eMemberFunctionKindInstanceMethod;
+              }
+            }
+          }
+        }
+      }
+      break;
+
+    default:
+      break;
+    }
+  }
+
+  if (kind == eMemberFunctionKindUnknown)
+    return TypeMemberFunctionImpl();
+  else
+    return TypeMemberFunctionImpl(clang_type, clang_decl, name, kind);
+}
+
+CompilerType
+TypeSystemClang::GetNonReferenceType(lldb::opaque_compiler_type_t type) {
+  if (type)
+    return GetType(GetQualType(type).getNonReferenceType());
+  return CompilerType();
+}
+
+CompilerType TypeSystemClang::CreateTypedefType(
+    const CompilerType &type, const char *typedef_name,
+    const CompilerDeclContext &compiler_decl_ctx) {
+  if (type && typedef_name && typedef_name[0]) {
+    TypeSystemClang *ast =
+        llvm::dyn_cast<TypeSystemClang>(type.GetTypeSystem());
+    if (!ast)
+      return CompilerType();
+    clang::ASTContext &clang_ast = ast->getASTContext();
+    clang::QualType qual_type(ClangUtil::GetQualType(type));
+
+    clang::DeclContext *decl_ctx =
+        TypeSystemClang::DeclContextGetAsDeclContext(compiler_decl_ctx);
+    if (decl_ctx == nullptr)
+      decl_ctx = ast->getASTContext().getTranslationUnitDecl();
+
+    clang::TypedefDecl *decl = clang::TypedefDecl::Create(
+        clang_ast, decl_ctx, clang::SourceLocation(), clang::SourceLocation(),
+        &clang_ast.Idents.get(typedef_name),
+        clang_ast.getTrivialTypeSourceInfo(qual_type));
+
+    decl->setAccess(clang::AS_public); // TODO respect proper access specifier
+
+    decl_ctx->addDecl(decl);
+
+    // Get a uniqued clang::QualType for the typedef decl type
+    return ast->GetType(clang_ast.getTypedefType(decl));
+  }
+  return CompilerType();
+}
+
+CompilerType
+TypeSystemClang::GetPointeeType(lldb::opaque_compiler_type_t type) {
+  if (type) {
+    clang::QualType qual_type(GetQualType(type));
+    return GetType(qual_type.getTypePtr()->getPointeeType());
+  }
+  return CompilerType();
+}
+
+CompilerType
+TypeSystemClang::GetPointerType(lldb::opaque_compiler_type_t type) {
+  if (type) {
+    clang::QualType qual_type(GetQualType(type));
+
+    const clang::Type::TypeClass type_class = qual_type->getTypeClass();
+    switch (type_class) {
+    case clang::Type::ObjCObject:
+    case clang::Type::ObjCInterface:
+      return GetType(getASTContext().getObjCObjectPointerType(qual_type));
+
+    default:
+      return GetType(getASTContext().getPointerType(qual_type));
+    }
+  }
+  return CompilerType();
+}
+
+CompilerType
+TypeSystemClang::GetLValueReferenceType(lldb::opaque_compiler_type_t type) {
+  if (type)
+    return GetType(getASTContext().getLValueReferenceType(GetQualType(type)));
+  else
+    return CompilerType();
+}
+
+CompilerType
+TypeSystemClang::GetRValueReferenceType(lldb::opaque_compiler_type_t type) {
+  if (type)
+    return GetType(getASTContext().getRValueReferenceType(GetQualType(type)));
+  else
+    return CompilerType();
+}
+
+CompilerType TypeSystemClang::GetAtomicType(lldb::opaque_compiler_type_t type) {
+  if (!type)
+    return CompilerType();
+  return GetType(getASTContext().getAtomicType(GetQualType(type)));
+}
+
+CompilerType
+TypeSystemClang::AddConstModifier(lldb::opaque_compiler_type_t type) {
+  if (type) {
+    clang::QualType result(GetQualType(type));
+    result.addConst();
+    return GetType(result);
+  }
+  return CompilerType();
+}
+
+CompilerType
+TypeSystemClang::AddVolatileModifier(lldb::opaque_compiler_type_t type) {
+  if (type) {
+    clang::QualType result(GetQualType(type));
+    result.addVolatile();
+    return GetType(result);
+  }
+  return CompilerType();
+}
+
+CompilerType
+TypeSystemClang::AddRestrictModifier(lldb::opaque_compiler_type_t type) {
+  if (type) {
+    clang::QualType result(GetQualType(type));
+    result.addRestrict();
+    return GetType(result);
+  }
+  return CompilerType();
+}
+
+CompilerType
+TypeSystemClang::CreateTypedef(lldb::opaque_compiler_type_t type,
+                               const char *typedef_name,
+                               const CompilerDeclContext &compiler_decl_ctx) {
+  if (type) {
+    clang::ASTContext &clang_ast = getASTContext();
+    clang::QualType qual_type(GetQualType(type));
+
+    clang::DeclContext *decl_ctx =
+        TypeSystemClang::DeclContextGetAsDeclContext(compiler_decl_ctx);
+    if (decl_ctx == nullptr)
+      decl_ctx = getASTContext().getTranslationUnitDecl();
+
+    clang::TypedefDecl *decl = clang::TypedefDecl::Create(
+        clang_ast, decl_ctx, clang::SourceLocation(), clang::SourceLocation(),
+        &clang_ast.Idents.get(typedef_name),
+        clang_ast.getTrivialTypeSourceInfo(qual_type));
+
+    clang::TagDecl *tdecl = nullptr;
+    if (!qual_type.isNull()) {
+      if (const clang::RecordType *rt = qual_type->getAs<clang::RecordType>())
+        tdecl = rt->getDecl();
+      if (const clang::EnumType *et = qual_type->getAs<clang::EnumType>())
+        tdecl = et->getDecl();
+    }
+
+    // Check whether this declaration is an anonymous struct, union, or enum,
+    // hidden behind a typedef. If so, we try to check whether we have a
+    // typedef tag to attach to the original record declaration
+    if (tdecl && !tdecl->getIdentifier() && !tdecl->getTypedefNameForAnonDecl())
+      tdecl->setTypedefNameForAnonDecl(decl);
+
+    decl->setAccess(clang::AS_public); // TODO respect proper access specifier
+
+    // Get a uniqued clang::QualType for the typedef decl type
+    return GetType(clang_ast.getTypedefType(decl));
+  }
+  return CompilerType();
+}
+
+CompilerType
+TypeSystemClang::GetTypedefedType(lldb::opaque_compiler_type_t type) {
+  if (type) {
+    const clang::TypedefType *typedef_type =
+        llvm::dyn_cast<clang::TypedefType>(GetQualType(type));
+    if (typedef_type)
+      return GetType(typedef_type->getDecl()->getUnderlyingType());
+  }
+  return CompilerType();
+}
+
+// Create related types using the current type's AST
+
+CompilerType TypeSystemClang::GetBasicTypeFromAST(lldb::BasicType basic_type) {
+  return TypeSystemClang::GetBasicType(basic_type);
+}
+// Exploring the type
+
+const llvm::fltSemantics &
+TypeSystemClang::GetFloatTypeSemantics(size_t byte_size) {
+  clang::ASTContext &ast = getASTContext();
+  const size_t bit_size = byte_size * 8;
+  if (bit_size == ast.getTypeSize(ast.FloatTy))
+    return ast.getFloatTypeSemantics(ast.FloatTy);
+  else if (bit_size == ast.getTypeSize(ast.DoubleTy))
+    return ast.getFloatTypeSemantics(ast.DoubleTy);
+  else if (bit_size == ast.getTypeSize(ast.LongDoubleTy))
+    return ast.getFloatTypeSemantics(ast.LongDoubleTy);
+  else if (bit_size == ast.getTypeSize(ast.HalfTy))
+    return ast.getFloatTypeSemantics(ast.HalfTy);
+  return llvm::APFloatBase::Bogus();
+}
+
+Optional<uint64_t>
+TypeSystemClang::GetBitSize(lldb::opaque_compiler_type_t type,
+                            ExecutionContextScope *exe_scope) {
+  if (GetCompleteType(type)) {
+    clang::QualType qual_type(GetCanonicalQualType(type));
+    const clang::Type::TypeClass type_class = qual_type->getTypeClass();
+    switch (type_class) {
+    case clang::Type::Record:
+      if (GetCompleteType(type))
+        return getASTContext().getTypeSize(qual_type);
+      else
+        return None;
+      break;
+
+    case clang::Type::ObjCInterface:
+    case clang::Type::ObjCObject: {
+      ExecutionContext exe_ctx(exe_scope);
+      Process *process = exe_ctx.GetProcessPtr();
+      if (process) {
+        ObjCLanguageRuntime *objc_runtime = ObjCLanguageRuntime::Get(*process);
+        if (objc_runtime) {
+          uint64_t bit_size = 0;
+          if (objc_runtime->GetTypeBitSize(GetType(qual_type), bit_size))
+            return bit_size;
+        }
+      } else {
+        static bool g_printed = false;
+        if (!g_printed) {
+          StreamString s;
+          DumpTypeDescription(type, &s);
+
+          llvm::outs() << "warning: trying to determine the size of type ";
+          llvm::outs() << s.GetString() << "\n";
+          llvm::outs() << "without a valid ExecutionContext. this is not "
+                          "reliable. please file a bug against LLDB.\n";
+          llvm::outs() << "backtrace:\n";
+          llvm::sys::PrintStackTrace(llvm::outs());
+          llvm::outs() << "\n";
+          g_printed = true;
+        }
+      }
+    }
+      LLVM_FALLTHROUGH;
+    default:
+      const uint32_t bit_size = getASTContext().getTypeSize(qual_type);
+      if (bit_size == 0) {
+        if (qual_type->isIncompleteArrayType())
+          return getASTContext().getTypeSize(
+              qual_type->getArrayElementTypeNoTypeQual()
+                  ->getCanonicalTypeUnqualified());
+      }
+      if (qual_type->isObjCObjectOrInterfaceType())
+        return bit_size +
+               getASTContext().getTypeSize(getASTContext().ObjCBuiltinClassTy);
+      // Function types actually have a size of 0, that's not an error.
+      if (qual_type->isFunctionProtoType())
+        return bit_size;
+      if (bit_size)
+        return bit_size;
+    }
+  }
+  return None;
+}
+
+llvm::Optional<size_t>
+TypeSystemClang::GetTypeBitAlign(lldb::opaque_compiler_type_t type,
+                                 ExecutionContextScope *exe_scope) {
+  if (GetCompleteType(type))
+    return getASTContext().getTypeAlign(GetQualType(type));
+  return {};
+}
+
+lldb::Encoding TypeSystemClang::GetEncoding(lldb::opaque_compiler_type_t type,
+                                            uint64_t &count) {
+  if (!type)
+    return lldb::eEncodingInvalid;
+
+  count = 1;
+  clang::QualType qual_type = RemoveWrappingTypes(GetCanonicalQualType(type));
+
+  switch (qual_type->getTypeClass()) {
+  case clang::Type::Atomic:
+  case clang::Type::Auto:
+  case clang::Type::Decltype:
+  case clang::Type::Elaborated:
+  case clang::Type::Paren:
+  case clang::Type::Typedef:
+  case clang::Type::TypeOf:
+  case clang::Type::TypeOfExpr:
+    llvm_unreachable("Handled in RemoveWrappingTypes!");
+
+  case clang::Type::UnaryTransform:
+    break;
+
+  case clang::Type::FunctionNoProto:
+  case clang::Type::FunctionProto:
+    break;
+
+  case clang::Type::IncompleteArray:
+  case clang::Type::VariableArray:
+    break;
+
+  case clang::Type::ConstantArray:
+    break;
+
+  case clang::Type::DependentVector:
+  case clang::Type::ExtVector:
+  case clang::Type::Vector:
+    // TODO: Set this to more than one???
+    break;
+
+  case clang::Type::Builtin:
+    switch (llvm::cast<clang::BuiltinType>(qual_type)->getKind()) {
+    case clang::BuiltinType::Void:
+      break;
+
+    case clang::BuiltinType::Bool:
+    case clang::BuiltinType::Char_S:
+    case clang::BuiltinType::SChar:
+    case clang::BuiltinType::WChar_S:
+    case clang::BuiltinType::Short:
+    case clang::BuiltinType::Int:
+    case clang::BuiltinType::Long:
+    case clang::BuiltinType::LongLong:
+    case clang::BuiltinType::Int128:
+      return lldb::eEncodingSint;
+
+    case clang::BuiltinType::Char_U:
+    case clang::BuiltinType::UChar:
+    case clang::BuiltinType::WChar_U:
+    case clang::BuiltinType::Char8:
+    case clang::BuiltinType::Char16:
+    case clang::BuiltinType::Char32:
+    case clang::BuiltinType::UShort:
+    case clang::BuiltinType::UInt:
+    case clang::BuiltinType::ULong:
+    case clang::BuiltinType::ULongLong:
+    case clang::BuiltinType::UInt128:
+      return lldb::eEncodingUint;
+
+    // Fixed point types. Note that they are currently ignored.
+    case clang::BuiltinType::ShortAccum:
+    case clang::BuiltinType::Accum:
+    case clang::BuiltinType::LongAccum:
+    case clang::BuiltinType::UShortAccum:
+    case clang::BuiltinType::UAccum:
+    case clang::BuiltinType::ULongAccum:
+    case clang::BuiltinType::ShortFract:
+    case clang::BuiltinType::Fract:
+    case clang::BuiltinType::LongFract:
+    case clang::BuiltinType::UShortFract:
+    case clang::BuiltinType::UFract:
+    case clang::BuiltinType::ULongFract:
+    case clang::BuiltinType::SatShortAccum:
+    case clang::BuiltinType::SatAccum:
+    case clang::BuiltinType::SatLongAccum:
+    case clang::BuiltinType::SatUShortAccum:
+    case clang::BuiltinType::SatUAccum:
+    case clang::BuiltinType::SatULongAccum:
+    case clang::BuiltinType::SatShortFract:
+    case clang::BuiltinType::SatFract:
+    case clang::BuiltinType::SatLongFract:
+    case clang::BuiltinType::SatUShortFract:
+    case clang::BuiltinType::SatUFract:
+    case clang::BuiltinType::SatULongFract:
+      break;
+
+    case clang::BuiltinType::Half:
+    case clang::BuiltinType::Float:
+    case clang::BuiltinType::Float16:
+    case clang::BuiltinType::Float128:
+    case clang::BuiltinType::Double:
+    case clang::BuiltinType::LongDouble:
+      return lldb::eEncodingIEEE754;
+
+    case clang::BuiltinType::ObjCClass:
+    case clang::BuiltinType::ObjCId:
+    case clang::BuiltinType::ObjCSel:
+      return lldb::eEncodingUint;
+
+    case clang::BuiltinType::NullPtr:
+      return lldb::eEncodingUint;
+
+    case clang::BuiltinType::Kind::ARCUnbridgedCast:
+    case clang::BuiltinType::Kind::BoundMember:
+    case clang::BuiltinType::Kind::BuiltinFn:
+    case clang::BuiltinType::Kind::Dependent:
+    case clang::BuiltinType::Kind::OCLClkEvent:
+    case clang::BuiltinType::Kind::OCLEvent:
+    case clang::BuiltinType::Kind::OCLImage1dRO:
+    case clang::BuiltinType::Kind::OCLImage1dWO:
+    case clang::BuiltinType::Kind::OCLImage1dRW:
+    case clang::BuiltinType::Kind::OCLImage1dArrayRO:
+    case clang::BuiltinType::Kind::OCLImage1dArrayWO:
+    case clang::BuiltinType::Kind::OCLImage1dArrayRW:
+    case clang::BuiltinType::Kind::OCLImage1dBufferRO:
+    case clang::BuiltinType::Kind::OCLImage1dBufferWO:
+    case clang::BuiltinType::Kind::OCLImage1dBufferRW:
+    case clang::BuiltinType::Kind::OCLImage2dRO:
+    case clang::BuiltinType::Kind::OCLImage2dWO:
+    case clang::BuiltinType::Kind::OCLImage2dRW:
+    case clang::BuiltinType::Kind::OCLImage2dArrayRO:
+    case clang::BuiltinType::Kind::OCLImage2dArrayWO:
+    case clang::BuiltinType::Kind::OCLImage2dArrayRW:
+    case clang::BuiltinType::Kind::OCLImage2dArrayDepthRO:
+    case clang::BuiltinType::Kind::OCLImage2dArrayDepthWO:
+    case clang::BuiltinType::Kind::OCLImage2dArrayDepthRW:
+    case clang::BuiltinType::Kind::OCLImage2dArrayMSAARO:
+    case clang::BuiltinType::Kind::OCLImage2dArrayMSAAWO:
+    case clang::BuiltinType::Kind::OCLImage2dArrayMSAARW:
+    case clang::BuiltinType::Kind::OCLImage2dArrayMSAADepthRO:
+    case clang::BuiltinType::Kind::OCLImage2dArrayMSAADepthWO:
+    case clang::BuiltinType::Kind::OCLImage2dArrayMSAADepthRW:
+    case clang::BuiltinType::Kind::OCLImage2dDepthRO:
+    case clang::BuiltinType::Kind::OCLImage2dDepthWO:
+    case clang::BuiltinType::Kind::OCLImage2dDepthRW:
+    case clang::BuiltinType::Kind::OCLImage2dMSAARO:
+    case clang::BuiltinType::Kind::OCLImage2dMSAAWO:
+    case clang::BuiltinType::Kind::OCLImage2dMSAARW:
+    case clang::BuiltinType::Kind::OCLImage2dMSAADepthRO:
+    case clang::BuiltinType::Kind::OCLImage2dMSAADepthWO:
+    case clang::BuiltinType::Kind::OCLImage2dMSAADepthRW:
+    case clang::BuiltinType::Kind::OCLImage3dRO:
+    case clang::BuiltinType::Kind::OCLImage3dWO:
+    case clang::BuiltinType::Kind::OCLImage3dRW:
+    case clang::BuiltinType::Kind::OCLQueue:
+    case clang::BuiltinType::Kind::OCLReserveID:
+    case clang::BuiltinType::Kind::OCLSampler:
+    case clang::BuiltinType::Kind::OMPArraySection:
+    case clang::BuiltinType::Kind::Overload:
+    case clang::BuiltinType::Kind::PseudoObject:
+    case clang::BuiltinType::Kind::UnknownAny:
+      break;
+
+    case clang::BuiltinType::OCLIntelSubgroupAVCMcePayload:
+    case clang::BuiltinType::OCLIntelSubgroupAVCImePayload:
+    case clang::BuiltinType::OCLIntelSubgroupAVCRefPayload:
+    case clang::BuiltinType::OCLIntelSubgroupAVCSicPayload:
+    case clang::BuiltinType::OCLIntelSubgroupAVCMceResult:
+    case clang::BuiltinType::OCLIntelSubgroupAVCImeResult:
+    case clang::BuiltinType::OCLIntelSubgroupAVCRefResult:
+    case clang::BuiltinType::OCLIntelSubgroupAVCSicResult:
+    case clang::BuiltinType::OCLIntelSubgroupAVCImeResultSingleRefStreamout:
+    case clang::BuiltinType::OCLIntelSubgroupAVCImeResultDualRefStreamout:
+    case clang::BuiltinType::OCLIntelSubgroupAVCImeSingleRefStreamin:
+    case clang::BuiltinType::OCLIntelSubgroupAVCImeDualRefStreamin:
+      break;
+
+    case clang::BuiltinType::SveBool:
+    case clang::BuiltinType::SveInt8:
+    case clang::BuiltinType::SveInt16:
+    case clang::BuiltinType::SveInt32:
+    case clang::BuiltinType::SveInt64:
+    case clang::BuiltinType::SveUint8:
+    case clang::BuiltinType::SveUint16:
+    case clang::BuiltinType::SveUint32:
+    case clang::BuiltinType::SveUint64:
+    case clang::BuiltinType::SveFloat16:
+    case clang::BuiltinType::SveFloat32:
+    case clang::BuiltinType::SveFloat64:
+      break;
+    }
+    break;
+  // All pointer types are represented as unsigned integer encodings. We may
+  // nee to add a eEncodingPointer if we ever need to know the difference
+  case clang::Type::ObjCObjectPointer:
+  case clang::Type::BlockPointer:
+  case clang::Type::Pointer:
+  case clang::Type::LValueReference:
+  case clang::Type::RValueReference:
+  case clang::Type::MemberPointer:
+    return lldb::eEncodingUint;
+  case clang::Type::Complex: {
+    lldb::Encoding encoding = lldb::eEncodingIEEE754;
+    if (qual_type->isComplexType())
+      encoding = lldb::eEncodingIEEE754;
+    else {
+      const clang::ComplexType *complex_type =
+          qual_type->getAsComplexIntegerType();
+      if (complex_type)
+        encoding = GetType(complex_type->getElementType()).GetEncoding(count);
+      else
+        encoding = lldb::eEncodingSint;
+    }
+    count = 2;
+    return encoding;
+  }
+
+  case clang::Type::ObjCInterface:
+    break;
+  case clang::Type::Record:
+    break;
+  case clang::Type::Enum:
+    return lldb::eEncodingSint;
+  case clang::Type::DependentSizedArray:
+  case clang::Type::DependentSizedExtVector:
+  case clang::Type::UnresolvedUsing:
+  case clang::Type::Attributed:
+  case clang::Type::TemplateTypeParm:
+  case clang::Type::SubstTemplateTypeParm:
+  case clang::Type::SubstTemplateTypeParmPack:
+  case clang::Type::InjectedClassName:
+  case clang::Type::DependentName:
+  case clang::Type::DependentTemplateSpecialization:
+  case clang::Type::PackExpansion:
+  case clang::Type::ObjCObject:
+
+  case clang::Type::TemplateSpecialization:
+  case clang::Type::DeducedTemplateSpecialization:
+  case clang::Type::Adjusted:
+  case clang::Type::Pipe:
+    break;
+
+  // pointer type decayed from an array or function type.
+  case clang::Type::Decayed:
+    break;
+  case clang::Type::ObjCTypeParam:
+    break;
+
+  case clang::Type::DependentAddressSpace:
+    break;
+  case clang::Type::MacroQualified:
+    break;
+  }
+  count = 0;
+  return lldb::eEncodingInvalid;
+}
+
+lldb::Format TypeSystemClang::GetFormat(lldb::opaque_compiler_type_t type) {
+  if (!type)
+    return lldb::eFormatDefault;
+
+  clang::QualType qual_type = RemoveWrappingTypes(GetCanonicalQualType(type));
+
+  switch (qual_type->getTypeClass()) {
+  case clang::Type::Atomic:
+  case clang::Type::Auto:
+  case clang::Type::Decltype:
+  case clang::Type::Elaborated:
+  case clang::Type::Paren:
+  case clang::Type::Typedef:
+  case clang::Type::TypeOf:
+  case clang::Type::TypeOfExpr:
+    llvm_unreachable("Handled in RemoveWrappingTypes!");
+  case clang::Type::UnaryTransform:
+    break;
+
+  case clang::Type::FunctionNoProto:
+  case clang::Type::FunctionProto:
+    break;
+
+  case clang::Type::IncompleteArray:
+  case clang::Type::VariableArray:
+    break;
+
+  case clang::Type::ConstantArray:
+    return lldb::eFormatVoid; // no value
+
+  case clang::Type::DependentVector:
+  case clang::Type::ExtVector:
+  case clang::Type::Vector:
+    break;
+
+  case clang::Type::Builtin:
+    switch (llvm::cast<clang::BuiltinType>(qual_type)->getKind()) {
+    // default: assert(0 && "Unknown builtin type!");
+    case clang::BuiltinType::UnknownAny:
+    case clang::BuiltinType::Void:
+    case clang::BuiltinType::BoundMember:
+      break;
+
+    case clang::BuiltinType::Bool:
+      return lldb::eFormatBoolean;
+    case clang::BuiltinType::Char_S:
+    case clang::BuiltinType::SChar:
+    case clang::BuiltinType::WChar_S:
+    case clang::BuiltinType::Char_U:
+    case clang::BuiltinType::UChar:
+    case clang::BuiltinType::WChar_U:
+      return lldb::eFormatChar;
+    case clang::BuiltinType::Char16:
+      return lldb::eFormatUnicode16;
+    case clang::BuiltinType::Char32:
+      return lldb::eFormatUnicode32;
+    case clang::BuiltinType::UShort:
+      return lldb::eFormatUnsigned;
+    case clang::BuiltinType::Short:
+      return lldb::eFormatDecimal;
+    case clang::BuiltinType::UInt:
+      return lldb::eFormatUnsigned;
+    case clang::BuiltinType::Int:
+      return lldb::eFormatDecimal;
+    case clang::BuiltinType::ULong:
+      return lldb::eFormatUnsigned;
+    case clang::BuiltinType::Long:
+      return lldb::eFormatDecimal;
+    case clang::BuiltinType::ULongLong:
+      return lldb::eFormatUnsigned;
+    case clang::BuiltinType::LongLong:
+      return lldb::eFormatDecimal;
+    case clang::BuiltinType::UInt128:
+      return lldb::eFormatUnsigned;
+    case clang::BuiltinType::Int128:
+      return lldb::eFormatDecimal;
+    case clang::BuiltinType::Half:
+    case clang::BuiltinType::Float:
+    case clang::BuiltinType::Double:
+    case clang::BuiltinType::LongDouble:
+      return lldb::eFormatFloat;
+    default:
+      return lldb::eFormatHex;
+    }
+    break;
+  case clang::Type::ObjCObjectPointer:
+    return lldb::eFormatHex;
+  case clang::Type::BlockPointer:
+    return lldb::eFormatHex;
+  case clang::Type::Pointer:
+    return lldb::eFormatHex;
+  case clang::Type::LValueReference:
+  case clang::Type::RValueReference:
+    return lldb::eFormatHex;
+  case clang::Type::MemberPointer:
+    break;
+  case clang::Type::Complex: {
+    if (qual_type->isComplexType())
+      return lldb::eFormatComplex;
+    else
+      return lldb::eFormatComplexInteger;
+  }
+  case clang::Type::ObjCInterface:
+    break;
+  case clang::Type::Record:
+    break;
+  case clang::Type::Enum:
+    return lldb::eFormatEnum;
+  case clang::Type::DependentSizedArray:
+  case clang::Type::DependentSizedExtVector:
+  case clang::Type::UnresolvedUsing:
+  case clang::Type::Attributed:
+  case clang::Type::TemplateTypeParm:
+  case clang::Type::SubstTemplateTypeParm:
+  case clang::Type::SubstTemplateTypeParmPack:
+  case clang::Type::InjectedClassName:
+  case clang::Type::DependentName:
+  case clang::Type::DependentTemplateSpecialization:
+  case clang::Type::PackExpansion:
+  case clang::Type::ObjCObject:
+
+  case clang::Type::TemplateSpecialization:
+  case clang::Type::DeducedTemplateSpecialization:
+  case clang::Type::Adjusted:
+  case clang::Type::Pipe:
+    break;
+
+  // pointer type decayed from an array or function type.
+  case clang::Type::Decayed:
+    break;
+  case clang::Type::ObjCTypeParam:
+    break;
+
+  case clang::Type::DependentAddressSpace:
+    break;
+  case clang::Type::MacroQualified:
+    break;
+  }
+  // We don't know hot to display this type...
+  return lldb::eFormatBytes;
+}
+
+static bool ObjCDeclHasIVars(clang::ObjCInterfaceDecl *class_interface_decl,
+                             bool check_superclass) {
+  while (class_interface_decl) {
+    if (class_interface_decl->ivar_size() > 0)
+      return true;
+
+    if (check_superclass)
+      class_interface_decl = class_interface_decl->getSuperClass();
+    else
+      break;
+  }
+  return false;
+}
+
+static Optional<SymbolFile::ArrayInfo>
+GetDynamicArrayInfo(TypeSystemClang &ast, SymbolFile *sym_file,
+                    clang::QualType qual_type,
+                    const ExecutionContext *exe_ctx) {
+  if (qual_type->isIncompleteArrayType())
+    if (auto *metadata = ast.GetMetadata(qual_type.getTypePtr()))
+      return sym_file->GetDynamicArrayInfoForUID(metadata->GetUserID(),
+                                                 exe_ctx);
+  return llvm::None;
+}
+
+uint32_t TypeSystemClang::GetNumChildren(lldb::opaque_compiler_type_t type,
+                                         bool omit_empty_base_classes,
+                                         const ExecutionContext *exe_ctx) {
+  if (!type)
+    return 0;
+
+  uint32_t num_children = 0;
+  clang::QualType qual_type(RemoveWrappingTypes(GetQualType(type)));
+  const clang::Type::TypeClass type_class = qual_type->getTypeClass();
+  switch (type_class) {
+  case clang::Type::Builtin:
+    switch (llvm::cast<clang::BuiltinType>(qual_type)->getKind()) {
+    case clang::BuiltinType::ObjCId:    // child is Class
+    case clang::BuiltinType::ObjCClass: // child is Class
+      num_children = 1;
+      break;
+
+    default:
+      break;
+    }
+    break;
+
+  case clang::Type::Complex:
+    return 0;
+  case clang::Type::Record:
+    if (GetCompleteQualType(&getASTContext(), qual_type)) {
+      const clang::RecordType *record_type =
+          llvm::cast<clang::RecordType>(qual_type.getTypePtr());
+      const clang::RecordDecl *record_decl = record_type->getDecl();
+      assert(record_decl);
+      const clang::CXXRecordDecl *cxx_record_decl =
+          llvm::dyn_cast<clang::CXXRecordDecl>(record_decl);
+      if (cxx_record_decl) {
+        if (omit_empty_base_classes) {
+          // Check each base classes to see if it or any of its base classes
+          // contain any fields. This can help limit the noise in variable
+          // views by not having to show base classes that contain no members.
+          clang::CXXRecordDecl::base_class_const_iterator base_class,
+              base_class_end;
+          for (base_class = cxx_record_decl->bases_begin(),
+              base_class_end = cxx_record_decl->bases_end();
+               base_class != base_class_end; ++base_class) {
+            const clang::CXXRecordDecl *base_class_decl =
+                llvm::cast<clang::CXXRecordDecl>(
+                    base_class->getType()
+                        ->getAs<clang::RecordType>()
+                        ->getDecl());
+
+            // Skip empty base classes
+            if (!TypeSystemClang::RecordHasFields(base_class_decl))
+              continue;
+
+            num_children++;
+          }
+        } else {
+          // Include all base classes
+          num_children += cxx_record_decl->getNumBases();
+        }
+      }
+      clang::RecordDecl::field_iterator field, field_end;
+      for (field = record_decl->field_begin(),
+          field_end = record_decl->field_end();
+           field != field_end; ++field)
+        ++num_children;
+    }
+    break;
+
+  case clang::Type::ObjCObject:
+  case clang::Type::ObjCInterface:
+    if (GetCompleteQualType(&getASTContext(), qual_type)) {
+      const clang::ObjCObjectType *objc_class_type =
+          llvm::dyn_cast<clang::ObjCObjectType>(qual_type.getTypePtr());
+      assert(objc_class_type);
+      if (objc_class_type) {
+        clang::ObjCInterfaceDecl *class_interface_decl =
+            objc_class_type->getInterface();
+
+        if (class_interface_decl) {
+
+          clang::ObjCInterfaceDecl *superclass_interface_decl =
+              class_interface_decl->getSuperClass();
+          if (superclass_interface_decl) {
+            if (omit_empty_base_classes) {
+              if (ObjCDeclHasIVars(superclass_interface_decl, true))
+                ++num_children;
+            } else
+              ++num_children;
+          }
+
+          num_children += class_interface_decl->ivar_size();
+        }
+      }
+    }
+    break;
+
+  case clang::Type::ObjCObjectPointer: {
+    const clang::ObjCObjectPointerType *pointer_type =
+        llvm::cast<clang::ObjCObjectPointerType>(qual_type.getTypePtr());
+    clang::QualType pointee_type = pointer_type->getPointeeType();
+    uint32_t num_pointee_children =
+        GetType(pointee_type).GetNumChildren(omit_empty_base_classes, exe_ctx);
+    // If this type points to a simple type, then it has 1 child
+    if (num_pointee_children == 0)
+      num_children = 1;
+    else
+      num_children = num_pointee_children;
+  } break;
+
+  case clang::Type::Vector:
+  case clang::Type::ExtVector:
+    num_children =
+        llvm::cast<clang::VectorType>(qual_type.getTypePtr())->getNumElements();
+    break;
+
+  case clang::Type::ConstantArray:
+    num_children = llvm::cast<clang::ConstantArrayType>(qual_type.getTypePtr())
+                       ->getSize()
+                       .getLimitedValue();
+    break;
+  case clang::Type::IncompleteArray:
+    if (auto array_info =
+            GetDynamicArrayInfo(*this, GetSymbolFile(), qual_type, exe_ctx))
+      // Only 1-dimensional arrays are supported.
+      num_children = array_info->element_orders.size()
+                         ? array_info->element_orders.back()
+                         : 0;
+    break;
+
+  case clang::Type::Pointer: {
+    const clang::PointerType *pointer_type =
+        llvm::cast<clang::PointerType>(qual_type.getTypePtr());
+    clang::QualType pointee_type(pointer_type->getPointeeType());
+    uint32_t num_pointee_children =
+        GetType(pointee_type).GetNumChildren(omit_empty_base_classes, exe_ctx);
+    if (num_pointee_children == 0) {
+      // We have a pointer to a pointee type that claims it has no children. We
+      // will want to look at
+      num_children = GetNumPointeeChildren(pointee_type);
+    } else
+      num_children = num_pointee_children;
+  } break;
+
+  case clang::Type::LValueReference:
+  case clang::Type::RValueReference: {
+    const clang::ReferenceType *reference_type =
+        llvm::cast<clang::ReferenceType>(qual_type.getTypePtr());
+    clang::QualType pointee_type = reference_type->getPointeeType();
+    uint32_t num_pointee_children =
+        GetType(pointee_type).GetNumChildren(omit_empty_base_classes, exe_ctx);
+    // If this type points to a simple type, then it has 1 child
+    if (num_pointee_children == 0)
+      num_children = 1;
+    else
+      num_children = num_pointee_children;
+  } break;
+
+  default:
+    break;
+  }
+  return num_children;
+}
+
+CompilerType TypeSystemClang::GetBuiltinTypeByName(ConstString name) {
+  return GetBasicType(GetBasicTypeEnumeration(name));
+}
+
+lldb::BasicType
+TypeSystemClang::GetBasicTypeEnumeration(lldb::opaque_compiler_type_t type) {
+  if (type) {
+    clang::QualType qual_type(GetQualType(type));
+    const clang::Type::TypeClass type_class = qual_type->getTypeClass();
+    if (type_class == clang::Type::Builtin) {
+      switch (llvm::cast<clang::BuiltinType>(qual_type)->getKind()) {
+      case clang::BuiltinType::Void:
+        return eBasicTypeVoid;
+      case clang::BuiltinType::Bool:
+        return eBasicTypeBool;
+      case clang::BuiltinType::Char_S:
+        return eBasicTypeSignedChar;
+      case clang::BuiltinType::Char_U:
+        return eBasicTypeUnsignedChar;
+      case clang::BuiltinType::Char16:
+        return eBasicTypeChar16;
+      case clang::BuiltinType::Char32:
+        return eBasicTypeChar32;
+      case clang::BuiltinType::UChar:
+        return eBasicTypeUnsignedChar;
+      case clang::BuiltinType::SChar:
+        return eBasicTypeSignedChar;
+      case clang::BuiltinType::WChar_S:
+        return eBasicTypeSignedWChar;
+      case clang::BuiltinType::WChar_U:
+        return eBasicTypeUnsignedWChar;
+      case clang::BuiltinType::Short:
+        return eBasicTypeShort;
+      case clang::BuiltinType::UShort:
+        return eBasicTypeUnsignedShort;
+      case clang::BuiltinType::Int:
+        return eBasicTypeInt;
+      case clang::BuiltinType::UInt:
+        return eBasicTypeUnsignedInt;
+      case clang::BuiltinType::Long:
+        return eBasicTypeLong;
+      case clang::BuiltinType::ULong:
+        return eBasicTypeUnsignedLong;
+      case clang::BuiltinType::LongLong:
+        return eBasicTypeLongLong;
+      case clang::BuiltinType::ULongLong:
+        return eBasicTypeUnsignedLongLong;
+      case clang::BuiltinType::Int128:
+        return eBasicTypeInt128;
+      case clang::BuiltinType::UInt128:
+        return eBasicTypeUnsignedInt128;
+
+      case clang::BuiltinType::Half:
+        return eBasicTypeHalf;
+      case clang::BuiltinType::Float:
+        return eBasicTypeFloat;
+      case clang::BuiltinType::Double:
+        return eBasicTypeDouble;
+      case clang::BuiltinType::LongDouble:
+        return eBasicTypeLongDouble;
+
+      case clang::BuiltinType::NullPtr:
+        return eBasicTypeNullPtr;
+      case clang::BuiltinType::ObjCId:
+        return eBasicTypeObjCID;
+      case clang::BuiltinType::ObjCClass:
+        return eBasicTypeObjCClass;
+      case clang::BuiltinType::ObjCSel:
+        return eBasicTypeObjCSel;
+      default:
+        return eBasicTypeOther;
+      }
+    }
+  }
+  return eBasicTypeInvalid;
+}
+
+void TypeSystemClang::ForEachEnumerator(
+    lldb::opaque_compiler_type_t type,
+    std::function<bool(const CompilerType &integer_type,
+                       ConstString name,
+                       const llvm::APSInt &value)> const &callback) {
+  const clang::EnumType *enum_type =
+      llvm::dyn_cast<clang::EnumType>(GetCanonicalQualType(type));
+  if (enum_type) {
+    const clang::EnumDecl *enum_decl = enum_type->getDecl();
+    if (enum_decl) {
+      CompilerType integer_type = GetType(enum_decl->getIntegerType());
+
+      clang::EnumDecl::enumerator_iterator enum_pos, enum_end_pos;
+      for (enum_pos = enum_decl->enumerator_begin(),
+          enum_end_pos = enum_decl->enumerator_end();
+           enum_pos != enum_end_pos; ++enum_pos) {
+        ConstString name(enum_pos->getNameAsString().c_str());
+        if (!callback(integer_type, name, enum_pos->getInitVal()))
+          break;
+      }
+    }
+  }
+}
+
+#pragma mark Aggregate Types
+
+uint32_t TypeSystemClang::GetNumFields(lldb::opaque_compiler_type_t type) {
+  if (!type)
+    return 0;
+
+  uint32_t count = 0;
+  clang::QualType qual_type(RemoveWrappingTypes(GetCanonicalQualType(type)));
+  const clang::Type::TypeClass type_class = qual_type->getTypeClass();
+  switch (type_class) {
+  case clang::Type::Record:
+    if (GetCompleteType(type)) {
+      const clang::RecordType *record_type =
+          llvm::dyn_cast<clang::RecordType>(qual_type.getTypePtr());
+      if (record_type) {
+        clang::RecordDecl *record_decl = record_type->getDecl();
+        if (record_decl) {
+          uint32_t field_idx = 0;
+          clang::RecordDecl::field_iterator field, field_end;
+          for (field = record_decl->field_begin(),
+              field_end = record_decl->field_end();
+               field != field_end; ++field)
+            ++field_idx;
+          count = field_idx;
+        }
+      }
+    }
+    break;
+
+  case clang::Type::ObjCObjectPointer: {
+    const clang::ObjCObjectPointerType *objc_class_type =
+        qual_type->getAs<clang::ObjCObjectPointerType>();
+    const clang::ObjCInterfaceType *objc_interface_type =
+        objc_class_type->getInterfaceType();
+    if (objc_interface_type &&
+        GetCompleteType(static_cast<lldb::opaque_compiler_type_t>(
+            const_cast<clang::ObjCInterfaceType *>(objc_interface_type)))) {
+      clang::ObjCInterfaceDecl *class_interface_decl =
+          objc_interface_type->getDecl();
+      if (class_interface_decl) {
+        count = class_interface_decl->ivar_size();
+      }
+    }
+    break;
+  }
+
+  case clang::Type::ObjCObject:
+  case clang::Type::ObjCInterface:
+    if (GetCompleteType(type)) {
+      const clang::ObjCObjectType *objc_class_type =
+          llvm::dyn_cast<clang::ObjCObjectType>(qual_type.getTypePtr());
+      if (objc_class_type) {
+        clang::ObjCInterfaceDecl *class_interface_decl =
+            objc_class_type->getInterface();
+
+        if (class_interface_decl)
+          count = class_interface_decl->ivar_size();
+      }
+    }
+    break;
+
+  default:
+    break;
+  }
+  return count;
+}
+
+static lldb::opaque_compiler_type_t
+GetObjCFieldAtIndex(clang::ASTContext *ast,
+                    clang::ObjCInterfaceDecl *class_interface_decl, size_t idx,
+                    std::string &name, uint64_t *bit_offset_ptr,
+                    uint32_t *bitfield_bit_size_ptr, bool *is_bitfield_ptr) {
+  if (class_interface_decl) {
+    if (idx < (class_interface_decl->ivar_size())) {
+      clang::ObjCInterfaceDecl::ivar_iterator ivar_pos,
+          ivar_end = class_interface_decl->ivar_end();
+      uint32_t ivar_idx = 0;
+
+      for (ivar_pos = class_interface_decl->ivar_begin(); ivar_pos != ivar_end;
+           ++ivar_pos, ++ivar_idx) {
+        if (ivar_idx == idx) {
+          const clang::ObjCIvarDecl *ivar_decl = *ivar_pos;
+
+          clang::QualType ivar_qual_type(ivar_decl->getType());
+
+          name.assign(ivar_decl->getNameAsString());
+
+          if (bit_offset_ptr) {
+            const clang::ASTRecordLayout &interface_layout =
+                ast->getASTObjCInterfaceLayout(class_interface_decl);
+            *bit_offset_ptr = interface_layout.getFieldOffset(ivar_idx);
+          }
+
+          const bool is_bitfield = ivar_pos->isBitField();
+
+          if (bitfield_bit_size_ptr) {
+            *bitfield_bit_size_ptr = 0;
+
+            if (is_bitfield && ast) {
+              clang::Expr *bitfield_bit_size_expr = ivar_pos->getBitWidth();
+              clang::Expr::EvalResult result;
+              if (bitfield_bit_size_expr &&
+                  bitfield_bit_size_expr->EvaluateAsInt(result, *ast)) {
+                llvm::APSInt bitfield_apsint = result.Val.getInt();
+                *bitfield_bit_size_ptr = bitfield_apsint.getLimitedValue();
+              }
+            }
+          }
+          if (is_bitfield_ptr)
+            *is_bitfield_ptr = is_bitfield;
+
+          return ivar_qual_type.getAsOpaquePtr();
+        }
+      }
+    }
+  }
+  return nullptr;
+}
+
+CompilerType TypeSystemClang::GetFieldAtIndex(lldb::opaque_compiler_type_t type,
+                                              size_t idx, std::string &name,
+                                              uint64_t *bit_offset_ptr,
+                                              uint32_t *bitfield_bit_size_ptr,
+                                              bool *is_bitfield_ptr) {
+  if (!type)
+    return CompilerType();
+
+  clang::QualType qual_type(RemoveWrappingTypes(GetCanonicalQualType(type)));
+  const clang::Type::TypeClass type_class = qual_type->getTypeClass();
+  switch (type_class) {
+  case clang::Type::Record:
+    if (GetCompleteType(type)) {
+      const clang::RecordType *record_type =
+          llvm::cast<clang::RecordType>(qual_type.getTypePtr());
+      const clang::RecordDecl *record_decl = record_type->getDecl();
+      uint32_t field_idx = 0;
+      clang::RecordDecl::field_iterator field, field_end;
+      for (field = record_decl->field_begin(),
+          field_end = record_decl->field_end();
+           field != field_end; ++field, ++field_idx) {
+        if (idx == field_idx) {
+          // Print the member type if requested
+          // Print the member name and equal sign
+          name.assign(field->getNameAsString());
+
+          // Figure out the type byte size (field_type_info.first) and
+          // alignment (field_type_info.second) from the AST context.
+          if (bit_offset_ptr) {
+            const clang::ASTRecordLayout &record_layout =
+                getASTContext().getASTRecordLayout(record_decl);
+            *bit_offset_ptr = record_layout.getFieldOffset(field_idx);
+          }
+
+          const bool is_bitfield = field->isBitField();
+
+          if (bitfield_bit_size_ptr) {
+            *bitfield_bit_size_ptr = 0;
+
+            if (is_bitfield) {
+              clang::Expr *bitfield_bit_size_expr = field->getBitWidth();
+              clang::Expr::EvalResult result;
+              if (bitfield_bit_size_expr &&
+                  bitfield_bit_size_expr->EvaluateAsInt(result,
+                                                        getASTContext())) {
+                llvm::APSInt bitfield_apsint = result.Val.getInt();
+                *bitfield_bit_size_ptr = bitfield_apsint.getLimitedValue();
+              }
+            }
+          }
+          if (is_bitfield_ptr)
+            *is_bitfield_ptr = is_bitfield;
+
+          return GetType(field->getType());
+        }
+      }
+    }
+    break;
+
+  case clang::Type::ObjCObjectPointer: {
+    const clang::ObjCObjectPointerType *objc_class_type =
+        qual_type->getAs<clang::ObjCObjectPointerType>();
+    const clang::ObjCInterfaceType *objc_interface_type =
+        objc_class_type->getInterfaceType();
+    if (objc_interface_type &&
+        GetCompleteType(static_cast<lldb::opaque_compiler_type_t>(
+            const_cast<clang::ObjCInterfaceType *>(objc_interface_type)))) {
+      clang::ObjCInterfaceDecl *class_interface_decl =
+          objc_interface_type->getDecl();
+      if (class_interface_decl) {
+        return CompilerType(
+            this, GetObjCFieldAtIndex(&getASTContext(), class_interface_decl,
+                                      idx, name, bit_offset_ptr,
+                                      bitfield_bit_size_ptr, is_bitfield_ptr));
+      }
+    }
+    break;
+  }
+
+  case clang::Type::ObjCObject:
+  case clang::Type::ObjCInterface:
+    if (GetCompleteType(type)) {
+      const clang::ObjCObjectType *objc_class_type =
+          llvm::dyn_cast<clang::ObjCObjectType>(qual_type.getTypePtr());
+      assert(objc_class_type);
+      if (objc_class_type) {
+        clang::ObjCInterfaceDecl *class_interface_decl =
+            objc_class_type->getInterface();
+        return CompilerType(
+            this, GetObjCFieldAtIndex(&getASTContext(), class_interface_decl,
+                                      idx, name, bit_offset_ptr,
+                                      bitfield_bit_size_ptr, is_bitfield_ptr));
+      }
+    }
+    break;
+
+  default:
+    break;
+  }
+  return CompilerType();
+}
+
+uint32_t
+TypeSystemClang::GetNumDirectBaseClasses(lldb::opaque_compiler_type_t type) {
+  uint32_t count = 0;
+  clang::QualType qual_type = RemoveWrappingTypes(GetCanonicalQualType(type));
+  const clang::Type::TypeClass type_class = qual_type->getTypeClass();
+  switch (type_class) {
+  case clang::Type::Record:
+    if (GetCompleteType(type)) {
+      const clang::CXXRecordDecl *cxx_record_decl =
+          qual_type->getAsCXXRecordDecl();
+      if (cxx_record_decl)
+        count = cxx_record_decl->getNumBases();
+    }
+    break;
+
+  case clang::Type::ObjCObjectPointer:
+    count = GetPointeeType(type).GetNumDirectBaseClasses();
+    break;
+
+  case clang::Type::ObjCObject:
+    if (GetCompleteType(type)) {
+      const clang::ObjCObjectType *objc_class_type =
+          qual_type->getAsObjCQualifiedInterfaceType();
+      if (objc_class_type) {
+        clang::ObjCInterfaceDecl *class_interface_decl =
+            objc_class_type->getInterface();
+
+        if (class_interface_decl && class_interface_decl->getSuperClass())
+          count = 1;
+      }
+    }
+    break;
+  case clang::Type::ObjCInterface:
+    if (GetCompleteType(type)) {
+      const clang::ObjCInterfaceType *objc_interface_type =
+          qual_type->getAs<clang::ObjCInterfaceType>();
+      if (objc_interface_type) {
+        clang::ObjCInterfaceDecl *class_interface_decl =
+            objc_interface_type->getInterface();
+
+        if (class_interface_decl && class_interface_decl->getSuperClass())
+          count = 1;
+      }
+    }
+    break;
+
+  default:
+    break;
+  }
+  return count;
+}
+
+uint32_t
+TypeSystemClang::GetNumVirtualBaseClasses(lldb::opaque_compiler_type_t type) {
+  uint32_t count = 0;
+  clang::QualType qual_type = RemoveWrappingTypes(GetCanonicalQualType(type));
+  const clang::Type::TypeClass type_class = qual_type->getTypeClass();
+  switch (type_class) {
+  case clang::Type::Record:
+    if (GetCompleteType(type)) {
+      const clang::CXXRecordDecl *cxx_record_decl =
+          qual_type->getAsCXXRecordDecl();
+      if (cxx_record_decl)
+        count = cxx_record_decl->getNumVBases();
+    }
+    break;
+
+  default:
+    break;
+  }
+  return count;
+}
+
+CompilerType TypeSystemClang::GetDirectBaseClassAtIndex(
+    lldb::opaque_compiler_type_t type, size_t idx, uint32_t *bit_offset_ptr) {
+  clang::QualType qual_type = RemoveWrappingTypes(GetCanonicalQualType(type));
+  const clang::Type::TypeClass type_class = qual_type->getTypeClass();
+  switch (type_class) {
+  case clang::Type::Record:
+    if (GetCompleteType(type)) {
+      const clang::CXXRecordDecl *cxx_record_decl =
+          qual_type->getAsCXXRecordDecl();
+      if (cxx_record_decl) {
+        uint32_t curr_idx = 0;
+        clang::CXXRecordDecl::base_class_const_iterator base_class,
+            base_class_end;
+        for (base_class = cxx_record_decl->bases_begin(),
+            base_class_end = cxx_record_decl->bases_end();
+             base_class != base_class_end; ++base_class, ++curr_idx) {
+          if (curr_idx == idx) {
+            if (bit_offset_ptr) {
+              const clang::ASTRecordLayout &record_layout =
+                  getASTContext().getASTRecordLayout(cxx_record_decl);
+              const clang::CXXRecordDecl *base_class_decl =
+                  llvm::cast<clang::CXXRecordDecl>(
+                      base_class->getType()
+                          ->getAs<clang::RecordType>()
+                          ->getDecl());
+              if (base_class->isVirtual())
+                *bit_offset_ptr =
+                    record_layout.getVBaseClassOffset(base_class_decl)
+                        .getQuantity() *
+                    8;
+              else
+                *bit_offset_ptr =
+                    record_layout.getBaseClassOffset(base_class_decl)
+                        .getQuantity() *
+                    8;
+            }
+            return GetType(base_class->getType());
+          }
+        }
+      }
+    }
+    break;
+
+  case clang::Type::ObjCObjectPointer:
+    return GetPointeeType(type).GetDirectBaseClassAtIndex(idx, bit_offset_ptr);
+
+  case clang::Type::ObjCObject:
+    if (idx == 0 && GetCompleteType(type)) {
+      const clang::ObjCObjectType *objc_class_type =
+          qual_type->getAsObjCQualifiedInterfaceType();
+      if (objc_class_type) {
+        clang::ObjCInterfaceDecl *class_interface_decl =
+            objc_class_type->getInterface();
+
+        if (class_interface_decl) {
+          clang::ObjCInterfaceDecl *superclass_interface_decl =
+              class_interface_decl->getSuperClass();
+          if (superclass_interface_decl) {
+            if (bit_offset_ptr)
+              *bit_offset_ptr = 0;
+            return GetType(getASTContext().getObjCInterfaceType(
+                superclass_interface_decl));
+          }
+        }
+      }
+    }
+    break;
+  case clang::Type::ObjCInterface:
+    if (idx == 0 && GetCompleteType(type)) {
+      const clang::ObjCObjectType *objc_interface_type =
+          qual_type->getAs<clang::ObjCInterfaceType>();
+      if (objc_interface_type) {
+        clang::ObjCInterfaceDecl *class_interface_decl =
+            objc_interface_type->getInterface();
+
+        if (class_interface_decl) {
+          clang::ObjCInterfaceDecl *superclass_interface_decl =
+              class_interface_decl->getSuperClass();
+          if (superclass_interface_decl) {
+            if (bit_offset_ptr)
+              *bit_offset_ptr = 0;
+            return GetType(getASTContext().getObjCInterfaceType(
+                superclass_interface_decl));
+          }
+        }
+      }
+    }
+    break;
+
+  default:
+    break;
+  }
+  return CompilerType();
+}
+
+CompilerType TypeSystemClang::GetVirtualBaseClassAtIndex(
+    lldb::opaque_compiler_type_t type, size_t idx, uint32_t *bit_offset_ptr) {
+  clang::QualType qual_type = RemoveWrappingTypes(GetCanonicalQualType(type));
+  const clang::Type::TypeClass type_class = qual_type->getTypeClass();
+  switch (type_class) {
+  case clang::Type::Record:
+    if (GetCompleteType(type)) {
+      const clang::CXXRecordDecl *cxx_record_decl =
+          qual_type->getAsCXXRecordDecl();
+      if (cxx_record_decl) {
+        uint32_t curr_idx = 0;
+        clang::CXXRecordDecl::base_class_const_iterator base_class,
+            base_class_end;
+        for (base_class = cxx_record_decl->vbases_begin(),
+            base_class_end = cxx_record_decl->vbases_end();
+             base_class != base_class_end; ++base_class, ++curr_idx) {
+          if (curr_idx == idx) {
+            if (bit_offset_ptr) {
+              const clang::ASTRecordLayout &record_layout =
+                  getASTContext().getASTRecordLayout(cxx_record_decl);
+              const clang::CXXRecordDecl *base_class_decl =
+                  llvm::cast<clang::CXXRecordDecl>(
+                      base_class->getType()
+                          ->getAs<clang::RecordType>()
+                          ->getDecl());
+              *bit_offset_ptr =
+                  record_layout.getVBaseClassOffset(base_class_decl)
+                      .getQuantity() *
+                  8;
+            }
+            return GetType(base_class->getType());
+          }
+        }
+      }
+    }
+    break;
+
+  default:
+    break;
+  }
+  return CompilerType();
+}
+
+// If a pointer to a pointee type (the clang_type arg) says that it has no
+// children, then we either need to trust it, or override it and return a
+// different result. For example, an "int *" has one child that is an integer,
+// but a function pointer doesn't have any children. Likewise if a Record type
+// claims it has no children, then there really is nothing to show.
+uint32_t TypeSystemClang::GetNumPointeeChildren(clang::QualType type) {
+  if (type.isNull())
+    return 0;
+
+  clang::QualType qual_type = RemoveWrappingTypes(type.getCanonicalType());
+  const clang::Type::TypeClass type_class = qual_type->getTypeClass();
+  switch (type_class) {
+  case clang::Type::Builtin:
+    switch (llvm::cast<clang::BuiltinType>(qual_type)->getKind()) {
+    case clang::BuiltinType::UnknownAny:
+    case clang::BuiltinType::Void:
+    case clang::BuiltinType::NullPtr:
+    case clang::BuiltinType::OCLEvent:
+    case clang::BuiltinType::OCLImage1dRO:
+    case clang::BuiltinType::OCLImage1dWO:
+    case clang::BuiltinType::OCLImage1dRW:
+    case clang::BuiltinType::OCLImage1dArrayRO:
+    case clang::BuiltinType::OCLImage1dArrayWO:
+    case clang::BuiltinType::OCLImage1dArrayRW:
+    case clang::BuiltinType::OCLImage1dBufferRO:
+    case clang::BuiltinType::OCLImage1dBufferWO:
+    case clang::BuiltinType::OCLImage1dBufferRW:
+    case clang::BuiltinType::OCLImage2dRO:
+    case clang::BuiltinType::OCLImage2dWO:
+    case clang::BuiltinType::OCLImage2dRW:
+    case clang::BuiltinType::OCLImage2dArrayRO:
+    case clang::BuiltinType::OCLImage2dArrayWO:
+    case clang::BuiltinType::OCLImage2dArrayRW:
+    case clang::BuiltinType::OCLImage3dRO:
+    case clang::BuiltinType::OCLImage3dWO:
+    case clang::BuiltinType::OCLImage3dRW:
+    case clang::BuiltinType::OCLSampler:
+      return 0;
+    case clang::BuiltinType::Bool:
+    case clang::BuiltinType::Char_U:
+    case clang::BuiltinType::UChar:
+    case clang::BuiltinType::WChar_U:
+    case clang::BuiltinType::Char16:
+    case clang::BuiltinType::Char32:
+    case clang::BuiltinType::UShort:
+    case clang::BuiltinType::UInt:
+    case clang::BuiltinType::ULong:
+    case clang::BuiltinType::ULongLong:
+    case clang::BuiltinType::UInt128:
+    case clang::BuiltinType::Char_S:
+    case clang::BuiltinType::SChar:
+    case clang::BuiltinType::WChar_S:
+    case clang::BuiltinType::Short:
+    case clang::BuiltinType::Int:
+    case clang::BuiltinType::Long:
+    case clang::BuiltinType::LongLong:
+    case clang::BuiltinType::Int128:
+    case clang::BuiltinType::Float:
+    case clang::BuiltinType::Double:
+    case clang::BuiltinType::LongDouble:
+    case clang::BuiltinType::Dependent:
+    case clang::BuiltinType::Overload:
+    case clang::BuiltinType::ObjCId:
+    case clang::BuiltinType::ObjCClass:
+    case clang::BuiltinType::ObjCSel:
+    case clang::BuiltinType::BoundMember:
+    case clang::BuiltinType::Half:
+    case clang::BuiltinType::ARCUnbridgedCast:
+    case clang::BuiltinType::PseudoObject:
+    case clang::BuiltinType::BuiltinFn:
+    case clang::BuiltinType::OMPArraySection:
+      return 1;
+    default:
+      return 0;
+    }
+    break;
+
+  case clang::Type::Complex:
+    return 1;
+  case clang::Type::Pointer:
+    return 1;
+  case clang::Type::BlockPointer:
+    return 0; // If block pointers don't have debug info, then no children for
+              // them
+  case clang::Type::LValueReference:
+    return 1;
+  case clang::Type::RValueReference:
+    return 1;
+  case clang::Type::MemberPointer:
+    return 0;
+  case clang::Type::ConstantArray:
+    return 0;
+  case clang::Type::IncompleteArray:
+    return 0;
+  case clang::Type::VariableArray:
+    return 0;
+  case clang::Type::DependentSizedArray:
+    return 0;
+  case clang::Type::DependentSizedExtVector:
+    return 0;
+  case clang::Type::Vector:
+    return 0;
+  case clang::Type::ExtVector:
+    return 0;
+  case clang::Type::FunctionProto:
+    return 0; // When we function pointers, they have no children...
+  case clang::Type::FunctionNoProto:
+    return 0; // When we function pointers, they have no children...
+  case clang::Type::UnresolvedUsing:
+    return 0;
+  case clang::Type::Record:
+    return 0;
+  case clang::Type::Enum:
+    return 1;
+  case clang::Type::TemplateTypeParm:
+    return 1;
+  case clang::Type::SubstTemplateTypeParm:
+    return 1;
+  case clang::Type::TemplateSpecialization:
+    return 1;
+  case clang::Type::InjectedClassName:
+    return 0;
+  case clang::Type::DependentName:
+    return 1;
+  case clang::Type::DependentTemplateSpecialization:
+    return 1;
+  case clang::Type::ObjCObject:
+    return 0;
+  case clang::Type::ObjCInterface:
+    return 0;
+  case clang::Type::ObjCObjectPointer:
+    return 1;
+  default:
+    break;
+  }
+  return 0;
+}
+
+CompilerType TypeSystemClang::GetChildCompilerTypeAtIndex(
+    lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx, size_t idx,
+    bool transparent_pointers, bool omit_empty_base_classes,
+    bool ignore_array_bounds, std::string &child_name,
+    uint32_t &child_byte_size, int32_t &child_byte_offset,
+    uint32_t &child_bitfield_bit_size, uint32_t &child_bitfield_bit_offset,
+    bool &child_is_base_class, bool &child_is_deref_of_parent,
+    ValueObject *valobj, uint64_t &language_flags) {
+  if (!type)
+    return CompilerType();
+
+  auto get_exe_scope = [&exe_ctx]() {
+    return exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr;
+  };
+
+  clang::QualType parent_qual_type(
+      RemoveWrappingTypes(GetCanonicalQualType(type)));
+  const clang::Type::TypeClass parent_type_class =
+      parent_qual_type->getTypeClass();
+  child_bitfield_bit_size = 0;
+  child_bitfield_bit_offset = 0;
+  child_is_base_class = false;
+  language_flags = 0;
+
+  const bool idx_is_valid =
+      idx < GetNumChildren(type, omit_empty_base_classes, exe_ctx);
+  int32_t bit_offset;
+  switch (parent_type_class) {
+  case clang::Type::Builtin:
+    if (idx_is_valid) {
+      switch (llvm::cast<clang::BuiltinType>(parent_qual_type)->getKind()) {
+      case clang::BuiltinType::ObjCId:
+      case clang::BuiltinType::ObjCClass:
+        child_name = "isa";
+        child_byte_size =
+            getASTContext().getTypeSize(getASTContext().ObjCBuiltinClassTy) /
+            CHAR_BIT;
+        return GetType(getASTContext().ObjCBuiltinClassTy);
+
+      default:
+        break;
+      }
+    }
+    break;
+
+  case clang::Type::Record:
+    if (idx_is_valid && GetCompleteType(type)) {
+      const clang::RecordType *record_type =
+          llvm::cast<clang::RecordType>(parent_qual_type.getTypePtr());
+      const clang::RecordDecl *record_decl = record_type->getDecl();
+      assert(record_decl);
+      const clang::ASTRecordLayout &record_layout =
+          getASTContext().getASTRecordLayout(record_decl);
+      uint32_t child_idx = 0;
+
+      const clang::CXXRecordDecl *cxx_record_decl =
+          llvm::dyn_cast<clang::CXXRecordDecl>(record_decl);
+      if (cxx_record_decl) {
+        // We might have base classes to print out first
+        clang::CXXRecordDecl::base_class_const_iterator base_class,
+            base_class_end;
+        for (base_class = cxx_record_decl->bases_begin(),
+            base_class_end = cxx_record_decl->bases_end();
+             base_class != base_class_end; ++base_class) {
+          const clang::CXXRecordDecl *base_class_decl = nullptr;
+
+          // Skip empty base classes
+          if (omit_empty_base_classes) {
+            base_class_decl = llvm::cast<clang::CXXRecordDecl>(
+                base_class->getType()->getAs<clang::RecordType>()->getDecl());
+            if (!TypeSystemClang::RecordHasFields(base_class_decl))
+              continue;
+          }
+
+          if (idx == child_idx) {
+            if (base_class_decl == nullptr)
+              base_class_decl = llvm::cast<clang::CXXRecordDecl>(
+                  base_class->getType()->getAs<clang::RecordType>()->getDecl());
+
+            if (base_class->isVirtual()) {
+              bool handled = false;
+              if (valobj) {
+                clang::VTableContextBase *vtable_ctx =
+                    getASTContext().getVTableContext();
+                if (vtable_ctx)
+                  handled = GetVBaseBitOffset(*vtable_ctx, *valobj,
+                                              record_layout, cxx_record_decl,
+                                              base_class_decl, bit_offset);
+              }
+              if (!handled)
+                bit_offset = record_layout.getVBaseClassOffset(base_class_decl)
+                                 .getQuantity() *
+                             8;
+            } else
+              bit_offset = record_layout.getBaseClassOffset(base_class_decl)
+                               .getQuantity() *
+                           8;
+
+            // Base classes should be a multiple of 8 bits in size
+            child_byte_offset = bit_offset / 8;
+            CompilerType base_class_clang_type = GetType(base_class->getType());
+            child_name = base_class_clang_type.GetTypeName().AsCString("");
+            Optional<uint64_t> size =
+                base_class_clang_type.GetBitSize(get_exe_scope());
+            if (!size)
+              return {};
+            uint64_t base_class_clang_type_bit_size = *size;
+
+            // Base classes bit sizes should be a multiple of 8 bits in size
+            assert(base_class_clang_type_bit_size % 8 == 0);
+            child_byte_size = base_class_clang_type_bit_size / 8;
+            child_is_base_class = true;
+            return base_class_clang_type;
+          }
+          // We don't increment the child index in the for loop since we might
+          // be skipping empty base classes
+          ++child_idx;
+        }
+      }
+      // Make sure index is in range...
+      uint32_t field_idx = 0;
+      clang::RecordDecl::field_iterator field, field_end;
+      for (field = record_decl->field_begin(),
+          field_end = record_decl->field_end();
+           field != field_end; ++field, ++field_idx, ++child_idx) {
+        if (idx == child_idx) {
+          // Print the member type if requested
+          // Print the member name and equal sign
+          child_name.assign(field->getNameAsString());
+
+          // Figure out the type byte size (field_type_info.first) and
+          // alignment (field_type_info.second) from the AST context.
+          CompilerType field_clang_type = GetType(field->getType());
+          assert(field_idx < record_layout.getFieldCount());
+          Optional<uint64_t> size =
+              field_clang_type.GetByteSize(get_exe_scope());
+          if (!size)
+            return {};
+          child_byte_size = *size;
+          const uint32_t child_bit_size = child_byte_size * 8;
+
+          // Figure out the field offset within the current struct/union/class
+          // type
+          bit_offset = record_layout.getFieldOffset(field_idx);
+          if (FieldIsBitfield(*field, child_bitfield_bit_size)) {
+            child_bitfield_bit_offset = bit_offset % child_bit_size;
+            const uint32_t child_bit_offset =
+                bit_offset - child_bitfield_bit_offset;
+            child_byte_offset = child_bit_offset / 8;
+          } else {
+            child_byte_offset = bit_offset / 8;
+          }
+
+          return field_clang_type;
+        }
+      }
+    }
+    break;
+
+  case clang::Type::ObjCObject:
+  case clang::Type::ObjCInterface:
+    if (idx_is_valid && GetCompleteType(type)) {
+      const clang::ObjCObjectType *objc_class_type =
+          llvm::dyn_cast<clang::ObjCObjectType>(parent_qual_type.getTypePtr());
+      assert(objc_class_type);
+      if (objc_class_type) {
+        uint32_t child_idx = 0;
+        clang::ObjCInterfaceDecl *class_interface_decl =
+            objc_class_type->getInterface();
+
+        if (class_interface_decl) {
+
+          const clang::ASTRecordLayout &interface_layout =
+              getASTContext().getASTObjCInterfaceLayout(class_interface_decl);
+          clang::ObjCInterfaceDecl *superclass_interface_decl =
+              class_interface_decl->getSuperClass();
+          if (superclass_interface_decl) {
+            if (omit_empty_base_classes) {
+              CompilerType base_class_clang_type =
+                  GetType(getASTContext().getObjCInterfaceType(
+                      superclass_interface_decl));
+              if (base_class_clang_type.GetNumChildren(omit_empty_base_classes,
+                                                       exe_ctx) > 0) {
+                if (idx == 0) {
+                  clang::QualType ivar_qual_type(
+                      getASTContext().getObjCInterfaceType(
+                          superclass_interface_decl));
+
+                  child_name.assign(
+                      superclass_interface_decl->getNameAsString());
+
+                  clang::TypeInfo ivar_type_info =
+                      getASTContext().getTypeInfo(ivar_qual_type.getTypePtr());
+
+                  child_byte_size = ivar_type_info.Width / 8;
+                  child_byte_offset = 0;
+                  child_is_base_class = true;
+
+                  return GetType(ivar_qual_type);
+                }
+
+                ++child_idx;
+              }
+            } else
+              ++child_idx;
+          }
+
+          const uint32_t superclass_idx = child_idx;
+
+          if (idx < (child_idx + class_interface_decl->ivar_size())) {
+            clang::ObjCInterfaceDecl::ivar_iterator ivar_pos,
+                ivar_end = class_interface_decl->ivar_end();
+
+            for (ivar_pos = class_interface_decl->ivar_begin();
+                 ivar_pos != ivar_end; ++ivar_pos) {
+              if (child_idx == idx) {
+                clang::ObjCIvarDecl *ivar_decl = *ivar_pos;
+
+                clang::QualType ivar_qual_type(ivar_decl->getType());
+
+                child_name.assign(ivar_decl->getNameAsString());
+
+                clang::TypeInfo ivar_type_info =
+                    getASTContext().getTypeInfo(ivar_qual_type.getTypePtr());
+
+                child_byte_size = ivar_type_info.Width / 8;
+
+                // Figure out the field offset within the current
+                // struct/union/class type For ObjC objects, we can't trust the
+                // bit offset we get from the Clang AST, since that doesn't
+                // account for the space taken up by unbacked properties, or
+                // from the changing size of base classes that are newer than
+                // this class. So if we have a process around that we can ask
+                // about this object, do so.
+                child_byte_offset = LLDB_INVALID_IVAR_OFFSET;
+                Process *process = nullptr;
+                if (exe_ctx)
+                  process = exe_ctx->GetProcessPtr();
+                if (process) {
+                  ObjCLanguageRuntime *objc_runtime =
+                      ObjCLanguageRuntime::Get(*process);
+                  if (objc_runtime != nullptr) {
+                    CompilerType parent_ast_type = GetType(parent_qual_type);
+                    child_byte_offset = objc_runtime->GetByteOffsetForIvar(
+                        parent_ast_type, ivar_decl->getNameAsString().c_str());
+                  }
+                }
+
+                // Setting this to INT32_MAX to make sure we don't compute it
+                // twice...
+                bit_offset = INT32_MAX;
+
+                if (child_byte_offset ==
+                    static_cast<int32_t>(LLDB_INVALID_IVAR_OFFSET)) {
+                  bit_offset = interface_layout.getFieldOffset(child_idx -
+                                                               superclass_idx);
+                  child_byte_offset = bit_offset / 8;
+                }
+
+                // Note, the ObjC Ivar Byte offset is just that, it doesn't
+                // account for the bit offset of a bitfield within its
+                // containing object.  So regardless of where we get the byte
+                // offset from, we still need to get the bit offset for
+                // bitfields from the layout.
+
+                if (FieldIsBitfield(ivar_decl, child_bitfield_bit_size)) {
+                  if (bit_offset == INT32_MAX)
+                    bit_offset = interface_layout.getFieldOffset(
+                        child_idx - superclass_idx);
+
+                  child_bitfield_bit_offset = bit_offset % 8;
+                }
+                return GetType(ivar_qual_type);
+              }
+              ++child_idx;
+            }
+          }
+        }
+      }
+    }
+    break;
+
+  case clang::Type::ObjCObjectPointer:
+    if (idx_is_valid) {
+      CompilerType pointee_clang_type(GetPointeeType(type));
+
+      if (transparent_pointers && pointee_clang_type.IsAggregateType()) {
+        child_is_deref_of_parent = false;
+        bool tmp_child_is_deref_of_parent = false;
+        return pointee_clang_type.GetChildCompilerTypeAtIndex(
+            exe_ctx, idx, transparent_pointers, omit_empty_base_classes,
+            ignore_array_bounds, child_name, child_byte_size, child_byte_offset,
+            child_bitfield_bit_size, child_bitfield_bit_offset,
+            child_is_base_class, tmp_child_is_deref_of_parent, valobj,
+            language_flags);
+      } else {
+        child_is_deref_of_parent = true;
+        const char *parent_name =
+            valobj ? valobj->GetName().GetCString() : nullptr;
+        if (parent_name) {
+          child_name.assign(1, '*');
+          child_name += parent_name;
+        }
+
+        // We have a pointer to an simple type
+        if (idx == 0 && pointee_clang_type.GetCompleteType()) {
+          if (Optional<uint64_t> size =
+                  pointee_clang_type.GetByteSize(get_exe_scope())) {
+            child_byte_size = *size;
+            child_byte_offset = 0;
+            return pointee_clang_type;
+          }
+        }
+      }
+    }
+    break;
+
+  case clang::Type::Vector:
+  case clang::Type::ExtVector:
+    if (idx_is_valid) {
+      const clang::VectorType *array =
+          llvm::cast<clang::VectorType>(parent_qual_type.getTypePtr());
+      if (array) {
+        CompilerType element_type = GetType(array->getElementType());
+        if (element_type.GetCompleteType()) {
+          char element_name[64];
+          ::snprintf(element_name, sizeof(element_name), "[%" PRIu64 "]",
+                     static_cast<uint64_t>(idx));
+          child_name.assign(element_name);
+          if (Optional<uint64_t> size =
+                  element_type.GetByteSize(get_exe_scope())) {
+            child_byte_size = *size;
+            child_byte_offset = (int32_t)idx * (int32_t)child_byte_size;
+            return element_type;
+          }
+        }
+      }
+    }
+    break;
+
+  case clang::Type::ConstantArray:
+  case clang::Type::IncompleteArray:
+    if (ignore_array_bounds || idx_is_valid) {
+      const clang::ArrayType *array = GetQualType(type)->getAsArrayTypeUnsafe();
+      if (array) {
+        CompilerType element_type = GetType(array->getElementType());
+        if (element_type.GetCompleteType()) {
+          child_name = std::string(llvm::formatv("[{0}]", idx));
+          if (Optional<uint64_t> size =
+                  element_type.GetByteSize(get_exe_scope())) {
+            child_byte_size = *size;
+            child_byte_offset = (int32_t)idx * (int32_t)child_byte_size;
+            return element_type;
+          }
+        }
+      }
+    }
+    break;
+
+  case clang::Type::Pointer: {
+    CompilerType pointee_clang_type(GetPointeeType(type));
+
+    // Don't dereference "void *" pointers
+    if (pointee_clang_type.IsVoidType())
+      return CompilerType();
+
+    if (transparent_pointers && pointee_clang_type.IsAggregateType()) {
+      child_is_deref_of_parent = false;
+      bool tmp_child_is_deref_of_parent = false;
+      return pointee_clang_type.GetChildCompilerTypeAtIndex(
+          exe_ctx, idx, transparent_pointers, omit_empty_base_classes,
+          ignore_array_bounds, child_name, child_byte_size, child_byte_offset,
+          child_bitfield_bit_size, child_bitfield_bit_offset,
+          child_is_base_class, tmp_child_is_deref_of_parent, valobj,
+          language_flags);
+    } else {
+      child_is_deref_of_parent = true;
+
+      const char *parent_name =
+          valobj ? valobj->GetName().GetCString() : nullptr;
+      if (parent_name) {
+        child_name.assign(1, '*');
+        child_name += parent_name;
+      }
+
+      // We have a pointer to an simple type
+      if (idx == 0) {
+        if (Optional<uint64_t> size =
+                pointee_clang_type.GetByteSize(get_exe_scope())) {
+          child_byte_size = *size;
+          child_byte_offset = 0;
+          return pointee_clang_type;
+        }
+      }
+    }
+    break;
+  }
+
+  case clang::Type::LValueReference:
+  case clang::Type::RValueReference:
+    if (idx_is_valid) {
+      const clang::ReferenceType *reference_type =
+          llvm::cast<clang::ReferenceType>(parent_qual_type.getTypePtr());
+      CompilerType pointee_clang_type =
+          GetType(reference_type->getPointeeType());
+      if (transparent_pointers && pointee_clang_type.IsAggregateType()) {
+        child_is_deref_of_parent = false;
+        bool tmp_child_is_deref_of_parent = false;
+        return pointee_clang_type.GetChildCompilerTypeAtIndex(
+            exe_ctx, idx, transparent_pointers, omit_empty_base_classes,
+            ignore_array_bounds, child_name, child_byte_size, child_byte_offset,
+            child_bitfield_bit_size, child_bitfield_bit_offset,
+            child_is_base_class, tmp_child_is_deref_of_parent, valobj,
+            language_flags);
+      } else {
+        const char *parent_name =
+            valobj ? valobj->GetName().GetCString() : nullptr;
+        if (parent_name) {
+          child_name.assign(1, '&');
+          child_name += parent_name;
+        }
+
+        // We have a pointer to an simple type
+        if (idx == 0) {
+          if (Optional<uint64_t> size =
+                  pointee_clang_type.GetByteSize(get_exe_scope())) {
+            child_byte_size = *size;
+            child_byte_offset = 0;
+            return pointee_clang_type;
+          }
+        }
+      }
+    }
+    break;
+
+  default:
+    break;
+  }
+  return CompilerType();
+}
+
+static uint32_t GetIndexForRecordBase(const clang::RecordDecl *record_decl,
+                                      const clang::CXXBaseSpecifier *base_spec,
+                                      bool omit_empty_base_classes) {
+  uint32_t child_idx = 0;
+
+  const clang::CXXRecordDecl *cxx_record_decl =
+      llvm::dyn_cast<clang::CXXRecordDecl>(record_decl);
+
+  //    const char *super_name = record_decl->getNameAsCString();
+  //    const char *base_name =
+  //    base_spec->getType()->getAs<clang::RecordType>()->getDecl()->getNameAsCString();
+  //    printf ("GetIndexForRecordChild (%s, %s)\n", super_name, base_name);
+  //
+  if (cxx_record_decl) {
+    clang::CXXRecordDecl::base_class_const_iterator base_class, base_class_end;
+    for (base_class = cxx_record_decl->bases_begin(),
+        base_class_end = cxx_record_decl->bases_end();
+         base_class != base_class_end; ++base_class) {
+      if (omit_empty_base_classes) {
+        if (BaseSpecifierIsEmpty(base_class))
+          continue;
+      }
+
+      //            printf ("GetIndexForRecordChild (%s, %s) base[%u] = %s\n",
+      //            super_name, base_name,
+      //                    child_idx,
+      //                    base_class->getType()->getAs<clang::RecordType>()->getDecl()->getNameAsCString());
+      //
+      //
+      if (base_class == base_spec)
+        return child_idx;
+      ++child_idx;
+    }
+  }
+
+  return UINT32_MAX;
+}
+
+static uint32_t GetIndexForRecordChild(const clang::RecordDecl *record_decl,
+                                       clang::NamedDecl *canonical_decl,
+                                       bool omit_empty_base_classes) {
+  uint32_t child_idx = TypeSystemClang::GetNumBaseClasses(
+      llvm::dyn_cast<clang::CXXRecordDecl>(record_decl),
+      omit_empty_base_classes);
+
+  clang::RecordDecl::field_iterator field, field_end;
+  for (field = record_decl->field_begin(), field_end = record_decl->field_end();
+       field != field_end; ++field, ++child_idx) {
+    if (field->getCanonicalDecl() == canonical_decl)
+      return child_idx;
+  }
+
+  return UINT32_MAX;
+}
+
+// Look for a child member (doesn't include base classes, but it does include
+// their members) in the type hierarchy. Returns an index path into
+// "clang_type" on how to reach the appropriate member.
+//
+//    class A
+//    {
+//    public:
+//        int m_a;
+//        int m_b;
+//    };
+//
+//    class B
+//    {
+//    };
+//
+//    class C :
+//        public B,
+//        public A
+//    {
+//    };
+//
+// If we have a clang type that describes "class C", and we wanted to looked
+// "m_b" in it:
+//
+// With omit_empty_base_classes == false we would get an integer array back
+// with: { 1,  1 } The first index 1 is the child index for "class A" within
+// class C The second index 1 is the child index for "m_b" within class A
+//
+// With omit_empty_base_classes == true we would get an integer array back
+// with: { 0,  1 } The first index 0 is the child index for "class A" within
+// class C (since class B doesn't have any members it doesn't count) The second
+// index 1 is the child index for "m_b" within class A
+
+size_t TypeSystemClang::GetIndexOfChildMemberWithName(
+    lldb::opaque_compiler_type_t type, const char *name,
+    bool omit_empty_base_classes, std::vector<uint32_t> &child_indexes) {
+  if (type && name && name[0]) {
+    clang::QualType qual_type = RemoveWrappingTypes(GetCanonicalQualType(type));
+    const clang::Type::TypeClass type_class = qual_type->getTypeClass();
+    switch (type_class) {
+    case clang::Type::Record:
+      if (GetCompleteType(type)) {
+        const clang::RecordType *record_type =
+            llvm::cast<clang::RecordType>(qual_type.getTypePtr());
+        const clang::RecordDecl *record_decl = record_type->getDecl();
+
+        assert(record_decl);
+        uint32_t child_idx = 0;
+
+        const clang::CXXRecordDecl *cxx_record_decl =
+            llvm::dyn_cast<clang::CXXRecordDecl>(record_decl);
+
+        // Try and find a field that matches NAME
+        clang::RecordDecl::field_iterator field, field_end;
+        llvm::StringRef name_sref(name);
+        for (field = record_decl->field_begin(),
+            field_end = record_decl->field_end();
+             field != field_end; ++field, ++child_idx) {
+          llvm::StringRef field_name = field->getName();
+          if (field_name.empty()) {
+            CompilerType field_type = GetType(field->getType());
+            child_indexes.push_back(child_idx);
+            if (field_type.GetIndexOfChildMemberWithName(
+                    name, omit_empty_base_classes, child_indexes))
+              return child_indexes.size();
+            child_indexes.pop_back();
+
+          } else if (field_name.equals(name_sref)) {
+            // We have to add on the number of base classes to this index!
+            child_indexes.push_back(
+                child_idx + TypeSystemClang::GetNumBaseClasses(
+                                cxx_record_decl, omit_empty_base_classes));
+            return child_indexes.size();
+          }
+        }
+
+        if (cxx_record_decl) {
+          const clang::RecordDecl *parent_record_decl = cxx_record_decl;
+
+          // printf ("parent = %s\n", parent_record_decl->getNameAsCString());
+
+          // const Decl *root_cdecl = cxx_record_decl->getCanonicalDecl();
+          // Didn't find things easily, lets let clang do its thang...
+          clang::IdentifierInfo &ident_ref =
+              getASTContext().Idents.get(name_sref);
+          clang::DeclarationName decl_name(&ident_ref);
+
+          clang::CXXBasePaths paths;
+          if (cxx_record_decl->lookupInBases(
+                  [decl_name](const clang::CXXBaseSpecifier *specifier,
+                              clang::CXXBasePath &path) {
+                    return clang::CXXRecordDecl::FindOrdinaryMember(
+                        specifier, path, decl_name);
+                  },
+                  paths)) {
+            clang::CXXBasePaths::const_paths_iterator path,
+                path_end = paths.end();
+            for (path = paths.begin(); path != path_end; ++path) {
+              const size_t num_path_elements = path->size();
+              for (size_t e = 0; e < num_path_elements; ++e) {
+                clang::CXXBasePathElement elem = (*path)[e];
+
+                child_idx = GetIndexForRecordBase(parent_record_decl, elem.Base,
+                                                  omit_empty_base_classes);
+                if (child_idx == UINT32_MAX) {
+                  child_indexes.clear();
+                  return 0;
+                } else {
+                  child_indexes.push_back(child_idx);
+                  parent_record_decl = llvm::cast<clang::RecordDecl>(
+                      elem.Base->getType()
+                          ->getAs<clang::RecordType>()
+                          ->getDecl());
+                }
+              }
+              for (clang::NamedDecl *path_decl : path->Decls) {
+                child_idx = GetIndexForRecordChild(
+                    parent_record_decl, path_decl, omit_empty_base_classes);
+                if (child_idx == UINT32_MAX) {
+                  child_indexes.clear();
+                  return 0;
+                } else {
+                  child_indexes.push_back(child_idx);
+                }
+              }
+            }
+            return child_indexes.size();
+          }
+        }
+      }
+      break;
+
+    case clang::Type::ObjCObject:
+    case clang::Type::ObjCInterface:
+      if (GetCompleteType(type)) {
+        llvm::StringRef name_sref(name);
+        const clang::ObjCObjectType *objc_class_type =
+            llvm::dyn_cast<clang::ObjCObjectType>(qual_type.getTypePtr());
+        assert(objc_class_type);
+        if (objc_class_type) {
+          uint32_t child_idx = 0;
+          clang::ObjCInterfaceDecl *class_interface_decl =
+              objc_class_type->getInterface();
+
+          if (class_interface_decl) {
+            clang::ObjCInterfaceDecl::ivar_iterator ivar_pos,
+                ivar_end = class_interface_decl->ivar_end();
+            clang::ObjCInterfaceDecl *superclass_interface_decl =
+                class_interface_decl->getSuperClass();
+
+            for (ivar_pos = class_interface_decl->ivar_begin();
+                 ivar_pos != ivar_end; ++ivar_pos, ++child_idx) {
+              const clang::ObjCIvarDecl *ivar_decl = *ivar_pos;
+
+              if (ivar_decl->getName().equals(name_sref)) {
+                if ((!omit_empty_base_classes && superclass_interface_decl) ||
+                    (omit_empty_base_classes &&
+                     ObjCDeclHasIVars(superclass_interface_decl, true)))
+                  ++child_idx;
+
+                child_indexes.push_back(child_idx);
+                return child_indexes.size();
+              }
+            }
+
+            if (superclass_interface_decl) {
+              // The super class index is always zero for ObjC classes, so we
+              // push it onto the child indexes in case we find an ivar in our
+              // superclass...
+              child_indexes.push_back(0);
+
+              CompilerType superclass_clang_type =
+                  GetType(getASTContext().getObjCInterfaceType(
+                      superclass_interface_decl));
+              if (superclass_clang_type.GetIndexOfChildMemberWithName(
+                      name, omit_empty_base_classes, child_indexes)) {
+                // We did find an ivar in a superclass so just return the
+                // results!
+                return child_indexes.size();
+              }
+
+              // We didn't find an ivar matching "name" in our superclass, pop
+              // the superclass zero index that we pushed on above.
+              child_indexes.pop_back();
+            }
+          }
+        }
+      }
+      break;
+
+    case clang::Type::ObjCObjectPointer: {
+      CompilerType objc_object_clang_type = GetType(
+          llvm::cast<clang::ObjCObjectPointerType>(qual_type.getTypePtr())
+              ->getPointeeType());
+      return objc_object_clang_type.GetIndexOfChildMemberWithName(
+          name, omit_empty_base_classes, child_indexes);
+    } break;
+
+    case clang::Type::ConstantArray: {
+      //                const clang::ConstantArrayType *array =
+      //                llvm::cast<clang::ConstantArrayType>(parent_qual_type.getTypePtr());
+      //                const uint64_t element_count =
+      //                array->getSize().getLimitedValue();
+      //
+      //                if (idx < element_count)
+      //                {
+      //                    std::pair<uint64_t, unsigned> field_type_info =
+      //                    ast->getTypeInfo(array->getElementType());
+      //
+      //                    char element_name[32];
+      //                    ::snprintf (element_name, sizeof (element_name),
+      //                    "%s[%u]", parent_name ? parent_name : "", idx);
+      //
+      //                    child_name.assign(element_name);
+      //                    assert(field_type_info.first % 8 == 0);
+      //                    child_byte_size = field_type_info.first / 8;
+      //                    child_byte_offset = idx * child_byte_size;
+      //                    return array->getElementType().getAsOpaquePtr();
+      //                }
+    } break;
+
+    //        case clang::Type::MemberPointerType:
+    //            {
+    //                MemberPointerType *mem_ptr_type =
+    //                llvm::cast<MemberPointerType>(qual_type.getTypePtr());
+    //                clang::QualType pointee_type =
+    //                mem_ptr_type->getPointeeType();
+    //
+    //                if (TypeSystemClang::IsAggregateType
+    //                (pointee_type.getAsOpaquePtr()))
+    //                {
+    //                    return GetIndexOfChildWithName (ast,
+    //                                                    mem_ptr_type->getPointeeType().getAsOpaquePtr(),
+    //                                                    name);
+    //                }
+    //            }
+    //            break;
+    //
+    case clang::Type::LValueReference:
+    case clang::Type::RValueReference: {
+      const clang::ReferenceType *reference_type =
+          llvm::cast<clang::ReferenceType>(qual_type.getTypePtr());
+      clang::QualType pointee_type(reference_type->getPointeeType());
+      CompilerType pointee_clang_type = GetType(pointee_type);
+
+      if (pointee_clang_type.IsAggregateType()) {
+        return pointee_clang_type.GetIndexOfChildMemberWithName(
+            name, omit_empty_base_classes, child_indexes);
+      }
+    } break;
+
+    case clang::Type::Pointer: {
+      CompilerType pointee_clang_type(GetPointeeType(type));
+
+      if (pointee_clang_type.IsAggregateType()) {
+        return pointee_clang_type.GetIndexOfChildMemberWithName(
+            name, omit_empty_base_classes, child_indexes);
+      }
+    } break;
+
+    default:
+      break;
+    }
+  }
+  return 0;
+}
+
+// Get the index of the child of "clang_type" whose name matches. This function
+// doesn't descend into the children, but only looks one level deep and name
+// matches can include base class names.
+
+uint32_t
+TypeSystemClang::GetIndexOfChildWithName(lldb::opaque_compiler_type_t type,
+                                         const char *name,
+                                         bool omit_empty_base_classes) {
+  if (type && name && name[0]) {
+    clang::QualType qual_type = RemoveWrappingTypes(GetCanonicalQualType(type));
+
+    const clang::Type::TypeClass type_class = qual_type->getTypeClass();
+
+    switch (type_class) {
+    case clang::Type::Record:
+      if (GetCompleteType(type)) {
+        const clang::RecordType *record_type =
+            llvm::cast<clang::RecordType>(qual_type.getTypePtr());
+        const clang::RecordDecl *record_decl = record_type->getDecl();
+
+        assert(record_decl);
+        uint32_t child_idx = 0;
+
+        const clang::CXXRecordDecl *cxx_record_decl =
+            llvm::dyn_cast<clang::CXXRecordDecl>(record_decl);
+
+        if (cxx_record_decl) {
+          clang::CXXRecordDecl::base_class_const_iterator base_class,
+              base_class_end;
+          for (base_class = cxx_record_decl->bases_begin(),
+              base_class_end = cxx_record_decl->bases_end();
+               base_class != base_class_end; ++base_class) {
+            // Skip empty base classes
+            clang::CXXRecordDecl *base_class_decl =
+                llvm::cast<clang::CXXRecordDecl>(
+                    base_class->getType()
+                        ->getAs<clang::RecordType>()
+                        ->getDecl());
+            if (omit_empty_base_classes &&
+                !TypeSystemClang::RecordHasFields(base_class_decl))
+              continue;
+
+            CompilerType base_class_clang_type = GetType(base_class->getType());
+            std::string base_class_type_name(
+                base_class_clang_type.GetTypeName().AsCString(""));
+            if (base_class_type_name == name)
+              return child_idx;
+            ++child_idx;
+          }
+        }
+
+        // Try and find a field that matches NAME
+        clang::RecordDecl::field_iterator field, field_end;
+        llvm::StringRef name_sref(name);
+        for (field = record_decl->field_begin(),
+            field_end = record_decl->field_end();
+             field != field_end; ++field, ++child_idx) {
+          if (field->getName().equals(name_sref))
+            return child_idx;
+        }
+      }
+      break;
+
+    case clang::Type::ObjCObject:
+    case clang::Type::ObjCInterface:
+      if (GetCompleteType(type)) {
+        llvm::StringRef name_sref(name);
+        const clang::ObjCObjectType *objc_class_type =
+            llvm::dyn_cast<clang::ObjCObjectType>(qual_type.getTypePtr());
+        assert(objc_class_type);
+        if (objc_class_type) {
+          uint32_t child_idx = 0;
+          clang::ObjCInterfaceDecl *class_interface_decl =
+              objc_class_type->getInterface();
+
+          if (class_interface_decl) {
+            clang::ObjCInterfaceDecl::ivar_iterator ivar_pos,
+                ivar_end = class_interface_decl->ivar_end();
+            clang::ObjCInterfaceDecl *superclass_interface_decl =
+                class_interface_decl->getSuperClass();
+
+            for (ivar_pos = class_interface_decl->ivar_begin();
+                 ivar_pos != ivar_end; ++ivar_pos, ++child_idx) {
+              const clang::ObjCIvarDecl *ivar_decl = *ivar_pos;
+
+              if (ivar_decl->getName().equals(name_sref)) {
+                if ((!omit_empty_base_classes && superclass_interface_decl) ||
+                    (omit_empty_base_classes &&
+                     ObjCDeclHasIVars(superclass_interface_decl, true)))
+                  ++child_idx;
+
+                return child_idx;
+              }
+            }
+
+            if (superclass_interface_decl) {
+              if (superclass_interface_decl->getName().equals(name_sref))
+                return 0;
+            }
+          }
+        }
+      }
+      break;
+
+    case clang::Type::ObjCObjectPointer: {
+      CompilerType pointee_clang_type = GetType(
+          llvm::cast<clang::ObjCObjectPointerType>(qual_type.getTypePtr())
+              ->getPointeeType());
+      return pointee_clang_type.GetIndexOfChildWithName(
+          name, omit_empty_base_classes);
+    } break;
+
+    case clang::Type::ConstantArray: {
+      //                const clang::ConstantArrayType *array =
+      //                llvm::cast<clang::ConstantArrayType>(parent_qual_type.getTypePtr());
+      //                const uint64_t element_count =
+      //                array->getSize().getLimitedValue();
+      //
+      //                if (idx < element_count)
+      //                {
+      //                    std::pair<uint64_t, unsigned> field_type_info =
+      //                    ast->getTypeInfo(array->getElementType());
+      //
+      //                    char element_name[32];
+      //                    ::snprintf (element_name, sizeof (element_name),
+      //                    "%s[%u]", parent_name ? parent_name : "", idx);
+      //
+      //                    child_name.assign(element_name);
+      //                    assert(field_type_info.first % 8 == 0);
+      //                    child_byte_size = field_type_info.first / 8;
+      //                    child_byte_offset = idx * child_byte_size;
+      //                    return array->getElementType().getAsOpaquePtr();
+      //                }
+    } break;
+
+    //        case clang::Type::MemberPointerType:
+    //            {
+    //                MemberPointerType *mem_ptr_type =
+    //                llvm::cast<MemberPointerType>(qual_type.getTypePtr());
+    //                clang::QualType pointee_type =
+    //                mem_ptr_type->getPointeeType();
+    //
+    //                if (TypeSystemClang::IsAggregateType
+    //                (pointee_type.getAsOpaquePtr()))
+    //                {
+    //                    return GetIndexOfChildWithName (ast,
+    //                                                    mem_ptr_type->getPointeeType().getAsOpaquePtr(),
+    //                                                    name);
+    //                }
+    //            }
+    //            break;
+    //
+    case clang::Type::LValueReference:
+    case clang::Type::RValueReference: {
+      const clang::ReferenceType *reference_type =
+          llvm::cast<clang::ReferenceType>(qual_type.getTypePtr());
+      CompilerType pointee_type = GetType(reference_type->getPointeeType());
+
+      if (pointee_type.IsAggregateType()) {
+        return pointee_type.GetIndexOfChildWithName(name,
+                                                    omit_empty_base_classes);
+      }
+    } break;
+
+    case clang::Type::Pointer: {
+      const clang::PointerType *pointer_type =
+          llvm::cast<clang::PointerType>(qual_type.getTypePtr());
+      CompilerType pointee_type = GetType(pointer_type->getPointeeType());
+
+      if (pointee_type.IsAggregateType()) {
+        return pointee_type.GetIndexOfChildWithName(name,
+                                                    omit_empty_base_classes);
+      } else {
+        //                    if (parent_name)
+        //                    {
+        //                        child_name.assign(1, '*');
+        //                        child_name += parent_name;
+        //                    }
+        //
+        //                    // We have a pointer to an simple type
+        //                    if (idx == 0)
+        //                    {
+        //                        std::pair<uint64_t, unsigned> clang_type_info
+        //                        = ast->getTypeInfo(pointee_type);
+        //                        assert(clang_type_info.first % 8 == 0);
+        //                        child_byte_size = clang_type_info.first / 8;
+        //                        child_byte_offset = 0;
+        //                        return pointee_type.getAsOpaquePtr();
+        //                    }
+      }
+    } break;
+
+    default:
+      break;
+    }
+  }
+  return UINT32_MAX;
+}
+
+size_t
+TypeSystemClang::GetNumTemplateArguments(lldb::opaque_compiler_type_t type) {
+  if (!type)
+    return 0;
+
+  clang::QualType qual_type = RemoveWrappingTypes(GetCanonicalQualType(type));
+  const clang::Type::TypeClass type_class = qual_type->getTypeClass();
+  switch (type_class) {
+  case clang::Type::Record:
+    if (GetCompleteType(type)) {
+      const clang::CXXRecordDecl *cxx_record_decl =
+          qual_type->getAsCXXRecordDecl();
+      if (cxx_record_decl) {
+        const clang::ClassTemplateSpecializationDecl *template_decl =
+            llvm::dyn_cast<clang::ClassTemplateSpecializationDecl>(
+                cxx_record_decl);
+        if (template_decl)
+          return template_decl->getTemplateArgs().size();
+      }
+    }
+    break;
+
+  default:
+    break;
+  }
+
+  return 0;
+}
+
+const clang::ClassTemplateSpecializationDecl *
+TypeSystemClang::GetAsTemplateSpecialization(
+    lldb::opaque_compiler_type_t type) {
+  if (!type)
+    return nullptr;
+
+  clang::QualType qual_type(RemoveWrappingTypes(GetCanonicalQualType(type)));
+  const clang::Type::TypeClass type_class = qual_type->getTypeClass();
+  switch (type_class) {
+  case clang::Type::Record: {
+    if (! GetCompleteType(type))
+      return nullptr;
+    const clang::CXXRecordDecl *cxx_record_decl =
+        qual_type->getAsCXXRecordDecl();
+    if (!cxx_record_decl)
+      return nullptr;
+    return llvm::dyn_cast<clang::ClassTemplateSpecializationDecl>(
+        cxx_record_decl);
+  }
+
+  default:
+    return nullptr;
+  }
+}
+
+lldb::TemplateArgumentKind
+TypeSystemClang::GetTemplateArgumentKind(lldb::opaque_compiler_type_t type,
+                                         size_t arg_idx) {
+  const clang::ClassTemplateSpecializationDecl *template_decl =
+      GetAsTemplateSpecialization(type);
+  if (! template_decl || arg_idx >= template_decl->getTemplateArgs().size())
+    return eTemplateArgumentKindNull;
+
+  switch (template_decl->getTemplateArgs()[arg_idx].getKind()) {
+  case clang::TemplateArgument::Null:
+    return eTemplateArgumentKindNull;
+
+  case clang::TemplateArgument::NullPtr:
+    return eTemplateArgumentKindNullPtr;
+
+  case clang::TemplateArgument::Type:
+    return eTemplateArgumentKindType;
+
+  case clang::TemplateArgument::Declaration:
+    return eTemplateArgumentKindDeclaration;
+
+  case clang::TemplateArgument::Integral:
+    return eTemplateArgumentKindIntegral;
+
+  case clang::TemplateArgument::Template:
+    return eTemplateArgumentKindTemplate;
+
+  case clang::TemplateArgument::TemplateExpansion:
+    return eTemplateArgumentKindTemplateExpansion;
+
+  case clang::TemplateArgument::Expression:
+    return eTemplateArgumentKindExpression;
+
+  case clang::TemplateArgument::Pack:
+    return eTemplateArgumentKindPack;
+  }
+  llvm_unreachable("Unhandled clang::TemplateArgument::ArgKind");
+}
+
+CompilerType
+TypeSystemClang::GetTypeTemplateArgument(lldb::opaque_compiler_type_t type,
+                                         size_t idx) {
+  const clang::ClassTemplateSpecializationDecl *template_decl =
+      GetAsTemplateSpecialization(type);
+  if (!template_decl || idx >= template_decl->getTemplateArgs().size())
+    return CompilerType();
+
+  const clang::TemplateArgument &template_arg =
+      template_decl->getTemplateArgs()[idx];
+  if (template_arg.getKind() != clang::TemplateArgument::Type)
+    return CompilerType();
+
+  return GetType(template_arg.getAsType());
+}
+
+Optional<CompilerType::IntegralTemplateArgument>
+TypeSystemClang::GetIntegralTemplateArgument(lldb::opaque_compiler_type_t type,
+                                             size_t idx) {
+  const clang::ClassTemplateSpecializationDecl *template_decl =
+      GetAsTemplateSpecialization(type);
+  if (! template_decl || idx >= template_decl->getTemplateArgs().size())
+    return llvm::None;
+
+  const clang::TemplateArgument &template_arg =
+      template_decl->getTemplateArgs()[idx];
+  if (template_arg.getKind() != clang::TemplateArgument::Integral)
+    return llvm::None;
+
+  return {
+      {template_arg.getAsIntegral(), GetType(template_arg.getIntegralType())}};
+}
+
+CompilerType TypeSystemClang::GetTypeForFormatters(void *type) {
+  if (type)
+    return ClangUtil::RemoveFastQualifiers(CompilerType(this, type));
+  return CompilerType();
+}
+
+clang::EnumDecl *TypeSystemClang::GetAsEnumDecl(const CompilerType &type) {
+  const clang::EnumType *enutype =
+      llvm::dyn_cast<clang::EnumType>(ClangUtil::GetCanonicalQualType(type));
+  if (enutype)
+    return enutype->getDecl();
+  return nullptr;
+}
+
+clang::RecordDecl *TypeSystemClang::GetAsRecordDecl(const CompilerType &type) {
+  const clang::RecordType *record_type =
+      llvm::dyn_cast<clang::RecordType>(ClangUtil::GetCanonicalQualType(type));
+  if (record_type)
+    return record_type->getDecl();
+  return nullptr;
+}
+
+clang::TagDecl *TypeSystemClang::GetAsTagDecl(const CompilerType &type) {
+  return ClangUtil::GetAsTagDecl(type);
+}
+
+clang::TypedefNameDecl *
+TypeSystemClang::GetAsTypedefDecl(const CompilerType &type) {
+  const clang::TypedefType *typedef_type =
+      llvm::dyn_cast<clang::TypedefType>(ClangUtil::GetQualType(type));
+  if (typedef_type)
+    return typedef_type->getDecl();
+  return nullptr;
+}
+
+clang::CXXRecordDecl *
+TypeSystemClang::GetAsCXXRecordDecl(lldb::opaque_compiler_type_t type) {
+  return GetCanonicalQualType(type)->getAsCXXRecordDecl();
+}
+
+clang::ObjCInterfaceDecl *
+TypeSystemClang::GetAsObjCInterfaceDecl(const CompilerType &type) {
+  const clang::ObjCObjectType *objc_class_type =
+      llvm::dyn_cast<clang::ObjCObjectType>(
+          ClangUtil::GetCanonicalQualType(type));
+  if (objc_class_type)
+    return objc_class_type->getInterface();
+  return nullptr;
+}
+
+clang::FieldDecl *TypeSystemClang::AddFieldToRecordType(
+    const CompilerType &type, llvm::StringRef name,
+    const CompilerType &field_clang_type, AccessType access,
+    uint32_t bitfield_bit_size) {
+  if (!type.IsValid() || !field_clang_type.IsValid())
+    return nullptr;
+  TypeSystemClang *ast =
+      llvm::dyn_cast_or_null<TypeSystemClang>(type.GetTypeSystem());
+  if (!ast)
+    return nullptr;
+  clang::ASTContext &clang_ast = ast->getASTContext();
+  clang::IdentifierInfo *ident = nullptr;
+  if (!name.empty())
+    ident = &clang_ast.Idents.get(name);
+
+  clang::FieldDecl *field = nullptr;
+
+  clang::Expr *bit_width = nullptr;
+  if (bitfield_bit_size != 0) {
+    llvm::APInt bitfield_bit_size_apint(clang_ast.getTypeSize(clang_ast.IntTy),
+                                        bitfield_bit_size);
+    bit_width = new (clang_ast)
+        clang::IntegerLiteral(clang_ast, bitfield_bit_size_apint,
+                              clang_ast.IntTy, clang::SourceLocation());
+  }
+
+  clang::RecordDecl *record_decl = ast->GetAsRecordDecl(type);
+  if (record_decl) {
+    field = clang::FieldDecl::Create(
+        clang_ast, record_decl, clang::SourceLocation(),
+        clang::SourceLocation(),
+        ident,                                    // Identifier
+        ClangUtil::GetQualType(field_clang_type), // Field type
+        nullptr,                                  // TInfo *
+        bit_width,                                // BitWidth
+        false,                                    // Mutable
+        clang::ICIS_NoInit);                      // HasInit
+
+    if (name.empty()) {
+      // Determine whether this field corresponds to an anonymous struct or
+      // union.
+      if (const clang::TagType *TagT =
+              field->getType()->getAs<clang::TagType>()) {
+        if (clang::RecordDecl *Rec =
+                llvm::dyn_cast<clang::RecordDecl>(TagT->getDecl()))
+          if (!Rec->getDeclName()) {
+            Rec->setAnonymousStructOrUnion(true);
+            field->setImplicit();
+          }
+      }
+    }
+
+    if (field) {
+      field->setAccess(
+          TypeSystemClang::ConvertAccessTypeToAccessSpecifier(access));
+
+      record_decl->addDecl(field);
+
+#ifdef LLDB_CONFIGURATION_DEBUG
+      VerifyDecl(field);
+#endif
+    }
+  } else {
+    clang::ObjCInterfaceDecl *class_interface_decl =
+        ast->GetAsObjCInterfaceDecl(type);
+
+    if (class_interface_decl) {
+      const bool is_synthesized = false;
+
+      field_clang_type.GetCompleteType();
+
+      field = clang::ObjCIvarDecl::Create(
+          clang_ast, class_interface_decl, clang::SourceLocation(),
+          clang::SourceLocation(),
+          ident,                                    // Identifier
+          ClangUtil::GetQualType(field_clang_type), // Field type
+          nullptr,                                  // TypeSourceInfo *
+          ConvertAccessTypeToObjCIvarAccessControl(access), bit_width,
+          is_synthesized);
+
+      if (field) {
+        class_interface_decl->addDecl(field);
+
+#ifdef LLDB_CONFIGURATION_DEBUG
+        VerifyDecl(field);
+#endif
+      }
+    }
+  }
+  return field;
+}
+
+void TypeSystemClang::BuildIndirectFields(const CompilerType &type) {
+  if (!type)
+    return;
+
+  TypeSystemClang *ast = llvm::dyn_cast<TypeSystemClang>(type.GetTypeSystem());
+  if (!ast)
+    return;
+
+  clang::RecordDecl *record_decl = ast->GetAsRecordDecl(type);
+
+  if (!record_decl)
+    return;
+
+  typedef llvm::SmallVector<clang::IndirectFieldDecl *, 1> IndirectFieldVector;
+
+  IndirectFieldVector indirect_fields;
+  clang::RecordDecl::field_iterator field_pos;
+  clang::RecordDecl::field_iterator field_end_pos = record_decl->field_end();
+  clang::RecordDecl::field_iterator last_field_pos = field_end_pos;
+  for (field_pos = record_decl->field_begin(); field_pos != field_end_pos;
+       last_field_pos = field_pos++) {
+    if (field_pos->isAnonymousStructOrUnion()) {
+      clang::QualType field_qual_type = field_pos->getType();
+
+      const clang::RecordType *field_record_type =
+          field_qual_type->getAs<clang::RecordType>();
+
+      if (!field_record_type)
+        continue;
+
+      clang::RecordDecl *field_record_decl = field_record_type->getDecl();
+
+      if (!field_record_decl)
+        continue;
+
+      for (clang::RecordDecl::decl_iterator
+               di = field_record_decl->decls_begin(),
+               de = field_record_decl->decls_end();
+           di != de; ++di) {
+        if (clang::FieldDecl *nested_field_decl =
+                llvm::dyn_cast<clang::FieldDecl>(*di)) {
+          clang::NamedDecl **chain =
+              new (ast->getASTContext()) clang::NamedDecl *[2];
+          chain[0] = *field_pos;
+          chain[1] = nested_field_decl;
+          clang::IndirectFieldDecl *indirect_field =
+              clang::IndirectFieldDecl::Create(
+                  ast->getASTContext(), record_decl, clang::SourceLocation(),
+                  nested_field_decl->getIdentifier(),
+                  nested_field_decl->getType(), {chain, 2});
+
+          indirect_field->setImplicit();
+
+          indirect_field->setAccess(TypeSystemClang::UnifyAccessSpecifiers(
+              field_pos->getAccess(), nested_field_decl->getAccess()));
+
+          indirect_fields.push_back(indirect_field);
+        } else if (clang::IndirectFieldDecl *nested_indirect_field_decl =
+                       llvm::dyn_cast<clang::IndirectFieldDecl>(*di)) {
+          size_t nested_chain_size =
+              nested_indirect_field_decl->getChainingSize();
+          clang::NamedDecl **chain = new (ast->getASTContext())
+              clang::NamedDecl *[nested_chain_size + 1];
+          chain[0] = *field_pos;
+
+          int chain_index = 1;
+          for (clang::IndirectFieldDecl::chain_iterator
+                   nci = nested_indirect_field_decl->chain_begin(),
+                   nce = nested_indirect_field_decl->chain_end();
+               nci < nce; ++nci) {
+            chain[chain_index] = *nci;
+            chain_index++;
+          }
+
+          clang::IndirectFieldDecl *indirect_field =
+              clang::IndirectFieldDecl::Create(
+                  ast->getASTContext(), record_decl, clang::SourceLocation(),
+                  nested_indirect_field_decl->getIdentifier(),
+                  nested_indirect_field_decl->getType(),
+                  {chain, nested_chain_size + 1});
+
+          indirect_field->setImplicit();
+
+          indirect_field->setAccess(TypeSystemClang::UnifyAccessSpecifiers(
+              field_pos->getAccess(), nested_indirect_field_decl->getAccess()));
+
+          indirect_fields.push_back(indirect_field);
+        }
+      }
+    }
+  }
+
+  // Check the last field to see if it has an incomplete array type as its last
+  // member and if it does, the tell the record decl about it
+  if (last_field_pos != field_end_pos) {
+    if (last_field_pos->getType()->isIncompleteArrayType())
+      record_decl->hasFlexibleArrayMember();
+  }
+
+  for (IndirectFieldVector::iterator ifi = indirect_fields.begin(),
+                                     ife = indirect_fields.end();
+       ifi < ife; ++ifi) {
+    record_decl->addDecl(*ifi);
+  }
+}
+
+void TypeSystemClang::SetIsPacked(const CompilerType &type) {
+  if (type) {
+    TypeSystemClang *ast =
+        llvm::dyn_cast<TypeSystemClang>(type.GetTypeSystem());
+    if (ast) {
+      clang::RecordDecl *record_decl = GetAsRecordDecl(type);
+
+      if (!record_decl)
+        return;
+
+      record_decl->addAttr(
+          clang::PackedAttr::CreateImplicit(ast->getASTContext()));
+    }
+  }
+}
+
+clang::VarDecl *TypeSystemClang::AddVariableToRecordType(
+    const CompilerType &type, llvm::StringRef name,
+    const CompilerType &var_type, AccessType access) {
+  if (!type.IsValid() || !var_type.IsValid())
+    return nullptr;
+
+  TypeSystemClang *ast = llvm::dyn_cast<TypeSystemClang>(type.GetTypeSystem());
+  if (!ast)
+    return nullptr;
+
+  clang::RecordDecl *record_decl = ast->GetAsRecordDecl(type);
+  if (!record_decl)
+    return nullptr;
+
+  clang::VarDecl *var_decl = nullptr;
+  clang::IdentifierInfo *ident = nullptr;
+  if (!name.empty())
+    ident = &ast->getASTContext().Idents.get(name);
+
+  var_decl = clang::VarDecl::Create(
+      ast->getASTContext(),             // ASTContext &
+      record_decl,                      // DeclContext *
+      clang::SourceLocation(),          // clang::SourceLocation StartLoc
+      clang::SourceLocation(),          // clang::SourceLocation IdLoc
+      ident,                            // clang::IdentifierInfo *
+      ClangUtil::GetQualType(var_type), // Variable clang::QualType
+      nullptr,                          // TypeSourceInfo *
+      clang::SC_Static);                // StorageClass
+  if (!var_decl)
+    return nullptr;
+
+  var_decl->setAccess(
+      TypeSystemClang::ConvertAccessTypeToAccessSpecifier(access));
+  record_decl->addDecl(var_decl);
+
+#ifdef LLDB_CONFIGURATION_DEBUG
+  VerifyDecl(var_decl);
+#endif
+
+  return var_decl;
+}
+
+clang::CXXMethodDecl *TypeSystemClang::AddMethodToCXXRecordType(
+    lldb::opaque_compiler_type_t type, llvm::StringRef name,
+    const char *mangled_name, const CompilerType &method_clang_type,
+    lldb::AccessType access, bool is_virtual, bool is_static, bool is_inline,
+    bool is_explicit, bool is_attr_used, bool is_artificial) {
+  if (!type || !method_clang_type.IsValid() || name.empty())
+    return nullptr;
+
+  clang::QualType record_qual_type(GetCanonicalQualType(type));
+
+  clang::CXXRecordDecl *cxx_record_decl =
+      record_qual_type->getAsCXXRecordDecl();
+
+  if (cxx_record_decl == nullptr)
+    return nullptr;
+
+  clang::QualType method_qual_type(ClangUtil::GetQualType(method_clang_type));
+
+  clang::CXXMethodDecl *cxx_method_decl = nullptr;
+
+  clang::DeclarationName decl_name(&getASTContext().Idents.get(name));
+
+  const clang::FunctionType *function_type =
+      llvm::dyn_cast<clang::FunctionType>(method_qual_type.getTypePtr());
+
+  if (function_type == nullptr)
+    return nullptr;
+
+  const clang::FunctionProtoType *method_function_prototype(
+      llvm::dyn_cast<clang::FunctionProtoType>(function_type));
+
+  if (!method_function_prototype)
+    return nullptr;
+
+  unsigned int num_params = method_function_prototype->getNumParams();
+
+  clang::CXXDestructorDecl *cxx_dtor_decl(nullptr);
+  clang::CXXConstructorDecl *cxx_ctor_decl(nullptr);
+
+  if (is_artificial)
+    return nullptr; // skip everything artificial
+
+  const clang::ExplicitSpecifier explicit_spec(
+      nullptr /*expr*/, is_explicit
+                            ? clang::ExplicitSpecKind::ResolvedTrue
+                            : clang::ExplicitSpecKind::ResolvedFalse);
+  if (name.startswith("~")) {
+    cxx_dtor_decl = clang::CXXDestructorDecl::Create(
+        getASTContext(), cxx_record_decl, clang::SourceLocation(),
+        clang::DeclarationNameInfo(
+            getASTContext().DeclarationNames.getCXXDestructorName(
+                getASTContext().getCanonicalType(record_qual_type)),
+            clang::SourceLocation()),
+        method_qual_type, nullptr, is_inline, is_artificial,
+        ConstexprSpecKind::CSK_unspecified);
+    cxx_method_decl = cxx_dtor_decl;
+  } else if (decl_name == cxx_record_decl->getDeclName()) {
+    cxx_ctor_decl = clang::CXXConstructorDecl::Create(
+        getASTContext(), cxx_record_decl, clang::SourceLocation(),
+        clang::DeclarationNameInfo(
+            getASTContext().DeclarationNames.getCXXConstructorName(
+                getASTContext().getCanonicalType(record_qual_type)),
+            clang::SourceLocation()),
+        method_qual_type,
+        nullptr, // TypeSourceInfo *
+        explicit_spec, is_inline, is_artificial, CSK_unspecified);
+    cxx_method_decl = cxx_ctor_decl;
+  } else {
+    clang::StorageClass SC = is_static ? clang::SC_Static : clang::SC_None;
+    clang::OverloadedOperatorKind op_kind = clang::NUM_OVERLOADED_OPERATORS;
+
+    if (IsOperator(name, op_kind)) {
+      if (op_kind != clang::NUM_OVERLOADED_OPERATORS) {
+        // Check the number of operator parameters. Sometimes we have seen bad
+        // DWARF that doesn't correctly describe operators and if we try to
+        // create a method and add it to the class, clang will assert and
+        // crash, so we need to make sure things are acceptable.
+        const bool is_method = true;
+        if (!TypeSystemClang::CheckOverloadedOperatorKindParameterCount(
+                is_method, op_kind, num_params))
+          return nullptr;
+        cxx_method_decl = clang::CXXMethodDecl::Create(
+            getASTContext(), cxx_record_decl, clang::SourceLocation(),
+            clang::DeclarationNameInfo(
+                getASTContext().DeclarationNames.getCXXOperatorName(op_kind),
+                clang::SourceLocation()),
+            method_qual_type,
+            nullptr, // TypeSourceInfo *
+            SC, is_inline, CSK_unspecified, clang::SourceLocation());
+      } else if (num_params == 0) {
+        // Conversion operators don't take params...
+        cxx_method_decl = clang::CXXConversionDecl::Create(
+            getASTContext(), cxx_record_decl, clang::SourceLocation(),
+            clang::DeclarationNameInfo(
+                getASTContext().DeclarationNames.getCXXConversionFunctionName(
+                    getASTContext().getCanonicalType(
+                        function_type->getReturnType())),
+                clang::SourceLocation()),
+            method_qual_type,
+            nullptr, // TypeSourceInfo *
+            is_inline, explicit_spec, CSK_unspecified, clang::SourceLocation());
+      }
+    }
+
+    if (cxx_method_decl == nullptr) {
+      cxx_method_decl = clang::CXXMethodDecl::Create(
+          getASTContext(), cxx_record_decl, clang::SourceLocation(),
+          clang::DeclarationNameInfo(decl_name, clang::SourceLocation()),
+          method_qual_type,
+          nullptr, // TypeSourceInfo *
+          SC, is_inline, CSK_unspecified, clang::SourceLocation());
+    }
+  }
+
+  clang::AccessSpecifier access_specifier =
+      TypeSystemClang::ConvertAccessTypeToAccessSpecifier(access);
+
+  cxx_method_decl->setAccess(access_specifier);
+  cxx_method_decl->setVirtualAsWritten(is_virtual);
+
+  if (is_attr_used)
+    cxx_method_decl->addAttr(clang::UsedAttr::CreateImplicit(getASTContext()));
+
+  if (mangled_name != nullptr) {
+    cxx_method_decl->addAttr(clang::AsmLabelAttr::CreateImplicit(
+        getASTContext(), mangled_name, /*literal=*/false));
+  }
+
+  // Populate the method decl with parameter decls
+
+  llvm::SmallVector<clang::ParmVarDecl *, 12> params;
+
+  for (unsigned param_index = 0; param_index < num_params; ++param_index) {
+    params.push_back(clang::ParmVarDecl::Create(
+        getASTContext(), cxx_method_decl, clang::SourceLocation(),
+        clang::SourceLocation(),
+        nullptr, // anonymous
+        method_function_prototype->getParamType(param_index), nullptr,
+        clang::SC_None, nullptr));
+  }
+
+  cxx_method_decl->setParams(llvm::ArrayRef<clang::ParmVarDecl *>(params));
+
+  cxx_record_decl->addDecl(cxx_method_decl);
+
+  // Sometimes the debug info will mention a constructor (default/copy/move),
+  // destructor, or assignment operator (copy/move) but there won't be any
+  // version of this in the code. So we check if the function was artificially
+  // generated and if it is trivial and this lets the compiler/backend know
+  // that it can inline the IR for these when it needs to and we can avoid a
+  // "missing function" error when running expressions.
+
+  if (is_artificial) {
+    if (cxx_ctor_decl && ((cxx_ctor_decl->isDefaultConstructor() &&
+                           cxx_record_decl->hasTrivialDefaultConstructor()) ||
+                          (cxx_ctor_decl->isCopyConstructor() &&
+                           cxx_record_decl->hasTrivialCopyConstructor()) ||
+                          (cxx_ctor_decl->isMoveConstructor() &&
+                           cxx_record_decl->hasTrivialMoveConstructor()))) {
+      cxx_ctor_decl->setDefaulted();
+      cxx_ctor_decl->setTrivial(true);
+    } else if (cxx_dtor_decl) {
+      if (cxx_record_decl->hasTrivialDestructor()) {
+        cxx_dtor_decl->setDefaulted();
+        cxx_dtor_decl->setTrivial(true);
+      }
+    } else if ((cxx_method_decl->isCopyAssignmentOperator() &&
+                cxx_record_decl->hasTrivialCopyAssignment()) ||
+               (cxx_method_decl->isMoveAssignmentOperator() &&
+                cxx_record_decl->hasTrivialMoveAssignment())) {
+      cxx_method_decl->setDefaulted();
+      cxx_method_decl->setTrivial(true);
+    }
+  }
+
+#ifdef LLDB_CONFIGURATION_DEBUG
+  VerifyDecl(cxx_method_decl);
+#endif
+
+  return cxx_method_decl;
+}
+
+void TypeSystemClang::AddMethodOverridesForCXXRecordType(
+    lldb::opaque_compiler_type_t type) {
+  if (auto *record = GetAsCXXRecordDecl(type))
+    for (auto *method : record->methods())
+      addOverridesForMethod(method);
+}
+
+#pragma mark C++ Base Classes
+
+std::unique_ptr<clang::CXXBaseSpecifier>
+TypeSystemClang::CreateBaseClassSpecifier(lldb::opaque_compiler_type_t type,
+                                          AccessType access, bool is_virtual,
+                                          bool base_of_class) {
+  if (!type)
+    return nullptr;
+
+  return std::make_unique<clang::CXXBaseSpecifier>(
+      clang::SourceRange(), is_virtual, base_of_class,
+      TypeSystemClang::ConvertAccessTypeToAccessSpecifier(access),
+      getASTContext().getTrivialTypeSourceInfo(GetQualType(type)),
+      clang::SourceLocation());
+}
+
+bool TypeSystemClang::TransferBaseClasses(
+    lldb::opaque_compiler_type_t type,
+    std::vector<std::unique_ptr<clang::CXXBaseSpecifier>> bases) {
+  if (!type)
+    return false;
+  clang::CXXRecordDecl *cxx_record_decl = GetAsCXXRecordDecl(type);
+  if (!cxx_record_decl)
+    return false;
+  std::vector<clang::CXXBaseSpecifier *> raw_bases;
+  raw_bases.reserve(bases.size());
+
+  // Clang will make a copy of them, so it's ok that we pass pointers that we're
+  // about to destroy.
+  for (auto &b : bases)
+    raw_bases.push_back(b.get());
+  cxx_record_decl->setBases(raw_bases.data(), raw_bases.size());
+  return true;
+}
+
+bool TypeSystemClang::SetObjCSuperClass(
+    const CompilerType &type, const CompilerType &superclass_clang_type) {
+  TypeSystemClang *ast =
+      llvm::dyn_cast_or_null<TypeSystemClang>(type.GetTypeSystem());
+  if (!ast)
+    return false;
+  clang::ASTContext &clang_ast = ast->getASTContext();
+
+  if (type && superclass_clang_type.IsValid() &&
+      superclass_clang_type.GetTypeSystem() == type.GetTypeSystem()) {
+    clang::ObjCInterfaceDecl *class_interface_decl =
+        GetAsObjCInterfaceDecl(type);
+    clang::ObjCInterfaceDecl *super_interface_decl =
+        GetAsObjCInterfaceDecl(superclass_clang_type);
+    if (class_interface_decl && super_interface_decl) {
+      class_interface_decl->setSuperClass(clang_ast.getTrivialTypeSourceInfo(
+          clang_ast.getObjCInterfaceType(super_interface_decl)));
+      return true;
+    }
+  }
+  return false;
+}
+
+bool TypeSystemClang::AddObjCClassProperty(
+    const CompilerType &type, const char *property_name,
+    const CompilerType &property_clang_type, clang::ObjCIvarDecl *ivar_decl,
+    const char *property_setter_name, const char *property_getter_name,
+    uint32_t property_attributes, ClangASTMetadata *metadata) {
+  if (!type || !property_clang_type.IsValid() || property_name == nullptr ||
+      property_name[0] == '\0')
+    return false;
+  TypeSystemClang *ast = llvm::dyn_cast<TypeSystemClang>(type.GetTypeSystem());
+  if (!ast)
+    return false;
+  clang::ASTContext &clang_ast = ast->getASTContext();
+
+  clang::ObjCInterfaceDecl *class_interface_decl = GetAsObjCInterfaceDecl(type);
+  if (!class_interface_decl)
+    return false;
+
+  CompilerType property_clang_type_to_access;
+
+  if (property_clang_type.IsValid())
+    property_clang_type_to_access = property_clang_type;
+  else if (ivar_decl)
+    property_clang_type_to_access = ast->GetType(ivar_decl->getType());
+
+  if (!class_interface_decl || !property_clang_type_to_access.IsValid())
+    return false;
+
+  clang::TypeSourceInfo *prop_type_source;
+  if (ivar_decl)
+    prop_type_source = clang_ast.getTrivialTypeSourceInfo(ivar_decl->getType());
+  else
+    prop_type_source = clang_ast.getTrivialTypeSourceInfo(
+        ClangUtil::GetQualType(property_clang_type));
+
+  clang::ObjCPropertyDecl *property_decl = clang::ObjCPropertyDecl::Create(
+      clang_ast, class_interface_decl,
+      clang::SourceLocation(), // Source Location
+      &clang_ast.Idents.get(property_name),
+      clang::SourceLocation(), // Source Location for AT
+      clang::SourceLocation(), // Source location for (
+      ivar_decl ? ivar_decl->getType()
+                : ClangUtil::GetQualType(property_clang_type),
+      prop_type_source);
+
+  if (!property_decl)
+    return false;
+
+  if (metadata)
+    ast->SetMetadata(property_decl, *metadata);
+
+  class_interface_decl->addDecl(property_decl);
+
+  clang::Selector setter_sel, getter_sel;
+
+  if (property_setter_name) {
+    std::string property_setter_no_colon(property_setter_name,
+                                         strlen(property_setter_name) - 1);
+    clang::IdentifierInfo *setter_ident =
+        &clang_ast.Idents.get(property_setter_no_colon);
+    setter_sel = clang_ast.Selectors.getSelector(1, &setter_ident);
+  } else if (!(property_attributes & DW_APPLE_PROPERTY_readonly)) {
+    std::string setter_sel_string("set");
+    setter_sel_string.push_back(::toupper(property_name[0]));
+    setter_sel_string.append(&property_name[1]);
+    clang::IdentifierInfo *setter_ident =
+        &clang_ast.Idents.get(setter_sel_string);
+    setter_sel = clang_ast.Selectors.getSelector(1, &setter_ident);
+  }
+  property_decl->setSetterName(setter_sel);
+  property_decl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_setter);
+
+  if (property_getter_name != nullptr) {
+    clang::IdentifierInfo *getter_ident =
+        &clang_ast.Idents.get(property_getter_name);
+    getter_sel = clang_ast.Selectors.getSelector(0, &getter_ident);
+  } else {
+    clang::IdentifierInfo *getter_ident = &clang_ast.Idents.get(property_name);
+    getter_sel = clang_ast.Selectors.getSelector(0, &getter_ident);
+  }
+  property_decl->setGetterName(getter_sel);
+  property_decl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_getter);
+
+  if (ivar_decl)
+    property_decl->setPropertyIvarDecl(ivar_decl);
+
+  if (property_attributes & DW_APPLE_PROPERTY_readonly)
+    property_decl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_readonly);
+  if (property_attributes & DW_APPLE_PROPERTY_readwrite)
+    property_decl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_readwrite);
+  if (property_attributes & DW_APPLE_PROPERTY_assign)
+    property_decl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_assign);
+  if (property_attributes & DW_APPLE_PROPERTY_retain)
+    property_decl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_retain);
+  if (property_attributes & DW_APPLE_PROPERTY_copy)
+    property_decl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_copy);
+  if (property_attributes & DW_APPLE_PROPERTY_nonatomic)
+    property_decl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_nonatomic);
+  if (property_attributes & ObjCPropertyDecl::OBJC_PR_nullability)
+    property_decl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_nullability);
+  if (property_attributes & ObjCPropertyDecl::OBJC_PR_null_resettable)
+    property_decl->setPropertyAttributes(
+        ObjCPropertyDecl::OBJC_PR_null_resettable);
+  if (property_attributes & ObjCPropertyDecl::OBJC_PR_class)
+    property_decl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_class);
+
+  const bool isInstance =
+      (property_attributes & ObjCPropertyDecl::OBJC_PR_class) == 0;
+
+  clang::ObjCMethodDecl *getter = nullptr;
+  if (!getter_sel.isNull())
+    getter = isInstance ? class_interface_decl->lookupInstanceMethod(getter_sel)
+                        : class_interface_decl->lookupClassMethod(getter_sel);
+  if (!getter_sel.isNull() && !getter) {
+    const bool isVariadic = false;
+    const bool isPropertyAccessor = false;
+    const bool isSynthesizedAccessorStub = false;
+    const bool isImplicitlyDeclared = true;
+    const bool isDefined = false;
+    const clang::ObjCMethodDecl::ImplementationControl impControl =
+        clang::ObjCMethodDecl::None;
+    const bool HasRelatedResultType = false;
+
+    getter = clang::ObjCMethodDecl::Create(
+        clang_ast, clang::SourceLocation(), clang::SourceLocation(), getter_sel,
+        ClangUtil::GetQualType(property_clang_type_to_access), nullptr,
+        class_interface_decl, isInstance, isVariadic, isPropertyAccessor,
+        isSynthesizedAccessorStub, isImplicitlyDeclared, isDefined, impControl,
+        HasRelatedResultType);
+
+    if (getter) {
+      if (metadata)
+        ast->SetMetadata(getter, *metadata);
+
+      getter->setMethodParams(clang_ast, llvm::ArrayRef<clang::ParmVarDecl *>(),
+                              llvm::ArrayRef<clang::SourceLocation>());
+      class_interface_decl->addDecl(getter);
+    }
+  }
+  if (getter) {
+    getter->setPropertyAccessor(true);
+    property_decl->setGetterMethodDecl(getter);
+  }
+
+  clang::ObjCMethodDecl *setter = nullptr;
+    setter = isInstance ? class_interface_decl->lookupInstanceMethod(setter_sel)
+                        : class_interface_decl->lookupClassMethod(setter_sel);
+  if (!setter_sel.isNull() && !setter) {
+    clang::QualType result_type = clang_ast.VoidTy;
+    const bool isVariadic = false;
+    const bool isPropertyAccessor = true;
+    const bool isSynthesizedAccessorStub = false;
+    const bool isImplicitlyDeclared = true;
+    const bool isDefined = false;
+    const clang::ObjCMethodDecl::ImplementationControl impControl =
+        clang::ObjCMethodDecl::None;
+    const bool HasRelatedResultType = false;
+
+    setter = clang::ObjCMethodDecl::Create(
+        clang_ast, clang::SourceLocation(), clang::SourceLocation(), setter_sel,
+        result_type, nullptr, class_interface_decl, isInstance, isVariadic,
+        isPropertyAccessor, isSynthesizedAccessorStub, isImplicitlyDeclared,
+        isDefined, impControl, HasRelatedResultType);
+
+    if (setter) {
+      if (metadata)
+        ast->SetMetadata(setter, *metadata);
+
+      llvm::SmallVector<clang::ParmVarDecl *, 1> params;
+      params.push_back(clang::ParmVarDecl::Create(
+          clang_ast, setter, clang::SourceLocation(), clang::SourceLocation(),
+          nullptr, // anonymous
+          ClangUtil::GetQualType(property_clang_type_to_access), nullptr,
+          clang::SC_Auto, nullptr));
+
+      setter->setMethodParams(clang_ast,
+                              llvm::ArrayRef<clang::ParmVarDecl *>(params),
+                              llvm::ArrayRef<clang::SourceLocation>());
+
+      class_interface_decl->addDecl(setter);
+    }
+  }
+  if (setter) {
+    setter->setPropertyAccessor(true);
+    property_decl->setSetterMethodDecl(setter);
+  }
+
+  return true;
+}
+
+bool TypeSystemClang::IsObjCClassTypeAndHasIVars(const CompilerType &type,
+                                                 bool check_superclass) {
+  clang::ObjCInterfaceDecl *class_interface_decl = GetAsObjCInterfaceDecl(type);
+  if (class_interface_decl)
+    return ObjCDeclHasIVars(class_interface_decl, check_superclass);
+  return false;
+}
+
+clang::ObjCMethodDecl *TypeSystemClang::AddMethodToObjCObjectType(
+    const CompilerType &type,
+    const char *name, // the full symbol name as seen in the symbol table
+                      // (lldb::opaque_compiler_type_t type, "-[NString
+                      // stringWithCString:]")
+    const CompilerType &method_clang_type, lldb::AccessType access,
+    bool is_artificial, bool is_variadic, bool is_objc_direct_call) {
+  if (!type || !method_clang_type.IsValid())
+    return nullptr;
+
+  clang::ObjCInterfaceDecl *class_interface_decl = GetAsObjCInterfaceDecl(type);
+
+  if (class_interface_decl == nullptr)
+    return nullptr;
+  TypeSystemClang *lldb_ast =
+      llvm::dyn_cast<TypeSystemClang>(type.GetTypeSystem());
+  if (lldb_ast == nullptr)
+    return nullptr;
+  clang::ASTContext &ast = lldb_ast->getASTContext();
+
+  const char *selector_start = ::strchr(name, ' ');
+  if (selector_start == nullptr)
+    return nullptr;
+
+  selector_start++;
+  llvm::SmallVector<clang::IdentifierInfo *, 12> selector_idents;
+
+  size_t len = 0;
+  const char *start;
+  // printf ("name = '%s'\n", name);
+
+  unsigned num_selectors_with_args = 0;
+  for (start = selector_start; start && *start != '\0' && *start != ']';
+       start += len) {
+    len = ::strcspn(start, ":]");
+    bool has_arg = (start[len] == ':');
+    if (has_arg)
+      ++num_selectors_with_args;
+    selector_idents.push_back(&ast.Idents.get(llvm::StringRef(start, len)));
+    if (has_arg)
+      len += 1;
+  }
+
+  if (selector_idents.size() == 0)
+    return nullptr;
+
+  clang::Selector method_selector = ast.Selectors.getSelector(
+      num_selectors_with_args ? selector_idents.size() : 0,
+      selector_idents.data());
+
+  clang::QualType method_qual_type(ClangUtil::GetQualType(method_clang_type));
+
+  // Populate the method decl with parameter decls
+  const clang::Type *method_type(method_qual_type.getTypePtr());
+
+  if (method_type == nullptr)
+    return nullptr;
+
+  const clang::FunctionProtoType *method_function_prototype(
+      llvm::dyn_cast<clang::FunctionProtoType>(method_type));
+
+  if (!method_function_prototype)
+    return nullptr;
+
+  const bool isInstance = (name[0] == '-');
+  const bool isVariadic = is_variadic;
+  const bool isPropertyAccessor = false;
+  const bool isSynthesizedAccessorStub = false;
+  /// Force this to true because we don't have source locations.
+  const bool isImplicitlyDeclared = true;
+  const bool isDefined = false;
+  const clang::ObjCMethodDecl::ImplementationControl impControl =
+      clang::ObjCMethodDecl::None;
+  const bool HasRelatedResultType = false;
+
+  const unsigned num_args = method_function_prototype->getNumParams();
+
+  if (num_args != num_selectors_with_args)
+    return nullptr; // some debug information is corrupt.  We are not going to
+                    // deal with it.
+
+  clang::ObjCMethodDecl *objc_method_decl = clang::ObjCMethodDecl::Create(
+      ast,
+      clang::SourceLocation(), // beginLoc,
+      clang::SourceLocation(), // endLoc,
+      method_selector, method_function_prototype->getReturnType(),
+      nullptr, // TypeSourceInfo *ResultTInfo,
+      lldb_ast->GetDeclContextForType(ClangUtil::GetQualType(type)), isInstance,
+      isVariadic, isPropertyAccessor, isSynthesizedAccessorStub,
+      isImplicitlyDeclared, isDefined, impControl, HasRelatedResultType);
+
+  if (objc_method_decl == nullptr)
+    return nullptr;
+
+  if (num_args > 0) {
+    llvm::SmallVector<clang::ParmVarDecl *, 12> params;
+
+    for (unsigned param_index = 0; param_index < num_args; ++param_index) {
+      params.push_back(clang::ParmVarDecl::Create(
+          ast, objc_method_decl, clang::SourceLocation(),
+          clang::SourceLocation(),
+          nullptr, // anonymous
+          method_function_prototype->getParamType(param_index), nullptr,
+          clang::SC_Auto, nullptr));
+    }
+
+    objc_method_decl->setMethodParams(
+        ast, llvm::ArrayRef<clang::ParmVarDecl *>(params),
+        llvm::ArrayRef<clang::SourceLocation>());
+  }
+
+  if (is_objc_direct_call) {
+    // Add a the objc_direct attribute to the declaration we generate that
+    // we generate a direct method call for this ObjCMethodDecl.
+    objc_method_decl->addAttr(
+        clang::ObjCDirectAttr::CreateImplicit(ast, SourceLocation()));
+    // Usually Sema is creating implicit parameters (e.g., self) when it
+    // parses the method. We don't have a parsing Sema when we build our own
+    // AST here so we manually need to create these implicit parameters to
+    // make the direct call code generation happy.
+    objc_method_decl->createImplicitParams(ast, class_interface_decl);
+  }
+
+  class_interface_decl->addDecl(objc_method_decl);
+
+#ifdef LLDB_CONFIGURATION_DEBUG
+  VerifyDecl(objc_method_decl);
+#endif
+
+  return objc_method_decl;
+}
+
+bool TypeSystemClang::SetHasExternalStorage(lldb::opaque_compiler_type_t type,
+                                            bool has_extern) {
+  if (!type)
+    return false;
+
+  clang::QualType qual_type(RemoveWrappingTypes(GetCanonicalQualType(type)));
+
+  const clang::Type::TypeClass type_class = qual_type->getTypeClass();
+  switch (type_class) {
+  case clang::Type::Record: {
+    clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl();
+    if (cxx_record_decl) {
+      cxx_record_decl->setHasExternalLexicalStorage(has_extern);
+      cxx_record_decl->setHasExternalVisibleStorage(has_extern);
+      return true;
+    }
+  } break;
+
+  case clang::Type::Enum: {
+    clang::EnumDecl *enum_decl =
+        llvm::cast<clang::EnumType>(qual_type)->getDecl();
+    if (enum_decl) {
+      enum_decl->setHasExternalLexicalStorage(has_extern);
+      enum_decl->setHasExternalVisibleStorage(has_extern);
+      return true;
+    }
+  } break;
+
+  case clang::Type::ObjCObject:
+  case clang::Type::ObjCInterface: {
+    const clang::ObjCObjectType *objc_class_type =
+        llvm::dyn_cast<clang::ObjCObjectType>(qual_type.getTypePtr());
+    assert(objc_class_type);
+    if (objc_class_type) {
+      clang::ObjCInterfaceDecl *class_interface_decl =
+          objc_class_type->getInterface();
+
+      if (class_interface_decl) {
+        class_interface_decl->setHasExternalLexicalStorage(has_extern);
+        class_interface_decl->setHasExternalVisibleStorage(has_extern);
+        return true;
+      }
+    }
+  } break;
+
+  default:
+    break;
+  }
+  return false;
+}
+
+#pragma mark TagDecl
+
+bool TypeSystemClang::StartTagDeclarationDefinition(const CompilerType &type) {
+  clang::QualType qual_type(ClangUtil::GetQualType(type));
+  if (!qual_type.isNull()) {
+    const clang::TagType *tag_type = qual_type->getAs<clang::TagType>();
+    if (tag_type) {
+      clang::TagDecl *tag_decl = tag_type->getDecl();
+      if (tag_decl) {
+        tag_decl->startDefinition();
+        return true;
+      }
+    }
+
+    const clang::ObjCObjectType *object_type =
+        qual_type->getAs<clang::ObjCObjectType>();
+    if (object_type) {
+      clang::ObjCInterfaceDecl *interface_decl = object_type->getInterface();
+      if (interface_decl) {
+        interface_decl->startDefinition();
+        return true;
+      }
+    }
+  }
+  return false;
+}
+
+bool TypeSystemClang::CompleteTagDeclarationDefinition(
+    const CompilerType &type) {
+  clang::QualType qual_type(ClangUtil::GetQualType(type));
+  if (qual_type.isNull())
+    return false;
+
+  // Make sure we use the same methodology as
+  // TypeSystemClang::StartTagDeclarationDefinition() as to how we start/end
+  // the definition.
+  const clang::TagType *tag_type = qual_type->getAs<clang::TagType>();
+  if (tag_type) {
+    clang::TagDecl *tag_decl = tag_type->getDecl();
+
+    if (auto *cxx_record_decl = llvm::dyn_cast<CXXRecordDecl>(tag_decl)) {
+      // If we have a move constructor declared but no copy constructor we
+      // need to explicitly mark it as deleted. Usually Sema would do this for
+      // us in Sema::DeclareImplicitCopyConstructor but we don't have a Sema
+      // when building an AST from debug information.
+      // See also:
+      // C++11 [class.copy]p7, p18:
+      //  If the class definition declares a move constructor or move assignment
+      //  operator, an implicitly declared copy constructor or copy assignment
+      //  operator is defined as deleted.
+      if (cxx_record_decl->hasUserDeclaredMoveConstructor() &&
+          cxx_record_decl->needsImplicitCopyConstructor())
+        cxx_record_decl->setImplicitCopyConstructorIsDeleted();
+
+      if (!cxx_record_decl->isCompleteDefinition())
+        cxx_record_decl->completeDefinition();
+      cxx_record_decl->setHasLoadedFieldsFromExternalStorage(true);
+      cxx_record_decl->setHasExternalLexicalStorage(false);
+      cxx_record_decl->setHasExternalVisibleStorage(false);
+      return true;
+    }
+  }
+
+  const clang::EnumType *enutype = qual_type->getAs<clang::EnumType>();
+
+  if (!enutype)
+    return false;
+  clang::EnumDecl *enum_decl = enutype->getDecl();
+
+  if (enum_decl->isCompleteDefinition())
+    return true;
+
+  TypeSystemClang *lldb_ast =
+      llvm::dyn_cast<TypeSystemClang>(type.GetTypeSystem());
+  if (lldb_ast == nullptr)
+    return false;
+  clang::ASTContext &ast = lldb_ast->getASTContext();
+
+  /// TODO This really needs to be fixed.
+
+  QualType integer_type(enum_decl->getIntegerType());
+  if (!integer_type.isNull()) {
+    unsigned NumPositiveBits = 1;
+    unsigned NumNegativeBits = 0;
+
+    clang::QualType promotion_qual_type;
+    // If the enum integer type is less than an integer in bit width,
+    // then we must promote it to an integer size.
+    if (ast.getTypeSize(enum_decl->getIntegerType()) <
+        ast.getTypeSize(ast.IntTy)) {
+      if (enum_decl->getIntegerType()->isSignedIntegerType())
+        promotion_qual_type = ast.IntTy;
+      else
+        promotion_qual_type = ast.UnsignedIntTy;
+    } else
+      promotion_qual_type = enum_decl->getIntegerType();
+
+    enum_decl->completeDefinition(enum_decl->getIntegerType(),
+                                  promotion_qual_type, NumPositiveBits,
+                                  NumNegativeBits);
+  }
+  return true;
+}
+
+clang::EnumConstantDecl *TypeSystemClang::AddEnumerationValueToEnumerationType(
+    const CompilerType &enum_type, const Declaration &decl, const char *name,
+    const llvm::APSInt &value) {
+
+  if (!enum_type || ConstString(name).IsEmpty())
+    return nullptr;
+
+  lldbassert(enum_type.GetTypeSystem() == static_cast<TypeSystem *>(this));
+
+  lldb::opaque_compiler_type_t enum_opaque_compiler_type =
+      enum_type.GetOpaqueQualType();
+
+  if (!enum_opaque_compiler_type)
+    return nullptr;
+
+  clang::QualType enum_qual_type(
+      GetCanonicalQualType(enum_opaque_compiler_type));
+
+  const clang::Type *clang_type = enum_qual_type.getTypePtr();
+
+  if (!clang_type)
+    return nullptr;
+
+  const clang::EnumType *enutype = llvm::dyn_cast<clang::EnumType>(clang_type);
+
+  if (!enutype)
+    return nullptr;
+
+  clang::EnumConstantDecl *enumerator_decl = clang::EnumConstantDecl::Create(
+      getASTContext(), enutype->getDecl(), clang::SourceLocation(),
+      name ? &getASTContext().Idents.get(name) : nullptr, // Identifier
+      clang::QualType(enutype, 0), nullptr, value);
+
+  if (!enumerator_decl)
+    return nullptr;
+
+  enutype->getDecl()->addDecl(enumerator_decl);
+
+#ifdef LLDB_CONFIGURATION_DEBUG
+  VerifyDecl(enumerator_decl);
+#endif
+
+  return enumerator_decl;
+}
+
+clang::EnumConstantDecl *TypeSystemClang::AddEnumerationValueToEnumerationType(
+    const CompilerType &enum_type, const Declaration &decl, const char *name,
+    int64_t enum_value, uint32_t enum_value_bit_size) {
+  CompilerType underlying_type =
+      GetEnumerationIntegerType(enum_type.GetOpaqueQualType());
+  bool is_signed = false;
+  underlying_type.IsIntegerType(is_signed);
+
+  llvm::APSInt value(enum_value_bit_size, is_signed);
+  value = enum_value;
+
+  return AddEnumerationValueToEnumerationType(enum_type, decl, name, value);
+}
+
+CompilerType
+TypeSystemClang::GetEnumerationIntegerType(lldb::opaque_compiler_type_t type) {
+  clang::QualType enum_qual_type(GetCanonicalQualType(type));
+  const clang::Type *clang_type = enum_qual_type.getTypePtr();
+  if (clang_type) {
+    const clang::EnumType *enutype =
+        llvm::dyn_cast<clang::EnumType>(clang_type);
+    if (enutype) {
+      clang::EnumDecl *enum_decl = enutype->getDecl();
+      if (enum_decl)
+        return GetType(enum_decl->getIntegerType());
+    }
+  }
+  return CompilerType();
+}
+
+CompilerType
+TypeSystemClang::CreateMemberPointerType(const CompilerType &type,
+                                         const CompilerType &pointee_type) {
+  if (type && pointee_type.IsValid() &&
+      type.GetTypeSystem() == pointee_type.GetTypeSystem()) {
+    TypeSystemClang *ast =
+        llvm::dyn_cast<TypeSystemClang>(type.GetTypeSystem());
+    if (!ast)
+      return CompilerType();
+    return ast->GetType(ast->getASTContext().getMemberPointerType(
+        ClangUtil::GetQualType(pointee_type),
+        ClangUtil::GetQualType(type).getTypePtr()));
+  }
+  return CompilerType();
+}
+
+// Dumping types
+#define DEPTH_INCREMENT 2
+
+#ifndef NDEBUG
+LLVM_DUMP_METHOD void
+TypeSystemClang::dump(lldb::opaque_compiler_type_t type) const {
+  if (!type)
+    return;
+  clang::QualType qual_type(GetQualType(type));
+  qual_type.dump();
+}
+#endif
+
+void TypeSystemClang::Dump(Stream &s) {
+  Decl *tu = Decl::castFromDeclContext(GetTranslationUnitDecl());
+  tu->dump(s.AsRawOstream());
+}
+
+void TypeSystemClang::DumpFromSymbolFile(Stream &s,
+                                         llvm::StringRef symbol_name) {
+  SymbolFile *symfile = GetSymbolFile();
+
+  if (!symfile)
+    return;
+
+  lldb_private::TypeList type_list;
+  symfile->GetTypes(nullptr, eTypeClassAny, type_list);
+  size_t ntypes = type_list.GetSize();
+
+  for (size_t i = 0; i < ntypes; ++i) {
+    TypeSP type = type_list.GetTypeAtIndex(i);
+
+    if (!symbol_name.empty())
+      if (symbol_name != type->GetName().GetStringRef())
+        continue;
+
+    s << type->GetName().AsCString() << "\n";
+
+    CompilerType full_type = type->GetFullCompilerType();
+    if (clang::TagDecl *tag_decl = GetAsTagDecl(full_type)) {
+      tag_decl->dump(s.AsRawOstream());
+      continue;
+    }
+    if (clang::TypedefNameDecl *typedef_decl = GetAsTypedefDecl(full_type)) {
+      typedef_decl->dump(s.AsRawOstream());
+      continue;
+    }
+    if (auto *objc_obj = llvm::dyn_cast<clang::ObjCObjectType>(
+            ClangUtil::GetQualType(full_type).getTypePtr())) {
+      if (clang::ObjCInterfaceDecl *interface_decl = objc_obj->getInterface()) {
+        interface_decl->dump(s.AsRawOstream());
+        continue;
+      }
+    }
+    GetCanonicalQualType(full_type.GetOpaqueQualType()).dump(s.AsRawOstream());
+  }
+}
+
+void TypeSystemClang::DumpValue(
+    lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx, Stream *s,
+    lldb::Format format, const lldb_private::DataExtractor &data,
+    lldb::offset_t data_byte_offset, size_t data_byte_size,
+    uint32_t bitfield_bit_size, uint32_t bitfield_bit_offset, bool show_types,
+    bool show_summary, bool verbose, uint32_t depth) {
+  if (!type)
+    return;
+
+  clang::QualType qual_type(GetQualType(type));
+  switch (qual_type->getTypeClass()) {
+  case clang::Type::Record:
+    if (GetCompleteType(type)) {
+      const clang::RecordType *record_type =
+          llvm::cast<clang::RecordType>(qual_type.getTypePtr());
+      const clang::RecordDecl *record_decl = record_type->getDecl();
+      assert(record_decl);
+      uint32_t field_bit_offset = 0;
+      uint32_t field_byte_offset = 0;
+      const clang::ASTRecordLayout &record_layout =
+          getASTContext().getASTRecordLayout(record_decl);
+      uint32_t child_idx = 0;
+
+      const clang::CXXRecordDecl *cxx_record_decl =
+          llvm::dyn_cast<clang::CXXRecordDecl>(record_decl);
+      if (cxx_record_decl) {
+        // We might have base classes to print out first
+        clang::CXXRecordDecl::base_class_const_iterator base_class,
+            base_class_end;
+        for (base_class = cxx_record_decl->bases_begin(),
+            base_class_end = cxx_record_decl->bases_end();
+             base_class != base_class_end; ++base_class) {
+          const clang::CXXRecordDecl *base_class_decl =
+              llvm::cast<clang::CXXRecordDecl>(
+                  base_class->getType()->getAs<clang::RecordType>()->getDecl());
+
+          // Skip empty base classes
+          if (!verbose && !TypeSystemClang::RecordHasFields(base_class_decl))
+            continue;
+
+          if (base_class->isVirtual())
+            field_bit_offset =
+                record_layout.getVBaseClassOffset(base_class_decl)
+                    .getQuantity() *
+                8;
+          else
+            field_bit_offset = record_layout.getBaseClassOffset(base_class_decl)
+                                   .getQuantity() *
+                               8;
+          field_byte_offset = field_bit_offset / 8;
+          assert(field_bit_offset % 8 == 0);
+          if (child_idx == 0)
+            s->PutChar('{');
+          else
+            s->PutChar(',');
+
+          clang::QualType base_class_qual_type = base_class->getType();
+          std::string base_class_type_name(base_class_qual_type.getAsString());
+
+          // Indent and print the base class type name
+          s->Format("\n{0}{1}", llvm::fmt_repeat(" ", depth + DEPTH_INCREMENT),
+                    base_class_type_name);
+
+          clang::TypeInfo base_class_type_info =
+              getASTContext().getTypeInfo(base_class_qual_type);
+
+          // Dump the value of the member
+          CompilerType base_clang_type = GetType(base_class_qual_type);
+          base_clang_type.DumpValue(
+              exe_ctx,
+              s, // Stream to dump to
+              base_clang_type
+                  .GetFormat(), // The format with which to display the member
+              data, // Data buffer containing all bytes for this type
+              data_byte_offset + field_byte_offset, // Offset into "data" where
+                                                    // to grab value from
+              base_class_type_info.Width / 8, // Size of this type in bytes
+              0,                              // Bitfield bit size
+              0,                              // Bitfield bit offset
+              show_types,   // Boolean indicating if we should show the variable
+                            // types
+              show_summary, // Boolean indicating if we should show a summary
+                            // for the current type
+              verbose,      // Verbose output?
+              depth + DEPTH_INCREMENT); // Scope depth for any types that have
+                                        // children
+
+          ++child_idx;
+        }
+      }
+      uint32_t field_idx = 0;
+      clang::RecordDecl::field_iterator field, field_end;
+      for (field = record_decl->field_begin(),
+          field_end = record_decl->field_end();
+           field != field_end; ++field, ++field_idx, ++child_idx) {
+        // Print the starting squiggly bracket (if this is the first member) or
+        // comma (for member 2 and beyond) for the struct/union/class member.
+        if (child_idx == 0)
+          s->PutChar('{');
+        else
+          s->PutChar(',');
+
+        // Indent
+        s->Printf("\n%*s", depth + DEPTH_INCREMENT, "");
+
+        clang::QualType field_type = field->getType();
+        // Print the member type if requested
+        // Figure out the type byte size (field_type_info.first) and alignment
+        // (field_type_info.second) from the AST context.
+        clang::TypeInfo field_type_info =
+            getASTContext().getTypeInfo(field_type);
+        assert(field_idx < record_layout.getFieldCount());
+        // Figure out the field offset within the current struct/union/class
+        // type
+        field_bit_offset = record_layout.getFieldOffset(field_idx);
+        field_byte_offset = field_bit_offset / 8;
+        uint32_t field_bitfield_bit_size = 0;
+        uint32_t field_bitfield_bit_offset = 0;
+        if (FieldIsBitfield(*field, field_bitfield_bit_size))
+          field_bitfield_bit_offset = field_bit_offset % 8;
+
+        if (show_types) {
+          std::string field_type_name(field_type.getAsString());
+          if (field_bitfield_bit_size > 0)
+            s->Printf("(%s:%u) ", field_type_name.c_str(),
+                      field_bitfield_bit_size);
+          else
+            s->Printf("(%s) ", field_type_name.c_str());
+        }
+        // Print the member name and equal sign
+        s->Printf("%s = ", field->getNameAsString().c_str());
+
+        // Dump the value of the member
+        CompilerType field_clang_type = GetType(field_type);
+        field_clang_type.DumpValue(
+            exe_ctx,
+            s, // Stream to dump to
+            field_clang_type
+                .GetFormat(), // The format with which to display the member
+            data,             // Data buffer containing all bytes for this type
+            data_byte_offset + field_byte_offset, // Offset into "data" where to
+                                                  // grab value from
+            field_type_info.Width / 8,            // Size of this type in bytes
+            field_bitfield_bit_size,              // Bitfield bit size
+            field_bitfield_bit_offset,            // Bitfield bit offset
+            show_types,   // Boolean indicating if we should show the variable
+                          // types
+            show_summary, // Boolean indicating if we should show a summary for
+                          // the current type
+            verbose,      // Verbose output?
+            depth + DEPTH_INCREMENT); // Scope depth for any types that have
+                                      // children
+      }
+
+      // Indent the trailing squiggly bracket
+      if (child_idx > 0)
+        s->Printf("\n%*s}", depth, "");
+    }
+    return;
+
+  case clang::Type::Enum:
+    if (GetCompleteType(type)) {
+      const clang::EnumType *enutype =
+          llvm::cast<clang::EnumType>(qual_type.getTypePtr());
+      const clang::EnumDecl *enum_decl = enutype->getDecl();
+      assert(enum_decl);
+      clang::EnumDecl::enumerator_iterator enum_pos, enum_end_pos;
+      lldb::offset_t offset = data_byte_offset;
+      const int64_t enum_value = data.GetMaxU64Bitfield(
+          &offset, data_byte_size, bitfield_bit_size, bitfield_bit_offset);
+      for (enum_pos = enum_decl->enumerator_begin(),
+          enum_end_pos = enum_decl->enumerator_end();
+           enum_pos != enum_end_pos; ++enum_pos) {
+        if (enum_pos->getInitVal() == enum_value) {
+          s->Printf("%s", enum_pos->getNameAsString().c_str());
+          return;
+        }
+      }
+      // If we have gotten here we didn't get find the enumerator in the enum
+      // decl, so just print the integer.
+      s->Printf("%" PRIi64, enum_value);
+    }
+    return;
+
+  case clang::Type::ConstantArray: {
+    const clang::ConstantArrayType *array =
+        llvm::cast<clang::ConstantArrayType>(qual_type.getTypePtr());
+    bool is_array_of_characters = false;
+    clang::QualType element_qual_type = array->getElementType();
+
+    const clang::Type *canonical_type =
+        element_qual_type->getCanonicalTypeInternal().getTypePtr();
+    if (canonical_type)
+      is_array_of_characters = canonical_type->isCharType();
+
+    const uint64_t element_count = array->getSize().getLimitedValue();
+
+    clang::TypeInfo field_type_info =
+        getASTContext().getTypeInfo(element_qual_type);
+
+    uint32_t element_idx = 0;
+    uint32_t element_offset = 0;
+    uint64_t element_byte_size = field_type_info.Width / 8;
+    uint32_t element_stride = element_byte_size;
+
+    if (is_array_of_characters) {
+      s->PutChar('"');
+      DumpDataExtractor(data, s, data_byte_offset, lldb::eFormatChar,
+                        element_byte_size, element_count, UINT32_MAX,
+                        LLDB_INVALID_ADDRESS, 0, 0);
+      s->PutChar('"');
+      return;
+    } else {
+      CompilerType element_clang_type = GetType(element_qual_type);
+      lldb::Format element_format = element_clang_type.GetFormat();
+
+      for (element_idx = 0; element_idx < element_count; ++element_idx) {
+        // Print the starting squiggly bracket (if this is the first member) or
+        // comman (for member 2 and beyong) for the struct/union/class member.
+        if (element_idx == 0)
+          s->PutChar('{');
+        else
+          s->PutChar(',');
+
+        // Indent and print the index
+        s->Printf("\n%*s[%u] ", depth + DEPTH_INCREMENT, "", element_idx);
+
+        // Figure out the field offset within the current struct/union/class
+        // type
+        element_offset = element_idx * element_stride;
+
+        // Dump the value of the member
+        element_clang_type.DumpValue(
+            exe_ctx,
+            s,              // Stream to dump to
+            element_format, // The format with which to display the element
+            data,           // Data buffer containing all bytes for this type
+            data_byte_offset +
+                element_offset, // Offset into "data" where to grab value from
+            element_byte_size,  // Size of this type in bytes
+            0,                  // Bitfield bit size
+            0,                  // Bitfield bit offset
+            show_types,   // Boolean indicating if we should show the variable
+                          // types
+            show_summary, // Boolean indicating if we should show a summary for
+                          // the current type
+            verbose,      // Verbose output?
+            depth + DEPTH_INCREMENT); // Scope depth for any types that have
+                                      // children
+      }
+
+      // Indent the trailing squiggly bracket
+      if (element_idx > 0)
+        s->Printf("\n%*s}", depth, "");
+    }
+  }
+    return;
+
+  case clang::Type::Typedef: {
+    clang::QualType typedef_qual_type =
+        llvm::cast<clang::TypedefType>(qual_type)
+            ->getDecl()
+            ->getUnderlyingType();
+
+    CompilerType typedef_clang_type = GetType(typedef_qual_type);
+    lldb::Format typedef_format = typedef_clang_type.GetFormat();
+    clang::TypeInfo typedef_type_info =
+        getASTContext().getTypeInfo(typedef_qual_type);
+    uint64_t typedef_byte_size = typedef_type_info.Width / 8;
+
+    return typedef_clang_type.DumpValue(
+        exe_ctx,
+        s,                   // Stream to dump to
+        typedef_format,      // The format with which to display the element
+        data,                // Data buffer containing all bytes for this type
+        data_byte_offset,    // Offset into "data" where to grab value from
+        typedef_byte_size,   // Size of this type in bytes
+        bitfield_bit_size,   // Bitfield bit size
+        bitfield_bit_offset, // Bitfield bit offset
+        show_types,   // Boolean indicating if we should show the variable types
+        show_summary, // Boolean indicating if we should show a summary for the
+                      // current type
+        verbose,      // Verbose output?
+        depth);       // Scope depth for any types that have children
+  } break;
+
+  case clang::Type::Auto: {
+    clang::QualType elaborated_qual_type =
+        llvm::cast<clang::AutoType>(qual_type)->getDeducedType();
+    CompilerType elaborated_clang_type = GetType(elaborated_qual_type);
+    lldb::Format elaborated_format = elaborated_clang_type.GetFormat();
+    clang::TypeInfo elaborated_type_info =
+        getASTContext().getTypeInfo(elaborated_qual_type);
+    uint64_t elaborated_byte_size = elaborated_type_info.Width / 8;
+
+    return elaborated_clang_type.DumpValue(
+        exe_ctx,
+        s,                    // Stream to dump to
+        elaborated_format,    // The format with which to display the element
+        data,                 // Data buffer containing all bytes for this type
+        data_byte_offset,     // Offset into "data" where to grab value from
+        elaborated_byte_size, // Size of this type in bytes
+        bitfield_bit_size,    // Bitfield bit size
+        bitfield_bit_offset,  // Bitfield bit offset
+        show_types,   // Boolean indicating if we should show the variable types
+        show_summary, // Boolean indicating if we should show a summary for the
+                      // current type
+        verbose,      // Verbose output?
+        depth);       // Scope depth for any types that have children
+  } break;
+
+  case clang::Type::Elaborated: {
+    clang::QualType elaborated_qual_type =
+        llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType();
+    CompilerType elaborated_clang_type = GetType(elaborated_qual_type);
+    lldb::Format elaborated_format = elaborated_clang_type.GetFormat();
+    clang::TypeInfo elaborated_type_info =
+        getASTContext().getTypeInfo(elaborated_qual_type);
+    uint64_t elaborated_byte_size = elaborated_type_info.Width / 8;
+
+    return elaborated_clang_type.DumpValue(
+        exe_ctx,
+        s,                    // Stream to dump to
+        elaborated_format,    // The format with which to display the element
+        data,                 // Data buffer containing all bytes for this type
+        data_byte_offset,     // Offset into "data" where to grab value from
+        elaborated_byte_size, // Size of this type in bytes
+        bitfield_bit_size,    // Bitfield bit size
+        bitfield_bit_offset,  // Bitfield bit offset
+        show_types,   // Boolean indicating if we should show the variable types
+        show_summary, // Boolean indicating if we should show a summary for the
+                      // current type
+        verbose,      // Verbose output?
+        depth);       // Scope depth for any types that have children
+  } break;
+
+  case clang::Type::Paren: {
+    clang::QualType desugar_qual_type =
+        llvm::cast<clang::ParenType>(qual_type)->desugar();
+    CompilerType desugar_clang_type = GetType(desugar_qual_type);
+
+    lldb::Format desugar_format = desugar_clang_type.GetFormat();
+    clang::TypeInfo desugar_type_info =
+        getASTContext().getTypeInfo(desugar_qual_type);
+    uint64_t desugar_byte_size = desugar_type_info.Width / 8;
+
+    return desugar_clang_type.DumpValue(
+        exe_ctx,
+        s,                   // Stream to dump to
+        desugar_format,      // The format with which to display the element
+        data,                // Data buffer containing all bytes for this type
+        data_byte_offset,    // Offset into "data" where to grab value from
+        desugar_byte_size,   // Size of this type in bytes
+        bitfield_bit_size,   // Bitfield bit size
+        bitfield_bit_offset, // Bitfield bit offset
+        show_types,   // Boolean indicating if we should show the variable types
+        show_summary, // Boolean indicating if we should show a summary for the
+                      // current type
+        verbose,      // Verbose output?
+        depth);       // Scope depth for any types that have children
+  } break;
+
+  default:
+    // We are down to a scalar type that we just need to display.
+    DumpDataExtractor(data, s, data_byte_offset, format, data_byte_size, 1,
+                      UINT32_MAX, LLDB_INVALID_ADDRESS, bitfield_bit_size,
+                      bitfield_bit_offset);
+
+    if (show_summary)
+      DumpSummary(type, exe_ctx, s, data, data_byte_offset, data_byte_size);
+    break;
+  }
+}
+
+static bool DumpEnumValue(const clang::QualType &qual_type, Stream *s,
+                          const DataExtractor &data, lldb::offset_t byte_offset,
+                          size_t byte_size, uint32_t bitfield_bit_offset,
+                          uint32_t bitfield_bit_size) {
+  const clang::EnumType *enutype =
+      llvm::cast<clang::EnumType>(qual_type.getTypePtr());
+  const clang::EnumDecl *enum_decl = enutype->getDecl();
+  assert(enum_decl);
+  lldb::offset_t offset = byte_offset;
+  const uint64_t enum_svalue = data.GetMaxS64Bitfield(
+      &offset, byte_size, bitfield_bit_size, bitfield_bit_offset);
+  bool can_be_bitfield = true;
+  uint64_t covered_bits = 0;
+  int num_enumerators = 0;
+
+  // Try to find an exact match for the value.
+  // At the same time, we're applying a heuristic to determine whether we want
+  // to print this enum as a bitfield. We're likely dealing with a bitfield if
+  // every enumrator is either a one bit value or a superset of the previous
+  // enumerators. Also 0 doesn't make sense when the enumerators are used as
+  // flags.
+  for (auto enumerator : enum_decl->enumerators()) {
+    uint64_t val = enumerator->getInitVal().getSExtValue();
+    val = llvm::SignExtend64(val, 8*byte_size);
+    if (llvm::countPopulation(val) != 1 && (val & ~covered_bits) != 0)
+      can_be_bitfield = false;
+    covered_bits |= val;
+    ++num_enumerators;
+    if (val == enum_svalue) {
+      // Found an exact match, that's all we need to do.
+      s->PutCString(enumerator->getNameAsString());
+      return true;
+    }
+  }
+
+  // Unsigned values make more sense for flags.
+  offset = byte_offset;
+  const uint64_t enum_uvalue = data.GetMaxU64Bitfield(
+      &offset, byte_size, bitfield_bit_size, bitfield_bit_offset);
+
+  // No exact match, but we don't think this is a bitfield. Print the value as
+  // decimal.
+  if (!can_be_bitfield) {
+    if (qual_type->isSignedIntegerOrEnumerationType())
+      s->Printf("%" PRIi64, enum_svalue);
+    else
+      s->Printf("%" PRIu64, enum_uvalue);
+    return true;
+  }
+
+  uint64_t remaining_value = enum_uvalue;
+  std::vector<std::pair<uint64_t, llvm::StringRef>> values;
+  values.reserve(num_enumerators);
+  for (auto enumerator : enum_decl->enumerators())
+    if (auto val = enumerator->getInitVal().getZExtValue())
+      values.emplace_back(val, enumerator->getName());
+
+  // Sort in reverse order of the number of the population count,  so that in
+  // `enum {A, B, ALL = A|B }` we visit ALL first. Use a stable sort so that
+  // A | C where A is declared before C is displayed in this order.
+  std::stable_sort(values.begin(), values.end(), [](const auto &a, const auto &b) {
+        return llvm::countPopulation(a.first) > llvm::countPopulation(b.first);
+      });
+
+  for (const auto &val : values) {
+    if ((remaining_value & val.first) != val.first)
+      continue;
+    remaining_value &= ~val.first;
+    s->PutCString(val.second);
+    if (remaining_value)
+      s->PutCString(" | ");
+  }
+
+  // If there is a remainder that is not covered by the value, print it as hex.
+  if (remaining_value)
+    s->Printf("0x%" PRIx64, remaining_value);
+
+  return true;
+}
+
+bool TypeSystemClang::DumpTypeValue(
+    lldb::opaque_compiler_type_t type, Stream *s, lldb::Format format,
+    const lldb_private::DataExtractor &data, lldb::offset_t byte_offset,
+    size_t byte_size, uint32_t bitfield_bit_size, uint32_t bitfield_bit_offset,
+    ExecutionContextScope *exe_scope) {
+  if (!type)
+    return false;
+  if (IsAggregateType(type)) {
+    return false;
+  } else {
+    clang::QualType qual_type(GetQualType(type));
+
+    const clang::Type::TypeClass type_class = qual_type->getTypeClass();
+
+    if (type_class == clang::Type::Elaborated) {
+      qual_type = llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType();
+      return DumpTypeValue(qual_type.getAsOpaquePtr(), s, format, data, byte_offset, byte_size,
+                           bitfield_bit_size, bitfield_bit_offset, exe_scope);
+    }
+
+    switch (type_class) {
+    case clang::Type::Typedef: {
+      clang::QualType typedef_qual_type =
+          llvm::cast<clang::TypedefType>(qual_type)
+              ->getDecl()
+              ->getUnderlyingType();
+      CompilerType typedef_clang_type = GetType(typedef_qual_type);
+      if (format == eFormatDefault)
+        format = typedef_clang_type.GetFormat();
+      clang::TypeInfo typedef_type_info =
+          getASTContext().getTypeInfo(typedef_qual_type);
+      uint64_t typedef_byte_size = typedef_type_info.Width / 8;
+
+      return typedef_clang_type.DumpTypeValue(
+          s,
+          format,            // The format with which to display the element
+          data,              // Data buffer containing all bytes for this type
+          byte_offset,       // Offset into "data" where to grab value from
+          typedef_byte_size, // Size of this type in bytes
+          bitfield_bit_size, // Size in bits of a bitfield value, if zero don't
+                             // treat as a bitfield
+          bitfield_bit_offset, // Offset in bits of a bitfield value if
+                               // bitfield_bit_size != 0
+          exe_scope);
+    } break;
+
+    case clang::Type::Enum:
+      // If our format is enum or default, show the enumeration value as its
+      // enumeration string value, else just display it as requested.
+      if ((format == eFormatEnum || format == eFormatDefault) &&
+          GetCompleteType(type))
+        return DumpEnumValue(qual_type, s, data, byte_offset, byte_size,
+                             bitfield_bit_offset, bitfield_bit_size);
+      // format was not enum, just fall through and dump the value as
+      // requested....
+      LLVM_FALLTHROUGH;
+
+    default:
+      // We are down to a scalar type that we just need to display.
+      {
+        uint32_t item_count = 1;
+        // A few formats, we might need to modify our size and count for
+        // depending
+        // on how we are trying to display the value...
+        switch (format) {
+        default:
+        case eFormatBoolean:
+        case eFormatBinary:
+        case eFormatComplex:
+        case eFormatCString: // NULL terminated C strings
+        case eFormatDecimal:
+        case eFormatEnum:
+        case eFormatHex:
+        case eFormatHexUppercase:
+        case eFormatFloat:
+        case eFormatOctal:
+        case eFormatOSType:
+        case eFormatUnsigned:
+        case eFormatPointer:
+        case eFormatVectorOfChar:
+        case eFormatVectorOfSInt8:
+        case eFormatVectorOfUInt8:
+        case eFormatVectorOfSInt16:
+        case eFormatVectorOfUInt16:
+        case eFormatVectorOfSInt32:
+        case eFormatVectorOfUInt32:
+        case eFormatVectorOfSInt64:
+        case eFormatVectorOfUInt64:
+        case eFormatVectorOfFloat32:
+        case eFormatVectorOfFloat64:
+        case eFormatVectorOfUInt128:
+          break;
+
+        case eFormatChar:
+        case eFormatCharPrintable:
+        case eFormatCharArray:
+        case eFormatBytes:
+        case eFormatBytesWithASCII:
+          item_count = byte_size;
+          byte_size = 1;
+          break;
+
+        case eFormatUnicode16:
+          item_count = byte_size / 2;
+          byte_size = 2;
+          break;
+
+        case eFormatUnicode32:
+          item_count = byte_size / 4;
+          byte_size = 4;
+          break;
+        }
+        return DumpDataExtractor(data, s, byte_offset, format, byte_size,
+                                 item_count, UINT32_MAX, LLDB_INVALID_ADDRESS,
+                                 bitfield_bit_size, bitfield_bit_offset,
+                                 exe_scope);
+      }
+      break;
+    }
+  }
+  return false;
+}
+
+void TypeSystemClang::DumpSummary(lldb::opaque_compiler_type_t type,
+                                  ExecutionContext *exe_ctx, Stream *s,
+                                  const lldb_private::DataExtractor &data,
+                                  lldb::offset_t data_byte_offset,
+                                  size_t data_byte_size) {
+  uint32_t length = 0;
+  if (IsCStringType(type, length)) {
+    if (exe_ctx) {
+      Process *process = exe_ctx->GetProcessPtr();
+      if (process) {
+        lldb::offset_t offset = data_byte_offset;
+        lldb::addr_t pointer_address = data.GetMaxU64(&offset, data_byte_size);
+        std::vector<uint8_t> buf;
+        if (length > 0)
+          buf.resize(length);
+        else
+          buf.resize(256);
+
+        DataExtractor cstr_data(&buf.front(), buf.size(),
+                                process->GetByteOrder(), 4);
+        buf.back() = '\0';
+        size_t bytes_read;
+        size_t total_cstr_len = 0;
+        Status error;
+        while ((bytes_read = process->ReadMemory(pointer_address, &buf.front(),
+                                                 buf.size(), error)) > 0) {
+          const size_t len = strlen((const char *)&buf.front());
+          if (len == 0)
+            break;
+          if (total_cstr_len == 0)
+            s->PutCString(" \"");
+          DumpDataExtractor(cstr_data, s, 0, lldb::eFormatChar, 1, len,
+                            UINT32_MAX, LLDB_INVALID_ADDRESS, 0, 0);
+          total_cstr_len += len;
+          if (len < buf.size())
+            break;
+          pointer_address += total_cstr_len;
+        }
+        if (total_cstr_len > 0)
+          s->PutChar('"');
+      }
+    }
+  }
+}
+
+void TypeSystemClang::DumpTypeDescription(lldb::opaque_compiler_type_t type) {
+  StreamFile s(stdout, false);
+  DumpTypeDescription(type, &s);
+
+  CompilerType ct(this, type);
+  const clang::Type *clang_type = ClangUtil::GetQualType(ct).getTypePtr();
+  ClangASTMetadata *metadata = GetMetadata(clang_type);
+  if (metadata) {
+    metadata->Dump(&s);
+  }
+}
+
+void TypeSystemClang::DumpTypeDescription(lldb::opaque_compiler_type_t type,
+                                          Stream *s) {
+  if (type) {
+    clang::QualType qual_type =
+        RemoveWrappingTypes(GetQualType(type), {clang::Type::Typedef});
+
+    llvm::SmallVector<char, 1024> buf;
+    llvm::raw_svector_ostream llvm_ostrm(buf);
+
+    const clang::Type::TypeClass type_class = qual_type->getTypeClass();
+    switch (type_class) {
+    case clang::Type::ObjCObject:
+    case clang::Type::ObjCInterface: {
+      GetCompleteType(type);
+
+      const clang::ObjCObjectType *objc_class_type =
+          llvm::dyn_cast<clang::ObjCObjectType>(qual_type.getTypePtr());
+      assert(objc_class_type);
+      if (objc_class_type) {
+        clang::ObjCInterfaceDecl *class_interface_decl =
+            objc_class_type->getInterface();
+        if (class_interface_decl) {
+          clang::PrintingPolicy policy = getASTContext().getPrintingPolicy();
+          class_interface_decl->print(llvm_ostrm, policy, s->GetIndentLevel());
+        }
+      }
+    } break;
+
+    case clang::Type::Typedef: {
+      const clang::TypedefType *typedef_type =
+          qual_type->getAs<clang::TypedefType>();
+      if (typedef_type) {
+        const clang::TypedefNameDecl *typedef_decl = typedef_type->getDecl();
+        std::string clang_typedef_name(
+            typedef_decl->getQualifiedNameAsString());
+        if (!clang_typedef_name.empty()) {
+          s->PutCString("typedef ");
+          s->PutCString(clang_typedef_name);
+        }
+      }
+    } break;
+
+    case clang::Type::Record: {
+      GetCompleteType(type);
+
+      const clang::RecordType *record_type =
+          llvm::cast<clang::RecordType>(qual_type.getTypePtr());
+      const clang::RecordDecl *record_decl = record_type->getDecl();
+      const clang::CXXRecordDecl *cxx_record_decl =
+          llvm::dyn_cast<clang::CXXRecordDecl>(record_decl);
+
+      if (cxx_record_decl)
+        cxx_record_decl->print(llvm_ostrm, getASTContext().getPrintingPolicy(),
+                               s->GetIndentLevel());
+      else
+        record_decl->print(llvm_ostrm, getASTContext().getPrintingPolicy(),
+                           s->GetIndentLevel());
+    } break;
+
+    default: {
+      const clang::TagType *tag_type =
+          llvm::dyn_cast<clang::TagType>(qual_type.getTypePtr());
+      if (tag_type) {
+        clang::TagDecl *tag_decl = tag_type->getDecl();
+        if (tag_decl)
+          tag_decl->print(llvm_ostrm, 0);
+      } else {
+        std::string clang_type_name(qual_type.getAsString());
+        if (!clang_type_name.empty())
+          s->PutCString(clang_type_name);
+      }
+    }
+    }
+
+    if (buf.size() > 0) {
+      s->Write(buf.data(), buf.size());
+    }
+  }
+}
+
+void TypeSystemClang::DumpTypeName(const CompilerType &type) {
+  if (ClangUtil::IsClangType(type)) {
+    clang::QualType qual_type(
+        ClangUtil::GetCanonicalQualType(ClangUtil::RemoveFastQualifiers(type)));
+
+    const clang::Type::TypeClass type_class = qual_type->getTypeClass();
+    switch (type_class) {
+    case clang::Type::Record: {
+      const clang::CXXRecordDecl *cxx_record_decl =
+          qual_type->getAsCXXRecordDecl();
+      if (cxx_record_decl)
+        printf("class %s", cxx_record_decl->getName().str().c_str());
+    } break;
+
+    case clang::Type::Enum: {
+      clang::EnumDecl *enum_decl =
+          llvm::cast<clang::EnumType>(qual_type)->getDecl();
+      if (enum_decl) {
+        printf("enum %s", enum_decl->getName().str().c_str());
+      }
+    } break;
+
+    case clang::Type::ObjCObject:
+    case clang::Type::ObjCInterface: {
+      const clang::ObjCObjectType *objc_class_type =
+          llvm::dyn_cast<clang::ObjCObjectType>(qual_type);
+      if (objc_class_type) {
+        clang::ObjCInterfaceDecl *class_interface_decl =
+            objc_class_type->getInterface();
+        // We currently can't complete objective C types through the newly
+        // added ASTContext because it only supports TagDecl objects right
+        // now...
+        if (class_interface_decl)
+          printf("@class %s", class_interface_decl->getName().str().c_str());
+      }
+    } break;
+
+    case clang::Type::Typedef:
+      printf("typedef %s", llvm::cast<clang::TypedefType>(qual_type)
+                               ->getDecl()
+                               ->getName()
+                               .str()
+                               .c_str());
+      break;
+
+    case clang::Type::Auto:
+      printf("auto ");
+      return DumpTypeName(CompilerType(type.GetTypeSystem(),
+                                       llvm::cast<clang::AutoType>(qual_type)
+                                           ->getDeducedType()
+                                           .getAsOpaquePtr()));
+
+    case clang::Type::Elaborated:
+      printf("elaborated ");
+      return DumpTypeName(CompilerType(
+          type.GetTypeSystem(), llvm::cast<clang::ElaboratedType>(qual_type)
+                                    ->getNamedType()
+                                    .getAsOpaquePtr()));
+
+    case clang::Type::Paren:
+      printf("paren ");
+      return DumpTypeName(CompilerType(
+          type.GetTypeSystem(),
+          llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr()));
+
+    default:
+      printf("TypeSystemClang::DumpTypeName() type_class = %u", type_class);
+      break;
+    }
+  }
+}
+
+clang::ClassTemplateDecl *TypeSystemClang::ParseClassTemplateDecl(
+    clang::DeclContext *decl_ctx, lldb::AccessType access_type,
+    const char *parent_name, int tag_decl_kind,
+    const TypeSystemClang::TemplateParameterInfos &template_param_infos) {
+  if (template_param_infos.IsValid()) {
+    std::string template_basename(parent_name);
+    template_basename.erase(template_basename.find('<'));
+
+    return CreateClassTemplateDecl(decl_ctx, access_type,
+                                   template_basename.c_str(), tag_decl_kind,
+                                   template_param_infos);
+  }
+  return nullptr;
+}
+
+void TypeSystemClang::CompleteTagDecl(clang::TagDecl *decl) {
+  SymbolFile *sym_file = GetSymbolFile();
+  if (sym_file) {
+    CompilerType clang_type = GetTypeForDecl(decl);
+    if (clang_type)
+      sym_file->CompleteType(clang_type);
+  }
+}
+
+void TypeSystemClang::CompleteObjCInterfaceDecl(
+    clang::ObjCInterfaceDecl *decl) {
+  SymbolFile *sym_file = GetSymbolFile();
+  if (sym_file) {
+    CompilerType clang_type = GetTypeForDecl(decl);
+    if (clang_type)
+      sym_file->CompleteType(clang_type);
+  }
+}
+
+DWARFASTParser *TypeSystemClang::GetDWARFParser() {
+  if (!m_dwarf_ast_parser_up)
+    m_dwarf_ast_parser_up.reset(new DWARFASTParserClang(*this));
+  return m_dwarf_ast_parser_up.get();
+}
+
+PDBASTParser *TypeSystemClang::GetPDBParser() {
+  if (!m_pdb_ast_parser_up)
+    m_pdb_ast_parser_up.reset(new PDBASTParser(*this));
+  return m_pdb_ast_parser_up.get();
+}
+
+bool TypeSystemClang::LayoutRecordType(
+    const clang::RecordDecl *record_decl, uint64_t &bit_size,
+    uint64_t &alignment,
+    llvm::DenseMap<const clang::FieldDecl *, uint64_t> &field_offsets,
+    llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits>
+        &base_offsets,
+    llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits>
+        &vbase_offsets) {
+  lldb_private::ClangASTImporter *importer = nullptr;
+  if (m_dwarf_ast_parser_up)
+    importer = &m_dwarf_ast_parser_up->GetClangASTImporter();
+  if (!importer && m_pdb_ast_parser_up)
+    importer = &m_pdb_ast_parser_up->GetClangASTImporter();
+  if (!importer)
+    return false;
+
+  return importer->LayoutRecordType(record_decl, bit_size, alignment,
+                                    field_offsets, base_offsets, vbase_offsets);
+}
+
+// CompilerDecl override functions
+
+ConstString TypeSystemClang::DeclGetName(void *opaque_decl) {
+  if (opaque_decl) {
+    clang::NamedDecl *nd =
+        llvm::dyn_cast<NamedDecl>((clang::Decl *)opaque_decl);
+    if (nd != nullptr)
+      return ConstString(nd->getDeclName().getAsString());
+  }
+  return ConstString();
+}
+
+ConstString TypeSystemClang::DeclGetMangledName(void *opaque_decl) {
+  if (opaque_decl) {
+    clang::NamedDecl *nd =
+        llvm::dyn_cast<clang::NamedDecl>((clang::Decl *)opaque_decl);
+    if (nd != nullptr && !llvm::isa<clang::ObjCMethodDecl>(nd)) {
+      clang::MangleContext *mc = getMangleContext();
+      if (mc && mc->shouldMangleCXXName(nd)) {
+        llvm::SmallVector<char, 1024> buf;
+        llvm::raw_svector_ostream llvm_ostrm(buf);
+        if (llvm::isa<clang::CXXConstructorDecl>(nd)) {
+          mc->mangleCXXCtor(llvm::dyn_cast<clang::CXXConstructorDecl>(nd),
+                            Ctor_Complete, llvm_ostrm);
+        } else if (llvm::isa<clang::CXXDestructorDecl>(nd)) {
+          mc->mangleCXXDtor(llvm::dyn_cast<clang::CXXDestructorDecl>(nd),
+                            Dtor_Complete, llvm_ostrm);
+        } else {
+          mc->mangleName(nd, llvm_ostrm);
+        }
+        if (buf.size() > 0)
+          return ConstString(buf.data(), buf.size());
+      }
+    }
+  }
+  return ConstString();
+}
+
+CompilerDeclContext TypeSystemClang::DeclGetDeclContext(void *opaque_decl) {
+  if (opaque_decl)
+    return CreateDeclContext(((clang::Decl *)opaque_decl)->getDeclContext());
+  return CompilerDeclContext();
+}
+
+CompilerType TypeSystemClang::DeclGetFunctionReturnType(void *opaque_decl) {
+  if (clang::FunctionDecl *func_decl =
+          llvm::dyn_cast<clang::FunctionDecl>((clang::Decl *)opaque_decl))
+    return GetType(func_decl->getReturnType());
+  if (clang::ObjCMethodDecl *objc_method =
+          llvm::dyn_cast<clang::ObjCMethodDecl>((clang::Decl *)opaque_decl))
+    return GetType(objc_method->getReturnType());
+  else
+    return CompilerType();
+}
+
+size_t TypeSystemClang::DeclGetFunctionNumArguments(void *opaque_decl) {
+  if (clang::FunctionDecl *func_decl =
+          llvm::dyn_cast<clang::FunctionDecl>((clang::Decl *)opaque_decl))
+    return func_decl->param_size();
+  if (clang::ObjCMethodDecl *objc_method =
+          llvm::dyn_cast<clang::ObjCMethodDecl>((clang::Decl *)opaque_decl))
+    return objc_method->param_size();
+  else
+    return 0;
+}
+
+CompilerType TypeSystemClang::DeclGetFunctionArgumentType(void *opaque_decl,
+                                                          size_t idx) {
+  if (clang::FunctionDecl *func_decl =
+          llvm::dyn_cast<clang::FunctionDecl>((clang::Decl *)opaque_decl)) {
+    if (idx < func_decl->param_size()) {
+      ParmVarDecl *var_decl = func_decl->getParamDecl(idx);
+      if (var_decl)
+        return GetType(var_decl->getOriginalType());
+    }
+  } else if (clang::ObjCMethodDecl *objc_method =
+                 llvm::dyn_cast<clang::ObjCMethodDecl>(
+                     (clang::Decl *)opaque_decl)) {
+    if (idx < objc_method->param_size())
+      return GetType(objc_method->parameters()[idx]->getOriginalType());
+  }
+  return CompilerType();
+}
+
+// CompilerDeclContext functions
+
+std::vector<CompilerDecl> TypeSystemClang::DeclContextFindDeclByName(
+    void *opaque_decl_ctx, ConstString name, const bool ignore_using_decls) {
+  std::vector<CompilerDecl> found_decls;
+  if (opaque_decl_ctx) {
+    DeclContext *root_decl_ctx = (DeclContext *)opaque_decl_ctx;
+    std::set<DeclContext *> searched;
+    std::multimap<DeclContext *, DeclContext *> search_queue;
+    SymbolFile *symbol_file = GetSymbolFile();
+
+    for (clang::DeclContext *decl_context = root_decl_ctx;
+         decl_context != nullptr && found_decls.empty();
+         decl_context = decl_context->getParent()) {
+      search_queue.insert(std::make_pair(decl_context, decl_context));
+
+      for (auto it = search_queue.find(decl_context); it != search_queue.end();
+           it++) {
+        if (!searched.insert(it->second).second)
+          continue;
+        symbol_file->ParseDeclsForContext(
+            CreateDeclContext(it->second));
+
+        for (clang::Decl *child : it->second->decls()) {
+          if (clang::UsingDirectiveDecl *ud =
+                  llvm::dyn_cast<clang::UsingDirectiveDecl>(child)) {
+            if (ignore_using_decls)
+              continue;
+            clang::DeclContext *from = ud->getCommonAncestor();
+            if (searched.find(ud->getNominatedNamespace()) == searched.end())
+              search_queue.insert(
+                  std::make_pair(from, ud->getNominatedNamespace()));
+          } else if (clang::UsingDecl *ud =
+                         llvm::dyn_cast<clang::UsingDecl>(child)) {
+            if (ignore_using_decls)
+              continue;
+            for (clang::UsingShadowDecl *usd : ud->shadows()) {
+              clang::Decl *target = usd->getTargetDecl();
+              if (clang::NamedDecl *nd =
+                      llvm::dyn_cast<clang::NamedDecl>(target)) {
+                IdentifierInfo *ii = nd->getIdentifier();
+                if (ii != nullptr &&
+                    ii->getName().equals(name.AsCString(nullptr)))
+                  found_decls.push_back(GetCompilerDecl(nd));
+              }
+            }
+          } else if (clang::NamedDecl *nd =
+                         llvm::dyn_cast<clang::NamedDecl>(child)) {
+            IdentifierInfo *ii = nd->getIdentifier();
+            if (ii != nullptr && ii->getName().equals(name.AsCString(nullptr)))
+              found_decls.push_back(GetCompilerDecl(nd));
+          }
+        }
+      }
+    }
+  }
+  return found_decls;
+}
+
+// Look for child_decl_ctx's lookup scope in frame_decl_ctx and its parents,
+// and return the number of levels it took to find it, or
+// LLDB_INVALID_DECL_LEVEL if not found.  If the decl was imported via a using
+// declaration, its name and/or type, if set, will be used to check that the
+// decl found in the scope is a match.
+//
+// The optional name is required by languages (like C++) to handle using
+// declarations like:
+//
+//     void poo();
+//     namespace ns {
+//         void foo();
+//         void goo();
+//     }
+//     void bar() {
+//         using ns::foo;
+//         // CountDeclLevels returns 0 for 'foo', 1 for 'poo', and
+//         // LLDB_INVALID_DECL_LEVEL for 'goo'.
+//     }
+//
+// The optional type is useful in the case that there's a specific overload
+// that we're looking for that might otherwise be shadowed, like:
+//
+//     void foo(int);
+//     namespace ns {
+//         void foo();
+//     }
+//     void bar() {
+//         using ns::foo;
+//         // CountDeclLevels returns 0 for { 'foo', void() },
+//         // 1 for { 'foo', void(int) }, and
+//         // LLDB_INVALID_DECL_LEVEL for { 'foo', void(int, int) }.
+//     }
+//
+// NOTE: Because file statics are at the TranslationUnit along with globals, a
+// function at file scope will return the same level as a function at global
+// scope. Ideally we'd like to treat the file scope as an additional scope just
+// below the global scope.  More work needs to be done to recognise that, if
+// the decl we're trying to look up is static, we should compare its source
+// file with that of the current scope and return a lower number for it.
+uint32_t TypeSystemClang::CountDeclLevels(clang::DeclContext *frame_decl_ctx,
+                                          clang::DeclContext *child_decl_ctx,
+                                          ConstString *child_name,
+                                          CompilerType *child_type) {
+  if (frame_decl_ctx) {
+    std::set<DeclContext *> searched;
+    std::multimap<DeclContext *, DeclContext *> search_queue;
+    SymbolFile *symbol_file = GetSymbolFile();
+
+    // Get the lookup scope for the decl we're trying to find.
+    clang::DeclContext *parent_decl_ctx = child_decl_ctx->getParent();
+
+    // Look for it in our scope's decl context and its parents.
+    uint32_t level = 0;
+    for (clang::DeclContext *decl_ctx = frame_decl_ctx; decl_ctx != nullptr;
+         decl_ctx = decl_ctx->getParent()) {
+      if (!decl_ctx->isLookupContext())
+        continue;
+      if (decl_ctx == parent_decl_ctx)
+        // Found it!
+        return level;
+      search_queue.insert(std::make_pair(decl_ctx, decl_ctx));
+      for (auto it = search_queue.find(decl_ctx); it != search_queue.end();
+           it++) {
+        if (searched.find(it->second) != searched.end())
+          continue;
+
+        // Currently DWARF has one shared translation unit for all Decls at top
+        // level, so this would erroneously find using statements anywhere.  So
+        // don't look at the top-level translation unit.
+        // TODO fix this and add a testcase that depends on it.
+
+        if (llvm::isa<clang::TranslationUnitDecl>(it->second))
+          continue;
+
+        searched.insert(it->second);
+        symbol_file->ParseDeclsForContext(
+            CreateDeclContext(it->second));
+
+        for (clang::Decl *child : it->second->decls()) {
+          if (clang::UsingDirectiveDecl *ud =
+                  llvm::dyn_cast<clang::UsingDirectiveDecl>(child)) {
+            clang::DeclContext *ns = ud->getNominatedNamespace();
+            if (ns == parent_decl_ctx)
+              // Found it!
+              return level;
+            clang::DeclContext *from = ud->getCommonAncestor();
+            if (searched.find(ns) == searched.end())
+              search_queue.insert(std::make_pair(from, ns));
+          } else if (child_name) {
+            if (clang::UsingDecl *ud =
+                    llvm::dyn_cast<clang::UsingDecl>(child)) {
+              for (clang::UsingShadowDecl *usd : ud->shadows()) {
+                clang::Decl *target = usd->getTargetDecl();
+                clang::NamedDecl *nd = llvm::dyn_cast<clang::NamedDecl>(target);
+                if (!nd)
+                  continue;
+                // Check names.
+                IdentifierInfo *ii = nd->getIdentifier();
+                if (ii == nullptr ||
+                    !ii->getName().equals(child_name->AsCString(nullptr)))
+                  continue;
+                // Check types, if one was provided.
+                if (child_type) {
+                  CompilerType clang_type = GetTypeForDecl(nd);
+                  if (!AreTypesSame(clang_type, *child_type,
+                                    /*ignore_qualifiers=*/true))
+                    continue;
+                }
+                // Found it!
+                return level;
+              }
+            }
+          }
+        }
+      }
+      ++level;
+    }
+  }
+  return LLDB_INVALID_DECL_LEVEL;
+}
+
+ConstString TypeSystemClang::DeclContextGetName(void *opaque_decl_ctx) {
+  if (opaque_decl_ctx) {
+    clang::NamedDecl *named_decl =
+        llvm::dyn_cast<clang::NamedDecl>((clang::DeclContext *)opaque_decl_ctx);
+    if (named_decl)
+      return ConstString(named_decl->getName());
+  }
+  return ConstString();
+}
+
+ConstString
+TypeSystemClang::DeclContextGetScopeQualifiedName(void *opaque_decl_ctx) {
+  if (opaque_decl_ctx) {
+    clang::NamedDecl *named_decl =
+        llvm::dyn_cast<clang::NamedDecl>((clang::DeclContext *)opaque_decl_ctx);
+    if (named_decl)
+      return ConstString(
+          llvm::StringRef(named_decl->getQualifiedNameAsString()));
+  }
+  return ConstString();
+}
+
+bool TypeSystemClang::DeclContextIsClassMethod(
+    void *opaque_decl_ctx, lldb::LanguageType *language_ptr,
+    bool *is_instance_method_ptr, ConstString *language_object_name_ptr) {
+  if (opaque_decl_ctx) {
+    clang::DeclContext *decl_ctx = (clang::DeclContext *)opaque_decl_ctx;
+    if (ObjCMethodDecl *objc_method =
+            llvm::dyn_cast<clang::ObjCMethodDecl>(decl_ctx)) {
+      if (is_instance_method_ptr)
+        *is_instance_method_ptr = objc_method->isInstanceMethod();
+      if (language_ptr)
+        *language_ptr = eLanguageTypeObjC;
+      if (language_object_name_ptr)
+        language_object_name_ptr->SetCString("self");
+      return true;
+    } else if (CXXMethodDecl *cxx_method =
+                   llvm::dyn_cast<clang::CXXMethodDecl>(decl_ctx)) {
+      if (is_instance_method_ptr)
+        *is_instance_method_ptr = cxx_method->isInstance();
+      if (language_ptr)
+        *language_ptr = eLanguageTypeC_plus_plus;
+      if (language_object_name_ptr)
+        language_object_name_ptr->SetCString("this");
+      return true;
+    } else if (clang::FunctionDecl *function_decl =
+                   llvm::dyn_cast<clang::FunctionDecl>(decl_ctx)) {
+      ClangASTMetadata *metadata = GetMetadata(function_decl);
+      if (metadata && metadata->HasObjectPtr()) {
+        if (is_instance_method_ptr)
+          *is_instance_method_ptr = true;
+        if (language_ptr)
+          *language_ptr = eLanguageTypeObjC;
+        if (language_object_name_ptr)
+          language_object_name_ptr->SetCString(metadata->GetObjectPtrName());
+        return true;
+      }
+    }
+  }
+  return false;
+}
+
+bool TypeSystemClang::DeclContextIsContainedInLookup(
+    void *opaque_decl_ctx, void *other_opaque_decl_ctx) {
+  auto *decl_ctx = (clang::DeclContext *)opaque_decl_ctx;
+  auto *other = (clang::DeclContext *)other_opaque_decl_ctx;
+
+  do {
+    // A decl context always includes its own contents in its lookup.
+    if (decl_ctx == other)
+      return true;
+
+    // If we have an inline namespace, then the lookup of the parent context
+    // also includes the inline namespace contents.
+  } while (other->isInlineNamespace() && (other = other->getParent()));
+
+  return false;
+}
+
+static bool IsClangDeclContext(const CompilerDeclContext &dc) {
+  return dc.IsValid() && isa<TypeSystemClang>(dc.GetTypeSystem());
+}
+
+clang::DeclContext *
+TypeSystemClang::DeclContextGetAsDeclContext(const CompilerDeclContext &dc) {
+  if (IsClangDeclContext(dc))
+    return (clang::DeclContext *)dc.GetOpaqueDeclContext();
+  return nullptr;
+}
+
+ObjCMethodDecl *
+TypeSystemClang::DeclContextGetAsObjCMethodDecl(const CompilerDeclContext &dc) {
+  if (IsClangDeclContext(dc))
+    return llvm::dyn_cast<clang::ObjCMethodDecl>(
+        (clang::DeclContext *)dc.GetOpaqueDeclContext());
+  return nullptr;
+}
+
+CXXMethodDecl *
+TypeSystemClang::DeclContextGetAsCXXMethodDecl(const CompilerDeclContext &dc) {
+  if (IsClangDeclContext(dc))
+    return llvm::dyn_cast<clang::CXXMethodDecl>(
+        (clang::DeclContext *)dc.GetOpaqueDeclContext());
+  return nullptr;
+}
+
+clang::FunctionDecl *
+TypeSystemClang::DeclContextGetAsFunctionDecl(const CompilerDeclContext &dc) {
+  if (IsClangDeclContext(dc))
+    return llvm::dyn_cast<clang::FunctionDecl>(
+        (clang::DeclContext *)dc.GetOpaqueDeclContext());
+  return nullptr;
+}
+
+clang::NamespaceDecl *
+TypeSystemClang::DeclContextGetAsNamespaceDecl(const CompilerDeclContext &dc) {
+  if (IsClangDeclContext(dc))
+    return llvm::dyn_cast<clang::NamespaceDecl>(
+        (clang::DeclContext *)dc.GetOpaqueDeclContext());
+  return nullptr;
+}
+
+ClangASTMetadata *
+TypeSystemClang::DeclContextGetMetaData(const CompilerDeclContext &dc,
+                                        const Decl *object) {
+  TypeSystemClang *ast = llvm::cast<TypeSystemClang>(dc.GetTypeSystem());
+  return ast->GetMetadata(object);
+}
+
+clang::ASTContext *
+TypeSystemClang::DeclContextGetTypeSystemClang(const CompilerDeclContext &dc) {
+  TypeSystemClang *ast =
+      llvm::dyn_cast_or_null<TypeSystemClang>(dc.GetTypeSystem());
+  if (ast)
+    return &ast->getASTContext();
+  return nullptr;
+}
+
+TypeSystemClangForExpressions::TypeSystemClangForExpressions(
+    Target &target, llvm::Triple triple)
+    : TypeSystemClang("scratch ASTContext", triple),
+      m_target_wp(target.shared_from_this()),
+      m_persistent_variables(new ClangPersistentVariables) {
+  m_scratch_ast_source_up.reset(new ClangASTSource(
+      target.shared_from_this(), m_persistent_variables->GetClangASTImporter()));
+  m_scratch_ast_source_up->InstallASTContext(*this);
+  llvm::IntrusiveRefCntPtr<clang::ExternalASTSource> proxy_ast_source(
+      m_scratch_ast_source_up->CreateProxy());
+  SetExternalSource(proxy_ast_source);
+}
+
+void TypeSystemClangForExpressions::Finalize() {
+  TypeSystemClang::Finalize();
+  m_scratch_ast_source_up.reset();
+}
+
+UserExpression *TypeSystemClangForExpressions::GetUserExpression(
+    llvm::StringRef expr, llvm::StringRef prefix, lldb::LanguageType language,
+    Expression::ResultType desired_type,
+    const EvaluateExpressionOptions &options,
+    ValueObject *ctx_obj) {
+  TargetSP target_sp = m_target_wp.lock();
+  if (!target_sp)
+    return nullptr;
+
+  return new ClangUserExpression(*target_sp.get(), expr, prefix, language,
+                                 desired_type, options, ctx_obj);
+}
+
+FunctionCaller *TypeSystemClangForExpressions::GetFunctionCaller(
+    const CompilerType &return_type, const Address &function_address,
+    const ValueList &arg_value_list, const char *name) {
+  TargetSP target_sp = m_target_wp.lock();
+  if (!target_sp)
+    return nullptr;
+
+  Process *process = target_sp->GetProcessSP().get();
+  if (!process)
+    return nullptr;
+
+  return new ClangFunctionCaller(*process, return_type, function_address,
+                                 arg_value_list, name);
+}
+
+UtilityFunction *
+TypeSystemClangForExpressions::GetUtilityFunction(const char *text,
+                                                  const char *name) {
+  TargetSP target_sp = m_target_wp.lock();
+  if (!target_sp)
+    return nullptr;
+
+  return new ClangUtilityFunction(*target_sp.get(), text, name);
+}
+
+PersistentExpressionState *
+TypeSystemClangForExpressions::GetPersistentExpressionState() {
+  return m_persistent_variables.get();
+}
diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h
new file mode 100644 (file)
index 0000000..fd8276d
--- /dev/null
@@ -0,0 +1,1029 @@
+//===-- TypeSystemClang.h ---------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_TypeSystemClang_h_
+#define liblldb_TypeSystemClang_h_
+
+#include <stdint.h>
+
+#include <functional>
+#include <initializer_list>
+#include <map>
+#include <memory>
+#include <set>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/ASTFwd.h"
+#include "clang/AST/TemplateBase.h"
+#include "llvm/ADT/APSInt.h"
+#include "llvm/ADT/SmallVector.h"
+
+#include "Plugins/ExpressionParser/Clang/ClangPersistentVariables.h"
+#include "lldb/Core/ClangForward.h"
+#include "lldb/Expression/ExpressionVariable.h"
+#include "lldb/Symbol/CompilerType.h"
+#include "lldb/Symbol/TypeSystem.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Utility/ConstString.h"
+#include "lldb/Utility/Log.h"
+#include "lldb/Utility/Logging.h"
+#include "lldb/lldb-enumerations.h"
+
+class DWARFASTParserClang;
+class PDBASTParser;
+
+namespace lldb_private {
+
+class Declaration;
+
+class TypeSystemClang : public TypeSystem {
+  // LLVM RTTI support
+  static char ID;
+
+public:
+  typedef void (*CompleteTagDeclCallback)(void *baton, clang::TagDecl *);
+  typedef void (*CompleteObjCInterfaceDeclCallback)(void *baton,
+                                                    clang::ObjCInterfaceDecl *);
+
+  // llvm casting support
+  bool isA(const void *ClassID) const override { return ClassID == &ID; }
+  static bool classof(const TypeSystem *ts) { return ts->isA(&ID); }
+
+  /// Constructs a TypeSystemClang with an ASTContext using the given triple.
+  ///
+  /// \param name The name for the TypeSystemClang (for logging purposes)
+  /// \param triple The llvm::Triple used for the ASTContext. The triple defines
+  ///               certain characteristics of the ASTContext and its types
+  ///               (e.g., whether certain primitive types exist or what their
+  ///               signedness is).
+  explicit TypeSystemClang(llvm::StringRef name, llvm::Triple triple);
+
+  /// Constructs a TypeSystemClang that uses an existing ASTContext internally.
+  /// Useful when having an existing ASTContext created by Clang.
+  ///
+  /// \param name The name for the TypeSystemClang (for logging purposes)
+  /// \param existing_ctxt An existing ASTContext.
+  explicit TypeSystemClang(llvm::StringRef name,
+                           clang::ASTContext &existing_ctxt);
+
+  ~TypeSystemClang() override;
+
+  void Finalize() override;
+
+  // PluginInterface functions
+  ConstString GetPluginName() override;
+
+  uint32_t GetPluginVersion() override;
+
+  static ConstString GetPluginNameStatic();
+
+  static lldb::TypeSystemSP CreateInstance(lldb::LanguageType language,
+                                           Module *module, Target *target);
+
+  static LanguageSet GetSupportedLanguagesForTypes();
+  static LanguageSet GetSupportedLanguagesForExpressions();
+
+  static void Initialize();
+
+  static void Terminate();
+
+  static TypeSystemClang *GetASTContext(clang::ASTContext *ast_ctx);
+
+  static TypeSystemClang *GetScratch(Target &target,
+                                     bool create_on_demand = true) {
+    auto type_system_or_err = target.GetScratchTypeSystemForLanguage(
+        lldb::eLanguageTypeC, create_on_demand);
+    if (auto err = type_system_or_err.takeError()) {
+      LLDB_LOG_ERROR(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_TARGET),
+                     std::move(err), "Couldn't get scratch TypeSystemClang");
+      return nullptr;
+    }
+    return llvm::dyn_cast<TypeSystemClang>(&type_system_or_err.get());
+  }
+
+  /// Returns the display name of this TypeSystemClang that indicates what
+  /// purpose it serves in LLDB. Used for example in logs.
+  llvm::StringRef getDisplayName() const { return m_display_name; }
+
+  clang::ASTContext &getASTContext();
+
+  clang::MangleContext *getMangleContext();
+
+  std::shared_ptr<clang::TargetOptions> &getTargetOptions();
+
+  clang::TargetInfo *getTargetInfo();
+
+  void setSema(clang::Sema *s);
+  clang::Sema *getSema() { return m_sema; }
+
+  const char *GetTargetTriple();
+
+  void SetExternalSource(
+      llvm::IntrusiveRefCntPtr<clang::ExternalASTSource> &ast_source_up);
+
+  bool GetCompleteDecl(clang::Decl *decl) {
+    return TypeSystemClang::GetCompleteDecl(&getASTContext(), decl);
+  }
+
+  static void DumpDeclHiearchy(clang::Decl *decl);
+
+  static void DumpDeclContextHiearchy(clang::DeclContext *decl_ctx);
+
+  static bool DeclsAreEquivalent(clang::Decl *lhs_decl, clang::Decl *rhs_decl);
+
+  static bool GetCompleteDecl(clang::ASTContext *ast, clang::Decl *decl);
+
+  void SetMetadataAsUserID(const clang::Decl *decl, lldb::user_id_t user_id);
+  void SetMetadataAsUserID(const clang::Type *type, lldb::user_id_t user_id);
+
+  void SetMetadata(const clang::Decl *object, ClangASTMetadata &meta_data);
+
+  void SetMetadata(const clang::Type *object, ClangASTMetadata &meta_data);
+  ClangASTMetadata *GetMetadata(const clang::Decl *object);
+  ClangASTMetadata *GetMetadata(const clang::Type *object);
+
+  // Basic Types
+  CompilerType GetBuiltinTypeForEncodingAndBitSize(lldb::Encoding encoding,
+                                                   size_t bit_size) override;
+
+  CompilerType GetBasicType(lldb::BasicType type);
+
+  static lldb::BasicType GetBasicTypeEnumeration(ConstString name);
+
+  CompilerType
+  GetBuiltinTypeForDWARFEncodingAndBitSize(llvm::StringRef type_name,
+                                           uint32_t dw_ate, uint32_t bit_size);
+
+  CompilerType GetCStringType(bool is_const);
+
+  static clang::DeclContext *GetDeclContextForType(clang::QualType type);
+
+  static clang::DeclContext *GetDeclContextForType(const CompilerType &type);
+
+  uint32_t GetPointerByteSize() override;
+
+  clang::TranslationUnitDecl *GetTranslationUnitDecl() {
+    return getASTContext().getTranslationUnitDecl();
+  }
+
+  static bool AreTypesSame(CompilerType type1, CompilerType type2,
+                           bool ignore_qualifiers = false);
+
+  /// Creates a CompilerType form the given QualType with the current
+  /// TypeSystemClang instance as the CompilerType's typesystem.
+  /// \param qt The QualType for a type that belongs to the ASTContext of this
+  ///           TypeSystemClang.
+  /// \return The CompilerType representing the given QualType. If the
+  ///         QualType's type pointer is a nullptr then the function returns an
+  ///         invalid CompilerType.
+  CompilerType GetType(clang::QualType qt) {
+    if (qt.getTypePtrOrNull() == nullptr)
+      return CompilerType();
+    // Check that the type actually belongs to this TypeSystemClang.
+    assert(qt->getAsTagDecl() == nullptr ||
+           &qt->getAsTagDecl()->getASTContext() == &getASTContext());
+    return CompilerType(this, qt.getAsOpaquePtr());
+  }
+
+  CompilerType GetTypeForDecl(clang::NamedDecl *decl);
+
+  CompilerType GetTypeForDecl(clang::TagDecl *decl);
+
+  CompilerType GetTypeForDecl(clang::ObjCInterfaceDecl *objc_decl);
+
+  template <typename RecordDeclType>
+  CompilerType
+  GetTypeForIdentifier(ConstString type_name,
+                       clang::DeclContext *decl_context = nullptr) {
+    CompilerType compiler_type;
+
+    if (type_name.GetLength()) {
+      clang::ASTContext &ast = getASTContext();
+      if (!decl_context)
+        decl_context = ast.getTranslationUnitDecl();
+
+      clang::IdentifierInfo &myIdent = ast.Idents.get(type_name.GetCString());
+      clang::DeclarationName myName =
+          ast.DeclarationNames.getIdentifier(&myIdent);
+
+      clang::DeclContext::lookup_result result = decl_context->lookup(myName);
+
+      if (!result.empty()) {
+        clang::NamedDecl *named_decl = result[0];
+        if (const RecordDeclType *record_decl =
+                llvm::dyn_cast<RecordDeclType>(named_decl))
+          compiler_type.SetCompilerType(
+              this, clang::QualType(record_decl->getTypeForDecl(), 0)
+                        .getAsOpaquePtr());
+      }
+    }
+
+    return compiler_type;
+  }
+
+  CompilerType CreateStructForIdentifier(
+      ConstString type_name,
+      const std::initializer_list<std::pair<const char *, CompilerType>>
+          &type_fields,
+      bool packed = false);
+
+  CompilerType GetOrCreateStructForIdentifier(
+      ConstString type_name,
+      const std::initializer_list<std::pair<const char *, CompilerType>>
+          &type_fields,
+      bool packed = false);
+
+  static bool IsOperator(llvm::StringRef name,
+                         clang::OverloadedOperatorKind &op_kind);
+
+  // Structure, Unions, Classes
+
+  static clang::AccessSpecifier
+  ConvertAccessTypeToAccessSpecifier(lldb::AccessType access);
+
+  static clang::AccessSpecifier
+  UnifyAccessSpecifiers(clang::AccessSpecifier lhs, clang::AccessSpecifier rhs);
+
+  static uint32_t GetNumBaseClasses(const clang::CXXRecordDecl *cxx_record_decl,
+                                    bool omit_empty_base_classes);
+
+  CompilerType CreateRecordType(clang::DeclContext *decl_ctx,
+                                lldb::AccessType access_type,
+                                llvm::StringRef name, int kind,
+                                lldb::LanguageType language,
+                                ClangASTMetadata *metadata = nullptr,
+                                bool exports_symbols = false);
+
+  class TemplateParameterInfos {
+  public:
+    bool IsValid() const {
+      if (args.empty())
+        return false;
+      return args.size() == names.size() &&
+        ((bool)pack_name == (bool)packed_args) &&
+        (!packed_args || !packed_args->packed_args);
+    }
+
+    llvm::SmallVector<const char *, 2> names;
+    llvm::SmallVector<clang::TemplateArgument, 2> args;
+    
+    const char * pack_name = nullptr;
+    std::unique_ptr<TemplateParameterInfos> packed_args;
+  };
+
+  clang::FunctionTemplateDecl *
+  CreateFunctionTemplateDecl(clang::DeclContext *decl_ctx,
+                             clang::FunctionDecl *func_decl, const char *name,
+                             const TemplateParameterInfos &infos);
+
+  void CreateFunctionTemplateSpecializationInfo(
+      clang::FunctionDecl *func_decl, clang::FunctionTemplateDecl *Template,
+      const TemplateParameterInfos &infos);
+
+  clang::ClassTemplateDecl *
+  CreateClassTemplateDecl(clang::DeclContext *decl_ctx,
+                          lldb::AccessType access_type, const char *class_name,
+                          int kind, const TemplateParameterInfos &infos);
+
+  clang::TemplateTemplateParmDecl *
+  CreateTemplateTemplateParmDecl(const char *template_name);
+
+  clang::ClassTemplateSpecializationDecl *CreateClassTemplateSpecializationDecl(
+      clang::DeclContext *decl_ctx,
+      clang::ClassTemplateDecl *class_template_decl, int kind,
+      const TemplateParameterInfos &infos);
+
+  CompilerType
+  CreateClassTemplateSpecializationType(clang::ClassTemplateSpecializationDecl *
+                                            class_template_specialization_decl);
+
+  static clang::DeclContext *
+  GetAsDeclContext(clang::FunctionDecl *function_decl);
+
+  static bool CheckOverloadedOperatorKindParameterCount(
+      bool is_method, clang::OverloadedOperatorKind op_kind,
+      uint32_t num_params);
+
+  bool FieldIsBitfield(clang::FieldDecl *field, uint32_t &bitfield_bit_size);
+
+  static bool RecordHasFields(const clang::RecordDecl *record_decl);
+
+  CompilerType CreateObjCClass(llvm::StringRef name,
+                               clang::DeclContext *decl_ctx, bool isForwardDecl,
+                               bool isInternal,
+                               ClangASTMetadata *metadata = nullptr);
+
+  bool SetTagTypeKind(clang::QualType type, int kind) const;
+
+  bool SetDefaultAccessForRecordFields(clang::RecordDecl *record_decl,
+                                       int default_accessibility,
+                                       int *assigned_accessibilities,
+                                       size_t num_assigned_accessibilities);
+
+  // Returns a mask containing bits from the TypeSystemClang::eTypeXXX
+  // enumerations
+
+  // Namespace Declarations
+
+  clang::NamespaceDecl *
+  GetUniqueNamespaceDeclaration(const char *name, clang::DeclContext *decl_ctx,
+                                bool is_inline = false);
+
+  // Function Types
+
+  clang::FunctionDecl *
+  CreateFunctionDeclaration(clang::DeclContext *decl_ctx, const char *name,
+                            const CompilerType &function_Type, int storage,
+                            bool is_inline);
+
+  CompilerType CreateFunctionType(const CompilerType &result_type,
+                                  const CompilerType *args, unsigned num_args,
+                                  bool is_variadic, unsigned type_quals,
+                                  clang::CallingConv cc);
+
+  CompilerType CreateFunctionType(const CompilerType &result_type,
+                                  const CompilerType *args, unsigned num_args,
+                                  bool is_variadic, unsigned type_quals) {
+    return CreateFunctionType(result_type, args, num_args, is_variadic,
+                              type_quals, clang::CC_C);
+  }
+
+  clang::ParmVarDecl *CreateParameterDeclaration(clang::DeclContext *decl_ctx,
+                                                 const char *name,
+                                                 const CompilerType &param_type,
+                                                 int storage,
+                                                 bool add_decl=false);
+
+  void SetFunctionParameters(clang::FunctionDecl *function_decl,
+                             clang::ParmVarDecl **params, unsigned num_params);
+
+  CompilerType CreateBlockPointerType(const CompilerType &function_type);
+
+  // Array Types
+
+  CompilerType CreateArrayType(const CompilerType &element_type,
+                               size_t element_count, bool is_vector);
+
+  // Enumeration Types
+  CompilerType CreateEnumerationType(const char *name,
+                                     clang::DeclContext *decl_ctx,
+                                     const Declaration &decl,
+                                     const CompilerType &integer_qual_type,
+                                     bool is_scoped);
+
+  // Integer type functions
+
+  CompilerType GetIntTypeFromBitSize(size_t bit_size, bool is_signed);
+
+  CompilerType GetPointerSizedIntType(bool is_signed);
+
+  // Floating point functions
+
+  static CompilerType GetFloatTypeFromBitSize(clang::ASTContext *ast,
+                                              size_t bit_size);
+
+  // TypeSystem methods
+  DWARFASTParser *GetDWARFParser() override;
+  PDBASTParser *GetPDBParser() override;
+
+  // TypeSystemClang callbacks for external source lookups.
+  void CompleteTagDecl(clang::TagDecl *);
+
+  void CompleteObjCInterfaceDecl(clang::ObjCInterfaceDecl *);
+
+  bool LayoutRecordType(
+      const clang::RecordDecl *record_decl, uint64_t &size, uint64_t &alignment,
+      llvm::DenseMap<const clang::FieldDecl *, uint64_t> &field_offsets,
+      llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits>
+          &base_offsets,
+      llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits>
+          &vbase_offsets);
+
+  /// Creates a CompilerDecl from the given Decl with the current
+  /// TypeSystemClang instance as its typesystem.
+  /// The Decl has to come from the ASTContext of this
+  /// TypeSystemClang.
+  CompilerDecl GetCompilerDecl(clang::Decl *decl) {
+    assert(&decl->getASTContext() == &getASTContext() &&
+           "CreateCompilerDecl for Decl from wrong ASTContext?");
+    return CompilerDecl(this, decl);
+  }
+
+  // CompilerDecl override functions
+  ConstString DeclGetName(void *opaque_decl) override;
+
+  ConstString DeclGetMangledName(void *opaque_decl) override;
+
+  CompilerDeclContext DeclGetDeclContext(void *opaque_decl) override;
+
+  CompilerType DeclGetFunctionReturnType(void *opaque_decl) override;
+
+  size_t DeclGetFunctionNumArguments(void *opaque_decl) override;
+
+  CompilerType DeclGetFunctionArgumentType(void *opaque_decl,
+                                           size_t arg_idx) override;
+
+  CompilerType GetTypeForDecl(void *opaque_decl) override;
+
+  // CompilerDeclContext override functions
+
+  /// Creates a CompilerDeclContext from the given DeclContext
+  /// with the current TypeSystemClang instance as its typesystem.
+  /// The DeclContext has to come from the ASTContext of this
+  /// TypeSystemClang.
+  CompilerDeclContext CreateDeclContext(clang::DeclContext *ctx);
+
+  std::vector<CompilerDecl>
+  DeclContextFindDeclByName(void *opaque_decl_ctx, ConstString name,
+                            const bool ignore_using_decls) override;
+
+  ConstString DeclContextGetName(void *opaque_decl_ctx) override;
+
+  ConstString DeclContextGetScopeQualifiedName(void *opaque_decl_ctx) override;
+
+  bool DeclContextIsClassMethod(void *opaque_decl_ctx,
+                                lldb::LanguageType *language_ptr,
+                                bool *is_instance_method_ptr,
+                                ConstString *language_object_name_ptr) override;
+
+  bool DeclContextIsContainedInLookup(void *opaque_decl_ctx,
+                                      void *other_opaque_decl_ctx) override;
+
+  // Clang specific clang::DeclContext functions
+
+  static clang::DeclContext *
+  DeclContextGetAsDeclContext(const CompilerDeclContext &dc);
+
+  static clang::ObjCMethodDecl *
+  DeclContextGetAsObjCMethodDecl(const CompilerDeclContext &dc);
+
+  static clang::CXXMethodDecl *
+  DeclContextGetAsCXXMethodDecl(const CompilerDeclContext &dc);
+
+  static clang::FunctionDecl *
+  DeclContextGetAsFunctionDecl(const CompilerDeclContext &dc);
+
+  static clang::NamespaceDecl *
+  DeclContextGetAsNamespaceDecl(const CompilerDeclContext &dc);
+
+  static ClangASTMetadata *DeclContextGetMetaData(const CompilerDeclContext &dc,
+                                                  const clang::Decl *object);
+
+  static clang::ASTContext *
+  DeclContextGetTypeSystemClang(const CompilerDeclContext &dc);
+
+  // Tests
+
+  bool IsArrayType(lldb::opaque_compiler_type_t type,
+                   CompilerType *element_type, uint64_t *size,
+                   bool *is_incomplete) override;
+
+  bool IsVectorType(lldb::opaque_compiler_type_t type,
+                    CompilerType *element_type, uint64_t *size) override;
+
+  bool IsAggregateType(lldb::opaque_compiler_type_t type) override;
+
+  bool IsAnonymousType(lldb::opaque_compiler_type_t type) override;
+
+  bool IsBeingDefined(lldb::opaque_compiler_type_t type) override;
+
+  bool IsCharType(lldb::opaque_compiler_type_t type) override;
+
+  bool IsCompleteType(lldb::opaque_compiler_type_t type) override;
+
+  bool IsConst(lldb::opaque_compiler_type_t type) override;
+
+  bool IsCStringType(lldb::opaque_compiler_type_t type,
+                     uint32_t &length) override;
+
+  static bool IsCXXClassType(const CompilerType &type);
+
+  bool IsDefined(lldb::opaque_compiler_type_t type) override;
+
+  bool IsFloatingPointType(lldb::opaque_compiler_type_t type, uint32_t &count,
+                           bool &is_complex) override;
+
+  bool IsFunctionType(lldb::opaque_compiler_type_t type,
+                      bool *is_variadic_ptr) override;
+
+  uint32_t IsHomogeneousAggregate(lldb::opaque_compiler_type_t type,
+                                  CompilerType *base_type_ptr) override;
+
+  size_t
+  GetNumberOfFunctionArguments(lldb::opaque_compiler_type_t type) override;
+
+  CompilerType GetFunctionArgumentAtIndex(lldb::opaque_compiler_type_t type,
+                                          const size_t index) override;
+
+  bool IsFunctionPointerType(lldb::opaque_compiler_type_t type) override;
+
+  bool IsBlockPointerType(lldb::opaque_compiler_type_t type,
+                          CompilerType *function_pointer_type_ptr) override;
+
+  bool IsIntegerType(lldb::opaque_compiler_type_t type,
+                     bool &is_signed) override;
+
+  bool IsEnumerationType(lldb::opaque_compiler_type_t type,
+                         bool &is_signed) override;
+
+  static bool IsObjCClassType(const CompilerType &type);
+
+  static bool IsObjCClassTypeAndHasIVars(const CompilerType &type,
+                                         bool check_superclass);
+
+  static bool IsObjCObjectOrInterfaceType(const CompilerType &type);
+
+  static bool IsObjCObjectPointerType(const CompilerType &type,
+                                      CompilerType *target_type = nullptr);
+
+  bool IsPolymorphicClass(lldb::opaque_compiler_type_t type) override;
+
+  static bool IsClassType(lldb::opaque_compiler_type_t type);
+
+  static bool IsEnumType(lldb::opaque_compiler_type_t type);
+
+  bool IsPossibleDynamicType(lldb::opaque_compiler_type_t type,
+                             CompilerType *target_type, // Can pass nullptr
+                             bool check_cplusplus, bool check_objc) override;
+
+  bool IsRuntimeGeneratedType(lldb::opaque_compiler_type_t type) override;
+
+  bool IsPointerType(lldb::opaque_compiler_type_t type,
+                     CompilerType *pointee_type) override;
+
+  bool IsPointerOrReferenceType(lldb::opaque_compiler_type_t type,
+                                CompilerType *pointee_type) override;
+
+  bool IsReferenceType(lldb::opaque_compiler_type_t type,
+                       CompilerType *pointee_type, bool *is_rvalue) override;
+
+  bool IsScalarType(lldb::opaque_compiler_type_t type) override;
+
+  bool IsTypedefType(lldb::opaque_compiler_type_t type) override;
+
+  bool IsVoidType(lldb::opaque_compiler_type_t type) override;
+
+  bool CanPassInRegisters(const CompilerType &type) override;
+
+  bool SupportsLanguage(lldb::LanguageType language) override;
+
+  static llvm::Optional<std::string> GetCXXClassName(const CompilerType &type);
+
+  // Type Completion
+
+  bool GetCompleteType(lldb::opaque_compiler_type_t type) override;
+
+  // Accessors
+
+  ConstString GetTypeName(lldb::opaque_compiler_type_t type) override;
+
+  uint32_t GetTypeInfo(lldb::opaque_compiler_type_t type,
+                       CompilerType *pointee_or_element_compiler_type) override;
+
+  lldb::LanguageType
+  GetMinimumLanguage(lldb::opaque_compiler_type_t type) override;
+
+  lldb::TypeClass GetTypeClass(lldb::opaque_compiler_type_t type) override;
+
+  unsigned GetTypeQualifiers(lldb::opaque_compiler_type_t type) override;
+
+  // Creating related types
+
+  // Using the current type, create a new typedef to that type using
+  // "typedef_name" as the name and "decl_ctx" as the decl context.
+  static CompilerType
+  CreateTypedefType(const CompilerType &type, const char *typedef_name,
+                    const CompilerDeclContext &compiler_decl_ctx);
+
+  CompilerType GetArrayElementType(lldb::opaque_compiler_type_t type,
+                                   uint64_t *stride) override;
+
+  CompilerType GetArrayType(lldb::opaque_compiler_type_t type,
+                            uint64_t size) override;
+
+  CompilerType GetCanonicalType(lldb::opaque_compiler_type_t type) override;
+
+  CompilerType
+  GetFullyUnqualifiedType(lldb::opaque_compiler_type_t type) override;
+
+  // Returns -1 if this isn't a function of if the function doesn't have a
+  // prototype Returns a value >= 0 if there is a prototype.
+  int GetFunctionArgumentCount(lldb::opaque_compiler_type_t type) override;
+
+  CompilerType GetFunctionArgumentTypeAtIndex(lldb::opaque_compiler_type_t type,
+                                              size_t idx) override;
+
+  CompilerType
+  GetFunctionReturnType(lldb::opaque_compiler_type_t type) override;
+
+  size_t GetNumMemberFunctions(lldb::opaque_compiler_type_t type) override;
+
+  TypeMemberFunctionImpl
+  GetMemberFunctionAtIndex(lldb::opaque_compiler_type_t type,
+                           size_t idx) override;
+
+  CompilerType GetNonReferenceType(lldb::opaque_compiler_type_t type) override;
+
+  CompilerType GetPointeeType(lldb::opaque_compiler_type_t type) override;
+
+  CompilerType GetPointerType(lldb::opaque_compiler_type_t type) override;
+
+  CompilerType
+  GetLValueReferenceType(lldb::opaque_compiler_type_t type) override;
+
+  CompilerType
+  GetRValueReferenceType(lldb::opaque_compiler_type_t type) override;
+
+  CompilerType GetAtomicType(lldb::opaque_compiler_type_t type) override;
+
+  CompilerType AddConstModifier(lldb::opaque_compiler_type_t type) override;
+
+  CompilerType AddVolatileModifier(lldb::opaque_compiler_type_t type) override;
+
+  CompilerType AddRestrictModifier(lldb::opaque_compiler_type_t type) override;
+
+  CompilerType CreateTypedef(lldb::opaque_compiler_type_t type,
+                             const char *name,
+                             const CompilerDeclContext &decl_ctx) override;
+
+  // If the current object represents a typedef type, get the underlying type
+  CompilerType GetTypedefedType(lldb::opaque_compiler_type_t type) override;
+
+  // Create related types using the current type's AST
+  CompilerType GetBasicTypeFromAST(lldb::BasicType basic_type) override;
+
+  // Exploring the type
+
+  const llvm::fltSemantics &GetFloatTypeSemantics(size_t byte_size) override;
+
+  llvm::Optional<uint64_t> GetByteSize(lldb::opaque_compiler_type_t type,
+                       ExecutionContextScope *exe_scope) {
+    if (llvm::Optional<uint64_t> bit_size = GetBitSize(type, exe_scope))
+      return (*bit_size + 7) / 8;
+    return llvm::None;
+  }
+
+  llvm::Optional<uint64_t>
+  GetBitSize(lldb::opaque_compiler_type_t type,
+             ExecutionContextScope *exe_scope) override;
+
+  lldb::Encoding GetEncoding(lldb::opaque_compiler_type_t type,
+                             uint64_t &count) override;
+
+  lldb::Format GetFormat(lldb::opaque_compiler_type_t type) override;
+
+  llvm::Optional<size_t>
+  GetTypeBitAlign(lldb::opaque_compiler_type_t type,
+                  ExecutionContextScope *exe_scope) override;
+
+  uint32_t GetNumChildren(lldb::opaque_compiler_type_t type,
+                          bool omit_empty_base_classes,
+                          const ExecutionContext *exe_ctx) override;
+
+  CompilerType GetBuiltinTypeByName(ConstString name) override;
+
+  lldb::BasicType
+  GetBasicTypeEnumeration(lldb::opaque_compiler_type_t type) override;
+
+  static lldb::BasicType
+  GetBasicTypeEnumeration(lldb::opaque_compiler_type_t type,
+                          ConstString name);
+
+  void ForEachEnumerator(
+      lldb::opaque_compiler_type_t type,
+      std::function<bool(const CompilerType &integer_type,
+                         ConstString name,
+                         const llvm::APSInt &value)> const &callback) override;
+
+  uint32_t GetNumFields(lldb::opaque_compiler_type_t type) override;
+
+  CompilerType GetFieldAtIndex(lldb::opaque_compiler_type_t type, size_t idx,
+                               std::string &name, uint64_t *bit_offset_ptr,
+                               uint32_t *bitfield_bit_size_ptr,
+                               bool *is_bitfield_ptr) override;
+
+  uint32_t GetNumDirectBaseClasses(lldb::opaque_compiler_type_t type) override;
+
+  uint32_t GetNumVirtualBaseClasses(lldb::opaque_compiler_type_t type) override;
+
+  CompilerType GetDirectBaseClassAtIndex(lldb::opaque_compiler_type_t type,
+                                         size_t idx,
+                                         uint32_t *bit_offset_ptr) override;
+
+  CompilerType GetVirtualBaseClassAtIndex(lldb::opaque_compiler_type_t type,
+                                          size_t idx,
+                                          uint32_t *bit_offset_ptr) override;
+
+  static uint32_t GetNumPointeeChildren(clang::QualType type);
+
+  CompilerType GetChildCompilerTypeAtIndex(
+      lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx, size_t idx,
+      bool transparent_pointers, bool omit_empty_base_classes,
+      bool ignore_array_bounds, std::string &child_name,
+      uint32_t &child_byte_size, int32_t &child_byte_offset,
+      uint32_t &child_bitfield_bit_size, uint32_t &child_bitfield_bit_offset,
+      bool &child_is_base_class, bool &child_is_deref_of_parent,
+      ValueObject *valobj, uint64_t &language_flags) override;
+
+  // Lookup a child given a name. This function will match base class names and
+  // member member names in "clang_type" only, not descendants.
+  uint32_t GetIndexOfChildWithName(lldb::opaque_compiler_type_t type,
+                                   const char *name,
+                                   bool omit_empty_base_classes) override;
+
+  // Lookup a child member given a name. This function will match member names
+  // only and will descend into "clang_type" children in search for the first
+  // member in this class, or any base class that matches "name".
+  // TODO: Return all matches for a given name by returning a
+  // vector<vector<uint32_t>>
+  // so we catch all names that match a given child name, not just the first.
+  size_t
+  GetIndexOfChildMemberWithName(lldb::opaque_compiler_type_t type,
+                                const char *name, bool omit_empty_base_classes,
+                                std::vector<uint32_t> &child_indexes) override;
+
+  size_t GetNumTemplateArguments(lldb::opaque_compiler_type_t type) override;
+
+  lldb::TemplateArgumentKind
+  GetTemplateArgumentKind(lldb::opaque_compiler_type_t type,
+                          size_t idx) override;
+  CompilerType GetTypeTemplateArgument(lldb::opaque_compiler_type_t type,
+                                       size_t idx) override;
+  llvm::Optional<CompilerType::IntegralTemplateArgument>
+  GetIntegralTemplateArgument(lldb::opaque_compiler_type_t type,
+                              size_t idx) override;
+
+  CompilerType GetTypeForFormatters(void *type) override;
+
+#define LLDB_INVALID_DECL_LEVEL UINT32_MAX
+  // LLDB_INVALID_DECL_LEVEL is returned by CountDeclLevels if child_decl_ctx
+  // could not be found in decl_ctx.
+  uint32_t CountDeclLevels(clang::DeclContext *frame_decl_ctx,
+                           clang::DeclContext *child_decl_ctx,
+                           ConstString *child_name = nullptr,
+                           CompilerType *child_type = nullptr);
+
+  // Modifying RecordType
+  static clang::FieldDecl *AddFieldToRecordType(const CompilerType &type,
+                                                llvm::StringRef name,
+                                                const CompilerType &field_type,
+                                                lldb::AccessType access,
+                                                uint32_t bitfield_bit_size);
+
+  static void BuildIndirectFields(const CompilerType &type);
+
+  static void SetIsPacked(const CompilerType &type);
+
+  static clang::VarDecl *AddVariableToRecordType(const CompilerType &type,
+                                                 llvm::StringRef name,
+                                                 const CompilerType &var_type,
+                                                 lldb::AccessType access);
+
+  clang::CXXMethodDecl *AddMethodToCXXRecordType(
+      lldb::opaque_compiler_type_t type, llvm::StringRef name,
+      const char *mangled_name, const CompilerType &method_type,
+      lldb::AccessType access, bool is_virtual, bool is_static, bool is_inline,
+      bool is_explicit, bool is_attr_used, bool is_artificial);
+
+  void AddMethodOverridesForCXXRecordType(lldb::opaque_compiler_type_t type);
+
+  // C++ Base Classes
+  std::unique_ptr<clang::CXXBaseSpecifier>
+  CreateBaseClassSpecifier(lldb::opaque_compiler_type_t type,
+                           lldb::AccessType access, bool is_virtual,
+                           bool base_of_class);
+
+  bool TransferBaseClasses(
+      lldb::opaque_compiler_type_t type,
+      std::vector<std::unique_ptr<clang::CXXBaseSpecifier>> bases);
+
+  static bool SetObjCSuperClass(const CompilerType &type,
+                                const CompilerType &superclass_compiler_type);
+
+  static bool AddObjCClassProperty(const CompilerType &type,
+                                   const char *property_name,
+                                   const CompilerType &property_compiler_type,
+                                   clang::ObjCIvarDecl *ivar_decl,
+                                   const char *property_setter_name,
+                                   const char *property_getter_name,
+                                   uint32_t property_attributes,
+                                   ClangASTMetadata *metadata);
+
+  static clang::ObjCMethodDecl *AddMethodToObjCObjectType(
+      const CompilerType &type,
+      const char *name, // the full symbol name as seen in the symbol table
+                        // (lldb::opaque_compiler_type_t type, "-[NString
+                        // stringWithCString:]")
+      const CompilerType &method_compiler_type, lldb::AccessType access,
+      bool is_artificial, bool is_variadic, bool is_objc_direct_call);
+
+  static bool SetHasExternalStorage(lldb::opaque_compiler_type_t type,
+                                    bool has_extern);
+
+  // Tag Declarations
+  static bool StartTagDeclarationDefinition(const CompilerType &type);
+
+  static bool CompleteTagDeclarationDefinition(const CompilerType &type);
+
+  // Modifying Enumeration types
+  clang::EnumConstantDecl *AddEnumerationValueToEnumerationType(
+      const CompilerType &enum_type, const Declaration &decl, const char *name,
+      int64_t enum_value, uint32_t enum_value_bit_size);
+  clang::EnumConstantDecl *AddEnumerationValueToEnumerationType(
+      const CompilerType &enum_type, const Declaration &decl, const char *name,
+      const llvm::APSInt &value);
+
+  CompilerType GetEnumerationIntegerType(lldb::opaque_compiler_type_t type);
+
+  // Pointers & References
+
+  // Call this function using the class type when you want to make a member
+  // pointer type to pointee_type.
+  static CompilerType CreateMemberPointerType(const CompilerType &type,
+                                              const CompilerType &pointee_type);
+
+  // Dumping types
+#ifndef NDEBUG
+  /// Convenience LLVM-style dump method for use in the debugger only.
+  /// In contrast to the other \p Dump() methods this directly invokes
+  /// \p clang::QualType::dump().
+  LLVM_DUMP_METHOD void dump(lldb::opaque_compiler_type_t type) const override;
+#endif
+
+  void Dump(Stream &s);
+
+  /// Dump clang AST types from the symbol file.
+  ///
+  /// \param[in] s
+  ///       A stream to send the dumped AST node(s) to
+  /// \param[in] symbol_name
+  ///       The name of the symbol to dump, if it is empty dump all the symbols
+  void DumpFromSymbolFile(Stream &s, llvm::StringRef symbol_name);
+
+  void DumpValue(lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx,
+                 Stream *s, lldb::Format format, const DataExtractor &data,
+                 lldb::offset_t data_offset, size_t data_byte_size,
+                 uint32_t bitfield_bit_size, uint32_t bitfield_bit_offset,
+                 bool show_types, bool show_summary, bool verbose,
+                 uint32_t depth) override;
+
+  bool DumpTypeValue(lldb::opaque_compiler_type_t type, Stream *s,
+                     lldb::Format format, const DataExtractor &data,
+                     lldb::offset_t data_offset, size_t data_byte_size,
+                     uint32_t bitfield_bit_size, uint32_t bitfield_bit_offset,
+                     ExecutionContextScope *exe_scope) override;
+
+  void DumpSummary(lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx,
+                   Stream *s, const DataExtractor &data,
+                   lldb::offset_t data_offset, size_t data_byte_size) override;
+
+  void DumpTypeDescription(
+      lldb::opaque_compiler_type_t type) override; // Dump to stdout
+
+  void DumpTypeDescription(lldb::opaque_compiler_type_t type,
+                           Stream *s) override;
+
+  static void DumpTypeName(const CompilerType &type);
+
+  static clang::EnumDecl *GetAsEnumDecl(const CompilerType &type);
+
+  static clang::RecordDecl *GetAsRecordDecl(const CompilerType &type);
+
+  static clang::TagDecl *GetAsTagDecl(const CompilerType &type);
+
+  static clang::TypedefNameDecl *GetAsTypedefDecl(const CompilerType &type);
+
+  static clang::CXXRecordDecl *
+  GetAsCXXRecordDecl(lldb::opaque_compiler_type_t type);
+
+  static clang::ObjCInterfaceDecl *
+  GetAsObjCInterfaceDecl(const CompilerType &type);
+
+  clang::ClassTemplateDecl *ParseClassTemplateDecl(
+      clang::DeclContext *decl_ctx, lldb::AccessType access_type,
+      const char *parent_name, int tag_decl_kind,
+      const TypeSystemClang::TemplateParameterInfos &template_param_infos);
+
+  clang::BlockDecl *CreateBlockDeclaration(clang::DeclContext *ctx);
+
+  clang::UsingDirectiveDecl *
+  CreateUsingDirectiveDeclaration(clang::DeclContext *decl_ctx,
+                                  clang::NamespaceDecl *ns_decl);
+
+  clang::UsingDecl *CreateUsingDeclaration(clang::DeclContext *current_decl_ctx,
+                                           clang::NamedDecl *target);
+
+  clang::VarDecl *CreateVariableDeclaration(clang::DeclContext *decl_context,
+                                            const char *name,
+                                            clang::QualType type);
+
+  static lldb::opaque_compiler_type_t
+  GetOpaqueCompilerType(clang::ASTContext *ast, lldb::BasicType basic_type);
+
+  static clang::QualType GetQualType(lldb::opaque_compiler_type_t type) {
+    if (type)
+      return clang::QualType::getFromOpaquePtr(type);
+    return clang::QualType();
+  }
+
+  static clang::QualType
+  GetCanonicalQualType(lldb::opaque_compiler_type_t type) {
+    if (type)
+      return clang::QualType::getFromOpaquePtr(type).getCanonicalType();
+    return clang::QualType();
+  }
+
+  clang::DeclarationName
+  GetDeclarationName(const char *name, const CompilerType &function_clang_type);
+
+private:
+  const clang::ClassTemplateSpecializationDecl *
+  GetAsTemplateSpecialization(lldb::opaque_compiler_type_t type);
+
+  // Classes that inherit from TypeSystemClang can see and modify these
+  std::string m_target_triple;
+  std::unique_ptr<clang::ASTContext> m_ast_up;
+  std::unique_ptr<clang::LangOptions> m_language_options_up;
+  std::unique_ptr<clang::FileManager> m_file_manager_up;
+  std::unique_ptr<clang::SourceManager> m_source_manager_up;
+  std::unique_ptr<clang::DiagnosticsEngine> m_diagnostics_engine_up;
+  std::unique_ptr<clang::DiagnosticConsumer> m_diagnostic_consumer_up;
+  std::shared_ptr<clang::TargetOptions> m_target_options_rp;
+  std::unique_ptr<clang::TargetInfo> m_target_info_up;
+  std::unique_ptr<clang::IdentifierTable> m_identifier_table_up;
+  std::unique_ptr<clang::SelectorTable> m_selector_table_up;
+  std::unique_ptr<clang::Builtin::Context> m_builtins_up;
+  std::unique_ptr<DWARFASTParserClang> m_dwarf_ast_parser_up;
+  std::unique_ptr<PDBASTParser> m_pdb_ast_parser_up;
+  std::unique_ptr<clang::MangleContext> m_mangle_ctx_up;
+  uint32_t m_pointer_byte_size = 0;
+  bool m_ast_owned = false;
+  /// A string describing what this TypeSystemClang represents (e.g.,
+  /// AST for debug information, an expression, some other utility ClangAST).
+  /// Useful for logging and debugging.
+  std::string m_display_name;
+
+  typedef llvm::DenseMap<const clang::Decl *, ClangASTMetadata> DeclMetadataMap;
+  /// Maps Decls to their associated ClangASTMetadata.
+  DeclMetadataMap m_decl_metadata;
+
+  typedef llvm::DenseMap<const clang::Type *, ClangASTMetadata> TypeMetadataMap;
+  /// Maps Types to their associated ClangASTMetadata.
+  TypeMetadataMap m_type_metadata;
+
+  /// The sema associated that is currently used to build this ASTContext.
+  /// May be null if we are already done parsing this ASTContext or the
+  /// ASTContext wasn't created by parsing source code.
+  clang::Sema *m_sema = nullptr;
+
+  // For TypeSystemClang only
+  TypeSystemClang(const TypeSystemClang &);
+  const TypeSystemClang &operator=(const TypeSystemClang &);
+  /// Creates the internal ASTContext.
+  void CreateASTContext();
+  void SetTargetTriple(llvm::StringRef target_triple);
+};
+
+class TypeSystemClangForExpressions : public TypeSystemClang {
+public:
+  TypeSystemClangForExpressions(Target &target, llvm::Triple triple);
+
+  ~TypeSystemClangForExpressions() override = default;
+
+  void Finalize() override;
+
+  UserExpression *
+  GetUserExpression(llvm::StringRef expr, llvm::StringRef prefix,
+                    lldb::LanguageType language,
+                    Expression::ResultType desired_type,
+                    const EvaluateExpressionOptions &options,
+                    ValueObject *ctx_obj) override;
+
+  FunctionCaller *GetFunctionCaller(const CompilerType &return_type,
+                                    const Address &function_address,
+                                    const ValueList &arg_value_list,
+                                    const char *name) override;
+
+  UtilityFunction *GetUtilityFunction(const char *text,
+                                      const char *name) override;
+
+  PersistentExpressionState *GetPersistentExpressionState() override;
+private:
+  lldb::TargetWP m_target_wp;
+  std::unique_ptr<ClangPersistentVariables>
+      m_persistent_variables; // These are the persistent variables associated
+                              // with this process for the expression parser
+  std::unique_ptr<ClangASTSource> m_scratch_ast_source_up;
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_TypeSystemClang_h_
index 46fb9a892c3e9285ccb00f6fddd9b959992cb3fe..95bf156ff538ba0ac643744e9fc2645338b4b00b 100644 (file)
@@ -7,17 +7,11 @@ endif()
 add_lldb_library(lldbSymbol
   ArmUnwindInfo.cpp
   Block.cpp
-  TypeSystemClang.cpp
-  ClangASTImporter.cpp
-  ClangASTMetadata.cpp
-  ClangExternalASTSourceCallbacks.cpp
-  ClangUtil.cpp
   CompactUnwindInfo.cpp
   CompileUnit.cpp
   CompilerDecl.cpp
   CompilerDeclContext.cpp
   CompilerType.cpp
-  CxxModuleHandler.cpp
   DWARFCallFrameInfo.cpp
   DebugMacros.cpp
   Declaration.cpp
@@ -51,16 +45,7 @@ add_lldb_library(lldbSymbol
     lldbHost
     lldbTarget
     lldbUtility
-    lldbPluginExpressionParserClang
-    lldbPluginSymbolFileDWARF
-    lldbPluginSymbolFilePDB
     lldbPluginObjCLanguage
-    lldbPluginObjCRuntime
-
-  CLANG_LIBS
-    clangAST
-    clangBasic
-    clangFrontend
 
   LINK_COMPONENTS
     Support
diff --git a/lldb/source/Symbol/ClangASTImporter.cpp b/lldb/source/Symbol/ClangASTImporter.cpp
deleted file mode 100644 (file)
index 10e9868..0000000
+++ /dev/null
@@ -1,1151 +0,0 @@
-//===-- ClangASTImporter.cpp ----------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "lldb/Symbol/ClangASTImporter.h"
-#include "lldb/Core/Module.h"
-#include "lldb/Symbol/TypeSystemClang.h"
-#include "lldb/Symbol/ClangASTMetadata.h"
-#include "lldb/Symbol/ClangUtil.h"
-#include "lldb/Utility/LLDBAssert.h"
-#include "lldb/Utility/Log.h"
-#include "clang/AST/Decl.h"
-#include "clang/AST/DeclCXX.h"
-#include "clang/AST/DeclObjC.h"
-#include "clang/Sema/Lookup.h"
-#include "clang/Sema/Sema.h"
-#include "llvm/Support/raw_ostream.h"
-
-#include <memory>
-
-using namespace lldb_private;
-using namespace clang;
-
-CompilerType ClangASTImporter::CopyType(TypeSystemClang &dst_ast,
-                                        const CompilerType &src_type) {
-  clang::ASTContext &dst_clang_ast = dst_ast.getASTContext();
-
-  TypeSystemClang *src_ast =
-      llvm::dyn_cast_or_null<TypeSystemClang>(src_type.GetTypeSystem());
-  if (!src_ast)
-    return CompilerType();
-
-  clang::ASTContext &src_clang_ast = src_ast->getASTContext();
-
-  clang::QualType src_qual_type = ClangUtil::GetQualType(src_type);
-
-  ImporterDelegateSP delegate_sp(GetDelegate(&dst_clang_ast, &src_clang_ast));
-  if (!delegate_sp)
-    return CompilerType();
-
-  ASTImporterDelegate::CxxModuleScope std_scope(*delegate_sp, &dst_clang_ast);
-
-  llvm::Expected<QualType> ret_or_error = delegate_sp->Import(src_qual_type);
-  if (!ret_or_error) {
-    Log *log =
-      lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS);
-    LLDB_LOG_ERROR(log, ret_or_error.takeError(),
-        "Couldn't import type: {0}");
-    return CompilerType();
-  }
-
-  lldb::opaque_compiler_type_t dst_clang_type = ret_or_error->getAsOpaquePtr();
-
-  if (dst_clang_type)
-    return CompilerType(&dst_ast, dst_clang_type);
-  return CompilerType();
-}
-
-clang::Decl *ClangASTImporter::CopyDecl(clang::ASTContext *dst_ast,
-                                        clang::Decl *decl) {
-  ImporterDelegateSP delegate_sp;
-
-  clang::ASTContext *src_ast = &decl->getASTContext();
-  delegate_sp = GetDelegate(dst_ast, src_ast);
-
-  ASTImporterDelegate::CxxModuleScope std_scope(*delegate_sp, dst_ast);
-
-  if (!delegate_sp)
-    return nullptr;
-
-  llvm::Expected<clang::Decl *> result = delegate_sp->Import(decl);
-  if (!result) {
-    Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
-    LLDB_LOG_ERROR(log, result.takeError(), "Couldn't import decl: {0}");
-    if (log) {
-      lldb::user_id_t user_id = LLDB_INVALID_UID;
-      ClangASTMetadata *metadata = GetDeclMetadata(decl);
-      if (metadata)
-        user_id = metadata->GetUserID();
-
-      if (NamedDecl *named_decl = dyn_cast<NamedDecl>(decl))
-        LLDB_LOG(log,
-                 "  [ClangASTImporter] WARNING: Failed to import a {0} "
-                 "'{1}', metadata {2}",
-                 decl->getDeclKindName(), named_decl->getNameAsString(),
-                 user_id);
-      else
-        LLDB_LOG(log,
-                 "  [ClangASTImporter] WARNING: Failed to import a {0}, "
-                 "metadata {1}",
-                 decl->getDeclKindName(), user_id);
-    }
-    return nullptr;
-  }
-
-  return *result;
-}
-
-class DeclContextOverride {
-private:
-  struct Backup {
-    clang::DeclContext *decl_context;
-    clang::DeclContext *lexical_decl_context;
-  };
-
-  llvm::DenseMap<clang::Decl *, Backup> m_backups;
-
-  void OverrideOne(clang::Decl *decl) {
-    if (m_backups.find(decl) != m_backups.end()) {
-      return;
-    }
-
-    m_backups[decl] = {decl->getDeclContext(), decl->getLexicalDeclContext()};
-
-    decl->setDeclContext(decl->getASTContext().getTranslationUnitDecl());
-    decl->setLexicalDeclContext(decl->getASTContext().getTranslationUnitDecl());
-  }
-
-  bool ChainPassesThrough(
-      clang::Decl *decl, clang::DeclContext *base,
-      clang::DeclContext *(clang::Decl::*contextFromDecl)(),
-      clang::DeclContext *(clang::DeclContext::*contextFromContext)()) {
-    for (DeclContext *decl_ctx = (decl->*contextFromDecl)(); decl_ctx;
-         decl_ctx = (decl_ctx->*contextFromContext)()) {
-      if (decl_ctx == base) {
-        return true;
-      }
-    }
-
-    return false;
-  }
-
-  clang::Decl *GetEscapedChild(clang::Decl *decl,
-                               clang::DeclContext *base = nullptr) {
-    if (base) {
-      // decl's DeclContext chains must pass through base.
-
-      if (!ChainPassesThrough(decl, base, &clang::Decl::getDeclContext,
-                              &clang::DeclContext::getParent) ||
-          !ChainPassesThrough(decl, base, &clang::Decl::getLexicalDeclContext,
-                              &clang::DeclContext::getLexicalParent)) {
-        return decl;
-      }
-    } else {
-      base = clang::dyn_cast<clang::DeclContext>(decl);
-
-      if (!base) {
-        return nullptr;
-      }
-    }
-
-    if (clang::DeclContext *context =
-            clang::dyn_cast<clang::DeclContext>(decl)) {
-      for (clang::Decl *decl : context->decls()) {
-        if (clang::Decl *escaped_child = GetEscapedChild(decl)) {
-          return escaped_child;
-        }
-      }
-    }
-
-    return nullptr;
-  }
-
-  void Override(clang::Decl *decl) {
-    if (clang::Decl *escaped_child = GetEscapedChild(decl)) {
-      Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
-
-      LLDB_LOG(log,
-               "    [ClangASTImporter] DeclContextOverride couldn't "
-               "override ({0}Decl*){1} - its child ({2}Decl*){3} escapes",
-               decl->getDeclKindName(), decl, escaped_child->getDeclKindName(),
-               escaped_child);
-      lldbassert(0 && "Couldn't override!");
-    }
-
-    OverrideOne(decl);
-  }
-
-public:
-  DeclContextOverride() {}
-
-  void OverrideAllDeclsFromContainingFunction(clang::Decl *decl) {
-    for (DeclContext *decl_context = decl->getLexicalDeclContext();
-         decl_context; decl_context = decl_context->getLexicalParent()) {
-      DeclContext *redecl_context = decl_context->getRedeclContext();
-
-      if (llvm::isa<FunctionDecl>(redecl_context) &&
-          llvm::isa<TranslationUnitDecl>(redecl_context->getLexicalParent())) {
-        for (clang::Decl *child_decl : decl_context->decls()) {
-          Override(child_decl);
-        }
-      }
-    }
-  }
-
-  ~DeclContextOverride() {
-    for (const std::pair<clang::Decl *, Backup> &backup : m_backups) {
-      backup.first->setDeclContext(backup.second.decl_context);
-      backup.first->setLexicalDeclContext(backup.second.lexical_decl_context);
-    }
-  }
-};
-
-namespace {
-/// Completes all imported TagDecls at the end of the scope.
-///
-/// While in a CompleteTagDeclsScope, every decl that could be completed will
-/// be completed at the end of the scope (including all Decls that are
-/// imported while completing the original Decls).
-class CompleteTagDeclsScope : public ClangASTImporter::NewDeclListener {
-  ClangASTImporter::ImporterDelegateSP m_delegate;
-  llvm::SmallVector<NamedDecl *, 32> m_decls_to_complete;
-  llvm::SmallPtrSet<NamedDecl *, 32> m_decls_already_completed;
-  clang::ASTContext *m_dst_ctx;
-  clang::ASTContext *m_src_ctx;
-  ClangASTImporter &importer;
-
-public:
-  /// Constructs a CompleteTagDeclsScope.
-  /// \param importer The ClangASTImporter that we should observe.
-  /// \param dst_ctx The ASTContext to which Decls are imported.
-  /// \param src_ctx The ASTContext from which Decls are imported.
-  explicit CompleteTagDeclsScope(ClangASTImporter &importer,
-                            clang::ASTContext *dst_ctx,
-                            clang::ASTContext *src_ctx)
-      : m_delegate(importer.GetDelegate(dst_ctx, src_ctx)), m_dst_ctx(dst_ctx),
-        m_src_ctx(src_ctx), importer(importer) {
-    m_delegate->SetImportListener(this);
-  }
-
-  virtual ~CompleteTagDeclsScope() {
-    ClangASTImporter::ASTContextMetadataSP to_context_md =
-        importer.GetContextMetadata(m_dst_ctx);
-
-    // Complete all decls we collected until now.
-    while (!m_decls_to_complete.empty()) {
-      NamedDecl *decl = m_decls_to_complete.pop_back_val();
-      m_decls_already_completed.insert(decl);
-
-      // We should only complete decls coming from the source context.
-      assert(to_context_md->m_origins[decl].ctx == m_src_ctx);
-
-      Decl *original_decl = to_context_md->m_origins[decl].decl;
-
-      // Complete the decl now.
-      TypeSystemClang::GetCompleteDecl(m_src_ctx, original_decl);
-      if (auto *tag_decl = dyn_cast<TagDecl>(decl)) {
-        if (auto *original_tag_decl = dyn_cast<TagDecl>(original_decl)) {
-          if (original_tag_decl->isCompleteDefinition()) {
-            m_delegate->ImportDefinitionTo(tag_decl, original_tag_decl);
-            tag_decl->setCompleteDefinition(true);
-          }
-        }
-
-        tag_decl->setHasExternalLexicalStorage(false);
-        tag_decl->setHasExternalVisibleStorage(false);
-      } else if (auto *container_decl = dyn_cast<ObjCContainerDecl>(decl)) {
-        container_decl->setHasExternalLexicalStorage(false);
-        container_decl->setHasExternalVisibleStorage(false);
-      }
-
-      to_context_md->m_origins.erase(decl);
-    }
-
-    // Stop listening to imported decls. We do this after clearing the
-    // Decls we needed to import to catch all Decls they might have pulled in.
-    m_delegate->RemoveImportListener();
-  }
-
-  void NewDeclImported(clang::Decl *from, clang::Decl *to) override {
-    // Filter out decls that we can't complete later.
-    if (!isa<TagDecl>(to) && !isa<ObjCInterfaceDecl>(to))
-      return;
-    RecordDecl *from_record_decl = dyn_cast<RecordDecl>(from);
-    // We don't need to complete injected class name decls.
-    if (from_record_decl && from_record_decl->isInjectedClassName())
-      return;
-
-    NamedDecl *to_named_decl = dyn_cast<NamedDecl>(to);
-    // Check if we already completed this type.
-    if (m_decls_already_completed.count(to_named_decl) != 0)
-      return;
-    m_decls_to_complete.push_back(to_named_decl);
-  }
-};
-} // namespace
-
-CompilerType ClangASTImporter::DeportType(TypeSystemClang &dst,
-                                          const CompilerType &src_type) {
-  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
-
-  TypeSystemClang *src_ctxt =
-      llvm::cast<TypeSystemClang>(src_type.GetTypeSystem());
-
-  LLDB_LOG(log,
-           "    [ClangASTImporter] DeportType called on ({0}Type*){1} "
-           "from (ASTContext*){2} to (ASTContext*){3}",
-           src_type.GetTypeName(), src_type.GetOpaqueQualType(),
-           &src_ctxt->getASTContext(), &dst.getASTContext());
-
-  DeclContextOverride decl_context_override;
-
-  if (auto *t = ClangUtil::GetQualType(src_type)->getAs<TagType>())
-    decl_context_override.OverrideAllDeclsFromContainingFunction(t->getDecl());
-
-  CompleteTagDeclsScope complete_scope(*this, &dst.getASTContext(),
-                                       &src_ctxt->getASTContext());
-  return CopyType(dst, src_type);
-}
-
-clang::Decl *ClangASTImporter::DeportDecl(clang::ASTContext *dst_ctx,
-                                          clang::Decl *decl) {
-  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
-
-  clang::ASTContext *src_ctx = &decl->getASTContext();
-  LLDB_LOG(log,
-           "    [ClangASTImporter] DeportDecl called on ({0}Decl*){1} from "
-           "(ASTContext*){2} to (ASTContext*){3}",
-           decl->getDeclKindName(), decl, src_ctx, dst_ctx);
-
-  DeclContextOverride decl_context_override;
-
-  decl_context_override.OverrideAllDeclsFromContainingFunction(decl);
-
-  clang::Decl *result;
-  {
-    CompleteTagDeclsScope complete_scope(*this, dst_ctx, src_ctx);
-    result = CopyDecl(dst_ctx, decl);
-  }
-
-  if (!result)
-    return nullptr;
-
-  LLDB_LOG(log,
-           "    [ClangASTImporter] DeportDecl deported ({0}Decl*){1} to "
-           "({2}Decl*){3}",
-           decl->getDeclKindName(), decl, result->getDeclKindName(), result);
-
-  return result;
-}
-
-bool ClangASTImporter::CanImport(const CompilerType &type) {
-  if (!ClangUtil::IsClangType(type))
-    return false;
-
-  // TODO: remove external completion BOOL
-  // CompleteAndFetchChildren should get the Decl out and check for the
-
-  clang::QualType qual_type(
-      ClangUtil::GetCanonicalQualType(ClangUtil::RemoveFastQualifiers(type)));
-
-  const clang::Type::TypeClass type_class = qual_type->getTypeClass();
-  switch (type_class) {
-  case clang::Type::Record: {
-    const clang::CXXRecordDecl *cxx_record_decl =
-        qual_type->getAsCXXRecordDecl();
-    if (cxx_record_decl) {
-      if (GetDeclOrigin(cxx_record_decl).Valid())
-        return true;
-    }
-  } break;
-
-  case clang::Type::Enum: {
-    clang::EnumDecl *enum_decl =
-        llvm::cast<clang::EnumType>(qual_type)->getDecl();
-    if (enum_decl) {
-      if (GetDeclOrigin(enum_decl).Valid())
-        return true;
-    }
-  } break;
-
-  case clang::Type::ObjCObject:
-  case clang::Type::ObjCInterface: {
-    const clang::ObjCObjectType *objc_class_type =
-        llvm::dyn_cast<clang::ObjCObjectType>(qual_type);
-    if (objc_class_type) {
-      clang::ObjCInterfaceDecl *class_interface_decl =
-          objc_class_type->getInterface();
-      // We currently can't complete objective C types through the newly added
-      // ASTContext because it only supports TagDecl objects right now...
-      if (class_interface_decl) {
-        if (GetDeclOrigin(class_interface_decl).Valid())
-          return true;
-      }
-    }
-  } break;
-
-  case clang::Type::Typedef:
-    return CanImport(CompilerType(type.GetTypeSystem(),
-                                  llvm::cast<clang::TypedefType>(qual_type)
-                                      ->getDecl()
-                                      ->getUnderlyingType()
-                                      .getAsOpaquePtr()));
-
-  case clang::Type::Auto:
-    return CanImport(CompilerType(type.GetTypeSystem(),
-                                  llvm::cast<clang::AutoType>(qual_type)
-                                      ->getDeducedType()
-                                      .getAsOpaquePtr()));
-
-  case clang::Type::Elaborated:
-    return CanImport(CompilerType(type.GetTypeSystem(),
-                                  llvm::cast<clang::ElaboratedType>(qual_type)
-                                      ->getNamedType()
-                                      .getAsOpaquePtr()));
-
-  case clang::Type::Paren:
-    return CanImport(CompilerType(
-        type.GetTypeSystem(),
-        llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr()));
-
-  default:
-    break;
-  }
-
-  return false;
-}
-
-bool ClangASTImporter::Import(const CompilerType &type) {
-  if (!ClangUtil::IsClangType(type))
-    return false;
-  // TODO: remove external completion BOOL
-  // CompleteAndFetchChildren should get the Decl out and check for the
-
-  clang::QualType qual_type(
-      ClangUtil::GetCanonicalQualType(ClangUtil::RemoveFastQualifiers(type)));
-
-  const clang::Type::TypeClass type_class = qual_type->getTypeClass();
-  switch (type_class) {
-  case clang::Type::Record: {
-    const clang::CXXRecordDecl *cxx_record_decl =
-        qual_type->getAsCXXRecordDecl();
-    if (cxx_record_decl) {
-      if (GetDeclOrigin(cxx_record_decl).Valid())
-        return CompleteAndFetchChildren(qual_type);
-    }
-  } break;
-
-  case clang::Type::Enum: {
-    clang::EnumDecl *enum_decl =
-        llvm::cast<clang::EnumType>(qual_type)->getDecl();
-    if (enum_decl) {
-      if (GetDeclOrigin(enum_decl).Valid())
-        return CompleteAndFetchChildren(qual_type);
-    }
-  } break;
-
-  case clang::Type::ObjCObject:
-  case clang::Type::ObjCInterface: {
-    const clang::ObjCObjectType *objc_class_type =
-        llvm::dyn_cast<clang::ObjCObjectType>(qual_type);
-    if (objc_class_type) {
-      clang::ObjCInterfaceDecl *class_interface_decl =
-          objc_class_type->getInterface();
-      // We currently can't complete objective C types through the newly added
-      // ASTContext because it only supports TagDecl objects right now...
-      if (class_interface_decl) {
-        if (GetDeclOrigin(class_interface_decl).Valid())
-          return CompleteAndFetchChildren(qual_type);
-      }
-    }
-  } break;
-
-  case clang::Type::Typedef:
-    return Import(CompilerType(type.GetTypeSystem(),
-                               llvm::cast<clang::TypedefType>(qual_type)
-                                   ->getDecl()
-                                   ->getUnderlyingType()
-                                   .getAsOpaquePtr()));
-
-  case clang::Type::Auto:
-    return Import(CompilerType(type.GetTypeSystem(),
-                               llvm::cast<clang::AutoType>(qual_type)
-                                   ->getDeducedType()
-                                   .getAsOpaquePtr()));
-
-  case clang::Type::Elaborated:
-    return Import(CompilerType(type.GetTypeSystem(),
-                               llvm::cast<clang::ElaboratedType>(qual_type)
-                                   ->getNamedType()
-                                   .getAsOpaquePtr()));
-
-  case clang::Type::Paren:
-    return Import(CompilerType(
-        type.GetTypeSystem(),
-        llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr()));
-
-  default:
-    break;
-  }
-  return false;
-}
-
-bool ClangASTImporter::CompleteType(const CompilerType &compiler_type) {
-  if (!CanImport(compiler_type))
-    return false;
-
-  if (Import(compiler_type)) {
-    TypeSystemClang::CompleteTagDeclarationDefinition(compiler_type);
-    return true;
-  }
-
-  TypeSystemClang::SetHasExternalStorage(compiler_type.GetOpaqueQualType(),
-                                         false);
-  return false;
-}
-
-bool ClangASTImporter::LayoutRecordType(
-    const clang::RecordDecl *record_decl, uint64_t &bit_size,
-    uint64_t &alignment,
-    llvm::DenseMap<const clang::FieldDecl *, uint64_t> &field_offsets,
-    llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits>
-        &base_offsets,
-    llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits>
-        &vbase_offsets) {
-  RecordDeclToLayoutMap::iterator pos =
-      m_record_decl_to_layout_map.find(record_decl);
-  bool success = false;
-  base_offsets.clear();
-  vbase_offsets.clear();
-  if (pos != m_record_decl_to_layout_map.end()) {
-    bit_size = pos->second.bit_size;
-    alignment = pos->second.alignment;
-    field_offsets.swap(pos->second.field_offsets);
-    base_offsets.swap(pos->second.base_offsets);
-    vbase_offsets.swap(pos->second.vbase_offsets);
-    m_record_decl_to_layout_map.erase(pos);
-    success = true;
-  } else {
-    bit_size = 0;
-    alignment = 0;
-    field_offsets.clear();
-  }
-  return success;
-}
-
-void ClangASTImporter::SetRecordLayout(clang::RecordDecl *decl,
-                                        const LayoutInfo &layout) {
-  m_record_decl_to_layout_map.insert(std::make_pair(decl, layout));
-}
-
-bool ClangASTImporter::CompleteTagDecl(clang::TagDecl *decl) {
-  DeclOrigin decl_origin = GetDeclOrigin(decl);
-
-  if (!decl_origin.Valid())
-    return false;
-
-  if (!TypeSystemClang::GetCompleteDecl(decl_origin.ctx, decl_origin.decl))
-    return false;
-
-  ImporterDelegateSP delegate_sp(
-      GetDelegate(&decl->getASTContext(), decl_origin.ctx));
-
-  ASTImporterDelegate::CxxModuleScope std_scope(*delegate_sp,
-                                                &decl->getASTContext());
-  if (delegate_sp)
-    delegate_sp->ImportDefinitionTo(decl, decl_origin.decl);
-
-  return true;
-}
-
-bool ClangASTImporter::CompleteTagDeclWithOrigin(clang::TagDecl *decl,
-                                                 clang::TagDecl *origin_decl) {
-  clang::ASTContext *origin_ast_ctx = &origin_decl->getASTContext();
-
-  if (!TypeSystemClang::GetCompleteDecl(origin_ast_ctx, origin_decl))
-    return false;
-
-  ImporterDelegateSP delegate_sp(
-      GetDelegate(&decl->getASTContext(), origin_ast_ctx));
-
-  if (delegate_sp)
-    delegate_sp->ImportDefinitionTo(decl, origin_decl);
-
-  ASTContextMetadataSP context_md = GetContextMetadata(&decl->getASTContext());
-
-  OriginMap &origins = context_md->m_origins;
-
-  origins[decl] = DeclOrigin(origin_ast_ctx, origin_decl);
-
-  return true;
-}
-
-bool ClangASTImporter::CompleteObjCInterfaceDecl(
-    clang::ObjCInterfaceDecl *interface_decl) {
-  DeclOrigin decl_origin = GetDeclOrigin(interface_decl);
-
-  if (!decl_origin.Valid())
-    return false;
-
-  if (!TypeSystemClang::GetCompleteDecl(decl_origin.ctx, decl_origin.decl))
-    return false;
-
-  ImporterDelegateSP delegate_sp(
-      GetDelegate(&interface_decl->getASTContext(), decl_origin.ctx));
-
-  if (delegate_sp)
-    delegate_sp->ImportDefinitionTo(interface_decl, decl_origin.decl);
-
-  if (ObjCInterfaceDecl *super_class = interface_decl->getSuperClass())
-    RequireCompleteType(clang::QualType(super_class->getTypeForDecl(), 0));
-
-  return true;
-}
-
-bool ClangASTImporter::CompleteAndFetchChildren(clang::QualType type) {
-  if (!RequireCompleteType(type))
-    return false;
-
-  Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS);
-
-  if (const TagType *tag_type = type->getAs<TagType>()) {
-    TagDecl *tag_decl = tag_type->getDecl();
-
-    DeclOrigin decl_origin = GetDeclOrigin(tag_decl);
-
-    if (!decl_origin.Valid())
-      return false;
-
-    ImporterDelegateSP delegate_sp(
-        GetDelegate(&tag_decl->getASTContext(), decl_origin.ctx));
-
-    ASTImporterDelegate::CxxModuleScope std_scope(*delegate_sp,
-                                                  &tag_decl->getASTContext());
-
-    TagDecl *origin_tag_decl = llvm::dyn_cast<TagDecl>(decl_origin.decl);
-
-    for (Decl *origin_child_decl : origin_tag_decl->decls()) {
-      llvm::Expected<Decl *> imported_or_err =
-          delegate_sp->Import(origin_child_decl);
-      if (!imported_or_err) {
-        LLDB_LOG_ERROR(log, imported_or_err.takeError(),
-                       "Couldn't import decl: {0}");
-        return false;
-      }
-    }
-
-    if (RecordDecl *record_decl = dyn_cast<RecordDecl>(origin_tag_decl))
-      record_decl->setHasLoadedFieldsFromExternalStorage(true);
-
-    return true;
-  }
-
-  if (const ObjCObjectType *objc_object_type = type->getAs<ObjCObjectType>()) {
-    if (ObjCInterfaceDecl *objc_interface_decl =
-            objc_object_type->getInterface()) {
-      DeclOrigin decl_origin = GetDeclOrigin(objc_interface_decl);
-
-      if (!decl_origin.Valid())
-        return false;
-
-      ImporterDelegateSP delegate_sp(
-          GetDelegate(&objc_interface_decl->getASTContext(), decl_origin.ctx));
-
-      ObjCInterfaceDecl *origin_interface_decl =
-          llvm::dyn_cast<ObjCInterfaceDecl>(decl_origin.decl);
-
-      for (Decl *origin_child_decl : origin_interface_decl->decls()) {
-        llvm::Expected<Decl *> imported_or_err =
-            delegate_sp->Import(origin_child_decl);
-        if (!imported_or_err) {
-          LLDB_LOG_ERROR(log, imported_or_err.takeError(),
-                         "Couldn't import decl: {0}");
-          return false;
-        }
-      }
-
-      return true;
-    }
-    return false;
-  }
-
-  return true;
-}
-
-bool ClangASTImporter::RequireCompleteType(clang::QualType type) {
-  if (type.isNull())
-    return false;
-
-  if (const TagType *tag_type = type->getAs<TagType>()) {
-    TagDecl *tag_decl = tag_type->getDecl();
-
-    if (tag_decl->getDefinition() || tag_decl->isBeingDefined())
-      return true;
-
-    return CompleteTagDecl(tag_decl);
-  }
-  if (const ObjCObjectType *objc_object_type = type->getAs<ObjCObjectType>()) {
-    if (ObjCInterfaceDecl *objc_interface_decl =
-            objc_object_type->getInterface())
-      return CompleteObjCInterfaceDecl(objc_interface_decl);
-    return false;
-  }
-  if (const ArrayType *array_type = type->getAsArrayTypeUnsafe())
-    return RequireCompleteType(array_type->getElementType());
-  if (const AtomicType *atomic_type = type->getAs<AtomicType>())
-    return RequireCompleteType(atomic_type->getPointeeType());
-
-  return true;
-}
-
-ClangASTMetadata *ClangASTImporter::GetDeclMetadata(const clang::Decl *decl) {
-  DeclOrigin decl_origin = GetDeclOrigin(decl);
-
-  if (decl_origin.Valid()) {
-    TypeSystemClang *ast = TypeSystemClang::GetASTContext(decl_origin.ctx);
-    return ast->GetMetadata(decl_origin.decl);
-  }
-  TypeSystemClang *ast = TypeSystemClang::GetASTContext(&decl->getASTContext());
-  return ast->GetMetadata(decl);
-}
-
-ClangASTImporter::DeclOrigin
-ClangASTImporter::GetDeclOrigin(const clang::Decl *decl) {
-  ASTContextMetadataSP context_md = GetContextMetadata(&decl->getASTContext());
-
-  OriginMap &origins = context_md->m_origins;
-
-  OriginMap::iterator iter = origins.find(decl);
-
-  if (iter != origins.end())
-    return iter->second;
-  return DeclOrigin();
-}
-
-void ClangASTImporter::SetDeclOrigin(const clang::Decl *decl,
-                                     clang::Decl *original_decl) {
-  ASTContextMetadataSP context_md = GetContextMetadata(&decl->getASTContext());
-
-  OriginMap &origins = context_md->m_origins;
-
-  OriginMap::iterator iter = origins.find(decl);
-
-  if (iter != origins.end()) {
-    iter->second.decl = original_decl;
-    iter->second.ctx = &original_decl->getASTContext();
-    return;
-  }
-  origins[decl] = DeclOrigin(&original_decl->getASTContext(), original_decl);
-}
-
-void ClangASTImporter::RegisterNamespaceMap(const clang::NamespaceDecl *decl,
-                                            NamespaceMapSP &namespace_map) {
-  ASTContextMetadataSP context_md = GetContextMetadata(&decl->getASTContext());
-
-  context_md->m_namespace_maps[decl] = namespace_map;
-}
-
-ClangASTImporter::NamespaceMapSP
-ClangASTImporter::GetNamespaceMap(const clang::NamespaceDecl *decl) {
-  ASTContextMetadataSP context_md = GetContextMetadata(&decl->getASTContext());
-
-  NamespaceMetaMap &namespace_maps = context_md->m_namespace_maps;
-
-  NamespaceMetaMap::iterator iter = namespace_maps.find(decl);
-
-  if (iter != namespace_maps.end())
-    return iter->second;
-  return NamespaceMapSP();
-}
-
-void ClangASTImporter::BuildNamespaceMap(const clang::NamespaceDecl *decl) {
-  assert(decl);
-  ASTContextMetadataSP context_md = GetContextMetadata(&decl->getASTContext());
-
-  const DeclContext *parent_context = decl->getDeclContext();
-  const NamespaceDecl *parent_namespace =
-      dyn_cast<NamespaceDecl>(parent_context);
-  NamespaceMapSP parent_map;
-
-  if (parent_namespace)
-    parent_map = GetNamespaceMap(parent_namespace);
-
-  NamespaceMapSP new_map;
-
-  new_map = std::make_shared<NamespaceMap>();
-
-  if (context_md->m_map_completer) {
-    std::string namespace_string = decl->getDeclName().getAsString();
-
-    context_md->m_map_completer->CompleteNamespaceMap(
-        new_map, ConstString(namespace_string.c_str()), parent_map);
-  }
-
-  context_md->m_namespace_maps[decl] = new_map;
-}
-
-void ClangASTImporter::ForgetDestination(clang::ASTContext *dst_ast) {
-  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
-
-  LLDB_LOG(log,
-           "    [ClangASTImporter] Forgetting destination (ASTContext*){0}",
-           dst_ast);
-
-  m_metadata_map.erase(dst_ast);
-}
-
-void ClangASTImporter::ForgetSource(clang::ASTContext *dst_ast,
-                                    clang::ASTContext *src_ast) {
-  ASTContextMetadataSP md = MaybeGetContextMetadata(dst_ast);
-
-  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
-
-  LLDB_LOG(log,
-           "    [ClangASTImporter] Forgetting source->dest "
-           "(ASTContext*){0}->(ASTContext*){1}",
-           src_ast, dst_ast);
-
-  if (!md)
-    return;
-
-  md->m_delegates.erase(src_ast);
-
-  for (OriginMap::iterator iter = md->m_origins.begin();
-       iter != md->m_origins.end();) {
-    if (iter->second.ctx == src_ast)
-      md->m_origins.erase(iter++);
-    else
-      ++iter;
-  }
-}
-
-ClangASTImporter::MapCompleter::~MapCompleter() { return; }
-
-llvm::Expected<Decl *>
-ClangASTImporter::ASTImporterDelegate::ImportImpl(Decl *From) {
-  if (m_std_handler) {
-    llvm::Optional<Decl *> D = m_std_handler->Import(From);
-    if (D) {
-      // Make sure we don't use this decl later to map it back to it's original
-      // decl. The decl the CxxModuleHandler created has nothing to do with
-      // the one from debug info, and linking those two would just cause the
-      // ASTImporter to try 'updating' the module decl with the minimal one from
-      // the debug info.
-      m_decls_to_ignore.insert(*D);
-      return *D;
-    }
-  }
-
-  // Check which ASTContext this declaration originally came from.
-  DeclOrigin origin = m_master.GetDeclOrigin(From);
-  // If it originally came from the target ASTContext then we can just
-  // pretend that the original is the one we imported. This can happen for
-  // example when inspecting a persistent declaration from the scratch
-  // ASTContext (which will provide the declaration when parsing the
-  // expression and then we later try to copy the declaration back to the
-  // scratch ASTContext to store the result).
-  // Without this check we would ask the ASTImporter to import a declaration
-  // into the same ASTContext where it came from (which doesn't make a lot of
-  // sense).
-  if (origin.Valid() && origin.ctx == &getToContext()) {
-    RegisterImportedDecl(From, origin.decl);
-    return origin.decl;
-  }
-
-  // This declaration came originally from another ASTContext. Instead of
-  // copying our potentially incomplete 'From' Decl we instead go to the
-  // original ASTContext and copy the original to the target. This is not
-  // only faster than first completing our current decl and then copying it
-  // to the target, but it also prevents that indirectly copying the same
-  // declaration to the same target requires the ASTImporter to merge all
-  // the different decls that appear to come from different ASTContexts (even
-  // though all these different source ASTContexts just got a copy from
-  // one source AST).
-  if (origin.Valid()) {
-    auto R = m_master.CopyDecl(&getToContext(), origin.decl);
-    if (R) {
-      RegisterImportedDecl(From, R);
-      return R;
-    }
-  }
-
-  return ASTImporter::ImportImpl(From);
-}
-
-void ClangASTImporter::ASTImporterDelegate::ImportDefinitionTo(
-    clang::Decl *to, clang::Decl *from) {
-  // We might have a forward declaration from a shared library that we
-  // gave external lexical storage so that Clang asks us about the full
-  // definition when it needs it. In this case the ASTImporter isn't aware
-  // that the forward decl from the shared library is the actual import
-  // target but would create a second declaration that would then be defined.
-  // We want that 'to' is actually complete after this function so let's
-  // tell the ASTImporter that 'to' was imported from 'from'.
-  MapImported(from, to);
-  ASTImporter::Imported(from, to);
-
-  /*
-  if (to_objc_interface)
-      to_objc_interface->startDefinition();
-
-  CXXRecordDecl *to_cxx_record = dyn_cast<CXXRecordDecl>(to);
-
-  if (to_cxx_record)
-      to_cxx_record->startDefinition();
-  */
-
-  Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS);
-
-  if (llvm::Error err = ImportDefinition(from)) {
-    LLDB_LOG_ERROR(log, std::move(err),
-                   "[ClangASTImporter] Error during importing definition: {0}");
-    return;
-  }
-
-  if (clang::TagDecl *to_tag = dyn_cast<clang::TagDecl>(to)) {
-    if (clang::TagDecl *from_tag = dyn_cast<clang::TagDecl>(from)) {
-      to_tag->setCompleteDefinition(from_tag->isCompleteDefinition());
-
-      if (Log *log_ast =
-              lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_AST)) {
-        std::string name_string;
-        if (NamedDecl *from_named_decl = dyn_cast<clang::NamedDecl>(from)) {
-          llvm::raw_string_ostream name_stream(name_string);
-          from_named_decl->printName(name_stream);
-          name_stream.flush();
-        }
-        LLDB_LOG(log_ast, "==== [ClangASTImporter][TUDecl: {0}] Imported "
-                          "({1}Decl*){2}, named {3} (from "
-                          "(Decl*){4})",
-                 static_cast<void *>(to->getTranslationUnitDecl()),
-                 from->getDeclKindName(), static_cast<void *>(to), name_string,
-                 static_cast<void *>(from));
-
-        // Log the AST of the TU.
-        std::string ast_string;
-        llvm::raw_string_ostream ast_stream(ast_string);
-        to->getTranslationUnitDecl()->dump(ast_stream);
-        LLDB_LOG(log_ast, "{0}", ast_string);
-      }
-    }
-  }
-
-  // If we're dealing with an Objective-C class, ensure that the inheritance
-  // has been set up correctly.  The ASTImporter may not do this correctly if
-  // the class was originally sourced from symbols.
-
-  if (ObjCInterfaceDecl *to_objc_interface = dyn_cast<ObjCInterfaceDecl>(to)) {
-    do {
-      ObjCInterfaceDecl *to_superclass = to_objc_interface->getSuperClass();
-
-      if (to_superclass)
-        break; // we're not going to override it if it's set
-
-      ObjCInterfaceDecl *from_objc_interface =
-          dyn_cast<ObjCInterfaceDecl>(from);
-
-      if (!from_objc_interface)
-        break;
-
-      ObjCInterfaceDecl *from_superclass = from_objc_interface->getSuperClass();
-
-      if (!from_superclass)
-        break;
-
-      llvm::Expected<Decl *> imported_from_superclass_decl =
-          Import(from_superclass);
-
-      if (!imported_from_superclass_decl) {
-        LLDB_LOG_ERROR(log, imported_from_superclass_decl.takeError(),
-                       "Couldn't import decl: {0}");
-        break;
-      }
-
-      ObjCInterfaceDecl *imported_from_superclass =
-          dyn_cast<ObjCInterfaceDecl>(*imported_from_superclass_decl);
-
-      if (!imported_from_superclass)
-        break;
-
-      if (!to_objc_interface->hasDefinition())
-        to_objc_interface->startDefinition();
-
-      to_objc_interface->setSuperClass(m_source_ctx->getTrivialTypeSourceInfo(
-          m_source_ctx->getObjCInterfaceType(imported_from_superclass)));
-    } while (false);
-  }
-}
-
-/// Takes a CXXMethodDecl and completes the return type if necessary. This
-/// is currently only necessary for virtual functions with covariant return
-/// types where Clang's CodeGen expects that the underlying records are already
-/// completed.
-static void MaybeCompleteReturnType(ClangASTImporter &importer,
-                                        CXXMethodDecl *to_method) {
-  if (!to_method->isVirtual())
-    return;
-  QualType return_type = to_method->getReturnType();
-  if (!return_type->isPointerType() && !return_type->isReferenceType())
-    return;
-
-  clang::RecordDecl *rd = return_type->getPointeeType()->getAsRecordDecl();
-  if (!rd)
-    return;
-
-  importer.CompleteTagDecl(rd);
-}
-
-void ClangASTImporter::ASTImporterDelegate::Imported(clang::Decl *from,
-                                                     clang::Decl *to) {
-  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
-
-  // Some decls shouldn't be tracked here because they were not created by
-  // copying 'from' to 'to'. Just exit early for those.
-  if (m_decls_to_ignore.find(to) != m_decls_to_ignore.end())
-    return clang::ASTImporter::Imported(from, to);
-
-  lldb::user_id_t user_id = LLDB_INVALID_UID;
-  ClangASTMetadata *metadata = m_master.GetDeclMetadata(from);
-  if (metadata)
-    user_id = metadata->GetUserID();
-
-  if (log) {
-    if (NamedDecl *from_named_decl = dyn_cast<clang::NamedDecl>(from)) {
-      std::string name_string;
-      llvm::raw_string_ostream name_stream(name_string);
-      from_named_decl->printName(name_stream);
-      name_stream.flush();
-
-      LLDB_LOG(log,
-               "    [ClangASTImporter] Imported ({0}Decl*){1}, named {2} (from "
-               "(Decl*){3}), metadata {4}",
-               from->getDeclKindName(), to, name_string, from, user_id);
-    } else {
-      LLDB_LOG(log,
-               "    [ClangASTImporter] Imported ({0}Decl*){1} (from "
-               "(Decl*){2}), metadata {3}",
-               from->getDeclKindName(), to, from, user_id);
-    }
-  }
-
-  ASTContextMetadataSP to_context_md =
-      m_master.GetContextMetadata(&to->getASTContext());
-  ASTContextMetadataSP from_context_md =
-      m_master.MaybeGetContextMetadata(m_source_ctx);
-
-  if (from_context_md) {
-    OriginMap &origins = from_context_md->m_origins;
-
-    OriginMap::iterator origin_iter = origins.find(from);
-
-    if (origin_iter != origins.end()) {
-      if (to_context_md->m_origins.find(to) == to_context_md->m_origins.end() ||
-          user_id != LLDB_INVALID_UID) {
-        if (origin_iter->second.ctx != &to->getASTContext())
-          to_context_md->m_origins[to] = origin_iter->second;
-      }
-
-      ImporterDelegateSP direct_completer =
-          m_master.GetDelegate(&to->getASTContext(), origin_iter->second.ctx);
-
-      if (direct_completer.get() != this)
-        direct_completer->ASTImporter::Imported(origin_iter->second.decl, to);
-
-      LLDB_LOG(log,
-               "    [ClangASTImporter] Propagated origin "
-               "(Decl*){0}/(ASTContext*){1} from (ASTContext*){2} to "
-               "(ASTContext*){3}",
-               origin_iter->second.decl, origin_iter->second.ctx,
-               &from->getASTContext(), &to->getASTContext());
-    } else {
-      if (m_new_decl_listener)
-        m_new_decl_listener->NewDeclImported(from, to);
-
-      if (to_context_md->m_origins.find(to) == to_context_md->m_origins.end() ||
-          user_id != LLDB_INVALID_UID) {
-        to_context_md->m_origins[to] = DeclOrigin(m_source_ctx, from);
-      }
-
-      LLDB_LOG(log,
-               "    [ClangASTImporter] Decl has no origin information in "
-               "(ASTContext*){0}",
-               &from->getASTContext());
-    }
-
-    if (auto *to_namespace = dyn_cast<clang::NamespaceDecl>(to)) {
-      auto *from_namespace = cast<clang::NamespaceDecl>(from);
-
-      NamespaceMetaMap &namespace_maps = from_context_md->m_namespace_maps;
-
-      NamespaceMetaMap::iterator namespace_map_iter =
-          namespace_maps.find(from_namespace);
-
-      if (namespace_map_iter != namespace_maps.end())
-        to_context_md->m_namespace_maps[to_namespace] =
-            namespace_map_iter->second;
-    }
-  } else {
-    to_context_md->m_origins[to] = DeclOrigin(m_source_ctx, from);
-
-    LLDB_LOG(log,
-             "    [ClangASTImporter] Sourced origin "
-             "(Decl*){0}/(ASTContext*){1} into (ASTContext*){2}",
-             from, m_source_ctx, &to->getASTContext());
-  }
-
-  if (auto *to_tag_decl = dyn_cast<TagDecl>(to)) {
-    to_tag_decl->setHasExternalLexicalStorage();
-    to_tag_decl->getPrimaryContext()->setMustBuildLookupTable();
-    auto from_tag_decl = cast<TagDecl>(from);
-
-    LLDB_LOG(
-        log,
-        "    [ClangASTImporter] To is a TagDecl - attributes {0}{1} [{2}->{3}]",
-        (to_tag_decl->hasExternalLexicalStorage() ? " Lexical" : ""),
-        (to_tag_decl->hasExternalVisibleStorage() ? " Visible" : ""),
-        (from_tag_decl->isCompleteDefinition() ? "complete" : "incomplete"),
-        (to_tag_decl->isCompleteDefinition() ? "complete" : "incomplete"));
-  }
-
-  if (auto *to_namespace_decl = dyn_cast<NamespaceDecl>(to)) {
-    m_master.BuildNamespaceMap(to_namespace_decl);
-    to_namespace_decl->setHasExternalVisibleStorage();
-  }
-
-  if (auto *to_container_decl = dyn_cast<ObjCContainerDecl>(to)) {
-    to_container_decl->setHasExternalLexicalStorage();
-    to_container_decl->setHasExternalVisibleStorage();
-
-    if (log) {
-      if (ObjCInterfaceDecl *to_interface_decl =
-              llvm::dyn_cast<ObjCInterfaceDecl>(to_container_decl)) {
-        LLDB_LOG(
-            log,
-            "    [ClangASTImporter] To is an ObjCInterfaceDecl - attributes "
-            "{0}{1}{2}",
-            (to_interface_decl->hasExternalLexicalStorage() ? " Lexical" : ""),
-            (to_interface_decl->hasExternalVisibleStorage() ? " Visible" : ""),
-            (to_interface_decl->hasDefinition() ? " HasDefinition" : ""));
-      } else {
-        LLDB_LOG(
-            log, "    [ClangASTImporter] To is an {0}Decl - attributes {1}{2}",
-            ((Decl *)to_container_decl)->getDeclKindName(),
-            (to_container_decl->hasExternalLexicalStorage() ? " Lexical" : ""),
-            (to_container_decl->hasExternalVisibleStorage() ? " Visible" : ""));
-      }
-    }
-  }
-
-  if (clang::CXXMethodDecl *to_method = dyn_cast<CXXMethodDecl>(to))
-    MaybeCompleteReturnType(m_master, to_method);
-}
-
-clang::Decl *
-ClangASTImporter::ASTImporterDelegate::GetOriginalDecl(clang::Decl *To) {
-  return m_master.GetDeclOrigin(To).decl;
-}
diff --git a/lldb/source/Symbol/ClangASTMetadata.cpp b/lldb/source/Symbol/ClangASTMetadata.cpp
deleted file mode 100644 (file)
index 0c894e0..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-//===-- ClangASTMetadata.cpp ----------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "lldb/Symbol/ClangASTMetadata.h"
-#include "lldb/Utility/Stream.h"
-
-using namespace lldb_private;
-
-void ClangASTMetadata::Dump(Stream *s) {
-  lldb::user_id_t uid = GetUserID();
-
-  if (uid != LLDB_INVALID_UID) {
-    s->Printf("uid=0x%" PRIx64, uid);
-  }
-
-  uint64_t isa_ptr = GetISAPtr();
-  if (isa_ptr != 0) {
-    s->Printf("isa_ptr=0x%" PRIx64, isa_ptr);
-  }
-
-  const char *obj_ptr_name = GetObjectPtrName();
-  if (obj_ptr_name) {
-    s->Printf("obj_ptr_name=\"%s\" ", obj_ptr_name);
-  }
-
-  if (m_is_dynamic_cxx) {
-    s->Printf("is_dynamic_cxx=%i ", m_is_dynamic_cxx);
-  }
-  s->EOL();
-}
diff --git a/lldb/source/Symbol/ClangExternalASTSourceCallbacks.cpp b/lldb/source/Symbol/ClangExternalASTSourceCallbacks.cpp
deleted file mode 100644 (file)
index 4aa1755..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-//===-- ClangExternalASTSourceCallbacks.cpp -------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "lldb/Symbol/ClangExternalASTSourceCallbacks.h"
-#include "lldb/Symbol/TypeSystemClang.h"
-
-#include "clang/AST/Decl.h"
-
-using namespace lldb_private;
-
-void ClangExternalASTSourceCallbacks::CompleteType(clang::TagDecl *tag_decl) {
-  m_ast.CompleteTagDecl(tag_decl);
-}
-
-void ClangExternalASTSourceCallbacks::CompleteType(
-    clang::ObjCInterfaceDecl *objc_decl) {
-  m_ast.CompleteObjCInterfaceDecl(objc_decl);
-}
-
-bool ClangExternalASTSourceCallbacks::layoutRecordType(
-    const clang::RecordDecl *Record, uint64_t &Size, uint64_t &Alignment,
-    llvm::DenseMap<const clang::FieldDecl *, uint64_t> &FieldOffsets,
-    llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &BaseOffsets,
-    llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits>
-        &VirtualBaseOffsets) {
-  return m_ast.LayoutRecordType(Record, Size, Alignment, FieldOffsets,
-                                BaseOffsets, VirtualBaseOffsets);
-}
-
-void ClangExternalASTSourceCallbacks::FindExternalLexicalDecls(
-    const clang::DeclContext *decl_ctx,
-    llvm::function_ref<bool(clang::Decl::Kind)> IsKindWeWant,
-    llvm::SmallVectorImpl<clang::Decl *> &decls) {
-  if (decl_ctx) {
-    clang::TagDecl *tag_decl = llvm::dyn_cast<clang::TagDecl>(
-        const_cast<clang::DeclContext *>(decl_ctx));
-    if (tag_decl)
-      CompleteType(tag_decl);
-  }
-}
diff --git a/lldb/source/Symbol/ClangUtil.cpp b/lldb/source/Symbol/ClangUtil.cpp
deleted file mode 100644 (file)
index 2f3307e..0000000
+++ /dev/null
@@ -1,87 +0,0 @@
-//===-- ClangUtil.cpp -----------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-// A collection of helper methods and data structures for manipulating clang
-// types and decls.
-//===----------------------------------------------------------------------===//
-
-#include "lldb/Symbol/ClangUtil.h"
-#include "lldb/Symbol/TypeSystemClang.h"
-
-using namespace clang;
-using namespace lldb_private;
-
-bool ClangUtil::IsClangType(const CompilerType &ct) {
-  // Invalid types are never Clang types.
-  if (!ct)
-    return false;
-
-  if (llvm::dyn_cast_or_null<TypeSystemClang>(ct.GetTypeSystem()) == nullptr)
-    return false;
-
-  if (!ct.GetOpaqueQualType())
-    return false;
-
-  return true;
-}
-
-clang::Decl *ClangUtil::GetDecl(const CompilerDecl &decl) {
-  assert(llvm::isa<TypeSystemClang>(decl.GetTypeSystem()));
-  return static_cast<clang::Decl *>(decl.GetOpaqueDecl());
-}
-
-QualType ClangUtil::GetQualType(const CompilerType &ct) {
-  // Make sure we have a clang type before making a clang::QualType
-  if (!IsClangType(ct))
-    return QualType();
-
-  return QualType::getFromOpaquePtr(ct.GetOpaqueQualType());
-}
-
-QualType ClangUtil::GetCanonicalQualType(const CompilerType &ct) {
-  if (!IsClangType(ct))
-    return QualType();
-
-  return GetQualType(ct).getCanonicalType();
-}
-
-CompilerType ClangUtil::RemoveFastQualifiers(const CompilerType &ct) {
-  if (!IsClangType(ct))
-    return ct;
-
-  QualType qual_type(GetQualType(ct));
-  qual_type.removeLocalFastQualifiers();
-  return CompilerType(ct.GetTypeSystem(), qual_type.getAsOpaquePtr());
-}
-
-clang::TagDecl *ClangUtil::GetAsTagDecl(const CompilerType &type) {
-  clang::QualType qual_type = ClangUtil::GetCanonicalQualType(type);
-  if (qual_type.isNull())
-    return nullptr;
-
-  return qual_type->getAsTagDecl();
-}
-
-std::string ClangUtil::DumpDecl(const clang::Decl *d) {
-  if (!d)
-    return "nullptr";
-
-  std::string result;
-  llvm::raw_string_ostream stream(result);
-  bool deserialize = false;
-  d->dump(stream, deserialize);
-
-  stream.flush();
-  return result;
-}
-
-std::string ClangUtil::ToString(const clang::Type *t) {
-  return clang::QualType(t, 0).getAsString();
-}
-
-std::string ClangUtil::ToString(const CompilerType &c) {
-  return ClangUtil::GetQualType(c).getAsString();
-}
diff --git a/lldb/source/Symbol/CxxModuleHandler.cpp b/lldb/source/Symbol/CxxModuleHandler.cpp
deleted file mode 100644 (file)
index 4d9af81..0000000
+++ /dev/null
@@ -1,289 +0,0 @@
-//===-- CxxModuleHandler.cpp ----------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "lldb/Symbol/CxxModuleHandler.h"
-
-#include "lldb/Symbol/TypeSystemClang.h"
-#include "lldb/Utility/Log.h"
-#include "clang/Sema/Lookup.h"
-#include "llvm/Support/Error.h"
-
-using namespace lldb_private;
-using namespace clang;
-
-CxxModuleHandler::CxxModuleHandler(ASTImporter &importer, ASTContext *target)
-    : m_importer(&importer),
-      m_sema(TypeSystemClang::GetASTContext(target)->getSema()) {
-
-  std::initializer_list<const char *> supported_names = {
-      // containers
-      "deque",
-      "forward_list",
-      "list",
-      "queue",
-      "stack",
-      "vector",
-      // pointers
-      "shared_ptr",
-      "unique_ptr",
-      "weak_ptr",
-      // utility
-      "allocator",
-  };
-  m_supported_templates.insert(supported_names.begin(), supported_names.end());
-}
-
-/// Builds a list of scopes that point into the given context.
-///
-/// \param sema The sema that will be using the scopes.
-/// \param ctxt The context that the scope should look into.
-/// \param result A list of scopes. The scopes need to be freed by the caller
-///               (except the TUScope which is owned by the sema).
-static void makeScopes(Sema &sema, DeclContext *ctxt,
-                       std::vector<Scope *> &result) {
-  // FIXME: The result should be a list of unique_ptrs, but the TUScope makes
-  // this currently impossible as it's owned by the Sema.
-
-  if (auto parent = ctxt->getParent()) {
-    makeScopes(sema, parent, result);
-
-    Scope *scope =
-        new Scope(result.back(), Scope::DeclScope, sema.getDiagnostics());
-    scope->setEntity(ctxt);
-    result.push_back(scope);
-  } else
-    result.push_back(sema.TUScope);
-}
-
-/// Uses the Sema to look up the given name in the given DeclContext.
-static std::unique_ptr<LookupResult>
-emulateLookupInCtxt(Sema &sema, llvm::StringRef name, DeclContext *ctxt) {
-  IdentifierInfo &ident = sema.getASTContext().Idents.get(name);
-
-  std::unique_ptr<LookupResult> lookup_result;
-  lookup_result.reset(new LookupResult(sema, DeclarationName(&ident),
-                                       SourceLocation(),
-                                       Sema::LookupOrdinaryName));
-
-  // Usually during parsing we already encountered the scopes we would use. But
-  // here don't have these scopes so we have to emulate the behavior of the
-  // Sema during parsing.
-  std::vector<Scope *> scopes;
-  makeScopes(sema, ctxt, scopes);
-
-  // Now actually perform the lookup with the sema.
-  sema.LookupName(*lookup_result, scopes.back());
-
-  // Delete all the allocated scopes beside the translation unit scope (which
-  // has depth 0).
-  for (Scope *s : scopes)
-    if (s->getDepth() != 0)
-      delete s;
-
-  return lookup_result;
-}
-
-/// Error class for handling problems when finding a certain DeclContext.
-struct MissingDeclContext : public llvm::ErrorInfo<MissingDeclContext> {
-
-  static char ID;
-
-  MissingDeclContext(DeclContext *context, std::string error)
-      : m_context(context), m_error(error) {}
-
-  DeclContext *m_context;
-  std::string m_error;
-
-  void log(llvm::raw_ostream &OS) const override {
-    OS << llvm::formatv("error when reconstructing context of kind {0}:{1}",
-                        m_context->getDeclKindName(), m_error);
-  }
-
-  std::error_code convertToErrorCode() const override {
-    return llvm::inconvertibleErrorCode();
-  }
-};
-
-char MissingDeclContext::ID = 0;
-
-/// Given a foreign decl context, this function finds the equivalent local
-/// decl context in the ASTContext of the given Sema. Potentially deserializes
-/// decls from the 'std' module if necessary.
-static llvm::Expected<DeclContext *>
-getEqualLocalDeclContext(Sema &sema, DeclContext *foreign_ctxt) {
-
-  // Inline namespaces don't matter for lookups, so let's skip them.
-  while (foreign_ctxt && foreign_ctxt->isInlineNamespace())
-    foreign_ctxt = foreign_ctxt->getParent();
-
-  // If the foreign context is the TU, we just return the local TU.
-  if (foreign_ctxt->isTranslationUnit())
-    return sema.getASTContext().getTranslationUnitDecl();
-
-  // Recursively find/build the parent DeclContext.
-  llvm::Expected<DeclContext *> parent =
-      getEqualLocalDeclContext(sema, foreign_ctxt->getParent());
-  if (!parent)
-    return parent;
-
-  // We currently only support building namespaces.
-  if (foreign_ctxt->isNamespace()) {
-    NamedDecl *ns = llvm::dyn_cast<NamedDecl>(foreign_ctxt);
-    llvm::StringRef ns_name = ns->getName();
-
-    auto lookup_result = emulateLookupInCtxt(sema, ns_name, *parent);
-    for (NamedDecl *named_decl : *lookup_result) {
-      if (DeclContext *DC = llvm::dyn_cast<DeclContext>(named_decl))
-        return DC->getPrimaryContext();
-    }
-    return llvm::make_error<MissingDeclContext>(
-        foreign_ctxt,
-        "Couldn't find namespace " + ns->getQualifiedNameAsString());
-  }
-
-  return llvm::make_error<MissingDeclContext>(foreign_ctxt, "Unknown context ");
-}
-
-/// Returns true iff tryInstantiateStdTemplate supports instantiating a template
-/// with the given template arguments.
-static bool templateArgsAreSupported(ArrayRef<TemplateArgument> a) {
-  for (const TemplateArgument &arg : a) {
-    switch (arg.getKind()) {
-    case TemplateArgument::Type:
-    case TemplateArgument::Integral:
-      break;
-    default:
-      // TemplateArgument kind hasn't been handled yet.
-      return false;
-    }
-  }
-  return true;
-}
-
-/// Constructor function for Clang declarations. Ensures that the created
-/// declaration is registered with the ASTImporter.
-template <typename T, typename... Args>
-T *createDecl(ASTImporter &importer, Decl *from_d, Args &&... args) {
-  T *to_d = T::Create(std::forward<Args>(args)...);
-  importer.RegisterImportedDecl(from_d, to_d);
-  return to_d;
-}
-
-llvm::Optional<Decl *> CxxModuleHandler::tryInstantiateStdTemplate(Decl *d) {
-  Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS);
-
-  // If we don't have a template to instiantiate, then there is nothing to do.
-  auto td = dyn_cast<ClassTemplateSpecializationDecl>(d);
-  if (!td)
-    return {};
-
-  // We only care about templates in the std namespace.
-  if (!td->getDeclContext()->isStdNamespace())
-    return {};
-
-  // We have a whitelist of supported template names.
-  if (m_supported_templates.find(td->getName()) == m_supported_templates.end())
-    return {};
-
-  // Early check if we even support instantiating this template. We do this
-  // before we import anything into the target AST.
-  auto &foreign_args = td->getTemplateInstantiationArgs();
-  if (!templateArgsAreSupported(foreign_args.asArray()))
-    return {};
-
-  // Find the local DeclContext that corresponds to the DeclContext of our
-  // decl we want to import.
-  llvm::Expected<DeclContext *> to_context =
-      getEqualLocalDeclContext(*m_sema, td->getDeclContext());
-  if (!to_context) {
-    LLDB_LOG_ERROR(log, to_context.takeError(),
-                   "Got error while searching equal local DeclContext for decl "
-                   "'{1}':\n{0}",
-                   td->getName());
-    return {};
-  }
-
-  // Look up the template in our local context.
-  std::unique_ptr<LookupResult> lookup =
-      emulateLookupInCtxt(*m_sema, td->getName(), *to_context);
-
-  ClassTemplateDecl *new_class_template = nullptr;
-  for (auto LD : *lookup) {
-    if ((new_class_template = dyn_cast<ClassTemplateDecl>(LD)))
-      break;
-  }
-  if (!new_class_template)
-    return {};
-
-  // Import the foreign template arguments.
-  llvm::SmallVector<TemplateArgument, 4> imported_args;
-
-  // If this logic is changed, also update templateArgsAreSupported.
-  for (const TemplateArgument &arg : foreign_args.asArray()) {
-    switch (arg.getKind()) {
-    case TemplateArgument::Type: {
-      llvm::Expected<QualType> type = m_importer->Import(arg.getAsType());
-      if (!type) {
-        LLDB_LOG_ERROR(log, type.takeError(), "Couldn't import type: {0}");
-        return {};
-      }
-      imported_args.push_back(TemplateArgument(*type));
-      break;
-    }
-    case TemplateArgument::Integral: {
-      llvm::APSInt integral = arg.getAsIntegral();
-      llvm::Expected<QualType> type =
-          m_importer->Import(arg.getIntegralType());
-      if (!type) {
-        LLDB_LOG_ERROR(log, type.takeError(), "Couldn't import type: {0}");
-        return {};
-      }
-      imported_args.push_back(
-          TemplateArgument(d->getASTContext(), integral, *type));
-      break;
-    }
-    default:
-      assert(false && "templateArgsAreSupported not updated?");
-    }
-  }
-
-  // Find the class template specialization declaration that
-  // corresponds to these arguments.
-  void *InsertPos = nullptr;
-  ClassTemplateSpecializationDecl *result =
-      new_class_template->findSpecialization(imported_args, InsertPos);
-
-  if (result) {
-    // We found an existing specialization in the module that fits our arguments
-    // so we can treat it as the result and register it with the ASTImporter.
-    m_importer->RegisterImportedDecl(d, result);
-    return result;
-  }
-
-  // Instantiate the template.
-  result = createDecl<ClassTemplateSpecializationDecl>(
-      *m_importer, d, m_sema->getASTContext(),
-      new_class_template->getTemplatedDecl()->getTagKind(),
-      new_class_template->getDeclContext(),
-      new_class_template->getTemplatedDecl()->getLocation(),
-      new_class_template->getLocation(), new_class_template, imported_args,
-      nullptr);
-
-  new_class_template->AddSpecialization(result, InsertPos);
-  if (new_class_template->isOutOfLine())
-    result->setLexicalDeclContext(
-        new_class_template->getLexicalDeclContext());
-  return result;
-}
-
-llvm::Optional<Decl *> CxxModuleHandler::Import(Decl *d) {
-  if (!isValid())
-    return {};
-
-  return tryInstantiateStdTemplate(d);
-}
diff --git a/lldb/source/Symbol/TypeSystemClang.cpp b/lldb/source/Symbol/TypeSystemClang.cpp
deleted file mode 100644 (file)
index 77e89eb..0000000
+++ /dev/null
@@ -1,9318 +0,0 @@
-//===-- TypeSystemClang.cpp -----------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "lldb/Symbol/TypeSystemClang.h"
-
-#include "llvm/Support/FormatAdapters.h"
-#include "llvm/Support/FormatVariadic.h"
-
-#include <mutex>
-#include <string>
-#include <vector>
-
-#include "clang/AST/ASTContext.h"
-#include "clang/AST/ASTImporter.h"
-#include "clang/AST/Attr.h"
-#include "clang/AST/CXXInheritance.h"
-#include "clang/AST/DeclObjC.h"
-#include "clang/AST/DeclTemplate.h"
-#include "clang/AST/Mangle.h"
-#include "clang/AST/RecordLayout.h"
-#include "clang/AST/Type.h"
-#include "clang/AST/VTableBuilder.h"
-#include "clang/Basic/Builtins.h"
-#include "clang/Basic/Diagnostic.h"
-#include "clang/Basic/FileManager.h"
-#include "clang/Basic/FileSystemOptions.h"
-#include "clang/Basic/LangStandard.h"
-#include "clang/Basic/SourceManager.h"
-#include "clang/Basic/TargetInfo.h"
-#include "clang/Basic/TargetOptions.h"
-#include "clang/Frontend/FrontendOptions.h"
-#include "clang/Sema/Sema.h"
-
-#include "llvm/Support/Signals.h"
-#include "llvm/Support/Threading.h"
-
-#include "Plugins/ExpressionParser/Clang/ClangFunctionCaller.h"
-#include "Plugins/ExpressionParser/Clang/ClangPersistentVariables.h"
-#include "Plugins/ExpressionParser/Clang/ClangUserExpression.h"
-#include "Plugins/ExpressionParser/Clang/ClangUtilityFunction.h"
-#include "lldb/Utility/ArchSpec.h"
-#include "lldb/Utility/Flags.h"
-
-#include "lldb/Core/DumpDataExtractor.h"
-#include "lldb/Core/Module.h"
-#include "lldb/Core/PluginManager.h"
-#include "lldb/Core/StreamFile.h"
-#include "lldb/Core/ThreadSafeDenseMap.h"
-#include "lldb/Core/UniqueCStringMap.h"
-#include "lldb/Symbol/ClangASTImporter.h"
-#include "lldb/Symbol/ClangASTMetadata.h"
-#include "lldb/Symbol/ClangExternalASTSourceCallbacks.h"
-#include "lldb/Symbol/ClangUtil.h"
-#include "lldb/Symbol/ObjectFile.h"
-#include "lldb/Symbol/SymbolFile.h"
-#include "lldb/Target/ExecutionContext.h"
-#include "lldb/Target/Language.h"
-#include "lldb/Target/Process.h"
-#include "lldb/Target/Target.h"
-#include "lldb/Utility/DataExtractor.h"
-#include "lldb/Utility/LLDBAssert.h"
-#include "lldb/Utility/Log.h"
-#include "lldb/Utility/RegularExpression.h"
-#include "lldb/Utility/Scalar.h"
-
-#include "Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.h"
-#include "Plugins/SymbolFile/DWARF/DWARFASTParserClang.h"
-#include "Plugins/SymbolFile/PDB/PDBASTParser.h"
-
-#include <stdio.h>
-
-#include <mutex>
-
-using namespace lldb;
-using namespace lldb_private;
-using namespace clang;
-using llvm::StringSwitch;
-
-namespace {
-#ifdef LLDB_CONFIGURATION_DEBUG
-static void VerifyDecl(clang::Decl *decl) {
-  assert(decl && "VerifyDecl called with nullptr?");
-  decl->getAccess();
-}
-#endif
-
-static inline bool
-TypeSystemClangSupportsLanguage(lldb::LanguageType language) {
-  return language == eLanguageTypeUnknown || // Clang is the default type system
-         lldb_private::Language::LanguageIsC(language) ||
-         lldb_private::Language::LanguageIsCPlusPlus(language) ||
-         lldb_private::Language::LanguageIsObjC(language) ||
-         lldb_private::Language::LanguageIsPascal(language) ||
-         // Use Clang for Rust until there is a proper language plugin for it
-         language == eLanguageTypeRust ||
-         language == eLanguageTypeExtRenderScript ||
-         // Use Clang for D until there is a proper language plugin for it
-         language == eLanguageTypeD ||
-         // Open Dylan compiler debug info is designed to be Clang-compatible
-         language == eLanguageTypeDylan;
-}
-
-// Checks whether m1 is an overload of m2 (as opposed to an override). This is
-// called by addOverridesForMethod to distinguish overrides (which share a
-// vtable entry) from overloads (which require distinct entries).
-bool isOverload(clang::CXXMethodDecl *m1, clang::CXXMethodDecl *m2) {
-  // FIXME: This should detect covariant return types, but currently doesn't.
-  lldbassert(&m1->getASTContext() == &m2->getASTContext() &&
-             "Methods should have the same AST context");
-  clang::ASTContext &context = m1->getASTContext();
-
-  const auto *m1Type = llvm::cast<clang::FunctionProtoType>(
-      context.getCanonicalType(m1->getType()));
-
-  const auto *m2Type = llvm::cast<clang::FunctionProtoType>(
-      context.getCanonicalType(m2->getType()));
-
-  auto compareArgTypes = [&context](const clang::QualType &m1p,
-                                    const clang::QualType &m2p) {
-    return context.hasSameType(m1p.getUnqualifiedType(),
-                               m2p.getUnqualifiedType());
-  };
-
-  // FIXME: In C++14 and later, we can just pass m2Type->param_type_end()
-  //        as a fourth parameter to std::equal().
-  return (m1->getNumParams() != m2->getNumParams()) ||
-         !std::equal(m1Type->param_type_begin(), m1Type->param_type_end(),
-                     m2Type->param_type_begin(), compareArgTypes);
-}
-
-// If decl is a virtual method, walk the base classes looking for methods that
-// decl overrides. This table of overridden methods is used by IRGen to
-// determine the vtable layout for decl's parent class.
-void addOverridesForMethod(clang::CXXMethodDecl *decl) {
-  if (!decl->isVirtual())
-    return;
-
-  clang::CXXBasePaths paths;
-
-  auto find_overridden_methods =
-      [decl](const clang::CXXBaseSpecifier *specifier,
-             clang::CXXBasePath &path) {
-        if (auto *base_record = llvm::dyn_cast<clang::CXXRecordDecl>(
-                specifier->getType()->getAs<clang::RecordType>()->getDecl())) {
-
-          clang::DeclarationName name = decl->getDeclName();
-
-          // If this is a destructor, check whether the base class destructor is
-          // virtual.
-          if (name.getNameKind() == clang::DeclarationName::CXXDestructorName)
-            if (auto *baseDtorDecl = base_record->getDestructor()) {
-              if (baseDtorDecl->isVirtual()) {
-                path.Decls = baseDtorDecl;
-                return true;
-              } else
-                return false;
-            }
-
-          // Otherwise, search for name in the base class.
-          for (path.Decls = base_record->lookup(name); !path.Decls.empty();
-               path.Decls = path.Decls.slice(1)) {
-            if (auto *method_decl =
-                    llvm::dyn_cast<clang::CXXMethodDecl>(path.Decls.front()))
-              if (method_decl->isVirtual() && !isOverload(decl, method_decl)) {
-                path.Decls = method_decl;
-                return true;
-              }
-          }
-        }
-
-        return false;
-      };
-
-  if (decl->getParent()->lookupInBases(find_overridden_methods, paths)) {
-    for (auto *overridden_decl : paths.found_decls())
-      decl->addOverriddenMethod(
-          llvm::cast<clang::CXXMethodDecl>(overridden_decl));
-  }
-}
-}
-
-static lldb::addr_t GetVTableAddress(Process &process,
-                                     VTableContextBase &vtable_ctx,
-                                     ValueObject &valobj,
-                                     const ASTRecordLayout &record_layout) {
-  // Retrieve type info
-  CompilerType pointee_type;
-  CompilerType this_type(valobj.GetCompilerType());
-  uint32_t type_info = this_type.GetTypeInfo(&pointee_type);
-  if (!type_info)
-    return LLDB_INVALID_ADDRESS;
-
-  // Check if it's a pointer or reference
-  bool ptr_or_ref = false;
-  if (type_info & (eTypeIsPointer | eTypeIsReference)) {
-    ptr_or_ref = true;
-    type_info = pointee_type.GetTypeInfo();
-  }
-
-  // We process only C++ classes
-  const uint32_t cpp_class = eTypeIsClass | eTypeIsCPlusPlus;
-  if ((type_info & cpp_class) != cpp_class)
-    return LLDB_INVALID_ADDRESS;
-
-  // Calculate offset to VTable pointer
-  lldb::offset_t vbtable_ptr_offset =
-      vtable_ctx.isMicrosoft() ? record_layout.getVBPtrOffset().getQuantity()
-                               : 0;
-
-  if (ptr_or_ref) {
-    // We have a pointer / ref to object, so read
-    // VTable pointer from process memory
-
-    if (valobj.GetAddressTypeOfChildren() != eAddressTypeLoad)
-      return LLDB_INVALID_ADDRESS;
-
-    auto vbtable_ptr_addr = valobj.GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
-    if (vbtable_ptr_addr == LLDB_INVALID_ADDRESS)
-      return LLDB_INVALID_ADDRESS;
-
-    vbtable_ptr_addr += vbtable_ptr_offset;
-
-    Status err;
-    return process.ReadPointerFromMemory(vbtable_ptr_addr, err);
-  }
-
-  // We have an object already read from process memory,
-  // so just extract VTable pointer from it
-
-  DataExtractor data;
-  Status err;
-  auto size = valobj.GetData(data, err);
-  if (err.Fail() || vbtable_ptr_offset + data.GetAddressByteSize() > size)
-    return LLDB_INVALID_ADDRESS;
-
-  return data.GetPointer(&vbtable_ptr_offset);
-}
-
-static int64_t ReadVBaseOffsetFromVTable(Process &process,
-                                         VTableContextBase &vtable_ctx,
-                                         lldb::addr_t vtable_ptr,
-                                         const CXXRecordDecl *cxx_record_decl,
-                                         const CXXRecordDecl *base_class_decl) {
-  if (vtable_ctx.isMicrosoft()) {
-    clang::MicrosoftVTableContext &msoft_vtable_ctx =
-        static_cast<clang::MicrosoftVTableContext &>(vtable_ctx);
-
-    // Get the index into the virtual base table. The
-    // index is the index in uint32_t from vbtable_ptr
-    const unsigned vbtable_index =
-        msoft_vtable_ctx.getVBTableIndex(cxx_record_decl, base_class_decl);
-    const lldb::addr_t base_offset_addr = vtable_ptr + vbtable_index * 4;
-    Status err;
-    return process.ReadSignedIntegerFromMemory(base_offset_addr, 4, INT64_MAX,
-                                               err);
-  }
-
-  clang::ItaniumVTableContext &itanium_vtable_ctx =
-      static_cast<clang::ItaniumVTableContext &>(vtable_ctx);
-
-  clang::CharUnits base_offset_offset =
-      itanium_vtable_ctx.getVirtualBaseOffsetOffset(cxx_record_decl,
-                                                    base_class_decl);
-  const lldb::addr_t base_offset_addr =
-      vtable_ptr + base_offset_offset.getQuantity();
-  const uint32_t base_offset_size = process.GetAddressByteSize();
-  Status err;
-  return process.ReadSignedIntegerFromMemory(base_offset_addr, base_offset_size,
-                                             INT64_MAX, err);
-}
-
-static bool GetVBaseBitOffset(VTableContextBase &vtable_ctx,
-                              ValueObject &valobj,
-                              const ASTRecordLayout &record_layout,
-                              const CXXRecordDecl *cxx_record_decl,
-                              const CXXRecordDecl *base_class_decl,
-                              int32_t &bit_offset) {
-  ExecutionContext exe_ctx(valobj.GetExecutionContextRef());
-  Process *process = exe_ctx.GetProcessPtr();
-  if (!process)
-    return false;
-
-  lldb::addr_t vtable_ptr =
-      GetVTableAddress(*process, vtable_ctx, valobj, record_layout);
-  if (vtable_ptr == LLDB_INVALID_ADDRESS)
-    return false;
-
-  auto base_offset = ReadVBaseOffsetFromVTable(
-      *process, vtable_ctx, vtable_ptr, cxx_record_decl, base_class_decl);
-  if (base_offset == INT64_MAX)
-    return false;
-
-  bit_offset = base_offset * 8;
-
-  return true;
-}
-
-typedef lldb_private::ThreadSafeDenseMap<clang::ASTContext *, TypeSystemClang *>
-    ClangASTMap;
-
-static ClangASTMap &GetASTMap() {
-  static ClangASTMap *g_map_ptr = nullptr;
-  static llvm::once_flag g_once_flag;
-  llvm::call_once(g_once_flag, []() {
-    g_map_ptr = new ClangASTMap(); // leaked on purpose to avoid spins
-  });
-  return *g_map_ptr;
-}
-
-char TypeSystemClang::ID;
-
-bool TypeSystemClang::IsOperator(llvm::StringRef name,
-                                 clang::OverloadedOperatorKind &op_kind) {
-  // All operators have to start with "operator".
-  if (!name.consume_front("operator"))
-    return false;
-
-  // Remember if there was a space after "operator". This is necessary to
-  // check for collisions with strangely named functions like "operatorint()".
-  bool space_after_operator = name.consume_front(" ");
-
-  op_kind = StringSwitch<clang::OverloadedOperatorKind>(name)
-                .Case("+", clang::OO_Plus)
-                .Case("+=", clang::OO_PlusEqual)
-                .Case("++", clang::OO_PlusPlus)
-                .Case("-", clang::OO_Minus)
-                .Case("-=", clang::OO_MinusEqual)
-                .Case("--", clang::OO_MinusMinus)
-                .Case("->", clang::OO_Arrow)
-                .Case("->*", clang::OO_ArrowStar)
-                .Case("*", clang::OO_Star)
-                .Case("*=", clang::OO_StarEqual)
-                .Case("/", clang::OO_Slash)
-                .Case("/=", clang::OO_SlashEqual)
-                .Case("%", clang::OO_Percent)
-                .Case("%=", clang::OO_PercentEqual)
-                .Case("^", clang::OO_Caret)
-                .Case("^=", clang::OO_CaretEqual)
-                .Case("&", clang::OO_Amp)
-                .Case("&=", clang::OO_AmpEqual)
-                .Case("&&", clang::OO_AmpAmp)
-                .Case("|", clang::OO_Pipe)
-                .Case("|=", clang::OO_PipeEqual)
-                .Case("||", clang::OO_PipePipe)
-                .Case("~", clang::OO_Tilde)
-                .Case("!", clang::OO_Exclaim)
-                .Case("!=", clang::OO_ExclaimEqual)
-                .Case("=", clang::OO_Equal)
-                .Case("==", clang::OO_EqualEqual)
-                .Case("<", clang::OO_Less)
-                .Case("<<", clang::OO_LessLess)
-                .Case("<<=", clang::OO_LessLessEqual)
-                .Case("<=", clang::OO_LessEqual)
-                .Case(">", clang::OO_Greater)
-                .Case(">>", clang::OO_GreaterGreater)
-                .Case(">>=", clang::OO_GreaterGreaterEqual)
-                .Case(">=", clang::OO_GreaterEqual)
-                .Case("()", clang::OO_Call)
-                .Case("[]", clang::OO_Subscript)
-                .Case(",", clang::OO_Comma)
-                .Default(clang::NUM_OVERLOADED_OPERATORS);
-
-  // We found a fitting operator, so we can exit now.
-  if (op_kind != clang::NUM_OVERLOADED_OPERATORS)
-    return true;
-
-  // After the "operator " or "operator" part is something unknown. This means
-  // it's either one of the named operators (new/delete), a conversion operator
-  // (e.g. operator bool) or a function which name starts with "operator"
-  // (e.g. void operatorbool).
-
-  // If it's a function that starts with operator it can't have a space after
-  // "operator" because identifiers can't contain spaces.
-  // E.g. "operator int" (conversion operator)
-  //  vs. "operatorint" (function with colliding name).
-  if (!space_after_operator)
-    return false; // not an operator.
-
-  // Now the operator is either one of the named operators or a conversion
-  // operator.
-  op_kind = StringSwitch<clang::OverloadedOperatorKind>(name)
-                .Case("new", clang::OO_New)
-                .Case("new[]", clang::OO_Array_New)
-                .Case("delete", clang::OO_Delete)
-                .Case("delete[]", clang::OO_Array_Delete)
-                // conversion operators hit this case.
-                .Default(clang::NUM_OVERLOADED_OPERATORS);
-
-  return true;
-}
-
-clang::AccessSpecifier
-TypeSystemClang::ConvertAccessTypeToAccessSpecifier(AccessType access) {
-  switch (access) {
-  default:
-    break;
-  case eAccessNone:
-    return AS_none;
-  case eAccessPublic:
-    return AS_public;
-  case eAccessPrivate:
-    return AS_private;
-  case eAccessProtected:
-    return AS_protected;
-  }
-  return AS_none;
-}
-
-static void ParseLangArgs(LangOptions &Opts, InputKind IK, const char *triple) {
-  // FIXME: Cleanup per-file based stuff.
-
-  // Set some properties which depend solely on the input kind; it would be
-  // nice to move these to the language standard, and have the driver resolve
-  // the input kind + language standard.
-  if (IK.getLanguage() == clang::Language::Asm) {
-    Opts.AsmPreprocessor = 1;
-  } else if (IK.isObjectiveC()) {
-    Opts.ObjC = 1;
-  }
-
-  LangStandard::Kind LangStd = LangStandard::lang_unspecified;
-
-  if (LangStd == LangStandard::lang_unspecified) {
-    // Based on the base language, pick one.
-    switch (IK.getLanguage()) {
-    case clang::Language::Unknown:
-    case clang::Language::LLVM_IR:
-    case clang::Language::RenderScript:
-      llvm_unreachable("Invalid input kind!");
-    case clang::Language::OpenCL:
-      LangStd = LangStandard::lang_opencl10;
-      break;
-    case clang::Language::CUDA:
-      LangStd = LangStandard::lang_cuda;
-      break;
-    case clang::Language::Asm:
-    case clang::Language::C:
-    case clang::Language::ObjC:
-      LangStd = LangStandard::lang_gnu99;
-      break;
-    case clang::Language::CXX:
-    case clang::Language::ObjCXX:
-      LangStd = LangStandard::lang_gnucxx98;
-      break;
-    case clang::Language::HIP:
-      LangStd = LangStandard::lang_hip;
-      break;
-    }
-  }
-
-  const LangStandard &Std = LangStandard::getLangStandardForKind(LangStd);
-  Opts.LineComment = Std.hasLineComments();
-  Opts.C99 = Std.isC99();
-  Opts.CPlusPlus = Std.isCPlusPlus();
-  Opts.CPlusPlus11 = Std.isCPlusPlus11();
-  Opts.Digraphs = Std.hasDigraphs();
-  Opts.GNUMode = Std.isGNUMode();
-  Opts.GNUInline = !Std.isC99();
-  Opts.HexFloats = Std.hasHexFloats();
-  Opts.ImplicitInt = Std.hasImplicitInt();
-
-  Opts.WChar = true;
-
-  // OpenCL has some additional defaults.
-  if (LangStd == LangStandard::lang_opencl10) {
-    Opts.OpenCL = 1;
-    Opts.AltiVec = 1;
-    Opts.CXXOperatorNames = 1;
-    Opts.setLaxVectorConversions(LangOptions::LaxVectorConversionKind::All);
-  }
-
-  // OpenCL and C++ both have bool, true, false keywords.
-  Opts.Bool = Opts.OpenCL || Opts.CPlusPlus;
-
-  Opts.setValueVisibilityMode(DefaultVisibility);
-
-  // Mimicing gcc's behavior, trigraphs are only enabled if -trigraphs is
-  // specified, or -std is set to a conforming mode.
-  Opts.Trigraphs = !Opts.GNUMode;
-  Opts.CharIsSigned = ArchSpec(triple).CharIsSignedByDefault();
-  Opts.OptimizeSize = 0;
-
-  // FIXME: Eliminate this dependency.
-  //    unsigned Opt =
-  //    Args.hasArg(OPT_Os) ? 2 : getLastArgIntValue(Args, OPT_O, 0, Diags);
-  //    Opts.Optimize = Opt != 0;
-  unsigned Opt = 0;
-
-  // This is the __NO_INLINE__ define, which just depends on things like the
-  // optimization level and -fno-inline, not actually whether the backend has
-  // inlining enabled.
-  //
-  // FIXME: This is affected by other options (-fno-inline).
-  Opts.NoInlineDefine = !Opt;
-}
-
-TypeSystemClang::TypeSystemClang(llvm::StringRef name,
-                                 llvm::Triple target_triple) {
-  m_display_name = name.str();
-  if (!target_triple.str().empty())
-    SetTargetTriple(target_triple.str());
-  // The caller didn't pass an ASTContext so create a new one for this
-  // TypeSystemClang.
-  CreateASTContext();
-}
-
-TypeSystemClang::TypeSystemClang(llvm::StringRef name,
-                                 ASTContext &existing_ctxt) {
-  m_display_name = name.str();
-  SetTargetTriple(existing_ctxt.getTargetInfo().getTriple().str());
-
-  m_ast_up.reset(&existing_ctxt);
-  GetASTMap().Insert(&existing_ctxt, this);
-}
-
-// Destructor
-TypeSystemClang::~TypeSystemClang() { Finalize(); }
-
-ConstString TypeSystemClang::GetPluginNameStatic() {
-  return ConstString("clang");
-}
-
-ConstString TypeSystemClang::GetPluginName() {
-  return TypeSystemClang::GetPluginNameStatic();
-}
-
-uint32_t TypeSystemClang::GetPluginVersion() { return 1; }
-
-lldb::TypeSystemSP TypeSystemClang::CreateInstance(lldb::LanguageType language,
-                                                   lldb_private::Module *module,
-                                                   Target *target) {
-  if (!TypeSystemClangSupportsLanguage(language))
-    return lldb::TypeSystemSP();
-  ArchSpec arch;
-  if (module)
-    arch = module->GetArchitecture();
-  else if (target)
-    arch = target->GetArchitecture();
-
-  if (!arch.IsValid())
-    return lldb::TypeSystemSP();
-
-  llvm::Triple triple = arch.GetTriple();
-  // LLVM wants this to be set to iOS or MacOSX; if we're working on
-  // a bare-boards type image, change the triple for llvm's benefit.
-  if (triple.getVendor() == llvm::Triple::Apple &&
-      triple.getOS() == llvm::Triple::UnknownOS) {
-    if (triple.getArch() == llvm::Triple::arm ||
-        triple.getArch() == llvm::Triple::aarch64 ||
-        triple.getArch() == llvm::Triple::aarch64_32 ||
-        triple.getArch() == llvm::Triple::thumb) {
-      triple.setOS(llvm::Triple::IOS);
-    } else {
-      triple.setOS(llvm::Triple::MacOSX);
-    }
-  }
-
-  if (module) {
-    std::string ast_name =
-        "ASTContext for '" + module->GetFileSpec().GetPath() + "'";
-    return std::make_shared<TypeSystemClang>(ast_name, triple);
-  } else if (target && target->IsValid())
-    return std::make_shared<TypeSystemClangForExpressions>(*target, triple);
-  return lldb::TypeSystemSP();
-}
-
-LanguageSet TypeSystemClang::GetSupportedLanguagesForTypes() {
-  LanguageSet languages;
-  languages.Insert(lldb::eLanguageTypeC89);
-  languages.Insert(lldb::eLanguageTypeC);
-  languages.Insert(lldb::eLanguageTypeC11);
-  languages.Insert(lldb::eLanguageTypeC_plus_plus);
-  languages.Insert(lldb::eLanguageTypeC99);
-  languages.Insert(lldb::eLanguageTypeObjC);
-  languages.Insert(lldb::eLanguageTypeObjC_plus_plus);
-  languages.Insert(lldb::eLanguageTypeC_plus_plus_03);
-  languages.Insert(lldb::eLanguageTypeC_plus_plus_11);
-  languages.Insert(lldb::eLanguageTypeC11);
-  languages.Insert(lldb::eLanguageTypeC_plus_plus_14);
-  return languages;
-}
-
-LanguageSet TypeSystemClang::GetSupportedLanguagesForExpressions() {
-  LanguageSet languages;
-  languages.Insert(lldb::eLanguageTypeC_plus_plus);
-  languages.Insert(lldb::eLanguageTypeObjC_plus_plus);
-  languages.Insert(lldb::eLanguageTypeC_plus_plus_03);
-  languages.Insert(lldb::eLanguageTypeC_plus_plus_11);
-  languages.Insert(lldb::eLanguageTypeC_plus_plus_14);
-  return languages;
-}
-
-void TypeSystemClang::Initialize() {
-  PluginManager::RegisterPlugin(
-      GetPluginNameStatic(), "clang base AST context plug-in", CreateInstance,
-      GetSupportedLanguagesForTypes(), GetSupportedLanguagesForExpressions());
-}
-
-void TypeSystemClang::Terminate() {
-  PluginManager::UnregisterPlugin(CreateInstance);
-}
-
-void TypeSystemClang::Finalize() {
-  assert(m_ast_up);
-  GetASTMap().Erase(m_ast_up.get());
-  if (!m_ast_owned)
-    m_ast_up.release();
-
-  m_builtins_up.reset();
-  m_selector_table_up.reset();
-  m_identifier_table_up.reset();
-  m_target_info_up.reset();
-  m_target_options_rp.reset();
-  m_diagnostics_engine_up.reset();
-  m_source_manager_up.reset();
-  m_language_options_up.reset();
-}
-
-void TypeSystemClang::setSema(Sema *s) {
-  // Ensure that the new sema actually belongs to our ASTContext.
-  assert(s == nullptr || &s->getASTContext() == m_ast_up.get());
-  m_sema = s;
-}
-
-const char *TypeSystemClang::GetTargetTriple() {
-  return m_target_triple.c_str();
-}
-
-void TypeSystemClang::SetTargetTriple(llvm::StringRef target_triple) {
-  m_target_triple = target_triple.str();
-}
-
-void TypeSystemClang::SetExternalSource(
-    llvm::IntrusiveRefCntPtr<ExternalASTSource> &ast_source_up) {
-  ASTContext &ast = getASTContext();
-  ast.setExternalSource(ast_source_up);
-  ast.getTranslationUnitDecl()->setHasExternalLexicalStorage(true);
-}
-
-ASTContext &TypeSystemClang::getASTContext() {
-  assert(m_ast_up);
-  return *m_ast_up;
-}
-
-class NullDiagnosticConsumer : public DiagnosticConsumer {
-public:
-  NullDiagnosticConsumer() {
-    m_log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS);
-  }
-
-  void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
-                        const clang::Diagnostic &info) override {
-    if (m_log) {
-      llvm::SmallVector<char, 32> diag_str(10);
-      info.FormatDiagnostic(diag_str);
-      diag_str.push_back('\0');
-      LLDB_LOGF(m_log, "Compiler diagnostic: %s\n", diag_str.data());
-    }
-  }
-
-  DiagnosticConsumer *clone(DiagnosticsEngine &Diags) const {
-    return new NullDiagnosticConsumer();
-  }
-
-private:
-  Log *m_log;
-};
-
-void TypeSystemClang::CreateASTContext() {
-  assert(!m_ast_up);
-  m_ast_owned = true;
-
-  m_language_options_up.reset(new LangOptions());
-  ParseLangArgs(*m_language_options_up, clang::Language::ObjCXX,
-                GetTargetTriple());
-
-  m_identifier_table_up.reset(
-      new IdentifierTable(*m_language_options_up, nullptr));
-  m_builtins_up.reset(new Builtin::Context());
-
-  m_selector_table_up.reset(new SelectorTable());
-
-  clang::FileSystemOptions file_system_options;
-  m_file_manager_up.reset(new clang::FileManager(
-      file_system_options, FileSystem::Instance().GetVirtualFileSystem()));
-
-  llvm::IntrusiveRefCntPtr<DiagnosticIDs> diag_id_sp(new DiagnosticIDs());
-  m_diagnostics_engine_up.reset(
-      new DiagnosticsEngine(diag_id_sp, new DiagnosticOptions()));
-
-  m_source_manager_up.reset(
-      new clang::SourceManager(*m_diagnostics_engine_up, *m_file_manager_up));
-  m_ast_up.reset(new ASTContext(*m_language_options_up, *m_source_manager_up,
-                                *m_identifier_table_up, *m_selector_table_up,
-                                *m_builtins_up));
-
-  m_diagnostic_consumer_up.reset(new NullDiagnosticConsumer);
-  m_ast_up->getDiagnostics().setClient(m_diagnostic_consumer_up.get(), false);
-
-  // This can be NULL if we don't know anything about the architecture or if
-  // the target for an architecture isn't enabled in the llvm/clang that we
-  // built
-  TargetInfo *target_info = getTargetInfo();
-  if (target_info)
-    m_ast_up->InitBuiltinTypes(*target_info);
-
-  GetASTMap().Insert(m_ast_up.get(), this);
-
-  llvm::IntrusiveRefCntPtr<clang::ExternalASTSource> ast_source_up(
-      new ClangExternalASTSourceCallbacks(*this));
-  SetExternalSource(ast_source_up);
-}
-
-TypeSystemClang *TypeSystemClang::GetASTContext(clang::ASTContext *ast) {
-  TypeSystemClang *clang_ast = GetASTMap().Lookup(ast);
-  return clang_ast;
-}
-
-clang::MangleContext *TypeSystemClang::getMangleContext() {
-  if (m_mangle_ctx_up == nullptr)
-    m_mangle_ctx_up.reset(getASTContext().createMangleContext());
-  return m_mangle_ctx_up.get();
-}
-
-std::shared_ptr<clang::TargetOptions> &TypeSystemClang::getTargetOptions() {
-  if (m_target_options_rp == nullptr && !m_target_triple.empty()) {
-    m_target_options_rp = std::make_shared<clang::TargetOptions>();
-    if (m_target_options_rp != nullptr)
-      m_target_options_rp->Triple = m_target_triple;
-  }
-  return m_target_options_rp;
-}
-
-TargetInfo *TypeSystemClang::getTargetInfo() {
-  // target_triple should be something like "x86_64-apple-macosx"
-  if (m_target_info_up == nullptr && !m_target_triple.empty())
-    m_target_info_up.reset(TargetInfo::CreateTargetInfo(
-        getASTContext().getDiagnostics(), getTargetOptions()));
-  return m_target_info_up.get();
-}
-
-#pragma mark Basic Types
-
-static inline bool QualTypeMatchesBitSize(const uint64_t bit_size,
-                                          ASTContext &ast, QualType qual_type) {
-  uint64_t qual_type_bit_size = ast.getTypeSize(qual_type);
-  return qual_type_bit_size == bit_size;
-}
-
-CompilerType
-TypeSystemClang::GetBuiltinTypeForEncodingAndBitSize(Encoding encoding,
-                                                     size_t bit_size) {
-  ASTContext &ast = getASTContext();
-  switch (encoding) {
-  case eEncodingInvalid:
-    if (QualTypeMatchesBitSize(bit_size, ast, ast.VoidPtrTy))
-      return GetType(ast.VoidPtrTy);
-    break;
-
-  case eEncodingUint:
-    if (QualTypeMatchesBitSize(bit_size, ast, ast.UnsignedCharTy))
-      return GetType(ast.UnsignedCharTy);
-    if (QualTypeMatchesBitSize(bit_size, ast, ast.UnsignedShortTy))
-      return GetType(ast.UnsignedShortTy);
-    if (QualTypeMatchesBitSize(bit_size, ast, ast.UnsignedIntTy))
-      return GetType(ast.UnsignedIntTy);
-    if (QualTypeMatchesBitSize(bit_size, ast, ast.UnsignedLongTy))
-      return GetType(ast.UnsignedLongTy);
-    if (QualTypeMatchesBitSize(bit_size, ast, ast.UnsignedLongLongTy))
-      return GetType(ast.UnsignedLongLongTy);
-    if (QualTypeMatchesBitSize(bit_size, ast, ast.UnsignedInt128Ty))
-      return GetType(ast.UnsignedInt128Ty);
-    break;
-
-  case eEncodingSint:
-    if (QualTypeMatchesBitSize(bit_size, ast, ast.SignedCharTy))
-      return GetType(ast.SignedCharTy);
-    if (QualTypeMatchesBitSize(bit_size, ast, ast.ShortTy))
-      return GetType(ast.ShortTy);
-    if (QualTypeMatchesBitSize(bit_size, ast, ast.IntTy))
-      return GetType(ast.IntTy);
-    if (QualTypeMatchesBitSize(bit_size, ast, ast.LongTy))
-      return GetType(ast.LongTy);
-    if (QualTypeMatchesBitSize(bit_size, ast, ast.LongLongTy))
-      return GetType(ast.LongLongTy);
-    if (QualTypeMatchesBitSize(bit_size, ast, ast.Int128Ty))
-      return GetType(ast.Int128Ty);
-    break;
-
-  case eEncodingIEEE754:
-    if (QualTypeMatchesBitSize(bit_size, ast, ast.FloatTy))
-      return GetType(ast.FloatTy);
-    if (QualTypeMatchesBitSize(bit_size, ast, ast.DoubleTy))
-      return GetType(ast.DoubleTy);
-    if (QualTypeMatchesBitSize(bit_size, ast, ast.LongDoubleTy))
-      return GetType(ast.LongDoubleTy);
-    if (QualTypeMatchesBitSize(bit_size, ast, ast.HalfTy))
-      return GetType(ast.HalfTy);
-    break;
-
-  case eEncodingVector:
-    // Sanity check that bit_size is a multiple of 8's.
-    if (bit_size && !(bit_size & 0x7u))
-      return GetType(ast.getExtVectorType(ast.UnsignedCharTy, bit_size / 8));
-    break;
-  }
-
-  return CompilerType();
-}
-
-lldb::BasicType
-TypeSystemClang::GetBasicTypeEnumeration(ConstString name) {
-  if (name) {
-    typedef UniqueCStringMap<lldb::BasicType> TypeNameToBasicTypeMap;
-    static TypeNameToBasicTypeMap g_type_map;
-    static llvm::once_flag g_once_flag;
-    llvm::call_once(g_once_flag, []() {
-      // "void"
-      g_type_map.Append(ConstString("void"), eBasicTypeVoid);
-
-      // "char"
-      g_type_map.Append(ConstString("char"), eBasicTypeChar);
-      g_type_map.Append(ConstString("signed char"), eBasicTypeSignedChar);
-      g_type_map.Append(ConstString("unsigned char"), eBasicTypeUnsignedChar);
-      g_type_map.Append(ConstString("wchar_t"), eBasicTypeWChar);
-      g_type_map.Append(ConstString("signed wchar_t"), eBasicTypeSignedWChar);
-      g_type_map.Append(ConstString("unsigned wchar_t"),
-                        eBasicTypeUnsignedWChar);
-      // "short"
-      g_type_map.Append(ConstString("short"), eBasicTypeShort);
-      g_type_map.Append(ConstString("short int"), eBasicTypeShort);
-      g_type_map.Append(ConstString("unsigned short"), eBasicTypeUnsignedShort);
-      g_type_map.Append(ConstString("unsigned short int"),
-                        eBasicTypeUnsignedShort);
-
-      // "int"
-      g_type_map.Append(ConstString("int"), eBasicTypeInt);
-      g_type_map.Append(ConstString("signed int"), eBasicTypeInt);
-      g_type_map.Append(ConstString("unsigned int"), eBasicTypeUnsignedInt);
-      g_type_map.Append(ConstString("unsigned"), eBasicTypeUnsignedInt);
-
-      // "long"
-      g_type_map.Append(ConstString("long"), eBasicTypeLong);
-      g_type_map.Append(ConstString("long int"), eBasicTypeLong);
-      g_type_map.Append(ConstString("unsigned long"), eBasicTypeUnsignedLong);
-      g_type_map.Append(ConstString("unsigned long int"),
-                        eBasicTypeUnsignedLong);
-
-      // "long long"
-      g_type_map.Append(ConstString("long long"), eBasicTypeLongLong);
-      g_type_map.Append(ConstString("long long int"), eBasicTypeLongLong);
-      g_type_map.Append(ConstString("unsigned long long"),
-                        eBasicTypeUnsignedLongLong);
-      g_type_map.Append(ConstString("unsigned long long int"),
-                        eBasicTypeUnsignedLongLong);
-
-      // "int128"
-      g_type_map.Append(ConstString("__int128_t"), eBasicTypeInt128);
-      g_type_map.Append(ConstString("__uint128_t"), eBasicTypeUnsignedInt128);
-
-      // Miscellaneous
-      g_type_map.Append(ConstString("bool"), eBasicTypeBool);
-      g_type_map.Append(ConstString("float"), eBasicTypeFloat);
-      g_type_map.Append(ConstString("double"), eBasicTypeDouble);
-      g_type_map.Append(ConstString("long double"), eBasicTypeLongDouble);
-      g_type_map.Append(ConstString("id"), eBasicTypeObjCID);
-      g_type_map.Append(ConstString("SEL"), eBasicTypeObjCSel);
-      g_type_map.Append(ConstString("nullptr"), eBasicTypeNullPtr);
-      g_type_map.Sort();
-    });
-
-    return g_type_map.Find(name, eBasicTypeInvalid);
-  }
-  return eBasicTypeInvalid;
-}
-
-uint32_t TypeSystemClang::GetPointerByteSize() {
-  if (m_pointer_byte_size == 0)
-    if (auto size = GetBasicType(lldb::eBasicTypeVoid)
-                        .GetPointerType()
-                        .GetByteSize(nullptr))
-      m_pointer_byte_size = *size;
-  return m_pointer_byte_size;
-}
-
-CompilerType TypeSystemClang::GetBasicType(lldb::BasicType basic_type) {
-  clang::ASTContext &ast = getASTContext();
-
-  lldb::opaque_compiler_type_t clang_type =
-      GetOpaqueCompilerType(&ast, basic_type);
-
-  if (clang_type)
-    return CompilerType(this, clang_type);
-  return CompilerType();
-}
-
-CompilerType TypeSystemClang::GetBuiltinTypeForDWARFEncodingAndBitSize(
-    llvm::StringRef type_name, uint32_t dw_ate, uint32_t bit_size) {
-  ASTContext &ast = getASTContext();
-
-  switch (dw_ate) {
-  default:
-    break;
-
-  case DW_ATE_address:
-    if (QualTypeMatchesBitSize(bit_size, ast, ast.VoidPtrTy))
-      return GetType(ast.VoidPtrTy);
-    break;
-
-  case DW_ATE_boolean:
-    if (QualTypeMatchesBitSize(bit_size, ast, ast.BoolTy))
-      return GetType(ast.BoolTy);
-    if (QualTypeMatchesBitSize(bit_size, ast, ast.UnsignedCharTy))
-      return GetType(ast.UnsignedCharTy);
-    if (QualTypeMatchesBitSize(bit_size, ast, ast.UnsignedShortTy))
-      return GetType(ast.UnsignedShortTy);
-    if (QualTypeMatchesBitSize(bit_size, ast, ast.UnsignedIntTy))
-      return GetType(ast.UnsignedIntTy);
-    break;
-
-  case DW_ATE_lo_user:
-    // This has been seen to mean DW_AT_complex_integer
-    if (type_name.contains("complex")) {
-      CompilerType complex_int_clang_type =
-          GetBuiltinTypeForDWARFEncodingAndBitSize("int", DW_ATE_signed,
-                                                   bit_size / 2);
-      return GetType(
-          ast.getComplexType(ClangUtil::GetQualType(complex_int_clang_type)));
-    }
-    break;
-
-  case DW_ATE_complex_float:
-    if (QualTypeMatchesBitSize(bit_size, ast, ast.FloatComplexTy))
-      return GetType(ast.FloatComplexTy);
-    else if (QualTypeMatchesBitSize(bit_size, ast, ast.DoubleComplexTy))
-      return GetType(ast.DoubleComplexTy);
-    else if (QualTypeMatchesBitSize(bit_size, ast, ast.LongDoubleComplexTy))
-      return GetType(ast.LongDoubleComplexTy);
-    else {
-      CompilerType complex_float_clang_type =
-          GetBuiltinTypeForDWARFEncodingAndBitSize("float", DW_ATE_float,
-                                                   bit_size / 2);
-      return GetType(
-          ast.getComplexType(ClangUtil::GetQualType(complex_float_clang_type)));
-    }
-    break;
-
-  case DW_ATE_float:
-    if (type_name == "float" &&
-        QualTypeMatchesBitSize(bit_size, ast, ast.FloatTy))
-      return GetType(ast.FloatTy);
-    if (type_name == "double" &&
-        QualTypeMatchesBitSize(bit_size, ast, ast.DoubleTy))
-      return GetType(ast.DoubleTy);
-    if (type_name == "long double" &&
-        QualTypeMatchesBitSize(bit_size, ast, ast.LongDoubleTy))
-      return GetType(ast.LongDoubleTy);
-    // Fall back to not requiring a name match
-    if (QualTypeMatchesBitSize(bit_size, ast, ast.FloatTy))
-      return GetType(ast.FloatTy);
-    if (QualTypeMatchesBitSize(bit_size, ast, ast.DoubleTy))
-      return GetType(ast.DoubleTy);
-    if (QualTypeMatchesBitSize(bit_size, ast, ast.LongDoubleTy))
-      return GetType(ast.LongDoubleTy);
-    if (QualTypeMatchesBitSize(bit_size, ast, ast.HalfTy))
-      return GetType(ast.HalfTy);
-    break;
-
-  case DW_ATE_signed:
-    if (!type_name.empty()) {
-      if (type_name == "wchar_t" &&
-          QualTypeMatchesBitSize(bit_size, ast, ast.WCharTy) &&
-          (getTargetInfo() &&
-           TargetInfo::isTypeSigned(getTargetInfo()->getWCharType())))
-        return GetType(ast.WCharTy);
-      if (type_name == "void" &&
-          QualTypeMatchesBitSize(bit_size, ast, ast.VoidTy))
-        return GetType(ast.VoidTy);
-      if (type_name.contains("long long") &&
-          QualTypeMatchesBitSize(bit_size, ast, ast.LongLongTy))
-        return GetType(ast.LongLongTy);
-      if (type_name.contains("long") &&
-          QualTypeMatchesBitSize(bit_size, ast, ast.LongTy))
-        return GetType(ast.LongTy);
-      if (type_name.contains("short") &&
-          QualTypeMatchesBitSize(bit_size, ast, ast.ShortTy))
-        return GetType(ast.ShortTy);
-      if (type_name.contains("char")) {
-        if (QualTypeMatchesBitSize(bit_size, ast, ast.CharTy))
-          return GetType(ast.CharTy);
-        if (QualTypeMatchesBitSize(bit_size, ast, ast.SignedCharTy))
-          return GetType(ast.SignedCharTy);
-      }
-      if (type_name.contains("int")) {
-        if (QualTypeMatchesBitSize(bit_size, ast, ast.IntTy))
-          return GetType(ast.IntTy);
-        if (QualTypeMatchesBitSize(bit_size, ast, ast.Int128Ty))
-          return GetType(ast.Int128Ty);
-      }
-    }
-    // We weren't able to match up a type name, just search by size
-    if (QualTypeMatchesBitSize(bit_size, ast, ast.CharTy))
-      return GetType(ast.CharTy);
-    if (QualTypeMatchesBitSize(bit_size, ast, ast.ShortTy))
-      return GetType(ast.ShortTy);
-    if (QualTypeMatchesBitSize(bit_size, ast, ast.IntTy))
-      return GetType(ast.IntTy);
-    if (QualTypeMatchesBitSize(bit_size, ast, ast.LongTy))
-      return GetType(ast.LongTy);
-    if (QualTypeMatchesBitSize(bit_size, ast, ast.LongLongTy))
-      return GetType(ast.LongLongTy);
-    if (QualTypeMatchesBitSize(bit_size, ast, ast.Int128Ty))
-      return GetType(ast.Int128Ty);
-    break;
-
-  case DW_ATE_signed_char:
-    if (ast.getLangOpts().CharIsSigned && type_name == "char") {
-      if (QualTypeMatchesBitSize(bit_size, ast, ast.CharTy))
-        return GetType(ast.CharTy);
-    }
-    if (QualTypeMatchesBitSize(bit_size, ast, ast.SignedCharTy))
-      return GetType(ast.SignedCharTy);
-    break;
-
-  case DW_ATE_unsigned:
-    if (!type_name.empty()) {
-      if (type_name == "wchar_t") {
-        if (QualTypeMatchesBitSize(bit_size, ast, ast.WCharTy)) {
-          if (!(getTargetInfo() &&
-                TargetInfo::isTypeSigned(getTargetInfo()->getWCharType())))
-            return GetType(ast.WCharTy);
-        }
-      }
-      if (type_name.contains("long long")) {
-        if (QualTypeMatchesBitSize(bit_size, ast, ast.UnsignedLongLongTy))
-          return GetType(ast.UnsignedLongLongTy);
-      } else if (type_name.contains("long")) {
-        if (QualTypeMatchesBitSize(bit_size, ast, ast.UnsignedLongTy))
-          return GetType(ast.UnsignedLongTy);
-      } else if (type_name.contains("short")) {
-        if (QualTypeMatchesBitSize(bit_size, ast, ast.UnsignedShortTy))
-          return GetType(ast.UnsignedShortTy);
-      } else if (type_name.contains("char")) {
-        if (QualTypeMatchesBitSize(bit_size, ast, ast.UnsignedCharTy))
-          return GetType(ast.UnsignedCharTy);
-      } else if (type_name.contains("int")) {
-        if (QualTypeMatchesBitSize(bit_size, ast, ast.UnsignedIntTy))
-          return GetType(ast.UnsignedIntTy);
-        if (QualTypeMatchesBitSize(bit_size, ast, ast.UnsignedInt128Ty))
-          return GetType(ast.UnsignedInt128Ty);
-      }
-    }
-    // We weren't able to match up a type name, just search by size
-    if (QualTypeMatchesBitSize(bit_size, ast, ast.UnsignedCharTy))
-      return GetType(ast.UnsignedCharTy);
-    if (QualTypeMatchesBitSize(bit_size, ast, ast.UnsignedShortTy))
-      return GetType(ast.UnsignedShortTy);
-    if (QualTypeMatchesBitSize(bit_size, ast, ast.UnsignedIntTy))
-      return GetType(ast.UnsignedIntTy);
-    if (QualTypeMatchesBitSize(bit_size, ast, ast.UnsignedLongTy))
-      return GetType(ast.UnsignedLongTy);
-    if (QualTypeMatchesBitSize(bit_size, ast, ast.UnsignedLongLongTy))
-      return GetType(ast.UnsignedLongLongTy);
-    if (QualTypeMatchesBitSize(bit_size, ast, ast.UnsignedInt128Ty))
-      return GetType(ast.UnsignedInt128Ty);
-    break;
-
-  case DW_ATE_unsigned_char:
-    if (!ast.getLangOpts().CharIsSigned && type_name == "char") {
-      if (QualTypeMatchesBitSize(bit_size, ast, ast.CharTy))
-        return GetType(ast.CharTy);
-    }
-    if (QualTypeMatchesBitSize(bit_size, ast, ast.UnsignedCharTy))
-      return GetType(ast.UnsignedCharTy);
-    if (QualTypeMatchesBitSize(bit_size, ast, ast.UnsignedShortTy))
-      return GetType(ast.UnsignedShortTy);
-    break;
-
-  case DW_ATE_imaginary_float:
-    break;
-
-  case DW_ATE_UTF:
-    if (!type_name.empty()) {
-      if (type_name == "char16_t")
-        return GetType(ast.Char16Ty);
-      if (type_name == "char32_t")
-        return GetType(ast.Char32Ty);
-      if (type_name == "char8_t")
-        return GetType(ast.Char8Ty);
-    }
-    break;
-  }
-  // This assert should fire for anything that we don't catch above so we know
-  // to fix any issues we run into.
-  if (!type_name.empty()) {
-    std::string type_name_str = type_name.str();
-    Host::SystemLog(Host::eSystemLogError,
-                    "error: need to add support for DW_TAG_base_type '%s' "
-                    "encoded with DW_ATE = 0x%x, bit_size = %u\n",
-                    type_name_str.c_str(), dw_ate, bit_size);
-  } else {
-    Host::SystemLog(Host::eSystemLogError, "error: need to add support for "
-                                           "DW_TAG_base_type encoded with "
-                                           "DW_ATE = 0x%x, bit_size = %u\n",
-                    dw_ate, bit_size);
-  }
-  return CompilerType();
-}
-
-CompilerType TypeSystemClang::GetCStringType(bool is_const) {
-  ASTContext &ast = getASTContext();
-  QualType char_type(ast.CharTy);
-
-  if (is_const)
-    char_type.addConst();
-
-  return GetType(ast.getPointerType(char_type));
-}
-
-bool TypeSystemClang::AreTypesSame(CompilerType type1, CompilerType type2,
-                                   bool ignore_qualifiers) {
-  TypeSystemClang *ast =
-      llvm::dyn_cast_or_null<TypeSystemClang>(type1.GetTypeSystem());
-  if (!ast || ast != type2.GetTypeSystem())
-    return false;
-
-  if (type1.GetOpaqueQualType() == type2.GetOpaqueQualType())
-    return true;
-
-  QualType type1_qual = ClangUtil::GetQualType(type1);
-  QualType type2_qual = ClangUtil::GetQualType(type2);
-
-  if (ignore_qualifiers) {
-    type1_qual = type1_qual.getUnqualifiedType();
-    type2_qual = type2_qual.getUnqualifiedType();
-  }
-
-  return ast->getASTContext().hasSameType(type1_qual, type2_qual);
-}
-
-CompilerType TypeSystemClang::GetTypeForDecl(void *opaque_decl) {
-  if (!opaque_decl)
-    return CompilerType();
-
-  clang::Decl *decl = static_cast<clang::Decl *>(opaque_decl);
-  if (auto *named_decl = llvm::dyn_cast<clang::NamedDecl>(decl))
-    return GetTypeForDecl(named_decl);
-  return CompilerType();
-}
-
-CompilerDeclContext TypeSystemClang::CreateDeclContext(DeclContext *ctx) {
-  // Check that the DeclContext actually belongs to this ASTContext.
-  assert(&ctx->getParentASTContext() == &getASTContext());
-  return CompilerDeclContext(this, ctx);
-}
-
-CompilerType TypeSystemClang::GetTypeForDecl(clang::NamedDecl *decl) {
-  if (clang::ObjCInterfaceDecl *interface_decl =
-      llvm::dyn_cast<clang::ObjCInterfaceDecl>(decl))
-    return GetTypeForDecl(interface_decl);
-  if (clang::TagDecl *tag_decl = llvm::dyn_cast<clang::TagDecl>(decl))
-    return GetTypeForDecl(tag_decl);
-  return CompilerType();
-}
-
-CompilerType TypeSystemClang::GetTypeForDecl(TagDecl *decl) {
-  return GetType(getASTContext().getTagDeclType(decl));
-}
-
-CompilerType TypeSystemClang::GetTypeForDecl(ObjCInterfaceDecl *decl) {
-  return GetType(getASTContext().getObjCInterfaceType(decl));
-}
-
-#pragma mark Structure, Unions, Classes
-
-CompilerType TypeSystemClang::CreateRecordType(DeclContext *decl_ctx,
-                                               AccessType access_type,
-                                               llvm::StringRef name, int kind,
-                                               LanguageType language,
-                                               ClangASTMetadata *metadata,
-                                               bool exports_symbols) {
-  ASTContext &ast = getASTContext();
-
-  if (decl_ctx == nullptr)
-    decl_ctx = ast.getTranslationUnitDecl();
-
-  if (language == eLanguageTypeObjC ||
-      language == eLanguageTypeObjC_plus_plus) {
-    bool isForwardDecl = true;
-    bool isInternal = false;
-    return CreateObjCClass(name, decl_ctx, isForwardDecl, isInternal, metadata);
-  }
-
-  // NOTE: Eventually CXXRecordDecl will be merged back into RecordDecl and
-  // we will need to update this code. I was told to currently always use the
-  // CXXRecordDecl class since we often don't know from debug information if
-  // something is struct or a class, so we default to always use the more
-  // complete definition just in case.
-
-  bool has_name = !name.empty();
-
-  CXXRecordDecl *decl = CXXRecordDecl::Create(
-      ast, (TagDecl::TagKind)kind, decl_ctx, SourceLocation(), SourceLocation(),
-      has_name ? &ast.Idents.get(name) : nullptr);
-
-  if (!has_name) {
-    // In C++ a lambda is also represented as an unnamed class. This is
-    // different from an *anonymous class* that the user wrote:
-    //
-    // struct A {
-    //  // anonymous class (GNU/MSVC extension)
-    //  struct {
-    //    int x;
-    //  };
-    //  // unnamed class within a class
-    //  struct {
-    //    int y;
-    //  } B;
-    // };
-    //
-    // void f() {
-    //    // unammed class outside of a class
-    //    struct {
-    //      int z;
-    //    } C;
-    // }
-    //
-    // Anonymous classes is a GNU/MSVC extension that clang supports. It
-    // requires the anonymous class be embedded within a class. So the new
-    // heuristic verifies this condition.
-    if (isa<CXXRecordDecl>(decl_ctx) && exports_symbols)
-      decl->setAnonymousStructOrUnion(true);
-  }
-
-  if (decl) {
-    if (metadata)
-      SetMetadata(decl, *metadata);
-
-    if (access_type != eAccessNone)
-      decl->setAccess(ConvertAccessTypeToAccessSpecifier(access_type));
-
-    if (decl_ctx)
-      decl_ctx->addDecl(decl);
-
-    return GetType(ast.getTagDeclType(decl));
-  }
-  return CompilerType();
-}
-
-namespace {
-  bool IsValueParam(const clang::TemplateArgument &argument) {
-    return argument.getKind() == TemplateArgument::Integral;
-  }
-}
-
-static TemplateParameterList *CreateTemplateParameterList(
-    ASTContext *ast,
-    const TypeSystemClang::TemplateParameterInfos &template_param_infos,
-    llvm::SmallVector<NamedDecl *, 8> &template_param_decls) {
-  const bool parameter_pack = false;
-  const bool is_typename = false;
-  const unsigned depth = 0;
-  const size_t num_template_params = template_param_infos.args.size();
-  DeclContext *const decl_context =
-      ast->getTranslationUnitDecl(); // Is this the right decl context?,
-  for (size_t i = 0; i < num_template_params; ++i) {
-    const char *name = template_param_infos.names[i];
-
-    IdentifierInfo *identifier_info = nullptr;
-    if (name && name[0])
-      identifier_info = &ast->Idents.get(name);
-    if (IsValueParam(template_param_infos.args[i])) {
-      template_param_decls.push_back(NonTypeTemplateParmDecl::Create(
-          *ast, decl_context,
-          SourceLocation(), SourceLocation(), depth, i, identifier_info,
-          template_param_infos.args[i].getIntegralType(), parameter_pack,
-          nullptr));
-
-    } else {
-      template_param_decls.push_back(TemplateTypeParmDecl::Create(
-          *ast, decl_context,
-          SourceLocation(), SourceLocation(), depth, i, identifier_info,
-          is_typename, parameter_pack));
-    }
-  }
-
-  if (template_param_infos.packed_args) {
-    IdentifierInfo *identifier_info = nullptr;
-    if (template_param_infos.pack_name && template_param_infos.pack_name[0])
-      identifier_info = &ast->Idents.get(template_param_infos.pack_name);
-    const bool parameter_pack_true = true;
-
-    if (!template_param_infos.packed_args->args.empty() &&
-        IsValueParam(template_param_infos.packed_args->args[0])) {
-      template_param_decls.push_back(NonTypeTemplateParmDecl::Create(
-          *ast, decl_context, SourceLocation(), SourceLocation(), depth,
-          num_template_params, identifier_info,
-          template_param_infos.packed_args->args[0].getIntegralType(),
-          parameter_pack_true, nullptr));
-    } else {
-      template_param_decls.push_back(TemplateTypeParmDecl::Create(
-          *ast, decl_context, SourceLocation(), SourceLocation(), depth,
-          num_template_params, identifier_info, is_typename,
-          parameter_pack_true));
-    }
-  }
-  clang::Expr *const requires_clause = nullptr; // TODO: Concepts
-  TemplateParameterList *template_param_list = TemplateParameterList::Create(
-      *ast, SourceLocation(), SourceLocation(), template_param_decls,
-      SourceLocation(), requires_clause);
-  return template_param_list;
-}
-
-clang::FunctionTemplateDecl *TypeSystemClang::CreateFunctionTemplateDecl(
-    clang::DeclContext *decl_ctx, clang::FunctionDecl *func_decl,
-    const char *name, const TemplateParameterInfos &template_param_infos) {
-  //    /// Create a function template node.
-  ASTContext &ast = getASTContext();
-
-  llvm::SmallVector<NamedDecl *, 8> template_param_decls;
-
-  TemplateParameterList *template_param_list = CreateTemplateParameterList(
-      &ast, template_param_infos, template_param_decls);
-  FunctionTemplateDecl *func_tmpl_decl = FunctionTemplateDecl::Create(
-      ast, decl_ctx, func_decl->getLocation(), func_decl->getDeclName(),
-      template_param_list, func_decl);
-
-  for (size_t i = 0, template_param_decl_count = template_param_decls.size();
-       i < template_param_decl_count; ++i) {
-    // TODO: verify which decl context we should put template_param_decls into..
-    template_param_decls[i]->setDeclContext(func_decl);
-  }
-  // Function templates inside a record need to have an access specifier.
-  // It doesn't matter what access specifier we give the template as LLDB
-  // anyway allows accessing everything inside a record.
-  if (decl_ctx->isRecord())
-    func_tmpl_decl->setAccess(clang::AccessSpecifier::AS_public);
-
-  return func_tmpl_decl;
-}
-
-void TypeSystemClang::CreateFunctionTemplateSpecializationInfo(
-    FunctionDecl *func_decl, clang::FunctionTemplateDecl *func_tmpl_decl,
-    const TemplateParameterInfos &infos) {
-  TemplateArgumentList *template_args_ptr =
-      TemplateArgumentList::CreateCopy(func_decl->getASTContext(), infos.args);
-
-  func_decl->setFunctionTemplateSpecialization(func_tmpl_decl,
-                                               template_args_ptr, nullptr);
-}
-
-ClassTemplateDecl *TypeSystemClang::CreateClassTemplateDecl(
-    DeclContext *decl_ctx, lldb::AccessType access_type, const char *class_name,
-    int kind, const TemplateParameterInfos &template_param_infos) {
-  ASTContext &ast = getASTContext();
-
-  ClassTemplateDecl *class_template_decl = nullptr;
-  if (decl_ctx == nullptr)
-    decl_ctx = ast.getTranslationUnitDecl();
-
-  IdentifierInfo &identifier_info = ast.Idents.get(class_name);
-  DeclarationName decl_name(&identifier_info);
-
-  clang::DeclContext::lookup_result result = decl_ctx->lookup(decl_name);
-
-  for (NamedDecl *decl : result) {
-    class_template_decl = dyn_cast<clang::ClassTemplateDecl>(decl);
-    if (class_template_decl)
-      return class_template_decl;
-  }
-
-  llvm::SmallVector<NamedDecl *, 8> template_param_decls;
-
-  TemplateParameterList *template_param_list = CreateTemplateParameterList(
-      &ast, template_param_infos, template_param_decls);
-
-  CXXRecordDecl *template_cxx_decl = CXXRecordDecl::Create(
-      ast, (TagDecl::TagKind)kind,
-      decl_ctx, // What decl context do we use here? TU? The actual decl
-                // context?
-      SourceLocation(), SourceLocation(), &identifier_info);
-
-  for (size_t i = 0, template_param_decl_count = template_param_decls.size();
-       i < template_param_decl_count; ++i) {
-    template_param_decls[i]->setDeclContext(template_cxx_decl);
-  }
-
-  // With templated classes, we say that a class is templated with
-  // specializations, but that the bare class has no functions.
-  // template_cxx_decl->startDefinition();
-  // template_cxx_decl->completeDefinition();
-
-  class_template_decl = ClassTemplateDecl::Create(
-      ast,
-      decl_ctx, // What decl context do we use here? TU? The actual decl
-                // context?
-      SourceLocation(), decl_name, template_param_list, template_cxx_decl);
-  template_cxx_decl->setDescribedClassTemplate(class_template_decl);
-
-  if (class_template_decl) {
-    if (access_type != eAccessNone)
-      class_template_decl->setAccess(
-          ConvertAccessTypeToAccessSpecifier(access_type));
-
-    // if (TagDecl *ctx_tag_decl = dyn_cast<TagDecl>(decl_ctx))
-    //    CompleteTagDeclarationDefinition(GetTypeForDecl(ctx_tag_decl));
-
-    decl_ctx->addDecl(class_template_decl);
-
-#ifdef LLDB_CONFIGURATION_DEBUG
-    VerifyDecl(class_template_decl);
-#endif
-  }
-
-  return class_template_decl;
-}
-
-TemplateTemplateParmDecl *
-TypeSystemClang::CreateTemplateTemplateParmDecl(const char *template_name) {
-  ASTContext &ast = getASTContext();
-
-  auto *decl_ctx = ast.getTranslationUnitDecl();
-
-  IdentifierInfo &identifier_info = ast.Idents.get(template_name);
-  llvm::SmallVector<NamedDecl *, 8> template_param_decls;
-
-  TypeSystemClang::TemplateParameterInfos template_param_infos;
-  TemplateParameterList *template_param_list = CreateTemplateParameterList(
-      &ast, template_param_infos, template_param_decls);
-
-  // LLDB needs to create those decls only to be able to display a
-  // type that includes a template template argument. Only the name matters for
-  // this purpose, so we use dummy values for the other characterisitcs of the
-  // type.
-  return TemplateTemplateParmDecl::Create(
-      ast, decl_ctx, SourceLocation(),
-      /*Depth*/ 0, /*Position*/ 0,
-      /*IsParameterPack*/ false, &identifier_info, template_param_list);
-}
-
-ClassTemplateSpecializationDecl *
-TypeSystemClang::CreateClassTemplateSpecializationDecl(
-    DeclContext *decl_ctx, ClassTemplateDecl *class_template_decl, int kind,
-    const TemplateParameterInfos &template_param_infos) {
-  ASTContext &ast = getASTContext();
-  llvm::SmallVector<clang::TemplateArgument, 2> args(
-      template_param_infos.args.size() +
-      (template_param_infos.packed_args ? 1 : 0));
-  std::copy(template_param_infos.args.begin(), template_param_infos.args.end(),
-            args.begin());
-  if (template_param_infos.packed_args) {
-    args[args.size() - 1] = TemplateArgument::CreatePackCopy(
-        ast, template_param_infos.packed_args->args);
-  }
-  ClassTemplateSpecializationDecl *class_template_specialization_decl =
-      ClassTemplateSpecializationDecl::Create(
-          ast, (TagDecl::TagKind)kind, decl_ctx, SourceLocation(),
-          SourceLocation(), class_template_decl, args, nullptr);
-
-  class_template_specialization_decl->setSpecializationKind(
-      TSK_ExplicitSpecialization);
-
-  return class_template_specialization_decl;
-}
-
-CompilerType TypeSystemClang::CreateClassTemplateSpecializationType(
-    ClassTemplateSpecializationDecl *class_template_specialization_decl) {
-  if (class_template_specialization_decl) {
-    ASTContext &ast = getASTContext();
-    return GetType(ast.getTagDeclType(class_template_specialization_decl));
-  }
-  return CompilerType();
-}
-
-static inline bool check_op_param(bool is_method,
-                                  clang::OverloadedOperatorKind op_kind,
-                                  bool unary, bool binary,
-                                  uint32_t num_params) {
-  // Special-case call since it can take any number of operands
-  if (op_kind == OO_Call)
-    return true;
-
-  // The parameter count doesn't include "this"
-  if (is_method)
-    ++num_params;
-  if (num_params == 1)
-    return unary;
-  if (num_params == 2)
-    return binary;
-  else
-    return false;
-}
-
-bool TypeSystemClang::CheckOverloadedOperatorKindParameterCount(
-    bool is_method, clang::OverloadedOperatorKind op_kind,
-    uint32_t num_params) {
-  switch (op_kind) {
-  default:
-    break;
-  // C++ standard allows any number of arguments to new/delete
-  case OO_New:
-  case OO_Array_New:
-  case OO_Delete:
-  case OO_Array_Delete:
-    return true;
-  }
-
-#define OVERLOADED_OPERATOR(Name, Spelling, Token, Unary, Binary, MemberOnly)  \
-  case OO_##Name:                                                              \
-    return check_op_param(is_method, op_kind, Unary, Binary, num_params);
-  switch (op_kind) {
-#include "clang/Basic/OperatorKinds.def"
-  default:
-    break;
-  }
-  return false;
-}
-
-clang::AccessSpecifier
-TypeSystemClang::UnifyAccessSpecifiers(clang::AccessSpecifier lhs,
-                                       clang::AccessSpecifier rhs) {
-  // Make the access equal to the stricter of the field and the nested field's
-  // access
-  if (lhs == AS_none || rhs == AS_none)
-    return AS_none;
-  if (lhs == AS_private || rhs == AS_private)
-    return AS_private;
-  if (lhs == AS_protected || rhs == AS_protected)
-    return AS_protected;
-  return AS_public;
-}
-
-bool TypeSystemClang::FieldIsBitfield(FieldDecl *field,
-                                      uint32_t &bitfield_bit_size) {
-  ASTContext &ast = getASTContext();
-  if (field == nullptr)
-    return false;
-
-  if (field->isBitField()) {
-    Expr *bit_width_expr = field->getBitWidth();
-    if (bit_width_expr) {
-      llvm::APSInt bit_width_apsint;
-      if (bit_width_expr->isIntegerConstantExpr(bit_width_apsint, ast)) {
-        bitfield_bit_size = bit_width_apsint.getLimitedValue(UINT32_MAX);
-        return true;
-      }
-    }
-  }
-  return false;
-}
-
-bool TypeSystemClang::RecordHasFields(const RecordDecl *record_decl) {
-  if (record_decl == nullptr)
-    return false;
-
-  if (!record_decl->field_empty())
-    return true;
-
-  // No fields, lets check this is a CXX record and check the base classes
-  const CXXRecordDecl *cxx_record_decl = dyn_cast<CXXRecordDecl>(record_decl);
-  if (cxx_record_decl) {
-    CXXRecordDecl::base_class_const_iterator base_class, base_class_end;
-    for (base_class = cxx_record_decl->bases_begin(),
-        base_class_end = cxx_record_decl->bases_end();
-         base_class != base_class_end; ++base_class) {
-      const CXXRecordDecl *base_class_decl = cast<CXXRecordDecl>(
-          base_class->getType()->getAs<RecordType>()->getDecl());
-      if (RecordHasFields(base_class_decl))
-        return true;
-    }
-  }
-  return false;
-}
-
-#pragma mark Objective-C Classes
-
-CompilerType TypeSystemClang::CreateObjCClass(llvm::StringRef name,
-                                              DeclContext *decl_ctx,
-                                              bool isForwardDecl,
-                                              bool isInternal,
-                                              ClangASTMetadata *metadata) {
-  ASTContext &ast = getASTContext();
-  assert(!name.empty());
-  if (decl_ctx == nullptr)
-    decl_ctx = ast.getTranslationUnitDecl();
-
-  ObjCInterfaceDecl *decl = ObjCInterfaceDecl::Create(
-      ast, decl_ctx, SourceLocation(), &ast.Idents.get(name), nullptr, nullptr,
-      SourceLocation(),
-      /*isForwardDecl,*/
-      isInternal);
-
-  if (decl && metadata)
-    SetMetadata(decl, *metadata);
-
-  return GetType(ast.getObjCInterfaceType(decl));
-}
-
-static inline bool BaseSpecifierIsEmpty(const CXXBaseSpecifier *b) {
-  return !TypeSystemClang::RecordHasFields(b->getType()->getAsCXXRecordDecl());
-}
-
-uint32_t
-TypeSystemClang::GetNumBaseClasses(const CXXRecordDecl *cxx_record_decl,
-                                   bool omit_empty_base_classes) {
-  uint32_t num_bases = 0;
-  if (cxx_record_decl) {
-    if (omit_empty_base_classes) {
-      CXXRecordDecl::base_class_const_iterator base_class, base_class_end;
-      for (base_class = cxx_record_decl->bases_begin(),
-          base_class_end = cxx_record_decl->bases_end();
-           base_class != base_class_end; ++base_class) {
-        // Skip empty base classes
-        if (omit_empty_base_classes) {
-          if (BaseSpecifierIsEmpty(base_class))
-            continue;
-        }
-        ++num_bases;
-      }
-    } else
-      num_bases = cxx_record_decl->getNumBases();
-  }
-  return num_bases;
-}
-
-#pragma mark Namespace Declarations
-
-NamespaceDecl *TypeSystemClang::GetUniqueNamespaceDeclaration(
-    const char *name, DeclContext *decl_ctx, bool is_inline) {
-  NamespaceDecl *namespace_decl = nullptr;
-  ASTContext &ast = getASTContext();
-  TranslationUnitDecl *translation_unit_decl = ast.getTranslationUnitDecl();
-  if (decl_ctx == nullptr)
-    decl_ctx = translation_unit_decl;
-
-  if (name) {
-    IdentifierInfo &identifier_info = ast.Idents.get(name);
-    DeclarationName decl_name(&identifier_info);
-    clang::DeclContext::lookup_result result = decl_ctx->lookup(decl_name);
-    for (NamedDecl *decl : result) {
-      namespace_decl = dyn_cast<clang::NamespaceDecl>(decl);
-      if (namespace_decl)
-        return namespace_decl;
-    }
-
-    namespace_decl =
-        NamespaceDecl::Create(ast, decl_ctx, is_inline, SourceLocation(),
-                              SourceLocation(), &identifier_info, nullptr);
-
-    decl_ctx->addDecl(namespace_decl);
-  } else {
-    if (decl_ctx == translation_unit_decl) {
-      namespace_decl = translation_unit_decl->getAnonymousNamespace();
-      if (namespace_decl)
-        return namespace_decl;
-
-      namespace_decl =
-          NamespaceDecl::Create(ast, decl_ctx, false, SourceLocation(),
-                                SourceLocation(), nullptr, nullptr);
-      translation_unit_decl->setAnonymousNamespace(namespace_decl);
-      translation_unit_decl->addDecl(namespace_decl);
-      assert(namespace_decl == translation_unit_decl->getAnonymousNamespace());
-    } else {
-      NamespaceDecl *parent_namespace_decl = cast<NamespaceDecl>(decl_ctx);
-      if (parent_namespace_decl) {
-        namespace_decl = parent_namespace_decl->getAnonymousNamespace();
-        if (namespace_decl)
-          return namespace_decl;
-        namespace_decl =
-            NamespaceDecl::Create(ast, decl_ctx, false, SourceLocation(),
-                                  SourceLocation(), nullptr, nullptr);
-        parent_namespace_decl->setAnonymousNamespace(namespace_decl);
-        parent_namespace_decl->addDecl(namespace_decl);
-        assert(namespace_decl ==
-               parent_namespace_decl->getAnonymousNamespace());
-      } else {
-        assert(false && "GetUniqueNamespaceDeclaration called with no name and "
-                        "no namespace as decl_ctx");
-      }
-    }
-  }
-#ifdef LLDB_CONFIGURATION_DEBUG
-  VerifyDecl(namespace_decl);
-#endif
-  return namespace_decl;
-}
-
-clang::BlockDecl *
-TypeSystemClang::CreateBlockDeclaration(clang::DeclContext *ctx) {
-  if (ctx != nullptr) {
-    clang::BlockDecl *decl =
-        clang::BlockDecl::Create(getASTContext(), ctx, clang::SourceLocation());
-    ctx->addDecl(decl);
-    return decl;
-  }
-  return nullptr;
-}
-
-clang::DeclContext *FindLCABetweenDecls(clang::DeclContext *left,
-                                        clang::DeclContext *right,
-                                        clang::DeclContext *root) {
-  if (root == nullptr)
-    return nullptr;
-
-  std::set<clang::DeclContext *> path_left;
-  for (clang::DeclContext *d = left; d != nullptr; d = d->getParent())
-    path_left.insert(d);
-
-  for (clang::DeclContext *d = right; d != nullptr; d = d->getParent())
-    if (path_left.find(d) != path_left.end())
-      return d;
-
-  return nullptr;
-}
-
-clang::UsingDirectiveDecl *TypeSystemClang::CreateUsingDirectiveDeclaration(
-    clang::DeclContext *decl_ctx, clang::NamespaceDecl *ns_decl) {
-  if (decl_ctx != nullptr && ns_decl != nullptr) {
-    auto *translation_unit = getASTContext().getTranslationUnitDecl();
-    clang::UsingDirectiveDecl *using_decl = clang::UsingDirectiveDecl::Create(
-        getASTContext(), decl_ctx, clang::SourceLocation(),
-        clang::SourceLocation(), clang::NestedNameSpecifierLoc(),
-        clang::SourceLocation(), ns_decl,
-        FindLCABetweenDecls(decl_ctx, ns_decl, translation_unit));
-    decl_ctx->addDecl(using_decl);
-    return using_decl;
-  }
-  return nullptr;
-}
-
-clang::UsingDecl *
-TypeSystemClang::CreateUsingDeclaration(clang::DeclContext *current_decl_ctx,
-                                        clang::NamedDecl *target) {
-  if (current_decl_ctx != nullptr && target != nullptr) {
-    clang::UsingDecl *using_decl = clang::UsingDecl::Create(
-        getASTContext(), current_decl_ctx, clang::SourceLocation(),
-        clang::NestedNameSpecifierLoc(), clang::DeclarationNameInfo(), false);
-    clang::UsingShadowDecl *shadow_decl = clang::UsingShadowDecl::Create(
-        getASTContext(), current_decl_ctx, clang::SourceLocation(), using_decl,
-        target);
-    using_decl->addShadowDecl(shadow_decl);
-    current_decl_ctx->addDecl(using_decl);
-    return using_decl;
-  }
-  return nullptr;
-}
-
-clang::VarDecl *TypeSystemClang::CreateVariableDeclaration(
-    clang::DeclContext *decl_context, const char *name, clang::QualType type) {
-  if (decl_context != nullptr) {
-    clang::VarDecl *var_decl = clang::VarDecl::Create(
-        getASTContext(), decl_context, clang::SourceLocation(),
-        clang::SourceLocation(),
-        name && name[0] ? &getASTContext().Idents.getOwn(name) : nullptr, type,
-        nullptr, clang::SC_None);
-    var_decl->setAccess(clang::AS_public);
-    decl_context->addDecl(var_decl);
-    return var_decl;
-  }
-  return nullptr;
-}
-
-lldb::opaque_compiler_type_t
-TypeSystemClang::GetOpaqueCompilerType(clang::ASTContext *ast,
-                                       lldb::BasicType basic_type) {
-  switch (basic_type) {
-  case eBasicTypeVoid:
-    return ast->VoidTy.getAsOpaquePtr();
-  case eBasicTypeChar:
-    return ast->CharTy.getAsOpaquePtr();
-  case eBasicTypeSignedChar:
-    return ast->SignedCharTy.getAsOpaquePtr();
-  case eBasicTypeUnsignedChar:
-    return ast->UnsignedCharTy.getAsOpaquePtr();
-  case eBasicTypeWChar:
-    return ast->getWCharType().getAsOpaquePtr();
-  case eBasicTypeSignedWChar:
-    return ast->getSignedWCharType().getAsOpaquePtr();
-  case eBasicTypeUnsignedWChar:
-    return ast->getUnsignedWCharType().getAsOpaquePtr();
-  case eBasicTypeChar16:
-    return ast->Char16Ty.getAsOpaquePtr();
-  case eBasicTypeChar32:
-    return ast->Char32Ty.getAsOpaquePtr();
-  case eBasicTypeShort:
-    return ast->ShortTy.getAsOpaquePtr();
-  case eBasicTypeUnsignedShort:
-    return ast->UnsignedShortTy.getAsOpaquePtr();
-  case eBasicTypeInt:
-    return ast->IntTy.getAsOpaquePtr();
-  case eBasicTypeUnsignedInt:
-    return ast->UnsignedIntTy.getAsOpaquePtr();
-  case eBasicTypeLong:
-    return ast->LongTy.getAsOpaquePtr();
-  case eBasicTypeUnsignedLong:
-    return ast->UnsignedLongTy.getAsOpaquePtr();
-  case eBasicTypeLongLong:
-    return ast->LongLongTy.getAsOpaquePtr();
-  case eBasicTypeUnsignedLongLong:
-    return ast->UnsignedLongLongTy.getAsOpaquePtr();
-  case eBasicTypeInt128:
-    return ast->Int128Ty.getAsOpaquePtr();
-  case eBasicTypeUnsignedInt128:
-    return ast->UnsignedInt128Ty.getAsOpaquePtr();
-  case eBasicTypeBool:
-    return ast->BoolTy.getAsOpaquePtr();
-  case eBasicTypeHalf:
-    return ast->HalfTy.getAsOpaquePtr();
-  case eBasicTypeFloat:
-    return ast->FloatTy.getAsOpaquePtr();
-  case eBasicTypeDouble:
-    return ast->DoubleTy.getAsOpaquePtr();
-  case eBasicTypeLongDouble:
-    return ast->LongDoubleTy.getAsOpaquePtr();
-  case eBasicTypeFloatComplex:
-    return ast->FloatComplexTy.getAsOpaquePtr();
-  case eBasicTypeDoubleComplex:
-    return ast->DoubleComplexTy.getAsOpaquePtr();
-  case eBasicTypeLongDoubleComplex:
-    return ast->LongDoubleComplexTy.getAsOpaquePtr();
-  case eBasicTypeObjCID:
-    return ast->getObjCIdType().getAsOpaquePtr();
-  case eBasicTypeObjCClass:
-    return ast->getObjCClassType().getAsOpaquePtr();
-  case eBasicTypeObjCSel:
-    return ast->getObjCSelType().getAsOpaquePtr();
-  case eBasicTypeNullPtr:
-    return ast->NullPtrTy.getAsOpaquePtr();
-  default:
-    return nullptr;
-  }
-}
-
-#pragma mark Function Types
-
-clang::DeclarationName
-TypeSystemClang::GetDeclarationName(const char *name,
-                                    const CompilerType &function_clang_type) {
-  if (!name || !name[0])
-    return clang::DeclarationName();
-
-  clang::OverloadedOperatorKind op_kind = clang::NUM_OVERLOADED_OPERATORS;
-  if (!IsOperator(name, op_kind) || op_kind == clang::NUM_OVERLOADED_OPERATORS)
-    return DeclarationName(&getASTContext().Idents.get(
-        name)); // Not operator, but a regular function.
-
-  // Check the number of operator parameters. Sometimes we have seen bad DWARF
-  // that doesn't correctly describe operators and if we try to create a method
-  // and add it to the class, clang will assert and crash, so we need to make
-  // sure things are acceptable.
-  clang::QualType method_qual_type(ClangUtil::GetQualType(function_clang_type));
-  const clang::FunctionProtoType *function_type =
-      llvm::dyn_cast<clang::FunctionProtoType>(method_qual_type.getTypePtr());
-  if (function_type == nullptr)
-    return clang::DeclarationName();
-
-  const bool is_method = false;
-  const unsigned int num_params = function_type->getNumParams();
-  if (!TypeSystemClang::CheckOverloadedOperatorKindParameterCount(
-          is_method, op_kind, num_params))
-    return clang::DeclarationName();
-
-  return getASTContext().DeclarationNames.getCXXOperatorName(op_kind);
-}
-
-FunctionDecl *TypeSystemClang::CreateFunctionDeclaration(
-    DeclContext *decl_ctx, const char *name,
-    const CompilerType &function_clang_type, int storage, bool is_inline) {
-  FunctionDecl *func_decl = nullptr;
-  ASTContext &ast = getASTContext();
-  if (decl_ctx == nullptr)
-    decl_ctx = ast.getTranslationUnitDecl();
-
-  const bool hasWrittenPrototype = true;
-  const bool isConstexprSpecified = false;
-
-  clang::DeclarationName declarationName =
-      GetDeclarationName(name, function_clang_type);
-  func_decl = FunctionDecl::Create(
-      ast, decl_ctx, SourceLocation(), SourceLocation(), declarationName,
-      ClangUtil::GetQualType(function_clang_type), nullptr,
-      (clang::StorageClass)storage, is_inline, hasWrittenPrototype,
-      isConstexprSpecified ? CSK_constexpr : CSK_unspecified);
-  if (func_decl)
-    decl_ctx->addDecl(func_decl);
-
-#ifdef LLDB_CONFIGURATION_DEBUG
-  VerifyDecl(func_decl);
-#endif
-
-  return func_decl;
-}
-
-CompilerType
-TypeSystemClang::CreateFunctionType(const CompilerType &result_type,
-                                    const CompilerType *args, unsigned num_args,
-                                    bool is_variadic, unsigned type_quals,
-                                    clang::CallingConv cc) {
-  if (!result_type || !ClangUtil::IsClangType(result_type))
-    return CompilerType(); // invalid return type
-
-  std::vector<QualType> qual_type_args;
-  if (num_args > 0 && args == nullptr)
-    return CompilerType(); // invalid argument array passed in
-
-  // Verify that all arguments are valid and the right type
-  for (unsigned i = 0; i < num_args; ++i) {
-    if (args[i]) {
-      // Make sure we have a clang type in args[i] and not a type from another
-      // language whose name might match
-      const bool is_clang_type = ClangUtil::IsClangType(args[i]);
-      lldbassert(is_clang_type);
-      if (is_clang_type)
-        qual_type_args.push_back(ClangUtil::GetQualType(args[i]));
-      else
-        return CompilerType(); //  invalid argument type (must be a clang type)
-    } else
-      return CompilerType(); // invalid argument type (empty)
-  }
-
-  // TODO: Detect calling convention in DWARF?
-  FunctionProtoType::ExtProtoInfo proto_info;
-  proto_info.ExtInfo = cc;
-  proto_info.Variadic = is_variadic;
-  proto_info.ExceptionSpec = EST_None;
-  proto_info.TypeQuals = clang::Qualifiers::fromFastMask(type_quals);
-  proto_info.RefQualifier = RQ_None;
-
-  return GetType(getASTContext().getFunctionType(
-      ClangUtil::GetQualType(result_type), qual_type_args, proto_info));
-}
-
-ParmVarDecl *TypeSystemClang::CreateParameterDeclaration(
-    clang::DeclContext *decl_ctx, const char *name,
-    const CompilerType &param_type, int storage, bool add_decl) {
-  ASTContext &ast = getASTContext();
-  auto *decl =
-      ParmVarDecl::Create(ast, decl_ctx, SourceLocation(), SourceLocation(),
-                          name && name[0] ? &ast.Idents.get(name) : nullptr,
-                          ClangUtil::GetQualType(param_type), nullptr,
-                          (clang::StorageClass)storage, nullptr);
-  if (add_decl)
-    decl_ctx->addDecl(decl);
-
-  return decl;
-}
-
-void TypeSystemClang::SetFunctionParameters(FunctionDecl *function_decl,
-                                            ParmVarDecl **params,
-                                            unsigned num_params) {
-  if (function_decl)
-    function_decl->setParams(ArrayRef<ParmVarDecl *>(params, num_params));
-}
-
-CompilerType
-TypeSystemClang::CreateBlockPointerType(const CompilerType &function_type) {
-  QualType block_type = m_ast_up->getBlockPointerType(
-      clang::QualType::getFromOpaquePtr(function_type.GetOpaqueQualType()));
-
-  return GetType(block_type);
-}
-
-#pragma mark Array Types
-
-CompilerType TypeSystemClang::CreateArrayType(const CompilerType &element_type,
-                                              size_t element_count,
-                                              bool is_vector) {
-  if (element_type.IsValid()) {
-    ASTContext &ast = getASTContext();
-
-    if (is_vector) {
-      return GetType(ast.getExtVectorType(ClangUtil::GetQualType(element_type),
-                                          element_count));
-    } else {
-
-      llvm::APInt ap_element_count(64, element_count);
-      if (element_count == 0) {
-        return GetType(ast.getIncompleteArrayType(
-            ClangUtil::GetQualType(element_type), clang::ArrayType::Normal, 0));
-      } else {
-        return GetType(ast.getConstantArrayType(
-            ClangUtil::GetQualType(element_type), ap_element_count, nullptr,
-            clang::ArrayType::Normal, 0));
-      }
-    }
-  }
-  return CompilerType();
-}
-
-CompilerType TypeSystemClang::CreateStructForIdentifier(
-    ConstString type_name,
-    const std::initializer_list<std::pair<const char *, CompilerType>>
-        &type_fields,
-    bool packed) {
-  CompilerType type;
-  if (!type_name.IsEmpty() &&
-      (type = GetTypeForIdentifier<clang::CXXRecordDecl>(type_name))
-          .IsValid()) {
-    lldbassert(0 && "Trying to create a type for an existing name");
-    return type;
-  }
-
-  type = CreateRecordType(nullptr, lldb::eAccessPublic, type_name.GetCString(),
-                          clang::TTK_Struct, lldb::eLanguageTypeC);
-  StartTagDeclarationDefinition(type);
-  for (const auto &field : type_fields)
-    AddFieldToRecordType(type, field.first, field.second, lldb::eAccessPublic,
-                         0);
-  if (packed)
-    SetIsPacked(type);
-  CompleteTagDeclarationDefinition(type);
-  return type;
-}
-
-CompilerType TypeSystemClang::GetOrCreateStructForIdentifier(
-    ConstString type_name,
-    const std::initializer_list<std::pair<const char *, CompilerType>>
-        &type_fields,
-    bool packed) {
-  CompilerType type;
-  if ((type = GetTypeForIdentifier<clang::CXXRecordDecl>(type_name)).IsValid())
-    return type;
-
-  return CreateStructForIdentifier(type_name, type_fields, packed);
-}
-
-#pragma mark Enumeration Types
-
-CompilerType
-TypeSystemClang::CreateEnumerationType(const char *name, DeclContext *decl_ctx,
-                                       const Declaration &decl,
-                                       const CompilerType &integer_clang_type,
-                                       bool is_scoped) {
-  // TODO: Do something intelligent with the Declaration object passed in
-  // like maybe filling in the SourceLocation with it...
-  ASTContext &ast = getASTContext();
-
-  // TODO: ask about these...
-  //    const bool IsFixed = false;
-
-  EnumDecl *enum_decl = EnumDecl::Create(
-      ast, decl_ctx, SourceLocation(), SourceLocation(),
-      name && name[0] ? &ast.Idents.get(name) : nullptr, nullptr,
-      is_scoped, // IsScoped
-      is_scoped, // IsScopedUsingClassTag
-      false);    // IsFixed
-
-  if (enum_decl) {
-    if (decl_ctx)
-      decl_ctx->addDecl(enum_decl);
-
-    // TODO: check if we should be setting the promotion type too?
-    enum_decl->setIntegerType(ClangUtil::GetQualType(integer_clang_type));
-
-    enum_decl->setAccess(AS_public); // TODO respect what's in the debug info
-
-    return GetType(ast.getTagDeclType(enum_decl));
-  }
-  return CompilerType();
-}
-
-CompilerType TypeSystemClang::GetIntTypeFromBitSize(size_t bit_size,
-                                                    bool is_signed) {
-  clang::ASTContext &ast = getASTContext();
-
-  if (is_signed) {
-    if (bit_size == ast.getTypeSize(ast.SignedCharTy))
-      return GetType(ast.SignedCharTy);
-
-    if (bit_size == ast.getTypeSize(ast.ShortTy))
-      return GetType(ast.ShortTy);
-
-    if (bit_size == ast.getTypeSize(ast.IntTy))
-      return GetType(ast.IntTy);
-
-    if (bit_size == ast.getTypeSize(ast.LongTy))
-      return GetType(ast.LongTy);
-
-    if (bit_size == ast.getTypeSize(ast.LongLongTy))
-      return GetType(ast.LongLongTy);
-
-    if (bit_size == ast.getTypeSize(ast.Int128Ty))
-      return GetType(ast.Int128Ty);
-  } else {
-    if (bit_size == ast.getTypeSize(ast.UnsignedCharTy))
-      return GetType(ast.UnsignedCharTy);
-
-    if (bit_size == ast.getTypeSize(ast.UnsignedShortTy))
-      return GetType(ast.UnsignedShortTy);
-
-    if (bit_size == ast.getTypeSize(ast.UnsignedIntTy))
-      return GetType(ast.UnsignedIntTy);
-
-    if (bit_size == ast.getTypeSize(ast.UnsignedLongTy))
-      return GetType(ast.UnsignedLongTy);
-
-    if (bit_size == ast.getTypeSize(ast.UnsignedLongLongTy))
-      return GetType(ast.UnsignedLongLongTy);
-
-    if (bit_size == ast.getTypeSize(ast.UnsignedInt128Ty))
-      return GetType(ast.UnsignedInt128Ty);
-  }
-  return CompilerType();
-}
-
-CompilerType TypeSystemClang::GetPointerSizedIntType(bool is_signed) {
-  return GetIntTypeFromBitSize(
-      getASTContext().getTypeSize(getASTContext().VoidPtrTy), is_signed);
-}
-
-void TypeSystemClang::DumpDeclContextHiearchy(clang::DeclContext *decl_ctx) {
-  if (decl_ctx) {
-    DumpDeclContextHiearchy(decl_ctx->getParent());
-
-    clang::NamedDecl *named_decl = llvm::dyn_cast<clang::NamedDecl>(decl_ctx);
-    if (named_decl) {
-      printf("%20s: %s\n", decl_ctx->getDeclKindName(),
-             named_decl->getDeclName().getAsString().c_str());
-    } else {
-      printf("%20s\n", decl_ctx->getDeclKindName());
-    }
-  }
-}
-
-void TypeSystemClang::DumpDeclHiearchy(clang::Decl *decl) {
-  if (decl == nullptr)
-    return;
-  DumpDeclContextHiearchy(decl->getDeclContext());
-
-  clang::RecordDecl *record_decl = llvm::dyn_cast<clang::RecordDecl>(decl);
-  if (record_decl) {
-    printf("%20s: %s%s\n", decl->getDeclKindName(),
-           record_decl->getDeclName().getAsString().c_str(),
-           record_decl->isInjectedClassName() ? " (injected class name)" : "");
-
-  } else {
-    clang::NamedDecl *named_decl = llvm::dyn_cast<clang::NamedDecl>(decl);
-    if (named_decl) {
-      printf("%20s: %s\n", decl->getDeclKindName(),
-             named_decl->getDeclName().getAsString().c_str());
-    } else {
-      printf("%20s\n", decl->getDeclKindName());
-    }
-  }
-}
-
-bool TypeSystemClang::DeclsAreEquivalent(clang::Decl *lhs_decl,
-                                         clang::Decl *rhs_decl) {
-  if (lhs_decl && rhs_decl) {
-    // Make sure the decl kinds match first
-    const clang::Decl::Kind lhs_decl_kind = lhs_decl->getKind();
-    const clang::Decl::Kind rhs_decl_kind = rhs_decl->getKind();
-
-    if (lhs_decl_kind == rhs_decl_kind) {
-      // Now check that the decl contexts kinds are all equivalent before we
-      // have to check any names of the decl contexts...
-      clang::DeclContext *lhs_decl_ctx = lhs_decl->getDeclContext();
-      clang::DeclContext *rhs_decl_ctx = rhs_decl->getDeclContext();
-      if (lhs_decl_ctx && rhs_decl_ctx) {
-        while (true) {
-          if (lhs_decl_ctx && rhs_decl_ctx) {
-            const clang::Decl::Kind lhs_decl_ctx_kind =
-                lhs_decl_ctx->getDeclKind();
-            const clang::Decl::Kind rhs_decl_ctx_kind =
-                rhs_decl_ctx->getDeclKind();
-            if (lhs_decl_ctx_kind == rhs_decl_ctx_kind) {
-              lhs_decl_ctx = lhs_decl_ctx->getParent();
-              rhs_decl_ctx = rhs_decl_ctx->getParent();
-
-              if (lhs_decl_ctx == nullptr && rhs_decl_ctx == nullptr)
-                break;
-            } else
-              return false;
-          } else
-            return false;
-        }
-
-        // Now make sure the name of the decls match
-        clang::NamedDecl *lhs_named_decl =
-            llvm::dyn_cast<clang::NamedDecl>(lhs_decl);
-        clang::NamedDecl *rhs_named_decl =
-            llvm::dyn_cast<clang::NamedDecl>(rhs_decl);
-        if (lhs_named_decl && rhs_named_decl) {
-          clang::DeclarationName lhs_decl_name = lhs_named_decl->getDeclName();
-          clang::DeclarationName rhs_decl_name = rhs_named_decl->getDeclName();
-          if (lhs_decl_name.getNameKind() == rhs_decl_name.getNameKind()) {
-            if (lhs_decl_name.getAsString() != rhs_decl_name.getAsString())
-              return false;
-          } else
-            return false;
-        } else
-          return false;
-
-        // We know that the decl context kinds all match, so now we need to
-        // make sure the names match as well
-        lhs_decl_ctx = lhs_decl->getDeclContext();
-        rhs_decl_ctx = rhs_decl->getDeclContext();
-        while (true) {
-          switch (lhs_decl_ctx->getDeclKind()) {
-          case clang::Decl::TranslationUnit:
-            // We don't care about the translation unit names
-            return true;
-          default: {
-            clang::NamedDecl *lhs_named_decl =
-                llvm::dyn_cast<clang::NamedDecl>(lhs_decl_ctx);
-            clang::NamedDecl *rhs_named_decl =
-                llvm::dyn_cast<clang::NamedDecl>(rhs_decl_ctx);
-            if (lhs_named_decl && rhs_named_decl) {
-              clang::DeclarationName lhs_decl_name =
-                  lhs_named_decl->getDeclName();
-              clang::DeclarationName rhs_decl_name =
-                  rhs_named_decl->getDeclName();
-              if (lhs_decl_name.getNameKind() == rhs_decl_name.getNameKind()) {
-                if (lhs_decl_name.getAsString() != rhs_decl_name.getAsString())
-                  return false;
-              } else
-                return false;
-            } else
-              return false;
-          } break;
-          }
-          lhs_decl_ctx = lhs_decl_ctx->getParent();
-          rhs_decl_ctx = rhs_decl_ctx->getParent();
-        }
-      }
-    }
-  }
-  return false;
-}
-bool TypeSystemClang::GetCompleteDecl(clang::ASTContext *ast,
-                                      clang::Decl *decl) {
-  if (!decl)
-    return false;
-
-  ExternalASTSource *ast_source = ast->getExternalSource();
-
-  if (!ast_source)
-    return false;
-
-  if (clang::TagDecl *tag_decl = llvm::dyn_cast<clang::TagDecl>(decl)) {
-    if (tag_decl->isCompleteDefinition())
-      return true;
-
-    if (!tag_decl->hasExternalLexicalStorage())
-      return false;
-
-    ast_source->CompleteType(tag_decl);
-
-    return !tag_decl->getTypeForDecl()->isIncompleteType();
-  } else if (clang::ObjCInterfaceDecl *objc_interface_decl =
-                 llvm::dyn_cast<clang::ObjCInterfaceDecl>(decl)) {
-    if (objc_interface_decl->getDefinition())
-      return true;
-
-    if (!objc_interface_decl->hasExternalLexicalStorage())
-      return false;
-
-    ast_source->CompleteType(objc_interface_decl);
-
-    return !objc_interface_decl->getTypeForDecl()->isIncompleteType();
-  } else {
-    return false;
-  }
-}
-
-void TypeSystemClang::SetMetadataAsUserID(const clang::Decl *decl,
-                                          user_id_t user_id) {
-  ClangASTMetadata meta_data;
-  meta_data.SetUserID(user_id);
-  SetMetadata(decl, meta_data);
-}
-
-void TypeSystemClang::SetMetadataAsUserID(const clang::Type *type,
-                                          user_id_t user_id) {
-  ClangASTMetadata meta_data;
-  meta_data.SetUserID(user_id);
-  SetMetadata(type, meta_data);
-}
-
-void TypeSystemClang::SetMetadata(const clang::Decl *object,
-                                  ClangASTMetadata &metadata) {
-  m_decl_metadata[object] = metadata;
-}
-
-void TypeSystemClang::SetMetadata(const clang::Type *object,
-                                  ClangASTMetadata &metadata) {
-  m_type_metadata[object] = metadata;
-}
-
-ClangASTMetadata *TypeSystemClang::GetMetadata(const clang::Decl *object) {
-  auto It = m_decl_metadata.find(object);
-  if (It != m_decl_metadata.end())
-    return &It->second;
-  return nullptr;
-}
-
-ClangASTMetadata *TypeSystemClang::GetMetadata(const clang::Type *object) {
-  auto It = m_type_metadata.find(object);
-  if (It != m_type_metadata.end())
-    return &It->second;
-  return nullptr;
-}
-
-bool TypeSystemClang::SetTagTypeKind(clang::QualType tag_qual_type,
-                                     int kind) const {
-  const clang::Type *clang_type = tag_qual_type.getTypePtr();
-  if (clang_type) {
-    const clang::TagType *tag_type = llvm::dyn_cast<clang::TagType>(clang_type);
-    if (tag_type) {
-      clang::TagDecl *tag_decl =
-          llvm::dyn_cast<clang::TagDecl>(tag_type->getDecl());
-      if (tag_decl) {
-        tag_decl->setTagKind((clang::TagDecl::TagKind)kind);
-        return true;
-      }
-    }
-  }
-  return false;
-}
-
-bool TypeSystemClang::SetDefaultAccessForRecordFields(
-    clang::RecordDecl *record_decl, int default_accessibility,
-    int *assigned_accessibilities, size_t num_assigned_accessibilities) {
-  if (record_decl) {
-    uint32_t field_idx;
-    clang::RecordDecl::field_iterator field, field_end;
-    for (field = record_decl->field_begin(),
-        field_end = record_decl->field_end(), field_idx = 0;
-         field != field_end; ++field, ++field_idx) {
-      // If no accessibility was assigned, assign the correct one
-      if (field_idx < num_assigned_accessibilities &&
-          assigned_accessibilities[field_idx] == clang::AS_none)
-        field->setAccess((clang::AccessSpecifier)default_accessibility);
-    }
-    return true;
-  }
-  return false;
-}
-
-clang::DeclContext *
-TypeSystemClang::GetDeclContextForType(const CompilerType &type) {
-  return GetDeclContextForType(ClangUtil::GetQualType(type));
-}
-
-/// Aggressively desugar the provided type, skipping past various kinds of
-/// syntactic sugar and other constructs one typically wants to ignore.
-/// The \p mask argument allows one to skip certain kinds of simplifications,
-/// when one wishes to handle a certain kind of type directly.
-static QualType
-RemoveWrappingTypes(QualType type, ArrayRef<clang::Type::TypeClass> mask = {}) {
-  while (true) {
-    if (find(mask, type->getTypeClass()) != mask.end())
-      return type;
-    switch (type->getTypeClass()) {
-    // This is not fully correct as _Atomic is more than sugar, but it is
-    // sufficient for the purposes we care about.
-    case clang::Type::Atomic:
-      type = cast<clang::AtomicType>(type)->getValueType();
-      break;
-    case clang::Type::Auto:
-    case clang::Type::Decltype:
-    case clang::Type::Elaborated:
-    case clang::Type::Paren:
-    case clang::Type::Typedef:
-    case clang::Type::TypeOf:
-    case clang::Type::TypeOfExpr:
-      type = type->getLocallyUnqualifiedSingleStepDesugaredType();
-      break;
-    default:
-      return type;
-    }
-  }
-}
-
-clang::DeclContext *
-TypeSystemClang::GetDeclContextForType(clang::QualType type) {
-  if (type.isNull())
-    return nullptr;
-
-  clang::QualType qual_type = RemoveWrappingTypes(type.getCanonicalType());
-  const clang::Type::TypeClass type_class = qual_type->getTypeClass();
-  switch (type_class) {
-  case clang::Type::ObjCInterface:
-    return llvm::cast<clang::ObjCObjectType>(qual_type.getTypePtr())
-        ->getInterface();
-  case clang::Type::ObjCObjectPointer:
-    return GetDeclContextForType(
-        llvm::cast<clang::ObjCObjectPointerType>(qual_type.getTypePtr())
-            ->getPointeeType());
-  case clang::Type::Record:
-    return llvm::cast<clang::RecordType>(qual_type)->getDecl();
-  case clang::Type::Enum:
-    return llvm::cast<clang::EnumType>(qual_type)->getDecl();
-  default:
-    break;
-  }
-  // No DeclContext in this type...
-  return nullptr;
-}
-
-static bool GetCompleteQualType(clang::ASTContext *ast,
-                                clang::QualType qual_type,
-                                bool allow_completion = true) {
-  qual_type = RemoveWrappingTypes(qual_type);
-  const clang::Type::TypeClass type_class = qual_type->getTypeClass();
-  switch (type_class) {
-  case clang::Type::ConstantArray:
-  case clang::Type::IncompleteArray:
-  case clang::Type::VariableArray: {
-    const clang::ArrayType *array_type =
-        llvm::dyn_cast<clang::ArrayType>(qual_type.getTypePtr());
-
-    if (array_type)
-      return GetCompleteQualType(ast, array_type->getElementType(),
-                                 allow_completion);
-  } break;
-  case clang::Type::Record: {
-    clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl();
-    if (cxx_record_decl) {
-      if (cxx_record_decl->hasExternalLexicalStorage()) {
-        const bool is_complete = cxx_record_decl->isCompleteDefinition();
-        const bool fields_loaded =
-            cxx_record_decl->hasLoadedFieldsFromExternalStorage();
-        if (is_complete && fields_loaded)
-          return true;
-
-        if (!allow_completion)
-          return false;
-
-        // Call the field_begin() accessor to for it to use the external source
-        // to load the fields...
-        clang::ExternalASTSource *external_ast_source =
-            ast->getExternalSource();
-        if (external_ast_source) {
-          external_ast_source->CompleteType(cxx_record_decl);
-          if (cxx_record_decl->isCompleteDefinition()) {
-            cxx_record_decl->field_begin();
-            cxx_record_decl->setHasLoadedFieldsFromExternalStorage(true);
-          }
-        }
-      }
-    }
-    const clang::TagType *tag_type =
-        llvm::cast<clang::TagType>(qual_type.getTypePtr());
-    return !tag_type->isIncompleteType();
-  } break;
-
-  case clang::Type::Enum: {
-    const clang::TagType *tag_type =
-        llvm::dyn_cast<clang::TagType>(qual_type.getTypePtr());
-    if (tag_type) {
-      clang::TagDecl *tag_decl = tag_type->getDecl();
-      if (tag_decl) {
-        if (tag_decl->getDefinition())
-          return true;
-
-        if (!allow_completion)
-          return false;
-
-        if (tag_decl->hasExternalLexicalStorage()) {
-          if (ast) {
-            clang::ExternalASTSource *external_ast_source =
-                ast->getExternalSource();
-            if (external_ast_source) {
-              external_ast_source->CompleteType(tag_decl);
-              return !tag_type->isIncompleteType();
-            }
-          }
-        }
-        return false;
-      }
-    }
-
-  } break;
-  case clang::Type::ObjCObject:
-  case clang::Type::ObjCInterface: {
-    const clang::ObjCObjectType *objc_class_type =
-        llvm::dyn_cast<clang::ObjCObjectType>(qual_type);
-    if (objc_class_type) {
-      clang::ObjCInterfaceDecl *class_interface_decl =
-          objc_class_type->getInterface();
-      // We currently can't complete objective C types through the newly added
-      // ASTContext because it only supports TagDecl objects right now...
-      if (class_interface_decl) {
-        if (class_interface_decl->getDefinition())
-          return true;
-
-        if (!allow_completion)
-          return false;
-
-        if (class_interface_decl->hasExternalLexicalStorage()) {
-          if (ast) {
-            clang::ExternalASTSource *external_ast_source =
-                ast->getExternalSource();
-            if (external_ast_source) {
-              external_ast_source->CompleteType(class_interface_decl);
-              return !objc_class_type->isIncompleteType();
-            }
-          }
-        }
-        return false;
-      }
-    }
-  } break;
-
-  case clang::Type::Attributed:
-    return GetCompleteQualType(
-        ast, llvm::cast<clang::AttributedType>(qual_type)->getModifiedType(),
-        allow_completion);
-
-  default:
-    break;
-  }
-
-  return true;
-}
-
-static clang::ObjCIvarDecl::AccessControl
-ConvertAccessTypeToObjCIvarAccessControl(AccessType access) {
-  switch (access) {
-  case eAccessNone:
-    return clang::ObjCIvarDecl::None;
-  case eAccessPublic:
-    return clang::ObjCIvarDecl::Public;
-  case eAccessPrivate:
-    return clang::ObjCIvarDecl::Private;
-  case eAccessProtected:
-    return clang::ObjCIvarDecl::Protected;
-  case eAccessPackage:
-    return clang::ObjCIvarDecl::Package;
-  }
-  return clang::ObjCIvarDecl::None;
-}
-
-// Tests
-
-bool TypeSystemClang::IsAggregateType(lldb::opaque_compiler_type_t type) {
-  clang::QualType qual_type(RemoveWrappingTypes(GetCanonicalQualType(type)));
-
-  const clang::Type::TypeClass type_class = qual_type->getTypeClass();
-  switch (type_class) {
-  case clang::Type::IncompleteArray:
-  case clang::Type::VariableArray:
-  case clang::Type::ConstantArray:
-  case clang::Type::ExtVector:
-  case clang::Type::Vector:
-  case clang::Type::Record:
-  case clang::Type::ObjCObject:
-  case clang::Type::ObjCInterface:
-    return true;
-  default:
-    break;
-  }
-  // The clang type does have a value
-  return false;
-}
-
-bool TypeSystemClang::IsAnonymousType(lldb::opaque_compiler_type_t type) {
-  clang::QualType qual_type(RemoveWrappingTypes(GetCanonicalQualType(type)));
-
-  const clang::Type::TypeClass type_class = qual_type->getTypeClass();
-  switch (type_class) {
-  case clang::Type::Record: {
-    if (const clang::RecordType *record_type =
-            llvm::dyn_cast_or_null<clang::RecordType>(
-                qual_type.getTypePtrOrNull())) {
-      if (const clang::RecordDecl *record_decl = record_type->getDecl()) {
-        return record_decl->isAnonymousStructOrUnion();
-      }
-    }
-    break;
-  }
-  default:
-    break;
-  }
-  // The clang type does have a value
-  return false;
-}
-
-bool TypeSystemClang::IsArrayType(lldb::opaque_compiler_type_t type,
-                                  CompilerType *element_type_ptr,
-                                  uint64_t *size, bool *is_incomplete) {
-  clang::QualType qual_type(RemoveWrappingTypes(GetCanonicalQualType(type)));
-
-  const clang::Type::TypeClass type_class = qual_type->getTypeClass();
-  switch (type_class) {
-  default:
-    break;
-
-  case clang::Type::ConstantArray:
-    if (element_type_ptr)
-      element_type_ptr->SetCompilerType(
-          this, llvm::cast<clang::ConstantArrayType>(qual_type)
-                    ->getElementType()
-                    .getAsOpaquePtr());
-    if (size)
-      *size = llvm::cast<clang::ConstantArrayType>(qual_type)
-                  ->getSize()
-                  .getLimitedValue(ULLONG_MAX);
-    if (is_incomplete)
-      *is_incomplete = false;
-    return true;
-
-  case clang::Type::IncompleteArray:
-    if (element_type_ptr)
-      element_type_ptr->SetCompilerType(
-          this, llvm::cast<clang::IncompleteArrayType>(qual_type)
-                    ->getElementType()
-                    .getAsOpaquePtr());
-    if (size)
-      *size = 0;
-    if (is_incomplete)
-      *is_incomplete = true;
-    return true;
-
-  case clang::Type::VariableArray:
-    if (element_type_ptr)
-      element_type_ptr->SetCompilerType(
-          this, llvm::cast<clang::VariableArrayType>(qual_type)
-                    ->getElementType()
-                    .getAsOpaquePtr());
-    if (size)
-      *size = 0;
-    if (is_incomplete)
-      *is_incomplete = false;
-    return true;
-
-  case clang::Type::DependentSizedArray:
-    if (element_type_ptr)
-      element_type_ptr->SetCompilerType(
-          this, llvm::cast<clang::DependentSizedArrayType>(qual_type)
-                    ->getElementType()
-                    .getAsOpaquePtr());
-    if (size)
-      *size = 0;
-    if (is_incomplete)
-      *is_incomplete = false;
-    return true;
-  }
-  if (element_type_ptr)
-    element_type_ptr->Clear();
-  if (size)
-    *size = 0;
-  if (is_incomplete)
-    *is_incomplete = false;
-  return false;
-}
-
-bool TypeSystemClang::IsVectorType(lldb::opaque_compiler_type_t type,
-                                   CompilerType *element_type, uint64_t *size) {
-  clang::QualType qual_type(GetCanonicalQualType(type));
-
-  const clang::Type::TypeClass type_class = qual_type->getTypeClass();
-  switch (type_class) {
-  case clang::Type::Vector: {
-    const clang::VectorType *vector_type =
-        qual_type->getAs<clang::VectorType>();
-    if (vector_type) {
-      if (size)
-        *size = vector_type->getNumElements();
-      if (element_type)
-        *element_type = GetType(vector_type->getElementType());
-    }
-    return true;
-  } break;
-  case clang::Type::ExtVector: {
-    const clang::ExtVectorType *ext_vector_type =
-        qual_type->getAs<clang::ExtVectorType>();
-    if (ext_vector_type) {
-      if (size)
-        *size = ext_vector_type->getNumElements();
-      if (element_type)
-        *element_type =
-            CompilerType(this, ext_vector_type->getElementType().getAsOpaquePtr());
-    }
-    return true;
-  }
-  default:
-    break;
-  }
-  return false;
-}
-
-bool TypeSystemClang::IsRuntimeGeneratedType(
-    lldb::opaque_compiler_type_t type) {
-  clang::DeclContext *decl_ctx = GetDeclContextForType(GetQualType(type));
-  if (!decl_ctx)
-    return false;
-
-  if (!llvm::isa<clang::ObjCInterfaceDecl>(decl_ctx))
-    return false;
-
-  clang::ObjCInterfaceDecl *result_iface_decl =
-      llvm::dyn_cast<clang::ObjCInterfaceDecl>(decl_ctx);
-
-  ClangASTMetadata *ast_metadata = GetMetadata(result_iface_decl);
-  if (!ast_metadata)
-    return false;
-  return (ast_metadata->GetISAPtr() != 0);
-}
-
-bool TypeSystemClang::IsCharType(lldb::opaque_compiler_type_t type) {
-  return GetQualType(type).getUnqualifiedType()->isCharType();
-}
-
-bool TypeSystemClang::IsCompleteType(lldb::opaque_compiler_type_t type) {
-  const bool allow_completion = false;
-  return GetCompleteQualType(&getASTContext(), GetQualType(type),
-                             allow_completion);
-}
-
-bool TypeSystemClang::IsConst(lldb::opaque_compiler_type_t type) {
-  return GetQualType(type).isConstQualified();
-}
-
-bool TypeSystemClang::IsCStringType(lldb::opaque_compiler_type_t type,
-                                    uint32_t &length) {
-  CompilerType pointee_or_element_clang_type;
-  length = 0;
-  Flags type_flags(GetTypeInfo(type, &pointee_or_element_clang_type));
-
-  if (!pointee_or_element_clang_type.IsValid())
-    return false;
-
-  if (type_flags.AnySet(eTypeIsArray | eTypeIsPointer)) {
-    if (pointee_or_element_clang_type.IsCharType()) {
-      if (type_flags.Test(eTypeIsArray)) {
-        // We know the size of the array and it could be a C string since it is
-        // an array of characters
-        length = llvm::cast<clang::ConstantArrayType>(
-                     GetCanonicalQualType(type).getTypePtr())
-                     ->getSize()
-                     .getLimitedValue();
-      }
-      return true;
-    }
-  }
-  return false;
-}
-
-bool TypeSystemClang::IsFunctionType(lldb::opaque_compiler_type_t type,
-                                     bool *is_variadic_ptr) {
-  if (type) {
-    clang::QualType qual_type = RemoveWrappingTypes(GetCanonicalQualType(type));
-
-    if (qual_type->isFunctionType()) {
-      if (is_variadic_ptr) {
-        const clang::FunctionProtoType *function_proto_type =
-            llvm::dyn_cast<clang::FunctionProtoType>(qual_type.getTypePtr());
-        if (function_proto_type)
-          *is_variadic_ptr = function_proto_type->isVariadic();
-        else
-          *is_variadic_ptr = false;
-      }
-      return true;
-    }
-
-    const clang::Type::TypeClass type_class = qual_type->getTypeClass();
-    switch (type_class) {
-    default:
-      break;
-    case clang::Type::LValueReference:
-    case clang::Type::RValueReference: {
-      const clang::ReferenceType *reference_type =
-          llvm::cast<clang::ReferenceType>(qual_type.getTypePtr());
-      if (reference_type)
-        return IsFunctionType(reference_type->getPointeeType().getAsOpaquePtr(),
-                              nullptr);
-    } break;
-    }
-  }
-  return false;
-}
-
-// Used to detect "Homogeneous Floating-point Aggregates"
-uint32_t
-TypeSystemClang::IsHomogeneousAggregate(lldb::opaque_compiler_type_t type,
-                                        CompilerType *base_type_ptr) {
-  if (!type)
-    return 0;
-
-  clang::QualType qual_type(RemoveWrappingTypes(GetCanonicalQualType(type)));
-  const clang::Type::TypeClass type_class = qual_type->getTypeClass();
-  switch (type_class) {
-  case clang::Type::Record:
-    if (GetCompleteType(type)) {
-      const clang::CXXRecordDecl *cxx_record_decl =
-          qual_type->getAsCXXRecordDecl();
-      if (cxx_record_decl) {
-        if (cxx_record_decl->getNumBases() || cxx_record_decl->isDynamicClass())
-          return 0;
-      }
-      const clang::RecordType *record_type =
-          llvm::cast<clang::RecordType>(qual_type.getTypePtr());
-      if (record_type) {
-        const clang::RecordDecl *record_decl = record_type->getDecl();
-        if (record_decl) {
-          // We are looking for a structure that contains only floating point
-          // types
-          clang::RecordDecl::field_iterator field_pos,
-              field_end = record_decl->field_end();
-          uint32_t num_fields = 0;
-          bool is_hva = false;
-          bool is_hfa = false;
-          clang::QualType base_qual_type;
-          uint64_t base_bitwidth = 0;
-          for (field_pos = record_decl->field_begin(); field_pos != field_end;
-               ++field_pos) {
-            clang::QualType field_qual_type = field_pos->getType();
-            uint64_t field_bitwidth = getASTContext().getTypeSize(qual_type);
-            if (field_qual_type->isFloatingType()) {
-              if (field_qual_type->isComplexType())
-                return 0;
-              else {
-                if (num_fields == 0)
-                  base_qual_type = field_qual_type;
-                else {
-                  if (is_hva)
-                    return 0;
-                  is_hfa = true;
-                  if (field_qual_type.getTypePtr() !=
-                      base_qual_type.getTypePtr())
-                    return 0;
-                }
-              }
-            } else if (field_qual_type->isVectorType() ||
-                       field_qual_type->isExtVectorType()) {
-              if (num_fields == 0) {
-                base_qual_type = field_qual_type;
-                base_bitwidth = field_bitwidth;
-              } else {
-                if (is_hfa)
-                  return 0;
-                is_hva = true;
-                if (base_bitwidth != field_bitwidth)
-                  return 0;
-                if (field_qual_type.getTypePtr() != base_qual_type.getTypePtr())
-                  return 0;
-              }
-            } else
-              return 0;
-            ++num_fields;
-          }
-          if (base_type_ptr)
-            *base_type_ptr = CompilerType(this, base_qual_type.getAsOpaquePtr());
-          return num_fields;
-        }
-      }
-    }
-    break;
-
-  default:
-    break;
-  }
-  return 0;
-}
-
-size_t TypeSystemClang::GetNumberOfFunctionArguments(
-    lldb::opaque_compiler_type_t type) {
-  if (type) {
-    clang::QualType qual_type(GetCanonicalQualType(type));
-    const clang::FunctionProtoType *func =
-        llvm::dyn_cast<clang::FunctionProtoType>(qual_type.getTypePtr());
-    if (func)
-      return func->getNumParams();
-  }
-  return 0;
-}
-
-CompilerType
-TypeSystemClang::GetFunctionArgumentAtIndex(lldb::opaque_compiler_type_t type,
-                                            const size_t index) {
-  if (type) {
-    clang::QualType qual_type(GetQualType(type));
-    const clang::FunctionProtoType *func =
-        llvm::dyn_cast<clang::FunctionProtoType>(qual_type.getTypePtr());
-    if (func) {
-      if (index < func->getNumParams())
-        return CompilerType(this, func->getParamType(index).getAsOpaquePtr());
-    }
-  }
-  return CompilerType();
-}
-
-bool TypeSystemClang::IsFunctionPointerType(lldb::opaque_compiler_type_t type) {
-  if (type) {
-    clang::QualType qual_type = RemoveWrappingTypes(GetCanonicalQualType(type));
-
-    if (qual_type->isFunctionPointerType())
-      return true;
-
-    const clang::Type::TypeClass type_class = qual_type->getTypeClass();
-    switch (type_class) {
-    default:
-      break;
-
-    case clang::Type::LValueReference:
-    case clang::Type::RValueReference: {
-      const clang::ReferenceType *reference_type =
-          llvm::cast<clang::ReferenceType>(qual_type.getTypePtr());
-      if (reference_type)
-        return IsFunctionPointerType(
-            reference_type->getPointeeType().getAsOpaquePtr());
-    } break;
-    }
-  }
-  return false;
-}
-
-bool TypeSystemClang::IsBlockPointerType(
-    lldb::opaque_compiler_type_t type,
-    CompilerType *function_pointer_type_ptr) {
-  if (type) {
-    clang::QualType qual_type = RemoveWrappingTypes(GetCanonicalQualType(type));
-
-    if (qual_type->isBlockPointerType()) {
-      if (function_pointer_type_ptr) {
-        const clang::BlockPointerType *block_pointer_type =
-            qual_type->getAs<clang::BlockPointerType>();
-        QualType pointee_type = block_pointer_type->getPointeeType();
-        QualType function_pointer_type = m_ast_up->getPointerType(pointee_type);
-        *function_pointer_type_ptr =
-            CompilerType(this, function_pointer_type.getAsOpaquePtr());
-      }
-      return true;
-    }
-
-    const clang::Type::TypeClass type_class = qual_type->getTypeClass();
-    switch (type_class) {
-    default:
-      break;
-
-    case clang::Type::LValueReference:
-    case clang::Type::RValueReference: {
-      const clang::ReferenceType *reference_type =
-          llvm::cast<clang::ReferenceType>(qual_type.getTypePtr());
-      if (reference_type)
-        return IsBlockPointerType(
-            reference_type->getPointeeType().getAsOpaquePtr(),
-            function_pointer_type_ptr);
-    } break;
-    }
-  }
-  return false;
-}
-
-bool TypeSystemClang::IsIntegerType(lldb::opaque_compiler_type_t type,
-                                    bool &is_signed) {
-  if (!type)
-    return false;
-
-  clang::QualType qual_type(GetCanonicalQualType(type));
-  const clang::BuiltinType *builtin_type =
-      llvm::dyn_cast<clang::BuiltinType>(qual_type->getCanonicalTypeInternal());
-
-  if (builtin_type) {
-    if (builtin_type->isInteger()) {
-      is_signed = builtin_type->isSignedInteger();
-      return true;
-    }
-  }
-
-  return false;
-}
-
-bool TypeSystemClang::IsEnumerationType(lldb::opaque_compiler_type_t type,
-                                        bool &is_signed) {
-  if (type) {
-    const clang::EnumType *enum_type = llvm::dyn_cast<clang::EnumType>(
-        GetCanonicalQualType(type)->getCanonicalTypeInternal());
-
-    if (enum_type) {
-      IsIntegerType(enum_type->getDecl()->getIntegerType().getAsOpaquePtr(),
-                    is_signed);
-      return true;
-    }
-  }
-
-  return false;
-}
-
-bool TypeSystemClang::IsPointerType(lldb::opaque_compiler_type_t type,
-                                    CompilerType *pointee_type) {
-  if (type) {
-    clang::QualType qual_type = RemoveWrappingTypes(GetCanonicalQualType(type));
-    const clang::Type::TypeClass type_class = qual_type->getTypeClass();
-    switch (type_class) {
-    case clang::Type::Builtin:
-      switch (llvm::cast<clang::BuiltinType>(qual_type)->getKind()) {
-      default:
-        break;
-      case clang::BuiltinType::ObjCId:
-      case clang::BuiltinType::ObjCClass:
-        return true;
-      }
-      return false;
-    case clang::Type::ObjCObjectPointer:
-      if (pointee_type)
-        pointee_type->SetCompilerType(
-            this, llvm::cast<clang::ObjCObjectPointerType>(qual_type)
-                      ->getPointeeType()
-                      .getAsOpaquePtr());
-      return true;
-    case clang::Type::BlockPointer:
-      if (pointee_type)
-        pointee_type->SetCompilerType(
-            this, llvm::cast<clang::BlockPointerType>(qual_type)
-                      ->getPointeeType()
-                      .getAsOpaquePtr());
-      return true;
-    case clang::Type::Pointer:
-      if (pointee_type)
-        pointee_type->SetCompilerType(this,
-                                      llvm::cast<clang::PointerType>(qual_type)
-                                          ->getPointeeType()
-                                          .getAsOpaquePtr());
-      return true;
-    case clang::Type::MemberPointer:
-      if (pointee_type)
-        pointee_type->SetCompilerType(
-            this, llvm::cast<clang::MemberPointerType>(qual_type)
-                      ->getPointeeType()
-                      .getAsOpaquePtr());
-      return true;
-    default:
-      break;
-    }
-  }
-  if (pointee_type)
-    pointee_type->Clear();
-  return false;
-}
-
-bool TypeSystemClang::IsPointerOrReferenceType(
-    lldb::opaque_compiler_type_t type, CompilerType *pointee_type) {
-  if (type) {
-    clang::QualType qual_type = RemoveWrappingTypes(GetCanonicalQualType(type));
-    const clang::Type::TypeClass type_class = qual_type->getTypeClass();
-    switch (type_class) {
-    case clang::Type::Builtin:
-      switch (llvm::cast<clang::BuiltinType>(qual_type)->getKind()) {
-      default:
-        break;
-      case clang::BuiltinType::ObjCId:
-      case clang::BuiltinType::ObjCClass:
-        return true;
-      }
-      return false;
-    case clang::Type::ObjCObjectPointer:
-      if (pointee_type)
-        pointee_type->SetCompilerType(
-            this, llvm::cast<clang::ObjCObjectPointerType>(qual_type)
-                                 ->getPointeeType().getAsOpaquePtr());
-      return true;
-    case clang::Type::BlockPointer:
-      if (pointee_type)
-        pointee_type->SetCompilerType(
-            this, llvm::cast<clang::BlockPointerType>(qual_type)
-                      ->getPointeeType()
-                      .getAsOpaquePtr());
-      return true;
-    case clang::Type::Pointer:
-      if (pointee_type)
-        pointee_type->SetCompilerType(this,
-                                      llvm::cast<clang::PointerType>(qual_type)
-                                          ->getPointeeType()
-                                          .getAsOpaquePtr());
-      return true;
-    case clang::Type::MemberPointer:
-      if (pointee_type)
-        pointee_type->SetCompilerType(
-            this, llvm::cast<clang::MemberPointerType>(qual_type)
-                      ->getPointeeType()
-                      .getAsOpaquePtr());
-      return true;
-    case clang::Type::LValueReference:
-      if (pointee_type)
-        pointee_type->SetCompilerType(
-            this, llvm::cast<clang::LValueReferenceType>(qual_type)
-                      ->desugar()
-                      .getAsOpaquePtr());
-      return true;
-    case clang::Type::RValueReference:
-      if (pointee_type)
-        pointee_type->SetCompilerType(
-            this, llvm::cast<clang::RValueReferenceType>(qual_type)
-                      ->desugar()
-                      .getAsOpaquePtr());
-      return true;
-    default:
-      break;
-    }
-  }
-  if (pointee_type)
-    pointee_type->Clear();
-  return false;
-}
-
-bool TypeSystemClang::IsReferenceType(lldb::opaque_compiler_type_t type,
-                                      CompilerType *pointee_type,
-                                      bool *is_rvalue) {
-  if (type) {
-    clang::QualType qual_type = RemoveWrappingTypes(GetCanonicalQualType(type));
-    const clang::Type::TypeClass type_class = qual_type->getTypeClass();
-
-    switch (type_class) {
-    case clang::Type::LValueReference:
-      if (pointee_type)
-        pointee_type->SetCompilerType(
-            this, llvm::cast<clang::LValueReferenceType>(qual_type)
-                      ->desugar()
-                      .getAsOpaquePtr());
-      if (is_rvalue)
-        *is_rvalue = false;
-      return true;
-    case clang::Type::RValueReference:
-      if (pointee_type)
-        pointee_type->SetCompilerType(
-            this, llvm::cast<clang::RValueReferenceType>(qual_type)
-                      ->desugar()
-                      .getAsOpaquePtr());
-      if (is_rvalue)
-        *is_rvalue = true;
-      return true;
-
-    default:
-      break;
-    }
-  }
-  if (pointee_type)
-    pointee_type->Clear();
-  return false;
-}
-
-bool TypeSystemClang::IsFloatingPointType(lldb::opaque_compiler_type_t type,
-                                          uint32_t &count, bool &is_complex) {
-  if (type) {
-    clang::QualType qual_type(GetCanonicalQualType(type));
-
-    if (const clang::BuiltinType *BT = llvm::dyn_cast<clang::BuiltinType>(
-            qual_type->getCanonicalTypeInternal())) {
-      clang::BuiltinType::Kind kind = BT->getKind();
-      if (kind >= clang::BuiltinType::Float &&
-          kind <= clang::BuiltinType::LongDouble) {
-        count = 1;
-        is_complex = false;
-        return true;
-      }
-    } else if (const clang::ComplexType *CT =
-                   llvm::dyn_cast<clang::ComplexType>(
-                       qual_type->getCanonicalTypeInternal())) {
-      if (IsFloatingPointType(CT->getElementType().getAsOpaquePtr(), count,
-                              is_complex)) {
-        count = 2;
-        is_complex = true;
-        return true;
-      }
-    } else if (const clang::VectorType *VT = llvm::dyn_cast<clang::VectorType>(
-                   qual_type->getCanonicalTypeInternal())) {
-      if (IsFloatingPointType(VT->getElementType().getAsOpaquePtr(), count,
-                              is_complex)) {
-        count = VT->getNumElements();
-        is_complex = false;
-        return true;
-      }
-    }
-  }
-  count = 0;
-  is_complex = false;
-  return false;
-}
-
-bool TypeSystemClang::IsDefined(lldb::opaque_compiler_type_t type) {
-  if (!type)
-    return false;
-
-  clang::QualType qual_type(GetQualType(type));
-  const clang::TagType *tag_type =
-      llvm::dyn_cast<clang::TagType>(qual_type.getTypePtr());
-  if (tag_type) {
-    clang::TagDecl *tag_decl = tag_type->getDecl();
-    if (tag_decl)
-      return tag_decl->isCompleteDefinition();
-    return false;
-  } else {
-    const clang::ObjCObjectType *objc_class_type =
-        llvm::dyn_cast<clang::ObjCObjectType>(qual_type);
-    if (objc_class_type) {
-      clang::ObjCInterfaceDecl *class_interface_decl =
-          objc_class_type->getInterface();
-      if (class_interface_decl)
-        return class_interface_decl->getDefinition() != nullptr;
-      return false;
-    }
-  }
-  return true;
-}
-
-bool TypeSystemClang::IsObjCClassType(const CompilerType &type) {
-  if (ClangUtil::IsClangType(type)) {
-    clang::QualType qual_type(ClangUtil::GetCanonicalQualType(type));
-
-    const clang::ObjCObjectPointerType *obj_pointer_type =
-        llvm::dyn_cast<clang::ObjCObjectPointerType>(qual_type);
-
-    if (obj_pointer_type)
-      return obj_pointer_type->isObjCClassType();
-  }
-  return false;
-}
-
-bool TypeSystemClang::IsObjCObjectOrInterfaceType(const CompilerType &type) {
-  if (ClangUtil::IsClangType(type))
-    return ClangUtil::GetCanonicalQualType(type)->isObjCObjectOrInterfaceType();
-  return false;
-}
-
-bool TypeSystemClang::IsClassType(lldb::opaque_compiler_type_t type) {
-  if (!type)
-    return false;
-  clang::QualType qual_type(GetCanonicalQualType(type));
-  const clang::Type::TypeClass type_class = qual_type->getTypeClass();
-  return (type_class == clang::Type::Record);
-}
-
-bool TypeSystemClang::IsEnumType(lldb::opaque_compiler_type_t type) {
-  if (!type)
-    return false;
-  clang::QualType qual_type(GetCanonicalQualType(type));
-  const clang::Type::TypeClass type_class = qual_type->getTypeClass();
-  return (type_class == clang::Type::Enum);
-}
-
-bool TypeSystemClang::IsPolymorphicClass(lldb::opaque_compiler_type_t type) {
-  if (type) {
-    clang::QualType qual_type(GetCanonicalQualType(type));
-    const clang::Type::TypeClass type_class = qual_type->getTypeClass();
-    switch (type_class) {
-    case clang::Type::Record:
-      if (GetCompleteType(type)) {
-        const clang::RecordType *record_type =
-            llvm::cast<clang::RecordType>(qual_type.getTypePtr());
-        const clang::RecordDecl *record_decl = record_type->getDecl();
-        if (record_decl) {
-          const clang::CXXRecordDecl *cxx_record_decl =
-              llvm::dyn_cast<clang::CXXRecordDecl>(record_decl);
-          if (cxx_record_decl)
-            return cxx_record_decl->isPolymorphic();
-        }
-      }
-      break;
-
-    default:
-      break;
-    }
-  }
-  return false;
-}
-
-bool TypeSystemClang::IsPossibleDynamicType(lldb::opaque_compiler_type_t type,
-                                            CompilerType *dynamic_pointee_type,
-                                            bool check_cplusplus,
-                                            bool check_objc) {
-  clang::QualType pointee_qual_type;
-  if (type) {
-    clang::QualType qual_type = RemoveWrappingTypes(GetCanonicalQualType(type));
-    bool success = false;
-    const clang::Type::TypeClass type_class = qual_type->getTypeClass();
-    switch (type_class) {
-    case clang::Type::Builtin:
-      if (check_objc &&
-          llvm::cast<clang::BuiltinType>(qual_type)->getKind() ==
-              clang::BuiltinType::ObjCId) {
-        if (dynamic_pointee_type)
-          dynamic_pointee_type->SetCompilerType(this, type);
-        return true;
-      }
-      break;
-
-    case clang::Type::ObjCObjectPointer:
-      if (check_objc) {
-        if (auto objc_pointee_type =
-                qual_type->getPointeeType().getTypePtrOrNull()) {
-          if (auto objc_object_type =
-                  llvm::dyn_cast_or_null<clang::ObjCObjectType>(
-                      objc_pointee_type)) {
-            if (objc_object_type->isObjCClass())
-              return false;
-          }
-        }
-        if (dynamic_pointee_type)
-          dynamic_pointee_type->SetCompilerType(
-              this, llvm::cast<clang::ObjCObjectPointerType>(qual_type)
-                        ->getPointeeType()
-                        .getAsOpaquePtr());
-        return true;
-      }
-      break;
-
-    case clang::Type::Pointer:
-      pointee_qual_type =
-          llvm::cast<clang::PointerType>(qual_type)->getPointeeType();
-      success = true;
-      break;
-
-    case clang::Type::LValueReference:
-    case clang::Type::RValueReference:
-      pointee_qual_type =
-          llvm::cast<clang::ReferenceType>(qual_type)->getPointeeType();
-      success = true;
-      break;
-
-    default:
-      break;
-    }
-
-    if (success) {
-      // Check to make sure what we are pointing too is a possible dynamic C++
-      // type We currently accept any "void *" (in case we have a class that
-      // has been watered down to an opaque pointer) and virtual C++ classes.
-      const clang::Type::TypeClass pointee_type_class =
-          pointee_qual_type.getCanonicalType()->getTypeClass();
-      switch (pointee_type_class) {
-      case clang::Type::Builtin:
-        switch (llvm::cast<clang::BuiltinType>(pointee_qual_type)->getKind()) {
-        case clang::BuiltinType::UnknownAny:
-        case clang::BuiltinType::Void:
-          if (dynamic_pointee_type)
-            dynamic_pointee_type->SetCompilerType(
-                this, pointee_qual_type.getAsOpaquePtr());
-          return true;
-        default:
-          break;
-        }
-        break;
-
-      case clang::Type::Record:
-        if (check_cplusplus) {
-          clang::CXXRecordDecl *cxx_record_decl =
-              pointee_qual_type->getAsCXXRecordDecl();
-          if (cxx_record_decl) {
-            bool is_complete = cxx_record_decl->isCompleteDefinition();
-
-            if (is_complete)
-              success = cxx_record_decl->isDynamicClass();
-            else {
-              ClangASTMetadata *metadata = GetMetadata(cxx_record_decl);
-              if (metadata)
-                success = metadata->GetIsDynamicCXXType();
-              else {
-                is_complete = GetType(pointee_qual_type).GetCompleteType();
-                if (is_complete)
-                  success = cxx_record_decl->isDynamicClass();
-                else
-                  success = false;
-              }
-            }
-
-            if (success) {
-              if (dynamic_pointee_type)
-                dynamic_pointee_type->SetCompilerType(
-                    this, pointee_qual_type.getAsOpaquePtr());
-              return true;
-            }
-          }
-        }
-        break;
-
-      case clang::Type::ObjCObject:
-      case clang::Type::ObjCInterface:
-        if (check_objc) {
-          if (dynamic_pointee_type)
-            dynamic_pointee_type->SetCompilerType(
-                this, pointee_qual_type.getAsOpaquePtr());
-          return true;
-        }
-        break;
-
-      default:
-        break;
-      }
-    }
-  }
-  if (dynamic_pointee_type)
-    dynamic_pointee_type->Clear();
-  return false;
-}
-
-bool TypeSystemClang::IsScalarType(lldb::opaque_compiler_type_t type) {
-  if (!type)
-    return false;
-
-  return (GetTypeInfo(type, nullptr) & eTypeIsScalar) != 0;
-}
-
-bool TypeSystemClang::IsTypedefType(lldb::opaque_compiler_type_t type) {
-  if (!type)
-    return false;
-  return GetQualType(type)->getTypeClass() == clang::Type::Typedef;
-}
-
-bool TypeSystemClang::IsVoidType(lldb::opaque_compiler_type_t type) {
-  if (!type)
-    return false;
-  return GetCanonicalQualType(type)->isVoidType();
-}
-
-bool TypeSystemClang::CanPassInRegisters(const CompilerType &type) {
-  if (auto *record_decl =
-      TypeSystemClang::GetAsRecordDecl(type)) {
-    return record_decl->canPassInRegisters();
-  }
-  return false;
-}
-
-bool TypeSystemClang::SupportsLanguage(lldb::LanguageType language) {
-  return TypeSystemClangSupportsLanguage(language);
-}
-
-Optional<std::string>
-TypeSystemClang::GetCXXClassName(const CompilerType &type) {
-  if (!type)
-    return llvm::None;
-
-  clang::QualType qual_type(ClangUtil::GetCanonicalQualType(type));
-  if (qual_type.isNull())
-    return llvm::None;
-
-  clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl();
-  if (!cxx_record_decl)
-    return llvm::None;
-
-  return std::string(cxx_record_decl->getIdentifier()->getNameStart());
-}
-
-bool TypeSystemClang::IsCXXClassType(const CompilerType &type) {
-  if (!type)
-    return false;
-
-  clang::QualType qual_type(ClangUtil::GetCanonicalQualType(type));
-  return !qual_type.isNull() && qual_type->getAsCXXRecordDecl() != nullptr;
-}
-
-bool TypeSystemClang::IsBeingDefined(lldb::opaque_compiler_type_t type) {
-  if (!type)
-    return false;
-  clang::QualType qual_type(GetCanonicalQualType(type));
-  const clang::TagType *tag_type = llvm::dyn_cast<clang::TagType>(qual_type);
-  if (tag_type)
-    return tag_type->isBeingDefined();
-  return false;
-}
-
-bool TypeSystemClang::IsObjCObjectPointerType(const CompilerType &type,
-                                              CompilerType *class_type_ptr) {
-  if (!ClangUtil::IsClangType(type))
-    return false;
-
-  clang::QualType qual_type(ClangUtil::GetCanonicalQualType(type));
-
-  if (!qual_type.isNull() && qual_type->isObjCObjectPointerType()) {
-    if (class_type_ptr) {
-      if (!qual_type->isObjCClassType() && !qual_type->isObjCIdType()) {
-        const clang::ObjCObjectPointerType *obj_pointer_type =
-            llvm::dyn_cast<clang::ObjCObjectPointerType>(qual_type);
-        if (obj_pointer_type == nullptr)
-          class_type_ptr->Clear();
-        else
-          class_type_ptr->SetCompilerType(
-              type.GetTypeSystem(),
-              clang::QualType(obj_pointer_type->getInterfaceType(), 0)
-                  .getAsOpaquePtr());
-      }
-    }
-    return true;
-  }
-  if (class_type_ptr)
-    class_type_ptr->Clear();
-  return false;
-}
-
-// Type Completion
-
-bool TypeSystemClang::GetCompleteType(lldb::opaque_compiler_type_t type) {
-  if (!type)
-    return false;
-  const bool allow_completion = true;
-  return GetCompleteQualType(&getASTContext(), GetQualType(type),
-                             allow_completion);
-}
-
-ConstString TypeSystemClang::GetTypeName(lldb::opaque_compiler_type_t type) {
-  std::string type_name;
-  if (type) {
-    clang::PrintingPolicy printing_policy(getASTContext().getPrintingPolicy());
-    clang::QualType qual_type(GetQualType(type));
-    printing_policy.SuppressTagKeyword = true;
-    const clang::TypedefType *typedef_type =
-        qual_type->getAs<clang::TypedefType>();
-    if (typedef_type) {
-      const clang::TypedefNameDecl *typedef_decl = typedef_type->getDecl();
-      type_name = typedef_decl->getQualifiedNameAsString();
-    } else {
-      type_name = qual_type.getAsString(printing_policy);
-    }
-  }
-  return ConstString(type_name);
-}
-
-uint32_t
-TypeSystemClang::GetTypeInfo(lldb::opaque_compiler_type_t type,
-                             CompilerType *pointee_or_element_clang_type) {
-  if (!type)
-    return 0;
-
-  if (pointee_or_element_clang_type)
-    pointee_or_element_clang_type->Clear();
-
-  clang::QualType qual_type =
-      RemoveWrappingTypes(GetQualType(type), {clang::Type::Typedef});
-
-  const clang::Type::TypeClass type_class = qual_type->getTypeClass();
-  switch (type_class) {
-  case clang::Type::Attributed:
-    return GetTypeInfo(
-        qual_type->getAs<clang::AttributedType>()
-            ->getModifiedType().getAsOpaquePtr(),
-        pointee_or_element_clang_type);
-  case clang::Type::Builtin: {
-    const clang::BuiltinType *builtin_type = llvm::dyn_cast<clang::BuiltinType>(
-        qual_type->getCanonicalTypeInternal());
-
-    uint32_t builtin_type_flags = eTypeIsBuiltIn | eTypeHasValue;
-    switch (builtin_type->getKind()) {
-    case clang::BuiltinType::ObjCId:
-    case clang::BuiltinType::ObjCClass:
-      if (pointee_or_element_clang_type)
-        pointee_or_element_clang_type->SetCompilerType(
-            this, getASTContext().ObjCBuiltinClassTy.getAsOpaquePtr());
-      builtin_type_flags |= eTypeIsPointer | eTypeIsObjC;
-      break;
-
-    case clang::BuiltinType::ObjCSel:
-      if (pointee_or_element_clang_type)
-        pointee_or_element_clang_type->SetCompilerType(
-            this, getASTContext().CharTy.getAsOpaquePtr());
-      builtin_type_flags |= eTypeIsPointer | eTypeIsObjC;
-      break;
-
-    case clang::BuiltinType::Bool:
-    case clang::BuiltinType::Char_U:
-    case clang::BuiltinType::UChar:
-    case clang::BuiltinType::WChar_U:
-    case clang::BuiltinType::Char16:
-    case clang::BuiltinType::Char32:
-    case clang::BuiltinType::UShort:
-    case clang::BuiltinType::UInt:
-    case clang::BuiltinType::ULong:
-    case clang::BuiltinType::ULongLong:
-    case clang::BuiltinType::UInt128:
-    case clang::BuiltinType::Char_S:
-    case clang::BuiltinType::SChar:
-    case clang::BuiltinType::WChar_S:
-    case clang::BuiltinType::Short:
-    case clang::BuiltinType::Int:
-    case clang::BuiltinType::Long:
-    case clang::BuiltinType::LongLong:
-    case clang::BuiltinType::Int128:
-    case clang::BuiltinType::Float:
-    case clang::BuiltinType::Double:
-    case clang::BuiltinType::LongDouble:
-      builtin_type_flags |= eTypeIsScalar;
-      if (builtin_type->isInteger()) {
-        builtin_type_flags |= eTypeIsInteger;
-        if (builtin_type->isSignedInteger())
-          builtin_type_flags |= eTypeIsSigned;
-      } else if (builtin_type->isFloatingPoint())
-        builtin_type_flags |= eTypeIsFloat;
-      break;
-    default:
-      break;
-    }
-    return builtin_type_flags;
-  }
-
-  case clang::Type::BlockPointer:
-    if (pointee_or_element_clang_type)
-      pointee_or_element_clang_type->SetCompilerType(
-          this, qual_type->getPointeeType().getAsOpaquePtr());
-    return eTypeIsPointer | eTypeHasChildren | eTypeIsBlock;
-
-  case clang::Type::Complex: {
-    uint32_t complex_type_flags =
-        eTypeIsBuiltIn | eTypeHasValue | eTypeIsComplex;
-    const clang::ComplexType *complex_type = llvm::dyn_cast<clang::ComplexType>(
-        qual_type->getCanonicalTypeInternal());
-    if (complex_type) {
-      clang::QualType complex_element_type(complex_type->getElementType());
-      if (complex_element_type->isIntegerType())
-        complex_type_flags |= eTypeIsFloat;
-      else if (complex_element_type->isFloatingType())
-        complex_type_flags |= eTypeIsInteger;
-    }
-    return complex_type_flags;
-  } break;
-
-  case clang::Type::ConstantArray:
-  case clang::Type::DependentSizedArray:
-  case clang::Type::IncompleteArray:
-  case clang::Type::VariableArray:
-    if (pointee_or_element_clang_type)
-      pointee_or_element_clang_type->SetCompilerType(
-          this, llvm::cast<clang::ArrayType>(qual_type.getTypePtr())
-                    ->getElementType()
-                    .getAsOpaquePtr());
-    return eTypeHasChildren | eTypeIsArray;
-
-  case clang::Type::DependentName:
-    return 0;
-  case clang::Type::DependentSizedExtVector:
-    return eTypeHasChildren | eTypeIsVector;
-  case clang::Type::DependentTemplateSpecialization:
-    return eTypeIsTemplate;
-
-  case clang::Type::Enum:
-    if (pointee_or_element_clang_type)
-      pointee_or_element_clang_type->SetCompilerType(
-          this, llvm::cast<clang::EnumType>(qual_type)
-                    ->getDecl()
-                    ->getIntegerType()
-                    .getAsOpaquePtr());
-    return eTypeIsEnumeration | eTypeHasValue;
-
-  case clang::Type::FunctionProto:
-    return eTypeIsFuncPrototype | eTypeHasValue;
-  case clang::Type::FunctionNoProto:
-    return eTypeIsFuncPrototype | eTypeHasValue;
-  case clang::Type::InjectedClassName:
-    return 0;
-
-  case clang::Type::LValueReference:
-  case clang::Type::RValueReference:
-    if (pointee_or_element_clang_type)
-      pointee_or_element_clang_type->SetCompilerType(
-          this, llvm::cast<clang::ReferenceType>(qual_type.getTypePtr())
-                    ->getPointeeType()
-                    .getAsOpaquePtr());
-    return eTypeHasChildren | eTypeIsReference | eTypeHasValue;
-
-  case clang::Type::MemberPointer:
-    return eTypeIsPointer | eTypeIsMember | eTypeHasValue;
-
-  case clang::Type::ObjCObjectPointer:
-    if (pointee_or_element_clang_type)
-      pointee_or_element_clang_type->SetCompilerType(
-          this, qual_type->getPointeeType().getAsOpaquePtr());
-    return eTypeHasChildren | eTypeIsObjC | eTypeIsClass | eTypeIsPointer |
-           eTypeHasValue;
-
-  case clang::Type::ObjCObject:
-    return eTypeHasChildren | eTypeIsObjC | eTypeIsClass;
-  case clang::Type::ObjCInterface:
-    return eTypeHasChildren | eTypeIsObjC | eTypeIsClass;
-
-  case clang::Type::Pointer:
-    if (pointee_or_element_clang_type)
-      pointee_or_element_clang_type->SetCompilerType(
-          this, qual_type->getPointeeType().getAsOpaquePtr());
-    return eTypeHasChildren | eTypeIsPointer | eTypeHasValue;
-
-  case clang::Type::Record:
-    if (qual_type->getAsCXXRecordDecl())
-      return eTypeHasChildren | eTypeIsClass | eTypeIsCPlusPlus;
-    else
-      return eTypeHasChildren | eTypeIsStructUnion;
-    break;
-  case clang::Type::SubstTemplateTypeParm:
-    return eTypeIsTemplate;
-  case clang::Type::TemplateTypeParm:
-    return eTypeIsTemplate;
-  case clang::Type::TemplateSpecialization:
-    return eTypeIsTemplate;
-
-  case clang::Type::Typedef:
-    return eTypeIsTypedef | GetType(llvm::cast<clang::TypedefType>(qual_type)
-                                        ->getDecl()
-                                        ->getUnderlyingType())
-                                .GetTypeInfo(pointee_or_element_clang_type);
-  case clang::Type::UnresolvedUsing:
-    return 0;
-
-  case clang::Type::ExtVector:
-  case clang::Type::Vector: {
-    uint32_t vector_type_flags = eTypeHasChildren | eTypeIsVector;
-    const clang::VectorType *vector_type = llvm::dyn_cast<clang::VectorType>(
-        qual_type->getCanonicalTypeInternal());
-    if (vector_type) {
-      if (vector_type->isIntegerType())
-        vector_type_flags |= eTypeIsFloat;
-      else if (vector_type->isFloatingType())
-        vector_type_flags |= eTypeIsInteger;
-    }
-    return vector_type_flags;
-  }
-  default:
-    return 0;
-  }
-  return 0;
-}
-
-lldb::LanguageType
-TypeSystemClang::GetMinimumLanguage(lldb::opaque_compiler_type_t type) {
-  if (!type)
-    return lldb::eLanguageTypeC;
-
-  // If the type is a reference, then resolve it to what it refers to first:
-  clang::QualType qual_type(GetCanonicalQualType(type).getNonReferenceType());
-  if (qual_type->isAnyPointerType()) {
-    if (qual_type->isObjCObjectPointerType())
-      return lldb::eLanguageTypeObjC;
-    if (qual_type->getPointeeCXXRecordDecl())
-      return lldb::eLanguageTypeC_plus_plus;
-
-    clang::QualType pointee_type(qual_type->getPointeeType());
-    if (pointee_type->getPointeeCXXRecordDecl())
-      return lldb::eLanguageTypeC_plus_plus;
-    if (pointee_type->isObjCObjectOrInterfaceType())
-      return lldb::eLanguageTypeObjC;
-    if (pointee_type->isObjCClassType())
-      return lldb::eLanguageTypeObjC;
-    if (pointee_type.getTypePtr() ==
-        getASTContext().ObjCBuiltinIdTy.getTypePtr())
-      return lldb::eLanguageTypeObjC;
-  } else {
-    if (qual_type->isObjCObjectOrInterfaceType())
-      return lldb::eLanguageTypeObjC;
-    if (qual_type->getAsCXXRecordDecl())
-      return lldb::eLanguageTypeC_plus_plus;
-    switch (qual_type->getTypeClass()) {
-    default:
-      break;
-    case clang::Type::Builtin:
-      switch (llvm::cast<clang::BuiltinType>(qual_type)->getKind()) {
-      default:
-      case clang::BuiltinType::Void:
-      case clang::BuiltinType::Bool:
-      case clang::BuiltinType::Char_U:
-      case clang::BuiltinType::UChar:
-      case clang::BuiltinType::WChar_U:
-      case clang::BuiltinType::Char16:
-      case clang::BuiltinType::Char32:
-      case clang::BuiltinType::UShort:
-      case clang::BuiltinType::UInt:
-      case clang::BuiltinType::ULong:
-      case clang::BuiltinType::ULongLong:
-      case clang::BuiltinType::UInt128:
-      case clang::BuiltinType::Char_S:
-      case clang::BuiltinType::SChar:
-      case clang::BuiltinType::WChar_S:
-      case clang::BuiltinType::Short:
-      case clang::BuiltinType::Int:
-      case clang::BuiltinType::Long:
-      case clang::BuiltinType::LongLong:
-      case clang::BuiltinType::Int128:
-      case clang::BuiltinType::Float:
-      case clang::BuiltinType::Double:
-      case clang::BuiltinType::LongDouble:
-        break;
-
-      case clang::BuiltinType::NullPtr:
-        return eLanguageTypeC_plus_plus;
-
-      case clang::BuiltinType::ObjCId:
-      case clang::BuiltinType::ObjCClass:
-      case clang::BuiltinType::ObjCSel:
-        return eLanguageTypeObjC;
-
-      case clang::BuiltinType::Dependent:
-      case clang::BuiltinType::Overload:
-      case clang::BuiltinType::BoundMember:
-      case clang::BuiltinType::UnknownAny:
-        break;
-      }
-      break;
-    case clang::Type::Typedef:
-      return GetType(llvm::cast<clang::TypedefType>(qual_type)
-                         ->getDecl()
-                         ->getUnderlyingType())
-          .GetMinimumLanguage();
-    }
-  }
-  return lldb::eLanguageTypeC;
-}
-
-lldb::TypeClass
-TypeSystemClang::GetTypeClass(lldb::opaque_compiler_type_t type) {
-  if (!type)
-    return lldb::eTypeClassInvalid;
-
-  clang::QualType qual_type =
-      RemoveWrappingTypes(GetQualType(type), {clang::Type::Typedef});
-
-  switch (qual_type->getTypeClass()) {
-  case clang::Type::Atomic:
-  case clang::Type::Auto:
-  case clang::Type::Decltype:
-  case clang::Type::Elaborated:
-  case clang::Type::Paren:
-  case clang::Type::TypeOf:
-  case clang::Type::TypeOfExpr:
-    llvm_unreachable("Handled in RemoveWrappingTypes!");
-  case clang::Type::UnaryTransform:
-    break;
-  case clang::Type::FunctionNoProto:
-    return lldb::eTypeClassFunction;
-  case clang::Type::FunctionProto:
-    return lldb::eTypeClassFunction;
-  case clang::Type::IncompleteArray:
-    return lldb::eTypeClassArray;
-  case clang::Type::VariableArray:
-    return lldb::eTypeClassArray;
-  case clang::Type::ConstantArray:
-    return lldb::eTypeClassArray;
-  case clang::Type::DependentSizedArray:
-    return lldb::eTypeClassArray;
-  case clang::Type::DependentSizedExtVector:
-    return lldb::eTypeClassVector;
-  case clang::Type::DependentVector:
-    return lldb::eTypeClassVector;
-  case clang::Type::ExtVector:
-    return lldb::eTypeClassVector;
-  case clang::Type::Vector:
-    return lldb::eTypeClassVector;
-  case clang::Type::Builtin:
-    return lldb::eTypeClassBuiltin;
-  case clang::Type::ObjCObjectPointer:
-    return lldb::eTypeClassObjCObjectPointer;
-  case clang::Type::BlockPointer:
-    return lldb::eTypeClassBlockPointer;
-  case clang::Type::Pointer:
-    return lldb::eTypeClassPointer;
-  case clang::Type::LValueReference:
-    return lldb::eTypeClassReference;
-  case clang::Type::RValueReference:
-    return lldb::eTypeClassReference;
-  case clang::Type::MemberPointer:
-    return lldb::eTypeClassMemberPointer;
-  case clang::Type::Complex:
-    if (qual_type->isComplexType())
-      return lldb::eTypeClassComplexFloat;
-    else
-      return lldb::eTypeClassComplexInteger;
-  case clang::Type::ObjCObject:
-    return lldb::eTypeClassObjCObject;
-  case clang::Type::ObjCInterface:
-    return lldb::eTypeClassObjCInterface;
-  case clang::Type::Record: {
-    const clang::RecordType *record_type =
-        llvm::cast<clang::RecordType>(qual_type.getTypePtr());
-    const clang::RecordDecl *record_decl = record_type->getDecl();
-    if (record_decl->isUnion())
-      return lldb::eTypeClassUnion;
-    else if (record_decl->isStruct())
-      return lldb::eTypeClassStruct;
-    else
-      return lldb::eTypeClassClass;
-  } break;
-  case clang::Type::Enum:
-    return lldb::eTypeClassEnumeration;
-  case clang::Type::Typedef:
-    return lldb::eTypeClassTypedef;
-  case clang::Type::UnresolvedUsing:
-    break;
-
-  case clang::Type::Attributed:
-    break;
-  case clang::Type::TemplateTypeParm:
-    break;
-  case clang::Type::SubstTemplateTypeParm:
-    break;
-  case clang::Type::SubstTemplateTypeParmPack:
-    break;
-  case clang::Type::InjectedClassName:
-    break;
-  case clang::Type::DependentName:
-    break;
-  case clang::Type::DependentTemplateSpecialization:
-    break;
-  case clang::Type::PackExpansion:
-    break;
-
-  case clang::Type::TemplateSpecialization:
-    break;
-  case clang::Type::DeducedTemplateSpecialization:
-    break;
-  case clang::Type::Pipe:
-    break;
-
-  // pointer type decayed from an array or function type.
-  case clang::Type::Decayed:
-    break;
-  case clang::Type::Adjusted:
-    break;
-  case clang::Type::ObjCTypeParam:
-    break;
-
-  case clang::Type::DependentAddressSpace:
-    break;
-  case clang::Type::MacroQualified:
-    break;
-  }
-  // We don't know hot to display this type...
-  return lldb::eTypeClassOther;
-}
-
-unsigned TypeSystemClang::GetTypeQualifiers(lldb::opaque_compiler_type_t type) {
-  if (type)
-    return GetQualType(type).getQualifiers().getCVRQualifiers();
-  return 0;
-}
-
-// Creating related types
-
-CompilerType
-TypeSystemClang::GetArrayElementType(lldb::opaque_compiler_type_t type,
-                                     uint64_t *stride) {
-  if (type) {
-    clang::QualType qual_type(GetQualType(type));
-
-    const clang::Type *array_eletype =
-        qual_type.getTypePtr()->getArrayElementTypeNoTypeQual();
-
-    if (!array_eletype)
-      return CompilerType();
-
-    CompilerType element_type = GetType(clang::QualType(array_eletype, 0));
-
-    // TODO: the real stride will be >= this value.. find the real one!
-    if (stride)
-      if (Optional<uint64_t> size = element_type.GetByteSize(nullptr))
-        *stride = *size;
-
-    return element_type;
-  }
-  return CompilerType();
-}
-
-CompilerType TypeSystemClang::GetArrayType(lldb::opaque_compiler_type_t type,
-                                           uint64_t size) {
-  if (type) {
-    clang::QualType qual_type(GetCanonicalQualType(type));
-    clang::ASTContext &ast_ctx = getASTContext();
-    if (size != 0)
-      return GetType(ast_ctx.getConstantArrayType(
-          qual_type, llvm::APInt(64, size), nullptr,
-          clang::ArrayType::ArraySizeModifier::Normal, 0));
-    else
-      return GetType(ast_ctx.getIncompleteArrayType(
-          qual_type, clang::ArrayType::ArraySizeModifier::Normal, 0));
-  }
-
-  return CompilerType();
-}
-
-CompilerType
-TypeSystemClang::GetCanonicalType(lldb::opaque_compiler_type_t type) {
-  if (type)
-    return GetType(GetCanonicalQualType(type));
-  return CompilerType();
-}
-
-static clang::QualType GetFullyUnqualifiedType_Impl(clang::ASTContext *ast,
-                                                    clang::QualType qual_type) {
-  if (qual_type->isPointerType())
-    qual_type = ast->getPointerType(
-        GetFullyUnqualifiedType_Impl(ast, qual_type->getPointeeType()));
-  else
-    qual_type = qual_type.getUnqualifiedType();
-  qual_type.removeLocalConst();
-  qual_type.removeLocalRestrict();
-  qual_type.removeLocalVolatile();
-  return qual_type;
-}
-
-CompilerType
-TypeSystemClang::GetFullyUnqualifiedType(lldb::opaque_compiler_type_t type) {
-  if (type)
-    return GetType(
-        GetFullyUnqualifiedType_Impl(&getASTContext(), GetQualType(type)));
-  return CompilerType();
-}
-
-int TypeSystemClang::GetFunctionArgumentCount(
-    lldb::opaque_compiler_type_t type) {
-  if (type) {
-    const clang::FunctionProtoType *func =
-        llvm::dyn_cast<clang::FunctionProtoType>(GetCanonicalQualType(type));
-    if (func)
-      return func->getNumParams();
-  }
-  return -1;
-}
-
-CompilerType TypeSystemClang::GetFunctionArgumentTypeAtIndex(
-    lldb::opaque_compiler_type_t type, size_t idx) {
-  if (type) {
-    const clang::FunctionProtoType *func =
-        llvm::dyn_cast<clang::FunctionProtoType>(GetQualType(type));
-    if (func) {
-      const uint32_t num_args = func->getNumParams();
-      if (idx < num_args)
-        return GetType(func->getParamType(idx));
-    }
-  }
-  return CompilerType();
-}
-
-CompilerType
-TypeSystemClang::GetFunctionReturnType(lldb::opaque_compiler_type_t type) {
-  if (type) {
-    clang::QualType qual_type(GetQualType(type));
-    const clang::FunctionProtoType *func =
-        llvm::dyn_cast<clang::FunctionProtoType>(qual_type.getTypePtr());
-    if (func)
-      return GetType(func->getReturnType());
-  }
-  return CompilerType();
-}
-
-size_t
-TypeSystemClang::GetNumMemberFunctions(lldb::opaque_compiler_type_t type) {
-  size_t num_functions = 0;
-  if (type) {
-    clang::QualType qual_type = RemoveWrappingTypes(GetCanonicalQualType(type));
-    switch (qual_type->getTypeClass()) {
-    case clang::Type::Record:
-      if (GetCompleteQualType(&getASTContext(), qual_type)) {
-        const clang::RecordType *record_type =
-            llvm::cast<clang::RecordType>(qual_type.getTypePtr());
-        const clang::RecordDecl *record_decl = record_type->getDecl();
-        assert(record_decl);
-        const clang::CXXRecordDecl *cxx_record_decl =
-            llvm::dyn_cast<clang::CXXRecordDecl>(record_decl);
-        if (cxx_record_decl)
-          num_functions = std::distance(cxx_record_decl->method_begin(),
-                                        cxx_record_decl->method_end());
-      }
-      break;
-
-    case clang::Type::ObjCObjectPointer: {
-      const clang::ObjCObjectPointerType *objc_class_type =
-          qual_type->getAs<clang::ObjCObjectPointerType>();
-      const clang::ObjCInterfaceType *objc_interface_type =
-          objc_class_type->getInterfaceType();
-      if (objc_interface_type &&
-          GetCompleteType(static_cast<lldb::opaque_compiler_type_t>(
-              const_cast<clang::ObjCInterfaceType *>(objc_interface_type)))) {
-        clang::ObjCInterfaceDecl *class_interface_decl =
-            objc_interface_type->getDecl();
-        if (class_interface_decl) {
-          num_functions = std::distance(class_interface_decl->meth_begin(),
-                                        class_interface_decl->meth_end());
-        }
-      }
-      break;
-    }
-
-    case clang::Type::ObjCObject:
-    case clang::Type::ObjCInterface:
-      if (GetCompleteType(type)) {
-        const clang::ObjCObjectType *objc_class_type =
-            llvm::dyn_cast<clang::ObjCObjectType>(qual_type.getTypePtr());
-        if (objc_class_type) {
-          clang::ObjCInterfaceDecl *class_interface_decl =
-              objc_class_type->getInterface();
-          if (class_interface_decl)
-            num_functions = std::distance(class_interface_decl->meth_begin(),
-                                          class_interface_decl->meth_end());
-        }
-      }
-      break;
-
-    default:
-      break;
-    }
-  }
-  return num_functions;
-}
-
-TypeMemberFunctionImpl
-TypeSystemClang::GetMemberFunctionAtIndex(lldb::opaque_compiler_type_t type,
-                                          size_t idx) {
-  std::string name;
-  MemberFunctionKind kind(MemberFunctionKind::eMemberFunctionKindUnknown);
-  CompilerType clang_type;
-  CompilerDecl clang_decl;
-  if (type) {
-    clang::QualType qual_type = RemoveWrappingTypes(GetCanonicalQualType(type));
-    switch (qual_type->getTypeClass()) {
-    case clang::Type::Record:
-      if (GetCompleteQualType(&getASTContext(), qual_type)) {
-        const clang::RecordType *record_type =
-            llvm::cast<clang::RecordType>(qual_type.getTypePtr());
-        const clang::RecordDecl *record_decl = record_type->getDecl();
-        assert(record_decl);
-        const clang::CXXRecordDecl *cxx_record_decl =
-            llvm::dyn_cast<clang::CXXRecordDecl>(record_decl);
-        if (cxx_record_decl) {
-          auto method_iter = cxx_record_decl->method_begin();
-          auto method_end = cxx_record_decl->method_end();
-          if (idx <
-              static_cast<size_t>(std::distance(method_iter, method_end))) {
-            std::advance(method_iter, idx);
-            clang::CXXMethodDecl *cxx_method_decl =
-                method_iter->getCanonicalDecl();
-            if (cxx_method_decl) {
-              name = cxx_method_decl->getDeclName().getAsString();
-              if (cxx_method_decl->isStatic())
-                kind = lldb::eMemberFunctionKindStaticMethod;
-              else if (llvm::isa<clang::CXXConstructorDecl>(cxx_method_decl))
-                kind = lldb::eMemberFunctionKindConstructor;
-              else if (llvm::isa<clang::CXXDestructorDecl>(cxx_method_decl))
-                kind = lldb::eMemberFunctionKindDestructor;
-              else
-                kind = lldb::eMemberFunctionKindInstanceMethod;
-              clang_type = GetType(cxx_method_decl->getType());
-              clang_decl = GetCompilerDecl(cxx_method_decl);
-            }
-          }
-        }
-      }
-      break;
-
-    case clang::Type::ObjCObjectPointer: {
-      const clang::ObjCObjectPointerType *objc_class_type =
-          qual_type->getAs<clang::ObjCObjectPointerType>();
-      const clang::ObjCInterfaceType *objc_interface_type =
-          objc_class_type->getInterfaceType();
-      if (objc_interface_type &&
-          GetCompleteType(static_cast<lldb::opaque_compiler_type_t>(
-              const_cast<clang::ObjCInterfaceType *>(objc_interface_type)))) {
-        clang::ObjCInterfaceDecl *class_interface_decl =
-            objc_interface_type->getDecl();
-        if (class_interface_decl) {
-          auto method_iter = class_interface_decl->meth_begin();
-          auto method_end = class_interface_decl->meth_end();
-          if (idx <
-              static_cast<size_t>(std::distance(method_iter, method_end))) {
-            std::advance(method_iter, idx);
-            clang::ObjCMethodDecl *objc_method_decl =
-                method_iter->getCanonicalDecl();
-            if (objc_method_decl) {
-              clang_decl = GetCompilerDecl(objc_method_decl);
-              name = objc_method_decl->getSelector().getAsString();
-              if (objc_method_decl->isClassMethod())
-                kind = lldb::eMemberFunctionKindStaticMethod;
-              else
-                kind = lldb::eMemberFunctionKindInstanceMethod;
-            }
-          }
-        }
-      }
-      break;
-    }
-
-    case clang::Type::ObjCObject:
-    case clang::Type::ObjCInterface:
-      if (GetCompleteType(type)) {
-        const clang::ObjCObjectType *objc_class_type =
-            llvm::dyn_cast<clang::ObjCObjectType>(qual_type.getTypePtr());
-        if (objc_class_type) {
-          clang::ObjCInterfaceDecl *class_interface_decl =
-              objc_class_type->getInterface();
-          if (class_interface_decl) {
-            auto method_iter = class_interface_decl->meth_begin();
-            auto method_end = class_interface_decl->meth_end();
-            if (idx <
-                static_cast<size_t>(std::distance(method_iter, method_end))) {
-              std::advance(method_iter, idx);
-              clang::ObjCMethodDecl *objc_method_decl =
-                  method_iter->getCanonicalDecl();
-              if (objc_method_decl) {
-                clang_decl = GetCompilerDecl(objc_method_decl);
-                name = objc_method_decl->getSelector().getAsString();
-                if (objc_method_decl->isClassMethod())
-                  kind = lldb::eMemberFunctionKindStaticMethod;
-                else
-                  kind = lldb::eMemberFunctionKindInstanceMethod;
-              }
-            }
-          }
-        }
-      }
-      break;
-
-    default:
-      break;
-    }
-  }
-
-  if (kind == eMemberFunctionKindUnknown)
-    return TypeMemberFunctionImpl();
-  else
-    return TypeMemberFunctionImpl(clang_type, clang_decl, name, kind);
-}
-
-CompilerType
-TypeSystemClang::GetNonReferenceType(lldb::opaque_compiler_type_t type) {
-  if (type)
-    return GetType(GetQualType(type).getNonReferenceType());
-  return CompilerType();
-}
-
-CompilerType TypeSystemClang::CreateTypedefType(
-    const CompilerType &type, const char *typedef_name,
-    const CompilerDeclContext &compiler_decl_ctx) {
-  if (type && typedef_name && typedef_name[0]) {
-    TypeSystemClang *ast =
-        llvm::dyn_cast<TypeSystemClang>(type.GetTypeSystem());
-    if (!ast)
-      return CompilerType();
-    clang::ASTContext &clang_ast = ast->getASTContext();
-    clang::QualType qual_type(ClangUtil::GetQualType(type));
-
-    clang::DeclContext *decl_ctx =
-        TypeSystemClang::DeclContextGetAsDeclContext(compiler_decl_ctx);
-    if (decl_ctx == nullptr)
-      decl_ctx = ast->getASTContext().getTranslationUnitDecl();
-
-    clang::TypedefDecl *decl = clang::TypedefDecl::Create(
-        clang_ast, decl_ctx, clang::SourceLocation(), clang::SourceLocation(),
-        &clang_ast.Idents.get(typedef_name),
-        clang_ast.getTrivialTypeSourceInfo(qual_type));
-
-    decl->setAccess(clang::AS_public); // TODO respect proper access specifier
-
-    decl_ctx->addDecl(decl);
-
-    // Get a uniqued clang::QualType for the typedef decl type
-    return ast->GetType(clang_ast.getTypedefType(decl));
-  }
-  return CompilerType();
-}
-
-CompilerType
-TypeSystemClang::GetPointeeType(lldb::opaque_compiler_type_t type) {
-  if (type) {
-    clang::QualType qual_type(GetQualType(type));
-    return GetType(qual_type.getTypePtr()->getPointeeType());
-  }
-  return CompilerType();
-}
-
-CompilerType
-TypeSystemClang::GetPointerType(lldb::opaque_compiler_type_t type) {
-  if (type) {
-    clang::QualType qual_type(GetQualType(type));
-
-    const clang::Type::TypeClass type_class = qual_type->getTypeClass();
-    switch (type_class) {
-    case clang::Type::ObjCObject:
-    case clang::Type::ObjCInterface:
-      return GetType(getASTContext().getObjCObjectPointerType(qual_type));
-
-    default:
-      return GetType(getASTContext().getPointerType(qual_type));
-    }
-  }
-  return CompilerType();
-}
-
-CompilerType
-TypeSystemClang::GetLValueReferenceType(lldb::opaque_compiler_type_t type) {
-  if (type)
-    return GetType(getASTContext().getLValueReferenceType(GetQualType(type)));
-  else
-    return CompilerType();
-}
-
-CompilerType
-TypeSystemClang::GetRValueReferenceType(lldb::opaque_compiler_type_t type) {
-  if (type)
-    return GetType(getASTContext().getRValueReferenceType(GetQualType(type)));
-  else
-    return CompilerType();
-}
-
-CompilerType TypeSystemClang::GetAtomicType(lldb::opaque_compiler_type_t type) {
-  if (!type)
-    return CompilerType();
-  return GetType(getASTContext().getAtomicType(GetQualType(type)));
-}
-
-CompilerType
-TypeSystemClang::AddConstModifier(lldb::opaque_compiler_type_t type) {
-  if (type) {
-    clang::QualType result(GetQualType(type));
-    result.addConst();
-    return GetType(result);
-  }
-  return CompilerType();
-}
-
-CompilerType
-TypeSystemClang::AddVolatileModifier(lldb::opaque_compiler_type_t type) {
-  if (type) {
-    clang::QualType result(GetQualType(type));
-    result.addVolatile();
-    return GetType(result);
-  }
-  return CompilerType();
-}
-
-CompilerType
-TypeSystemClang::AddRestrictModifier(lldb::opaque_compiler_type_t type) {
-  if (type) {
-    clang::QualType result(GetQualType(type));
-    result.addRestrict();
-    return GetType(result);
-  }
-  return CompilerType();
-}
-
-CompilerType
-TypeSystemClang::CreateTypedef(lldb::opaque_compiler_type_t type,
-                               const char *typedef_name,
-                               const CompilerDeclContext &compiler_decl_ctx) {
-  if (type) {
-    clang::ASTContext &clang_ast = getASTContext();
-    clang::QualType qual_type(GetQualType(type));
-
-    clang::DeclContext *decl_ctx =
-        TypeSystemClang::DeclContextGetAsDeclContext(compiler_decl_ctx);
-    if (decl_ctx == nullptr)
-      decl_ctx = getASTContext().getTranslationUnitDecl();
-
-    clang::TypedefDecl *decl = clang::TypedefDecl::Create(
-        clang_ast, decl_ctx, clang::SourceLocation(), clang::SourceLocation(),
-        &clang_ast.Idents.get(typedef_name),
-        clang_ast.getTrivialTypeSourceInfo(qual_type));
-
-    clang::TagDecl *tdecl = nullptr;
-    if (!qual_type.isNull()) {
-      if (const clang::RecordType *rt = qual_type->getAs<clang::RecordType>())
-        tdecl = rt->getDecl();
-      if (const clang::EnumType *et = qual_type->getAs<clang::EnumType>())
-        tdecl = et->getDecl();
-    }
-
-    // Check whether this declaration is an anonymous struct, union, or enum,
-    // hidden behind a typedef. If so, we try to check whether we have a
-    // typedef tag to attach to the original record declaration
-    if (tdecl && !tdecl->getIdentifier() && !tdecl->getTypedefNameForAnonDecl())
-      tdecl->setTypedefNameForAnonDecl(decl);
-
-    decl->setAccess(clang::AS_public); // TODO respect proper access specifier
-
-    // Get a uniqued clang::QualType for the typedef decl type
-    return GetType(clang_ast.getTypedefType(decl));
-  }
-  return CompilerType();
-}
-
-CompilerType
-TypeSystemClang::GetTypedefedType(lldb::opaque_compiler_type_t type) {
-  if (type) {
-    const clang::TypedefType *typedef_type =
-        llvm::dyn_cast<clang::TypedefType>(GetQualType(type));
-    if (typedef_type)
-      return GetType(typedef_type->getDecl()->getUnderlyingType());
-  }
-  return CompilerType();
-}
-
-// Create related types using the current type's AST
-
-CompilerType TypeSystemClang::GetBasicTypeFromAST(lldb::BasicType basic_type) {
-  return TypeSystemClang::GetBasicType(basic_type);
-}
-// Exploring the type
-
-const llvm::fltSemantics &
-TypeSystemClang::GetFloatTypeSemantics(size_t byte_size) {
-  clang::ASTContext &ast = getASTContext();
-  const size_t bit_size = byte_size * 8;
-  if (bit_size == ast.getTypeSize(ast.FloatTy))
-    return ast.getFloatTypeSemantics(ast.FloatTy);
-  else if (bit_size == ast.getTypeSize(ast.DoubleTy))
-    return ast.getFloatTypeSemantics(ast.DoubleTy);
-  else if (bit_size == ast.getTypeSize(ast.LongDoubleTy))
-    return ast.getFloatTypeSemantics(ast.LongDoubleTy);
-  else if (bit_size == ast.getTypeSize(ast.HalfTy))
-    return ast.getFloatTypeSemantics(ast.HalfTy);
-  return llvm::APFloatBase::Bogus();
-}
-
-Optional<uint64_t>
-TypeSystemClang::GetBitSize(lldb::opaque_compiler_type_t type,
-                            ExecutionContextScope *exe_scope) {
-  if (GetCompleteType(type)) {
-    clang::QualType qual_type(GetCanonicalQualType(type));
-    const clang::Type::TypeClass type_class = qual_type->getTypeClass();
-    switch (type_class) {
-    case clang::Type::Record:
-      if (GetCompleteType(type))
-        return getASTContext().getTypeSize(qual_type);
-      else
-        return None;
-      break;
-
-    case clang::Type::ObjCInterface:
-    case clang::Type::ObjCObject: {
-      ExecutionContext exe_ctx(exe_scope);
-      Process *process = exe_ctx.GetProcessPtr();
-      if (process) {
-        ObjCLanguageRuntime *objc_runtime = ObjCLanguageRuntime::Get(*process);
-        if (objc_runtime) {
-          uint64_t bit_size = 0;
-          if (objc_runtime->GetTypeBitSize(GetType(qual_type), bit_size))
-            return bit_size;
-        }
-      } else {
-        static bool g_printed = false;
-        if (!g_printed) {
-          StreamString s;
-          DumpTypeDescription(type, &s);
-
-          llvm::outs() << "warning: trying to determine the size of type ";
-          llvm::outs() << s.GetString() << "\n";
-          llvm::outs() << "without a valid ExecutionContext. this is not "
-                          "reliable. please file a bug against LLDB.\n";
-          llvm::outs() << "backtrace:\n";
-          llvm::sys::PrintStackTrace(llvm::outs());
-          llvm::outs() << "\n";
-          g_printed = true;
-        }
-      }
-    }
-      LLVM_FALLTHROUGH;
-    default:
-      const uint32_t bit_size = getASTContext().getTypeSize(qual_type);
-      if (bit_size == 0) {
-        if (qual_type->isIncompleteArrayType())
-          return getASTContext().getTypeSize(
-              qual_type->getArrayElementTypeNoTypeQual()
-                  ->getCanonicalTypeUnqualified());
-      }
-      if (qual_type->isObjCObjectOrInterfaceType())
-        return bit_size +
-               getASTContext().getTypeSize(getASTContext().ObjCBuiltinClassTy);
-      // Function types actually have a size of 0, that's not an error.
-      if (qual_type->isFunctionProtoType())
-        return bit_size;
-      if (bit_size)
-        return bit_size;
-    }
-  }
-  return None;
-}
-
-llvm::Optional<size_t>
-TypeSystemClang::GetTypeBitAlign(lldb::opaque_compiler_type_t type,
-                                 ExecutionContextScope *exe_scope) {
-  if (GetCompleteType(type))
-    return getASTContext().getTypeAlign(GetQualType(type));
-  return {};
-}
-
-lldb::Encoding TypeSystemClang::GetEncoding(lldb::opaque_compiler_type_t type,
-                                            uint64_t &count) {
-  if (!type)
-    return lldb::eEncodingInvalid;
-
-  count = 1;
-  clang::QualType qual_type = RemoveWrappingTypes(GetCanonicalQualType(type));
-
-  switch (qual_type->getTypeClass()) {
-  case clang::Type::Atomic:
-  case clang::Type::Auto:
-  case clang::Type::Decltype:
-  case clang::Type::Elaborated:
-  case clang::Type::Paren:
-  case clang::Type::Typedef:
-  case clang::Type::TypeOf:
-  case clang::Type::TypeOfExpr:
-    llvm_unreachable("Handled in RemoveWrappingTypes!");
-
-  case clang::Type::UnaryTransform:
-    break;
-
-  case clang::Type::FunctionNoProto:
-  case clang::Type::FunctionProto:
-    break;
-
-  case clang::Type::IncompleteArray:
-  case clang::Type::VariableArray:
-    break;
-
-  case clang::Type::ConstantArray:
-    break;
-
-  case clang::Type::DependentVector:
-  case clang::Type::ExtVector:
-  case clang::Type::Vector:
-    // TODO: Set this to more than one???
-    break;
-
-  case clang::Type::Builtin:
-    switch (llvm::cast<clang::BuiltinType>(qual_type)->getKind()) {
-    case clang::BuiltinType::Void:
-      break;
-
-    case clang::BuiltinType::Bool:
-    case clang::BuiltinType::Char_S:
-    case clang::BuiltinType::SChar:
-    case clang::BuiltinType::WChar_S:
-    case clang::BuiltinType::Short:
-    case clang::BuiltinType::Int:
-    case clang::BuiltinType::Long:
-    case clang::BuiltinType::LongLong:
-    case clang::BuiltinType::Int128:
-      return lldb::eEncodingSint;
-
-    case clang::BuiltinType::Char_U:
-    case clang::BuiltinType::UChar:
-    case clang::BuiltinType::WChar_U:
-    case clang::BuiltinType::Char8:
-    case clang::BuiltinType::Char16:
-    case clang::BuiltinType::Char32:
-    case clang::BuiltinType::UShort:
-    case clang::BuiltinType::UInt:
-    case clang::BuiltinType::ULong:
-    case clang::BuiltinType::ULongLong:
-    case clang::BuiltinType::UInt128:
-      return lldb::eEncodingUint;
-
-    // Fixed point types. Note that they are currently ignored.
-    case clang::BuiltinType::ShortAccum:
-    case clang::BuiltinType::Accum:
-    case clang::BuiltinType::LongAccum:
-    case clang::BuiltinType::UShortAccum:
-    case clang::BuiltinType::UAccum:
-    case clang::BuiltinType::ULongAccum:
-    case clang::BuiltinType::ShortFract:
-    case clang::BuiltinType::Fract:
-    case clang::BuiltinType::LongFract:
-    case clang::BuiltinType::UShortFract:
-    case clang::BuiltinType::UFract:
-    case clang::BuiltinType::ULongFract:
-    case clang::BuiltinType::SatShortAccum:
-    case clang::BuiltinType::SatAccum:
-    case clang::BuiltinType::SatLongAccum:
-    case clang::BuiltinType::SatUShortAccum:
-    case clang::BuiltinType::SatUAccum:
-    case clang::BuiltinType::SatULongAccum:
-    case clang::BuiltinType::SatShortFract:
-    case clang::BuiltinType::SatFract:
-    case clang::BuiltinType::SatLongFract:
-    case clang::BuiltinType::SatUShortFract:
-    case clang::BuiltinType::SatUFract:
-    case clang::BuiltinType::SatULongFract:
-      break;
-
-    case clang::BuiltinType::Half:
-    case clang::BuiltinType::Float:
-    case clang::BuiltinType::Float16:
-    case clang::BuiltinType::Float128:
-    case clang::BuiltinType::Double:
-    case clang::BuiltinType::LongDouble:
-      return lldb::eEncodingIEEE754;
-
-    case clang::BuiltinType::ObjCClass:
-    case clang::BuiltinType::ObjCId:
-    case clang::BuiltinType::ObjCSel:
-      return lldb::eEncodingUint;
-
-    case clang::BuiltinType::NullPtr:
-      return lldb::eEncodingUint;
-
-    case clang::BuiltinType::Kind::ARCUnbridgedCast:
-    case clang::BuiltinType::Kind::BoundMember:
-    case clang::BuiltinType::Kind::BuiltinFn:
-    case clang::BuiltinType::Kind::Dependent:
-    case clang::BuiltinType::Kind::OCLClkEvent:
-    case clang::BuiltinType::Kind::OCLEvent:
-    case clang::BuiltinType::Kind::OCLImage1dRO:
-    case clang::BuiltinType::Kind::OCLImage1dWO:
-    case clang::BuiltinType::Kind::OCLImage1dRW:
-    case clang::BuiltinType::Kind::OCLImage1dArrayRO:
-    case clang::BuiltinType::Kind::OCLImage1dArrayWO:
-    case clang::BuiltinType::Kind::OCLImage1dArrayRW:
-    case clang::BuiltinType::Kind::OCLImage1dBufferRO:
-    case clang::BuiltinType::Kind::OCLImage1dBufferWO:
-    case clang::BuiltinType::Kind::OCLImage1dBufferRW:
-    case clang::BuiltinType::Kind::OCLImage2dRO:
-    case clang::BuiltinType::Kind::OCLImage2dWO:
-    case clang::BuiltinType::Kind::OCLImage2dRW:
-    case clang::BuiltinType::Kind::OCLImage2dArrayRO:
-    case clang::BuiltinType::Kind::OCLImage2dArrayWO:
-    case clang::BuiltinType::Kind::OCLImage2dArrayRW:
-    case clang::BuiltinType::Kind::OCLImage2dArrayDepthRO:
-    case clang::BuiltinType::Kind::OCLImage2dArrayDepthWO:
-    case clang::BuiltinType::Kind::OCLImage2dArrayDepthRW:
-    case clang::BuiltinType::Kind::OCLImage2dArrayMSAARO:
-    case clang::BuiltinType::Kind::OCLImage2dArrayMSAAWO:
-    case clang::BuiltinType::Kind::OCLImage2dArrayMSAARW:
-    case clang::BuiltinType::Kind::OCLImage2dArrayMSAADepthRO:
-    case clang::BuiltinType::Kind::OCLImage2dArrayMSAADepthWO:
-    case clang::BuiltinType::Kind::OCLImage2dArrayMSAADepthRW:
-    case clang::BuiltinType::Kind::OCLImage2dDepthRO:
-    case clang::BuiltinType::Kind::OCLImage2dDepthWO:
-    case clang::BuiltinType::Kind::OCLImage2dDepthRW:
-    case clang::BuiltinType::Kind::OCLImage2dMSAARO:
-    case clang::BuiltinType::Kind::OCLImage2dMSAAWO:
-    case clang::BuiltinType::Kind::OCLImage2dMSAARW:
-    case clang::BuiltinType::Kind::OCLImage2dMSAADepthRO:
-    case clang::BuiltinType::Kind::OCLImage2dMSAADepthWO:
-    case clang::BuiltinType::Kind::OCLImage2dMSAADepthRW:
-    case clang::BuiltinType::Kind::OCLImage3dRO:
-    case clang::BuiltinType::Kind::OCLImage3dWO:
-    case clang::BuiltinType::Kind::OCLImage3dRW:
-    case clang::BuiltinType::Kind::OCLQueue:
-    case clang::BuiltinType::Kind::OCLReserveID:
-    case clang::BuiltinType::Kind::OCLSampler:
-    case clang::BuiltinType::Kind::OMPArraySection:
-    case clang::BuiltinType::Kind::Overload:
-    case clang::BuiltinType::Kind::PseudoObject:
-    case clang::BuiltinType::Kind::UnknownAny:
-      break;
-
-    case clang::BuiltinType::OCLIntelSubgroupAVCMcePayload:
-    case clang::BuiltinType::OCLIntelSubgroupAVCImePayload:
-    case clang::BuiltinType::OCLIntelSubgroupAVCRefPayload:
-    case clang::BuiltinType::OCLIntelSubgroupAVCSicPayload:
-    case clang::BuiltinType::OCLIntelSubgroupAVCMceResult:
-    case clang::BuiltinType::OCLIntelSubgroupAVCImeResult:
-    case clang::BuiltinType::OCLIntelSubgroupAVCRefResult:
-    case clang::BuiltinType::OCLIntelSubgroupAVCSicResult:
-    case clang::BuiltinType::OCLIntelSubgroupAVCImeResultSingleRefStreamout:
-    case clang::BuiltinType::OCLIntelSubgroupAVCImeResultDualRefStreamout:
-    case clang::BuiltinType::OCLIntelSubgroupAVCImeSingleRefStreamin:
-    case clang::BuiltinType::OCLIntelSubgroupAVCImeDualRefStreamin:
-      break;
-
-    case clang::BuiltinType::SveBool:
-    case clang::BuiltinType::SveInt8:
-    case clang::BuiltinType::SveInt16:
-    case clang::BuiltinType::SveInt32:
-    case clang::BuiltinType::SveInt64:
-    case clang::BuiltinType::SveUint8:
-    case clang::BuiltinType::SveUint16:
-    case clang::BuiltinType::SveUint32:
-    case clang::BuiltinType::SveUint64:
-    case clang::BuiltinType::SveFloat16:
-    case clang::BuiltinType::SveFloat32:
-    case clang::BuiltinType::SveFloat64:
-      break;
-    }
-    break;
-  // All pointer types are represented as unsigned integer encodings. We may
-  // nee to add a eEncodingPointer if we ever need to know the difference
-  case clang::Type::ObjCObjectPointer:
-  case clang::Type::BlockPointer:
-  case clang::Type::Pointer:
-  case clang::Type::LValueReference:
-  case clang::Type::RValueReference:
-  case clang::Type::MemberPointer:
-    return lldb::eEncodingUint;
-  case clang::Type::Complex: {
-    lldb::Encoding encoding = lldb::eEncodingIEEE754;
-    if (qual_type->isComplexType())
-      encoding = lldb::eEncodingIEEE754;
-    else {
-      const clang::ComplexType *complex_type =
-          qual_type->getAsComplexIntegerType();
-      if (complex_type)
-        encoding = GetType(complex_type->getElementType()).GetEncoding(count);
-      else
-        encoding = lldb::eEncodingSint;
-    }
-    count = 2;
-    return encoding;
-  }
-
-  case clang::Type::ObjCInterface:
-    break;
-  case clang::Type::Record:
-    break;
-  case clang::Type::Enum:
-    return lldb::eEncodingSint;
-  case clang::Type::DependentSizedArray:
-  case clang::Type::DependentSizedExtVector:
-  case clang::Type::UnresolvedUsing:
-  case clang::Type::Attributed:
-  case clang::Type::TemplateTypeParm:
-  case clang::Type::SubstTemplateTypeParm:
-  case clang::Type::SubstTemplateTypeParmPack:
-  case clang::Type::InjectedClassName:
-  case clang::Type::DependentName:
-  case clang::Type::DependentTemplateSpecialization:
-  case clang::Type::PackExpansion:
-  case clang::Type::ObjCObject:
-
-  case clang::Type::TemplateSpecialization:
-  case clang::Type::DeducedTemplateSpecialization:
-  case clang::Type::Adjusted:
-  case clang::Type::Pipe:
-    break;
-
-  // pointer type decayed from an array or function type.
-  case clang::Type::Decayed:
-    break;
-  case clang::Type::ObjCTypeParam:
-    break;
-
-  case clang::Type::DependentAddressSpace:
-    break;
-  case clang::Type::MacroQualified:
-    break;
-  }
-  count = 0;
-  return lldb::eEncodingInvalid;
-}
-
-lldb::Format TypeSystemClang::GetFormat(lldb::opaque_compiler_type_t type) {
-  if (!type)
-    return lldb::eFormatDefault;
-
-  clang::QualType qual_type = RemoveWrappingTypes(GetCanonicalQualType(type));
-
-  switch (qual_type->getTypeClass()) {
-  case clang::Type::Atomic:
-  case clang::Type::Auto:
-  case clang::Type::Decltype:
-  case clang::Type::Elaborated:
-  case clang::Type::Paren:
-  case clang::Type::Typedef:
-  case clang::Type::TypeOf:
-  case clang::Type::TypeOfExpr:
-    llvm_unreachable("Handled in RemoveWrappingTypes!");
-  case clang::Type::UnaryTransform:
-    break;
-
-  case clang::Type::FunctionNoProto:
-  case clang::Type::FunctionProto:
-    break;
-
-  case clang::Type::IncompleteArray:
-  case clang::Type::VariableArray:
-    break;
-
-  case clang::Type::ConstantArray:
-    return lldb::eFormatVoid; // no value
-
-  case clang::Type::DependentVector:
-  case clang::Type::ExtVector:
-  case clang::Type::Vector:
-    break;
-
-  case clang::Type::Builtin:
-    switch (llvm::cast<clang::BuiltinType>(qual_type)->getKind()) {
-    // default: assert(0 && "Unknown builtin type!");
-    case clang::BuiltinType::UnknownAny:
-    case clang::BuiltinType::Void:
-    case clang::BuiltinType::BoundMember:
-      break;
-
-    case clang::BuiltinType::Bool:
-      return lldb::eFormatBoolean;
-    case clang::BuiltinType::Char_S:
-    case clang::BuiltinType::SChar:
-    case clang::BuiltinType::WChar_S:
-    case clang::BuiltinType::Char_U:
-    case clang::BuiltinType::UChar:
-    case clang::BuiltinType::WChar_U:
-      return lldb::eFormatChar;
-    case clang::BuiltinType::Char16:
-      return lldb::eFormatUnicode16;
-    case clang::BuiltinType::Char32:
-      return lldb::eFormatUnicode32;
-    case clang::BuiltinType::UShort:
-      return lldb::eFormatUnsigned;
-    case clang::BuiltinType::Short:
-      return lldb::eFormatDecimal;
-    case clang::BuiltinType::UInt:
-      return lldb::eFormatUnsigned;
-    case clang::BuiltinType::Int:
-      return lldb::eFormatDecimal;
-    case clang::BuiltinType::ULong:
-      return lldb::eFormatUnsigned;
-    case clang::BuiltinType::Long:
-      return lldb::eFormatDecimal;
-    case clang::BuiltinType::ULongLong:
-      return lldb::eFormatUnsigned;
-    case clang::BuiltinType::LongLong:
-      return lldb::eFormatDecimal;
-    case clang::BuiltinType::UInt128:
-      return lldb::eFormatUnsigned;
-    case clang::BuiltinType::Int128:
-      return lldb::eFormatDecimal;
-    case clang::BuiltinType::Half:
-    case clang::BuiltinType::Float:
-    case clang::BuiltinType::Double:
-    case clang::BuiltinType::LongDouble:
-      return lldb::eFormatFloat;
-    default:
-      return lldb::eFormatHex;
-    }
-    break;
-  case clang::Type::ObjCObjectPointer:
-    return lldb::eFormatHex;
-  case clang::Type::BlockPointer:
-    return lldb::eFormatHex;
-  case clang::Type::Pointer:
-    return lldb::eFormatHex;
-  case clang::Type::LValueReference:
-  case clang::Type::RValueReference:
-    return lldb::eFormatHex;
-  case clang::Type::MemberPointer:
-    break;
-  case clang::Type::Complex: {
-    if (qual_type->isComplexType())
-      return lldb::eFormatComplex;
-    else
-      return lldb::eFormatComplexInteger;
-  }
-  case clang::Type::ObjCInterface:
-    break;
-  case clang::Type::Record:
-    break;
-  case clang::Type::Enum:
-    return lldb::eFormatEnum;
-  case clang::Type::DependentSizedArray:
-  case clang::Type::DependentSizedExtVector:
-  case clang::Type::UnresolvedUsing:
-  case clang::Type::Attributed:
-  case clang::Type::TemplateTypeParm:
-  case clang::Type::SubstTemplateTypeParm:
-  case clang::Type::SubstTemplateTypeParmPack:
-  case clang::Type::InjectedClassName:
-  case clang::Type::DependentName:
-  case clang::Type::DependentTemplateSpecialization:
-  case clang::Type::PackExpansion:
-  case clang::Type::ObjCObject:
-
-  case clang::Type::TemplateSpecialization:
-  case clang::Type::DeducedTemplateSpecialization:
-  case clang::Type::Adjusted:
-  case clang::Type::Pipe:
-    break;
-
-  // pointer type decayed from an array or function type.
-  case clang::Type::Decayed:
-    break;
-  case clang::Type::ObjCTypeParam:
-    break;
-
-  case clang::Type::DependentAddressSpace:
-    break;
-  case clang::Type::MacroQualified:
-    break;
-  }
-  // We don't know hot to display this type...
-  return lldb::eFormatBytes;
-}
-
-static bool ObjCDeclHasIVars(clang::ObjCInterfaceDecl *class_interface_decl,
-                             bool check_superclass) {
-  while (class_interface_decl) {
-    if (class_interface_decl->ivar_size() > 0)
-      return true;
-
-    if (check_superclass)
-      class_interface_decl = class_interface_decl->getSuperClass();
-    else
-      break;
-  }
-  return false;
-}
-
-static Optional<SymbolFile::ArrayInfo>
-GetDynamicArrayInfo(TypeSystemClang &ast, SymbolFile *sym_file,
-                    clang::QualType qual_type,
-                    const ExecutionContext *exe_ctx) {
-  if (qual_type->isIncompleteArrayType())
-    if (auto *metadata = ast.GetMetadata(qual_type.getTypePtr()))
-      return sym_file->GetDynamicArrayInfoForUID(metadata->GetUserID(),
-                                                 exe_ctx);
-  return llvm::None;
-}
-
-uint32_t TypeSystemClang::GetNumChildren(lldb::opaque_compiler_type_t type,
-                                         bool omit_empty_base_classes,
-                                         const ExecutionContext *exe_ctx) {
-  if (!type)
-    return 0;
-
-  uint32_t num_children = 0;
-  clang::QualType qual_type(RemoveWrappingTypes(GetQualType(type)));
-  const clang::Type::TypeClass type_class = qual_type->getTypeClass();
-  switch (type_class) {
-  case clang::Type::Builtin:
-    switch (llvm::cast<clang::BuiltinType>(qual_type)->getKind()) {
-    case clang::BuiltinType::ObjCId:    // child is Class
-    case clang::BuiltinType::ObjCClass: // child is Class
-      num_children = 1;
-      break;
-
-    default:
-      break;
-    }
-    break;
-
-  case clang::Type::Complex:
-    return 0;
-  case clang::Type::Record:
-    if (GetCompleteQualType(&getASTContext(), qual_type)) {
-      const clang::RecordType *record_type =
-          llvm::cast<clang::RecordType>(qual_type.getTypePtr());
-      const clang::RecordDecl *record_decl = record_type->getDecl();
-      assert(record_decl);
-      const clang::CXXRecordDecl *cxx_record_decl =
-          llvm::dyn_cast<clang::CXXRecordDecl>(record_decl);
-      if (cxx_record_decl) {
-        if (omit_empty_base_classes) {
-          // Check each base classes to see if it or any of its base classes
-          // contain any fields. This can help limit the noise in variable
-          // views by not having to show base classes that contain no members.
-          clang::CXXRecordDecl::base_class_const_iterator base_class,
-              base_class_end;
-          for (base_class = cxx_record_decl->bases_begin(),
-              base_class_end = cxx_record_decl->bases_end();
-               base_class != base_class_end; ++base_class) {
-            const clang::CXXRecordDecl *base_class_decl =
-                llvm::cast<clang::CXXRecordDecl>(
-                    base_class->getType()
-                        ->getAs<clang::RecordType>()
-                        ->getDecl());
-
-            // Skip empty base classes
-            if (!TypeSystemClang::RecordHasFields(base_class_decl))
-              continue;
-
-            num_children++;
-          }
-        } else {
-          // Include all base classes
-          num_children += cxx_record_decl->getNumBases();
-        }
-      }
-      clang::RecordDecl::field_iterator field, field_end;
-      for (field = record_decl->field_begin(),
-          field_end = record_decl->field_end();
-           field != field_end; ++field)
-        ++num_children;
-    }
-    break;
-
-  case clang::Type::ObjCObject:
-  case clang::Type::ObjCInterface:
-    if (GetCompleteQualType(&getASTContext(), qual_type)) {
-      const clang::ObjCObjectType *objc_class_type =
-          llvm::dyn_cast<clang::ObjCObjectType>(qual_type.getTypePtr());
-      assert(objc_class_type);
-      if (objc_class_type) {
-        clang::ObjCInterfaceDecl *class_interface_decl =
-            objc_class_type->getInterface();
-
-        if (class_interface_decl) {
-
-          clang::ObjCInterfaceDecl *superclass_interface_decl =
-              class_interface_decl->getSuperClass();
-          if (superclass_interface_decl) {
-            if (omit_empty_base_classes) {
-              if (ObjCDeclHasIVars(superclass_interface_decl, true))
-                ++num_children;
-            } else
-              ++num_children;
-          }
-
-          num_children += class_interface_decl->ivar_size();
-        }
-      }
-    }
-    break;
-
-  case clang::Type::ObjCObjectPointer: {
-    const clang::ObjCObjectPointerType *pointer_type =
-        llvm::cast<clang::ObjCObjectPointerType>(qual_type.getTypePtr());
-    clang::QualType pointee_type = pointer_type->getPointeeType();
-    uint32_t num_pointee_children =
-        GetType(pointee_type).GetNumChildren(omit_empty_base_classes, exe_ctx);
-    // If this type points to a simple type, then it has 1 child
-    if (num_pointee_children == 0)
-      num_children = 1;
-    else
-      num_children = num_pointee_children;
-  } break;
-
-  case clang::Type::Vector:
-  case clang::Type::ExtVector:
-    num_children =
-        llvm::cast<clang::VectorType>(qual_type.getTypePtr())->getNumElements();
-    break;
-
-  case clang::Type::ConstantArray:
-    num_children = llvm::cast<clang::ConstantArrayType>(qual_type.getTypePtr())
-                       ->getSize()
-                       .getLimitedValue();
-    break;
-  case clang::Type::IncompleteArray:
-    if (auto array_info =
-            GetDynamicArrayInfo(*this, GetSymbolFile(), qual_type, exe_ctx))
-      // Only 1-dimensional arrays are supported.
-      num_children = array_info->element_orders.size()
-                         ? array_info->element_orders.back()
-                         : 0;
-    break;
-
-  case clang::Type::Pointer: {
-    const clang::PointerType *pointer_type =
-        llvm::cast<clang::PointerType>(qual_type.getTypePtr());
-    clang::QualType pointee_type(pointer_type->getPointeeType());
-    uint32_t num_pointee_children =
-        GetType(pointee_type).GetNumChildren(omit_empty_base_classes, exe_ctx);
-    if (num_pointee_children == 0) {
-      // We have a pointer to a pointee type that claims it has no children. We
-      // will want to look at
-      num_children = GetNumPointeeChildren(pointee_type);
-    } else
-      num_children = num_pointee_children;
-  } break;
-
-  case clang::Type::LValueReference:
-  case clang::Type::RValueReference: {
-    const clang::ReferenceType *reference_type =
-        llvm::cast<clang::ReferenceType>(qual_type.getTypePtr());
-    clang::QualType pointee_type = reference_type->getPointeeType();
-    uint32_t num_pointee_children =
-        GetType(pointee_type).GetNumChildren(omit_empty_base_classes, exe_ctx);
-    // If this type points to a simple type, then it has 1 child
-    if (num_pointee_children == 0)
-      num_children = 1;
-    else
-      num_children = num_pointee_children;
-  } break;
-
-  default:
-    break;
-  }
-  return num_children;
-}
-
-CompilerType TypeSystemClang::GetBuiltinTypeByName(ConstString name) {
-  return GetBasicType(GetBasicTypeEnumeration(name));
-}
-
-lldb::BasicType
-TypeSystemClang::GetBasicTypeEnumeration(lldb::opaque_compiler_type_t type) {
-  if (type) {
-    clang::QualType qual_type(GetQualType(type));
-    const clang::Type::TypeClass type_class = qual_type->getTypeClass();
-    if (type_class == clang::Type::Builtin) {
-      switch (llvm::cast<clang::BuiltinType>(qual_type)->getKind()) {
-      case clang::BuiltinType::Void:
-        return eBasicTypeVoid;
-      case clang::BuiltinType::Bool:
-        return eBasicTypeBool;
-      case clang::BuiltinType::Char_S:
-        return eBasicTypeSignedChar;
-      case clang::BuiltinType::Char_U:
-        return eBasicTypeUnsignedChar;
-      case clang::BuiltinType::Char16:
-        return eBasicTypeChar16;
-      case clang::BuiltinType::Char32:
-        return eBasicTypeChar32;
-      case clang::BuiltinType::UChar:
-        return eBasicTypeUnsignedChar;
-      case clang::BuiltinType::SChar:
-        return eBasicTypeSignedChar;
-      case clang::BuiltinType::WChar_S:
-        return eBasicTypeSignedWChar;
-      case clang::BuiltinType::WChar_U:
-        return eBasicTypeUnsignedWChar;
-      case clang::BuiltinType::Short:
-        return eBasicTypeShort;
-      case clang::BuiltinType::UShort:
-        return eBasicTypeUnsignedShort;
-      case clang::BuiltinType::Int:
-        return eBasicTypeInt;
-      case clang::BuiltinType::UInt:
-        return eBasicTypeUnsignedInt;
-      case clang::BuiltinType::Long:
-        return eBasicTypeLong;
-      case clang::BuiltinType::ULong:
-        return eBasicTypeUnsignedLong;
-      case clang::BuiltinType::LongLong:
-        return eBasicTypeLongLong;
-      case clang::BuiltinType::ULongLong:
-        return eBasicTypeUnsignedLongLong;
-      case clang::BuiltinType::Int128:
-        return eBasicTypeInt128;
-      case clang::BuiltinType::UInt128:
-        return eBasicTypeUnsignedInt128;
-
-      case clang::BuiltinType::Half:
-        return eBasicTypeHalf;
-      case clang::BuiltinType::Float:
-        return eBasicTypeFloat;
-      case clang::BuiltinType::Double:
-        return eBasicTypeDouble;
-      case clang::BuiltinType::LongDouble:
-        return eBasicTypeLongDouble;
-
-      case clang::BuiltinType::NullPtr:
-        return eBasicTypeNullPtr;
-      case clang::BuiltinType::ObjCId:
-        return eBasicTypeObjCID;
-      case clang::BuiltinType::ObjCClass:
-        return eBasicTypeObjCClass;
-      case clang::BuiltinType::ObjCSel:
-        return eBasicTypeObjCSel;
-      default:
-        return eBasicTypeOther;
-      }
-    }
-  }
-  return eBasicTypeInvalid;
-}
-
-void TypeSystemClang::ForEachEnumerator(
-    lldb::opaque_compiler_type_t type,
-    std::function<bool(const CompilerType &integer_type,
-                       ConstString name,
-                       const llvm::APSInt &value)> const &callback) {
-  const clang::EnumType *enum_type =
-      llvm::dyn_cast<clang::EnumType>(GetCanonicalQualType(type));
-  if (enum_type) {
-    const clang::EnumDecl *enum_decl = enum_type->getDecl();
-    if (enum_decl) {
-      CompilerType integer_type = GetType(enum_decl->getIntegerType());
-
-      clang::EnumDecl::enumerator_iterator enum_pos, enum_end_pos;
-      for (enum_pos = enum_decl->enumerator_begin(),
-          enum_end_pos = enum_decl->enumerator_end();
-           enum_pos != enum_end_pos; ++enum_pos) {
-        ConstString name(enum_pos->getNameAsString().c_str());
-        if (!callback(integer_type, name, enum_pos->getInitVal()))
-          break;
-      }
-    }
-  }
-}
-
-#pragma mark Aggregate Types
-
-uint32_t TypeSystemClang::GetNumFields(lldb::opaque_compiler_type_t type) {
-  if (!type)
-    return 0;
-
-  uint32_t count = 0;
-  clang::QualType qual_type(RemoveWrappingTypes(GetCanonicalQualType(type)));
-  const clang::Type::TypeClass type_class = qual_type->getTypeClass();
-  switch (type_class) {
-  case clang::Type::Record:
-    if (GetCompleteType(type)) {
-      const clang::RecordType *record_type =
-          llvm::dyn_cast<clang::RecordType>(qual_type.getTypePtr());
-      if (record_type) {
-        clang::RecordDecl *record_decl = record_type->getDecl();
-        if (record_decl) {
-          uint32_t field_idx = 0;
-          clang::RecordDecl::field_iterator field, field_end;
-          for (field = record_decl->field_begin(),
-              field_end = record_decl->field_end();
-               field != field_end; ++field)
-            ++field_idx;
-          count = field_idx;
-        }
-      }
-    }
-    break;
-
-  case clang::Type::ObjCObjectPointer: {
-    const clang::ObjCObjectPointerType *objc_class_type =
-        qual_type->getAs<clang::ObjCObjectPointerType>();
-    const clang::ObjCInterfaceType *objc_interface_type =
-        objc_class_type->getInterfaceType();
-    if (objc_interface_type &&
-        GetCompleteType(static_cast<lldb::opaque_compiler_type_t>(
-            const_cast<clang::ObjCInterfaceType *>(objc_interface_type)))) {
-      clang::ObjCInterfaceDecl *class_interface_decl =
-          objc_interface_type->getDecl();
-      if (class_interface_decl) {
-        count = class_interface_decl->ivar_size();
-      }
-    }
-    break;
-  }
-
-  case clang::Type::ObjCObject:
-  case clang::Type::ObjCInterface:
-    if (GetCompleteType(type)) {
-      const clang::ObjCObjectType *objc_class_type =
-          llvm::dyn_cast<clang::ObjCObjectType>(qual_type.getTypePtr());
-      if (objc_class_type) {
-        clang::ObjCInterfaceDecl *class_interface_decl =
-            objc_class_type->getInterface();
-
-        if (class_interface_decl)
-          count = class_interface_decl->ivar_size();
-      }
-    }
-    break;
-
-  default:
-    break;
-  }
-  return count;
-}
-
-static lldb::opaque_compiler_type_t
-GetObjCFieldAtIndex(clang::ASTContext *ast,
-                    clang::ObjCInterfaceDecl *class_interface_decl, size_t idx,
-                    std::string &name, uint64_t *bit_offset_ptr,
-                    uint32_t *bitfield_bit_size_ptr, bool *is_bitfield_ptr) {
-  if (class_interface_decl) {
-    if (idx < (class_interface_decl->ivar_size())) {
-      clang::ObjCInterfaceDecl::ivar_iterator ivar_pos,
-          ivar_end = class_interface_decl->ivar_end();
-      uint32_t ivar_idx = 0;
-
-      for (ivar_pos = class_interface_decl->ivar_begin(); ivar_pos != ivar_end;
-           ++ivar_pos, ++ivar_idx) {
-        if (ivar_idx == idx) {
-          const clang::ObjCIvarDecl *ivar_decl = *ivar_pos;
-
-          clang::QualType ivar_qual_type(ivar_decl->getType());
-
-          name.assign(ivar_decl->getNameAsString());
-
-          if (bit_offset_ptr) {
-            const clang::ASTRecordLayout &interface_layout =
-                ast->getASTObjCInterfaceLayout(class_interface_decl);
-            *bit_offset_ptr = interface_layout.getFieldOffset(ivar_idx);
-          }
-
-          const bool is_bitfield = ivar_pos->isBitField();
-
-          if (bitfield_bit_size_ptr) {
-            *bitfield_bit_size_ptr = 0;
-
-            if (is_bitfield && ast) {
-              clang::Expr *bitfield_bit_size_expr = ivar_pos->getBitWidth();
-              clang::Expr::EvalResult result;
-              if (bitfield_bit_size_expr &&
-                  bitfield_bit_size_expr->EvaluateAsInt(result, *ast)) {
-                llvm::APSInt bitfield_apsint = result.Val.getInt();
-                *bitfield_bit_size_ptr = bitfield_apsint.getLimitedValue();
-              }
-            }
-          }
-          if (is_bitfield_ptr)
-            *is_bitfield_ptr = is_bitfield;
-
-          return ivar_qual_type.getAsOpaquePtr();
-        }
-      }
-    }
-  }
-  return nullptr;
-}
-
-CompilerType TypeSystemClang::GetFieldAtIndex(lldb::opaque_compiler_type_t type,
-                                              size_t idx, std::string &name,
-                                              uint64_t *bit_offset_ptr,
-                                              uint32_t *bitfield_bit_size_ptr,
-                                              bool *is_bitfield_ptr) {
-  if (!type)
-    return CompilerType();
-
-  clang::QualType qual_type(RemoveWrappingTypes(GetCanonicalQualType(type)));
-  const clang::Type::TypeClass type_class = qual_type->getTypeClass();
-  switch (type_class) {
-  case clang::Type::Record:
-    if (GetCompleteType(type)) {
-      const clang::RecordType *record_type =
-          llvm::cast<clang::RecordType>(qual_type.getTypePtr());
-      const clang::RecordDecl *record_decl = record_type->getDecl();
-      uint32_t field_idx = 0;
-      clang::RecordDecl::field_iterator field, field_end;
-      for (field = record_decl->field_begin(),
-          field_end = record_decl->field_end();
-           field != field_end; ++field, ++field_idx) {
-        if (idx == field_idx) {
-          // Print the member type if requested
-          // Print the member name and equal sign
-          name.assign(field->getNameAsString());
-
-          // Figure out the type byte size (field_type_info.first) and
-          // alignment (field_type_info.second) from the AST context.
-          if (bit_offset_ptr) {
-            const clang::ASTRecordLayout &record_layout =
-                getASTContext().getASTRecordLayout(record_decl);
-            *bit_offset_ptr = record_layout.getFieldOffset(field_idx);
-          }
-
-          const bool is_bitfield = field->isBitField();
-
-          if (bitfield_bit_size_ptr) {
-            *bitfield_bit_size_ptr = 0;
-
-            if (is_bitfield) {
-              clang::Expr *bitfield_bit_size_expr = field->getBitWidth();
-              clang::Expr::EvalResult result;
-              if (bitfield_bit_size_expr &&
-                  bitfield_bit_size_expr->EvaluateAsInt(result,
-                                                        getASTContext())) {
-                llvm::APSInt bitfield_apsint = result.Val.getInt();
-                *bitfield_bit_size_ptr = bitfield_apsint.getLimitedValue();
-              }
-            }
-          }
-          if (is_bitfield_ptr)
-            *is_bitfield_ptr = is_bitfield;
-
-          return GetType(field->getType());
-        }
-      }
-    }
-    break;
-
-  case clang::Type::ObjCObjectPointer: {
-    const clang::ObjCObjectPointerType *objc_class_type =
-        qual_type->getAs<clang::ObjCObjectPointerType>();
-    const clang::ObjCInterfaceType *objc_interface_type =
-        objc_class_type->getInterfaceType();
-    if (objc_interface_type &&
-        GetCompleteType(static_cast<lldb::opaque_compiler_type_t>(
-            const_cast<clang::ObjCInterfaceType *>(objc_interface_type)))) {
-      clang::ObjCInterfaceDecl *class_interface_decl =
-          objc_interface_type->getDecl();
-      if (class_interface_decl) {
-        return CompilerType(
-            this, GetObjCFieldAtIndex(&getASTContext(), class_interface_decl,
-                                      idx, name, bit_offset_ptr,
-                                      bitfield_bit_size_ptr, is_bitfield_ptr));
-      }
-    }
-    break;
-  }
-
-  case clang::Type::ObjCObject:
-  case clang::Type::ObjCInterface:
-    if (GetCompleteType(type)) {
-      const clang::ObjCObjectType *objc_class_type =
-          llvm::dyn_cast<clang::ObjCObjectType>(qual_type.getTypePtr());
-      assert(objc_class_type);
-      if (objc_class_type) {
-        clang::ObjCInterfaceDecl *class_interface_decl =
-            objc_class_type->getInterface();
-        return CompilerType(
-            this, GetObjCFieldAtIndex(&getASTContext(), class_interface_decl,
-                                      idx, name, bit_offset_ptr,
-                                      bitfield_bit_size_ptr, is_bitfield_ptr));
-      }
-    }
-    break;
-
-  default:
-    break;
-  }
-  return CompilerType();
-}
-
-uint32_t
-TypeSystemClang::GetNumDirectBaseClasses(lldb::opaque_compiler_type_t type) {
-  uint32_t count = 0;
-  clang::QualType qual_type = RemoveWrappingTypes(GetCanonicalQualType(type));
-  const clang::Type::TypeClass type_class = qual_type->getTypeClass();
-  switch (type_class) {
-  case clang::Type::Record:
-    if (GetCompleteType(type)) {
-      const clang::CXXRecordDecl *cxx_record_decl =
-          qual_type->getAsCXXRecordDecl();
-      if (cxx_record_decl)
-        count = cxx_record_decl->getNumBases();
-    }
-    break;
-
-  case clang::Type::ObjCObjectPointer:
-    count = GetPointeeType(type).GetNumDirectBaseClasses();
-    break;
-
-  case clang::Type::ObjCObject:
-    if (GetCompleteType(type)) {
-      const clang::ObjCObjectType *objc_class_type =
-          qual_type->getAsObjCQualifiedInterfaceType();
-      if (objc_class_type) {
-        clang::ObjCInterfaceDecl *class_interface_decl =
-            objc_class_type->getInterface();
-
-        if (class_interface_decl && class_interface_decl->getSuperClass())
-          count = 1;
-      }
-    }
-    break;
-  case clang::Type::ObjCInterface:
-    if (GetCompleteType(type)) {
-      const clang::ObjCInterfaceType *objc_interface_type =
-          qual_type->getAs<clang::ObjCInterfaceType>();
-      if (objc_interface_type) {
-        clang::ObjCInterfaceDecl *class_interface_decl =
-            objc_interface_type->getInterface();
-
-        if (class_interface_decl && class_interface_decl->getSuperClass())
-          count = 1;
-      }
-    }
-    break;
-
-  default:
-    break;
-  }
-  return count;
-}
-
-uint32_t
-TypeSystemClang::GetNumVirtualBaseClasses(lldb::opaque_compiler_type_t type) {
-  uint32_t count = 0;
-  clang::QualType qual_type = RemoveWrappingTypes(GetCanonicalQualType(type));
-  const clang::Type::TypeClass type_class = qual_type->getTypeClass();
-  switch (type_class) {
-  case clang::Type::Record:
-    if (GetCompleteType(type)) {
-      const clang::CXXRecordDecl *cxx_record_decl =
-          qual_type->getAsCXXRecordDecl();
-      if (cxx_record_decl)
-        count = cxx_record_decl->getNumVBases();
-    }
-    break;
-
-  default:
-    break;
-  }
-  return count;
-}
-
-CompilerType TypeSystemClang::GetDirectBaseClassAtIndex(
-    lldb::opaque_compiler_type_t type, size_t idx, uint32_t *bit_offset_ptr) {
-  clang::QualType qual_type = RemoveWrappingTypes(GetCanonicalQualType(type));
-  const clang::Type::TypeClass type_class = qual_type->getTypeClass();
-  switch (type_class) {
-  case clang::Type::Record:
-    if (GetCompleteType(type)) {
-      const clang::CXXRecordDecl *cxx_record_decl =
-          qual_type->getAsCXXRecordDecl();
-      if (cxx_record_decl) {
-        uint32_t curr_idx = 0;
-        clang::CXXRecordDecl::base_class_const_iterator base_class,
-            base_class_end;
-        for (base_class = cxx_record_decl->bases_begin(),
-            base_class_end = cxx_record_decl->bases_end();
-             base_class != base_class_end; ++base_class, ++curr_idx) {
-          if (curr_idx == idx) {
-            if (bit_offset_ptr) {
-              const clang::ASTRecordLayout &record_layout =
-                  getASTContext().getASTRecordLayout(cxx_record_decl);
-              const clang::CXXRecordDecl *base_class_decl =
-                  llvm::cast<clang::CXXRecordDecl>(
-                      base_class->getType()
-                          ->getAs<clang::RecordType>()
-                          ->getDecl());
-              if (base_class->isVirtual())
-                *bit_offset_ptr =
-                    record_layout.getVBaseClassOffset(base_class_decl)
-                        .getQuantity() *
-                    8;
-              else
-                *bit_offset_ptr =
-                    record_layout.getBaseClassOffset(base_class_decl)
-                        .getQuantity() *
-                    8;
-            }
-            return GetType(base_class->getType());
-          }
-        }
-      }
-    }
-    break;
-
-  case clang::Type::ObjCObjectPointer:
-    return GetPointeeType(type).GetDirectBaseClassAtIndex(idx, bit_offset_ptr);
-
-  case clang::Type::ObjCObject:
-    if (idx == 0 && GetCompleteType(type)) {
-      const clang::ObjCObjectType *objc_class_type =
-          qual_type->getAsObjCQualifiedInterfaceType();
-      if (objc_class_type) {
-        clang::ObjCInterfaceDecl *class_interface_decl =
-            objc_class_type->getInterface();
-
-        if (class_interface_decl) {
-          clang::ObjCInterfaceDecl *superclass_interface_decl =
-              class_interface_decl->getSuperClass();
-          if (superclass_interface_decl) {
-            if (bit_offset_ptr)
-              *bit_offset_ptr = 0;
-            return GetType(getASTContext().getObjCInterfaceType(
-                superclass_interface_decl));
-          }
-        }
-      }
-    }
-    break;
-  case clang::Type::ObjCInterface:
-    if (idx == 0 && GetCompleteType(type)) {
-      const clang::ObjCObjectType *objc_interface_type =
-          qual_type->getAs<clang::ObjCInterfaceType>();
-      if (objc_interface_type) {
-        clang::ObjCInterfaceDecl *class_interface_decl =
-            objc_interface_type->getInterface();
-
-        if (class_interface_decl) {
-          clang::ObjCInterfaceDecl *superclass_interface_decl =
-              class_interface_decl->getSuperClass();
-          if (superclass_interface_decl) {
-            if (bit_offset_ptr)
-              *bit_offset_ptr = 0;
-            return GetType(getASTContext().getObjCInterfaceType(
-                superclass_interface_decl));
-          }
-        }
-      }
-    }
-    break;
-
-  default:
-    break;
-  }
-  return CompilerType();
-}
-
-CompilerType TypeSystemClang::GetVirtualBaseClassAtIndex(
-    lldb::opaque_compiler_type_t type, size_t idx, uint32_t *bit_offset_ptr) {
-  clang::QualType qual_type = RemoveWrappingTypes(GetCanonicalQualType(type));
-  const clang::Type::TypeClass type_class = qual_type->getTypeClass();
-  switch (type_class) {
-  case clang::Type::Record:
-    if (GetCompleteType(type)) {
-      const clang::CXXRecordDecl *cxx_record_decl =
-          qual_type->getAsCXXRecordDecl();
-      if (cxx_record_decl) {
-        uint32_t curr_idx = 0;
-        clang::CXXRecordDecl::base_class_const_iterator base_class,
-            base_class_end;
-        for (base_class = cxx_record_decl->vbases_begin(),
-            base_class_end = cxx_record_decl->vbases_end();
-             base_class != base_class_end; ++base_class, ++curr_idx) {
-          if (curr_idx == idx) {
-            if (bit_offset_ptr) {
-              const clang::ASTRecordLayout &record_layout =
-                  getASTContext().getASTRecordLayout(cxx_record_decl);
-              const clang::CXXRecordDecl *base_class_decl =
-                  llvm::cast<clang::CXXRecordDecl>(
-                      base_class->getType()
-                          ->getAs<clang::RecordType>()
-                          ->getDecl());
-              *bit_offset_ptr =
-                  record_layout.getVBaseClassOffset(base_class_decl)
-                      .getQuantity() *
-                  8;
-            }
-            return GetType(base_class->getType());
-          }
-        }
-      }
-    }
-    break;
-
-  default:
-    break;
-  }
-  return CompilerType();
-}
-
-// If a pointer to a pointee type (the clang_type arg) says that it has no
-// children, then we either need to trust it, or override it and return a
-// different result. For example, an "int *" has one child that is an integer,
-// but a function pointer doesn't have any children. Likewise if a Record type
-// claims it has no children, then there really is nothing to show.
-uint32_t TypeSystemClang::GetNumPointeeChildren(clang::QualType type) {
-  if (type.isNull())
-    return 0;
-
-  clang::QualType qual_type = RemoveWrappingTypes(type.getCanonicalType());
-  const clang::Type::TypeClass type_class = qual_type->getTypeClass();
-  switch (type_class) {
-  case clang::Type::Builtin:
-    switch (llvm::cast<clang::BuiltinType>(qual_type)->getKind()) {
-    case clang::BuiltinType::UnknownAny:
-    case clang::BuiltinType::Void:
-    case clang::BuiltinType::NullPtr:
-    case clang::BuiltinType::OCLEvent:
-    case clang::BuiltinType::OCLImage1dRO:
-    case clang::BuiltinType::OCLImage1dWO:
-    case clang::BuiltinType::OCLImage1dRW:
-    case clang::BuiltinType::OCLImage1dArrayRO:
-    case clang::BuiltinType::OCLImage1dArrayWO:
-    case clang::BuiltinType::OCLImage1dArrayRW:
-    case clang::BuiltinType::OCLImage1dBufferRO:
-    case clang::BuiltinType::OCLImage1dBufferWO:
-    case clang::BuiltinType::OCLImage1dBufferRW:
-    case clang::BuiltinType::OCLImage2dRO:
-    case clang::BuiltinType::OCLImage2dWO:
-    case clang::BuiltinType::OCLImage2dRW:
-    case clang::BuiltinType::OCLImage2dArrayRO:
-    case clang::BuiltinType::OCLImage2dArrayWO:
-    case clang::BuiltinType::OCLImage2dArrayRW:
-    case clang::BuiltinType::OCLImage3dRO:
-    case clang::BuiltinType::OCLImage3dWO:
-    case clang::BuiltinType::OCLImage3dRW:
-    case clang::BuiltinType::OCLSampler:
-      return 0;
-    case clang::BuiltinType::Bool:
-    case clang::BuiltinType::Char_U:
-    case clang::BuiltinType::UChar:
-    case clang::BuiltinType::WChar_U:
-    case clang::BuiltinType::Char16:
-    case clang::BuiltinType::Char32:
-    case clang::BuiltinType::UShort:
-    case clang::BuiltinType::UInt:
-    case clang::BuiltinType::ULong:
-    case clang::BuiltinType::ULongLong:
-    case clang::BuiltinType::UInt128:
-    case clang::BuiltinType::Char_S:
-    case clang::BuiltinType::SChar:
-    case clang::BuiltinType::WChar_S:
-    case clang::BuiltinType::Short:
-    case clang::BuiltinType::Int:
-    case clang::BuiltinType::Long:
-    case clang::BuiltinType::LongLong:
-    case clang::BuiltinType::Int128:
-    case clang::BuiltinType::Float:
-    case clang::BuiltinType::Double:
-    case clang::BuiltinType::LongDouble:
-    case clang::BuiltinType::Dependent:
-    case clang::BuiltinType::Overload:
-    case clang::BuiltinType::ObjCId:
-    case clang::BuiltinType::ObjCClass:
-    case clang::BuiltinType::ObjCSel:
-    case clang::BuiltinType::BoundMember:
-    case clang::BuiltinType::Half:
-    case clang::BuiltinType::ARCUnbridgedCast:
-    case clang::BuiltinType::PseudoObject:
-    case clang::BuiltinType::BuiltinFn:
-    case clang::BuiltinType::OMPArraySection:
-      return 1;
-    default:
-      return 0;
-    }
-    break;
-
-  case clang::Type::Complex:
-    return 1;
-  case clang::Type::Pointer:
-    return 1;
-  case clang::Type::BlockPointer:
-    return 0; // If block pointers don't have debug info, then no children for
-              // them
-  case clang::Type::LValueReference:
-    return 1;
-  case clang::Type::RValueReference:
-    return 1;
-  case clang::Type::MemberPointer:
-    return 0;
-  case clang::Type::ConstantArray:
-    return 0;
-  case clang::Type::IncompleteArray:
-    return 0;
-  case clang::Type::VariableArray:
-    return 0;
-  case clang::Type::DependentSizedArray:
-    return 0;
-  case clang::Type::DependentSizedExtVector:
-    return 0;
-  case clang::Type::Vector:
-    return 0;
-  case clang::Type::ExtVector:
-    return 0;
-  case clang::Type::FunctionProto:
-    return 0; // When we function pointers, they have no children...
-  case clang::Type::FunctionNoProto:
-    return 0; // When we function pointers, they have no children...
-  case clang::Type::UnresolvedUsing:
-    return 0;
-  case clang::Type::Record:
-    return 0;
-  case clang::Type::Enum:
-    return 1;
-  case clang::Type::TemplateTypeParm:
-    return 1;
-  case clang::Type::SubstTemplateTypeParm:
-    return 1;
-  case clang::Type::TemplateSpecialization:
-    return 1;
-  case clang::Type::InjectedClassName:
-    return 0;
-  case clang::Type::DependentName:
-    return 1;
-  case clang::Type::DependentTemplateSpecialization:
-    return 1;
-  case clang::Type::ObjCObject:
-    return 0;
-  case clang::Type::ObjCInterface:
-    return 0;
-  case clang::Type::ObjCObjectPointer:
-    return 1;
-  default:
-    break;
-  }
-  return 0;
-}
-
-CompilerType TypeSystemClang::GetChildCompilerTypeAtIndex(
-    lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx, size_t idx,
-    bool transparent_pointers, bool omit_empty_base_classes,
-    bool ignore_array_bounds, std::string &child_name,
-    uint32_t &child_byte_size, int32_t &child_byte_offset,
-    uint32_t &child_bitfield_bit_size, uint32_t &child_bitfield_bit_offset,
-    bool &child_is_base_class, bool &child_is_deref_of_parent,
-    ValueObject *valobj, uint64_t &language_flags) {
-  if (!type)
-    return CompilerType();
-
-  auto get_exe_scope = [&exe_ctx]() {
-    return exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr;
-  };
-
-  clang::QualType parent_qual_type(
-      RemoveWrappingTypes(GetCanonicalQualType(type)));
-  const clang::Type::TypeClass parent_type_class =
-      parent_qual_type->getTypeClass();
-  child_bitfield_bit_size = 0;
-  child_bitfield_bit_offset = 0;
-  child_is_base_class = false;
-  language_flags = 0;
-
-  const bool idx_is_valid =
-      idx < GetNumChildren(type, omit_empty_base_classes, exe_ctx);
-  int32_t bit_offset;
-  switch (parent_type_class) {
-  case clang::Type::Builtin:
-    if (idx_is_valid) {
-      switch (llvm::cast<clang::BuiltinType>(parent_qual_type)->getKind()) {
-      case clang::BuiltinType::ObjCId:
-      case clang::BuiltinType::ObjCClass:
-        child_name = "isa";
-        child_byte_size =
-            getASTContext().getTypeSize(getASTContext().ObjCBuiltinClassTy) /
-            CHAR_BIT;
-        return GetType(getASTContext().ObjCBuiltinClassTy);
-
-      default:
-        break;
-      }
-    }
-    break;
-
-  case clang::Type::Record:
-    if (idx_is_valid && GetCompleteType(type)) {
-      const clang::RecordType *record_type =
-          llvm::cast<clang::RecordType>(parent_qual_type.getTypePtr());
-      const clang::RecordDecl *record_decl = record_type->getDecl();
-      assert(record_decl);
-      const clang::ASTRecordLayout &record_layout =
-          getASTContext().getASTRecordLayout(record_decl);
-      uint32_t child_idx = 0;
-
-      const clang::CXXRecordDecl *cxx_record_decl =
-          llvm::dyn_cast<clang::CXXRecordDecl>(record_decl);
-      if (cxx_record_decl) {
-        // We might have base classes to print out first
-        clang::CXXRecordDecl::base_class_const_iterator base_class,
-            base_class_end;
-        for (base_class = cxx_record_decl->bases_begin(),
-            base_class_end = cxx_record_decl->bases_end();
-             base_class != base_class_end; ++base_class) {
-          const clang::CXXRecordDecl *base_class_decl = nullptr;
-
-          // Skip empty base classes
-          if (omit_empty_base_classes) {
-            base_class_decl = llvm::cast<clang::CXXRecordDecl>(
-                base_class->getType()->getAs<clang::RecordType>()->getDecl());
-            if (!TypeSystemClang::RecordHasFields(base_class_decl))
-              continue;
-          }
-
-          if (idx == child_idx) {
-            if (base_class_decl == nullptr)
-              base_class_decl = llvm::cast<clang::CXXRecordDecl>(
-                  base_class->getType()->getAs<clang::RecordType>()->getDecl());
-
-            if (base_class->isVirtual()) {
-              bool handled = false;
-              if (valobj) {
-                clang::VTableContextBase *vtable_ctx =
-                    getASTContext().getVTableContext();
-                if (vtable_ctx)
-                  handled = GetVBaseBitOffset(*vtable_ctx, *valobj,
-                                              record_layout, cxx_record_decl,
-                                              base_class_decl, bit_offset);
-              }
-              if (!handled)
-                bit_offset = record_layout.getVBaseClassOffset(base_class_decl)
-                                 .getQuantity() *
-                             8;
-            } else
-              bit_offset = record_layout.getBaseClassOffset(base_class_decl)
-                               .getQuantity() *
-                           8;
-
-            // Base classes should be a multiple of 8 bits in size
-            child_byte_offset = bit_offset / 8;
-            CompilerType base_class_clang_type = GetType(base_class->getType());
-            child_name = base_class_clang_type.GetTypeName().AsCString("");
-            Optional<uint64_t> size =
-                base_class_clang_type.GetBitSize(get_exe_scope());
-            if (!size)
-              return {};
-            uint64_t base_class_clang_type_bit_size = *size;
-
-            // Base classes bit sizes should be a multiple of 8 bits in size
-            assert(base_class_clang_type_bit_size % 8 == 0);
-            child_byte_size = base_class_clang_type_bit_size / 8;
-            child_is_base_class = true;
-            return base_class_clang_type;
-          }
-          // We don't increment the child index in the for loop since we might
-          // be skipping empty base classes
-          ++child_idx;
-        }
-      }
-      // Make sure index is in range...
-      uint32_t field_idx = 0;
-      clang::RecordDecl::field_iterator field, field_end;
-      for (field = record_decl->field_begin(),
-          field_end = record_decl->field_end();
-           field != field_end; ++field, ++field_idx, ++child_idx) {
-        if (idx == child_idx) {
-          // Print the member type if requested
-          // Print the member name and equal sign
-          child_name.assign(field->getNameAsString());
-
-          // Figure out the type byte size (field_type_info.first) and
-          // alignment (field_type_info.second) from the AST context.
-          CompilerType field_clang_type = GetType(field->getType());
-          assert(field_idx < record_layout.getFieldCount());
-          Optional<uint64_t> size =
-              field_clang_type.GetByteSize(get_exe_scope());
-          if (!size)
-            return {};
-          child_byte_size = *size;
-          const uint32_t child_bit_size = child_byte_size * 8;
-
-          // Figure out the field offset within the current struct/union/class
-          // type
-          bit_offset = record_layout.getFieldOffset(field_idx);
-          if (FieldIsBitfield(*field, child_bitfield_bit_size)) {
-            child_bitfield_bit_offset = bit_offset % child_bit_size;
-            const uint32_t child_bit_offset =
-                bit_offset - child_bitfield_bit_offset;
-            child_byte_offset = child_bit_offset / 8;
-          } else {
-            child_byte_offset = bit_offset / 8;
-          }
-
-          return field_clang_type;
-        }
-      }
-    }
-    break;
-
-  case clang::Type::ObjCObject:
-  case clang::Type::ObjCInterface:
-    if (idx_is_valid && GetCompleteType(type)) {
-      const clang::ObjCObjectType *objc_class_type =
-          llvm::dyn_cast<clang::ObjCObjectType>(parent_qual_type.getTypePtr());
-      assert(objc_class_type);
-      if (objc_class_type) {
-        uint32_t child_idx = 0;
-        clang::ObjCInterfaceDecl *class_interface_decl =
-            objc_class_type->getInterface();
-
-        if (class_interface_decl) {
-
-          const clang::ASTRecordLayout &interface_layout =
-              getASTContext().getASTObjCInterfaceLayout(class_interface_decl);
-          clang::ObjCInterfaceDecl *superclass_interface_decl =
-              class_interface_decl->getSuperClass();
-          if (superclass_interface_decl) {
-            if (omit_empty_base_classes) {
-              CompilerType base_class_clang_type =
-                  GetType(getASTContext().getObjCInterfaceType(
-                      superclass_interface_decl));
-              if (base_class_clang_type.GetNumChildren(omit_empty_base_classes,
-                                                       exe_ctx) > 0) {
-                if (idx == 0) {
-                  clang::QualType ivar_qual_type(
-                      getASTContext().getObjCInterfaceType(
-                          superclass_interface_decl));
-
-                  child_name.assign(
-                      superclass_interface_decl->getNameAsString());
-
-                  clang::TypeInfo ivar_type_info =
-                      getASTContext().getTypeInfo(ivar_qual_type.getTypePtr());
-
-                  child_byte_size = ivar_type_info.Width / 8;
-                  child_byte_offset = 0;
-                  child_is_base_class = true;
-
-                  return GetType(ivar_qual_type);
-                }
-
-                ++child_idx;
-              }
-            } else
-              ++child_idx;
-          }
-
-          const uint32_t superclass_idx = child_idx;
-
-          if (idx < (child_idx + class_interface_decl->ivar_size())) {
-            clang::ObjCInterfaceDecl::ivar_iterator ivar_pos,
-                ivar_end = class_interface_decl->ivar_end();
-
-            for (ivar_pos = class_interface_decl->ivar_begin();
-                 ivar_pos != ivar_end; ++ivar_pos) {
-              if (child_idx == idx) {
-                clang::ObjCIvarDecl *ivar_decl = *ivar_pos;
-
-                clang::QualType ivar_qual_type(ivar_decl->getType());
-
-                child_name.assign(ivar_decl->getNameAsString());
-
-                clang::TypeInfo ivar_type_info =
-                    getASTContext().getTypeInfo(ivar_qual_type.getTypePtr());
-
-                child_byte_size = ivar_type_info.Width / 8;
-
-                // Figure out the field offset within the current
-                // struct/union/class type For ObjC objects, we can't trust the
-                // bit offset we get from the Clang AST, since that doesn't
-                // account for the space taken up by unbacked properties, or
-                // from the changing size of base classes that are newer than
-                // this class. So if we have a process around that we can ask
-                // about this object, do so.
-                child_byte_offset = LLDB_INVALID_IVAR_OFFSET;
-                Process *process = nullptr;
-                if (exe_ctx)
-                  process = exe_ctx->GetProcessPtr();
-                if (process) {
-                  ObjCLanguageRuntime *objc_runtime =
-                      ObjCLanguageRuntime::Get(*process);
-                  if (objc_runtime != nullptr) {
-                    CompilerType parent_ast_type = GetType(parent_qual_type);
-                    child_byte_offset = objc_runtime->GetByteOffsetForIvar(
-                        parent_ast_type, ivar_decl->getNameAsString().c_str());
-                  }
-                }
-
-                // Setting this to INT32_MAX to make sure we don't compute it
-                // twice...
-                bit_offset = INT32_MAX;
-
-                if (child_byte_offset ==
-                    static_cast<int32_t>(LLDB_INVALID_IVAR_OFFSET)) {
-                  bit_offset = interface_layout.getFieldOffset(child_idx -
-                                                               superclass_idx);
-                  child_byte_offset = bit_offset / 8;
-                }
-
-                // Note, the ObjC Ivar Byte offset is just that, it doesn't
-                // account for the bit offset of a bitfield within its
-                // containing object.  So regardless of where we get the byte
-                // offset from, we still need to get the bit offset for
-                // bitfields from the layout.
-
-                if (FieldIsBitfield(ivar_decl, child_bitfield_bit_size)) {
-                  if (bit_offset == INT32_MAX)
-                    bit_offset = interface_layout.getFieldOffset(
-                        child_idx - superclass_idx);
-
-                  child_bitfield_bit_offset = bit_offset % 8;
-                }
-                return GetType(ivar_qual_type);
-              }
-              ++child_idx;
-            }
-          }
-        }
-      }
-    }
-    break;
-
-  case clang::Type::ObjCObjectPointer:
-    if (idx_is_valid) {
-      CompilerType pointee_clang_type(GetPointeeType(type));
-
-      if (transparent_pointers && pointee_clang_type.IsAggregateType()) {
-        child_is_deref_of_parent = false;
-        bool tmp_child_is_deref_of_parent = false;
-        return pointee_clang_type.GetChildCompilerTypeAtIndex(
-            exe_ctx, idx, transparent_pointers, omit_empty_base_classes,
-            ignore_array_bounds, child_name, child_byte_size, child_byte_offset,
-            child_bitfield_bit_size, child_bitfield_bit_offset,
-            child_is_base_class, tmp_child_is_deref_of_parent, valobj,
-            language_flags);
-      } else {
-        child_is_deref_of_parent = true;
-        const char *parent_name =
-            valobj ? valobj->GetName().GetCString() : nullptr;
-        if (parent_name) {
-          child_name.assign(1, '*');
-          child_name += parent_name;
-        }
-
-        // We have a pointer to an simple type
-        if (idx == 0 && pointee_clang_type.GetCompleteType()) {
-          if (Optional<uint64_t> size =
-                  pointee_clang_type.GetByteSize(get_exe_scope())) {
-            child_byte_size = *size;
-            child_byte_offset = 0;
-            return pointee_clang_type;
-          }
-        }
-      }
-    }
-    break;
-
-  case clang::Type::Vector:
-  case clang::Type::ExtVector:
-    if (idx_is_valid) {
-      const clang::VectorType *array =
-          llvm::cast<clang::VectorType>(parent_qual_type.getTypePtr());
-      if (array) {
-        CompilerType element_type = GetType(array->getElementType());
-        if (element_type.GetCompleteType()) {
-          char element_name[64];
-          ::snprintf(element_name, sizeof(element_name), "[%" PRIu64 "]",
-                     static_cast<uint64_t>(idx));
-          child_name.assign(element_name);
-          if (Optional<uint64_t> size =
-                  element_type.GetByteSize(get_exe_scope())) {
-            child_byte_size = *size;
-            child_byte_offset = (int32_t)idx * (int32_t)child_byte_size;
-            return element_type;
-          }
-        }
-      }
-    }
-    break;
-
-  case clang::Type::ConstantArray:
-  case clang::Type::IncompleteArray:
-    if (ignore_array_bounds || idx_is_valid) {
-      const clang::ArrayType *array = GetQualType(type)->getAsArrayTypeUnsafe();
-      if (array) {
-        CompilerType element_type = GetType(array->getElementType());
-        if (element_type.GetCompleteType()) {
-          child_name = std::string(llvm::formatv("[{0}]", idx));
-          if (Optional<uint64_t> size =
-                  element_type.GetByteSize(get_exe_scope())) {
-            child_byte_size = *size;
-            child_byte_offset = (int32_t)idx * (int32_t)child_byte_size;
-            return element_type;
-          }
-        }
-      }
-    }
-    break;
-
-  case clang::Type::Pointer: {
-    CompilerType pointee_clang_type(GetPointeeType(type));
-
-    // Don't dereference "void *" pointers
-    if (pointee_clang_type.IsVoidType())
-      return CompilerType();
-
-    if (transparent_pointers && pointee_clang_type.IsAggregateType()) {
-      child_is_deref_of_parent = false;
-      bool tmp_child_is_deref_of_parent = false;
-      return pointee_clang_type.GetChildCompilerTypeAtIndex(
-          exe_ctx, idx, transparent_pointers, omit_empty_base_classes,
-          ignore_array_bounds, child_name, child_byte_size, child_byte_offset,
-          child_bitfield_bit_size, child_bitfield_bit_offset,
-          child_is_base_class, tmp_child_is_deref_of_parent, valobj,
-          language_flags);
-    } else {
-      child_is_deref_of_parent = true;
-
-      const char *parent_name =
-          valobj ? valobj->GetName().GetCString() : nullptr;
-      if (parent_name) {
-        child_name.assign(1, '*');
-        child_name += parent_name;
-      }
-
-      // We have a pointer to an simple type
-      if (idx == 0) {
-        if (Optional<uint64_t> size =
-                pointee_clang_type.GetByteSize(get_exe_scope())) {
-          child_byte_size = *size;
-          child_byte_offset = 0;
-          return pointee_clang_type;
-        }
-      }
-    }
-    break;
-  }
-
-  case clang::Type::LValueReference:
-  case clang::Type::RValueReference:
-    if (idx_is_valid) {
-      const clang::ReferenceType *reference_type =
-          llvm::cast<clang::ReferenceType>(parent_qual_type.getTypePtr());
-      CompilerType pointee_clang_type =
-          GetType(reference_type->getPointeeType());
-      if (transparent_pointers && pointee_clang_type.IsAggregateType()) {
-        child_is_deref_of_parent = false;
-        bool tmp_child_is_deref_of_parent = false;
-        return pointee_clang_type.GetChildCompilerTypeAtIndex(
-            exe_ctx, idx, transparent_pointers, omit_empty_base_classes,
-            ignore_array_bounds, child_name, child_byte_size, child_byte_offset,
-            child_bitfield_bit_size, child_bitfield_bit_offset,
-            child_is_base_class, tmp_child_is_deref_of_parent, valobj,
-            language_flags);
-      } else {
-        const char *parent_name =
-            valobj ? valobj->GetName().GetCString() : nullptr;
-        if (parent_name) {
-          child_name.assign(1, '&');
-          child_name += parent_name;
-        }
-
-        // We have a pointer to an simple type
-        if (idx == 0) {
-          if (Optional<uint64_t> size =
-                  pointee_clang_type.GetByteSize(get_exe_scope())) {
-            child_byte_size = *size;
-            child_byte_offset = 0;
-            return pointee_clang_type;
-          }
-        }
-      }
-    }
-    break;
-
-  default:
-    break;
-  }
-  return CompilerType();
-}
-
-static uint32_t GetIndexForRecordBase(const clang::RecordDecl *record_decl,
-                                      const clang::CXXBaseSpecifier *base_spec,
-                                      bool omit_empty_base_classes) {
-  uint32_t child_idx = 0;
-
-  const clang::CXXRecordDecl *cxx_record_decl =
-      llvm::dyn_cast<clang::CXXRecordDecl>(record_decl);
-
-  //    const char *super_name = record_decl->getNameAsCString();
-  //    const char *base_name =
-  //    base_spec->getType()->getAs<clang::RecordType>()->getDecl()->getNameAsCString();
-  //    printf ("GetIndexForRecordChild (%s, %s)\n", super_name, base_name);
-  //
-  if (cxx_record_decl) {
-    clang::CXXRecordDecl::base_class_const_iterator base_class, base_class_end;
-    for (base_class = cxx_record_decl->bases_begin(),
-        base_class_end = cxx_record_decl->bases_end();
-         base_class != base_class_end; ++base_class) {
-      if (omit_empty_base_classes) {
-        if (BaseSpecifierIsEmpty(base_class))
-          continue;
-      }
-
-      //            printf ("GetIndexForRecordChild (%s, %s) base[%u] = %s\n",
-      //            super_name, base_name,
-      //                    child_idx,
-      //                    base_class->getType()->getAs<clang::RecordType>()->getDecl()->getNameAsCString());
-      //
-      //
-      if (base_class == base_spec)
-        return child_idx;
-      ++child_idx;
-    }
-  }
-
-  return UINT32_MAX;
-}
-
-static uint32_t GetIndexForRecordChild(const clang::RecordDecl *record_decl,
-                                       clang::NamedDecl *canonical_decl,
-                                       bool omit_empty_base_classes) {
-  uint32_t child_idx = TypeSystemClang::GetNumBaseClasses(
-      llvm::dyn_cast<clang::CXXRecordDecl>(record_decl),
-      omit_empty_base_classes);
-
-  clang::RecordDecl::field_iterator field, field_end;
-  for (field = record_decl->field_begin(), field_end = record_decl->field_end();
-       field != field_end; ++field, ++child_idx) {
-    if (field->getCanonicalDecl() == canonical_decl)
-      return child_idx;
-  }
-
-  return UINT32_MAX;
-}
-
-// Look for a child member (doesn't include base classes, but it does include
-// their members) in the type hierarchy. Returns an index path into
-// "clang_type" on how to reach the appropriate member.
-//
-//    class A
-//    {
-//    public:
-//        int m_a;
-//        int m_b;
-//    };
-//
-//    class B
-//    {
-//    };
-//
-//    class C :
-//        public B,
-//        public A
-//    {
-//    };
-//
-// If we have a clang type that describes "class C", and we wanted to looked
-// "m_b" in it:
-//
-// With omit_empty_base_classes == false we would get an integer array back
-// with: { 1,  1 } The first index 1 is the child index for "class A" within
-// class C The second index 1 is the child index for "m_b" within class A
-//
-// With omit_empty_base_classes == true we would get an integer array back
-// with: { 0,  1 } The first index 0 is the child index for "class A" within
-// class C (since class B doesn't have any members it doesn't count) The second
-// index 1 is the child index for "m_b" within class A
-
-size_t TypeSystemClang::GetIndexOfChildMemberWithName(
-    lldb::opaque_compiler_type_t type, const char *name,
-    bool omit_empty_base_classes, std::vector<uint32_t> &child_indexes) {
-  if (type && name && name[0]) {
-    clang::QualType qual_type = RemoveWrappingTypes(GetCanonicalQualType(type));
-    const clang::Type::TypeClass type_class = qual_type->getTypeClass();
-    switch (type_class) {
-    case clang::Type::Record:
-      if (GetCompleteType(type)) {
-        const clang::RecordType *record_type =
-            llvm::cast<clang::RecordType>(qual_type.getTypePtr());
-        const clang::RecordDecl *record_decl = record_type->getDecl();
-
-        assert(record_decl);
-        uint32_t child_idx = 0;
-
-        const clang::CXXRecordDecl *cxx_record_decl =
-            llvm::dyn_cast<clang::CXXRecordDecl>(record_decl);
-
-        // Try and find a field that matches NAME
-        clang::RecordDecl::field_iterator field, field_end;
-        llvm::StringRef name_sref(name);
-        for (field = record_decl->field_begin(),
-            field_end = record_decl->field_end();
-             field != field_end; ++field, ++child_idx) {
-          llvm::StringRef field_name = field->getName();
-          if (field_name.empty()) {
-            CompilerType field_type = GetType(field->getType());
-            child_indexes.push_back(child_idx);
-            if (field_type.GetIndexOfChildMemberWithName(
-                    name, omit_empty_base_classes, child_indexes))
-              return child_indexes.size();
-            child_indexes.pop_back();
-
-          } else if (field_name.equals(name_sref)) {
-            // We have to add on the number of base classes to this index!
-            child_indexes.push_back(
-                child_idx + TypeSystemClang::GetNumBaseClasses(
-                                cxx_record_decl, omit_empty_base_classes));
-            return child_indexes.size();
-          }
-        }
-
-        if (cxx_record_decl) {
-          const clang::RecordDecl *parent_record_decl = cxx_record_decl;
-
-          // printf ("parent = %s\n", parent_record_decl->getNameAsCString());
-
-          // const Decl *root_cdecl = cxx_record_decl->getCanonicalDecl();
-          // Didn't find things easily, lets let clang do its thang...
-          clang::IdentifierInfo &ident_ref =
-              getASTContext().Idents.get(name_sref);
-          clang::DeclarationName decl_name(&ident_ref);
-
-          clang::CXXBasePaths paths;
-          if (cxx_record_decl->lookupInBases(
-                  [decl_name](const clang::CXXBaseSpecifier *specifier,
-                              clang::CXXBasePath &path) {
-                    return clang::CXXRecordDecl::FindOrdinaryMember(
-                        specifier, path, decl_name);
-                  },
-                  paths)) {
-            clang::CXXBasePaths::const_paths_iterator path,
-                path_end = paths.end();
-            for (path = paths.begin(); path != path_end; ++path) {
-              const size_t num_path_elements = path->size();
-              for (size_t e = 0; e < num_path_elements; ++e) {
-                clang::CXXBasePathElement elem = (*path)[e];
-
-                child_idx = GetIndexForRecordBase(parent_record_decl, elem.Base,
-                                                  omit_empty_base_classes);
-                if (child_idx == UINT32_MAX) {
-                  child_indexes.clear();
-                  return 0;
-                } else {
-                  child_indexes.push_back(child_idx);
-                  parent_record_decl = llvm::cast<clang::RecordDecl>(
-                      elem.Base->getType()
-                          ->getAs<clang::RecordType>()
-                          ->getDecl());
-                }
-              }
-              for (clang::NamedDecl *path_decl : path->Decls) {
-                child_idx = GetIndexForRecordChild(
-                    parent_record_decl, path_decl, omit_empty_base_classes);
-                if (child_idx == UINT32_MAX) {
-                  child_indexes.clear();
-                  return 0;
-                } else {
-                  child_indexes.push_back(child_idx);
-                }
-              }
-            }
-            return child_indexes.size();
-          }
-        }
-      }
-      break;
-
-    case clang::Type::ObjCObject:
-    case clang::Type::ObjCInterface:
-      if (GetCompleteType(type)) {
-        llvm::StringRef name_sref(name);
-        const clang::ObjCObjectType *objc_class_type =
-            llvm::dyn_cast<clang::ObjCObjectType>(qual_type.getTypePtr());
-        assert(objc_class_type);
-        if (objc_class_type) {
-          uint32_t child_idx = 0;
-          clang::ObjCInterfaceDecl *class_interface_decl =
-              objc_class_type->getInterface();
-
-          if (class_interface_decl) {
-            clang::ObjCInterfaceDecl::ivar_iterator ivar_pos,
-                ivar_end = class_interface_decl->ivar_end();
-            clang::ObjCInterfaceDecl *superclass_interface_decl =
-                class_interface_decl->getSuperClass();
-
-            for (ivar_pos = class_interface_decl->ivar_begin();
-                 ivar_pos != ivar_end; ++ivar_pos, ++child_idx) {
-              const clang::ObjCIvarDecl *ivar_decl = *ivar_pos;
-
-              if (ivar_decl->getName().equals(name_sref)) {
-                if ((!omit_empty_base_classes && superclass_interface_decl) ||
-                    (omit_empty_base_classes &&
-                     ObjCDeclHasIVars(superclass_interface_decl, true)))
-                  ++child_idx;
-
-                child_indexes.push_back(child_idx);
-                return child_indexes.size();
-              }
-            }
-
-            if (superclass_interface_decl) {
-              // The super class index is always zero for ObjC classes, so we
-              // push it onto the child indexes in case we find an ivar in our
-              // superclass...
-              child_indexes.push_back(0);
-
-              CompilerType superclass_clang_type =
-                  GetType(getASTContext().getObjCInterfaceType(
-                      superclass_interface_decl));
-              if (superclass_clang_type.GetIndexOfChildMemberWithName(
-                      name, omit_empty_base_classes, child_indexes)) {
-                // We did find an ivar in a superclass so just return the
-                // results!
-                return child_indexes.size();
-              }
-
-              // We didn't find an ivar matching "name" in our superclass, pop
-              // the superclass zero index that we pushed on above.
-              child_indexes.pop_back();
-            }
-          }
-        }
-      }
-      break;
-
-    case clang::Type::ObjCObjectPointer: {
-      CompilerType objc_object_clang_type = GetType(
-          llvm::cast<clang::ObjCObjectPointerType>(qual_type.getTypePtr())
-              ->getPointeeType());
-      return objc_object_clang_type.GetIndexOfChildMemberWithName(
-          name, omit_empty_base_classes, child_indexes);
-    } break;
-
-    case clang::Type::ConstantArray: {
-      //                const clang::ConstantArrayType *array =
-      //                llvm::cast<clang::ConstantArrayType>(parent_qual_type.getTypePtr());
-      //                const uint64_t element_count =
-      //                array->getSize().getLimitedValue();
-      //
-      //                if (idx < element_count)
-      //                {
-      //                    std::pair<uint64_t, unsigned> field_type_info =
-      //                    ast->getTypeInfo(array->getElementType());
-      //
-      //                    char element_name[32];
-      //                    ::snprintf (element_name, sizeof (element_name),
-      //                    "%s[%u]", parent_name ? parent_name : "", idx);
-      //
-      //                    child_name.assign(element_name);
-      //                    assert(field_type_info.first % 8 == 0);
-      //                    child_byte_size = field_type_info.first / 8;
-      //                    child_byte_offset = idx * child_byte_size;
-      //                    return array->getElementType().getAsOpaquePtr();
-      //                }
-    } break;
-
-    //        case clang::Type::MemberPointerType:
-    //            {
-    //                MemberPointerType *mem_ptr_type =
-    //                llvm::cast<MemberPointerType>(qual_type.getTypePtr());
-    //                clang::QualType pointee_type =
-    //                mem_ptr_type->getPointeeType();
-    //
-    //                if (TypeSystemClang::IsAggregateType
-    //                (pointee_type.getAsOpaquePtr()))
-    //                {
-    //                    return GetIndexOfChildWithName (ast,
-    //                                                    mem_ptr_type->getPointeeType().getAsOpaquePtr(),
-    //                                                    name);
-    //                }
-    //            }
-    //            break;
-    //
-    case clang::Type::LValueReference:
-    case clang::Type::RValueReference: {
-      const clang::ReferenceType *reference_type =
-          llvm::cast<clang::ReferenceType>(qual_type.getTypePtr());
-      clang::QualType pointee_type(reference_type->getPointeeType());
-      CompilerType pointee_clang_type = GetType(pointee_type);
-
-      if (pointee_clang_type.IsAggregateType()) {
-        return pointee_clang_type.GetIndexOfChildMemberWithName(
-            name, omit_empty_base_classes, child_indexes);
-      }
-    } break;
-
-    case clang::Type::Pointer: {
-      CompilerType pointee_clang_type(GetPointeeType(type));
-
-      if (pointee_clang_type.IsAggregateType()) {
-        return pointee_clang_type.GetIndexOfChildMemberWithName(
-            name, omit_empty_base_classes, child_indexes);
-      }
-    } break;
-
-    default:
-      break;
-    }
-  }
-  return 0;
-}
-
-// Get the index of the child of "clang_type" whose name matches. This function
-// doesn't descend into the children, but only looks one level deep and name
-// matches can include base class names.
-
-uint32_t
-TypeSystemClang::GetIndexOfChildWithName(lldb::opaque_compiler_type_t type,
-                                         const char *name,
-                                         bool omit_empty_base_classes) {
-  if (type && name && name[0]) {
-    clang::QualType qual_type = RemoveWrappingTypes(GetCanonicalQualType(type));
-
-    const clang::Type::TypeClass type_class = qual_type->getTypeClass();
-
-    switch (type_class) {
-    case clang::Type::Record:
-      if (GetCompleteType(type)) {
-        const clang::RecordType *record_type =
-            llvm::cast<clang::RecordType>(qual_type.getTypePtr());
-        const clang::RecordDecl *record_decl = record_type->getDecl();
-
-        assert(record_decl);
-        uint32_t child_idx = 0;
-
-        const clang::CXXRecordDecl *cxx_record_decl =
-            llvm::dyn_cast<clang::CXXRecordDecl>(record_decl);
-
-        if (cxx_record_decl) {
-          clang::CXXRecordDecl::base_class_const_iterator base_class,
-              base_class_end;
-          for (base_class = cxx_record_decl->bases_begin(),
-              base_class_end = cxx_record_decl->bases_end();
-               base_class != base_class_end; ++base_class) {
-            // Skip empty base classes
-            clang::CXXRecordDecl *base_class_decl =
-                llvm::cast<clang::CXXRecordDecl>(
-                    base_class->getType()
-                        ->getAs<clang::RecordType>()
-                        ->getDecl());
-            if (omit_empty_base_classes &&
-                !TypeSystemClang::RecordHasFields(base_class_decl))
-              continue;
-
-            CompilerType base_class_clang_type = GetType(base_class->getType());
-            std::string base_class_type_name(
-                base_class_clang_type.GetTypeName().AsCString(""));
-            if (base_class_type_name == name)
-              return child_idx;
-            ++child_idx;
-          }
-        }
-
-        // Try and find a field that matches NAME
-        clang::RecordDecl::field_iterator field, field_end;
-        llvm::StringRef name_sref(name);
-        for (field = record_decl->field_begin(),
-            field_end = record_decl->field_end();
-             field != field_end; ++field, ++child_idx) {
-          if (field->getName().equals(name_sref))
-            return child_idx;
-        }
-      }
-      break;
-
-    case clang::Type::ObjCObject:
-    case clang::Type::ObjCInterface:
-      if (GetCompleteType(type)) {
-        llvm::StringRef name_sref(name);
-        const clang::ObjCObjectType *objc_class_type =
-            llvm::dyn_cast<clang::ObjCObjectType>(qual_type.getTypePtr());
-        assert(objc_class_type);
-        if (objc_class_type) {
-          uint32_t child_idx = 0;
-          clang::ObjCInterfaceDecl *class_interface_decl =
-              objc_class_type->getInterface();
-
-          if (class_interface_decl) {
-            clang::ObjCInterfaceDecl::ivar_iterator ivar_pos,
-                ivar_end = class_interface_decl->ivar_end();
-            clang::ObjCInterfaceDecl *superclass_interface_decl =
-                class_interface_decl->getSuperClass();
-
-            for (ivar_pos = class_interface_decl->ivar_begin();
-                 ivar_pos != ivar_end; ++ivar_pos, ++child_idx) {
-              const clang::ObjCIvarDecl *ivar_decl = *ivar_pos;
-
-              if (ivar_decl->getName().equals(name_sref)) {
-                if ((!omit_empty_base_classes && superclass_interface_decl) ||
-                    (omit_empty_base_classes &&
-                     ObjCDeclHasIVars(superclass_interface_decl, true)))
-                  ++child_idx;
-
-                return child_idx;
-              }
-            }
-
-            if (superclass_interface_decl) {
-              if (superclass_interface_decl->getName().equals(name_sref))
-                return 0;
-            }
-          }
-        }
-      }
-      break;
-
-    case clang::Type::ObjCObjectPointer: {
-      CompilerType pointee_clang_type = GetType(
-          llvm::cast<clang::ObjCObjectPointerType>(qual_type.getTypePtr())
-              ->getPointeeType());
-      return pointee_clang_type.GetIndexOfChildWithName(
-          name, omit_empty_base_classes);
-    } break;
-
-    case clang::Type::ConstantArray: {
-      //                const clang::ConstantArrayType *array =
-      //                llvm::cast<clang::ConstantArrayType>(parent_qual_type.getTypePtr());
-      //                const uint64_t element_count =
-      //                array->getSize().getLimitedValue();
-      //
-      //                if (idx < element_count)
-      //                {
-      //                    std::pair<uint64_t, unsigned> field_type_info =
-      //                    ast->getTypeInfo(array->getElementType());
-      //
-      //                    char element_name[32];
-      //                    ::snprintf (element_name, sizeof (element_name),
-      //                    "%s[%u]", parent_name ? parent_name : "", idx);
-      //
-      //                    child_name.assign(element_name);
-      //                    assert(field_type_info.first % 8 == 0);
-      //                    child_byte_size = field_type_info.first / 8;
-      //                    child_byte_offset = idx * child_byte_size;
-      //                    return array->getElementType().getAsOpaquePtr();
-      //                }
-    } break;
-
-    //        case clang::Type::MemberPointerType:
-    //            {
-    //                MemberPointerType *mem_ptr_type =
-    //                llvm::cast<MemberPointerType>(qual_type.getTypePtr());
-    //                clang::QualType pointee_type =
-    //                mem_ptr_type->getPointeeType();
-    //
-    //                if (TypeSystemClang::IsAggregateType
-    //                (pointee_type.getAsOpaquePtr()))
-    //                {
-    //                    return GetIndexOfChildWithName (ast,
-    //                                                    mem_ptr_type->getPointeeType().getAsOpaquePtr(),
-    //                                                    name);
-    //                }
-    //            }
-    //            break;
-    //
-    case clang::Type::LValueReference:
-    case clang::Type::RValueReference: {
-      const clang::ReferenceType *reference_type =
-          llvm::cast<clang::ReferenceType>(qual_type.getTypePtr());
-      CompilerType pointee_type = GetType(reference_type->getPointeeType());
-
-      if (pointee_type.IsAggregateType()) {
-        return pointee_type.GetIndexOfChildWithName(name,
-                                                    omit_empty_base_classes);
-      }
-    } break;
-
-    case clang::Type::Pointer: {
-      const clang::PointerType *pointer_type =
-          llvm::cast<clang::PointerType>(qual_type.getTypePtr());
-      CompilerType pointee_type = GetType(pointer_type->getPointeeType());
-
-      if (pointee_type.IsAggregateType()) {
-        return pointee_type.GetIndexOfChildWithName(name,
-                                                    omit_empty_base_classes);
-      } else {
-        //                    if (parent_name)
-        //                    {
-        //                        child_name.assign(1, '*');
-        //                        child_name += parent_name;
-        //                    }
-        //
-        //                    // We have a pointer to an simple type
-        //                    if (idx == 0)
-        //                    {
-        //                        std::pair<uint64_t, unsigned> clang_type_info
-        //                        = ast->getTypeInfo(pointee_type);
-        //                        assert(clang_type_info.first % 8 == 0);
-        //                        child_byte_size = clang_type_info.first / 8;
-        //                        child_byte_offset = 0;
-        //                        return pointee_type.getAsOpaquePtr();
-        //                    }
-      }
-    } break;
-
-    default:
-      break;
-    }
-  }
-  return UINT32_MAX;
-}
-
-size_t
-TypeSystemClang::GetNumTemplateArguments(lldb::opaque_compiler_type_t type) {
-  if (!type)
-    return 0;
-
-  clang::QualType qual_type = RemoveWrappingTypes(GetCanonicalQualType(type));
-  const clang::Type::TypeClass type_class = qual_type->getTypeClass();
-  switch (type_class) {
-  case clang::Type::Record:
-    if (GetCompleteType(type)) {
-      const clang::CXXRecordDecl *cxx_record_decl =
-          qual_type->getAsCXXRecordDecl();
-      if (cxx_record_decl) {
-        const clang::ClassTemplateSpecializationDecl *template_decl =
-            llvm::dyn_cast<clang::ClassTemplateSpecializationDecl>(
-                cxx_record_decl);
-        if (template_decl)
-          return template_decl->getTemplateArgs().size();
-      }
-    }
-    break;
-
-  default:
-    break;
-  }
-
-  return 0;
-}
-
-const clang::ClassTemplateSpecializationDecl *
-TypeSystemClang::GetAsTemplateSpecialization(
-    lldb::opaque_compiler_type_t type) {
-  if (!type)
-    return nullptr;
-
-  clang::QualType qual_type(RemoveWrappingTypes(GetCanonicalQualType(type)));
-  const clang::Type::TypeClass type_class = qual_type->getTypeClass();
-  switch (type_class) {
-  case clang::Type::Record: {
-    if (! GetCompleteType(type))
-      return nullptr;
-    const clang::CXXRecordDecl *cxx_record_decl =
-        qual_type->getAsCXXRecordDecl();
-    if (!cxx_record_decl)
-      return nullptr;
-    return llvm::dyn_cast<clang::ClassTemplateSpecializationDecl>(
-        cxx_record_decl);
-  }
-
-  default:
-    return nullptr;
-  }
-}
-
-lldb::TemplateArgumentKind
-TypeSystemClang::GetTemplateArgumentKind(lldb::opaque_compiler_type_t type,
-                                         size_t arg_idx) {
-  const clang::ClassTemplateSpecializationDecl *template_decl =
-      GetAsTemplateSpecialization(type);
-  if (! template_decl || arg_idx >= template_decl->getTemplateArgs().size())
-    return eTemplateArgumentKindNull;
-
-  switch (template_decl->getTemplateArgs()[arg_idx].getKind()) {
-  case clang::TemplateArgument::Null:
-    return eTemplateArgumentKindNull;
-
-  case clang::TemplateArgument::NullPtr:
-    return eTemplateArgumentKindNullPtr;
-
-  case clang::TemplateArgument::Type:
-    return eTemplateArgumentKindType;
-
-  case clang::TemplateArgument::Declaration:
-    return eTemplateArgumentKindDeclaration;
-
-  case clang::TemplateArgument::Integral:
-    return eTemplateArgumentKindIntegral;
-
-  case clang::TemplateArgument::Template:
-    return eTemplateArgumentKindTemplate;
-
-  case clang::TemplateArgument::TemplateExpansion:
-    return eTemplateArgumentKindTemplateExpansion;
-
-  case clang::TemplateArgument::Expression:
-    return eTemplateArgumentKindExpression;
-
-  case clang::TemplateArgument::Pack:
-    return eTemplateArgumentKindPack;
-  }
-  llvm_unreachable("Unhandled clang::TemplateArgument::ArgKind");
-}
-
-CompilerType
-TypeSystemClang::GetTypeTemplateArgument(lldb::opaque_compiler_type_t type,
-                                         size_t idx) {
-  const clang::ClassTemplateSpecializationDecl *template_decl =
-      GetAsTemplateSpecialization(type);
-  if (!template_decl || idx >= template_decl->getTemplateArgs().size())
-    return CompilerType();
-
-  const clang::TemplateArgument &template_arg =
-      template_decl->getTemplateArgs()[idx];
-  if (template_arg.getKind() != clang::TemplateArgument::Type)
-    return CompilerType();
-
-  return GetType(template_arg.getAsType());
-}
-
-Optional<CompilerType::IntegralTemplateArgument>
-TypeSystemClang::GetIntegralTemplateArgument(lldb::opaque_compiler_type_t type,
-                                             size_t idx) {
-  const clang::ClassTemplateSpecializationDecl *template_decl =
-      GetAsTemplateSpecialization(type);
-  if (! template_decl || idx >= template_decl->getTemplateArgs().size())
-    return llvm::None;
-
-  const clang::TemplateArgument &template_arg =
-      template_decl->getTemplateArgs()[idx];
-  if (template_arg.getKind() != clang::TemplateArgument::Integral)
-    return llvm::None;
-
-  return {
-      {template_arg.getAsIntegral(), GetType(template_arg.getIntegralType())}};
-}
-
-CompilerType TypeSystemClang::GetTypeForFormatters(void *type) {
-  if (type)
-    return ClangUtil::RemoveFastQualifiers(CompilerType(this, type));
-  return CompilerType();
-}
-
-clang::EnumDecl *TypeSystemClang::GetAsEnumDecl(const CompilerType &type) {
-  const clang::EnumType *enutype =
-      llvm::dyn_cast<clang::EnumType>(ClangUtil::GetCanonicalQualType(type));
-  if (enutype)
-    return enutype->getDecl();
-  return nullptr;
-}
-
-clang::RecordDecl *TypeSystemClang::GetAsRecordDecl(const CompilerType &type) {
-  const clang::RecordType *record_type =
-      llvm::dyn_cast<clang::RecordType>(ClangUtil::GetCanonicalQualType(type));
-  if (record_type)
-    return record_type->getDecl();
-  return nullptr;
-}
-
-clang::TagDecl *TypeSystemClang::GetAsTagDecl(const CompilerType &type) {
-  return ClangUtil::GetAsTagDecl(type);
-}
-
-clang::TypedefNameDecl *
-TypeSystemClang::GetAsTypedefDecl(const CompilerType &type) {
-  const clang::TypedefType *typedef_type =
-      llvm::dyn_cast<clang::TypedefType>(ClangUtil::GetQualType(type));
-  if (typedef_type)
-    return typedef_type->getDecl();
-  return nullptr;
-}
-
-clang::CXXRecordDecl *
-TypeSystemClang::GetAsCXXRecordDecl(lldb::opaque_compiler_type_t type) {
-  return GetCanonicalQualType(type)->getAsCXXRecordDecl();
-}
-
-clang::ObjCInterfaceDecl *
-TypeSystemClang::GetAsObjCInterfaceDecl(const CompilerType &type) {
-  const clang::ObjCObjectType *objc_class_type =
-      llvm::dyn_cast<clang::ObjCObjectType>(
-          ClangUtil::GetCanonicalQualType(type));
-  if (objc_class_type)
-    return objc_class_type->getInterface();
-  return nullptr;
-}
-
-clang::FieldDecl *TypeSystemClang::AddFieldToRecordType(
-    const CompilerType &type, llvm::StringRef name,
-    const CompilerType &field_clang_type, AccessType access,
-    uint32_t bitfield_bit_size) {
-  if (!type.IsValid() || !field_clang_type.IsValid())
-    return nullptr;
-  TypeSystemClang *ast =
-      llvm::dyn_cast_or_null<TypeSystemClang>(type.GetTypeSystem());
-  if (!ast)
-    return nullptr;
-  clang::ASTContext &clang_ast = ast->getASTContext();
-  clang::IdentifierInfo *ident = nullptr;
-  if (!name.empty())
-    ident = &clang_ast.Idents.get(name);
-
-  clang::FieldDecl *field = nullptr;
-
-  clang::Expr *bit_width = nullptr;
-  if (bitfield_bit_size != 0) {
-    llvm::APInt bitfield_bit_size_apint(clang_ast.getTypeSize(clang_ast.IntTy),
-                                        bitfield_bit_size);
-    bit_width = new (clang_ast)
-        clang::IntegerLiteral(clang_ast, bitfield_bit_size_apint,
-                              clang_ast.IntTy, clang::SourceLocation());
-  }
-
-  clang::RecordDecl *record_decl = ast->GetAsRecordDecl(type);
-  if (record_decl) {
-    field = clang::FieldDecl::Create(
-        clang_ast, record_decl, clang::SourceLocation(),
-        clang::SourceLocation(),
-        ident,                                    // Identifier
-        ClangUtil::GetQualType(field_clang_type), // Field type
-        nullptr,                                  // TInfo *
-        bit_width,                                // BitWidth
-        false,                                    // Mutable
-        clang::ICIS_NoInit);                      // HasInit
-
-    if (name.empty()) {
-      // Determine whether this field corresponds to an anonymous struct or
-      // union.
-      if (const clang::TagType *TagT =
-              field->getType()->getAs<clang::TagType>()) {
-        if (clang::RecordDecl *Rec =
-                llvm::dyn_cast<clang::RecordDecl>(TagT->getDecl()))
-          if (!Rec->getDeclName()) {
-            Rec->setAnonymousStructOrUnion(true);
-            field->setImplicit();
-          }
-      }
-    }
-
-    if (field) {
-      field->setAccess(
-          TypeSystemClang::ConvertAccessTypeToAccessSpecifier(access));
-
-      record_decl->addDecl(field);
-
-#ifdef LLDB_CONFIGURATION_DEBUG
-      VerifyDecl(field);
-#endif
-    }
-  } else {
-    clang::ObjCInterfaceDecl *class_interface_decl =
-        ast->GetAsObjCInterfaceDecl(type);
-
-    if (class_interface_decl) {
-      const bool is_synthesized = false;
-
-      field_clang_type.GetCompleteType();
-
-      field = clang::ObjCIvarDecl::Create(
-          clang_ast, class_interface_decl, clang::SourceLocation(),
-          clang::SourceLocation(),
-          ident,                                    // Identifier
-          ClangUtil::GetQualType(field_clang_type), // Field type
-          nullptr,                                  // TypeSourceInfo *
-          ConvertAccessTypeToObjCIvarAccessControl(access), bit_width,
-          is_synthesized);
-
-      if (field) {
-        class_interface_decl->addDecl(field);
-
-#ifdef LLDB_CONFIGURATION_DEBUG
-        VerifyDecl(field);
-#endif
-      }
-    }
-  }
-  return field;
-}
-
-void TypeSystemClang::BuildIndirectFields(const CompilerType &type) {
-  if (!type)
-    return;
-
-  TypeSystemClang *ast = llvm::dyn_cast<TypeSystemClang>(type.GetTypeSystem());
-  if (!ast)
-    return;
-
-  clang::RecordDecl *record_decl = ast->GetAsRecordDecl(type);
-
-  if (!record_decl)
-    return;
-
-  typedef llvm::SmallVector<clang::IndirectFieldDecl *, 1> IndirectFieldVector;
-
-  IndirectFieldVector indirect_fields;
-  clang::RecordDecl::field_iterator field_pos;
-  clang::RecordDecl::field_iterator field_end_pos = record_decl->field_end();
-  clang::RecordDecl::field_iterator last_field_pos = field_end_pos;
-  for (field_pos = record_decl->field_begin(); field_pos != field_end_pos;
-       last_field_pos = field_pos++) {
-    if (field_pos->isAnonymousStructOrUnion()) {
-      clang::QualType field_qual_type = field_pos->getType();
-
-      const clang::RecordType *field_record_type =
-          field_qual_type->getAs<clang::RecordType>();
-
-      if (!field_record_type)
-        continue;
-
-      clang::RecordDecl *field_record_decl = field_record_type->getDecl();
-
-      if (!field_record_decl)
-        continue;
-
-      for (clang::RecordDecl::decl_iterator
-               di = field_record_decl->decls_begin(),
-               de = field_record_decl->decls_end();
-           di != de; ++di) {
-        if (clang::FieldDecl *nested_field_decl =
-                llvm::dyn_cast<clang::FieldDecl>(*di)) {
-          clang::NamedDecl **chain =
-              new (ast->getASTContext()) clang::NamedDecl *[2];
-          chain[0] = *field_pos;
-          chain[1] = nested_field_decl;
-          clang::IndirectFieldDecl *indirect_field =
-              clang::IndirectFieldDecl::Create(
-                  ast->getASTContext(), record_decl, clang::SourceLocation(),
-                  nested_field_decl->getIdentifier(),
-                  nested_field_decl->getType(), {chain, 2});
-
-          indirect_field->setImplicit();
-
-          indirect_field->setAccess(TypeSystemClang::UnifyAccessSpecifiers(
-              field_pos->getAccess(), nested_field_decl->getAccess()));
-
-          indirect_fields.push_back(indirect_field);
-        } else if (clang::IndirectFieldDecl *nested_indirect_field_decl =
-                       llvm::dyn_cast<clang::IndirectFieldDecl>(*di)) {
-          size_t nested_chain_size =
-              nested_indirect_field_decl->getChainingSize();
-          clang::NamedDecl **chain = new (ast->getASTContext())
-              clang::NamedDecl *[nested_chain_size + 1];
-          chain[0] = *field_pos;
-
-          int chain_index = 1;
-          for (clang::IndirectFieldDecl::chain_iterator
-                   nci = nested_indirect_field_decl->chain_begin(),
-                   nce = nested_indirect_field_decl->chain_end();
-               nci < nce; ++nci) {
-            chain[chain_index] = *nci;
-            chain_index++;
-          }
-
-          clang::IndirectFieldDecl *indirect_field =
-              clang::IndirectFieldDecl::Create(
-                  ast->getASTContext(), record_decl, clang::SourceLocation(),
-                  nested_indirect_field_decl->getIdentifier(),
-                  nested_indirect_field_decl->getType(),
-                  {chain, nested_chain_size + 1});
-
-          indirect_field->setImplicit();
-
-          indirect_field->setAccess(TypeSystemClang::UnifyAccessSpecifiers(
-              field_pos->getAccess(), nested_indirect_field_decl->getAccess()));
-
-          indirect_fields.push_back(indirect_field);
-        }
-      }
-    }
-  }
-
-  // Check the last field to see if it has an incomplete array type as its last
-  // member and if it does, the tell the record decl about it
-  if (last_field_pos != field_end_pos) {
-    if (last_field_pos->getType()->isIncompleteArrayType())
-      record_decl->hasFlexibleArrayMember();
-  }
-
-  for (IndirectFieldVector::iterator ifi = indirect_fields.begin(),
-                                     ife = indirect_fields.end();
-       ifi < ife; ++ifi) {
-    record_decl->addDecl(*ifi);
-  }
-}
-
-void TypeSystemClang::SetIsPacked(const CompilerType &type) {
-  if (type) {
-    TypeSystemClang *ast =
-        llvm::dyn_cast<TypeSystemClang>(type.GetTypeSystem());
-    if (ast) {
-      clang::RecordDecl *record_decl = GetAsRecordDecl(type);
-
-      if (!record_decl)
-        return;
-
-      record_decl->addAttr(
-          clang::PackedAttr::CreateImplicit(ast->getASTContext()));
-    }
-  }
-}
-
-clang::VarDecl *TypeSystemClang::AddVariableToRecordType(
-    const CompilerType &type, llvm::StringRef name,
-    const CompilerType &var_type, AccessType access) {
-  if (!type.IsValid() || !var_type.IsValid())
-    return nullptr;
-
-  TypeSystemClang *ast = llvm::dyn_cast<TypeSystemClang>(type.GetTypeSystem());
-  if (!ast)
-    return nullptr;
-
-  clang::RecordDecl *record_decl = ast->GetAsRecordDecl(type);
-  if (!record_decl)
-    return nullptr;
-
-  clang::VarDecl *var_decl = nullptr;
-  clang::IdentifierInfo *ident = nullptr;
-  if (!name.empty())
-    ident = &ast->getASTContext().Idents.get(name);
-
-  var_decl = clang::VarDecl::Create(
-      ast->getASTContext(),             // ASTContext &
-      record_decl,                      // DeclContext *
-      clang::SourceLocation(),          // clang::SourceLocation StartLoc
-      clang::SourceLocation(),          // clang::SourceLocation IdLoc
-      ident,                            // clang::IdentifierInfo *
-      ClangUtil::GetQualType(var_type), // Variable clang::QualType
-      nullptr,                          // TypeSourceInfo *
-      clang::SC_Static);                // StorageClass
-  if (!var_decl)
-    return nullptr;
-
-  var_decl->setAccess(
-      TypeSystemClang::ConvertAccessTypeToAccessSpecifier(access));
-  record_decl->addDecl(var_decl);
-
-#ifdef LLDB_CONFIGURATION_DEBUG
-  VerifyDecl(var_decl);
-#endif
-
-  return var_decl;
-}
-
-clang::CXXMethodDecl *TypeSystemClang::AddMethodToCXXRecordType(
-    lldb::opaque_compiler_type_t type, llvm::StringRef name,
-    const char *mangled_name, const CompilerType &method_clang_type,
-    lldb::AccessType access, bool is_virtual, bool is_static, bool is_inline,
-    bool is_explicit, bool is_attr_used, bool is_artificial) {
-  if (!type || !method_clang_type.IsValid() || name.empty())
-    return nullptr;
-
-  clang::QualType record_qual_type(GetCanonicalQualType(type));
-
-  clang::CXXRecordDecl *cxx_record_decl =
-      record_qual_type->getAsCXXRecordDecl();
-
-  if (cxx_record_decl == nullptr)
-    return nullptr;
-
-  clang::QualType method_qual_type(ClangUtil::GetQualType(method_clang_type));
-
-  clang::CXXMethodDecl *cxx_method_decl = nullptr;
-
-  clang::DeclarationName decl_name(&getASTContext().Idents.get(name));
-
-  const clang::FunctionType *function_type =
-      llvm::dyn_cast<clang::FunctionType>(method_qual_type.getTypePtr());
-
-  if (function_type == nullptr)
-    return nullptr;
-
-  const clang::FunctionProtoType *method_function_prototype(
-      llvm::dyn_cast<clang::FunctionProtoType>(function_type));
-
-  if (!method_function_prototype)
-    return nullptr;
-
-  unsigned int num_params = method_function_prototype->getNumParams();
-
-  clang::CXXDestructorDecl *cxx_dtor_decl(nullptr);
-  clang::CXXConstructorDecl *cxx_ctor_decl(nullptr);
-
-  if (is_artificial)
-    return nullptr; // skip everything artificial
-
-  const clang::ExplicitSpecifier explicit_spec(
-      nullptr /*expr*/, is_explicit
-                            ? clang::ExplicitSpecKind::ResolvedTrue
-                            : clang::ExplicitSpecKind::ResolvedFalse);
-  if (name.startswith("~")) {
-    cxx_dtor_decl = clang::CXXDestructorDecl::Create(
-        getASTContext(), cxx_record_decl, clang::SourceLocation(),
-        clang::DeclarationNameInfo(
-            getASTContext().DeclarationNames.getCXXDestructorName(
-                getASTContext().getCanonicalType(record_qual_type)),
-            clang::SourceLocation()),
-        method_qual_type, nullptr, is_inline, is_artificial,
-        ConstexprSpecKind::CSK_unspecified);
-    cxx_method_decl = cxx_dtor_decl;
-  } else if (decl_name == cxx_record_decl->getDeclName()) {
-    cxx_ctor_decl = clang::CXXConstructorDecl::Create(
-        getASTContext(), cxx_record_decl, clang::SourceLocation(),
-        clang::DeclarationNameInfo(
-            getASTContext().DeclarationNames.getCXXConstructorName(
-                getASTContext().getCanonicalType(record_qual_type)),
-            clang::SourceLocation()),
-        method_qual_type,
-        nullptr, // TypeSourceInfo *
-        explicit_spec, is_inline, is_artificial, CSK_unspecified);
-    cxx_method_decl = cxx_ctor_decl;
-  } else {
-    clang::StorageClass SC = is_static ? clang::SC_Static : clang::SC_None;
-    clang::OverloadedOperatorKind op_kind = clang::NUM_OVERLOADED_OPERATORS;
-
-    if (IsOperator(name, op_kind)) {
-      if (op_kind != clang::NUM_OVERLOADED_OPERATORS) {
-        // Check the number of operator parameters. Sometimes we have seen bad
-        // DWARF that doesn't correctly describe operators and if we try to
-        // create a method and add it to the class, clang will assert and
-        // crash, so we need to make sure things are acceptable.
-        const bool is_method = true;
-        if (!TypeSystemClang::CheckOverloadedOperatorKindParameterCount(
-                is_method, op_kind, num_params))
-          return nullptr;
-        cxx_method_decl = clang::CXXMethodDecl::Create(
-            getASTContext(), cxx_record_decl, clang::SourceLocation(),
-            clang::DeclarationNameInfo(
-                getASTContext().DeclarationNames.getCXXOperatorName(op_kind),
-                clang::SourceLocation()),
-            method_qual_type,
-            nullptr, // TypeSourceInfo *
-            SC, is_inline, CSK_unspecified, clang::SourceLocation());
-      } else if (num_params == 0) {
-        // Conversion operators don't take params...
-        cxx_method_decl = clang::CXXConversionDecl::Create(
-            getASTContext(), cxx_record_decl, clang::SourceLocation(),
-            clang::DeclarationNameInfo(
-                getASTContext().DeclarationNames.getCXXConversionFunctionName(
-                    getASTContext().getCanonicalType(
-                        function_type->getReturnType())),
-                clang::SourceLocation()),
-            method_qual_type,
-            nullptr, // TypeSourceInfo *
-            is_inline, explicit_spec, CSK_unspecified, clang::SourceLocation());
-      }
-    }
-
-    if (cxx_method_decl == nullptr) {
-      cxx_method_decl = clang::CXXMethodDecl::Create(
-          getASTContext(), cxx_record_decl, clang::SourceLocation(),
-          clang::DeclarationNameInfo(decl_name, clang::SourceLocation()),
-          method_qual_type,
-          nullptr, // TypeSourceInfo *
-          SC, is_inline, CSK_unspecified, clang::SourceLocation());
-    }
-  }
-
-  clang::AccessSpecifier access_specifier =
-      TypeSystemClang::ConvertAccessTypeToAccessSpecifier(access);
-
-  cxx_method_decl->setAccess(access_specifier);
-  cxx_method_decl->setVirtualAsWritten(is_virtual);
-
-  if (is_attr_used)
-    cxx_method_decl->addAttr(clang::UsedAttr::CreateImplicit(getASTContext()));
-
-  if (mangled_name != nullptr) {
-    cxx_method_decl->addAttr(clang::AsmLabelAttr::CreateImplicit(
-        getASTContext(), mangled_name, /*literal=*/false));
-  }
-
-  // Populate the method decl with parameter decls
-
-  llvm::SmallVector<clang::ParmVarDecl *, 12> params;
-
-  for (unsigned param_index = 0; param_index < num_params; ++param_index) {
-    params.push_back(clang::ParmVarDecl::Create(
-        getASTContext(), cxx_method_decl, clang::SourceLocation(),
-        clang::SourceLocation(),
-        nullptr, // anonymous
-        method_function_prototype->getParamType(param_index), nullptr,
-        clang::SC_None, nullptr));
-  }
-
-  cxx_method_decl->setParams(llvm::ArrayRef<clang::ParmVarDecl *>(params));
-
-  cxx_record_decl->addDecl(cxx_method_decl);
-
-  // Sometimes the debug info will mention a constructor (default/copy/move),
-  // destructor, or assignment operator (copy/move) but there won't be any
-  // version of this in the code. So we check if the function was artificially
-  // generated and if it is trivial and this lets the compiler/backend know
-  // that it can inline the IR for these when it needs to and we can avoid a
-  // "missing function" error when running expressions.
-
-  if (is_artificial) {
-    if (cxx_ctor_decl && ((cxx_ctor_decl->isDefaultConstructor() &&
-                           cxx_record_decl->hasTrivialDefaultConstructor()) ||
-                          (cxx_ctor_decl->isCopyConstructor() &&
-                           cxx_record_decl->hasTrivialCopyConstructor()) ||
-                          (cxx_ctor_decl->isMoveConstructor() &&
-                           cxx_record_decl->hasTrivialMoveConstructor()))) {
-      cxx_ctor_decl->setDefaulted();
-      cxx_ctor_decl->setTrivial(true);
-    } else if (cxx_dtor_decl) {
-      if (cxx_record_decl->hasTrivialDestructor()) {
-        cxx_dtor_decl->setDefaulted();
-        cxx_dtor_decl->setTrivial(true);
-      }
-    } else if ((cxx_method_decl->isCopyAssignmentOperator() &&
-                cxx_record_decl->hasTrivialCopyAssignment()) ||
-               (cxx_method_decl->isMoveAssignmentOperator() &&
-                cxx_record_decl->hasTrivialMoveAssignment())) {
-      cxx_method_decl->setDefaulted();
-      cxx_method_decl->setTrivial(true);
-    }
-  }
-
-#ifdef LLDB_CONFIGURATION_DEBUG
-  VerifyDecl(cxx_method_decl);
-#endif
-
-  return cxx_method_decl;
-}
-
-void TypeSystemClang::AddMethodOverridesForCXXRecordType(
-    lldb::opaque_compiler_type_t type) {
-  if (auto *record = GetAsCXXRecordDecl(type))
-    for (auto *method : record->methods())
-      addOverridesForMethod(method);
-}
-
-#pragma mark C++ Base Classes
-
-std::unique_ptr<clang::CXXBaseSpecifier>
-TypeSystemClang::CreateBaseClassSpecifier(lldb::opaque_compiler_type_t type,
-                                          AccessType access, bool is_virtual,
-                                          bool base_of_class) {
-  if (!type)
-    return nullptr;
-
-  return std::make_unique<clang::CXXBaseSpecifier>(
-      clang::SourceRange(), is_virtual, base_of_class,
-      TypeSystemClang::ConvertAccessTypeToAccessSpecifier(access),
-      getASTContext().getTrivialTypeSourceInfo(GetQualType(type)),
-      clang::SourceLocation());
-}
-
-bool TypeSystemClang::TransferBaseClasses(
-    lldb::opaque_compiler_type_t type,
-    std::vector<std::unique_ptr<clang::CXXBaseSpecifier>> bases) {
-  if (!type)
-    return false;
-  clang::CXXRecordDecl *cxx_record_decl = GetAsCXXRecordDecl(type);
-  if (!cxx_record_decl)
-    return false;
-  std::vector<clang::CXXBaseSpecifier *> raw_bases;
-  raw_bases.reserve(bases.size());
-
-  // Clang will make a copy of them, so it's ok that we pass pointers that we're
-  // about to destroy.
-  for (auto &b : bases)
-    raw_bases.push_back(b.get());
-  cxx_record_decl->setBases(raw_bases.data(), raw_bases.size());
-  return true;
-}
-
-bool TypeSystemClang::SetObjCSuperClass(
-    const CompilerType &type, const CompilerType &superclass_clang_type) {
-  TypeSystemClang *ast =
-      llvm::dyn_cast_or_null<TypeSystemClang>(type.GetTypeSystem());
-  if (!ast)
-    return false;
-  clang::ASTContext &clang_ast = ast->getASTContext();
-
-  if (type && superclass_clang_type.IsValid() &&
-      superclass_clang_type.GetTypeSystem() == type.GetTypeSystem()) {
-    clang::ObjCInterfaceDecl *class_interface_decl =
-        GetAsObjCInterfaceDecl(type);
-    clang::ObjCInterfaceDecl *super_interface_decl =
-        GetAsObjCInterfaceDecl(superclass_clang_type);
-    if (class_interface_decl && super_interface_decl) {
-      class_interface_decl->setSuperClass(clang_ast.getTrivialTypeSourceInfo(
-          clang_ast.getObjCInterfaceType(super_interface_decl)));
-      return true;
-    }
-  }
-  return false;
-}
-
-bool TypeSystemClang::AddObjCClassProperty(
-    const CompilerType &type, const char *property_name,
-    const CompilerType &property_clang_type, clang::ObjCIvarDecl *ivar_decl,
-    const char *property_setter_name, const char *property_getter_name,
-    uint32_t property_attributes, ClangASTMetadata *metadata) {
-  if (!type || !property_clang_type.IsValid() || property_name == nullptr ||
-      property_name[0] == '\0')
-    return false;
-  TypeSystemClang *ast = llvm::dyn_cast<TypeSystemClang>(type.GetTypeSystem());
-  if (!ast)
-    return false;
-  clang::ASTContext &clang_ast = ast->getASTContext();
-
-  clang::ObjCInterfaceDecl *class_interface_decl = GetAsObjCInterfaceDecl(type);
-  if (!class_interface_decl)
-    return false;
-
-  CompilerType property_clang_type_to_access;
-
-  if (property_clang_type.IsValid())
-    property_clang_type_to_access = property_clang_type;
-  else if (ivar_decl)
-    property_clang_type_to_access = ast->GetType(ivar_decl->getType());
-
-  if (!class_interface_decl || !property_clang_type_to_access.IsValid())
-    return false;
-
-  clang::TypeSourceInfo *prop_type_source;
-  if (ivar_decl)
-    prop_type_source = clang_ast.getTrivialTypeSourceInfo(ivar_decl->getType());
-  else
-    prop_type_source = clang_ast.getTrivialTypeSourceInfo(
-        ClangUtil::GetQualType(property_clang_type));
-
-  clang::ObjCPropertyDecl *property_decl = clang::ObjCPropertyDecl::Create(
-      clang_ast, class_interface_decl,
-      clang::SourceLocation(), // Source Location
-      &clang_ast.Idents.get(property_name),
-      clang::SourceLocation(), // Source Location for AT
-      clang::SourceLocation(), // Source location for (
-      ivar_decl ? ivar_decl->getType()
-                : ClangUtil::GetQualType(property_clang_type),
-      prop_type_source);
-
-  if (!property_decl)
-    return false;
-
-  if (metadata)
-    ast->SetMetadata(property_decl, *metadata);
-
-  class_interface_decl->addDecl(property_decl);
-
-  clang::Selector setter_sel, getter_sel;
-
-  if (property_setter_name) {
-    std::string property_setter_no_colon(property_setter_name,
-                                         strlen(property_setter_name) - 1);
-    clang::IdentifierInfo *setter_ident =
-        &clang_ast.Idents.get(property_setter_no_colon);
-    setter_sel = clang_ast.Selectors.getSelector(1, &setter_ident);
-  } else if (!(property_attributes & DW_APPLE_PROPERTY_readonly)) {
-    std::string setter_sel_string("set");
-    setter_sel_string.push_back(::toupper(property_name[0]));
-    setter_sel_string.append(&property_name[1]);
-    clang::IdentifierInfo *setter_ident =
-        &clang_ast.Idents.get(setter_sel_string);
-    setter_sel = clang_ast.Selectors.getSelector(1, &setter_ident);
-  }
-  property_decl->setSetterName(setter_sel);
-  property_decl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_setter);
-
-  if (property_getter_name != nullptr) {
-    clang::IdentifierInfo *getter_ident =
-        &clang_ast.Idents.get(property_getter_name);
-    getter_sel = clang_ast.Selectors.getSelector(0, &getter_ident);
-  } else {
-    clang::IdentifierInfo *getter_ident = &clang_ast.Idents.get(property_name);
-    getter_sel = clang_ast.Selectors.getSelector(0, &getter_ident);
-  }
-  property_decl->setGetterName(getter_sel);
-  property_decl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_getter);
-
-  if (ivar_decl)
-    property_decl->setPropertyIvarDecl(ivar_decl);
-
-  if (property_attributes & DW_APPLE_PROPERTY_readonly)
-    property_decl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_readonly);
-  if (property_attributes & DW_APPLE_PROPERTY_readwrite)
-    property_decl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_readwrite);
-  if (property_attributes & DW_APPLE_PROPERTY_assign)
-    property_decl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_assign);
-  if (property_attributes & DW_APPLE_PROPERTY_retain)
-    property_decl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_retain);
-  if (property_attributes & DW_APPLE_PROPERTY_copy)
-    property_decl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_copy);
-  if (property_attributes & DW_APPLE_PROPERTY_nonatomic)
-    property_decl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_nonatomic);
-  if (property_attributes & ObjCPropertyDecl::OBJC_PR_nullability)
-    property_decl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_nullability);
-  if (property_attributes & ObjCPropertyDecl::OBJC_PR_null_resettable)
-    property_decl->setPropertyAttributes(
-        ObjCPropertyDecl::OBJC_PR_null_resettable);
-  if (property_attributes & ObjCPropertyDecl::OBJC_PR_class)
-    property_decl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_class);
-
-  const bool isInstance =
-      (property_attributes & ObjCPropertyDecl::OBJC_PR_class) == 0;
-
-  clang::ObjCMethodDecl *getter = nullptr;
-  if (!getter_sel.isNull())
-    getter = isInstance ? class_interface_decl->lookupInstanceMethod(getter_sel)
-                        : class_interface_decl->lookupClassMethod(getter_sel);
-  if (!getter_sel.isNull() && !getter) {
-    const bool isVariadic = false;
-    const bool isPropertyAccessor = false;
-    const bool isSynthesizedAccessorStub = false;
-    const bool isImplicitlyDeclared = true;
-    const bool isDefined = false;
-    const clang::ObjCMethodDecl::ImplementationControl impControl =
-        clang::ObjCMethodDecl::None;
-    const bool HasRelatedResultType = false;
-
-    getter = clang::ObjCMethodDecl::Create(
-        clang_ast, clang::SourceLocation(), clang::SourceLocation(), getter_sel,
-        ClangUtil::GetQualType(property_clang_type_to_access), nullptr,
-        class_interface_decl, isInstance, isVariadic, isPropertyAccessor,
-        isSynthesizedAccessorStub, isImplicitlyDeclared, isDefined, impControl,
-        HasRelatedResultType);
-
-    if (getter) {
-      if (metadata)
-        ast->SetMetadata(getter, *metadata);
-
-      getter->setMethodParams(clang_ast, llvm::ArrayRef<clang::ParmVarDecl *>(),
-                              llvm::ArrayRef<clang::SourceLocation>());
-      class_interface_decl->addDecl(getter);
-    }
-  }
-  if (getter) {
-    getter->setPropertyAccessor(true);
-    property_decl->setGetterMethodDecl(getter);
-  }
-
-  clang::ObjCMethodDecl *setter = nullptr;
-    setter = isInstance ? class_interface_decl->lookupInstanceMethod(setter_sel)
-                        : class_interface_decl->lookupClassMethod(setter_sel);
-  if (!setter_sel.isNull() && !setter) {
-    clang::QualType result_type = clang_ast.VoidTy;
-    const bool isVariadic = false;
-    const bool isPropertyAccessor = true;
-    const bool isSynthesizedAccessorStub = false;
-    const bool isImplicitlyDeclared = true;
-    const bool isDefined = false;
-    const clang::ObjCMethodDecl::ImplementationControl impControl =
-        clang::ObjCMethodDecl::None;
-    const bool HasRelatedResultType = false;
-
-    setter = clang::ObjCMethodDecl::Create(
-        clang_ast, clang::SourceLocation(), clang::SourceLocation(), setter_sel,
-        result_type, nullptr, class_interface_decl, isInstance, isVariadic,
-        isPropertyAccessor, isSynthesizedAccessorStub, isImplicitlyDeclared,
-        isDefined, impControl, HasRelatedResultType);
-
-    if (setter) {
-      if (metadata)
-        ast->SetMetadata(setter, *metadata);
-
-      llvm::SmallVector<clang::ParmVarDecl *, 1> params;
-      params.push_back(clang::ParmVarDecl::Create(
-          clang_ast, setter, clang::SourceLocation(), clang::SourceLocation(),
-          nullptr, // anonymous
-          ClangUtil::GetQualType(property_clang_type_to_access), nullptr,
-          clang::SC_Auto, nullptr));
-
-      setter->setMethodParams(clang_ast,
-                              llvm::ArrayRef<clang::ParmVarDecl *>(params),
-                              llvm::ArrayRef<clang::SourceLocation>());
-
-      class_interface_decl->addDecl(setter);
-    }
-  }
-  if (setter) {
-    setter->setPropertyAccessor(true);
-    property_decl->setSetterMethodDecl(setter);
-  }
-
-  return true;
-}
-
-bool TypeSystemClang::IsObjCClassTypeAndHasIVars(const CompilerType &type,
-                                                 bool check_superclass) {
-  clang::ObjCInterfaceDecl *class_interface_decl = GetAsObjCInterfaceDecl(type);
-  if (class_interface_decl)
-    return ObjCDeclHasIVars(class_interface_decl, check_superclass);
-  return false;
-}
-
-clang::ObjCMethodDecl *TypeSystemClang::AddMethodToObjCObjectType(
-    const CompilerType &type,
-    const char *name, // the full symbol name as seen in the symbol table
-                      // (lldb::opaque_compiler_type_t type, "-[NString
-                      // stringWithCString:]")
-    const CompilerType &method_clang_type, lldb::AccessType access,
-    bool is_artificial, bool is_variadic, bool is_objc_direct_call) {
-  if (!type || !method_clang_type.IsValid())
-    return nullptr;
-
-  clang::ObjCInterfaceDecl *class_interface_decl = GetAsObjCInterfaceDecl(type);
-
-  if (class_interface_decl == nullptr)
-    return nullptr;
-  TypeSystemClang *lldb_ast =
-      llvm::dyn_cast<TypeSystemClang>(type.GetTypeSystem());
-  if (lldb_ast == nullptr)
-    return nullptr;
-  clang::ASTContext &ast = lldb_ast->getASTContext();
-
-  const char *selector_start = ::strchr(name, ' ');
-  if (selector_start == nullptr)
-    return nullptr;
-
-  selector_start++;
-  llvm::SmallVector<clang::IdentifierInfo *, 12> selector_idents;
-
-  size_t len = 0;
-  const char *start;
-  // printf ("name = '%s'\n", name);
-
-  unsigned num_selectors_with_args = 0;
-  for (start = selector_start; start && *start != '\0' && *start != ']';
-       start += len) {
-    len = ::strcspn(start, ":]");
-    bool has_arg = (start[len] == ':');
-    if (has_arg)
-      ++num_selectors_with_args;
-    selector_idents.push_back(&ast.Idents.get(llvm::StringRef(start, len)));
-    if (has_arg)
-      len += 1;
-  }
-
-  if (selector_idents.size() == 0)
-    return nullptr;
-
-  clang::Selector method_selector = ast.Selectors.getSelector(
-      num_selectors_with_args ? selector_idents.size() : 0,
-      selector_idents.data());
-
-  clang::QualType method_qual_type(ClangUtil::GetQualType(method_clang_type));
-
-  // Populate the method decl with parameter decls
-  const clang::Type *method_type(method_qual_type.getTypePtr());
-
-  if (method_type == nullptr)
-    return nullptr;
-
-  const clang::FunctionProtoType *method_function_prototype(
-      llvm::dyn_cast<clang::FunctionProtoType>(method_type));
-
-  if (!method_function_prototype)
-    return nullptr;
-
-  const bool isInstance = (name[0] == '-');
-  const bool isVariadic = is_variadic;
-  const bool isPropertyAccessor = false;
-  const bool isSynthesizedAccessorStub = false;
-  /// Force this to true because we don't have source locations.
-  const bool isImplicitlyDeclared = true;
-  const bool isDefined = false;
-  const clang::ObjCMethodDecl::ImplementationControl impControl =
-      clang::ObjCMethodDecl::None;
-  const bool HasRelatedResultType = false;
-
-  const unsigned num_args = method_function_prototype->getNumParams();
-
-  if (num_args != num_selectors_with_args)
-    return nullptr; // some debug information is corrupt.  We are not going to
-                    // deal with it.
-
-  clang::ObjCMethodDecl *objc_method_decl = clang::ObjCMethodDecl::Create(
-      ast,
-      clang::SourceLocation(), // beginLoc,
-      clang::SourceLocation(), // endLoc,
-      method_selector, method_function_prototype->getReturnType(),
-      nullptr, // TypeSourceInfo *ResultTInfo,
-      lldb_ast->GetDeclContextForType(ClangUtil::GetQualType(type)), isInstance,
-      isVariadic, isPropertyAccessor, isSynthesizedAccessorStub,
-      isImplicitlyDeclared, isDefined, impControl, HasRelatedResultType);
-
-  if (objc_method_decl == nullptr)
-    return nullptr;
-
-  if (num_args > 0) {
-    llvm::SmallVector<clang::ParmVarDecl *, 12> params;
-
-    for (unsigned param_index = 0; param_index < num_args; ++param_index) {
-      params.push_back(clang::ParmVarDecl::Create(
-          ast, objc_method_decl, clang::SourceLocation(),
-          clang::SourceLocation(),
-          nullptr, // anonymous
-          method_function_prototype->getParamType(param_index), nullptr,
-          clang::SC_Auto, nullptr));
-    }
-
-    objc_method_decl->setMethodParams(
-        ast, llvm::ArrayRef<clang::ParmVarDecl *>(params),
-        llvm::ArrayRef<clang::SourceLocation>());
-  }
-
-  if (is_objc_direct_call) {
-    // Add a the objc_direct attribute to the declaration we generate that
-    // we generate a direct method call for this ObjCMethodDecl.
-    objc_method_decl->addAttr(
-        clang::ObjCDirectAttr::CreateImplicit(ast, SourceLocation()));
-    // Usually Sema is creating implicit parameters (e.g., self) when it
-    // parses the method. We don't have a parsing Sema when we build our own
-    // AST here so we manually need to create these implicit parameters to
-    // make the direct call code generation happy.
-    objc_method_decl->createImplicitParams(ast, class_interface_decl);
-  }
-
-  class_interface_decl->addDecl(objc_method_decl);
-
-#ifdef LLDB_CONFIGURATION_DEBUG
-  VerifyDecl(objc_method_decl);
-#endif
-
-  return objc_method_decl;
-}
-
-bool TypeSystemClang::SetHasExternalStorage(lldb::opaque_compiler_type_t type,
-                                            bool has_extern) {
-  if (!type)
-    return false;
-
-  clang::QualType qual_type(RemoveWrappingTypes(GetCanonicalQualType(type)));
-
-  const clang::Type::TypeClass type_class = qual_type->getTypeClass();
-  switch (type_class) {
-  case clang::Type::Record: {
-    clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl();
-    if (cxx_record_decl) {
-      cxx_record_decl->setHasExternalLexicalStorage(has_extern);
-      cxx_record_decl->setHasExternalVisibleStorage(has_extern);
-      return true;
-    }
-  } break;
-
-  case clang::Type::Enum: {
-    clang::EnumDecl *enum_decl =
-        llvm::cast<clang::EnumType>(qual_type)->getDecl();
-    if (enum_decl) {
-      enum_decl->setHasExternalLexicalStorage(has_extern);
-      enum_decl->setHasExternalVisibleStorage(has_extern);
-      return true;
-    }
-  } break;
-
-  case clang::Type::ObjCObject:
-  case clang::Type::ObjCInterface: {
-    const clang::ObjCObjectType *objc_class_type =
-        llvm::dyn_cast<clang::ObjCObjectType>(qual_type.getTypePtr());
-    assert(objc_class_type);
-    if (objc_class_type) {
-      clang::ObjCInterfaceDecl *class_interface_decl =
-          objc_class_type->getInterface();
-
-      if (class_interface_decl) {
-        class_interface_decl->setHasExternalLexicalStorage(has_extern);
-        class_interface_decl->setHasExternalVisibleStorage(has_extern);
-        return true;
-      }
-    }
-  } break;
-
-  default:
-    break;
-  }
-  return false;
-}
-
-#pragma mark TagDecl
-
-bool TypeSystemClang::StartTagDeclarationDefinition(const CompilerType &type) {
-  clang::QualType qual_type(ClangUtil::GetQualType(type));
-  if (!qual_type.isNull()) {
-    const clang::TagType *tag_type = qual_type->getAs<clang::TagType>();
-    if (tag_type) {
-      clang::TagDecl *tag_decl = tag_type->getDecl();
-      if (tag_decl) {
-        tag_decl->startDefinition();
-        return true;
-      }
-    }
-
-    const clang::ObjCObjectType *object_type =
-        qual_type->getAs<clang::ObjCObjectType>();
-    if (object_type) {
-      clang::ObjCInterfaceDecl *interface_decl = object_type->getInterface();
-      if (interface_decl) {
-        interface_decl->startDefinition();
-        return true;
-      }
-    }
-  }
-  return false;
-}
-
-bool TypeSystemClang::CompleteTagDeclarationDefinition(
-    const CompilerType &type) {
-  clang::QualType qual_type(ClangUtil::GetQualType(type));
-  if (qual_type.isNull())
-    return false;
-
-  // Make sure we use the same methodology as
-  // TypeSystemClang::StartTagDeclarationDefinition() as to how we start/end
-  // the definition.
-  const clang::TagType *tag_type = qual_type->getAs<clang::TagType>();
-  if (tag_type) {
-    clang::TagDecl *tag_decl = tag_type->getDecl();
-
-    if (auto *cxx_record_decl = llvm::dyn_cast<CXXRecordDecl>(tag_decl)) {
-      // If we have a move constructor declared but no copy constructor we
-      // need to explicitly mark it as deleted. Usually Sema would do this for
-      // us in Sema::DeclareImplicitCopyConstructor but we don't have a Sema
-      // when building an AST from debug information.
-      // See also:
-      // C++11 [class.copy]p7, p18:
-      //  If the class definition declares a move constructor or move assignment
-      //  operator, an implicitly declared copy constructor or copy assignment
-      //  operator is defined as deleted.
-      if (cxx_record_decl->hasUserDeclaredMoveConstructor() &&
-          cxx_record_decl->needsImplicitCopyConstructor())
-        cxx_record_decl->setImplicitCopyConstructorIsDeleted();
-
-      if (!cxx_record_decl->isCompleteDefinition())
-        cxx_record_decl->completeDefinition();
-      cxx_record_decl->setHasLoadedFieldsFromExternalStorage(true);
-      cxx_record_decl->setHasExternalLexicalStorage(false);
-      cxx_record_decl->setHasExternalVisibleStorage(false);
-      return true;
-    }
-  }
-
-  const clang::EnumType *enutype = qual_type->getAs<clang::EnumType>();
-
-  if (!enutype)
-    return false;
-  clang::EnumDecl *enum_decl = enutype->getDecl();
-
-  if (enum_decl->isCompleteDefinition())
-    return true;
-
-  TypeSystemClang *lldb_ast =
-      llvm::dyn_cast<TypeSystemClang>(type.GetTypeSystem());
-  if (lldb_ast == nullptr)
-    return false;
-  clang::ASTContext &ast = lldb_ast->getASTContext();
-
-  /// TODO This really needs to be fixed.
-
-  QualType integer_type(enum_decl->getIntegerType());
-  if (!integer_type.isNull()) {
-    unsigned NumPositiveBits = 1;
-    unsigned NumNegativeBits = 0;
-
-    clang::QualType promotion_qual_type;
-    // If the enum integer type is less than an integer in bit width,
-    // then we must promote it to an integer size.
-    if (ast.getTypeSize(enum_decl->getIntegerType()) <
-        ast.getTypeSize(ast.IntTy)) {
-      if (enum_decl->getIntegerType()->isSignedIntegerType())
-        promotion_qual_type = ast.IntTy;
-      else
-        promotion_qual_type = ast.UnsignedIntTy;
-    } else
-      promotion_qual_type = enum_decl->getIntegerType();
-
-    enum_decl->completeDefinition(enum_decl->getIntegerType(),
-                                  promotion_qual_type, NumPositiveBits,
-                                  NumNegativeBits);
-  }
-  return true;
-}
-
-clang::EnumConstantDecl *TypeSystemClang::AddEnumerationValueToEnumerationType(
-    const CompilerType &enum_type, const Declaration &decl, const char *name,
-    const llvm::APSInt &value) {
-
-  if (!enum_type || ConstString(name).IsEmpty())
-    return nullptr;
-
-  lldbassert(enum_type.GetTypeSystem() == static_cast<TypeSystem *>(this));
-
-  lldb::opaque_compiler_type_t enum_opaque_compiler_type =
-      enum_type.GetOpaqueQualType();
-
-  if (!enum_opaque_compiler_type)
-    return nullptr;
-
-  clang::QualType enum_qual_type(
-      GetCanonicalQualType(enum_opaque_compiler_type));
-
-  const clang::Type *clang_type = enum_qual_type.getTypePtr();
-
-  if (!clang_type)
-    return nullptr;
-
-  const clang::EnumType *enutype = llvm::dyn_cast<clang::EnumType>(clang_type);
-
-  if (!enutype)
-    return nullptr;
-
-  clang::EnumConstantDecl *enumerator_decl = clang::EnumConstantDecl::Create(
-      getASTContext(), enutype->getDecl(), clang::SourceLocation(),
-      name ? &getASTContext().Idents.get(name) : nullptr, // Identifier
-      clang::QualType(enutype, 0), nullptr, value);
-
-  if (!enumerator_decl)
-    return nullptr;
-
-  enutype->getDecl()->addDecl(enumerator_decl);
-
-#ifdef LLDB_CONFIGURATION_DEBUG
-  VerifyDecl(enumerator_decl);
-#endif
-
-  return enumerator_decl;
-}
-
-clang::EnumConstantDecl *TypeSystemClang::AddEnumerationValueToEnumerationType(
-    const CompilerType &enum_type, const Declaration &decl, const char *name,
-    int64_t enum_value, uint32_t enum_value_bit_size) {
-  CompilerType underlying_type =
-      GetEnumerationIntegerType(enum_type.GetOpaqueQualType());
-  bool is_signed = false;
-  underlying_type.IsIntegerType(is_signed);
-
-  llvm::APSInt value(enum_value_bit_size, is_signed);
-  value = enum_value;
-
-  return AddEnumerationValueToEnumerationType(enum_type, decl, name, value);
-}
-
-CompilerType
-TypeSystemClang::GetEnumerationIntegerType(lldb::opaque_compiler_type_t type) {
-  clang::QualType enum_qual_type(GetCanonicalQualType(type));
-  const clang::Type *clang_type = enum_qual_type.getTypePtr();
-  if (clang_type) {
-    const clang::EnumType *enutype =
-        llvm::dyn_cast<clang::EnumType>(clang_type);
-    if (enutype) {
-      clang::EnumDecl *enum_decl = enutype->getDecl();
-      if (enum_decl)
-        return GetType(enum_decl->getIntegerType());
-    }
-  }
-  return CompilerType();
-}
-
-CompilerType
-TypeSystemClang::CreateMemberPointerType(const CompilerType &type,
-                                         const CompilerType &pointee_type) {
-  if (type && pointee_type.IsValid() &&
-      type.GetTypeSystem() == pointee_type.GetTypeSystem()) {
-    TypeSystemClang *ast =
-        llvm::dyn_cast<TypeSystemClang>(type.GetTypeSystem());
-    if (!ast)
-      return CompilerType();
-    return ast->GetType(ast->getASTContext().getMemberPointerType(
-        ClangUtil::GetQualType(pointee_type),
-        ClangUtil::GetQualType(type).getTypePtr()));
-  }
-  return CompilerType();
-}
-
-// Dumping types
-#define DEPTH_INCREMENT 2
-
-#ifndef NDEBUG
-LLVM_DUMP_METHOD void
-TypeSystemClang::dump(lldb::opaque_compiler_type_t type) const {
-  if (!type)
-    return;
-  clang::QualType qual_type(GetQualType(type));
-  qual_type.dump();
-}
-#endif
-
-void TypeSystemClang::Dump(Stream &s) {
-  Decl *tu = Decl::castFromDeclContext(GetTranslationUnitDecl());
-  tu->dump(s.AsRawOstream());
-}
-
-void TypeSystemClang::DumpFromSymbolFile(Stream &s,
-                                         llvm::StringRef symbol_name) {
-  SymbolFile *symfile = GetSymbolFile();
-
-  if (!symfile)
-    return;
-
-  lldb_private::TypeList type_list;
-  symfile->GetTypes(nullptr, eTypeClassAny, type_list);
-  size_t ntypes = type_list.GetSize();
-
-  for (size_t i = 0; i < ntypes; ++i) {
-    TypeSP type = type_list.GetTypeAtIndex(i);
-
-    if (!symbol_name.empty())
-      if (symbol_name != type->GetName().GetStringRef())
-        continue;
-
-    s << type->GetName().AsCString() << "\n";
-
-    CompilerType full_type = type->GetFullCompilerType();
-    if (clang::TagDecl *tag_decl = GetAsTagDecl(full_type)) {
-      tag_decl->dump(s.AsRawOstream());
-      continue;
-    }
-    if (clang::TypedefNameDecl *typedef_decl = GetAsTypedefDecl(full_type)) {
-      typedef_decl->dump(s.AsRawOstream());
-      continue;
-    }
-    if (auto *objc_obj = llvm::dyn_cast<clang::ObjCObjectType>(
-            ClangUtil::GetQualType(full_type).getTypePtr())) {
-      if (clang::ObjCInterfaceDecl *interface_decl = objc_obj->getInterface()) {
-        interface_decl->dump(s.AsRawOstream());
-        continue;
-      }
-    }
-    GetCanonicalQualType(full_type.GetOpaqueQualType()).dump(s.AsRawOstream());
-  }
-}
-
-void TypeSystemClang::DumpValue(
-    lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx, Stream *s,
-    lldb::Format format, const lldb_private::DataExtractor &data,
-    lldb::offset_t data_byte_offset, size_t data_byte_size,
-    uint32_t bitfield_bit_size, uint32_t bitfield_bit_offset, bool show_types,
-    bool show_summary, bool verbose, uint32_t depth) {
-  if (!type)
-    return;
-
-  clang::QualType qual_type(GetQualType(type));
-  switch (qual_type->getTypeClass()) {
-  case clang::Type::Record:
-    if (GetCompleteType(type)) {
-      const clang::RecordType *record_type =
-          llvm::cast<clang::RecordType>(qual_type.getTypePtr());
-      const clang::RecordDecl *record_decl = record_type->getDecl();
-      assert(record_decl);
-      uint32_t field_bit_offset = 0;
-      uint32_t field_byte_offset = 0;
-      const clang::ASTRecordLayout &record_layout =
-          getASTContext().getASTRecordLayout(record_decl);
-      uint32_t child_idx = 0;
-
-      const clang::CXXRecordDecl *cxx_record_decl =
-          llvm::dyn_cast<clang::CXXRecordDecl>(record_decl);
-      if (cxx_record_decl) {
-        // We might have base classes to print out first
-        clang::CXXRecordDecl::base_class_const_iterator base_class,
-            base_class_end;
-        for (base_class = cxx_record_decl->bases_begin(),
-            base_class_end = cxx_record_decl->bases_end();
-             base_class != base_class_end; ++base_class) {
-          const clang::CXXRecordDecl *base_class_decl =
-              llvm::cast<clang::CXXRecordDecl>(
-                  base_class->getType()->getAs<clang::RecordType>()->getDecl());
-
-          // Skip empty base classes
-          if (!verbose && !TypeSystemClang::RecordHasFields(base_class_decl))
-            continue;
-
-          if (base_class->isVirtual())
-            field_bit_offset =
-                record_layout.getVBaseClassOffset(base_class_decl)
-                    .getQuantity() *
-                8;
-          else
-            field_bit_offset = record_layout.getBaseClassOffset(base_class_decl)
-                                   .getQuantity() *
-                               8;
-          field_byte_offset = field_bit_offset / 8;
-          assert(field_bit_offset % 8 == 0);
-          if (child_idx == 0)
-            s->PutChar('{');
-          else
-            s->PutChar(',');
-
-          clang::QualType base_class_qual_type = base_class->getType();
-          std::string base_class_type_name(base_class_qual_type.getAsString());
-
-          // Indent and print the base class type name
-          s->Format("\n{0}{1}", llvm::fmt_repeat(" ", depth + DEPTH_INCREMENT),
-                    base_class_type_name);
-
-          clang::TypeInfo base_class_type_info =
-              getASTContext().getTypeInfo(base_class_qual_type);
-
-          // Dump the value of the member
-          CompilerType base_clang_type = GetType(base_class_qual_type);
-          base_clang_type.DumpValue(
-              exe_ctx,
-              s, // Stream to dump to
-              base_clang_type
-                  .GetFormat(), // The format with which to display the member
-              data, // Data buffer containing all bytes for this type
-              data_byte_offset + field_byte_offset, // Offset into "data" where
-                                                    // to grab value from
-              base_class_type_info.Width / 8, // Size of this type in bytes
-              0,                              // Bitfield bit size
-              0,                              // Bitfield bit offset
-              show_types,   // Boolean indicating if we should show the variable
-                            // types
-              show_summary, // Boolean indicating if we should show a summary
-                            // for the current type
-              verbose,      // Verbose output?
-              depth + DEPTH_INCREMENT); // Scope depth for any types that have
-                                        // children
-
-          ++child_idx;
-        }
-      }
-      uint32_t field_idx = 0;
-      clang::RecordDecl::field_iterator field, field_end;
-      for (field = record_decl->field_begin(),
-          field_end = record_decl->field_end();
-           field != field_end; ++field, ++field_idx, ++child_idx) {
-        // Print the starting squiggly bracket (if this is the first member) or
-        // comma (for member 2 and beyond) for the struct/union/class member.
-        if (child_idx == 0)
-          s->PutChar('{');
-        else
-          s->PutChar(',');
-
-        // Indent
-        s->Printf("\n%*s", depth + DEPTH_INCREMENT, "");
-
-        clang::QualType field_type = field->getType();
-        // Print the member type if requested
-        // Figure out the type byte size (field_type_info.first) and alignment
-        // (field_type_info.second) from the AST context.
-        clang::TypeInfo field_type_info =
-            getASTContext().getTypeInfo(field_type);
-        assert(field_idx < record_layout.getFieldCount());
-        // Figure out the field offset within the current struct/union/class
-        // type
-        field_bit_offset = record_layout.getFieldOffset(field_idx);
-        field_byte_offset = field_bit_offset / 8;
-        uint32_t field_bitfield_bit_size = 0;
-        uint32_t field_bitfield_bit_offset = 0;
-        if (FieldIsBitfield(*field, field_bitfield_bit_size))
-          field_bitfield_bit_offset = field_bit_offset % 8;
-
-        if (show_types) {
-          std::string field_type_name(field_type.getAsString());
-          if (field_bitfield_bit_size > 0)
-            s->Printf("(%s:%u) ", field_type_name.c_str(),
-                      field_bitfield_bit_size);
-          else
-            s->Printf("(%s) ", field_type_name.c_str());
-        }
-        // Print the member name and equal sign
-        s->Printf("%s = ", field->getNameAsString().c_str());
-
-        // Dump the value of the member
-        CompilerType field_clang_type = GetType(field_type);
-        field_clang_type.DumpValue(
-            exe_ctx,
-            s, // Stream to dump to
-            field_clang_type
-                .GetFormat(), // The format with which to display the member
-            data,             // Data buffer containing all bytes for this type
-            data_byte_offset + field_byte_offset, // Offset into "data" where to
-                                                  // grab value from
-            field_type_info.Width / 8,            // Size of this type in bytes
-            field_bitfield_bit_size,              // Bitfield bit size
-            field_bitfield_bit_offset,            // Bitfield bit offset
-            show_types,   // Boolean indicating if we should show the variable
-                          // types
-            show_summary, // Boolean indicating if we should show a summary for
-                          // the current type
-            verbose,      // Verbose output?
-            depth + DEPTH_INCREMENT); // Scope depth for any types that have
-                                      // children
-      }
-
-      // Indent the trailing squiggly bracket
-      if (child_idx > 0)
-        s->Printf("\n%*s}", depth, "");
-    }
-    return;
-
-  case clang::Type::Enum:
-    if (GetCompleteType(type)) {
-      const clang::EnumType *enutype =
-          llvm::cast<clang::EnumType>(qual_type.getTypePtr());
-      const clang::EnumDecl *enum_decl = enutype->getDecl();
-      assert(enum_decl);
-      clang::EnumDecl::enumerator_iterator enum_pos, enum_end_pos;
-      lldb::offset_t offset = data_byte_offset;
-      const int64_t enum_value = data.GetMaxU64Bitfield(
-          &offset, data_byte_size, bitfield_bit_size, bitfield_bit_offset);
-      for (enum_pos = enum_decl->enumerator_begin(),
-          enum_end_pos = enum_decl->enumerator_end();
-           enum_pos != enum_end_pos; ++enum_pos) {
-        if (enum_pos->getInitVal() == enum_value) {
-          s->Printf("%s", enum_pos->getNameAsString().c_str());
-          return;
-        }
-      }
-      // If we have gotten here we didn't get find the enumerator in the enum
-      // decl, so just print the integer.
-      s->Printf("%" PRIi64, enum_value);
-    }
-    return;
-
-  case clang::Type::ConstantArray: {
-    const clang::ConstantArrayType *array =
-        llvm::cast<clang::ConstantArrayType>(qual_type.getTypePtr());
-    bool is_array_of_characters = false;
-    clang::QualType element_qual_type = array->getElementType();
-
-    const clang::Type *canonical_type =
-        element_qual_type->getCanonicalTypeInternal().getTypePtr();
-    if (canonical_type)
-      is_array_of_characters = canonical_type->isCharType();
-
-    const uint64_t element_count = array->getSize().getLimitedValue();
-
-    clang::TypeInfo field_type_info =
-        getASTContext().getTypeInfo(element_qual_type);
-
-    uint32_t element_idx = 0;
-    uint32_t element_offset = 0;
-    uint64_t element_byte_size = field_type_info.Width / 8;
-    uint32_t element_stride = element_byte_size;
-
-    if (is_array_of_characters) {
-      s->PutChar('"');
-      DumpDataExtractor(data, s, data_byte_offset, lldb::eFormatChar,
-                        element_byte_size, element_count, UINT32_MAX,
-                        LLDB_INVALID_ADDRESS, 0, 0);
-      s->PutChar('"');
-      return;
-    } else {
-      CompilerType element_clang_type = GetType(element_qual_type);
-      lldb::Format element_format = element_clang_type.GetFormat();
-
-      for (element_idx = 0; element_idx < element_count; ++element_idx) {
-        // Print the starting squiggly bracket (if this is the first member) or
-        // comman (for member 2 and beyong) for the struct/union/class member.
-        if (element_idx == 0)
-          s->PutChar('{');
-        else
-          s->PutChar(',');
-
-        // Indent and print the index
-        s->Printf("\n%*s[%u] ", depth + DEPTH_INCREMENT, "", element_idx);
-
-        // Figure out the field offset within the current struct/union/class
-        // type
-        element_offset = element_idx * element_stride;
-
-        // Dump the value of the member
-        element_clang_type.DumpValue(
-            exe_ctx,
-            s,              // Stream to dump to
-            element_format, // The format with which to display the element
-            data,           // Data buffer containing all bytes for this type
-            data_byte_offset +
-                element_offset, // Offset into "data" where to grab value from
-            element_byte_size,  // Size of this type in bytes
-            0,                  // Bitfield bit size
-            0,                  // Bitfield bit offset
-            show_types,   // Boolean indicating if we should show the variable
-                          // types
-            show_summary, // Boolean indicating if we should show a summary for
-                          // the current type
-            verbose,      // Verbose output?
-            depth + DEPTH_INCREMENT); // Scope depth for any types that have
-                                      // children
-      }
-
-      // Indent the trailing squiggly bracket
-      if (element_idx > 0)
-        s->Printf("\n%*s}", depth, "");
-    }
-  }
-    return;
-
-  case clang::Type::Typedef: {
-    clang::QualType typedef_qual_type =
-        llvm::cast<clang::TypedefType>(qual_type)
-            ->getDecl()
-            ->getUnderlyingType();
-
-    CompilerType typedef_clang_type = GetType(typedef_qual_type);
-    lldb::Format typedef_format = typedef_clang_type.GetFormat();
-    clang::TypeInfo typedef_type_info =
-        getASTContext().getTypeInfo(typedef_qual_type);
-    uint64_t typedef_byte_size = typedef_type_info.Width / 8;
-
-    return typedef_clang_type.DumpValue(
-        exe_ctx,
-        s,                   // Stream to dump to
-        typedef_format,      // The format with which to display the element
-        data,                // Data buffer containing all bytes for this type
-        data_byte_offset,    // Offset into "data" where to grab value from
-        typedef_byte_size,   // Size of this type in bytes
-        bitfield_bit_size,   // Bitfield bit size
-        bitfield_bit_offset, // Bitfield bit offset
-        show_types,   // Boolean indicating if we should show the variable types
-        show_summary, // Boolean indicating if we should show a summary for the
-                      // current type
-        verbose,      // Verbose output?
-        depth);       // Scope depth for any types that have children
-  } break;
-
-  case clang::Type::Auto: {
-    clang::QualType elaborated_qual_type =
-        llvm::cast<clang::AutoType>(qual_type)->getDeducedType();
-    CompilerType elaborated_clang_type = GetType(elaborated_qual_type);
-    lldb::Format elaborated_format = elaborated_clang_type.GetFormat();
-    clang::TypeInfo elaborated_type_info =
-        getASTContext().getTypeInfo(elaborated_qual_type);
-    uint64_t elaborated_byte_size = elaborated_type_info.Width / 8;
-
-    return elaborated_clang_type.DumpValue(
-        exe_ctx,
-        s,                    // Stream to dump to
-        elaborated_format,    // The format with which to display the element
-        data,                 // Data buffer containing all bytes for this type
-        data_byte_offset,     // Offset into "data" where to grab value from
-        elaborated_byte_size, // Size of this type in bytes
-        bitfield_bit_size,    // Bitfield bit size
-        bitfield_bit_offset,  // Bitfield bit offset
-        show_types,   // Boolean indicating if we should show the variable types
-        show_summary, // Boolean indicating if we should show a summary for the
-                      // current type
-        verbose,      // Verbose output?
-        depth);       // Scope depth for any types that have children
-  } break;
-
-  case clang::Type::Elaborated: {
-    clang::QualType elaborated_qual_type =
-        llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType();
-    CompilerType elaborated_clang_type = GetType(elaborated_qual_type);
-    lldb::Format elaborated_format = elaborated_clang_type.GetFormat();
-    clang::TypeInfo elaborated_type_info =
-        getASTContext().getTypeInfo(elaborated_qual_type);
-    uint64_t elaborated_byte_size = elaborated_type_info.Width / 8;
-
-    return elaborated_clang_type.DumpValue(
-        exe_ctx,
-        s,                    // Stream to dump to
-        elaborated_format,    // The format with which to display the element
-        data,                 // Data buffer containing all bytes for this type
-        data_byte_offset,     // Offset into "data" where to grab value from
-        elaborated_byte_size, // Size of this type in bytes
-        bitfield_bit_size,    // Bitfield bit size
-        bitfield_bit_offset,  // Bitfield bit offset
-        show_types,   // Boolean indicating if we should show the variable types
-        show_summary, // Boolean indicating if we should show a summary for the
-                      // current type
-        verbose,      // Verbose output?
-        depth);       // Scope depth for any types that have children
-  } break;
-
-  case clang::Type::Paren: {
-    clang::QualType desugar_qual_type =
-        llvm::cast<clang::ParenType>(qual_type)->desugar();
-    CompilerType desugar_clang_type = GetType(desugar_qual_type);
-
-    lldb::Format desugar_format = desugar_clang_type.GetFormat();
-    clang::TypeInfo desugar_type_info =
-        getASTContext().getTypeInfo(desugar_qual_type);
-    uint64_t desugar_byte_size = desugar_type_info.Width / 8;
-
-    return desugar_clang_type.DumpValue(
-        exe_ctx,
-        s,                   // Stream to dump to
-        desugar_format,      // The format with which to display the element
-        data,                // Data buffer containing all bytes for this type
-        data_byte_offset,    // Offset into "data" where to grab value from
-        desugar_byte_size,   // Size of this type in bytes
-        bitfield_bit_size,   // Bitfield bit size
-        bitfield_bit_offset, // Bitfield bit offset
-        show_types,   // Boolean indicating if we should show the variable types
-        show_summary, // Boolean indicating if we should show a summary for the
-                      // current type
-        verbose,      // Verbose output?
-        depth);       // Scope depth for any types that have children
-  } break;
-
-  default:
-    // We are down to a scalar type that we just need to display.
-    DumpDataExtractor(data, s, data_byte_offset, format, data_byte_size, 1,
-                      UINT32_MAX, LLDB_INVALID_ADDRESS, bitfield_bit_size,
-                      bitfield_bit_offset);
-
-    if (show_summary)
-      DumpSummary(type, exe_ctx, s, data, data_byte_offset, data_byte_size);
-    break;
-  }
-}
-
-static bool DumpEnumValue(const clang::QualType &qual_type, Stream *s,
-                          const DataExtractor &data, lldb::offset_t byte_offset,
-                          size_t byte_size, uint32_t bitfield_bit_offset,
-                          uint32_t bitfield_bit_size) {
-  const clang::EnumType *enutype =
-      llvm::cast<clang::EnumType>(qual_type.getTypePtr());
-  const clang::EnumDecl *enum_decl = enutype->getDecl();
-  assert(enum_decl);
-  lldb::offset_t offset = byte_offset;
-  const uint64_t enum_svalue = data.GetMaxS64Bitfield(
-      &offset, byte_size, bitfield_bit_size, bitfield_bit_offset);
-  bool can_be_bitfield = true;
-  uint64_t covered_bits = 0;
-  int num_enumerators = 0;
-
-  // Try to find an exact match for the value.
-  // At the same time, we're applying a heuristic to determine whether we want
-  // to print this enum as a bitfield. We're likely dealing with a bitfield if
-  // every enumrator is either a one bit value or a superset of the previous
-  // enumerators. Also 0 doesn't make sense when the enumerators are used as
-  // flags.
-  for (auto enumerator : enum_decl->enumerators()) {
-    uint64_t val = enumerator->getInitVal().getSExtValue();
-    val = llvm::SignExtend64(val, 8*byte_size);
-    if (llvm::countPopulation(val) != 1 && (val & ~covered_bits) != 0)
-      can_be_bitfield = false;
-    covered_bits |= val;
-    ++num_enumerators;
-    if (val == enum_svalue) {
-      // Found an exact match, that's all we need to do.
-      s->PutCString(enumerator->getNameAsString());
-      return true;
-    }
-  }
-
-  // Unsigned values make more sense for flags.
-  offset = byte_offset;
-  const uint64_t enum_uvalue = data.GetMaxU64Bitfield(
-      &offset, byte_size, bitfield_bit_size, bitfield_bit_offset);
-
-  // No exact match, but we don't think this is a bitfield. Print the value as
-  // decimal.
-  if (!can_be_bitfield) {
-    if (qual_type->isSignedIntegerOrEnumerationType())
-      s->Printf("%" PRIi64, enum_svalue);
-    else
-      s->Printf("%" PRIu64, enum_uvalue);
-    return true;
-  }
-
-  uint64_t remaining_value = enum_uvalue;
-  std::vector<std::pair<uint64_t, llvm::StringRef>> values;
-  values.reserve(num_enumerators);
-  for (auto enumerator : enum_decl->enumerators())
-    if (auto val = enumerator->getInitVal().getZExtValue())
-      values.emplace_back(val, enumerator->getName());
-
-  // Sort in reverse order of the number of the population count,  so that in
-  // `enum {A, B, ALL = A|B }` we visit ALL first. Use a stable sort so that
-  // A | C where A is declared before C is displayed in this order.
-  std::stable_sort(values.begin(), values.end(), [](const auto &a, const auto &b) {
-        return llvm::countPopulation(a.first) > llvm::countPopulation(b.first);
-      });
-
-  for (const auto &val : values) {
-    if ((remaining_value & val.first) != val.first)
-      continue;
-    remaining_value &= ~val.first;
-    s->PutCString(val.second);
-    if (remaining_value)
-      s->PutCString(" | ");
-  }
-
-  // If there is a remainder that is not covered by the value, print it as hex.
-  if (remaining_value)
-    s->Printf("0x%" PRIx64, remaining_value);
-
-  return true;
-}
-
-bool TypeSystemClang::DumpTypeValue(
-    lldb::opaque_compiler_type_t type, Stream *s, lldb::Format format,
-    const lldb_private::DataExtractor &data, lldb::offset_t byte_offset,
-    size_t byte_size, uint32_t bitfield_bit_size, uint32_t bitfield_bit_offset,
-    ExecutionContextScope *exe_scope) {
-  if (!type)
-    return false;
-  if (IsAggregateType(type)) {
-    return false;
-  } else {
-    clang::QualType qual_type(GetQualType(type));
-
-    const clang::Type::TypeClass type_class = qual_type->getTypeClass();
-
-    if (type_class == clang::Type::Elaborated) {
-      qual_type = llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType();
-      return DumpTypeValue(qual_type.getAsOpaquePtr(), s, format, data, byte_offset, byte_size,
-                           bitfield_bit_size, bitfield_bit_offset, exe_scope);
-    }
-
-    switch (type_class) {
-    case clang::Type::Typedef: {
-      clang::QualType typedef_qual_type =
-          llvm::cast<clang::TypedefType>(qual_type)
-              ->getDecl()
-              ->getUnderlyingType();
-      CompilerType typedef_clang_type = GetType(typedef_qual_type);
-      if (format == eFormatDefault)
-        format = typedef_clang_type.GetFormat();
-      clang::TypeInfo typedef_type_info =
-          getASTContext().getTypeInfo(typedef_qual_type);
-      uint64_t typedef_byte_size = typedef_type_info.Width / 8;
-
-      return typedef_clang_type.DumpTypeValue(
-          s,
-          format,            // The format with which to display the element
-          data,              // Data buffer containing all bytes for this type
-          byte_offset,       // Offset into "data" where to grab value from
-          typedef_byte_size, // Size of this type in bytes
-          bitfield_bit_size, // Size in bits of a bitfield value, if zero don't
-                             // treat as a bitfield
-          bitfield_bit_offset, // Offset in bits of a bitfield value if
-                               // bitfield_bit_size != 0
-          exe_scope);
-    } break;
-
-    case clang::Type::Enum:
-      // If our format is enum or default, show the enumeration value as its
-      // enumeration string value, else just display it as requested.
-      if ((format == eFormatEnum || format == eFormatDefault) &&
-          GetCompleteType(type))
-        return DumpEnumValue(qual_type, s, data, byte_offset, byte_size,
-                             bitfield_bit_offset, bitfield_bit_size);
-      // format was not enum, just fall through and dump the value as
-      // requested....
-      LLVM_FALLTHROUGH;
-
-    default:
-      // We are down to a scalar type that we just need to display.
-      {
-        uint32_t item_count = 1;
-        // A few formats, we might need to modify our size and count for
-        // depending
-        // on how we are trying to display the value...
-        switch (format) {
-        default:
-        case eFormatBoolean:
-        case eFormatBinary:
-        case eFormatComplex:
-        case eFormatCString: // NULL terminated C strings
-        case eFormatDecimal:
-        case eFormatEnum:
-        case eFormatHex:
-        case eFormatHexUppercase:
-        case eFormatFloat:
-        case eFormatOctal:
-        case eFormatOSType:
-        case eFormatUnsigned:
-        case eFormatPointer:
-        case eFormatVectorOfChar:
-        case eFormatVectorOfSInt8:
-        case eFormatVectorOfUInt8:
-        case eFormatVectorOfSInt16:
-        case eFormatVectorOfUInt16:
-        case eFormatVectorOfSInt32:
-        case eFormatVectorOfUInt32:
-        case eFormatVectorOfSInt64:
-        case eFormatVectorOfUInt64:
-        case eFormatVectorOfFloat32:
-        case eFormatVectorOfFloat64:
-        case eFormatVectorOfUInt128:
-          break;
-
-        case eFormatChar:
-        case eFormatCharPrintable:
-        case eFormatCharArray:
-        case eFormatBytes:
-        case eFormatBytesWithASCII:
-          item_count = byte_size;
-          byte_size = 1;
-          break;
-
-        case eFormatUnicode16:
-          item_count = byte_size / 2;
-          byte_size = 2;
-          break;
-
-        case eFormatUnicode32:
-          item_count = byte_size / 4;
-          byte_size = 4;
-          break;
-        }
-        return DumpDataExtractor(data, s, byte_offset, format, byte_size,
-                                 item_count, UINT32_MAX, LLDB_INVALID_ADDRESS,
-                                 bitfield_bit_size, bitfield_bit_offset,
-                                 exe_scope);
-      }
-      break;
-    }
-  }
-  return false;
-}
-
-void TypeSystemClang::DumpSummary(lldb::opaque_compiler_type_t type,
-                                  ExecutionContext *exe_ctx, Stream *s,
-                                  const lldb_private::DataExtractor &data,
-                                  lldb::offset_t data_byte_offset,
-                                  size_t data_byte_size) {
-  uint32_t length = 0;
-  if (IsCStringType(type, length)) {
-    if (exe_ctx) {
-      Process *process = exe_ctx->GetProcessPtr();
-      if (process) {
-        lldb::offset_t offset = data_byte_offset;
-        lldb::addr_t pointer_address = data.GetMaxU64(&offset, data_byte_size);
-        std::vector<uint8_t> buf;
-        if (length > 0)
-          buf.resize(length);
-        else
-          buf.resize(256);
-
-        DataExtractor cstr_data(&buf.front(), buf.size(),
-                                process->GetByteOrder(), 4);
-        buf.back() = '\0';
-        size_t bytes_read;
-        size_t total_cstr_len = 0;
-        Status error;
-        while ((bytes_read = process->ReadMemory(pointer_address, &buf.front(),
-                                                 buf.size(), error)) > 0) {
-          const size_t len = strlen((const char *)&buf.front());
-          if (len == 0)
-            break;
-          if (total_cstr_len == 0)
-            s->PutCString(" \"");
-          DumpDataExtractor(cstr_data, s, 0, lldb::eFormatChar, 1, len,
-                            UINT32_MAX, LLDB_INVALID_ADDRESS, 0, 0);
-          total_cstr_len += len;
-          if (len < buf.size())
-            break;
-          pointer_address += total_cstr_len;
-        }
-        if (total_cstr_len > 0)
-          s->PutChar('"');
-      }
-    }
-  }
-}
-
-void TypeSystemClang::DumpTypeDescription(lldb::opaque_compiler_type_t type) {
-  StreamFile s(stdout, false);
-  DumpTypeDescription(type, &s);
-
-  CompilerType ct(this, type);
-  const clang::Type *clang_type = ClangUtil::GetQualType(ct).getTypePtr();
-  ClangASTMetadata *metadata = GetMetadata(clang_type);
-  if (metadata) {
-    metadata->Dump(&s);
-  }
-}
-
-void TypeSystemClang::DumpTypeDescription(lldb::opaque_compiler_type_t type,
-                                          Stream *s) {
-  if (type) {
-    clang::QualType qual_type =
-        RemoveWrappingTypes(GetQualType(type), {clang::Type::Typedef});
-
-    llvm::SmallVector<char, 1024> buf;
-    llvm::raw_svector_ostream llvm_ostrm(buf);
-
-    const clang::Type::TypeClass type_class = qual_type->getTypeClass();
-    switch (type_class) {
-    case clang::Type::ObjCObject:
-    case clang::Type::ObjCInterface: {
-      GetCompleteType(type);
-
-      const clang::ObjCObjectType *objc_class_type =
-          llvm::dyn_cast<clang::ObjCObjectType>(qual_type.getTypePtr());
-      assert(objc_class_type);
-      if (objc_class_type) {
-        clang::ObjCInterfaceDecl *class_interface_decl =
-            objc_class_type->getInterface();
-        if (class_interface_decl) {
-          clang::PrintingPolicy policy = getASTContext().getPrintingPolicy();
-          class_interface_decl->print(llvm_ostrm, policy, s->GetIndentLevel());
-        }
-      }
-    } break;
-
-    case clang::Type::Typedef: {
-      const clang::TypedefType *typedef_type =
-          qual_type->getAs<clang::TypedefType>();
-      if (typedef_type) {
-        const clang::TypedefNameDecl *typedef_decl = typedef_type->getDecl();
-        std::string clang_typedef_name(
-            typedef_decl->getQualifiedNameAsString());
-        if (!clang_typedef_name.empty()) {
-          s->PutCString("typedef ");
-          s->PutCString(clang_typedef_name);
-        }
-      }
-    } break;
-
-    case clang::Type::Record: {
-      GetCompleteType(type);
-
-      const clang::RecordType *record_type =
-          llvm::cast<clang::RecordType>(qual_type.getTypePtr());
-      const clang::RecordDecl *record_decl = record_type->getDecl();
-      const clang::CXXRecordDecl *cxx_record_decl =
-          llvm::dyn_cast<clang::CXXRecordDecl>(record_decl);
-
-      if (cxx_record_decl)
-        cxx_record_decl->print(llvm_ostrm, getASTContext().getPrintingPolicy(),
-                               s->GetIndentLevel());
-      else
-        record_decl->print(llvm_ostrm, getASTContext().getPrintingPolicy(),
-                           s->GetIndentLevel());
-    } break;
-
-    default: {
-      const clang::TagType *tag_type =
-          llvm::dyn_cast<clang::TagType>(qual_type.getTypePtr());
-      if (tag_type) {
-        clang::TagDecl *tag_decl = tag_type->getDecl();
-        if (tag_decl)
-          tag_decl->print(llvm_ostrm, 0);
-      } else {
-        std::string clang_type_name(qual_type.getAsString());
-        if (!clang_type_name.empty())
-          s->PutCString(clang_type_name);
-      }
-    }
-    }
-
-    if (buf.size() > 0) {
-      s->Write(buf.data(), buf.size());
-    }
-  }
-}
-
-void TypeSystemClang::DumpTypeName(const CompilerType &type) {
-  if (ClangUtil::IsClangType(type)) {
-    clang::QualType qual_type(
-        ClangUtil::GetCanonicalQualType(ClangUtil::RemoveFastQualifiers(type)));
-
-    const clang::Type::TypeClass type_class = qual_type->getTypeClass();
-    switch (type_class) {
-    case clang::Type::Record: {
-      const clang::CXXRecordDecl *cxx_record_decl =
-          qual_type->getAsCXXRecordDecl();
-      if (cxx_record_decl)
-        printf("class %s", cxx_record_decl->getName().str().c_str());
-    } break;
-
-    case clang::Type::Enum: {
-      clang::EnumDecl *enum_decl =
-          llvm::cast<clang::EnumType>(qual_type)->getDecl();
-      if (enum_decl) {
-        printf("enum %s", enum_decl->getName().str().c_str());
-      }
-    } break;
-
-    case clang::Type::ObjCObject:
-    case clang::Type::ObjCInterface: {
-      const clang::ObjCObjectType *objc_class_type =
-          llvm::dyn_cast<clang::ObjCObjectType>(qual_type);
-      if (objc_class_type) {
-        clang::ObjCInterfaceDecl *class_interface_decl =
-            objc_class_type->getInterface();
-        // We currently can't complete objective C types through the newly
-        // added ASTContext because it only supports TagDecl objects right
-        // now...
-        if (class_interface_decl)
-          printf("@class %s", class_interface_decl->getName().str().c_str());
-      }
-    } break;
-
-    case clang::Type::Typedef:
-      printf("typedef %s", llvm::cast<clang::TypedefType>(qual_type)
-                               ->getDecl()
-                               ->getName()
-                               .str()
-                               .c_str());
-      break;
-
-    case clang::Type::Auto:
-      printf("auto ");
-      return DumpTypeName(CompilerType(type.GetTypeSystem(),
-                                       llvm::cast<clang::AutoType>(qual_type)
-                                           ->getDeducedType()
-                                           .getAsOpaquePtr()));
-
-    case clang::Type::Elaborated:
-      printf("elaborated ");
-      return DumpTypeName(CompilerType(
-          type.GetTypeSystem(), llvm::cast<clang::ElaboratedType>(qual_type)
-                                    ->getNamedType()
-                                    .getAsOpaquePtr()));
-
-    case clang::Type::Paren:
-      printf("paren ");
-      return DumpTypeName(CompilerType(
-          type.GetTypeSystem(),
-          llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr()));
-
-    default:
-      printf("TypeSystemClang::DumpTypeName() type_class = %u", type_class);
-      break;
-    }
-  }
-}
-
-clang::ClassTemplateDecl *TypeSystemClang::ParseClassTemplateDecl(
-    clang::DeclContext *decl_ctx, lldb::AccessType access_type,
-    const char *parent_name, int tag_decl_kind,
-    const TypeSystemClang::TemplateParameterInfos &template_param_infos) {
-  if (template_param_infos.IsValid()) {
-    std::string template_basename(parent_name);
-    template_basename.erase(template_basename.find('<'));
-
-    return CreateClassTemplateDecl(decl_ctx, access_type,
-                                   template_basename.c_str(), tag_decl_kind,
-                                   template_param_infos);
-  }
-  return nullptr;
-}
-
-void TypeSystemClang::CompleteTagDecl(clang::TagDecl *decl) {
-  SymbolFile *sym_file = GetSymbolFile();
-  if (sym_file) {
-    CompilerType clang_type = GetTypeForDecl(decl);
-    if (clang_type)
-      sym_file->CompleteType(clang_type);
-  }
-}
-
-void TypeSystemClang::CompleteObjCInterfaceDecl(
-    clang::ObjCInterfaceDecl *decl) {
-  SymbolFile *sym_file = GetSymbolFile();
-  if (sym_file) {
-    CompilerType clang_type = GetTypeForDecl(decl);
-    if (clang_type)
-      sym_file->CompleteType(clang_type);
-  }
-}
-
-DWARFASTParser *TypeSystemClang::GetDWARFParser() {
-  if (!m_dwarf_ast_parser_up)
-    m_dwarf_ast_parser_up.reset(new DWARFASTParserClang(*this));
-  return m_dwarf_ast_parser_up.get();
-}
-
-PDBASTParser *TypeSystemClang::GetPDBParser() {
-  if (!m_pdb_ast_parser_up)
-    m_pdb_ast_parser_up.reset(new PDBASTParser(*this));
-  return m_pdb_ast_parser_up.get();
-}
-
-bool TypeSystemClang::LayoutRecordType(
-    const clang::RecordDecl *record_decl, uint64_t &bit_size,
-    uint64_t &alignment,
-    llvm::DenseMap<const clang::FieldDecl *, uint64_t> &field_offsets,
-    llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits>
-        &base_offsets,
-    llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits>
-        &vbase_offsets) {
-  lldb_private::ClangASTImporter *importer = nullptr;
-  if (m_dwarf_ast_parser_up)
-    importer = &m_dwarf_ast_parser_up->GetClangASTImporter();
-  if (!importer && m_pdb_ast_parser_up)
-    importer = &m_pdb_ast_parser_up->GetClangASTImporter();
-  if (!importer)
-    return false;
-
-  return importer->LayoutRecordType(record_decl, bit_size, alignment,
-                                    field_offsets, base_offsets, vbase_offsets);
-}
-
-// CompilerDecl override functions
-
-ConstString TypeSystemClang::DeclGetName(void *opaque_decl) {
-  if (opaque_decl) {
-    clang::NamedDecl *nd =
-        llvm::dyn_cast<NamedDecl>((clang::Decl *)opaque_decl);
-    if (nd != nullptr)
-      return ConstString(nd->getDeclName().getAsString());
-  }
-  return ConstString();
-}
-
-ConstString TypeSystemClang::DeclGetMangledName(void *opaque_decl) {
-  if (opaque_decl) {
-    clang::NamedDecl *nd =
-        llvm::dyn_cast<clang::NamedDecl>((clang::Decl *)opaque_decl);
-    if (nd != nullptr && !llvm::isa<clang::ObjCMethodDecl>(nd)) {
-      clang::MangleContext *mc = getMangleContext();
-      if (mc && mc->shouldMangleCXXName(nd)) {
-        llvm::SmallVector<char, 1024> buf;
-        llvm::raw_svector_ostream llvm_ostrm(buf);
-        if (llvm::isa<clang::CXXConstructorDecl>(nd)) {
-          mc->mangleCXXCtor(llvm::dyn_cast<clang::CXXConstructorDecl>(nd),
-                            Ctor_Complete, llvm_ostrm);
-        } else if (llvm::isa<clang::CXXDestructorDecl>(nd)) {
-          mc->mangleCXXDtor(llvm::dyn_cast<clang::CXXDestructorDecl>(nd),
-                            Dtor_Complete, llvm_ostrm);
-        } else {
-          mc->mangleName(nd, llvm_ostrm);
-        }
-        if (buf.size() > 0)
-          return ConstString(buf.data(), buf.size());
-      }
-    }
-  }
-  return ConstString();
-}
-
-CompilerDeclContext TypeSystemClang::DeclGetDeclContext(void *opaque_decl) {
-  if (opaque_decl)
-    return CreateDeclContext(((clang::Decl *)opaque_decl)->getDeclContext());
-  return CompilerDeclContext();
-}
-
-CompilerType TypeSystemClang::DeclGetFunctionReturnType(void *opaque_decl) {
-  if (clang::FunctionDecl *func_decl =
-          llvm::dyn_cast<clang::FunctionDecl>((clang::Decl *)opaque_decl))
-    return GetType(func_decl->getReturnType());
-  if (clang::ObjCMethodDecl *objc_method =
-          llvm::dyn_cast<clang::ObjCMethodDecl>((clang::Decl *)opaque_decl))
-    return GetType(objc_method->getReturnType());
-  else
-    return CompilerType();
-}
-
-size_t TypeSystemClang::DeclGetFunctionNumArguments(void *opaque_decl) {
-  if (clang::FunctionDecl *func_decl =
-          llvm::dyn_cast<clang::FunctionDecl>((clang::Decl *)opaque_decl))
-    return func_decl->param_size();
-  if (clang::ObjCMethodDecl *objc_method =
-          llvm::dyn_cast<clang::ObjCMethodDecl>((clang::Decl *)opaque_decl))
-    return objc_method->param_size();
-  else
-    return 0;
-}
-
-CompilerType TypeSystemClang::DeclGetFunctionArgumentType(void *opaque_decl,
-                                                          size_t idx) {
-  if (clang::FunctionDecl *func_decl =
-          llvm::dyn_cast<clang::FunctionDecl>((clang::Decl *)opaque_decl)) {
-    if (idx < func_decl->param_size()) {
-      ParmVarDecl *var_decl = func_decl->getParamDecl(idx);
-      if (var_decl)
-        return GetType(var_decl->getOriginalType());
-    }
-  } else if (clang::ObjCMethodDecl *objc_method =
-                 llvm::dyn_cast<clang::ObjCMethodDecl>(
-                     (clang::Decl *)opaque_decl)) {
-    if (idx < objc_method->param_size())
-      return GetType(objc_method->parameters()[idx]->getOriginalType());
-  }
-  return CompilerType();
-}
-
-// CompilerDeclContext functions
-
-std::vector<CompilerDecl> TypeSystemClang::DeclContextFindDeclByName(
-    void *opaque_decl_ctx, ConstString name, const bool ignore_using_decls) {
-  std::vector<CompilerDecl> found_decls;
-  if (opaque_decl_ctx) {
-    DeclContext *root_decl_ctx = (DeclContext *)opaque_decl_ctx;
-    std::set<DeclContext *> searched;
-    std::multimap<DeclContext *, DeclContext *> search_queue;
-    SymbolFile *symbol_file = GetSymbolFile();
-
-    for (clang::DeclContext *decl_context = root_decl_ctx;
-         decl_context != nullptr && found_decls.empty();
-         decl_context = decl_context->getParent()) {
-      search_queue.insert(std::make_pair(decl_context, decl_context));
-
-      for (auto it = search_queue.find(decl_context); it != search_queue.end();
-           it++) {
-        if (!searched.insert(it->second).second)
-          continue;
-        symbol_file->ParseDeclsForContext(
-            CreateDeclContext(it->second));
-
-        for (clang::Decl *child : it->second->decls()) {
-          if (clang::UsingDirectiveDecl *ud =
-                  llvm::dyn_cast<clang::UsingDirectiveDecl>(child)) {
-            if (ignore_using_decls)
-              continue;
-            clang::DeclContext *from = ud->getCommonAncestor();
-            if (searched.find(ud->getNominatedNamespace()) == searched.end())
-              search_queue.insert(
-                  std::make_pair(from, ud->getNominatedNamespace()));
-          } else if (clang::UsingDecl *ud =
-                         llvm::dyn_cast<clang::UsingDecl>(child)) {
-            if (ignore_using_decls)
-              continue;
-            for (clang::UsingShadowDecl *usd : ud->shadows()) {
-              clang::Decl *target = usd->getTargetDecl();
-              if (clang::NamedDecl *nd =
-                      llvm::dyn_cast<clang::NamedDecl>(target)) {
-                IdentifierInfo *ii = nd->getIdentifier();
-                if (ii != nullptr &&
-                    ii->getName().equals(name.AsCString(nullptr)))
-                  found_decls.push_back(GetCompilerDecl(nd));
-              }
-            }
-          } else if (clang::NamedDecl *nd =
-                         llvm::dyn_cast<clang::NamedDecl>(child)) {
-            IdentifierInfo *ii = nd->getIdentifier();
-            if (ii != nullptr && ii->getName().equals(name.AsCString(nullptr)))
-              found_decls.push_back(GetCompilerDecl(nd));
-          }
-        }
-      }
-    }
-  }
-  return found_decls;
-}
-
-// Look for child_decl_ctx's lookup scope in frame_decl_ctx and its parents,
-// and return the number of levels it took to find it, or
-// LLDB_INVALID_DECL_LEVEL if not found.  If the decl was imported via a using
-// declaration, its name and/or type, if set, will be used to check that the
-// decl found in the scope is a match.
-//
-// The optional name is required by languages (like C++) to handle using
-// declarations like:
-//
-//     void poo();
-//     namespace ns {
-//         void foo();
-//         void goo();
-//     }
-//     void bar() {
-//         using ns::foo;
-//         // CountDeclLevels returns 0 for 'foo', 1 for 'poo', and
-//         // LLDB_INVALID_DECL_LEVEL for 'goo'.
-//     }
-//
-// The optional type is useful in the case that there's a specific overload
-// that we're looking for that might otherwise be shadowed, like:
-//
-//     void foo(int);
-//     namespace ns {
-//         void foo();
-//     }
-//     void bar() {
-//         using ns::foo;
-//         // CountDeclLevels returns 0 for { 'foo', void() },
-//         // 1 for { 'foo', void(int) }, and
-//         // LLDB_INVALID_DECL_LEVEL for { 'foo', void(int, int) }.
-//     }
-//
-// NOTE: Because file statics are at the TranslationUnit along with globals, a
-// function at file scope will return the same level as a function at global
-// scope. Ideally we'd like to treat the file scope as an additional scope just
-// below the global scope.  More work needs to be done to recognise that, if
-// the decl we're trying to look up is static, we should compare its source
-// file with that of the current scope and return a lower number for it.
-uint32_t TypeSystemClang::CountDeclLevels(clang::DeclContext *frame_decl_ctx,
-                                          clang::DeclContext *child_decl_ctx,
-                                          ConstString *child_name,
-                                          CompilerType *child_type) {
-  if (frame_decl_ctx) {
-    std::set<DeclContext *> searched;
-    std::multimap<DeclContext *, DeclContext *> search_queue;
-    SymbolFile *symbol_file = GetSymbolFile();
-
-    // Get the lookup scope for the decl we're trying to find.
-    clang::DeclContext *parent_decl_ctx = child_decl_ctx->getParent();
-
-    // Look for it in our scope's decl context and its parents.
-    uint32_t level = 0;
-    for (clang::DeclContext *decl_ctx = frame_decl_ctx; decl_ctx != nullptr;
-         decl_ctx = decl_ctx->getParent()) {
-      if (!decl_ctx->isLookupContext())
-        continue;
-      if (decl_ctx == parent_decl_ctx)
-        // Found it!
-        return level;
-      search_queue.insert(std::make_pair(decl_ctx, decl_ctx));
-      for (auto it = search_queue.find(decl_ctx); it != search_queue.end();
-           it++) {
-        if (searched.find(it->second) != searched.end())
-          continue;
-
-        // Currently DWARF has one shared translation unit for all Decls at top
-        // level, so this would erroneously find using statements anywhere.  So
-        // don't look at the top-level translation unit.
-        // TODO fix this and add a testcase that depends on it.
-
-        if (llvm::isa<clang::TranslationUnitDecl>(it->second))
-          continue;
-
-        searched.insert(it->second);
-        symbol_file->ParseDeclsForContext(
-            CreateDeclContext(it->second));
-
-        for (clang::Decl *child : it->second->decls()) {
-          if (clang::UsingDirectiveDecl *ud =
-                  llvm::dyn_cast<clang::UsingDirectiveDecl>(child)) {
-            clang::DeclContext *ns = ud->getNominatedNamespace();
-            if (ns == parent_decl_ctx)
-              // Found it!
-              return level;
-            clang::DeclContext *from = ud->getCommonAncestor();
-            if (searched.find(ns) == searched.end())
-              search_queue.insert(std::make_pair(from, ns));
-          } else if (child_name) {
-            if (clang::UsingDecl *ud =
-                    llvm::dyn_cast<clang::UsingDecl>(child)) {
-              for (clang::UsingShadowDecl *usd : ud->shadows()) {
-                clang::Decl *target = usd->getTargetDecl();
-                clang::NamedDecl *nd = llvm::dyn_cast<clang::NamedDecl>(target);
-                if (!nd)
-                  continue;
-                // Check names.
-                IdentifierInfo *ii = nd->getIdentifier();
-                if (ii == nullptr ||
-                    !ii->getName().equals(child_name->AsCString(nullptr)))
-                  continue;
-                // Check types, if one was provided.
-                if (child_type) {
-                  CompilerType clang_type = GetTypeForDecl(nd);
-                  if (!AreTypesSame(clang_type, *child_type,
-                                    /*ignore_qualifiers=*/true))
-                    continue;
-                }
-                // Found it!
-                return level;
-              }
-            }
-          }
-        }
-      }
-      ++level;
-    }
-  }
-  return LLDB_INVALID_DECL_LEVEL;
-}
-
-ConstString TypeSystemClang::DeclContextGetName(void *opaque_decl_ctx) {
-  if (opaque_decl_ctx) {
-    clang::NamedDecl *named_decl =
-        llvm::dyn_cast<clang::NamedDecl>((clang::DeclContext *)opaque_decl_ctx);
-    if (named_decl)
-      return ConstString(named_decl->getName());
-  }
-  return ConstString();
-}
-
-ConstString
-TypeSystemClang::DeclContextGetScopeQualifiedName(void *opaque_decl_ctx) {
-  if (opaque_decl_ctx) {
-    clang::NamedDecl *named_decl =
-        llvm::dyn_cast<clang::NamedDecl>((clang::DeclContext *)opaque_decl_ctx);
-    if (named_decl)
-      return ConstString(
-          llvm::StringRef(named_decl->getQualifiedNameAsString()));
-  }
-  return ConstString();
-}
-
-bool TypeSystemClang::DeclContextIsClassMethod(
-    void *opaque_decl_ctx, lldb::LanguageType *language_ptr,
-    bool *is_instance_method_ptr, ConstString *language_object_name_ptr) {
-  if (opaque_decl_ctx) {
-    clang::DeclContext *decl_ctx = (clang::DeclContext *)opaque_decl_ctx;
-    if (ObjCMethodDecl *objc_method =
-            llvm::dyn_cast<clang::ObjCMethodDecl>(decl_ctx)) {
-      if (is_instance_method_ptr)
-        *is_instance_method_ptr = objc_method->isInstanceMethod();
-      if (language_ptr)
-        *language_ptr = eLanguageTypeObjC;
-      if (language_object_name_ptr)
-        language_object_name_ptr->SetCString("self");
-      return true;
-    } else if (CXXMethodDecl *cxx_method =
-                   llvm::dyn_cast<clang::CXXMethodDecl>(decl_ctx)) {
-      if (is_instance_method_ptr)
-        *is_instance_method_ptr = cxx_method->isInstance();
-      if (language_ptr)
-        *language_ptr = eLanguageTypeC_plus_plus;
-      if (language_object_name_ptr)
-        language_object_name_ptr->SetCString("this");
-      return true;
-    } else if (clang::FunctionDecl *function_decl =
-                   llvm::dyn_cast<clang::FunctionDecl>(decl_ctx)) {
-      ClangASTMetadata *metadata = GetMetadata(function_decl);
-      if (metadata && metadata->HasObjectPtr()) {
-        if (is_instance_method_ptr)
-          *is_instance_method_ptr = true;
-        if (language_ptr)
-          *language_ptr = eLanguageTypeObjC;
-        if (language_object_name_ptr)
-          language_object_name_ptr->SetCString(metadata->GetObjectPtrName());
-        return true;
-      }
-    }
-  }
-  return false;
-}
-
-bool TypeSystemClang::DeclContextIsContainedInLookup(
-    void *opaque_decl_ctx, void *other_opaque_decl_ctx) {
-  auto *decl_ctx = (clang::DeclContext *)opaque_decl_ctx;
-  auto *other = (clang::DeclContext *)other_opaque_decl_ctx;
-
-  do {
-    // A decl context always includes its own contents in its lookup.
-    if (decl_ctx == other)
-      return true;
-
-    // If we have an inline namespace, then the lookup of the parent context
-    // also includes the inline namespace contents.
-  } while (other->isInlineNamespace() && (other = other->getParent()));
-
-  return false;
-}
-
-static bool IsClangDeclContext(const CompilerDeclContext &dc) {
-  return dc.IsValid() && isa<TypeSystemClang>(dc.GetTypeSystem());
-}
-
-clang::DeclContext *
-TypeSystemClang::DeclContextGetAsDeclContext(const CompilerDeclContext &dc) {
-  if (IsClangDeclContext(dc))
-    return (clang::DeclContext *)dc.GetOpaqueDeclContext();
-  return nullptr;
-}
-
-ObjCMethodDecl *
-TypeSystemClang::DeclContextGetAsObjCMethodDecl(const CompilerDeclContext &dc) {
-  if (IsClangDeclContext(dc))
-    return llvm::dyn_cast<clang::ObjCMethodDecl>(
-        (clang::DeclContext *)dc.GetOpaqueDeclContext());
-  return nullptr;
-}
-
-CXXMethodDecl *
-TypeSystemClang::DeclContextGetAsCXXMethodDecl(const CompilerDeclContext &dc) {
-  if (IsClangDeclContext(dc))
-    return llvm::dyn_cast<clang::CXXMethodDecl>(
-        (clang::DeclContext *)dc.GetOpaqueDeclContext());
-  return nullptr;
-}
-
-clang::FunctionDecl *
-TypeSystemClang::DeclContextGetAsFunctionDecl(const CompilerDeclContext &dc) {
-  if (IsClangDeclContext(dc))
-    return llvm::dyn_cast<clang::FunctionDecl>(
-        (clang::DeclContext *)dc.GetOpaqueDeclContext());
-  return nullptr;
-}
-
-clang::NamespaceDecl *
-TypeSystemClang::DeclContextGetAsNamespaceDecl(const CompilerDeclContext &dc) {
-  if (IsClangDeclContext(dc))
-    return llvm::dyn_cast<clang::NamespaceDecl>(
-        (clang::DeclContext *)dc.GetOpaqueDeclContext());
-  return nullptr;
-}
-
-ClangASTMetadata *
-TypeSystemClang::DeclContextGetMetaData(const CompilerDeclContext &dc,
-                                        const Decl *object) {
-  TypeSystemClang *ast = llvm::cast<TypeSystemClang>(dc.GetTypeSystem());
-  return ast->GetMetadata(object);
-}
-
-clang::ASTContext *
-TypeSystemClang::DeclContextGetTypeSystemClang(const CompilerDeclContext &dc) {
-  TypeSystemClang *ast =
-      llvm::dyn_cast_or_null<TypeSystemClang>(dc.GetTypeSystem());
-  if (ast)
-    return &ast->getASTContext();
-  return nullptr;
-}
-
-TypeSystemClangForExpressions::TypeSystemClangForExpressions(
-    Target &target, llvm::Triple triple)
-    : TypeSystemClang("scratch ASTContext", triple),
-      m_target_wp(target.shared_from_this()),
-      m_persistent_variables(new ClangPersistentVariables) {
-  m_scratch_ast_source_up.reset(new ClangASTSource(
-      target.shared_from_this(), m_persistent_variables->GetClangASTImporter()));
-  m_scratch_ast_source_up->InstallASTContext(*this);
-  llvm::IntrusiveRefCntPtr<clang::ExternalASTSource> proxy_ast_source(
-      m_scratch_ast_source_up->CreateProxy());
-  SetExternalSource(proxy_ast_source);
-}
-
-void TypeSystemClangForExpressions::Finalize() {
-  TypeSystemClang::Finalize();
-  m_scratch_ast_source_up.reset();
-}
-
-UserExpression *TypeSystemClangForExpressions::GetUserExpression(
-    llvm::StringRef expr, llvm::StringRef prefix, lldb::LanguageType language,
-    Expression::ResultType desired_type,
-    const EvaluateExpressionOptions &options,
-    ValueObject *ctx_obj) {
-  TargetSP target_sp = m_target_wp.lock();
-  if (!target_sp)
-    return nullptr;
-
-  return new ClangUserExpression(*target_sp.get(), expr, prefix, language,
-                                 desired_type, options, ctx_obj);
-}
-
-FunctionCaller *TypeSystemClangForExpressions::GetFunctionCaller(
-    const CompilerType &return_type, const Address &function_address,
-    const ValueList &arg_value_list, const char *name) {
-  TargetSP target_sp = m_target_wp.lock();
-  if (!target_sp)
-    return nullptr;
-
-  Process *process = target_sp->GetProcessSP().get();
-  if (!process)
-    return nullptr;
-
-  return new ClangFunctionCaller(*process, return_type, function_address,
-                                 arg_value_list, name);
-}
-
-UtilityFunction *
-TypeSystemClangForExpressions::GetUtilityFunction(const char *text,
-                                                  const char *name) {
-  TargetSP target_sp = m_target_wp.lock();
-  if (!target_sp)
-    return nullptr;
-
-  return new ClangUtilityFunction(*target_sp.get(), text, name);
-}
-
-PersistentExpressionState *
-TypeSystemClangForExpressions::GetPersistentExpressionState() {
-  return m_persistent_variables.get();
-}
index 37147a8807a0d2ce62edb43e1acca556a07530c5..5cc998f6031bede93add2642496bb688493a90d0 100644 (file)
@@ -12,7 +12,6 @@
 #include "lldb/Host/Host.h"
 #include "lldb/Initialization/SystemInitializerCommon.h"
 #include "lldb/Interpreter/CommandInterpreter.h"
-#include "lldb/Symbol/TypeSystemClang.h"
 #include "lldb/Utility/Timer.h"
 
 #include "Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.h"
@@ -85,6 +84,7 @@
 #include "Plugins/SymbolVendor/ELF/SymbolVendorELF.h"
 #include "Plugins/SymbolVendor/wasm/SymbolVendorWasm.h"
 #include "Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.h"
+#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
 #include "Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.h"
 #include "Plugins/UnwindAssembly/x86/UnwindAssembly-x86.h"
 
index 696f64cdeff9e3450115afb7f8c8c85b42282cf4..0bd532fa2945a982f22d963bd6292d62e9d82437 100644 (file)
@@ -10,6 +10,7 @@
 #include "SystemInitializerTest.h"
 
 #include "Plugins/SymbolFile/DWARF/SymbolFileDWARF.h"
+#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
 #include "lldb/Breakpoint/BreakpointLocation.h"
 #include "lldb/Core/Debugger.h"
 #include "lldb/Core/Module.h"
@@ -18,7 +19,6 @@
 #include "lldb/Initialization/SystemLifetimeManager.h"
 #include "lldb/Interpreter/CommandInterpreter.h"
 #include "lldb/Interpreter/CommandReturnObject.h"
-#include "lldb/Symbol/TypeSystemClang.h"
 #include "lldb/Symbol/CompileUnit.h"
 #include "lldb/Symbol/LineTable.h"
 #include "lldb/Symbol/SymbolFile.h"
index 25e94f4d88fdd1d73b771d15dc46b747f66f0357..2f5304ab212d9b6f1926c77646a2007019190df9 100644 (file)
@@ -8,6 +8,7 @@ add_lldb_unittest(ExpressionTests
   LINK_LIBS
     lldbCore
     lldbPluginExpressionParserClang
+    lldbPluginTypeSystemClang
     lldbUtility
     lldbUtilityHelpers
     LLVMTestingSupport
index 41a4868fa8211d77a1911a9220275b658d9cc764..7d1e0ed3b3657fb0e74d7c1f75adccc145b68b84 100644 (file)
@@ -7,12 +7,12 @@
 //===----------------------------------------------------------------------===//
 
 #include "Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h"
+#include "Plugins/ExpressionParser/Clang/ClangUtil.h"
+#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
 #include "TestingSupport/SubsystemRAII.h"
 #include "TestingSupport/Symbol/ClangTestUtils.h"
 #include "lldb/Host/FileSystem.h"
 #include "lldb/Host/HostInfo.h"
-#include "lldb/Symbol/TypeSystemClang.h"
-#include "lldb/Symbol/ClangUtil.h"
 #include "lldb/lldb-defines.h"
 #include "gtest/gtest.h"
 
index d726f6ecad098f036397bf75526abc91ac8acde5..76c7b645f277ad87c42a766fa30dcfc73f5f7bda 100644 (file)
@@ -15,6 +15,7 @@ add_lldb_unittest(SymbolTests
     lldbPluginObjectFileMachO
     lldbPluginSymbolFileDWARF
     lldbPluginSymbolFileSymtab
+    lldbPluginTypeSystemClang
     LLVMTestingSupport
   )
 
index 1340ef3ea62f7d089a8220fae8e3c4fc13c10fde..02151a20a20b8d4102d95c77ca63ee0b2fb2df2f 100644 (file)
@@ -8,14 +8,14 @@
 
 #include "gtest/gtest.h"
 
+#include "Plugins/ExpressionParser/Clang/ClangASTImporter.h"
+#include "Plugins/ExpressionParser/Clang/ClangASTMetadata.h"
+#include "Plugins/ExpressionParser/Clang/ClangUtil.h"
+#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
 #include "TestingSupport/SubsystemRAII.h"
 #include "TestingSupport/Symbol/ClangTestUtils.h"
 #include "lldb/Host/FileSystem.h"
 #include "lldb/Host/HostInfo.h"
-#include "lldb/Symbol/TypeSystemClang.h"
-#include "lldb/Symbol/ClangASTImporter.h"
-#include "lldb/Symbol/ClangASTMetadata.h"
-#include "lldb/Symbol/ClangUtil.h"
 #include "lldb/Symbol/Declaration.h"
 #include "clang/AST/DeclCXX.h"
 
index d0ac06713161d54996ed8b44c44d368ca23f01a5..389b338faa421a7320761b9cc660088624a5f824 100644 (file)
@@ -14,9 +14,9 @@
 #include "Plugins/ObjectFile/Mach-O/ObjectFileMachO.h"
 #include "Plugins/SymbolFile/DWARF/DWARFASTParserClang.h"
 #include "Plugins/SymbolFile/DWARF/SymbolFileDWARF.h"
+#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
 #include "TestingSupport/SubsystemRAII.h"
 #include "TestingSupport/TestUtilities.h"
-#include "lldb/Symbol/TypeSystemClang.h"
 
 #include "lldb/Core/Module.h"
 #include "lldb/Host/FileSystem.h"
index 7d90a925c46a8775e1c6d1e7730dc00ef798d919..b0a42a26fd6c14d861e3f150bdb17a0cdb4dfeb2 100644 (file)
@@ -6,12 +6,12 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "Plugins/ExpressionParser/Clang/ClangUtil.h"
+#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
 #include "TestingSupport/SubsystemRAII.h"
 #include "TestingSupport/Symbol/ClangTestUtils.h"
 #include "lldb/Host/FileSystem.h"
 #include "lldb/Host/HostInfo.h"
-#include "lldb/Symbol/TypeSystemClang.h"
-#include "lldb/Symbol/ClangUtil.h"
 #include "lldb/Symbol/Declaration.h"
 #include "clang/AST/DeclCXX.h"
 #include "clang/AST/ExprCXX.h"
index 57ee46316e03f23f8a80180b01ec6e4688bbd8e2..0a4d3cc2938da36169f78731b392603e524e9a4e 100644 (file)
@@ -9,6 +9,7 @@ add_lldb_unittest(SymbolFileDWARFTests
     lldbPluginObjectFilePECOFF
     lldbPluginSymbolFileDWARF
     lldbPluginSymbolFilePDB
+    lldbPluginTypeSystemClang
     lldbUtilityHelpers
   LINK_COMPONENTS
     Support
index e512d65937834bc75e7ee1ba9cbd7e8e2144d580..c971eda2d46ec42aae7f7c5807f34a35df5ad35b 100644 (file)
@@ -20,6 +20,7 @@
 #include "Plugins/SymbolFile/DWARF/DWARFDebugAbbrev.h"
 #include "Plugins/SymbolFile/DWARF/SymbolFileDWARF.h"
 #include "Plugins/SymbolFile/PDB/SymbolFilePDB.h"
+#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
 #include "TestingSupport/SubsystemRAII.h"
 #include "TestingSupport/TestUtilities.h"
 #include "lldb/Core/Address.h"
@@ -27,7 +28,6 @@
 #include "lldb/Core/ModuleSpec.h"
 #include "lldb/Host/FileSystem.h"
 #include "lldb/Host/HostInfo.h"
-#include "lldb/Symbol/TypeSystemClang.h"
 #include "lldb/Symbol/CompileUnit.h"
 #include "lldb/Symbol/LineTable.h"
 #include "lldb/Utility/ArchSpec.h"
@@ -35,8 +35,6 @@
 #include "lldb/Utility/FileSpec.h"
 #include "lldb/Utility/StreamString.h"
 
-
-
 using namespace lldb;
 using namespace lldb_private;
 
index 75e4b50424966f7e917f659fc0c20aa28784fd08..8fc2167ee6ba271978d63f3c2ae1a53b8f96ca11 100644 (file)
@@ -8,6 +8,7 @@ add_lldb_unittest(SymbolFilePDBTests
     lldbPluginObjectFilePECOFF
     lldbPluginSymbolFileDWARF
     lldbPluginSymbolFilePDB
+    lldbPluginTypeSystemClang
     lldbUtilityHelpers
     LLVMTestingSupport
   LINK_COMPONENTS
index 1db4adad1e642d7f388fe9393ada90f0f8ecdedd..880daaee056b9714463479511c0c9e1350ca7eab 100644 (file)
 #include "Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h"
 #include "Plugins/SymbolFile/DWARF/SymbolFileDWARF.h"
 #include "Plugins/SymbolFile/PDB/SymbolFilePDB.h"
+#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
 #include "TestingSupport/TestUtilities.h"
 #include "lldb/Core/Address.h"
 #include "lldb/Core/Module.h"
 #include "lldb/Core/ModuleSpec.h"
 #include "lldb/Host/FileSystem.h"
 #include "lldb/Host/HostInfo.h"
-#include "lldb/Symbol/TypeSystemClang.h"
 #include "lldb/Symbol/CompileUnit.h"
 #include "lldb/Symbol/LineTable.h"
 #include "lldb/Symbol/TypeMap.h"
index 8bb6e283db0fcc945cd89c5b54a4a7c63acd30c9..c6954af126797bfe5f11d49c938028e929938bdf 100644 (file)
@@ -9,9 +9,9 @@
 #ifndef LLDB_UNITTESTS_TESTINGSUPPORT_SYMBOL_CLANGTESTUTILS_H
 #define LLDB_UNITTESTS_TESTINGSUPPORT_SYMBOL_CLANGTESTUTILS_H
 
+#include "Plugins/ExpressionParser/Clang/ClangUtil.h"
+#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
 #include "lldb/Host/HostInfo.h"
-#include "lldb/Symbol/TypeSystemClang.h"
-#include "lldb/Symbol/ClangUtil.h"
 
 namespace lldb_private {
 namespace clang_utils {