diff --git a/lldb/include/lldb/Expression/ClangExpressionVariable.h b/lldb/include/lldb/Expression/ClangExpressionVariable.h index ced83e358f551f3ec6a2f6692b3faf950cb9113c..39b22bad00abfbce1c734b8fbdd856f9aff9956e 100644 --- a/lldb/include/lldb/Expression/ClangExpressionVariable.h +++ b/lldb/include/lldb/Expression/ClangExpressionVariable.h @@ -224,7 +224,8 @@ public: EVIsFreezeDried = 1 << 3, ///< This variable's authoritative version is in m_frozen_sp (for example, for statically-computed results) EVNeedsFreezeDry = 1 << 4, ///< Copy from m_live_sp to m_frozen_sp during dematerialization EVKeepInTarget = 1 << 5, ///< Keep the allocation after the expression is complete rather than freeze drying its contents and freeing it - EVUnknownType = 1 << 6 ///< This is a symbol of unknown type, and the type must be resolved after parsing is complete + EVTypeIsReference = 1 << 6, ///< The original type of this variable is a reference, so materialize the value rather than the location + EVUnknownType = 1 << 7 ///< This is a symbol of unknown type, and the type must be resolved after parsing is complete }; uint16_t m_flags; // takes elements of Flags diff --git a/lldb/include/lldb/Symbol/ClangASTContext.h b/lldb/include/lldb/Symbol/ClangASTContext.h index 13abb86f5b9c29ab17896ace2b5d7a085dd43a81..9cd7d2ea275bf71129897de99917fd744e6dbcfa 100644 --- a/lldb/include/lldb/Symbol/ClangASTContext.h +++ b/lldb/include/lldb/Symbol/ClangASTContext.h @@ -709,6 +709,9 @@ public: static bool IsPointerType (lldb::clang_type_t clang_type, lldb::clang_type_t *target_type = NULL); + static bool + IsReferenceType (lldb::clang_type_t clang_type, lldb::clang_type_t *target_type = NULL); + static bool IsPointerOrReferenceType (lldb::clang_type_t clang_type, lldb::clang_type_t *target_type = NULL); diff --git a/lldb/source/Expression/ClangExpressionDeclMap.cpp b/lldb/source/Expression/ClangExpressionDeclMap.cpp index 64a2508fb87209604bed0244940b1500b179606a..d92ea4e9c451081e5ed5c34284c4159b90602c52 100644 --- a/lldb/source/Expression/ClangExpressionDeclMap.cpp +++ b/lldb/source/Expression/ClangExpressionDeclMap.cpp @@ -1663,6 +1663,8 @@ ClangExpressionDeclMap::DoMaterializeOneVariable VariableSP &var(expr_var->m_parser_vars->m_lldb_var); lldb_private::Symbol *sym(expr_var->m_parser_vars->m_lldb_sym); + bool is_reference(expr_var->m_flags & ClangExpressionVariable::EVTypeIsReference); + std::auto_ptr location_value; if (var) @@ -1741,15 +1743,42 @@ ClangExpressionDeclMap::DoMaterializeOneVariable { Error write_error; - if (!process->WriteScalarToMemory (addr, - location_value->GetScalar(), - process->GetAddressByteSize(), - write_error)) + if (is_reference) { - err.SetErrorStringWithFormat ("Couldn't write %s to the target: %s", - name.GetCString(), - write_error.AsCString()); - return false; + Error read_error; + + addr_t ref_value = process->ReadPointerFromMemory(location_value->GetScalar().ULongLong(), read_error); + + if (!read_error.Success()) + { + err.SetErrorStringWithFormat ("Couldn't read reference to %s from the target: %s", + name.GetCString(), + read_error.AsCString()); + return false; + } + + if (!process->WritePointerToMemory(addr, + ref_value, + write_error)) + { + err.SetErrorStringWithFormat ("Couldn't write %s to the target: %s", + name.GetCString(), + write_error.AsCString()); + return false; + } + } + else + { + if (!process->WriteScalarToMemory (addr, + location_value->GetScalar(), + process->GetAddressByteSize(), + write_error)) + { + err.SetErrorStringWithFormat ("Couldn't write %s to the target: %s", + name.GetCString(), + write_error.AsCString()); + return false; + } } } } @@ -1792,6 +1821,9 @@ ClangExpressionDeclMap::DoMaterializeOneVariable if (dematerialize) { + if (is_reference) + return true; // reference types don't need demateralizing + // Get the location of the spare memory area out of the variable's live data. if (!expr_var->m_live_sp) @@ -1839,14 +1871,45 @@ ClangExpressionDeclMap::DoMaterializeOneVariable } else { + Error write_error; + + RegisterValue reg_value; + + if (!reg_ctx->ReadRegister (reg_info, reg_value)) + { + err.SetErrorStringWithFormat ("Couldn't read %s from %s", + name.GetCString(), + reg_info->name); + return false; + } + + if (is_reference) + { + write_error = reg_ctx->WriteRegisterValueToMemory(reg_info, + addr, + process->GetAddressByteSize(), + reg_value); + + if (!write_error.Success()) + { + err.SetErrorStringWithFormat ("Couldn't write %s from register %s to the target: %s", + name.GetCString(), + reg_info->name, + write_error.AsCString()); + return false; + } + + return true; + } + // Allocate a spare memory area to place the register's contents into. This memory area will be pointed to by the slot in the // struct. Error allocate_error; Scalar reg_addr (process->AllocateMemory (value_byte_size, - lldb::ePermissionsReadable | lldb::ePermissionsWritable, - allocate_error)); + lldb::ePermissionsReadable | lldb::ePermissionsWritable, + allocate_error)); if (reg_addr.ULongLong() == LLDB_INVALID_ADDRESS) { @@ -1867,13 +1930,11 @@ ClangExpressionDeclMap::DoMaterializeOneVariable value_byte_size); // Now write the location of the area into the struct. - - Error write_error; - + if (!process->WriteScalarToMemory (addr, - reg_addr, - process->GetAddressByteSize(), - write_error)) + reg_addr, + process->GetAddressByteSize(), + write_error)) { err.SetErrorStringWithFormat ("Couldn't write %s to the target: %s", name.GetCString(), @@ -1889,8 +1950,6 @@ ClangExpressionDeclMap::DoMaterializeOneVariable return false; } - RegisterValue reg_value; - if (!reg_ctx->ReadRegister (reg_info, reg_value)) { err.SetErrorStringWithFormat ("Couldn't read %s from %s", @@ -2924,7 +2983,15 @@ ClangExpressionDeclMap::AddOneVariable (NameSearchContext &context, VariableSP v if (!var_location) return; - NamedDecl *var_decl = context.AddVarDecl(ClangASTContext::CreateLValueReferenceType(pt.GetASTContext(), pt.GetOpaqueQualType())); + NamedDecl *var_decl; + + bool is_reference = ClangASTContext::IsReferenceType(pt.GetOpaqueQualType()); + + if (is_reference) + var_decl = context.AddVarDecl(pt.GetOpaqueQualType()); + else + var_decl = context.AddVarDecl(ClangASTContext::CreateLValueReferenceType(pt.GetASTContext(), pt.GetOpaqueQualType())); + std::string decl_name(context.m_decl_name.getAsString()); ConstString entity_name(decl_name.c_str()); ClangExpressionVariableSP entity(m_found_entities.CreateVariable (m_parser_vars->m_exe_ctx->GetBestExecutionContextScope (), @@ -2940,6 +3007,9 @@ ClangExpressionDeclMap::AddOneVariable (NameSearchContext &context, VariableSP v entity->m_parser_vars->m_lldb_value = var_location; entity->m_parser_vars->m_lldb_var = var; + if (is_reference) + entity->m_flags |= ClangExpressionVariable::EVTypeIsReference; + if (log) { ASTDumper ast_dumper(var_decl); diff --git a/lldb/source/Symbol/ClangASTContext.cpp b/lldb/source/Symbol/ClangASTContext.cpp index 8e7e4f6c54bc4045ce673d21cea57b98efb762f8..021bd66101ccb1cf9ed95480eeed2595197147e4 100644 --- a/lldb/source/Symbol/ClangASTContext.cpp +++ b/lldb/source/Symbol/ClangASTContext.cpp @@ -4964,6 +4964,35 @@ ClangASTContext::IsPossibleCPlusPlusDynamicType (clang::ASTContext *ast, clang_t return false; } +bool +ClangASTContext::IsReferenceType (clang_type_t clang_type, clang_type_t *target_type) +{ + if (clang_type == NULL) + return false; + + QualType qual_type (QualType::getFromOpaquePtr(clang_type)); + const clang::Type::TypeClass type_class = qual_type->getTypeClass(); + + switch (type_class) + { + case clang::Type::LValueReference: + if (target_type) + *target_type = cast(qual_type)->desugar().getAsOpaquePtr(); + return true; + case clang::Type::RValueReference: + if (target_type) + *target_type = cast(qual_type)->desugar().getAsOpaquePtr(); + return true; + case clang::Type::Typedef: + return ClangASTContext::IsReferenceType (cast(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr()); + case clang::Type::Elaborated: + return ClangASTContext::IsReferenceType (cast(qual_type)->getNamedType().getAsOpaquePtr()); + default: + break; + } + + return false; +} bool ClangASTContext::IsPointerOrReferenceType (clang_type_t clang_type, clang_type_t*target_type)