diff options
Diffstat (limited to 'lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp')
| -rw-r--r-- | lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp | 173 |
1 files changed, 154 insertions, 19 deletions
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp index 4305a9982343..6ba03dad98d1 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp @@ -9,10 +9,13 @@ #include "ClangExpressionDeclMap.h" #include "ClangASTSource.h" +#include "ClangExpressionUtil.h" +#include "ClangExpressionVariable.h" #include "ClangModulesDeclVendor.h" #include "ClangPersistentVariables.h" #include "ClangUtil.h" +#include "NameSearchContext.h" #include "Plugins/TypeSystem/Clang/TypeSystemClang.h" #include "lldb/Core/Address.h" #include "lldb/Core/Module.h" @@ -44,6 +47,7 @@ #include "lldb/Utility/Log.h" #include "lldb/Utility/RegisterValue.h" #include "lldb/Utility/Status.h" +#include "lldb/lldb-private-types.h" #include "lldb/lldb-private.h" #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" @@ -62,6 +66,24 @@ using namespace clang; static const char *g_lldb_local_vars_namespace_cstr = "$__lldb_local_vars"; +namespace { +/// A lambda is represented by Clang as an artifical class whose +/// members are the lambda captures. If we capture a 'this' pointer, +/// the artifical class will contain a member variable named 'this'. +/// The function returns a ValueObject for the captured 'this' if such +/// member exists. If no 'this' was captured, return a nullptr. +lldb::ValueObjectSP GetCapturedThisValueObject(StackFrame *frame) { + assert(frame); + + if (auto thisValSP = frame->FindVariable(ConstString("this"))) + if (auto thisThisValSP = + thisValSP->GetChildMemberWithName(ConstString("this"), true)) + return thisThisValSP; + + return nullptr; +} +} // namespace + ClangExpressionDeclMap::ClangExpressionDeclMap( bool keep_result_in_memory, Materializer::PersistentVariableDelegate *result_delegate, @@ -394,6 +416,10 @@ bool ClangExpressionDeclMap::AddValueToStruct(const NamedDecl *decl, else if (parser_vars->m_lldb_var) offset = m_parser_vars->m_materializer->AddVariable( parser_vars->m_lldb_var, err); + else if (parser_vars->m_lldb_valobj_provider) { + offset = m_parser_vars->m_materializer->AddValueObject( + name, parser_vars->m_lldb_valobj_provider, err); + } } if (!err.Success()) @@ -795,6 +821,28 @@ void ClangExpressionDeclMap::LookUpLldbClass(NameSearchContext &context) { TypeSystemClang::DeclContextGetAsCXXMethodDecl(function_decl_ctx); if (method_decl) { + if (auto capturedThis = GetCapturedThisValueObject(frame)) { + // We're inside a lambda and we captured a 'this'. + // Import the outer class's AST instead of the + // (unnamed) lambda structure AST so unqualified + // member lookups are understood by the Clang parser. + // + // If we're in a lambda which didn't capture 'this', + // $__lldb_class will correspond to the lambda closure + // AST and references to captures will resolve like + // regular member varaiable accesses do. + TypeFromUser pointee_type = + capturedThis->GetCompilerType().GetPointeeType(); + + LLDB_LOG(log, + " CEDM::FEVD Adding captured type ({0} for" + " $__lldb_class: {1}", + capturedThis->GetTypeName(), capturedThis->GetName()); + + AddContextClassType(context, pointee_type); + return; + } + clang::CXXRecordDecl *class_decl = method_decl->getParent(); QualType class_qual_type(class_decl->getTypeForDecl(), 0); @@ -1053,6 +1101,30 @@ bool ClangExpressionDeclMap::LookupLocalVariable( context.m_found_variable = true; } } + + // We're in a local_var_lookup but haven't found any local variables + // so far. When performing a variable lookup from within the context of + // a lambda, we count the lambda captures as local variables. Thus, + // see if we captured any variables with the requested 'name'. + if (!variable_found) { + auto find_capture = [](ConstString varname, + StackFrame *frame) -> ValueObjectSP { + if (auto lambda = ClangExpressionUtil::GetLambdaValueObject(frame)) { + if (auto capture = lambda->GetChildMemberWithName(varname, true)) { + return capture; + } + } + + return nullptr; + }; + + if (auto capture = find_capture(name, frame)) { + variable_found = true; + context.m_found_variable = true; + AddOneVariable(context, std::move(capture), std::move(find_capture)); + } + } + return variable_found; } @@ -1493,25 +1565,15 @@ bool ClangExpressionDeclMap::GetVariableValue(VariableSP &var, return true; } -void ClangExpressionDeclMap::AddOneVariable(NameSearchContext &context, - VariableSP var, - ValueObjectSP valobj) { - assert(m_parser_vars.get()); - - Log *log = GetLog(LLDBLog::Expressions); - - TypeFromUser ut; - TypeFromParser pt; - Value var_location; - - if (!GetVariableValue(var, var_location, &ut, &pt)) - return; - +ClangExpressionVariable::ParserVars * +ClangExpressionDeclMap::AddExpressionVariable(NameSearchContext &context, + TypeFromParser const &pt, + ValueObjectSP valobj) { clang::QualType parser_opaque_type = QualType::getFromOpaquePtr(pt.GetOpaqueQualType()); if (parser_opaque_type.isNull()) - return; + return nullptr; if (const clang::Type *parser_type = parser_opaque_type.getTypePtr()) { if (const TagType *tag_type = dyn_cast<TagType>(parser_type)) @@ -1538,16 +1600,89 @@ void ClangExpressionDeclMap::AddOneVariable(NameSearchContext &context, entity->EnableParserVars(GetParserID()); ClangExpressionVariable::ParserVars *parser_vars = entity->GetParserVars(GetParserID()); + parser_vars->m_named_decl = var_decl; - parser_vars->m_llvm_value = nullptr; - parser_vars->m_lldb_value = var_location; - parser_vars->m_lldb_var = var; if (is_reference) entity->m_flags |= ClangExpressionVariable::EVTypeIsReference; + return parser_vars; +} + +void ClangExpressionDeclMap::AddOneVariable( + NameSearchContext &context, ValueObjectSP valobj, + ValueObjectProviderTy valobj_provider) { + assert(m_parser_vars.get()); + assert(valobj); + + Log *log = GetLog(LLDBLog::Expressions); + + Value var_location = valobj->GetValue(); + + TypeFromUser user_type = valobj->GetCompilerType(); + + TypeSystemClang *clang_ast = + llvm::dyn_cast_or_null<TypeSystemClang>(user_type.GetTypeSystem()); + + if (!clang_ast) { + LLDB_LOG(log, "Skipped a definition because it has no Clang AST"); + return; + } + + TypeFromParser parser_type = GuardedCopyType(user_type); + + if (!parser_type) { + LLDB_LOG(log, + "Couldn't copy a variable's type into the parser's AST context"); + + return; + } + + if (var_location.GetContextType() == Value::ContextType::Invalid) + var_location.SetCompilerType(parser_type); + + ClangExpressionVariable::ParserVars *parser_vars = + AddExpressionVariable(context, parser_type, valobj); + + if (!parser_vars) + return; + + LLDB_LOG(log, " CEDM::FEVD Found variable {0}, returned\n{1} (original {2})", + context.m_decl_name, ClangUtil::DumpDecl(parser_vars->m_named_decl), + ClangUtil::ToString(user_type)); + + parser_vars->m_llvm_value = nullptr; + parser_vars->m_lldb_value = std::move(var_location); + parser_vars->m_lldb_valobj_provider = std::move(valobj_provider); +} + +void ClangExpressionDeclMap::AddOneVariable(NameSearchContext &context, + VariableSP var, + ValueObjectSP valobj) { + assert(m_parser_vars.get()); + + Log *log = GetLog(LLDBLog::Expressions); + + TypeFromUser ut; + TypeFromParser pt; + Value var_location; + + if (!GetVariableValue(var, var_location, &ut, &pt)) + return; + + ClangExpressionVariable::ParserVars *parser_vars = + AddExpressionVariable(context, pt, std::move(valobj)); + + if (!parser_vars) + return; + LLDB_LOG(log, " CEDM::FEVD Found variable {0}, returned\n{1} (original {2})", - decl_name, ClangUtil::DumpDecl(var_decl), ClangUtil::ToString(ut)); + context.m_decl_name, ClangUtil::DumpDecl(parser_vars->m_named_decl), + ClangUtil::ToString(ut)); + + parser_vars->m_llvm_value = nullptr; + parser_vars->m_lldb_value = var_location; + parser_vars->m_lldb_var = var; } void ClangExpressionDeclMap::AddOneVariable(NameSearchContext &context, |
