summaryrefslogtreecommitdiff
path: root/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp')
-rw-r--r--source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp268
1 files changed, 171 insertions, 97 deletions
diff --git a/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp b/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp
index 8fde41052192b..07ff2e97aac77 100644
--- a/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp
+++ b/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp
@@ -48,8 +48,10 @@
#include "lldb/lldb-private.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
+#include "clang/AST/ASTImporter.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclarationName.h"
+#include "clang/AST/RecursiveASTVisitor.h"
#include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h"
@@ -178,6 +180,134 @@ ClangExpressionDeclMap::TargetInfo ClangExpressionDeclMap::GetTargetInfo() {
return ret;
}
+namespace {
+/// This class walks an AST and ensures that all DeclContexts defined inside the
+/// current source file are properly complete.
+///
+/// This is used to ensure that persistent types defined in the current source
+/// file migrate completely to the persistent AST context before they are
+/// reused. If that didn't happen, it would be impoossible to complete them
+/// because their origin would be gone.
+///
+/// The stragtegy used by this class is to check the SourceLocation (to be
+/// specific, the FileID) and see if it's the FileID for the current expression.
+/// Alternate strategies could include checking whether an ExternalASTMerger,
+/// set up to not have the current context as a source, can find an original for
+/// the type.
+class Completer : public clang::RecursiveASTVisitor<Completer> {
+private:
+ clang::ASTImporter &m_exporter; /// Used to import Decl contents
+ clang::FileID m_file; /// The file that's going away
+ llvm::DenseSet<clang::Decl *> m_completed; /// Visited Decls, to avoid cycles
+
+ bool ImportAndCheckCompletable(clang::Decl *decl) {
+ (void)m_exporter.Import(decl);
+ if (m_completed.count(decl))
+ return false;
+ if (!llvm::isa<DeclContext>(decl))
+ return false;
+ const clang::SourceLocation loc = decl->getLocation();
+ if (!loc.isValid())
+ return false;
+ const clang::FileID file =
+ m_exporter.getFromContext().getSourceManager().getFileID(loc);
+ if (file != m_file)
+ return false;
+ // We are assuming the Decl was parsed in this very expression, so it should
+ // not have external storage.
+ lldbassert(!llvm::cast<DeclContext>(decl)->hasExternalLexicalStorage());
+ return true;
+ }
+
+ void Complete(clang::Decl *decl) {
+ m_completed.insert(decl);
+ auto *decl_context = llvm::cast<DeclContext>(decl);
+ (void)m_exporter.Import(decl);
+ m_exporter.CompleteDecl(decl);
+ for (Decl *child : decl_context->decls())
+ if (ImportAndCheckCompletable(child))
+ Complete(child);
+ }
+
+ void MaybeComplete(clang::Decl *decl) {
+ if (ImportAndCheckCompletable(decl))
+ Complete(decl);
+ }
+
+public:
+ Completer(clang::ASTImporter &exporter, clang::FileID file)
+ : m_exporter(exporter), m_file(file) {}
+
+ // Implements the RecursiveASTVisitor's core API. It is called on each Decl
+ // that the RecursiveASTVisitor encounters, and returns true if the traversal
+ // should continue.
+ bool VisitDecl(clang::Decl *decl) {
+ MaybeComplete(decl);
+ return true;
+ }
+};
+}
+
+static void CompleteAllDeclContexts(clang::ASTImporter &exporter,
+ clang::FileID file,
+ clang::QualType root) {
+ clang::QualType canonical_type = root.getCanonicalType();
+ if (clang::TagDecl *tag_decl = canonical_type->getAsTagDecl()) {
+ Completer(exporter, file).TraverseDecl(tag_decl);
+ } else if (auto interface_type = llvm::dyn_cast<ObjCInterfaceType>(
+ canonical_type.getTypePtr())) {
+ Completer(exporter, file).TraverseDecl(interface_type->getDecl());
+ } else {
+ Completer(exporter, file).TraverseType(canonical_type);
+ }
+}
+
+static clang::QualType ExportAllDeclaredTypes(
+ clang::ExternalASTMerger &merger,
+ clang::ASTContext &source, clang::FileManager &source_file_manager,
+ const clang::ExternalASTMerger::OriginMap &source_origin_map,
+ clang::FileID file, clang::QualType root) {
+ clang::ExternalASTMerger::ImporterSource importer_source =
+ { source, source_file_manager, source_origin_map };
+ merger.AddSources(importer_source);
+ clang::ASTImporter &exporter = merger.ImporterForOrigin(source);
+ CompleteAllDeclContexts(exporter, file, root);
+ clang::QualType ret = exporter.Import(root);
+ merger.RemoveSources(importer_source);
+ return ret;
+}
+
+TypeFromUser ClangExpressionDeclMap::DeportType(ClangASTContext &target,
+ ClangASTContext &source,
+ TypeFromParser parser_type) {
+ assert (&target == m_target->GetScratchClangASTContext());
+ assert ((TypeSystem*)&source == parser_type.GetTypeSystem());
+ assert (source.getASTContext() == m_ast_context);
+
+ if (m_ast_importer_sp) {
+ return TypeFromUser(m_ast_importer_sp->DeportType(
+ target.getASTContext(), source.getASTContext(),
+ parser_type.GetOpaqueQualType()),
+ &target);
+ } else if (m_merger_up) {
+ clang::FileID source_file =
+ source.getASTContext()->getSourceManager().getFileID(
+ source.getASTContext()->getTranslationUnitDecl()->getLocation());
+ auto scratch_ast_context = static_cast<ClangASTContextForExpressions*>(
+ m_target->GetScratchClangASTContext());
+ clang::QualType exported_type = ExportAllDeclaredTypes(
+ scratch_ast_context->GetMergerUnchecked(),
+ *source.getASTContext(), *source.getFileManager(),
+ m_merger_up->GetOrigins(),
+ source_file,
+ clang::QualType::getFromOpaquePtr(parser_type.GetOpaqueQualType()));
+ return TypeFromUser(exported_type.getAsOpaquePtr(), &target);
+ } else {
+ lldbassert(0 && "No mechanism for deporting a type!");
+ return TypeFromUser();
+ }
+}
+
bool ClangExpressionDeclMap::AddPersistentVariable(const NamedDecl *decl,
const ConstString &name,
TypeFromParser parser_type,
@@ -198,12 +328,8 @@ bool ClangExpressionDeclMap::AddPersistentVariable(const NamedDecl *decl,
if (target == nullptr)
return false;
- ClangASTContext *context(target->GetScratchClangASTContext());
-
- TypeFromUser user_type(m_ast_importer_sp->DeportType(
- context->getASTContext(), ast->getASTContext(),
- parser_type.GetOpaqueQualType()),
- context);
+ TypeFromUser user_type =
+ DeportType(*target->GetScratchClangASTContext(), *ast, parser_type);
uint32_t offset = m_parser_vars->m_materializer->AddResultVariable(
user_type, is_lvalue, m_keep_result_in_memory, m_result_delegate, err);
@@ -240,10 +366,7 @@ bool ClangExpressionDeclMap::AddPersistentVariable(const NamedDecl *decl,
ClangASTContext *context(target->GetScratchClangASTContext());
- TypeFromUser user_type(m_ast_importer_sp->DeportType(
- context->getASTContext(), ast->getASTContext(),
- parser_type.GetOpaqueQualType()),
- context);
+ TypeFromUser user_type = DeportType(*context, *ast, parser_type);
if (!user_type.GetOpaqueQualType()) {
if (log)
@@ -688,16 +811,18 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls(
}
ClangASTImporter::NamespaceMapSP namespace_map =
- m_ast_importer_sp->GetNamespaceMap(namespace_context);
+ m_ast_importer_sp
+ ? m_ast_importer_sp->GetNamespaceMap(namespace_context)
+ : ClangASTImporter::NamespaceMapSP();
+
+ if (!namespace_map)
+ return;
if (log && log->GetVerbose())
log->Printf(" CEDM::FEVD[%u] Inspecting (NamespaceMap*)%p (%d entries)",
current_id, static_cast<void *>(namespace_map.get()),
(int)namespace_map->size());
-
- if (!namespace_map)
- return;
-
+
for (ClangASTImporter::NamespaceMap::iterator i = namespace_map->begin(),
e = namespace_map->end();
i != e; ++i) {
@@ -739,16 +864,7 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls(
SymbolContextList sc_list;
const ConstString name(context.m_decl_name.getAsString().c_str());
-
- const char *name_unique_cstr = name.GetCString();
-
- if (name_unique_cstr == NULL)
- return;
-
- static ConstString id_name("id");
- static ConstString Class_name("Class");
-
- if (name == id_name || name == Class_name)
+ if (IgnoreName(name, false))
return;
// Only look for functions by name out in our symbols if the function
@@ -784,8 +900,7 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls(
if (!persistent_decl)
break;
- Decl *parser_persistent_decl = m_ast_importer_sp->CopyDecl(
- m_ast_context, scratch_ast_context, persistent_decl);
+ Decl *parser_persistent_decl = CopyDecl(persistent_decl);
if (!parser_persistent_decl)
break;
@@ -809,7 +924,7 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls(
} while (0);
}
- if (name_unique_cstr[0] == '$' && !namespace_decl) {
+ if (name.GetCString()[0] == '$' && !namespace_decl) {
static ConstString g_lldb_class_name("$__lldb_class");
if (name == g_lldb_class_name) {
@@ -1041,7 +1156,7 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls(
if (ast) {
clang::NamespaceDecl *namespace_decl =
ClangASTContext::GetUniqueNamespaceDeclaration(
- m_ast_context, name_unique_cstr, nullptr);
+ m_ast_context, name.GetCString(), nullptr);
if (namespace_decl) {
context.AddNamedDecl(namespace_decl);
clang::DeclContext *clang_decl_ctx =
@@ -1056,7 +1171,7 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls(
}
// any other $__lldb names should be weeded out now
- if (!::strncmp(name_unique_cstr, "$__lldb", sizeof("$__lldb") - 1))
+ if (name.GetStringRef().startswith("$__lldb"))
return;
ExpressionVariableSP pvar_sp(
@@ -1329,8 +1444,7 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls(
for (clang::NamedDecl *decl : decls_from_modules) {
if (llvm::isa<clang::FunctionDecl>(decl)) {
clang::NamedDecl *copied_decl =
- llvm::cast_or_null<FunctionDecl>(m_ast_importer_sp->CopyDecl(
- m_ast_context, &decl->getASTContext(), decl));
+ llvm::cast_or_null<FunctionDecl>(CopyDecl(decl));
if (copied_decl) {
context.AddNamedDecl(copied_decl);
context.m_found.function_with_type_info = true;
@@ -1372,9 +1486,7 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls(
current_id, name.GetCString());
}
- clang::Decl *copied_decl = m_ast_importer_sp->CopyDecl(
- m_ast_context, &decl_from_modules->getASTContext(),
- decl_from_modules);
+ clang::Decl *copied_decl = CopyDecl(decl_from_modules);
clang::FunctionDecl *copied_function_decl =
copied_decl ? dyn_cast<clang::FunctionDecl>(copied_decl)
: nullptr;
@@ -1401,9 +1513,7 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls(
current_id, name.GetCString());
}
- clang::Decl *copied_decl = m_ast_importer_sp->CopyDecl(
- m_ast_context, &decl_from_modules->getASTContext(),
- decl_from_modules);
+ clang::Decl *copied_decl = CopyDecl(decl_from_modules);
clang::VarDecl *copied_var_decl =
copied_decl ? dyn_cast_or_null<clang::VarDecl>(copied_decl)
: nullptr;
@@ -1430,17 +1540,17 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls(
// a generic
// data symbol, and -- if it is found -- treat it as a variable.
Status error;
-
+
const Symbol *data_symbol =
m_parser_vars->m_sym_ctx.FindBestGlobalDataSymbol(name, error);
-
+
if (!error.Success()) {
const unsigned diag_id =
m_ast_context->getDiagnostics().getCustomDiagID(
clang::DiagnosticsEngine::Level::Error, "%0");
m_ast_context->getDiagnostics().Report(diag_id) << error.AsCString();
}
-
+
if (data_symbol) {
std::string warning("got name from symbols: ");
warning.append(name.AsCString());
@@ -1455,49 +1565,6 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls(
}
}
-// static opaque_compiler_type_t
-// MaybePromoteToBlockPointerType
-//(
-// ASTContext *ast_context,
-// opaque_compiler_type_t candidate_type
-//)
-//{
-// if (!candidate_type)
-// return candidate_type;
-//
-// QualType candidate_qual_type = QualType::getFromOpaquePtr(candidate_type);
-//
-// const PointerType *candidate_pointer_type =
-// dyn_cast<PointerType>(candidate_qual_type);
-//
-// if (!candidate_pointer_type)
-// return candidate_type;
-//
-// QualType pointee_qual_type = candidate_pointer_type->getPointeeType();
-//
-// const RecordType *pointee_record_type =
-// dyn_cast<RecordType>(pointee_qual_type);
-//
-// if (!pointee_record_type)
-// return candidate_type;
-//
-// RecordDecl *pointee_record_decl = pointee_record_type->getDecl();
-//
-// if (!pointee_record_decl->isRecord())
-// return candidate_type;
-//
-// if
-// (!pointee_record_decl->getName().startswith(llvm::StringRef("__block_literal_")))
-// return candidate_type;
-//
-// QualType generic_function_type =
-// ast_context->getFunctionNoProtoType(ast_context->UnknownAnyTy);
-// QualType block_pointer_type =
-// ast_context->getBlockPointerType(generic_function_type);
-//
-// return block_pointer_type.getAsOpaquePtr();
-//}
-
bool ClangExpressionDeclMap::GetVariableValue(VariableSP &var,
lldb_private::Value &var_location,
TypeFromUser *user_type,
@@ -1537,7 +1604,6 @@ bool ClangExpressionDeclMap::GetVariableValue(VariableSP &var,
"There is no AST context for the current execution context");
return false;
}
- // var_clang_type = MaybePromoteToBlockPointerType (ast, var_clang_type);
DWARFExpression &var_location_expr = var->LocationExpression();
@@ -1762,7 +1828,9 @@ bool ClangExpressionDeclMap::ResolveUnknownTypes() {
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
Target *target = m_parser_vars->m_exe_ctx.GetTargetPtr();
- ClangASTContext *scratch_ast_context = target->GetScratchClangASTContext();
+ ClangASTContextForExpressions *scratch_ast_context =
+ static_cast<ClangASTContextForExpressions*>(
+ target->GetScratchClangASTContext());
for (size_t index = 0, num_entities = m_found_entities.GetSize();
index < num_entities; ++index) {
@@ -1793,9 +1861,20 @@ bool ClangExpressionDeclMap::ResolveUnknownTypes() {
var_type.getAsOpaquePtr(),
ClangASTContext::GetASTContext(&var_decl->getASTContext()));
- lldb::opaque_compiler_type_t copied_type = m_ast_importer_sp->CopyType(
- scratch_ast_context->getASTContext(), &var_decl->getASTContext(),
- var_type.getAsOpaquePtr());
+ lldb::opaque_compiler_type_t copied_type = 0;
+ if (m_ast_importer_sp) {
+ copied_type = m_ast_importer_sp->CopyType(
+ scratch_ast_context->getASTContext(), &var_decl->getASTContext(),
+ var_type.getAsOpaquePtr());
+ } else if (HasMerger()) {
+ copied_type = CopyTypeWithMerger(
+ var_decl->getASTContext(),
+ scratch_ast_context->GetMergerUnchecked(),
+ var_type).getAsOpaquePtr();
+ } else {
+ lldbassert(0 && "No mechanism to copy a resolved unknown type!");
+ return false;
+ }
if (!copied_type) {
if (log)
@@ -1892,8 +1971,7 @@ void ClangExpressionDeclMap::AddOneFunction(NameSearchContext &context,
if (!extern_c) {
TypeSystem *type_system = function->GetDeclContext().GetTypeSystem();
- if (ClangASTContext *src_ast =
- llvm::dyn_cast<ClangASTContext>(type_system)) {
+ if (llvm::isa<ClangASTContext>(type_system)) {
clang::DeclContext *src_decl_context =
(clang::DeclContext *)function->GetDeclContext()
.GetOpaqueDeclContext();
@@ -1905,9 +1983,7 @@ void ClangExpressionDeclMap::AddOneFunction(NameSearchContext &context,
src_function_decl->getTemplateSpecializationInfo()->getTemplate();
clang::FunctionTemplateDecl *copied_function_template =
llvm::dyn_cast_or_null<clang::FunctionTemplateDecl>(
- m_ast_importer_sp->CopyDecl(m_ast_context,
- src_ast->getASTContext(),
- function_template));
+ CopyDecl(function_template));
if (copied_function_template) {
if (log) {
ASTDumper ast_dumper((clang::Decl *)copied_function_template);
@@ -1928,9 +2004,7 @@ void ClangExpressionDeclMap::AddOneFunction(NameSearchContext &context,
} else if (src_function_decl) {
if (clang::FunctionDecl *copied_function_decl =
llvm::dyn_cast_or_null<clang::FunctionDecl>(
- m_ast_importer_sp->CopyDecl(m_ast_context,
- src_ast->getASTContext(),
- src_function_decl))) {
+ CopyDecl(src_function_decl))) {
if (log) {
ASTDumper ast_dumper((clang::Decl *)copied_function_decl);