I have brought LLDB up-to-date with top of tree
LLVM/Clang.  This brings in several fixes, including:

- Improvements in the Just-In-Time compiler's
  allocation of memory: the JIT now allocates
  memory in chunks of sections, improving its
  ability to generate relocations.  I have
  revamped the RecordingMemoryManager to reflect
  these changes, as well as to get the memory
  allocation and data copying out fo the
  ClangExpressionParser code.  Jim Grosbach wrote
  the updates to the JIT on the LLVM side.

- A new ExternalASTSource interface to allow LLDB to
  report accurate structure layout information to
  Clang.  Previously we could only report the sizes
  of fields, not their offsets.  This meant that if
  data structures included field alignment
  directives, we could not communicate the necessary
  alignment to Clang and accesses to the data would
  fail.  Now we can (and I have update the relevant
  test case).  Thanks to Doug Gregor for implementing
  the Clang side of this fix.

- The way Objective-C interfaces are completed by
  Clang has been made consistent with RecordDecls;
  with help from Doug Gregor and Greg Clayton I have
  ensured that this still works.

- I have eliminated all local LLVM and Clang patches,
  committing the ones that are still relevant to LLVM
  and Clang as needed.

I have tested the changes extensively locally, but
please let me know if they cause any trouble for you.


git-svn-id: https://llvm.org/svn/llvm-project/lldb/trunk@149775 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/source/Expression/ClangASTSource.cpp b/source/Expression/ClangASTSource.cpp
index 162dfab..738b342 100644
--- a/source/Expression/ClangASTSource.cpp
+++ b/source/Expression/ClangASTSource.cpp
@@ -9,6 +9,7 @@
 
 
 #include "clang/AST/ASTContext.h"
+#include "clang/AST/RecordLayout.h"
 #include "lldb/Core/Log.h"
 #include "lldb/Core/Module.h"
 #include "lldb/Core/ModuleList.h"
@@ -448,7 +449,7 @@
     }
     else if (isa<ObjCInterfaceDecl>(context.m_decl_context))
     {
-        FindObjCPropertyDecls(context);
+        FindObjCPropertyAndIvarDecls(context);
     }
     else if (!isa<TranslationUnitDecl>(context.m_decl_context))
     {
@@ -499,6 +500,12 @@
     
     const char *name_unique_cstr = name.GetCString();
     
+    static ConstString id_name("id");
+    static ConstString Class_name("Class");
+    
+    if (name == id_name || name == Class_name)
+        return;
+    
     if (name_unique_cstr == NULL)
         return;
     
@@ -567,16 +574,10 @@
         }
     }
     
-    static ConstString id_name("id");
-    static ConstString Class_name("Class");
-    
     do 
     {
         TypeList types;
         SymbolContext null_sc;
-        
-        if (name == id_name || name == Class_name)
-            break;
       
         if (module_sp && namespace_decl)
             module_sp->FindTypes(null_sc, name, &namespace_decl, true, 1, types);
@@ -788,62 +789,308 @@
     }
 }
 
+template <class D> class TaggedASTDecl {
+public:
+    TaggedASTDecl() : decl(NULL) { }
+    TaggedASTDecl(D *_decl) : decl(_decl) { }
+    bool IsValid() const { return (decl != NULL); }
+    bool IsInvalid() const { return !IsValid(); }
+    D *operator->() const { return decl; }
+    D *decl;
+};
+
+template <class D2, template <class D> class TD, class D1> 
+TD<D2>
+DynCast(TD<D1> source)
+{
+    return TD<D2> (dyn_cast<D2>(source.decl));
+}
+
+template <class D = Decl> class DeclFromParser;
+template <class D = Decl> class DeclFromUser;
+
+template <class D> class DeclFromParser : public TaggedASTDecl<D> { 
+public:
+    DeclFromParser() : TaggedASTDecl<D>() { }
+    DeclFromParser(D *_decl) : TaggedASTDecl<D>(_decl) { }
+    
+    DeclFromUser<D> GetOrigin(ClangASTImporter *importer);
+};
+
+template <class D> class DeclFromUser : public TaggedASTDecl<D> { 
+public:
+    DeclFromUser() : TaggedASTDecl<D>() { }
+    DeclFromUser(D *_decl) : TaggedASTDecl<D>(_decl) { }
+    
+    DeclFromParser<D> Import(ClangASTImporter *importer, ASTContext &dest_ctx);
+};
+
+template <class D>
+DeclFromUser<D>
+DeclFromParser<D>::GetOrigin(ClangASTImporter *importer)
+{
+    DeclFromUser <> origin_decl;
+    importer->ResolveDeclOrigin(this->decl, &origin_decl.decl, NULL);
+    if (origin_decl.IsInvalid())
+        return DeclFromUser<D>();
+    return DeclFromUser<D>(dyn_cast<D>(origin_decl.decl));
+}
+
+template <class D>
+DeclFromParser<D>
+DeclFromUser<D>::Import(ClangASTImporter *importer, ASTContext &dest_ctx)
+{
+    DeclFromParser <> parser_generic_decl(importer->CopyDecl(&dest_ctx, &this->decl->getASTContext(), this->decl));
+    if (parser_generic_decl.IsInvalid())
+        return DeclFromParser<D>();
+    return DeclFromParser<D>(dyn_cast<D>(parser_generic_decl.decl));
+}
+
 void
-ClangASTSource::FindObjCPropertyDecls (NameSearchContext &context)
+ClangASTSource::FindObjCPropertyAndIvarDecls (NameSearchContext &context)
 {
     lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
 
     static unsigned int invocation_id = 0;
     unsigned int current_id = invocation_id++;
     
-    const ObjCInterfaceDecl *iface_decl = cast<ObjCInterfaceDecl>(context.m_decl_context);
-    Decl *orig_decl;
-    ASTContext *orig_ast_ctx;
+    DeclFromParser<const ObjCInterfaceDecl> parser_iface_decl(cast<ObjCInterfaceDecl>(context.m_decl_context));
+    DeclFromUser<const ObjCInterfaceDecl> origin_iface_decl(parser_iface_decl.GetOrigin(m_ast_importer));
     
-    m_ast_importer->ResolveDeclOrigin(iface_decl, &orig_decl, &orig_ast_ctx);
-    
-    if (!orig_decl)
+    if (origin_iface_decl.IsInvalid())
         return;
     
-    ObjCInterfaceDecl *orig_iface_decl = dyn_cast<ObjCInterfaceDecl>(orig_decl);
-    
-    if (!orig_iface_decl)
-        return;
-    
-    if (!ClangASTContext::GetCompleteDecl(orig_ast_ctx, orig_iface_decl))
-        return;
-    
-    std::string property_name_str = context.m_decl_name.getAsString();
-    StringRef property_name(property_name_str.c_str());
-    ObjCPropertyDecl *property_decl = orig_iface_decl->FindPropertyDeclaration(&orig_ast_ctx->Idents.get(property_name));
+    std::string name_str = context.m_decl_name.getAsString();
+    StringRef name(name_str.c_str());
+    IdentifierInfo &name_identifier(origin_iface_decl->getASTContext().Idents.get(name));
     
     if (log)
-        log->Printf("ClangASTSource::FindObjCPropertyDecls[%d] on (ASTContext*)%p for property '%s.%s'",
+        log->Printf("ClangASTSource::FindObjCPropertyAndIvarDecls[%d] on (ASTContext*)%p for '%s.%s'",
                     current_id, 
                     m_ast_context,
-                    iface_decl->getNameAsString().c_str(), 
-                    property_name_str.c_str());
+                    parser_iface_decl->getNameAsString().c_str(), 
+                    name_str.c_str());
     
-    if (!property_decl)
-        return;
+    DeclFromUser<ObjCPropertyDecl> origin_property_decl(origin_iface_decl->FindPropertyDeclaration(&name_identifier));
     
-    Decl *copied_decl = m_ast_importer->CopyDecl(m_ast_context, orig_ast_ctx, property_decl);
+    if (origin_property_decl.IsValid())
+    {
+        DeclFromParser<ObjCPropertyDecl> parser_property_decl(origin_property_decl.Import(m_ast_importer, *m_ast_context));
+        if (parser_property_decl.IsValid())
+        {
+            if (log)
+            {
+                ASTDumper dumper((Decl*)parser_property_decl.decl);
+                log->Printf("  CAS::FOPD[%d] found %s", current_id, dumper.GetCString());
+            }
+            
+            context.AddNamedDecl(parser_property_decl.decl);
+        }
+    }
     
-    if (!copied_decl)
-        return;
+    DeclFromUser<ObjCIvarDecl> origin_ivar_decl(origin_iface_decl->getIvarDecl(&name_identifier));
     
-    ObjCPropertyDecl *copied_property_decl = dyn_cast<ObjCPropertyDecl>(copied_decl);
+    if (origin_ivar_decl.IsValid())
+    {
+        DeclFromParser<ObjCIvarDecl> parser_ivar_decl(origin_ivar_decl.Import(m_ast_importer, *m_ast_context));
+        if (parser_ivar_decl.IsValid())
+        {
+            if (log)
+            {
+                ASTDumper dumper((Decl*)parser_ivar_decl.decl);
+                log->Printf("  CAS::FOPD[%d] found %s", current_id, dumper.GetCString());
+            }
+            
+            context.AddNamedDecl(parser_ivar_decl.decl);
+        }
+    }
+}
+
+typedef llvm::DenseMap <const FieldDecl *, uint64_t> FieldOffsetMap;
+typedef llvm::DenseMap <const CXXRecordDecl *, CharUnits> BaseOffsetMap;
+
+template <class D, class O>
+static bool
+ImportOffsetMap (llvm::DenseMap <const D*, O> &destination_map, 
+                 llvm::DenseMap <const D*, O> &source_map,
+                 ClangASTImporter *importer,
+                 ASTContext &dest_ctx)
+{
+    typedef llvm::DenseMap <const D*, O> MapType;
     
-    if (!copied_property_decl)
-        return;
+    for (typename MapType::iterator fi = source_map.begin(), fe = source_map.end();
+         fi != fe;
+         ++fi)
+    {
+        DeclFromUser <D> user_decl(const_cast<D*>(fi->first));
+        DeclFromParser <D> parser_decl(user_decl.Import(importer, dest_ctx));
+        if (parser_decl.IsInvalid())
+            return false;
+        destination_map.insert(std::pair<const D *, O>(parser_decl.decl, fi->second));
+    }
+    
+    return true;
+}
+
+template <bool IsVirtual> bool ExtractBaseOffsets (const ASTRecordLayout &record_layout,
+                                                   DeclFromUser<const CXXRecordDecl> &record,
+                                                   BaseOffsetMap &base_offsets)
+{
+    for (CXXRecordDecl::base_class_const_iterator 
+            bi = (IsVirtual ? record->vbases_begin() : record->bases_begin()), 
+            be = (IsVirtual ? record->vbases_end() : record->bases_end());
+         bi != be;
+         ++bi)
+    {
+        if (!IsVirtual && bi->isVirtual())
+            continue;
+        
+        const clang::Type *origin_base_type = bi->getType().getTypePtr();
+        const clang::RecordType *origin_base_record_type = origin_base_type->getAs<RecordType>();
+        
+        if (!origin_base_record_type)
+            return false;
+        
+        DeclFromUser <RecordDecl> origin_base_record(origin_base_record_type->getDecl());
+        
+        if (origin_base_record.IsInvalid())
+            return false;
+        
+        DeclFromUser <CXXRecordDecl> origin_base_cxx_record(DynCast<CXXRecordDecl>(origin_base_record));
+        
+        if (origin_base_cxx_record.IsInvalid())
+            return false;
+        
+        CharUnits base_offset;
+        
+        if (IsVirtual)
+            base_offset = record_layout.getVBaseClassOffset(origin_base_cxx_record.decl);
+        else
+            base_offset = record_layout.getBaseClassOffset(origin_base_cxx_record.decl);
+        
+        base_offsets.insert(std::pair<const CXXRecordDecl *, CharUnits>(origin_base_cxx_record.decl, base_offset));
+    }
+    
+    return true;
+}
+                         
+bool 
+ClangASTSource::layoutRecordType(const RecordDecl *record,
+                                 uint64_t &size, 
+                                 uint64_t &alignment,
+                                 FieldOffsetMap &field_offsets,
+                                 BaseOffsetMap &base_offsets,
+                                 BaseOffsetMap &virtual_base_offsets)
+{
+    static unsigned int invocation_id = 0;
+    unsigned int current_id = invocation_id++;
+    
+    lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+    
+    if (!record->getNameAsString().compare("PseudoObjectExprBitfields"))
+        fprintf(stderr, "THIS IS THE ONE!");
     
     if (log)
     {
-        ASTDumper dumper((Decl*)copied_property_decl);
-        log->Printf("  CAS::FOPD[%d] found %s", current_id, dumper.GetCString());
+        log->Printf("LayoutRecordType[%u] on (RecordDecl*)%p [name = '%s']",
+                    current_id,
+                    m_ast_context,
+                    record->getNameAsString().c_str());
     }
- 
-    context.AddNamedDecl(copied_property_decl);
+    
+    
+    DeclFromParser <const RecordDecl> parser_record(record);
+    DeclFromUser <const RecordDecl> origin_record(parser_record.GetOrigin(m_ast_importer));
+    
+    if (origin_record.IsInvalid())
+        return false;
+        
+    FieldOffsetMap origin_field_offsets;
+    BaseOffsetMap origin_base_offsets;
+    BaseOffsetMap origin_virtual_base_offsets;
+    
+    const ASTRecordLayout &record_layout(origin_record->getASTContext().getASTRecordLayout(origin_record.decl));
+    
+    int field_idx = 0;
+    
+    for (RecordDecl::field_iterator fi = origin_record->field_begin(), fe = origin_record->field_end();
+         fi != fe;
+         ++fi)
+    {
+        uint64_t field_offset = record_layout.getFieldOffset(field_idx);
+        
+        origin_field_offsets.insert(std::pair<const FieldDecl *, uint64_t>(*fi, field_offset));
+        
+        field_idx++;
+    }
+        
+    ASTContext &parser_ast_context(record->getASTContext());
+
+    DeclFromUser <const CXXRecordDecl> origin_cxx_record(DynCast<const CXXRecordDecl>(origin_record));
+
+    if (origin_cxx_record.IsValid())
+    {
+        if (!ExtractBaseOffsets<false>(record_layout, origin_cxx_record, origin_base_offsets) ||
+            !ExtractBaseOffsets<true>(record_layout, origin_cxx_record, origin_virtual_base_offsets))
+            return false;
+    }
+
+    if (!ImportOffsetMap(field_offsets, origin_field_offsets, m_ast_importer, parser_ast_context) ||
+        !ImportOffsetMap(base_offsets, origin_base_offsets, m_ast_importer, parser_ast_context) ||
+        !ImportOffsetMap(virtual_base_offsets, origin_virtual_base_offsets, m_ast_importer, parser_ast_context))
+        return false;
+    
+    size = record_layout.getSize().getQuantity() * m_ast_context->getCharWidth();
+    alignment = record_layout.getAlignment().getQuantity() * m_ast_context->getCharWidth();
+    
+    if (log)
+    {
+        log->Printf("LRT[%u] returned:", current_id);
+        log->Printf("LRT[%u]   Original = (RecordDecl*)%p", current_id, origin_record.decl);
+        log->Printf("LRT[%u]   Size = %lld", current_id, size);
+        log->Printf("LRT[%u]   Alignment = %lld", current_id, alignment);
+        log->Printf("LRT[%u]   Fields:", current_id);
+        for (RecordDecl::field_iterator fi = record->field_begin(), fe = record->field_end();
+             fi != fe;
+             ++fi)
+        {
+            log->Printf("LRT[%u]     (FieldDecl*)%p, Name = '%s', Offset = %lld bits",
+                        current_id,
+                        *fi,
+                        fi->getNameAsString().c_str(),
+                        field_offsets[*fi]);
+        }
+        DeclFromParser <const CXXRecordDecl> parser_cxx_record = DynCast<const CXXRecordDecl>(parser_record);
+        if (parser_cxx_record.IsValid())
+        {
+            log->Printf("LRT[%u]   Bases:", current_id);
+            for (CXXRecordDecl::base_class_const_iterator bi = parser_cxx_record->bases_begin(), be = parser_cxx_record->bases_end();
+                 bi != be;
+                 ++bi)
+            {
+                bool is_virtual = bi->isVirtual();
+                
+                QualType base_type = bi->getType();
+                const RecordType *base_record_type = base_type->getAs<RecordType>();
+                DeclFromParser <RecordDecl> base_record(base_record_type->getDecl());
+                DeclFromParser <CXXRecordDecl> base_cxx_record = DynCast<CXXRecordDecl>(base_record);
+                
+                log->Printf("LRT[%u]     %s(CXXRecordDecl*)%p, Name = '%s', Offset = %lld chars",
+                            current_id,
+                            (is_virtual ? "Virtual " : ""),
+                            base_cxx_record.decl,
+                            base_cxx_record.decl->getNameAsString().c_str(),
+                            (is_virtual ? virtual_base_offsets[base_cxx_record.decl].getQuantity() :
+                                          base_offsets[base_cxx_record.decl].getQuantity()));
+            }
+        }
+        else
+        {
+            log->Printf("LRD[%u]   Not a CXXRecord, so no bases", current_id);
+        }
+    }
+    
+    return true;
 }
 
 void