[Lldb-commits] [lldb] r178410 - Fixed the way ClangASTImporter deports types from

Sean Callanan scallanan at apple.com
Fri Mar 29 19:31:21 PDT 2013


Author: spyffe
Date: Fri Mar 29 21:31:21 2013
New Revision: 178410

URL: http://llvm.org/viewvc/llvm-project?rev=178410&view=rev
Log:
Fixed the way ClangASTImporter deports types from
ASTContexts that will not stay around.  Before, we
did this in a very half-hearted way.  Now we maintain
work queues of all Decls that need to be completed
before the source ASTContext can go away; we then
expunge their origins completely.

<rdar://problem/13511875>

Modified:
    lldb/trunk/include/lldb/Symbol/ClangASTImporter.h
    lldb/trunk/source/Symbol/ClangASTImporter.cpp

Modified: lldb/trunk/include/lldb/Symbol/ClangASTImporter.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Symbol/ClangASTImporter.h?rev=178410&r1=178409&r2=178410&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Symbol/ClangASTImporter.h (original)
+++ lldb/trunk/include/lldb/Symbol/ClangASTImporter.h Fri Mar 29 21:31:21 2013
@@ -11,6 +11,7 @@
 #define liblldb_ClangASTImporter_h_
 
 #include <map>
+#include <set>
 
 #include "lldb/lldb-types.h"
 
@@ -250,17 +251,38 @@ private:
                                *source_ctx,
                                master.m_file_manager,
                                true /*minimal*/),
+            m_decls_to_deport(NULL),
+            m_decls_already_deported(NULL),
             m_master(master),
             m_source_ctx(source_ctx)
         {
         }
         
+        // A call to "InitDeportWorkQueues" puts the minion into deport mode.
+        // In deport mode, every copied Decl that could require completion is
+        // recorded and placed into the decls_to_deport set.
+        //
+        // A call to "ExecuteDeportWorkQueues" completes all the Decls that
+        // are in decls_to_deport, adding any Decls it sees along the way that
+        // it hasn't already deported.  It proceeds until decls_to_deport is
+        // empty.
+        //
+        // These calls must be paired.  Leaving a minion in deport mode or
+        // trying to start deport minion with a new pair of queues will result
+        // in an assertion failure.
+        
+        void InitDeportWorkQueues (std::set<clang::NamedDecl *> *decls_to_deport,
+                                   std::set<clang::NamedDecl *> *decls_already_deported);
+        void ExecuteDeportWorkQueues ();
+        
         void ImportDefinitionTo (clang::Decl *to, clang::Decl *from);
         
         clang::Decl *Imported (clang::Decl *from, clang::Decl *to);
         
-        ClangASTImporter   &m_master;
-        clang::ASTContext  *m_source_ctx;
+        std::set<clang::NamedDecl *>   *m_decls_to_deport;
+        std::set<clang::NamedDecl *>   *m_decls_already_deported;
+        ClangASTImporter               &m_master;
+        clang::ASTContext              *m_source_ctx;
     };
     
     typedef STD_SHARED_PTR(Minion) MinionSP;

Modified: lldb/trunk/source/Symbol/ClangASTImporter.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/ClangASTImporter.cpp?rev=178410&r1=178409&r2=178410&view=diff
==============================================================================
--- lldb/trunk/source/Symbol/ClangASTImporter.cpp (original)
+++ lldb/trunk/source/Symbol/ClangASTImporter.cpp Fri Mar 29 21:31:21 2013
@@ -113,37 +113,27 @@ lldb::clang_type_t
 ClangASTImporter::DeportType (clang::ASTContext *dst_ctx,
                               clang::ASTContext *src_ctx,
                               lldb::clang_type_t type)
-{
-    lldb::clang_type_t result = CopyType(dst_ctx, src_ctx, type);
+{    
+    MinionSP minion_sp (GetMinion (dst_ctx, src_ctx));
     
-    if (!result)
+    if (!minion_sp)
         return NULL;
     
-    QualType qual_type = QualType::getFromOpaquePtr(type);
+    std::set<NamedDecl *> decls_to_deport;
+    std::set<NamedDecl *> decls_already_deported;
     
-    if (const TagType *tag_type = qual_type->getAs<TagType>())
-    {
-        TagDecl *tag_decl = tag_type->getDecl();
-        const TagType *result_tag_type = QualType::getFromOpaquePtr(result)->getAs<TagType>();
-        TagDecl *result_tag_decl = result_tag_type->getDecl();
-        
-        if (tag_decl)
-        {
-            MinionSP minion_sp (GetMinion (dst_ctx, src_ctx));
-
-            minion_sp->ImportDefinitionTo(result_tag_decl, tag_decl);
-            
-            ASTContextMetadataSP to_context_md = GetContextMetadata(dst_ctx);
-            
-            OriginMap::iterator oi = to_context_md->m_origins.find(result_tag_decl);
-            
-            if (oi != to_context_md->m_origins.end() &&
-                oi->second.ctx == src_ctx)
-                to_context_md->m_origins.erase(oi);
-        }
-    }
+    minion_sp->InitDeportWorkQueues(&decls_to_deport,
+                                    &decls_already_deported);
+    
+    lldb::clang_type_t result = CopyType(dst_ctx, src_ctx, type);
+    
+    minion_sp->ExecuteDeportWorkQueues();
+    
+    if (!result)
+        return NULL;
     
     return result;
+
 }
 
 clang::Decl *
@@ -160,31 +150,23 @@ ClangASTImporter::DeportDecl (clang::AST
                     src_ctx,
                     dst_ctx);
     
-    clang::Decl *result = CopyDecl(dst_ctx, src_ctx, decl);
+    MinionSP minion_sp (GetMinion (dst_ctx, src_ctx));
     
-    if (!result)
+    if (!minion_sp)
         return NULL;
-        
-    ClangASTContext::GetCompleteDecl (src_ctx, decl);
-
-    MinionSP minion_sp (GetMinion (dst_ctx, src_ctx));
     
-    if (minion_sp && isa<TagDecl>(decl))
-        minion_sp->ImportDefinitionTo(result, decl);
+    std::set<NamedDecl *> decls_to_deport;
+    std::set<NamedDecl *> decls_already_deported;
     
-    ASTContextMetadataSP to_context_md = GetContextMetadata(dst_ctx);
-
-    OriginMap::iterator oi = to_context_md->m_origins.find(result);
+    minion_sp->InitDeportWorkQueues(&decls_to_deport,
+                                    &decls_already_deported);
     
-    if (oi != to_context_md->m_origins.end() &&
-        oi->second.ctx == src_ctx)
-        to_context_md->m_origins.erase(oi);
+    clang::Decl *result = CopyDecl(dst_ctx, src_ctx, decl);
+
+    minion_sp->ExecuteDeportWorkQueues();
     
-    if (TagDecl *result_tag_decl = dyn_cast<TagDecl>(result))
-    {
-        result_tag_decl->setHasExternalLexicalStorage(false);
-        result_tag_decl->setHasExternalVisibleStorage(false);
-    }
+    if (!result)
+        return NULL;
     
     if (log)
         log->Printf("    [ClangASTImporter] DeportDecl deported (%sDecl*)%p to (%sDecl*)%p",
@@ -469,6 +451,63 @@ ClangASTImporter::MapCompleter::~MapComp
 }
 
 void
+ClangASTImporter::Minion::InitDeportWorkQueues (std::set<clang::NamedDecl *> *decls_to_deport,
+                                                std::set<clang::NamedDecl *> *decls_already_deported)
+{
+    assert(!m_decls_to_deport); // TODO make debug only
+    assert(!m_decls_already_deported);
+    
+    m_decls_to_deport = decls_to_deport;
+    m_decls_already_deported = decls_already_deported;
+}
+
+void
+ClangASTImporter::Minion::ExecuteDeportWorkQueues ()
+{
+    assert(m_decls_to_deport); // TODO make debug only
+    assert(m_decls_already_deported);
+    
+    ASTContextMetadataSP to_context_md = m_master.GetContextMetadata(&getToContext());
+        
+    while (!m_decls_to_deport->empty())
+    {
+        NamedDecl *decl = *m_decls_to_deport->begin();
+        
+        m_decls_already_deported->insert(decl);
+        m_decls_to_deport->erase(decl);
+        
+        DeclOrigin &origin = to_context_md->m_origins[decl];
+        
+        assert (origin.ctx == m_source_ctx);    // otherwise we should never have added this
+                                                // because it doesn't need to be deported
+        
+        Decl *original_decl = to_context_md->m_origins[decl].decl;
+        
+        ClangASTContext::GetCompleteDecl (m_source_ctx, original_decl);
+        
+        if (TagDecl *tag_decl = dyn_cast<TagDecl>(decl))
+        {
+            if (TagDecl *original_tag_decl = dyn_cast<TagDecl>(original_decl))
+                if (original_tag_decl->isCompleteDefinition())
+                    ImportDefinitionTo(tag_decl, original_tag_decl);
+            
+            tag_decl->setHasExternalLexicalStorage(false);
+            tag_decl->setHasExternalVisibleStorage(false);
+        }
+        else if (ObjCInterfaceDecl *interface_decl = dyn_cast<ObjCInterfaceDecl>(decl))
+        {
+            interface_decl->setHasExternalLexicalStorage(false);
+            interface_decl->setHasExternalVisibleStorage(false);
+        }
+        
+        to_context_md->m_origins.erase(decl);
+    }
+    
+    m_decls_to_deport = NULL;
+    m_decls_already_deported = NULL;
+}
+
+void
 ClangASTImporter::Minion::ImportDefinitionTo (clang::Decl *to, clang::Decl *from)
 {
     ASTImporter::Imported(from, to);
@@ -594,6 +633,17 @@ clang::Decl
         }
         else
         {
+            if (m_decls_to_deport && m_decls_already_deported)
+            {
+                if (isa<TagDecl>(to) || isa<ObjCInterfaceDecl>(to))
+                {
+                    NamedDecl *to_named_decl = dyn_cast<NamedDecl>(to);
+                    
+                    if (!m_decls_already_deported->count(to_named_decl))
+                        m_decls_to_deport->insert(to_named_decl);
+                }
+
+            }
             to_context_md->m_origins[to] = DeclOrigin(m_source_ctx, from);
             
             if (log)
@@ -630,15 +680,13 @@ clang::Decl
         
         to_tag_decl->setHasExternalLexicalStorage();
         to_tag_decl->setMustBuildLookupTable();
-                                
+        
         if (log)
             log->Printf("    [ClangASTImporter] To is a TagDecl - attributes %s%s [%s->%s]",
                         (to_tag_decl->hasExternalLexicalStorage() ? " Lexical" : ""),
                         (to_tag_decl->hasExternalVisibleStorage() ? " Visible" : ""),
                         (from_tag_decl->isCompleteDefinition() ? "complete" : "incomplete"),
                         (to_tag_decl->isCompleteDefinition() ? "complete" : "incomplete"));
-        
-        to_tag_decl = NULL;
     }
     
     if (isa<NamespaceDecl>(from))
@@ -656,7 +704,7 @@ clang::Decl
                 
         to_interface_decl->setHasExternalLexicalStorage();
         to_interface_decl->setHasExternalVisibleStorage();
-                 
+        
         /*to_interface_decl->setExternallyCompleted();*/
                 
         if (log)





More information about the lldb-commits mailing list