Initial checkin of lldb code from internal Apple repo.


git-svn-id: https://llvm.org/svn/llvm-project/llvdb/trunk@105619 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/source/Symbol/ClangASTContext.cpp b/source/Symbol/ClangASTContext.cpp
new file mode 100644
index 0000000..be63de2
--- /dev/null
+++ b/source/Symbol/ClangASTContext.cpp
@@ -0,0 +1,2552 @@
+//===-- ClangASTContext.cpp -------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangASTContext.h"
+
+// C Includes
+// C++ Includes
+#include <string>
+
+// Other libraries and framework includes
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/ASTImporter.h"
+#include "clang/AST/CXXInheritance.h"
+#include "clang/AST/RecordLayout.h"
+#include "clang/AST/Type.h"
+#include "clang/Basic/Builtins.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/TargetOptions.h"
+#include "clang/Frontend/FrontendOptions.h"
+#include "clang/Frontend/LangStandard.h"
+
+// Project includes
+#include "lldb/Core/dwarf.h"
+
+using namespace lldb_private;
+using namespace llvm;
+using namespace clang;
+
+
+static void
+ParseLangArgs
+(
+    LangOptions &Opts,
+    FrontendOptions::InputKind IK
+)
+{
+    // FIXME: Cleanup per-file based stuff.
+
+    // Set some properties which depend soley 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 == FrontendOptions::IK_Asm) {
+        Opts.AsmPreprocessor = 1;
+    } else if (IK == FrontendOptions::IK_ObjC ||
+               IK == FrontendOptions::IK_ObjCXX ||
+               IK == FrontendOptions::IK_PreprocessedObjC ||
+               IK == FrontendOptions::IK_PreprocessedObjCXX) {
+        Opts.ObjC1 = Opts.ObjC2 = 1;
+    }
+
+    LangStandard::Kind LangStd = LangStandard::lang_unspecified;
+
+    if (LangStd == LangStandard::lang_unspecified) {
+        // Based on the base language, pick one.
+        switch (IK) {
+            case FrontendOptions::IK_None:
+            case FrontendOptions::IK_AST:
+                assert(0 && "Invalid input kind!");
+            case FrontendOptions::IK_OpenCL:
+                LangStd = LangStandard::lang_opencl;
+                break;
+            case FrontendOptions::IK_Asm:
+            case FrontendOptions::IK_C:
+            case FrontendOptions::IK_PreprocessedC:
+            case FrontendOptions::IK_ObjC:
+            case FrontendOptions::IK_PreprocessedObjC:
+                LangStd = LangStandard::lang_gnu99;
+                break;
+            case FrontendOptions::IK_CXX:
+            case FrontendOptions::IK_PreprocessedCXX:
+            case FrontendOptions::IK_ObjCXX:
+            case FrontendOptions::IK_PreprocessedObjCXX:
+                LangStd = LangStandard::lang_gnucxx98;
+                break;
+        }
+    }
+
+    const LangStandard &Std = LangStandard::getLangStandardForKind(LangStd);
+    Opts.BCPLComment = Std.hasBCPLComments();
+    Opts.C99 = Std.isC99();
+    Opts.CPlusPlus = Std.isCPlusPlus();
+    Opts.CPlusPlus0x = Std.isCPlusPlus0x();
+    Opts.Digraphs = Std.hasDigraphs();
+    Opts.GNUMode = Std.isGNUMode();
+    Opts.GNUInline = !Std.isC99();
+    Opts.HexFloats = Std.hasHexFloats();
+    Opts.ImplicitInt = Std.hasImplicitInt();
+
+    // OpenCL has some additional defaults.
+    if (LangStd == LangStandard::lang_opencl) {
+        Opts.OpenCL = 1;
+        Opts.AltiVec = 1;
+        Opts.CXXOperatorNames = 1;
+        Opts.LaxVectorConversions = 1;
+    }
+
+    // OpenCL and C++ both have bool, true, false keywords.
+    Opts.Bool = Opts.OpenCL || Opts.CPlusPlus;
+
+//    if (Opts.CPlusPlus)
+//        Opts.CXXOperatorNames = !Args.hasArg(OPT_fno_operator_names);
+//
+//    if (Args.hasArg(OPT_fobjc_gc_only))
+//        Opts.setGCMode(LangOptions::GCOnly);
+//    else if (Args.hasArg(OPT_fobjc_gc))
+//        Opts.setGCMode(LangOptions::HybridGC);
+//
+//    if (Args.hasArg(OPT_print_ivar_layout))
+//        Opts.ObjCGCBitmapPrint = 1;
+//
+//    if (Args.hasArg(OPT_faltivec))
+//        Opts.AltiVec = 1;
+//
+//    if (Args.hasArg(OPT_pthread))
+//        Opts.POSIXThreads = 1;
+//
+//    llvm::StringRef Vis = getLastArgValue(Args, OPT_fvisibility,
+//                                          "default");
+//    if (Vis == "default")
+        Opts.setVisibilityMode(LangOptions::Default);
+//    else if (Vis == "hidden")
+//        Opts.setVisibilityMode(LangOptions::Hidden);
+//    else if (Vis == "protected")
+//        Opts.setVisibilityMode(LangOptions::Protected);
+//    else
+//        Diags.Report(diag::err_drv_invalid_value)
+//        << Args.getLastArg(OPT_fvisibility)->getAsString(Args) << Vis;
+
+//    Opts.OverflowChecking = Args.hasArg(OPT_ftrapv);
+
+    // Mimicing gcc's behavior, trigraphs are only enabled if -trigraphs
+    // is specified, or -std is set to a conforming mode.
+    Opts.Trigraphs = !Opts.GNUMode;
+//    if (Args.hasArg(OPT_trigraphs))
+//        Opts.Trigraphs = 1;
+//
+//    Opts.DollarIdents = Args.hasFlag(OPT_fdollars_in_identifiers,
+//                                     OPT_fno_dollars_in_identifiers,
+//                                     !Opts.AsmPreprocessor);
+//    Opts.PascalStrings = Args.hasArg(OPT_fpascal_strings);
+//    Opts.Microsoft = Args.hasArg(OPT_fms_extensions);
+//    Opts.WritableStrings = Args.hasArg(OPT_fwritable_strings);
+//    if (Args.hasArg(OPT_fno_lax_vector_conversions))
+//        Opts.LaxVectorConversions = 0;
+//    Opts.Exceptions = Args.hasArg(OPT_fexceptions);
+//    Opts.RTTI = !Args.hasArg(OPT_fno_rtti);
+//    Opts.Blocks = Args.hasArg(OPT_fblocks);
+//    Opts.CharIsSigned = !Args.hasArg(OPT_fno_signed_char);
+//    Opts.ShortWChar = Args.hasArg(OPT_fshort_wchar);
+//    Opts.Freestanding = Args.hasArg(OPT_ffreestanding);
+//    Opts.NoBuiltin = Args.hasArg(OPT_fno_builtin) || Opts.Freestanding;
+//    Opts.AssumeSaneOperatorNew = !Args.hasArg(OPT_fno_assume_sane_operator_new);
+//    Opts.HeinousExtensions = Args.hasArg(OPT_fheinous_gnu_extensions);
+//    Opts.AccessControl = Args.hasArg(OPT_faccess_control);
+//    Opts.ElideConstructors = !Args.hasArg(OPT_fno_elide_constructors);
+//    Opts.MathErrno = !Args.hasArg(OPT_fno_math_errno);
+//    Opts.InstantiationDepth = getLastArgIntValue(Args, OPT_ftemplate_depth, 99,
+//                                                 Diags);
+//    Opts.NeXTRuntime = !Args.hasArg(OPT_fgnu_runtime);
+//    Opts.ObjCConstantStringClass = getLastArgValue(Args,
+//                                                   OPT_fconstant_string_class);
+//    Opts.ObjCNonFragileABI = Args.hasArg(OPT_fobjc_nonfragile_abi);
+//    Opts.CatchUndefined = Args.hasArg(OPT_fcatch_undefined_behavior);
+//    Opts.EmitAllDecls = Args.hasArg(OPT_femit_all_decls);
+//    Opts.PICLevel = getLastArgIntValue(Args, OPT_pic_level, 0, Diags);
+//    Opts.Static = Args.hasArg(OPT_static_define);
+    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.NoInline = !Opt;
+
+//    unsigned SSP = getLastArgIntValue(Args, OPT_stack_protector, 0, Diags);
+//    switch (SSP) {
+//        default:
+//            Diags.Report(diag::err_drv_invalid_value)
+//            << Args.getLastArg(OPT_stack_protector)->getAsString(Args) << SSP;
+//            break;
+//        case 0: Opts.setStackProtectorMode(LangOptions::SSPOff); break;
+//        case 1: Opts.setStackProtectorMode(LangOptions::SSPOn);  break;
+//        case 2: Opts.setStackProtectorMode(LangOptions::SSPReq); break;
+//    }
+}
+
+//----------------------------------------------------------------------
+// ClangASTContext constructor
+//----------------------------------------------------------------------
+//ClangASTContext::ClangASTContext(Module *module) :
+//  m_target_triple(),
+//  m_ast_context_ap(),
+//  m_language_options_ap(),
+//  m_source_manager_ap(),
+//  m_target_info_ap(),
+//  m_identifier_table_ap(),
+//  m_selector_table_ap(),
+//  m_builtins_ap()
+//{
+//  if (module)
+//  {
+//      ObjectFile * objfile = module->GetObjectFile();
+//      if (objfile)
+//          objfile->GetTargetTriple(m_target_triple);
+//  }
+//}
+
+//ClangASTContext::ClangASTContext(const ConstString& target_triple) :
+//  m_target_triple(target_triple),
+//  m_ast_context_ap(),
+//  m_language_options_ap(),
+//  m_source_manager_ap(),
+//  m_target_info_ap(),
+//  m_identifier_table_ap(),
+//  m_selector_table_ap(),
+//  m_builtins_ap()
+//{
+//}
+ClangASTContext::ClangASTContext(const char *target_triple) :
+    m_target_triple(),
+    m_ast_context_ap(),
+    m_language_options_ap(),
+    m_source_manager_ap(),
+    m_diagnostic_ap(),
+    m_target_options_ap(),
+    m_target_info_ap(),
+    m_identifier_table_ap(),
+    m_selector_table_ap(),
+    m_builtins_ap()
+{
+    if (target_triple && target_triple[0])
+        m_target_triple.assign (target_triple);
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+ClangASTContext::~ClangASTContext()
+{
+    m_builtins_ap.reset();
+    m_selector_table_ap.reset();
+    m_identifier_table_ap.reset();
+    m_target_info_ap.reset();
+    m_target_options_ap.reset();
+    m_diagnostic_ap.reset();
+    m_source_manager_ap.reset();
+    m_language_options_ap.reset();
+    m_ast_context_ap.reset();
+}
+
+
+void
+ClangASTContext::Clear()
+{
+    m_ast_context_ap.reset();
+    m_language_options_ap.reset();
+    m_source_manager_ap.reset();
+    m_diagnostic_ap.reset();
+    m_target_options_ap.reset();
+    m_target_info_ap.reset();
+    m_identifier_table_ap.reset();
+    m_selector_table_ap.reset();
+    m_builtins_ap.reset();
+}
+
+const char *
+ClangASTContext::GetTargetTriple ()
+{
+    return m_target_triple.c_str();
+}
+
+void
+ClangASTContext::SetTargetTriple (const char *target_triple)
+{
+    Clear();
+    m_target_triple.assign(target_triple);
+}
+
+
+ASTContext *
+ClangASTContext::getASTContext()
+{
+    if (m_ast_context_ap.get() == NULL)
+    {
+        m_ast_context_ap.reset(
+            new ASTContext(
+                *getLanguageOptions(),
+                *getSourceManager(),
+                *getTargetInfo(),
+                *getIdentifierTable(),
+                *getSelectorTable(),
+                *getBuiltinContext()));
+    }
+    return m_ast_context_ap.get();
+}
+
+Builtin::Context *
+ClangASTContext::getBuiltinContext()
+{
+    if (m_builtins_ap.get() == NULL)
+        m_builtins_ap.reset (new Builtin::Context(*getTargetInfo()));
+    return m_builtins_ap.get();
+}
+
+IdentifierTable *
+ClangASTContext::getIdentifierTable()
+{
+    if (m_identifier_table_ap.get() == NULL)
+        m_identifier_table_ap.reset(new IdentifierTable (*ClangASTContext::getLanguageOptions(), NULL));
+    return m_identifier_table_ap.get();
+}
+
+LangOptions *
+ClangASTContext::getLanguageOptions()
+{
+    if (m_language_options_ap.get() == NULL)
+    {
+        m_language_options_ap.reset(new LangOptions());
+        ParseLangArgs(*m_language_options_ap, FrontendOptions::IK_ObjCXX);
+//        InitializeLangOptions(*m_language_options_ap, FrontendOptions::IK_ObjCXX);
+    }
+    return m_language_options_ap.get();
+}
+
+SelectorTable *
+ClangASTContext::getSelectorTable()
+{
+    if (m_selector_table_ap.get() == NULL)
+        m_selector_table_ap.reset (new SelectorTable());
+    return m_selector_table_ap.get();
+}
+
+SourceManager *
+ClangASTContext::getSourceManager()
+{
+    if (m_source_manager_ap.get() == NULL)
+        m_source_manager_ap.reset(new SourceManager(*getDiagnostic()));
+    return m_source_manager_ap.get();
+}
+
+Diagnostic *
+ClangASTContext::getDiagnostic()
+{
+    if (m_diagnostic_ap.get() == NULL)
+        m_diagnostic_ap.reset(new Diagnostic());
+    return m_diagnostic_ap.get();
+}
+
+TargetOptions *
+ClangASTContext::getTargetOptions()
+{
+    if (m_target_options_ap.get() == NULL && !m_target_triple.empty())
+    {
+        m_target_options_ap.reset (new TargetOptions());
+        if (m_target_options_ap.get())
+            m_target_options_ap->Triple = m_target_triple;
+    }
+    return m_target_options_ap.get();
+}
+
+
+TargetInfo *
+ClangASTContext::getTargetInfo()
+{
+    // target_triple should be something like "x86_64-apple-darwin10"
+    if (m_target_info_ap.get() == NULL && !m_target_triple.empty())
+        m_target_info_ap.reset (TargetInfo::CreateTargetInfo(*getDiagnostic(), *getTargetOptions()));
+    return m_target_info_ap.get();
+}
+
+#pragma mark Basic Types
+
+static inline bool
+QualTypeMatchesBitSize(const uint64_t bit_size, ASTContext *ast_context, QualType qual_type)
+{
+    uint64_t qual_type_bit_size = ast_context->getTypeSize(qual_type);
+    if (qual_type_bit_size == bit_size)
+        return true;
+    return false;
+}
+
+void *
+ClangASTContext::GetBuiltinTypeForEncodingAndBitSize (lldb::Encoding encoding, uint32_t bit_size)
+{
+    ASTContext *ast_context = getASTContext();
+
+    assert (ast_context != NULL);
+
+    return GetBuiltinTypeForEncodingAndBitSize (ast_context, encoding, bit_size);
+}
+
+void *
+ClangASTContext::GetBuiltinTypeForEncodingAndBitSize (clang::ASTContext *ast_context, lldb::Encoding encoding, uint32_t bit_size)
+{
+    if (!ast_context)
+        return NULL;
+    
+    switch (encoding)
+    {
+    case lldb::eEncodingInvalid:
+        if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->VoidPtrTy))
+            return ast_context->VoidPtrTy.getAsOpaquePtr();
+        break;
+        
+    case lldb::eEncodingUint:
+        if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->UnsignedCharTy))
+            return ast_context->UnsignedCharTy.getAsOpaquePtr();
+        if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->UnsignedShortTy))
+            return ast_context->UnsignedShortTy.getAsOpaquePtr();
+        if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->UnsignedIntTy))
+            return ast_context->UnsignedIntTy.getAsOpaquePtr();
+        if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->UnsignedLongTy))
+            return ast_context->UnsignedLongTy.getAsOpaquePtr();
+        if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->UnsignedLongLongTy))
+            return ast_context->UnsignedLongLongTy.getAsOpaquePtr();
+        if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->UnsignedInt128Ty))
+            return ast_context->UnsignedInt128Ty.getAsOpaquePtr();
+        break;
+        
+    case lldb::eEncodingSint:
+        if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->CharTy))
+            return ast_context->CharTy.getAsOpaquePtr();
+        if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->ShortTy))
+            return ast_context->ShortTy.getAsOpaquePtr();
+        if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->IntTy))
+            return ast_context->IntTy.getAsOpaquePtr();
+        if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->LongTy))
+            return ast_context->LongTy.getAsOpaquePtr();
+        if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->LongLongTy))
+            return ast_context->LongLongTy.getAsOpaquePtr();
+        if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->Int128Ty))
+            return ast_context->Int128Ty.getAsOpaquePtr();
+        break;
+        
+    case lldb::eEncodingIEEE754:
+        if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->FloatTy))
+            return ast_context->FloatTy.getAsOpaquePtr();
+        if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->DoubleTy))
+            return ast_context->DoubleTy.getAsOpaquePtr();
+        if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->LongDoubleTy))
+            return ast_context->LongDoubleTy.getAsOpaquePtr();
+        break;
+        
+    case lldb::eEncodingVector:
+    default:
+        break;
+    }
+    
+    return NULL;
+}
+
+void *
+ClangASTContext::GetBuiltinTypeForDWARFEncodingAndBitSize (const char *type_name, uint32_t dw_ate, uint32_t bit_size)
+{
+    ASTContext *ast_context = getASTContext();
+
+    #define streq(a,b) strcmp(a,b) == 0
+    assert (ast_context != NULL);
+    if (ast_context)
+    {
+        switch (dw_ate)
+        {
+        default:
+            break;
+
+        case DW_ATE_address:
+            if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->VoidPtrTy))
+                return ast_context->VoidPtrTy.getAsOpaquePtr();
+            break;
+
+        case DW_ATE_boolean:
+            if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->BoolTy))
+                return ast_context->BoolTy.getAsOpaquePtr();
+            if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->UnsignedCharTy))
+                return ast_context->UnsignedCharTy.getAsOpaquePtr();
+            if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->UnsignedShortTy))
+                return ast_context->UnsignedShortTy.getAsOpaquePtr();
+            if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->UnsignedIntTy))
+                return ast_context->UnsignedIntTy.getAsOpaquePtr();
+            break;
+
+        case DW_ATE_complex_float:
+            if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->FloatComplexTy))
+                return ast_context->FloatComplexTy.getAsOpaquePtr();
+            if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->DoubleComplexTy))
+                return ast_context->DoubleComplexTy.getAsOpaquePtr();
+            if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->LongDoubleComplexTy))
+                return ast_context->LongDoubleComplexTy.getAsOpaquePtr();
+            break;
+
+        case DW_ATE_float:
+            if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->FloatTy))
+                return ast_context->FloatTy.getAsOpaquePtr();
+            if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->DoubleTy))
+                return ast_context->DoubleTy.getAsOpaquePtr();
+            if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->LongDoubleTy))
+                return ast_context->LongDoubleTy.getAsOpaquePtr();
+            break;
+
+        case DW_ATE_signed:
+            if (type_name)
+            {
+                if (streq(type_name, "int") ||
+                    streq(type_name, "signed int"))
+                {
+                    if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->IntTy))
+                        return ast_context->IntTy.getAsOpaquePtr();
+                    if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->Int128Ty))
+                        return ast_context->Int128Ty.getAsOpaquePtr();
+                }
+
+                if (streq(type_name, "long int") ||
+                    streq(type_name, "long long int") ||
+                    streq(type_name, "signed long long"))
+                {
+                    if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->LongTy))
+                        return ast_context->LongTy.getAsOpaquePtr();
+                    if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->LongLongTy))
+                        return ast_context->LongLongTy.getAsOpaquePtr();
+                }
+
+                if (streq(type_name, "short") ||
+                    streq(type_name, "short int") ||
+                    streq(type_name, "signed short") ||
+                    streq(type_name, "short signed int"))
+                {
+                    if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->ShortTy))
+                        return ast_context->ShortTy.getAsOpaquePtr();
+                }
+
+                if (streq(type_name, "char") ||
+                    streq(type_name, "signed char"))
+                {
+                    if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->CharTy))
+                        return ast_context->CharTy.getAsOpaquePtr();
+                    if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->SignedCharTy))
+                        return ast_context->SignedCharTy.getAsOpaquePtr();
+                }
+
+                if (streq(type_name, "wchar_t"))
+                {
+                    if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->WCharTy))
+                        return ast_context->WCharTy.getAsOpaquePtr();
+                }
+
+            }
+            // We weren't able to match up a type name, just search by size
+            if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->CharTy))
+                return ast_context->CharTy.getAsOpaquePtr();
+            if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->ShortTy))
+                return ast_context->ShortTy.getAsOpaquePtr();
+            if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->IntTy))
+                return ast_context->IntTy.getAsOpaquePtr();
+            if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->LongTy))
+                return ast_context->LongTy.getAsOpaquePtr();
+            if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->LongLongTy))
+                return ast_context->LongLongTy.getAsOpaquePtr();
+            if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->Int128Ty))
+                return ast_context->Int128Ty.getAsOpaquePtr();
+            break;
+
+        case DW_ATE_signed_char:
+            if (type_name)
+            {
+                if (streq(type_name, "signed char"))
+                {
+                    if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->SignedCharTy))
+                        return ast_context->SignedCharTy.getAsOpaquePtr();
+                }
+            }
+            if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->CharTy))
+                return ast_context->CharTy.getAsOpaquePtr();
+            if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->SignedCharTy))
+                return ast_context->SignedCharTy.getAsOpaquePtr();
+            break;
+
+        case DW_ATE_unsigned:
+            if (type_name)
+            {
+                if (streq(type_name, "unsigned int"))
+                {
+                    if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->UnsignedIntTy))
+                        return ast_context->UnsignedIntTy.getAsOpaquePtr();
+                    if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->UnsignedInt128Ty))
+                        return ast_context->UnsignedInt128Ty.getAsOpaquePtr();
+                }
+
+                if (streq(type_name, "unsigned int") ||
+                    streq(type_name, "long unsigned int") ||
+                    streq(type_name, "unsigned long long"))
+                {
+                    if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->UnsignedLongTy))
+                        return ast_context->UnsignedLongTy.getAsOpaquePtr();
+                    if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->UnsignedLongLongTy))
+                        return ast_context->UnsignedLongLongTy.getAsOpaquePtr();
+                }
+
+                if (streq(type_name, "unsigned short") ||
+                    streq(type_name, "short unsigned int"))
+                {
+                    if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->UnsignedShortTy))
+                        return ast_context->UnsignedShortTy.getAsOpaquePtr();
+                }
+                if (streq(type_name, "unsigned char"))
+                {
+                    if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->UnsignedCharTy))
+                        return ast_context->UnsignedCharTy.getAsOpaquePtr();
+                }
+
+            }
+            // We weren't able to match up a type name, just search by size
+            if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->UnsignedCharTy))
+                return ast_context->UnsignedCharTy.getAsOpaquePtr();
+            if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->UnsignedShortTy))
+                return ast_context->UnsignedShortTy.getAsOpaquePtr();
+            if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->UnsignedIntTy))
+                return ast_context->UnsignedIntTy.getAsOpaquePtr();
+            if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->UnsignedLongTy))
+                return ast_context->UnsignedLongTy.getAsOpaquePtr();
+            if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->UnsignedLongLongTy))
+                return ast_context->UnsignedLongLongTy.getAsOpaquePtr();
+            if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->UnsignedInt128Ty))
+                return ast_context->UnsignedInt128Ty.getAsOpaquePtr();
+            break;
+
+        case DW_ATE_unsigned_char:
+            if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->UnsignedCharTy))
+                return ast_context->UnsignedCharTy.getAsOpaquePtr();
+            break;
+
+        case DW_ATE_imaginary_float:
+            break;
+        }
+    }
+    // This assert should fire for anything that we don't catch above so we know
+    // to fix any issues we run into.
+    assert (!"error: ClangASTContext::GetClangTypeForDWARFEncodingAndSize() contains an unhandled encoding. Fix this ASAP!");
+    return NULL;
+}
+
+void *
+ClangASTContext::GetVoidBuiltInType()
+{
+    return getASTContext()->VoidTy.getAsOpaquePtr();
+}
+
+void *
+ClangASTContext::GetCStringType (bool is_const)
+{
+    QualType char_type(getASTContext()->CharTy);
+    
+    if (is_const)
+        char_type.addConst();
+    
+    return getASTContext()->getPointerType(char_type).getAsOpaquePtr();
+}
+
+void *
+ClangASTContext::GetVoidPtrType (bool is_const)
+{
+    return GetVoidPtrType(getASTContext(), is_const);
+}
+
+void *
+ClangASTContext::GetVoidPtrType (clang::ASTContext *ast_context, bool is_const)
+{
+    QualType void_ptr_type(ast_context->VoidPtrTy);
+    
+    if (is_const)
+        void_ptr_type.addConst();
+    
+    return void_ptr_type.getAsOpaquePtr();
+}
+
+void *
+ClangASTContext::CopyType(clang::ASTContext *dest_context, 
+                          clang::ASTContext *source_context,
+                          void * clang_type)
+{
+    Diagnostic diagnostics;
+    FileManager file_manager;
+    ASTImporter importer(diagnostics,
+                         *dest_context, file_manager,
+                         *source_context, file_manager);
+    QualType ret = importer.Import(QualType::getFromOpaquePtr(clang_type));
+    return ret.getAsOpaquePtr();
+}
+
+#pragma mark CVR modifiers
+
+void *
+ClangASTContext::AddConstModifier (void *clang_type)
+{
+    if (clang_type)
+    {
+        QualType result(QualType::getFromOpaquePtr(clang_type));
+        result.addConst();
+        return result.getAsOpaquePtr();
+    }
+    return NULL;
+}
+
+void *
+ClangASTContext::AddRestrictModifier (void *clang_type)
+{
+    if (clang_type)
+    {
+        QualType result(QualType::getFromOpaquePtr(clang_type));
+        result.getQualifiers().setRestrict (true);
+        return result.getAsOpaquePtr();
+    }
+    return NULL;
+}
+
+void *
+ClangASTContext::AddVolatileModifier (void *clang_type)
+{
+    if (clang_type)
+    {
+        QualType result(QualType::getFromOpaquePtr(clang_type));
+        result.getQualifiers().setVolatile (true);
+        return result.getAsOpaquePtr();
+    }
+    return NULL;
+}
+
+#pragma mark Structure, Unions, Classes
+
+void *
+ClangASTContext::CreateRecordType (const char *name, int kind, DeclContext *decl_ctx)
+{
+    ASTContext *ast_context = getASTContext();
+    assert (ast_context != NULL);
+
+    if (decl_ctx == NULL)
+        decl_ctx = ast_context->getTranslationUnitDecl();
+
+    // 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.
+    CXXRecordDecl *decl = CXXRecordDecl::Create(*ast_context,
+                                                (TagDecl::TagKind)kind,
+                                                decl_ctx,
+                                                SourceLocation(),
+                                                name && name[0] ? &ast_context->Idents.get(name) : NULL);
+
+    return ast_context->getTagDeclType(decl).getAsOpaquePtr();
+}
+
+bool
+ClangASTContext::AddFieldToRecordType (void * record_clang_type, const char *name, void * field_type, int access, uint32_t bitfield_bit_size)
+{
+    if (record_clang_type == NULL || field_type == NULL)
+        return false;
+
+    ASTContext *ast_context = getASTContext();
+    IdentifierTable *identifier_table = getIdentifierTable();
+
+    assert (ast_context != NULL);
+    assert (identifier_table != NULL);
+
+    QualType record_qual_type(QualType::getFromOpaquePtr(record_clang_type));
+
+    Type *clang_type = record_qual_type.getTypePtr();
+    if (clang_type)
+    {
+        const RecordType *record_type = dyn_cast<RecordType>(clang_type);
+
+        if (record_type)
+        {
+            RecordDecl *record_decl = record_type->getDecl();
+
+            CXXRecordDecl *cxx_record_decl = dyn_cast<CXXRecordDecl>(record_decl);
+            if (cxx_record_decl)
+                cxx_record_decl->setEmpty (false);
+
+            clang::Expr *bit_width = NULL;
+            if (bitfield_bit_size != 0)
+            {
+                APInt bitfield_bit_size_apint(ast_context->getTypeSize(ast_context->IntTy), bitfield_bit_size);
+                bit_width = new (*ast_context)IntegerLiteral (bitfield_bit_size_apint, ast_context->IntTy, SourceLocation());
+            }
+            FieldDecl *field = FieldDecl::Create(*ast_context,
+                                                record_decl,
+                                                SourceLocation(),
+                                                name ? &identifier_table->get(name) : NULL, // Identifier
+                                                QualType::getFromOpaquePtr(field_type), // Field type
+                                                NULL,       // DeclaratorInfo *
+                                                bit_width,  // BitWidth
+                                                false);     // Mutable
+
+            field->setAccess((AccessSpecifier)access);
+
+            if (field)
+            {
+                record_decl->addDecl(field);
+                return true;
+            }
+        }
+    }
+    return false;
+}
+
+bool
+ClangASTContext::FieldIsBitfield (FieldDecl* field, uint32_t& bitfield_bit_size)
+{
+    return FieldIsBitfield(getASTContext(), field, bitfield_bit_size);
+}
+
+bool
+ClangASTContext::FieldIsBitfield
+(
+    ASTContext *ast_context,
+    FieldDecl* field,
+    uint32_t& bitfield_bit_size
+)
+{
+    if (ast_context == NULL || field == NULL)
+        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_context))
+            {
+                bitfield_bit_size = bit_width_apsint.getLimitedValue(UINT32_MAX);
+                return true;
+            }
+        }
+    }
+    return false;
+}
+
+bool
+ClangASTContext::RecordHasFields (const RecordDecl *record_decl)
+{
+    if (record_decl == NULL)
+        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;
+}
+
+void
+ClangASTContext::SetDefaultAccessForRecordFields (void *clang_qual_type, int default_accessibility, int *assigned_accessibilities, size_t num_assigned_accessibilities)
+{
+    if (clang_qual_type)
+    {
+        QualType qual_type(QualType::getFromOpaquePtr(clang_qual_type));
+        Type *clang_type = qual_type.getTypePtr();
+        if (clang_type)
+        {
+            RecordType *record_type = dyn_cast<RecordType>(clang_type);
+            if (record_type)
+            {
+                RecordDecl *record_decl = record_type->getDecl();
+                if (record_decl)
+                {
+                    uint32_t field_idx;
+                    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 ((AccessSpecifier)default_accessibility);
+                    }
+                }
+            }
+        }
+    }
+}
+
+#pragma mark C++ Base Classes
+
+CXXBaseSpecifier *
+ClangASTContext::CreateBaseClassSpecifier (void *base_class_type, int access, bool is_virtual, bool base_of_class)
+{
+    if (base_class_type)
+        return new CXXBaseSpecifier(SourceRange(), is_virtual, base_of_class, (AccessSpecifier)access, QualType::getFromOpaquePtr(base_class_type));
+    return NULL;
+}
+
+bool
+ClangASTContext::SetBaseClassesForClassType (void *class_clang_type, CXXBaseSpecifier const * const *base_classes, unsigned num_base_classes)
+{
+    if (class_clang_type)
+    {
+        ASTContext *ast_context = getASTContext();
+        IdentifierTable *identifier_table = getIdentifierTable();
+
+        assert (ast_context != NULL);
+        assert (identifier_table != NULL);
+
+        Type *clang_type = QualType::getFromOpaquePtr(class_clang_type).getTypePtr();
+        if (clang_type)
+        {
+            RecordType *record_type = dyn_cast<RecordType>(clang_type);
+            if (record_type)
+            {
+                CXXRecordDecl *cxx_record_decl = dyn_cast<CXXRecordDecl>(record_type->getDecl());
+                if (cxx_record_decl)
+                {
+                    //cxx_record_decl->setEmpty (false);
+                    cxx_record_decl->setBases(base_classes, num_base_classes);
+                    return true;
+                }
+            }
+        }
+    }
+    return false;
+}
+
+
+#pragma mark Aggregate Types
+
+bool
+ClangASTContext::IsAggregateType (void *clang_type)
+{
+    if (clang_type == NULL)
+        return false;
+
+    QualType qual_type (QualType::getFromOpaquePtr(clang_type));
+
+    if (qual_type->isAggregateType ())
+        return true;
+
+    switch (qual_type->getTypeClass())
+    {
+    case Type::IncompleteArray:
+    case Type::VariableArray:
+    case Type::ConstantArray:
+    case Type::ExtVector:
+    case Type::Vector:
+    case Type::Record:
+        return true;
+
+    case Type::Typedef:
+        return ClangASTContext::IsAggregateType (cast<TypedefType>(qual_type)->LookThroughTypedefs().getAsOpaquePtr());
+
+    default:
+        break;
+    }
+    // The clang type does have a value
+    return false;
+}
+
+uint32_t
+ClangASTContext::GetNumChildren (void *clang_qual_type, bool omit_empty_base_classes)
+{
+    if (clang_qual_type == NULL)
+        return 0;
+
+    uint32_t num_children = 0;
+    QualType qual_type(QualType::getFromOpaquePtr(clang_qual_type));
+    switch (qual_type->getTypeClass())
+    {
+    case Type::Record:
+        {
+            const RecordType *record_type = cast<RecordType>(qual_type.getTypePtr());
+            const RecordDecl *record_decl = record_type->getDecl();
+            assert(record_decl);
+            const CXXRecordDecl *cxx_record_decl = dyn_cast<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.
+                    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());
+
+                        // Skip empty base classes
+                        if (RecordHasFields(base_class_decl) == false)
+                            continue;
+
+                        num_children++;
+                    }
+                }
+                else
+                {
+                    // Include all base classes
+                    num_children += cxx_record_decl->getNumBases();
+                }
+
+            }
+            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 Type::ConstantArray:
+        num_children = cast<ConstantArrayType>(qual_type.getTypePtr())->getSize().getLimitedValue();
+        break;
+
+    case Type::Pointer:
+        {
+            PointerType *pointer_type = cast<PointerType>(qual_type.getTypePtr());
+            QualType pointee_type = pointer_type->getPointeeType();
+            uint32_t num_pointee_children = ClangASTContext::GetNumChildren (pointee_type.getAsOpaquePtr(), omit_empty_base_classes);
+            // 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 Type::Typedef:
+        num_children = ClangASTContext::GetNumChildren (cast<TypedefType>(qual_type)->LookThroughTypedefs().getAsOpaquePtr(), omit_empty_base_classes);
+        break;
+
+    default:
+        break;
+    }
+    return num_children;
+}
+
+
+void *
+ClangASTContext::GetChildClangTypeAtIndex
+(
+    const char *parent_name,
+    void *parent_clang_type,
+    uint32_t idx,
+    bool transparent_pointers,
+    bool omit_empty_base_classes,
+    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
+)
+{
+    if (parent_clang_type)
+
+        return GetChildClangTypeAtIndex (getASTContext(),
+                                         parent_name,
+                                         parent_clang_type,
+                                         idx,
+                                         transparent_pointers,
+                                         omit_empty_base_classes,
+                                         child_name,
+                                         child_byte_size,
+                                         child_byte_offset,
+                                         child_bitfield_bit_size,
+                                         child_bitfield_bit_offset);
+    return NULL;
+}
+
+void *
+ClangASTContext::GetChildClangTypeAtIndex
+(
+    ASTContext *ast_context,
+    const char *parent_name,
+    void *parent_clang_type,
+    uint32_t idx,
+    bool transparent_pointers,
+    bool omit_empty_base_classes,
+    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
+)
+{
+    if (parent_clang_type == NULL)
+        return NULL;
+
+    if (idx < ClangASTContext::GetNumChildren (parent_clang_type, omit_empty_base_classes))
+    {
+        uint32_t bit_offset;
+        child_bitfield_bit_size = 0;
+        child_bitfield_bit_offset = 0;
+        QualType parent_qual_type(QualType::getFromOpaquePtr(parent_clang_type));
+        switch (parent_qual_type->getTypeClass())
+        {
+        case Type::Record:
+            {
+                const RecordType *record_type = cast<RecordType>(parent_qual_type.getTypePtr());
+                const RecordDecl *record_decl = record_type->getDecl();
+                assert(record_decl);
+                const ASTRecordLayout &record_layout = ast_context->getASTRecordLayout(record_decl);
+                uint32_t child_idx = 0;
+
+                const CXXRecordDecl *cxx_record_decl = dyn_cast<CXXRecordDecl>(record_decl);
+                if (cxx_record_decl)
+                {
+                    // We might have base classes to print out first
+                    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 = NULL;
+
+                        // Skip empty base classes
+                        if (omit_empty_base_classes)
+                        {
+                            base_class_decl = cast<CXXRecordDecl>(base_class->getType()->getAs<RecordType>()->getDecl());
+                            if (RecordHasFields(base_class_decl) == false)
+                                continue;
+                        }
+
+                        if (idx == child_idx)
+                        {
+                            if (base_class_decl == NULL)
+                                base_class_decl = cast<CXXRecordDecl>(base_class->getType()->getAs<RecordType>()->getDecl());
+
+
+                            if (base_class->isVirtual())
+                                bit_offset = record_layout.getVBaseClassOffset(base_class_decl);
+                            else
+                                bit_offset = record_layout.getBaseClassOffset(base_class_decl);
+
+                            // Base classes should be a multiple of 8 bits in size
+                            assert (bit_offset % 8 == 0);
+                            child_byte_offset = bit_offset/8;
+                            std::string base_class_type_name(base_class->getType().getAsString());
+
+                            child_name.assign(base_class_type_name.c_str());
+
+                            uint64_t clang_type_info_bit_size = ast_context->getTypeSize(base_class->getType());
+
+                            // Base classes biut sizes should be a multiple of 8 bits in size
+                            assert (clang_type_info_bit_size % 8 == 0);
+                            child_byte_size = clang_type_info_bit_size / 8;
+                            return base_class->getType().getAsOpaquePtr();
+                        }
+                        // We don't increment the child index in the for loop since we might
+                        // be skipping empty base classes
+                        ++child_idx;
+                    }
+                }
+                const unsigned num_fields = record_layout.getFieldCount();
+
+                // Make sure index is in range...
+                uint32_t field_idx = 0;
+                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().c_str());
+
+                        // Figure out the type byte size (field_type_info.first) and
+                        // alignment (field_type_info.second) from the AST context.
+                        std::pair<uint64_t, unsigned> field_type_info = ast_context->getTypeInfo(field->getType());
+                        assert(field_idx < num_fields);
+
+                        child_byte_size = field_type_info.first / 8;
+
+                        // Figure out the field offset within the current struct/union/class type
+                        bit_offset = record_layout.getFieldOffset (field_idx);
+                        child_byte_offset = bit_offset / 8;
+                        if (ClangASTContext::FieldIsBitfield (ast_context, *field, child_bitfield_bit_size))
+                            child_bitfield_bit_offset = bit_offset % 8;
+
+                        return field->getType().getAsOpaquePtr();
+                    }
+                }
+            }
+            break;
+
+        case Type::ConstantArray:
+            {
+                const ConstantArrayType *array = cast<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_context->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 Type::Pointer:
+            {
+                PointerType *pointer_type = cast<PointerType>(parent_qual_type.getTypePtr());
+                QualType pointee_type = pointer_type->getPointeeType();
+
+                if (transparent_pointers && ClangASTContext::IsAggregateType (pointee_type.getAsOpaquePtr()))
+                {
+                    return GetChildClangTypeAtIndex (ast_context,
+                                                     parent_name,
+                                                     pointer_type->getPointeeType().getAsOpaquePtr(),
+                                                     idx,
+                                                     transparent_pointers,
+                                                     omit_empty_base_classes,
+                                                     child_name,
+                                                     child_byte_size,
+                                                     child_byte_offset,
+                                                     child_bitfield_bit_size,
+                                                     child_bitfield_bit_offset);
+                }
+                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_context->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;
+
+        case Type::Typedef:
+            return GetChildClangTypeAtIndex (ast_context,
+                                             parent_name,
+                                             cast<TypedefType>(parent_qual_type)->LookThroughTypedefs().getAsOpaquePtr(),
+                                             idx,
+                                             transparent_pointers,
+                                             omit_empty_base_classes,
+                                             child_name,
+                                             child_byte_size,
+                                             child_byte_offset,
+                                             child_bitfield_bit_size,
+                                             child_bitfield_bit_offset);
+            break;
+
+        default:
+            break;
+        }
+    }
+    return false;
+}
+
+static inline bool
+BaseSpecifierIsEmpty (const CXXBaseSpecifier *b)
+{
+    return ClangASTContext::RecordHasFields(cast<CXXRecordDecl>(b->getType()->getAs<RecordType>()->getDecl())) == false;
+}
+
+static uint32_t
+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;
+}
+
+
+static uint32_t
+GetIndexForRecordBase
+(
+    const RecordDecl *record_decl,
+    const CXXBaseSpecifier *base_spec,
+    bool omit_empty_base_classes
+)
+{
+    uint32_t child_idx = 0;
+
+    const CXXRecordDecl *cxx_record_decl = dyn_cast<CXXRecordDecl>(record_decl);
+
+//    const char *super_name = record_decl->getNameAsCString();
+//    const char *base_name = base_spec->getType()->getAs<RecordType>()->getDecl()->getNameAsCString();
+//    printf ("GetIndexForRecordChild (%s, %s)\n", super_name, base_name);
+//
+    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)
+        {
+            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<RecordType>()->getDecl()->getNameAsCString());
+//
+//
+            if (base_class == base_spec)
+                return child_idx;
+            ++child_idx;
+        }
+    }
+
+    return UINT32_MAX;
+}
+
+
+static uint32_t
+GetIndexForRecordChild
+(
+    const RecordDecl *record_decl,
+    NamedDecl *canonical_decl,
+    bool omit_empty_base_classes
+)
+{
+    uint32_t child_idx = GetNumBaseClasses (dyn_cast<CXXRecordDecl>(record_decl), omit_empty_base_classes);
+
+//    const CXXRecordDecl *cxx_record_decl = dyn_cast<CXXRecordDecl>(record_decl);
+//
+////    printf ("GetIndexForRecordChild (%s, %s)\n", record_decl->getNameAsCString(), canonical_decl->getNameAsCString());
+//    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)
+//        {
+//            if (omit_empty_base_classes)
+//            {
+//                if (BaseSpecifierIsEmpty (base_class))
+//                    continue;
+//            }
+//
+////            printf ("GetIndexForRecordChild (%s, %s) base[%u] = %s\n",
+////                    record_decl->getNameAsCString(),
+////                    canonical_decl->getNameAsCString(),
+////                    child_idx,
+////                    base_class->getType()->getAs<RecordType>()->getDecl()->getNameAsCString());
+//
+//
+//            CXXRecordDecl *curr_base_class_decl = cast<CXXRecordDecl>(base_class->getType()->getAs<RecordType>()->getDecl());
+//            if (curr_base_class_decl == canonical_decl)
+//            {
+//                return child_idx;
+//            }
+//            ++child_idx;
+//        }
+//    }
+//
+//    const uint32_t num_bases = child_idx;
+    RecordDecl::field_iterator field, field_end;
+    for (field = record_decl->field_begin(), field_end = record_decl->field_end();
+         field != field_end;
+         ++field, ++child_idx)
+    {
+//            printf ("GetIndexForRecordChild (%s, %s) field[%u] = %s\n",
+//                    record_decl->getNameAsCString(),
+//                    canonical_decl->getNameAsCString(),
+//                    child_idx - num_bases,
+//                    field->getNameAsCString());
+
+        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
+ClangASTContext::GetIndexOfChildMemberWithName
+(
+    ASTContext *ast_context,
+    void *clang_type,
+    const char *name,
+    bool omit_empty_base_classes,
+    std::vector<uint32_t>& child_indexes
+)
+{
+    if (clang_type && name && name[0])
+    {
+        QualType qual_type(QualType::getFromOpaquePtr(clang_type));
+        switch (qual_type->getTypeClass())
+        {
+        case Type::Record:
+            {
+                const RecordType *record_type = cast<RecordType>(qual_type.getTypePtr());
+                const RecordDecl *record_decl = record_type->getDecl();
+
+                assert(record_decl);
+                uint32_t child_idx = 0;
+
+                const CXXRecordDecl *cxx_record_decl = dyn_cast<CXXRecordDecl>(record_decl);
+
+                // Try and find a field that matches NAME
+                RecordDecl::field_iterator field, field_end;
+                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))
+                    {
+                        // We have to add on the number of base classes to this index!
+                        child_indexes.push_back (child_idx + GetNumBaseClasses (cxx_record_decl, omit_empty_base_classes));
+                        return child_indexes.size();
+                    }
+                }
+
+                if (cxx_record_decl)
+                {
+                    const 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...
+                    IdentifierInfo & ident_ref = ast_context->Idents.get(name, name + strlen (name));
+                    DeclarationName decl_name(&ident_ref);
+
+                    CXXBasePaths paths;
+                    if (cxx_record_decl->lookupInBases(CXXRecordDecl::FindOrdinaryMember,
+                                                       decl_name.getAsOpaquePtr(),
+                                                       paths))
+                    {
+                        uint32_t child_idx;
+                        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)
+                            {
+                                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 = cast<RecordDecl>(elem.Base->getType()->getAs<RecordType>()->getDecl());
+                                }
+                            }
+                            DeclContext::lookup_iterator named_decl_pos;
+                            for (named_decl_pos = path->Decls.first;
+                                 named_decl_pos != path->Decls.second && parent_record_decl;
+                                 ++named_decl_pos)
+                            {
+                                //printf ("path[%zu] = %s\n", child_indexes.size(), (*named_decl_pos)->getNameAsCString());
+
+                                child_idx = GetIndexForRecordChild (parent_record_decl, *named_decl_pos, 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 Type::ConstantArray:
+            {
+//                const ConstantArrayType *array = cast<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_context->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 Type::MemberPointerType:
+//            {
+//                MemberPointerType *mem_ptr_type = cast<MemberPointerType>(qual_type.getTypePtr());
+//                QualType pointee_type = mem_ptr_type->getPointeeType();
+//
+//                if (ClangASTContext::IsAggregateType (pointee_type.getAsOpaquePtr()))
+//                {
+//                    return GetIndexOfChildWithName (ast_context,
+//                                                    mem_ptr_type->getPointeeType().getAsOpaquePtr(),
+//                                                    name);
+//                }
+//            }
+//            break;
+//
+        case Type::LValueReference:
+        case Type::RValueReference:
+            {
+                ReferenceType *reference_type = cast<ReferenceType>(qual_type.getTypePtr());
+                QualType pointee_type = reference_type->getPointeeType();
+
+                if (ClangASTContext::IsAggregateType (pointee_type.getAsOpaquePtr()))
+                {
+                    return GetIndexOfChildMemberWithName (ast_context,
+                                                          reference_type->getPointeeType().getAsOpaquePtr(),
+                                                          name,
+                                                          omit_empty_base_classes,
+                                                          child_indexes);
+                }
+            }
+            break;
+
+        case Type::Pointer:
+            {
+                PointerType *pointer_type = cast<PointerType>(qual_type.getTypePtr());
+                QualType pointee_type = pointer_type->getPointeeType();
+
+                if (ClangASTContext::IsAggregateType (pointee_type.getAsOpaquePtr()))
+                {
+                    return GetIndexOfChildMemberWithName (ast_context,
+                                                          pointer_type->getPointeeType().getAsOpaquePtr(),
+                                                          name,
+                                                          omit_empty_base_classes,
+                                                          child_indexes);
+                }
+                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_context->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;
+
+        case Type::Typedef:
+            return GetIndexOfChildMemberWithName (ast_context,
+                                                  cast<TypedefType>(qual_type)->LookThroughTypedefs().getAsOpaquePtr(),
+                                                  name,
+                                                  omit_empty_base_classes,
+                                                  child_indexes);
+
+        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
+ClangASTContext::GetIndexOfChildWithName
+(
+    ASTContext *ast_context,
+    void *clang_type,
+    const char *name,
+    bool omit_empty_base_classes
+)
+{
+    if (clang_type && name && name[0])
+    {
+        QualType qual_type(QualType::getFromOpaquePtr(clang_type));
+        switch (qual_type->getTypeClass())
+        {
+        case Type::Record:
+            {
+                const RecordType *record_type = cast<RecordType>(qual_type.getTypePtr());
+                const RecordDecl *record_decl = record_type->getDecl();
+
+                assert(record_decl);
+                uint32_t child_idx = 0;
+
+                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)
+                    {
+                        // Skip empty base classes
+                        CXXRecordDecl *base_class_decl = cast<CXXRecordDecl>(base_class->getType()->getAs<RecordType>()->getDecl());
+                        if (omit_empty_base_classes && RecordHasFields(base_class_decl) == false)
+                            continue;
+
+                        if (base_class->getType().getAsString().compare (name) == 0)
+                            return child_idx;
+                        ++child_idx;
+                    }
+                }
+
+                // Try and find a field that matches NAME
+                RecordDecl::field_iterator field, field_end;
+                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 Type::ConstantArray:
+            {
+//                const ConstantArrayType *array = cast<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_context->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 Type::MemberPointerType:
+//            {
+//                MemberPointerType *mem_ptr_type = cast<MemberPointerType>(qual_type.getTypePtr());
+//                QualType pointee_type = mem_ptr_type->getPointeeType();
+//
+//                if (ClangASTContext::IsAggregateType (pointee_type.getAsOpaquePtr()))
+//                {
+//                    return GetIndexOfChildWithName (ast_context,
+//                                                    mem_ptr_type->getPointeeType().getAsOpaquePtr(),
+//                                                    name);
+//                }
+//            }
+//            break;
+//
+        case Type::LValueReference:
+        case Type::RValueReference:
+            {
+                ReferenceType *reference_type = cast<ReferenceType>(qual_type.getTypePtr());
+                QualType pointee_type = reference_type->getPointeeType();
+
+                if (ClangASTContext::IsAggregateType (pointee_type.getAsOpaquePtr()))
+                {
+                    return GetIndexOfChildWithName (ast_context,
+                                                    reference_type->getPointeeType().getAsOpaquePtr(),
+                                                    name,
+                                                    omit_empty_base_classes);
+                }
+            }
+            break;
+
+        case Type::Pointer:
+            {
+                PointerType *pointer_type = cast<PointerType>(qual_type.getTypePtr());
+                QualType pointee_type = pointer_type->getPointeeType();
+
+                if (ClangASTContext::IsAggregateType (pointee_type.getAsOpaquePtr()))
+                {
+                    return GetIndexOfChildWithName (ast_context,
+                                                    pointer_type->getPointeeType().getAsOpaquePtr(),
+                                                    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_context->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;
+
+        case Type::Typedef:
+            return GetIndexOfChildWithName (ast_context,
+                                            cast<TypedefType>(qual_type)->LookThroughTypedefs().getAsOpaquePtr(),
+                                            name,
+                                            omit_empty_base_classes);
+
+        default:
+            break;
+        }
+    }
+    return UINT32_MAX;
+}
+
+#pragma mark TagType
+
+bool
+ClangASTContext::SetTagTypeKind (void *tag_clang_type, int kind)
+{
+    if (tag_clang_type)
+    {
+        QualType tag_qual_type(QualType::getFromOpaquePtr(tag_clang_type));
+        Type *clang_type = tag_qual_type.getTypePtr();
+        if (clang_type)
+        {
+            TagType *tag_type = dyn_cast<TagType>(clang_type);
+            if (tag_type)
+            {
+                TagDecl *tag_decl = dyn_cast<TagDecl>(tag_type->getDecl());
+                if (tag_decl)
+                {
+                    tag_decl->setTagKind ((TagDecl::TagKind)kind);
+                    return true;
+                }
+            }
+        }
+    }
+    return false;
+}
+
+
+#pragma mark DeclContext Functions
+
+DeclContext *
+ClangASTContext::GetDeclContextForType (void *clang_type)
+{
+    if (clang_type == NULL)
+        return NULL;
+
+    QualType qual_type(QualType::getFromOpaquePtr(clang_type));
+    switch (qual_type->getTypeClass())
+    {
+    case Type::FunctionNoProto:         break;
+    case Type::FunctionProto:           break;
+    case Type::IncompleteArray:         break;
+    case Type::VariableArray:           break;
+    case Type::ConstantArray:           break;
+    case Type::ExtVector:               break;
+    case Type::Vector:                  break;
+    case Type::Builtin:                 break;
+    case Type::ObjCObjectPointer:       break;
+    case Type::BlockPointer:            break;
+    case Type::Pointer:                 break;
+    case Type::LValueReference:         break;
+    case Type::RValueReference:         break;
+    case Type::MemberPointer:           break;
+    case Type::Complex:                 break;
+    case Type::ObjCInterface:           break;
+    case Type::Record:
+        return cast<RecordType>(qual_type)->getDecl();
+    case Type::Enum:
+        return cast<EnumType>(qual_type)->getDecl();
+    case Type::Typedef:
+        return ClangASTContext::GetDeclContextForType (cast<TypedefType>(qual_type)->LookThroughTypedefs().getAsOpaquePtr());
+
+    case Type::TypeOfExpr:              break;
+    case Type::TypeOf:                  break;
+    case Type::Decltype:                break;
+    //case Type::QualifiedName:           break;
+    case Type::TemplateSpecialization:  break;
+    }
+    // No DeclContext in this type...
+    return NULL;
+}
+
+#pragma mark Namespace Declarations
+
+NamespaceDecl *
+ClangASTContext::GetUniqueNamespaceDeclaration (const char *name, const Declaration &decl, DeclContext *decl_ctx)
+{
+    // TODO: Do something intelligent with the Declaration object passed in
+    // like maybe filling in the SourceLocation with it...
+    if (name)
+    {
+        ASTContext *ast_context = getASTContext();
+        if (decl_ctx == NULL)
+            decl_ctx = ast_context->getTranslationUnitDecl();
+        return NamespaceDecl::Create(*ast_context, decl_ctx, SourceLocation(), &ast_context->Idents.get(name));
+    }
+    return NULL;
+}
+
+
+#pragma mark Function Types
+
+FunctionDecl *
+ClangASTContext::CreateFunctionDeclaration (const char *name, void *function_clang_type, int storage, bool is_inline)
+{
+    if (name)
+    {
+        ASTContext *ast_context = getASTContext();
+        assert (ast_context != NULL);
+
+        if (name && name[0])
+        {
+            return FunctionDecl::Create(*ast_context,
+                                        ast_context->getTranslationUnitDecl(),
+                                        SourceLocation(),
+                                        DeclarationName (&ast_context->Idents.get(name)),
+                                        QualType::getFromOpaquePtr(function_clang_type),
+                                        NULL,
+                                        (FunctionDecl::StorageClass)storage,
+                                        (FunctionDecl::StorageClass)storage,
+                                        is_inline);
+        }
+        else
+        {
+            return FunctionDecl::Create(*ast_context,
+                                        ast_context->getTranslationUnitDecl(),
+                                        SourceLocation(),
+                                        DeclarationName (),
+                                        QualType::getFromOpaquePtr(function_clang_type),
+                                        NULL,
+                                        (FunctionDecl::StorageClass)storage,
+                                        (FunctionDecl::StorageClass)storage,
+                                        is_inline);
+        }
+    }
+    return NULL;
+}
+
+void *
+ClangASTContext::CreateFunctionType (void *result_type, void **args, unsigned num_args, bool isVariadic, unsigned TypeQuals)
+{
+    ASTContext *ast_context = getASTContext();
+    assert (ast_context != NULL);
+    std::vector<QualType> qual_type_args;
+    for (unsigned i=0; i<num_args; ++i)
+        qual_type_args.push_back (QualType::getFromOpaquePtr(args[i]));
+
+    // TODO: Detect calling convention in DWARF?
+    return ast_context->getFunctionType(QualType::getFromOpaquePtr(result_type),
+                                        qual_type_args.data(),
+                                        qual_type_args.size(),
+                                        isVariadic,
+                                        TypeQuals,
+                                        false,  // hasExceptionSpec
+                                        false,  // hasAnyExceptionSpec,
+                                        0,      // NumExs
+                                        0,      // const QualType *ExArray
+                                        FunctionType::ExtInfo ()).getAsOpaquePtr();    // NoReturn);
+}
+
+ParmVarDecl *
+ClangASTContext::CreateParmeterDeclaration (const char *name, void * return_type, int storage)
+{
+    ASTContext *ast_context = getASTContext();
+    assert (ast_context != NULL);
+    return ParmVarDecl::Create(*ast_context,
+                                ast_context->getTranslationUnitDecl(),
+                                SourceLocation(),
+                                name && name[0] ? &ast_context->Idents.get(name) : NULL,
+                                QualType::getFromOpaquePtr(return_type),
+                                NULL,
+                                (VarDecl::StorageClass)storage,
+                                (VarDecl::StorageClass)storage,
+                                0);
+}
+
+void
+ClangASTContext::SetFunctionParameters (FunctionDecl *function_decl, ParmVarDecl **params, unsigned num_params)
+{
+    if (function_decl)
+        function_decl->setParams (params, num_params);
+}
+
+
+#pragma mark Array Types
+
+void *
+ClangASTContext::CreateArrayType (void *element_type, size_t element_count, uint32_t bit_stride)
+{
+    if (element_type)
+    {
+        ASTContext *ast_context = getASTContext();
+        assert (ast_context != NULL);
+        llvm::APInt ap_element_count (64, element_count);
+        return ast_context->getConstantArrayType(QualType::getFromOpaquePtr(element_type),
+                                                 ap_element_count,
+                                                 ArrayType::Normal,
+                                                 0).getAsOpaquePtr(); // ElemQuals
+    }
+    return NULL;
+}
+
+
+#pragma mark TagDecl
+
+bool
+ClangASTContext::StartTagDeclarationDefinition (void *clang_type)
+{
+    if (clang_type)
+    {
+        QualType qual_type (QualType::getFromOpaquePtr(clang_type));
+        Type *t = qual_type.getTypePtr();
+        if (t)
+        {
+            TagType *tag_type = dyn_cast<TagType>(t);
+            if (tag_type)
+            {
+                TagDecl *tag_decl = tag_type->getDecl();
+                if (tag_decl)
+                {
+                    tag_decl->startDefinition();
+                    return true;
+                }
+            }
+        }
+    }
+    return false;
+}
+
+bool
+ClangASTContext::CompleteTagDeclarationDefinition (void *clang_type)
+{
+    if (clang_type)
+    {
+        QualType qual_type (QualType::getFromOpaquePtr(clang_type));
+        Type *t = qual_type.getTypePtr();
+        if (t)
+        {
+            TagType *tag_type = dyn_cast<TagType>(t);
+            if (tag_type)
+            {
+                TagDecl *tag_decl = tag_type->getDecl();
+                if (tag_decl)
+                {
+                    tag_decl->completeDefinition();
+                    return true;
+                }
+            }
+        }
+    }
+    return false;
+}
+
+
+#pragma mark Enumeration Types
+
+void *
+ClangASTContext::CreateEnumerationType (const Declaration &decl, const char *name)
+{
+    // TODO: Do something intelligent with the Declaration object passed in
+    // like maybe filling in the SourceLocation with it...
+    ASTContext *ast_context = getASTContext();
+    assert (ast_context != NULL);
+    EnumDecl *enum_decl = EnumDecl::Create(*ast_context,
+                                           ast_context->getTranslationUnitDecl(),
+                                           SourceLocation(),
+                                           name && name[0] ? &ast_context->Idents.get(name) : NULL,
+                                           SourceLocation(),
+                                           NULL);
+    if (enum_decl)
+        return ast_context->getTagDeclType(enum_decl).getAsOpaquePtr();
+    return NULL;
+}
+
+bool
+ClangASTContext::AddEnumerationValueToEnumerationType
+(
+    void *enum_clang_type,
+    void *enumerator_clang_type,
+    const Declaration &decl,
+    const char *name,
+    int64_t enum_value,
+    uint32_t enum_value_bit_size
+)
+{
+    if (enum_clang_type && enumerator_clang_type && name)
+    {
+        // TODO: Do something intelligent with the Declaration object passed in
+        // like maybe filling in the SourceLocation with it...
+        ASTContext *ast_context = getASTContext();
+        IdentifierTable *identifier_table = getIdentifierTable();
+
+        assert (ast_context != NULL);
+        assert (identifier_table != NULL);
+        QualType enum_qual_type (QualType::getFromOpaquePtr(enum_clang_type));
+
+        Type *clang_type = enum_qual_type.getTypePtr();
+        if (clang_type)
+        {
+            const EnumType *enum_type = dyn_cast<EnumType>(clang_type);
+
+            if (enum_type)
+            {
+                llvm::APSInt enum_llvm_apsint(enum_value_bit_size, false);
+                enum_llvm_apsint = enum_value;
+                EnumConstantDecl *enumerator_decl =
+                    EnumConstantDecl::Create(*ast_context,
+                                             enum_type->getDecl(),
+                                             SourceLocation(),
+                                             name ? &identifier_table->get(name) : NULL,    // Identifier
+                                             QualType::getFromOpaquePtr(enumerator_clang_type),
+                                             NULL,
+                                             enum_llvm_apsint);
+
+                if (enumerator_decl)
+                {
+                    enum_type->getDecl()->addDecl(enumerator_decl);
+                    return true;
+                }
+            }
+        }
+    }
+    return false;
+}
+
+#pragma mark Pointers & References
+
+void *
+ClangASTContext::CreatePointerType (void *clang_type)
+{
+    if (clang_type)
+        return getASTContext()->getPointerType(QualType::getFromOpaquePtr(clang_type)).getAsOpaquePtr();
+    return NULL;
+}
+
+void *
+ClangASTContext::CreateLValueReferenceType (void *clang_type)
+{
+    if (clang_type)
+        return getASTContext()->getLValueReferenceType (QualType::getFromOpaquePtr(clang_type)).getAsOpaquePtr();
+    return NULL;
+}
+
+void *
+ClangASTContext::CreateRValueReferenceType (void *clang_type)
+{
+    if (clang_type)
+        return getASTContext()->getRValueReferenceType (QualType::getFromOpaquePtr(clang_type)).getAsOpaquePtr();
+    return NULL;
+}
+
+size_t
+ClangASTContext::GetPointerBitSize ()
+{
+    ASTContext *ast_context = getASTContext();
+    return ast_context->getTypeSize(ast_context->VoidPtrTy);
+}
+
+bool
+ClangASTContext::IsPointerOrReferenceType (void *clang_type, void **target_type)
+{
+    if (clang_type == NULL)
+        return false;
+
+    QualType qual_type (QualType::getFromOpaquePtr(clang_type));
+    switch (qual_type->getTypeClass())
+    {
+    case Type::ObjCObjectPointer:
+        if (target_type)
+            *target_type = cast<ObjCObjectPointerType>(qual_type)->getPointeeType().getAsOpaquePtr();
+        return true;
+    case Type::BlockPointer:
+        if (target_type)
+            *target_type = cast<BlockPointerType>(qual_type)->getPointeeType().getAsOpaquePtr();
+        return true;
+    case Type::Pointer:
+        if (target_type)
+            *target_type = cast<PointerType>(qual_type)->getPointeeType().getAsOpaquePtr();
+        return true;
+    case Type::MemberPointer:
+        if (target_type)
+            *target_type = cast<MemberPointerType>(qual_type)->getPointeeType().getAsOpaquePtr();
+        return true;
+    case Type::LValueReference:
+        if (target_type)
+            *target_type = cast<LValueReferenceType>(qual_type)->desugar().getAsOpaquePtr();
+        return true;
+    case Type::RValueReference:
+        if (target_type)
+            *target_type = cast<LValueReferenceType>(qual_type)->desugar().getAsOpaquePtr();
+        return true;
+    case Type::Typedef:
+        return ClangASTContext::IsPointerOrReferenceType (cast<TypedefType>(qual_type)->LookThroughTypedefs().getAsOpaquePtr());
+    default:
+        break;
+    }
+    return false;
+}
+
+size_t
+ClangASTContext::GetTypeBitSize (clang::ASTContext *ast_context, void *clang_type)
+{
+    if (clang_type)
+        return ast_context->getTypeSize(QualType::getFromOpaquePtr(clang_type));
+    return 0;
+}
+
+size_t
+ClangASTContext::GetTypeBitAlign (clang::ASTContext *ast_context, void *clang_type)
+{
+    if (clang_type)
+        return ast_context->getTypeAlign(QualType::getFromOpaquePtr(clang_type));
+    return 0;
+}
+
+bool
+ClangASTContext::IsIntegerType (void * clang_type, bool &is_signed)
+{
+    if (!clang_type)
+        return false;
+    
+    QualType qual_type (QualType::getFromOpaquePtr(clang_type));
+    const BuiltinType *builtin_type = dyn_cast<BuiltinType>(qual_type->getCanonicalTypeInternal());
+    
+    if (builtin_type)
+    {
+        if (builtin_type->isInteger())
+            is_signed = builtin_type->isSignedInteger();
+        
+        return true;
+    }
+    
+    return false;
+}
+
+bool
+ClangASTContext::IsPointerType (void *clang_type, void **target_type)
+{
+    if (clang_type)
+    {
+        QualType qual_type (QualType::getFromOpaquePtr(clang_type));
+        switch (qual_type->getTypeClass())
+        {
+        case Type::ObjCObjectPointer:
+            if (target_type)
+                *target_type = cast<ObjCObjectPointerType>(qual_type)->getPointeeType().getAsOpaquePtr();
+            return true;
+        case Type::BlockPointer:
+            if (target_type)
+                *target_type = cast<BlockPointerType>(qual_type)->getPointeeType().getAsOpaquePtr();
+            return true;
+        case Type::Pointer:
+            if (target_type)
+                *target_type = cast<PointerType>(qual_type)->getPointeeType().getAsOpaquePtr();
+            return true;
+        case Type::MemberPointer:
+            if (target_type)
+                *target_type = cast<MemberPointerType>(qual_type)->getPointeeType().getAsOpaquePtr();
+            return true;
+        case Type::Typedef:
+            return ClangASTContext::IsPointerOrReferenceType (cast<TypedefType>(qual_type)->LookThroughTypedefs().getAsOpaquePtr(), target_type);
+        default:
+            break;
+        }
+    }
+    return false;
+}
+
+bool
+ClangASTContext::IsFloatingPointType (void *clang_type, uint32_t &count, bool &is_complex)
+{
+    if (clang_type)
+    {
+        QualType qual_type (QualType::getFromOpaquePtr(clang_type));
+
+        if (const BuiltinType *BT = dyn_cast<BuiltinType>(qual_type->getCanonicalTypeInternal()))
+        {
+            clang::BuiltinType::Kind kind = BT->getKind();
+            if (kind >= BuiltinType::Float && kind <= BuiltinType::LongDouble)
+            {
+                count = 1;
+                is_complex = false;
+                return true;
+            }
+        }
+        else if (const ComplexType *CT = dyn_cast<ComplexType>(qual_type->getCanonicalTypeInternal()))
+        {
+            if (IsFloatingPointType(CT->getElementType().getAsOpaquePtr(), count, is_complex))
+            {
+                count = 2;
+                is_complex = true;
+                return true;
+            }
+        }
+        else if (const VectorType *VT = dyn_cast<VectorType>(qual_type->getCanonicalTypeInternal()))
+        {
+            if (IsFloatingPointType(VT->getElementType().getAsOpaquePtr(), count, is_complex))
+            {
+                count = VT->getNumElements();
+                is_complex = false;
+                return true;
+            }
+        }
+    }
+    return false;
+}
+
+
+bool
+ClangASTContext::IsCStringType (void *clang_type, uint32_t &length)
+{
+    if (clang_type)
+    {
+        QualType qual_type (QualType::getFromOpaquePtr(clang_type));
+        switch (qual_type->getTypeClass())
+        {
+        case Type::ConstantArray:
+            {
+                ConstantArrayType *array = cast<ConstantArrayType>(qual_type.getTypePtr());
+                QualType element_qual_type = array->getElementType();
+                Type *canonical_type = element_qual_type->getCanonicalTypeInternal().getTypePtr();
+                if (canonical_type && canonical_type->isCharType())
+                {
+                    // We know the size of the array and it could be a C string
+                    // since it is an array of characters
+                    length = array->getSize().getLimitedValue();
+                    return true;
+                }
+            }
+            break;
+
+        case Type::Pointer:
+            {
+                PointerType *pointer_type = cast<PointerType>(qual_type.getTypePtr());
+                Type *pointee_type_ptr = pointer_type->getPointeeType().getTypePtr();
+                if (pointee_type_ptr)
+                {
+                    Type *canonical_type_ptr = pointee_type_ptr->getCanonicalTypeInternal().getTypePtr();
+                    length = 0; // No length info, read until a NULL terminator is received
+                    if (canonical_type_ptr)
+                        return canonical_type_ptr->isCharType();
+                    else
+                        return pointee_type_ptr->isCharType();
+                }
+            }
+            break;
+
+        case Type::Typedef:
+            return ClangASTContext::IsCStringType (cast<TypedefType>(qual_type)->LookThroughTypedefs().getAsOpaquePtr(), length);
+
+        case Type::LValueReference:
+        case Type::RValueReference:
+            {
+                ReferenceType *reference_type = cast<ReferenceType>(qual_type.getTypePtr());
+                Type *pointee_type_ptr = reference_type->getPointeeType().getTypePtr();
+                if (pointee_type_ptr)
+                {
+                    Type *canonical_type_ptr = pointee_type_ptr->getCanonicalTypeInternal().getTypePtr();
+                    length = 0; // No length info, read until a NULL terminator is received
+                    if (canonical_type_ptr)
+                        return canonical_type_ptr->isCharType();
+                    else
+                        return pointee_type_ptr->isCharType();
+                }
+            }
+            break;
+        }
+    }
+    return false;
+}
+
+bool
+ClangASTContext::IsArrayType (void * clang_type, void **member_type, uint64_t *size)
+{
+    if (!clang_type)
+        return false;
+    
+    QualType qual_type (QualType::getFromOpaquePtr(clang_type));
+    
+    switch (qual_type->getTypeClass())
+    {
+    case Type::ConstantArray:
+        if (member_type)
+            *member_type = cast<ConstantArrayType>(qual_type)->getElementType().getAsOpaquePtr();
+        if (size)
+            *size = cast<ConstantArrayType>(qual_type)->getSize().getLimitedValue(ULONG_LONG_MAX);
+        return true;
+    case Type::IncompleteArray:
+        if (member_type)
+            *member_type = cast<IncompleteArrayType>(qual_type)->getElementType().getAsOpaquePtr();
+        if (size)
+            *size = 0;
+        return true;
+    case Type::VariableArray:
+        if (member_type)
+            *member_type = cast<VariableArrayType>(qual_type)->getElementType().getAsOpaquePtr();
+        if (size)
+            *size = 0;
+    case Type::DependentSizedArray:
+        if (member_type)
+            *member_type = cast<DependentSizedArrayType>(qual_type)->getElementType().getAsOpaquePtr();
+        if (size)
+            *size = 0;
+        return true;
+    }
+    return false;
+}
+
+
+#pragma mark Typedefs
+
+void *
+ClangASTContext::CreateTypedefType (const char *name, void *clang_type, DeclContext *decl_ctx)
+{
+    if (clang_type)
+    {
+        QualType qual_type (QualType::getFromOpaquePtr(clang_type));
+        ASTContext *ast_context = getASTContext();
+        IdentifierTable *identifier_table = getIdentifierTable();
+        assert (ast_context != NULL);
+        assert (identifier_table != NULL);
+        if (decl_ctx == NULL)
+            decl_ctx = ast_context->getTranslationUnitDecl();
+        TypedefDecl *decl = TypedefDecl::Create(*ast_context,
+                                                decl_ctx,
+                                                SourceLocation(),
+                                                name ? &identifier_table->get(name) : NULL, // Identifier
+                                                ast_context->CreateTypeSourceInfo(qual_type));
+
+        // Get a uniqued QualType for the typedef decl type
+        return ast_context->getTypedefType (decl).getAsOpaquePtr();
+    }
+    return NULL;
+}
+
+
+std::string
+ClangASTContext::GetTypeName (void *opaque_qual_type)
+{
+    std::string return_name;
+    
+    clang::QualType qual_type(clang::QualType::getFromOpaquePtr(opaque_qual_type));
+
+    const clang::TypedefType *typedef_type = qual_type->getAs<clang::TypedefType>();
+    if (typedef_type)
+    {
+        const clang::TypedefDecl *typedef_decl = typedef_type->getDecl();
+        return_name = typedef_decl->getQualifiedNameAsString();
+    }
+    else
+    {
+        return_name = qual_type.getAsString();
+    }
+
+    return return_name;
+}
+
+// Disable this for now since I can't seem to get a nicely formatted float
+// out of the APFloat class without just getting the float, double or quad
+// and then using a formatted print on it which defeats the purpose. We ideally
+// would like to get perfect string values for any kind of float semantics
+// so we can support remote targets. The code below also requires a patch to
+// llvm::APInt.
+//bool
+//ClangASTContext::ConvertFloatValueToString (ASTContext *ast_context, void *clang_type, const uint8_t* bytes, size_t byte_size, int apint_byte_order, std::string &float_str)
+//{
+//  uint32_t count = 0;
+//  bool is_complex = false;
+//  if (ClangASTContext::IsFloatingPointType (clang_type, count, is_complex))
+//  {
+//      unsigned num_bytes_per_float = byte_size / count;
+//      unsigned num_bits_per_float = num_bytes_per_float * 8;
+//
+//      float_str.clear();
+//      uint32_t i;
+//      for (i=0; i<count; i++)
+//      {
+//          APInt ap_int(num_bits_per_float, bytes + i * num_bytes_per_float, (APInt::ByteOrder)apint_byte_order);
+//          bool is_ieee = false;
+//          APFloat ap_float(ap_int, is_ieee);
+//          char s[1024];
+//          unsigned int hex_digits = 0;
+//          bool upper_case = false;
+//
+//          if (ap_float.convertToHexString(s, hex_digits, upper_case, APFloat::rmNearestTiesToEven) > 0)
+//          {
+//              if (i > 0)
+//                  float_str.append(", ");
+//              float_str.append(s);
+//              if (i == 1 && is_complex)
+//                  float_str.append(1, 'i');
+//          }
+//      }
+//      return !float_str.empty();
+//  }
+//  return false;
+//}
+
+size_t
+ClangASTContext::ConvertStringToFloatValue (ASTContext *ast_context, void *clang_type, const char *s, uint8_t *dst, size_t dst_size)
+{
+    if (clang_type)
+    {
+        QualType qual_type (QualType::getFromOpaquePtr(clang_type));
+        uint32_t count = 0;
+        bool is_complex = false;
+        if (ClangASTContext::IsFloatingPointType (clang_type, count, is_complex))
+        {
+            // TODO: handle complex and vector types
+            if (count != 1)
+                return false;
+
+            StringRef s_sref(s);
+            APFloat ap_float(ast_context->getFloatTypeSemantics(qual_type), s_sref);
+
+            const uint64_t bit_size = ast_context->getTypeSize (qual_type);
+            const uint64_t byte_size = bit_size / 8;
+            if (dst_size >= byte_size)
+            {
+                if (bit_size == sizeof(float)*8)
+                {
+                    float float32 = ap_float.convertToFloat();
+                    ::memcpy (dst, &float32, byte_size);
+                    return byte_size;
+                }
+                else if (bit_size >= 64)
+                {
+                    llvm::APInt ap_int(ap_float.bitcastToAPInt());
+                    ::memcpy (dst, ap_int.getRawData(), byte_size);
+                    return byte_size;
+                }
+            }
+        }
+    }
+    return 0;
+}