diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2022-07-24 15:03:44 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2022-07-24 15:03:44 +0000 |
commit | 4b4fe385e49bd883fd183b5f21c1ea486c722e61 (patch) | |
tree | c3d8fdb355c9c73e57723718c22103aaf7d15aa6 /lldb/source/Plugins/ExpressionParser/Clang | |
parent | 1f917f69ff07f09b6dbb670971f57f8efe718b84 (diff) | |
download | src-4b4fe385e49bd883fd183b5f21c1ea486c722e61.tar.gz src-4b4fe385e49bd883fd183b5f21c1ea486c722e61.zip |
Vendor import of llvm-project main llvmorg-15-init-17485-ga3e38b4a206b.vendor/llvm-project/llvmorg-15-init-17485-ga3e38b4a206b
Diffstat (limited to 'lldb/source/Plugins/ExpressionParser/Clang')
11 files changed, 375 insertions, 40 deletions
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp index 7a1ac7870547..799ae29e2841 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp @@ -197,6 +197,27 @@ bool ASTResultSynthesizer::SynthesizeObjCMethodResult( return ret; } +/// Returns true if LLDB can take the address of the given lvalue for the sake +/// of capturing the expression result. Returns false if LLDB should instead +/// store the expression result in a result variable. +static bool CanTakeAddressOfLValue(const Expr *lvalue_expr) { + assert(lvalue_expr->getValueKind() == VK_LValue && + "lvalue_expr not a lvalue"); + + QualType qt = lvalue_expr->getType(); + // If the lvalue has const-qualified non-volatile integral or enum type, then + // the underlying value might come from a const static data member as + // described in C++11 [class.static.data]p3. If that's the case, then the + // value might not have an address if the user didn't also define the member + // in a namespace scope. Taking the address would cause that LLDB later fails + // to link the expression, so those lvalues should be stored in a result + // variable. + if (qt->isIntegralOrEnumerationType() && qt.isConstQualified() && + !qt.isVolatileQualified()) + return false; + return true; +} + bool ASTResultSynthesizer::SynthesizeBodyResult(CompoundStmt *Body, DeclContext *DC) { Log *log = GetLog(LLDBLog::Expressions); @@ -265,6 +286,10 @@ bool ASTResultSynthesizer::SynthesizeBodyResult(CompoundStmt *Body, // - During dematerialization, $0 is marked up as a load address with value // equal to the contents of the structure entry. // + // - Note: if we cannot take an address of the resulting Lvalue (e.g. it's + // a static const member without an out-of-class definition), then we + // follow the Rvalue route. + // // For Rvalues // // - In AST result synthesis the expression E is transformed into an @@ -304,7 +329,7 @@ bool ASTResultSynthesizer::SynthesizeBodyResult(CompoundStmt *Body, clang::VarDecl *result_decl = nullptr; - if (is_lvalue) { + if (is_lvalue && CanTakeAddressOfLValue(last_expr)) { IdentifierInfo *result_ptr_id; if (expr_type->isFunctionType()) diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp index 1bf29efb0bee..f8443d608ac3 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp @@ -1430,10 +1430,9 @@ static bool ImportOffsetMap(llvm::DenseMap<const D *, O> &destination_map, std::vector<PairType> sorted_items; sorted_items.reserve(source_map.size()); sorted_items.assign(source_map.begin(), source_map.end()); - llvm::sort(sorted_items.begin(), sorted_items.end(), - [](const PairType &lhs, const PairType &rhs) { - return lhs.second < rhs.second; - }); + llvm::sort(sorted_items, [](const PairType &lhs, const PairType &rhs) { + return lhs.second < rhs.second; + }); for (const auto &item : sorted_items) { DeclFromUser<D> user_decl(const_cast<D *>(item.first)); 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})", - decl_name, ClangUtil::DumpDecl(var_decl), ClangUtil::ToString(ut)); + 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})", + 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, diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h index f968f859cc72..bf7646ccaedf 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h @@ -531,6 +531,23 @@ private: TypeFromParser *parser_type = nullptr); /// Use the NameSearchContext to generate a Decl for the given LLDB + /// ValueObject, and put it in the list of found entities. + /// + /// Helper function used by the other AddOneVariable APIs. + /// + /// \param[in,out] context + /// The NameSearchContext to use when constructing the Decl. + /// + /// \param[in] pt + /// The CompilerType of the variable we're adding a Decl for. + /// + /// \param[in] var + /// The LLDB ValueObject that needs a Decl. + ClangExpressionVariable::ParserVars * + AddExpressionVariable(NameSearchContext &context, TypeFromParser const &pt, + lldb::ValueObjectSP valobj); + + /// Use the NameSearchContext to generate a Decl for the given LLDB /// Variable, and put it in the Tuple list. /// /// \param[in] context @@ -544,6 +561,20 @@ private: void AddOneVariable(NameSearchContext &context, lldb::VariableSP var, lldb::ValueObjectSP valobj); + /// Use the NameSearchContext to generate a Decl for the given ValueObject + /// and put it in the list of found entities. + /// + /// \param[in,out] context + /// The NameSearchContext to use when constructing the Decl. + /// + /// \param[in] valobj + /// The ValueObject that needs a Decl. + /// + /// \param[in] valobj_provider Callback that fetches a ValueObjectSP + /// from the specified frame + void AddOneVariable(NameSearchContext &context, lldb::ValueObjectSP valobj, + ValueObjectProviderTy valobj_provider); + /// Use the NameSearchContext to generate a Decl for the given persistent /// variable, and put it in the list of found entities. /// diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp index 5168f637c443..56c00b35ba11 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp @@ -8,6 +8,8 @@ #include "ClangExpressionSourceCode.h" +#include "ClangExpressionUtil.h" + #include "clang/Basic/CharInfo.h" #include "clang/Basic/FileManager.h" #include "clang/Basic/SourceManager.h" @@ -27,6 +29,7 @@ #include "lldb/Target/StackFrame.h" #include "lldb/Target/Target.h" #include "lldb/Utility/StreamString.h" +#include "lldb/lldb-forward.h" using namespace lldb_private; @@ -200,6 +203,34 @@ public: return m_tokens.find(token) != m_tokens.end(); } }; + +// If we're evaluating from inside a lambda that captures a 'this' pointer, +// add a "using" declaration to 'stream' for each capture used in the +// expression (tokenized by 'verifier'). +// +// If no 'this' capture exists, generate no using declarations. Instead +// capture lookups will get resolved by the same mechanism as class member +// variable lookup. That's because Clang generates an unnamed structure +// representing the lambda closure whose members are the captured variables. +void AddLambdaCaptureDecls(StreamString &stream, StackFrame *frame, + TokenVerifier const &verifier) { + assert(frame); + + if (auto thisValSP = ClangExpressionUtil::GetLambdaValueObject(frame)) { + uint32_t numChildren = thisValSP->GetNumChildren(); + for (uint32_t i = 0; i < numChildren; ++i) { + auto childVal = thisValSP->GetChildAtIndex(i, true); + ConstString childName(childVal ? childVal->GetName() : ConstString("")); + + if (!childName.IsEmpty() && verifier.hasToken(childName.GetStringRef()) && + childName != "this") { + stream.Printf("using $__lldb_local_vars::%s;\n", + childName.GetCString()); + } + } + } +} + } // namespace TokenVerifier::TokenVerifier(std::string body) { @@ -264,16 +295,24 @@ TokenVerifier::TokenVerifier(std::string body) { } } -void ClangExpressionSourceCode::AddLocalVariableDecls( - const lldb::VariableListSP &var_list_sp, StreamString &stream, - const std::string &expr) const { +void ClangExpressionSourceCode::AddLocalVariableDecls(StreamString &stream, + const std::string &expr, + StackFrame *frame) const { + assert(frame); TokenVerifier tokens(expr); + lldb::VariableListSP var_list_sp = frame->GetInScopeVariableList(false, true); + for (size_t i = 0; i < var_list_sp->GetSize(); i++) { lldb::VariableSP var_sp = var_list_sp->GetVariableAtIndex(i); ConstString var_name = var_sp->GetName(); + if (var_name == "this" && m_wrap_kind == WrapKind::CppMemberFunction) { + AddLambdaCaptureDecls(stream, frame, tokens); + + continue; + } // We can check for .block_descriptor w/o checking for langauge since this // is not a valid identifier in either C or C++. @@ -288,9 +327,6 @@ void ClangExpressionSourceCode::AddLocalVariableDecls( if ((var_name == "self" || var_name == "_cmd") && is_objc) continue; - if (var_name == "this" && m_wrap_kind == WrapKind::CppMemberFunction) - continue; - stream.Printf("using $__lldb_local_vars::%s;\n", var_name.AsCString()); } } @@ -376,10 +412,8 @@ bool ClangExpressionSourceCode::GetText( if (add_locals) if (target->GetInjectLocalVariables(&exe_ctx)) { - lldb::VariableListSP var_list_sp = - frame->GetInScopeVariableList(false, true); - AddLocalVariableDecls(var_list_sp, lldb_local_var_decls, - force_add_all_locals ? "" : m_body); + AddLocalVariableDecls(lldb_local_var_decls, + force_add_all_locals ? "" : m_body, frame); } } diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.h index 54ae837fb30f..f721bb2f319e 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.h +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.h @@ -78,9 +78,19 @@ protected: Wrapping wrap, WrapKind wrap_kind); private: - void AddLocalVariableDecls(const lldb::VariableListSP &var_list_sp, - StreamString &stream, - const std::string &expr) const; + /// Writes "using" declarations for local variables into the specified stream. + /// + /// Behaviour is undefined if 'frame == nullptr'. + /// + /// \param[out] stream Stream that this function generates "using" + /// declarations into. + /// + /// \param[in] expr Expression source that we're evaluating. + /// + /// \param[in] frame StackFrame which carries information about the local + /// variables that we're generating "using" declarations for. + void AddLocalVariableDecls(StreamString &stream, const std::string &expr, + StackFrame *frame) const; /// String marking the start of the user expression. std::string m_start_marker; diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionUtil.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionUtil.cpp new file mode 100644 index 000000000000..9b490e1c036e --- /dev/null +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionUtil.cpp @@ -0,0 +1,27 @@ +//===-- ClangExpressionUtil.cpp -------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "ClangExpressionUtil.h" + +#include "lldb/Core/ValueObject.h" +#include "lldb/Target/StackFrame.h" +#include "lldb/Utility/ConstString.h" + +namespace lldb_private { +namespace ClangExpressionUtil { +lldb::ValueObjectSP GetLambdaValueObject(StackFrame *frame) { + assert(frame); + + if (auto this_val_sp = frame->FindVariable(ConstString("this"))) + if (this_val_sp->GetChildMemberWithName(ConstString("this"), true)) + return this_val_sp; + + return nullptr; +} +} // namespace ClangExpressionUtil +} // namespace lldb_private diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionUtil.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionUtil.h new file mode 100644 index 000000000000..fb8b857256c0 --- /dev/null +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionUtil.h @@ -0,0 +1,30 @@ +//===-- ClangExpressionUtil.h -----------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_SOURCE_PLUGINS_EXPRESSIONPARSER_CLANG_CLANGEXPRESSIONUTIL_H +#define LLDB_SOURCE_PLUGINS_EXPRESSIONPARSER_CLANG_CLANGEXPRESSIONUTIL_H + +#include "lldb/lldb-private.h" + +namespace lldb_private { +namespace ClangExpressionUtil { +/// Returns a ValueObject for the lambda class in the current frame +/// +/// To represent a lambda, Clang generates an artificial class +/// whose members are the captures and whose operator() is the +/// lambda implementation. If we capture a 'this' pointer, +/// the artifical class will contain a member variable named 'this'. +/// +/// This method returns the 'this' pointer to the artificial lambda +/// class if a real 'this' was captured. Otherwise, returns nullptr. +lldb::ValueObjectSP GetLambdaValueObject(StackFrame *frame); + +} // namespace ClangExpressionUtil +} // namespace lldb_private + +#endif // LLDB_SOURCE_PLUGINS_EXPRESSIONPARSER_CLANG_CLANGEXPRESSIONHELPER_H diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.h index 7bb68e78373f..c7d9e05269fa 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.h +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.h @@ -116,7 +116,7 @@ public: /// The following values should not live beyond parsing class ParserVars { public: - ParserVars() : m_lldb_value(), m_lldb_var() {} + ParserVars() = default; const clang::NamedDecl *m_named_decl = nullptr; ///< The Decl corresponding to this variable @@ -129,6 +129,12 @@ public: const lldb_private::Symbol *m_lldb_sym = nullptr; ///< The original symbol for this /// variable, if it was a symbol + + /// Callback that provides a ValueObject for the + /// specified frame. Used by the materializer for + /// re-fetching ValueObjects when materializing + /// ivars. + ValueObjectProviderTy m_lldb_valobj_provider; }; private: diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp index 78b8bf11220a..7145e7804e68 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp @@ -872,6 +872,34 @@ bool ClangUserExpression::Complete(ExecutionContext &exe_ctx, return true; } +lldb::addr_t ClangUserExpression::GetCppObjectPointer( + lldb::StackFrameSP frame_sp, ConstString &object_name, Status &err) { + auto valobj_sp = + GetObjectPointerValueObject(std::move(frame_sp), object_name, err); + + // We're inside a C++ class method. This could potentially be an unnamed + // lambda structure. If the lambda captured a "this", that should be + // the object pointer. + if (auto thisChildSP = + valobj_sp->GetChildMemberWithName(ConstString("this"), true)) { + valobj_sp = thisChildSP; + } + + if (!err.Success() || !valobj_sp.get()) + return LLDB_INVALID_ADDRESS; + + lldb::addr_t ret = valobj_sp->GetValueAsUnsigned(LLDB_INVALID_ADDRESS); + + if (ret == LLDB_INVALID_ADDRESS) { + err.SetErrorStringWithFormat( + "Couldn't load '%s' because its value couldn't be evaluated", + object_name.AsCString()); + return LLDB_INVALID_ADDRESS; + } + + return ret; +} + bool ClangUserExpression::AddArguments(ExecutionContext &exe_ctx, std::vector<lldb::addr_t> &args, lldb::addr_t struct_address, @@ -906,8 +934,14 @@ bool ClangUserExpression::AddArguments(ExecutionContext &exe_ctx, address_type != eAddressTypeLoad) object_ptr_error.SetErrorString("Can't get context object's " "debuggee address"); - } else - object_ptr = GetObjectPointer(frame_sp, object_name, object_ptr_error); + } else { + if (m_in_cplusplus_method) { + object_ptr = + GetCppObjectPointer(frame_sp, object_name, object_ptr_error); + } else { + object_ptr = GetObjectPointer(frame_sp, object_name, object_ptr_error); + } + } if (!object_ptr_error.Success()) { exe_ctx.GetTargetRef().GetDebugger().GetAsyncOutputStream()->Printf( diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h index 30cdd2f3e990..4d5458f1807d 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h @@ -198,6 +198,10 @@ private: ExecutionContext &exe_ctx, std::vector<std::string> modules_to_import, bool for_completion); + + lldb::addr_t GetCppObjectPointer(lldb::StackFrameSP frame, + ConstString &object_name, Status &err); + /// Defines how the current expression should be wrapped. ClangExpressionSourceCode::WrapKind GetWrapKind() const; bool SetupPersistentState(DiagnosticManager &diagnostic_manager, |