summaryrefslogtreecommitdiff
path: root/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp')
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp173
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,