diff options
Diffstat (limited to 'contrib/llvm/tools/lldb/source/Expression/ClangASTSource.cpp')
-rw-r--r-- | contrib/llvm/tools/lldb/source/Expression/ClangASTSource.cpp | 142 |
1 files changed, 98 insertions, 44 deletions
diff --git a/contrib/llvm/tools/lldb/source/Expression/ClangASTSource.cpp b/contrib/llvm/tools/lldb/source/Expression/ClangASTSource.cpp index 9a6d6e5..3988cd6 100644 --- a/contrib/llvm/tools/lldb/source/Expression/ClangASTSource.cpp +++ b/contrib/llvm/tools/lldb/source/Expression/ClangASTSource.cpp @@ -16,15 +16,45 @@ #include "lldb/Expression/ASTDumper.h" #include "lldb/Expression/ClangASTSource.h" #include "lldb/Expression/ClangExpression.h" +#include "lldb/Expression/ClangModulesDeclVendor.h" +#include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/ClangNamespaceDecl.h" #include "lldb/Symbol/Function.h" #include "lldb/Symbol/SymbolVendor.h" +#include "lldb/Symbol/TaggedASTType.h" #include "lldb/Target/ObjCLanguageRuntime.h" #include "lldb/Target/Target.h" +#include <vector> + using namespace clang; using namespace lldb_private; +//------------------------------------------------------------------ +// Scoped class that will remove an active lexical decl from the set +// when it goes out of scope. +//------------------------------------------------------------------ +namespace { + class ScopedLexicalDeclEraser + { + public: + ScopedLexicalDeclEraser(std::set<const clang::Decl *> &decls, + const clang::Decl *decl) + : m_active_lexical_decls(decls), m_decl(decl) + { + } + + ~ScopedLexicalDeclEraser() + { + m_active_lexical_decls.erase(m_decl); + } + + private: + std::set<const clang::Decl *> &m_active_lexical_decls; + const clang::Decl *m_decl; + }; +} + ClangASTSource::~ClangASTSource() { m_ast_importer->ForgetDestination(m_ast_context); @@ -186,6 +216,12 @@ ClangASTSource::CompleteType (TagDecl *tag_decl) dumper.ToLog(log, " [CTD] "); } + auto iter = m_active_lexical_decls.find(tag_decl); + if (iter != m_active_lexical_decls.end()) + return; + m_active_lexical_decls.insert(tag_decl); + ScopedLexicalDeclEraser eraser(m_active_lexical_decls, tag_decl); + if (!m_ast_importer->CompleteTagDecl (tag_decl)) { // We couldn't complete the type. Maybe there's a definition @@ -397,6 +433,12 @@ ClangASTSource::FindExternalLexicalDecls (const DeclContext *decl_context, if (!context_decl) return ELR_Failure; + auto iter = m_active_lexical_decls.find(context_decl); + if (iter != m_active_lexical_decls.end()) + return ELR_Failure; + m_active_lexical_decls.insert(context_decl); + ScopedLexicalDeclEraser eraser(m_active_lexical_decls, context_decl); + static unsigned int invocation_id = 0; unsigned int current_id = invocation_id++; @@ -1529,41 +1571,50 @@ ClangASTSource::FindObjCPropertyAndIvarDecls (NameSearchContext &context) while(0); } -typedef llvm::DenseMap <const FieldDecl *, uint64_t> FieldOffsetMap; -typedef llvm::DenseMap <const CXXRecordDecl *, CharUnits> BaseOffsetMap; +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) +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; - - for (typename MapType::iterator fi = source_map.begin(), fe = source_map.end(); - fi != fe; - ++fi) + // When importing fields into a new record, clang has a hard requirement that + // fields be imported in field offset order. Since they are stored in a DenseMap + // with a pointer as the key type, this means we cannot simply iterate over the + // map, as the order will be non-deterministic. Instead we have to sort by the offset + // and then insert in sorted order. + typedef llvm::DenseMap<const D *, O> MapType; + typedef typename MapType::value_type PairType; + std::vector<PairType> sorted_items; + sorted_items.reserve(source_map.size()); + sorted_items.assign(source_map.begin(), source_map.end()); + std::sort(sorted_items.begin(), sorted_items.end(), + [](const PairType &lhs, const PairType &rhs) + { + return lhs.second < rhs.second; + }); + + for (const auto &item : sorted_items) { - DeclFromUser <D> user_decl(const_cast<D*>(fi->first)); + DeclFromUser<D> user_decl(const_cast<D *>(item.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)); + destination_map.insert(std::pair<const D *, O>(parser_decl.decl, item.second)); } return true; } -template <bool IsVirtual> bool ExtractBaseOffsets (const ASTRecordLayout &record_layout, - DeclFromUser<const CXXRecordDecl> &record, - BaseOffsetMap &base_offsets) +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) + 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; @@ -1598,11 +1649,8 @@ template <bool IsVirtual> bool ExtractBaseOffsets (const ASTRecordLayout &record } bool -ClangASTSource::layoutRecordType(const RecordDecl *record, - uint64_t &size, - uint64_t &alignment, - FieldOffsetMap &field_offsets, - BaseOffsetMap &base_offsets, +ClangASTSource::layoutRecordType(const RecordDecl *record, uint64_t &size, uint64_t &alignment, + FieldOffsetMap &field_offsets, BaseOffsetMap &base_offsets, BaseOffsetMap &virtual_base_offsets) { ClangASTMetrics::RegisterRecordLayout(); @@ -1637,9 +1685,7 @@ ClangASTSource::layoutRecordType(const RecordDecl *record, int field_idx = 0, field_count = record_layout.getFieldCount(); - for (RecordDecl::field_iterator fi = origin_record->field_begin(), fe = origin_record->field_end(); - fi != fe; - ++fi) + for (RecordDecl::field_iterator fi = origin_record->field_begin(), fe = origin_record->field_end(); fi != fe; ++fi) { if (field_idx >= field_count) return false; // Layout didn't go well. Bail out. @@ -1682,9 +1728,8 @@ ClangASTSource::layoutRecordType(const RecordDecl *record, fi != fe; ++fi) { - log->Printf("LRT[%u] (FieldDecl*)%p, Name = '%s', Offset = %" PRId64 " bits", - current_id, static_cast<void*>(*fi), - fi->getNameAsString().c_str(), field_offsets[*fi]); + log->Printf("LRT[%u] (FieldDecl*)%p, Name = '%s', Offset = %" PRId64 " bits", current_id, + static_cast<void *>(*fi), fi->getNameAsString().c_str(), field_offsets[*fi]); } DeclFromParser <const CXXRecordDecl> parser_cxx_record = DynCast<const CXXRecordDecl>(parser_record); if (parser_cxx_record.IsValid()) @@ -1701,13 +1746,11 @@ ClangASTSource::layoutRecordType(const RecordDecl *record, 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 = %" PRId64 " chars", - current_id, (is_virtual ? "Virtual " : ""), - static_cast<void*>(base_cxx_record.decl), + log->Printf("LRT[%u] %s(CXXRecordDecl*)%p, Name = '%s', Offset = %" PRId64 " chars", current_id, + (is_virtual ? "Virtual " : ""), static_cast<void *>(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())); + (is_virtual ? virtual_base_offsets[base_cxx_record.decl].getQuantity() + : base_offsets[base_cxx_record.decl].getQuantity())); } } else @@ -1883,7 +1926,7 @@ NameSearchContext::AddVarDecl(const ClangASTType &type) } clang::NamedDecl * -NameSearchContext::AddFunDecl (const ClangASTType &type) +NameSearchContext::AddFunDecl (const ClangASTType &type, bool extern_c) { assert (type && "Type for variable must be valid!"); @@ -1902,15 +1945,26 @@ NameSearchContext::AddFunDecl (const ClangASTType &type) const bool isInlineSpecified = false; const bool hasWrittenPrototype = true; const bool isConstexprSpecified = false; + + clang::DeclContext *context = const_cast<DeclContext*>(m_decl_context); + + if (extern_c) { + context = LinkageSpecDecl::Create(*ast, + context, + SourceLocation(), + SourceLocation(), + clang::LinkageSpecDecl::LanguageIDs::lang_c, + false); + } clang::FunctionDecl *func_decl = FunctionDecl::Create (*ast, - const_cast<DeclContext*>(m_decl_context), + context, SourceLocation(), SourceLocation(), m_decl_name.getAsIdentifierInfo(), qual_type, NULL, - SC_Static, + SC_Extern, isInlineSpecified, hasWrittenPrototype, isConstexprSpecified); @@ -1933,7 +1987,7 @@ NameSearchContext::AddFunDecl (const ClangASTType &type) QualType arg_qual_type (func_proto_type->getParamType(ArgIndex)); parm_var_decls.push_back(ParmVarDecl::Create (*ast, - const_cast<DeclContext*>(m_decl_context), + const_cast<DeclContext*>(context), SourceLocation(), SourceLocation(), NULL, @@ -1969,7 +2023,7 @@ NameSearchContext::AddGenericFunDecl() ArrayRef<QualType>(), // argument types proto_info)); - return AddFunDecl(ClangASTType (m_ast_source.m_ast_context, generic_function_type)); + return AddFunDecl(ClangASTType (m_ast_source.m_ast_context, generic_function_type), true); } clang::NamedDecl * @@ -2008,7 +2062,7 @@ NameSearchContext::AddTypeDecl(const ClangASTType &clang_type) } void -NameSearchContext::AddLookupResult (clang::DeclContextLookupConstResult result) +NameSearchContext::AddLookupResult (clang::DeclContextLookupResult result) { for (clang::NamedDecl *decl : result) m_decls.push_back (decl); |