diff options
| author | Greg Clayton <gclayton@apple.com> | 2011-06-25 00:44:06 +0000 |
|---|---|---|
| committer | Greg Clayton <gclayton@apple.com> | 2011-06-25 00:44:06 +0000 |
| commit | a2721476e7e8ec57418b460d27fd0900e8e7aa30 (patch) | |
| tree | 9fdaf40ff3793d9907fe6007e245528e2d6ccc75 /lldb/source | |
| parent | 5f836782222045a4b87837917ba8f61f25e92df4 (diff) | |
| download | bcm5719-llvm-a2721476e7e8ec57418b460d27fd0900e8e7aa30.tar.gz bcm5719-llvm-a2721476e7e8ec57418b460d27fd0900e8e7aa30.zip | |
This commit adds broad architectural support for hierarchical
inspection of namespaces in the expression parser.
ClangExpressionDeclMap hitherto reported that namespaces had
been completely imported, even though the namespaces are
returned empty. To deal with this situation, ClangASTSource
was recently extended with an API to complete incomplete type
definitions, and, for greater efficiency, to complete these
definitions partially, returning only those objects that have
a given name.
This commit supports these APIs on LLDB's side, and uses it
to provide information on types resident in namespaces.
Namespaces are now imported as they were -- that is to say,
empty -- but with minimal import mode on. This means that
Clang will come back and request their contents by name as
needed. We now respond with information on the contained
types; this will be followed soon by information on functions
and variables.
llvm-svn: 133852
Diffstat (limited to 'lldb/source')
| -rw-r--r-- | lldb/source/Expression/ClangASTSource.cpp | 15 | ||||
| -rw-r--r-- | lldb/source/Expression/ClangExpressionDeclMap.cpp | 147 | ||||
| -rw-r--r-- | lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp | 80 | ||||
| -rw-r--r-- | lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h | 21 | ||||
| -rw-r--r-- | lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp | 1 | ||||
| -rw-r--r-- | lldb/source/Symbol/ClangASTContext.cpp | 42 | ||||
| -rw-r--r-- | lldb/source/Symbol/ClangASTImporter.cpp | 61 | ||||
| -rw-r--r-- | lldb/source/Symbol/ClangExternalASTSourceCallbacks.cpp | 11 |
8 files changed, 358 insertions, 20 deletions
diff --git a/lldb/source/Expression/ClangASTSource.cpp b/lldb/source/Expression/ClangASTSource.cpp index d91f2f1069e..a229a4a7f45 100644 --- a/lldb/source/Expression/ClangASTSource.cpp +++ b/lldb/source/Expression/ClangASTSource.cpp @@ -266,3 +266,18 @@ NameSearchContext::AddTypeDecl(void *type) } return NULL; } + +void +NameSearchContext::AddLookupResult (clang::DeclContextLookupConstResult result) +{ + for (clang::NamedDecl * const *decl_iterator = result.first; + decl_iterator != result.second; + ++decl_iterator) + m_decls.push_back (*decl_iterator); +} + +void +NameSearchContext::AddNamedDecl (clang::NamedDecl *decl) +{ + m_decls.push_back (decl); +} diff --git a/lldb/source/Expression/ClangExpressionDeclMap.cpp b/lldb/source/Expression/ClangExpressionDeclMap.cpp index eacacaae4a7..3216b65588c 100644 --- a/lldb/source/Expression/ClangExpressionDeclMap.cpp +++ b/lldb/source/Expression/ClangExpressionDeclMap.cpp @@ -1656,6 +1656,69 @@ ClangExpressionDeclMap::GetDecls (NameSearchContext &context, const ConstString log->Printf("Ignoring a query during an import"); return; } + + do + { + if (isa<TranslationUnitDecl>(context.m_decl_context)) + break; + + if (log) + log->Printf("'%s' is in something other than a translation unit", name.GetCString()); + + const Decl *context_decl = dyn_cast<Decl>(context.m_decl_context); + + if (!context_decl) + return; + + if (const NamespaceDecl *namespace_decl = dyn_cast<NamespaceDecl>(context_decl)) + { + Decl *original_decl; + ASTContext *original_ctx; + + if (log) + log->Printf("Resolving the containing context's origin..."); + + if (!m_parser_vars->GetASTImporter(context.GetASTContext())->ResolveDeclOrigin(namespace_decl, &original_decl, &original_ctx)) + break; + + if (log) + log->Printf("Casting it to a DeclContext..."); + + DeclContext *original_decl_context = dyn_cast<DeclContext>(original_decl); + + if (!original_decl_context) + break; + + if (log) + { + std::string s; + llvm::raw_string_ostream os(s); + original_decl->print(os); + os.flush(); + + log->Printf("Containing context:"); + log->Printf("%s", s.c_str()); + } + + if (!original_ctx->getExternalSource()) + break; + + DeclContextLookupConstResult original_lookup_result = original_ctx->getExternalSource()->FindExternalVisibleDeclsByName(original_decl_context, context.m_decl_name); + + NamedDecl *const *iter; + + for (iter = original_lookup_result.first; + iter != original_lookup_result.second; + ++iter) + { + clang::NamedDecl *copied_result = dyn_cast<NamedDecl>(m_parser_vars->GetASTImporter(context.GetASTContext())->CopyDecl(original_ctx, *iter)); + + if (copied_result) + context.AddNamedDecl(copied_result); + } + } + } + while (0); SymbolContextList sc_list; @@ -1721,14 +1784,6 @@ ClangExpressionDeclMap::GetDecls (NameSearchContext &context, const ConstString else if (non_extern_symbol) AddOneFunction (context, NULL, non_extern_symbol); } - - ClangNamespaceDecl namespace_decl (m_parser_vars->m_sym_ctx.FindNamespace(name)); - if (namespace_decl) - { - clang::NamespaceDecl *clang_namespace_decl = AddNamespace(context, namespace_decl); - if (clang_namespace_decl) - clang_namespace_decl->setHasExternalLexicalStorage(); - } } else { @@ -1741,6 +1796,26 @@ ClangExpressionDeclMap::GetDecls (NameSearchContext &context, const ConstString AddOneGenericVariable(context, *data_symbol); } } + + ClangNamespaceDecl namespace_decl (m_parser_vars->m_sym_ctx.FindNamespace(name)); + + if (namespace_decl) + { + if (log) + { + std::string s; + llvm::raw_string_ostream os(s); + namespace_decl.GetNamespaceDecl()->print(os); + os.flush(); + + log->Printf("Added namespace decl:"); + log->Printf("%s", s.c_str()); + } + + clang::NamespaceDecl *clang_namespace_decl = AddNamespace(context, namespace_decl); + if (clang_namespace_decl) + clang_namespace_decl->setHasExternalLexicalStorage(); + } } else { @@ -1883,7 +1958,47 @@ ClangExpressionDeclMap::GetDecls (NameSearchContext &context, const ConstString AddOneType(context, user_type, false); } } + +const clang::DeclContext * +ClangExpressionDeclMap::CompleteDeclContext (clang::ASTContext *ast_context, + const clang::DeclContext *decl_context) +{ + lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + if (log) + { + const NamedDecl *named_decl = dyn_cast<NamedDecl>(decl_context); + if (named_decl) + log->Printf("Completing a '%s' DeclContext named '%s'", decl_context->getDeclKindName(), named_decl->getDeclName().getAsString().c_str()); + else + log->Printf("Completing a '%s' DeclContext", decl_context->getDeclKindName()); + } + + assert (m_parser_vars.get()); + + if (!m_parser_vars->GetASTImporter (ast_context)->CompleteDeclContext(decl_context)) + return NULL; + + if (log) + { + const Decl *decl = dyn_cast<Decl>(decl_context); + + if (decl) + { + std::string s; + llvm::raw_string_ostream os(s); + decl->print(os); + os.flush(); + + log->Printf("After:"); + log->Printf("%s", s.c_str()); + } + } + + return decl_context; +} + Value * ClangExpressionDeclMap::GetVariableValue ( @@ -2247,9 +2362,10 @@ ClangExpressionDeclMap::AddNamespace (NameSearchContext &context, const ClangNam { lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - clang::Decl *copied_decl = ClangASTContext::CopyDecl (context.GetASTContext(), - namespace_decl.GetASTContext(), - namespace_decl.GetNamespaceDecl()); + assert (m_parser_vars.get()); + + clang::Decl *copied_decl = m_parser_vars->GetASTImporter(context.GetASTContext())->CopyDecl(namespace_decl.GetASTContext(), + namespace_decl.GetNamespaceDecl()); return dyn_cast<clang::NamespaceDecl>(copied_decl); } @@ -2393,9 +2509,12 @@ ClangExpressionDeclMap::GuardedCopyType (ASTContext *dest_context, m_parser_vars->m_ignore_lookups = true; - void *ret = ClangASTContext::CopyType (dest_context, - source_context, - clang_type); + lldb_private::ClangASTImporter *importer = m_parser_vars->GetASTImporter(dest_context); + + QualType ret_qual_type = importer->CopyType (source_context, + QualType::getFromOpaquePtr(clang_type)); + + void *ret = ret_qual_type.getAsOpaquePtr(); m_parser_vars->m_ignore_lookups = false; diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp index 57aaa011672..9a7e7fdfc3b 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -218,6 +218,7 @@ SymbolFileDWARF::GetClangASTContext () llvm::OwningPtr<clang::ExternalASTSource> ast_source_ap ( new ClangExternalASTSourceCallbacks (SymbolFileDWARF::CompleteTagDecl, SymbolFileDWARF::CompleteObjCInterfaceDecl, + SymbolFileDWARF::FindExternalVisibleDeclsByName, this)); ast.SetExternalSource (ast_source_ap); @@ -2789,7 +2790,7 @@ SymbolFileDWARF::ResolveNamespaceDIE (DWARFCompileUnit *curr_cu, const DWARFDebu Declaration decl; // TODO: fill in the decl object clang::NamespaceDecl *namespace_decl = GetClangASTContext().GetUniqueNamespaceDeclaration (namespace_name, decl, GetClangDeclContextForDIE (curr_cu, die->GetParent())); if (namespace_decl) - m_die_to_decl_ctx[die] = (clang::DeclContext*)namespace_decl; + LinkDeclContextToDIE((clang::DeclContext*)namespace_decl, die); return namespace_decl; } } @@ -2834,7 +2835,7 @@ SymbolFileDWARF::GetClangDeclContextForDIE (DWARFCompileUnit *curr_cu, const DWA if (namespace_decl) { //printf ("SymbolFileDWARF::GetClangDeclContextForDIE ( die = 0x%8.8x ) => 0x%8.8x\n", decl_die->GetOffset(), die->GetOffset()); - m_die_to_decl_ctx[die] = (clang::DeclContext*)namespace_decl; + LinkDeclContextToDIE((clang::DeclContext*)namespace_decl, die); } return namespace_decl; } @@ -3282,8 +3283,8 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu, // Store a forward declaration to this class type in case any // parameters in any class methods need it for the clang - // types for function prototypes. - m_die_to_decl_ctx[die] = ClangASTContext::GetDeclContextForType (clang_type); + // types for function prototypes. + LinkDeclContextToDIE(ClangASTContext::GetDeclContextForType(clang_type), die); type_sp.reset (new Type (die->GetOffset(), this, type_name_const_str, @@ -3396,7 +3397,8 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu, assert (enumerator_clang_type != NULL); } - m_die_to_decl_ctx[die] = ClangASTContext::GetDeclContextForType (clang_type); + LinkDeclContextToDIE(ClangASTContext::GetDeclContextForType(clang_type), die); + type_sp.reset( new Type (die->GetOffset(), this, type_name_const_str, @@ -3661,7 +3663,7 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu, // Add the decl to our DIE to decl context map assert (function_decl); - m_die_to_decl_ctx[die] = function_decl; + LinkDeclContextToDIE(function_decl, die); if (!function_param_decls.empty()) ast.SetFunctionParameters (function_decl, &function_param_decls.front(), @@ -4409,3 +4411,69 @@ SymbolFileDWARF::CompleteObjCInterfaceDecl (void *baton, clang::ObjCInterfaceDec symbol_file_dwarf->ResolveClangOpaqueTypeDefinition (clang_type); } +void +SymbolFileDWARF::SearchNamespace (const clang::NamespaceDecl *namespace_decl, + const char *name, + llvm::SmallVectorImpl <clang::NamedDecl *> *results) +{ + DeclContextToDIEMap::iterator iter = m_decl_ctx_to_die.find((const clang::DeclContext*)namespace_decl); + + if (iter == m_decl_ctx_to_die.end()) + return; + + const DWARFDebugInfoEntry *namespace_die = iter->second; + + if (!results) + return; + + DWARFDebugInfo* info = DebugInfo(); + + std::vector<NameToDIE::Info> die_info_array; + + size_t num_matches = m_type_index.Find (name, die_info_array); + + if (num_matches) + { + for (int i = 0; + i < num_matches; + ++i) + { + DWARFCompileUnit* compile_unit = info->GetCompileUnitAtIndex(die_info_array[i].cu_idx); + compile_unit->ExtractDIEsIfNeeded (false); + const DWARFDebugInfoEntry *die = compile_unit->GetDIEAtIndexUnchecked(die_info_array[i].die_idx); + + if (die->GetParent() != namespace_die) + continue; + + Type *matching_type = ResolveType (compile_unit, die); + + lldb::clang_type_t type = matching_type->GetClangFullType(); + clang::QualType qual_type = clang::QualType::getFromOpaquePtr(type); + + + if (const clang::TagType *tag_type = dyn_cast<clang::TagType>(qual_type.getTypePtr())) + { + clang::TagDecl *tag_decl = tag_type->getDecl(); + results->push_back(tag_decl); + } + else if (const clang::TypedefType *typedef_type = dyn_cast<clang::TypedefType>(qual_type.getTypePtr())) + { + clang::TypedefNameDecl *typedef_decl = typedef_type->getDecl(); + results->push_back(typedef_decl); + } + } + } +} + +void +SymbolFileDWARF::FindExternalVisibleDeclsByName (void *baton, + const clang::DeclContext *DC, + clang::DeclarationName Name, + llvm::SmallVectorImpl <clang::NamedDecl *> *results) +{ + SymbolFileDWARF *symbol_file_dwarf = (SymbolFileDWARF *)baton; + + const clang::NamespaceDecl *DC_namespace = llvm::dyn_cast<clang::NamespaceDecl>(DC); + + symbol_file_dwarf->SearchNamespace (DC_namespace, Name.getAsString().c_str(), results); +} diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h index f3c36c734e3..d3b309cfc9e 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h @@ -18,6 +18,7 @@ #include <vector> // Other libraries and framework includes +#include "clang/AST/ExternalASTSource.h" #include "llvm/ADT/DenseMap.h" #include "lldb/Core/ClangForward.h" @@ -127,6 +128,12 @@ public: static void CompleteObjCInterfaceDecl (void *baton, clang::ObjCInterfaceDecl *); + + static void + FindExternalVisibleDeclsByName (void *baton, + const clang::DeclContext *DC, + clang::DeclarationName Name, + llvm::SmallVectorImpl <clang::NamedDecl *> *results); //------------------------------------------------------------------ // PluginInterface protocol @@ -180,6 +187,11 @@ public: clang::DeclContext * GetClangDeclContextForDIEOffset (dw_offset_t die_offset); + + void + SearchNamespace (const clang::NamespaceDecl *namespace_decl, + const char *name, + llvm::SmallVectorImpl <clang::NamedDecl *> *results); lldb_private::Flags& GetFlags () @@ -328,6 +340,13 @@ protected: UniqueDWARFASTTypeMap & GetUniqueDWARFASTTypeMap (); + void LinkDeclContextToDIE (clang::DeclContext *decl_ctx, + const DWARFDebugInfoEntry *die) + { + m_die_to_decl_ctx[die] = decl_ctx; + m_decl_ctx_to_die[decl_ctx] = die; + } + SymbolFileDWARFDebugMap * m_debug_map_symfile; clang::TranslationUnitDecl * m_clang_tu_decl; lldb_private::Flags m_flags; @@ -360,11 +379,13 @@ protected: std::auto_ptr<DWARFDebugRanges> m_ranges; UniqueDWARFASTTypeMap m_unique_ast_type_map; typedef llvm::DenseMap<const DWARFDebugInfoEntry *, clang::DeclContext *> DIEToDeclContextMap; + typedef llvm::DenseMap<const clang::DeclContext *, const DWARFDebugInfoEntry *> DeclContextToDIEMap; typedef llvm::DenseMap<const DWARFDebugInfoEntry *, lldb_private::Type *> DIEToTypePtr; typedef llvm::DenseMap<const DWARFDebugInfoEntry *, lldb::VariableSP> DIEToVariableSP; typedef llvm::DenseMap<const DWARFDebugInfoEntry *, lldb::clang_type_t> DIEToClangType; typedef llvm::DenseMap<lldb::clang_type_t, const DWARFDebugInfoEntry *> ClangTypeToDIE; DIEToDeclContextMap m_die_to_decl_ctx; + DeclContextToDIEMap m_decl_ctx_to_die; DIEToTypePtr m_die_to_type; DIEToVariableSP m_die_to_variable_sp; DIEToClangType m_forward_decl_die_to_clang_type; diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp index 2c9a7c39c4a..b6480cc9ac9 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp @@ -81,6 +81,7 @@ SymbolFileDWARFDebugMap::InitializeObject() llvm::OwningPtr<clang::ExternalASTSource> ast_source_ap ( new ClangExternalASTSourceCallbacks (SymbolFileDWARFDebugMap::CompleteTagDecl, SymbolFileDWARFDebugMap::CompleteObjCInterfaceDecl, + NULL, this)); GetClangASTContext().SetExternalSource (ast_source_ap); diff --git a/lldb/source/Symbol/ClangASTContext.cpp b/lldb/source/Symbol/ClangASTContext.cpp index add42fc7b41..b692ae507c5 100644 --- a/lldb/source/Symbol/ClangASTContext.cpp +++ b/lldb/source/Symbol/ClangASTContext.cpp @@ -4644,3 +4644,45 @@ ClangASTContext::GetCompleteType (clang_type_t clang_type) return ClangASTContext::GetCompleteType (getASTContext(), clang_type); } +bool +ClangASTContext::GetCompleteDecl (clang::ASTContext *ast, + clang::Decl *decl) +{ + if (!decl) + return false; + + ExternalASTSource *ast_source = ast->getExternalSource(); + + if (!ast_source) + return false; + + if (clang::TagDecl *tag_decl = llvm::dyn_cast<clang::TagDecl>(decl)) + { + if (tag_decl->getDefinition()) + return true; + + if (!tag_decl->hasExternalLexicalStorage()) + return false; + + ast_source->CompleteType(tag_decl); + + return !tag_decl->getTypeForDecl()->isIncompleteType(); + } + else if (clang::ObjCInterfaceDecl *objc_interface_decl = llvm::dyn_cast<clang::ObjCInterfaceDecl>(decl)) + { + if (!objc_interface_decl->isForwardDecl()) + return true; + + if (!objc_interface_decl->hasExternalLexicalStorage()) + return false; + + ast_source->CompleteType(objc_interface_decl); + + return !objc_interface_decl->isForwardDecl(); + } + else + { + return false; + } +} + diff --git a/lldb/source/Symbol/ClangASTImporter.cpp b/lldb/source/Symbol/ClangASTImporter.cpp new file mode 100644 index 00000000000..84a765a1f35 --- /dev/null +++ b/lldb/source/Symbol/ClangASTImporter.cpp @@ -0,0 +1,61 @@ +//===-- ClangASTImporter.cpp ------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "clang/AST/Decl.h" +#include "lldb/Symbol/ClangASTContext.h" +#include "lldb/Symbol/ClangASTImporter.h" + +using namespace lldb_private; +using namespace clang; + +clang::QualType +ClangASTImporter::CopyType (clang::ASTContext *src_ast, + clang::QualType type) +{ + MinionSP minion = GetMinion(src_ast, false); + + return minion->Import(type); +} + +clang::Decl * +ClangASTImporter::CopyDecl (clang::ASTContext *src_ast, + clang::Decl *decl) +{ + MinionSP minion; + + if (isa<clang::NamespaceDecl>(decl)) + minion = GetMinion(src_ast, true); + else + minion = GetMinion(src_ast, false); + + return minion->Import(decl); +} + +const clang::DeclContext * +ClangASTImporter::CompleteDeclContext (const clang::DeclContext *decl_context) +{ + const Decl *context_decl = dyn_cast<Decl>(decl_context); + + if (!context_decl) + return NULL; + + DeclOrigin context_decl_origin = GetDeclOrigin(context_decl); + + if (!context_decl_origin.Valid()) + return NULL; + + if (!ClangASTContext::GetCompleteDecl(context_decl_origin.ctx, context_decl_origin.decl)) + return NULL; + + MinionSP minion = GetMinion(context_decl_origin.ctx, false); + + minion->ImportDefinition(context_decl_origin.decl); + + return decl_context; +} diff --git a/lldb/source/Symbol/ClangExternalASTSourceCallbacks.cpp b/lldb/source/Symbol/ClangExternalASTSourceCallbacks.cpp index c79aefca53e..5b7b48fa901 100644 --- a/lldb/source/Symbol/ClangExternalASTSourceCallbacks.cpp +++ b/lldb/source/Symbol/ClangExternalASTSourceCallbacks.cpp @@ -52,6 +52,17 @@ ClangExternalASTSourceCallbacks::FindExternalVisibleDeclsByName clang::DeclarationName clang_decl_name ) { + if (m_callback_find_by_name) + { + llvm::SmallVector <clang::NamedDecl *, 3> results; + + m_callback_find_by_name (m_callback_baton, decl_ctx, clang_decl_name, &results); + + DeclContextLookupResult lookup_result (SetExternalVisibleDeclsForName(decl_ctx, clang_decl_name, results)); + + return lookup_result; + } + std::string decl_name (clang_decl_name.getAsString()); switch (clang_decl_name.getNameKind()) { |

