From 9829801437b0bea7caa218df91eb6a6c4ffa2a34 Mon Sep 17 00:00:00 2001 From: Sean Callanan Date: Thu, 27 Oct 2011 19:41:13 +0000 Subject: [PATCH] Changed the way the expression parser handles variables of reference types. Previously, such variables were materialized as references to those references, which caused undesried behavior in Clang and was useless anyway (the benefit of using references to variables is that it allows expressions to modify variables in place, but for references that's not required). Now we just materialize the references directly, which fixes a variety of expressions that use references. llvm-svn: 143137 --- .../lldb/Expression/ClangExpressionVariable.h | 3 +- lldb/include/lldb/Symbol/ClangASTContext.h | 3 + .../Expression/ClangExpressionDeclMap.cpp | 108 +++++++++++++++--- lldb/source/Symbol/ClangASTContext.cpp | 29 +++++ 4 files changed, 123 insertions(+), 20 deletions(-) diff --git a/lldb/include/lldb/Expression/ClangExpressionVariable.h b/lldb/include/lldb/Expression/ClangExpressionVariable.h index ced83e358f55..39b22bad00ab 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 13abb86f5b9c..9cd7d2ea275b 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 64a2508fb872..d92ea4e9c451 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 8e7e4f6c54bc..021bd66101cc 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) -- GitLab