diff options
| author | Sean Callanan <scallanan@apple.com> | 2011-10-27 19:41:13 +0000 |
|---|---|---|
| committer | Sean Callanan <scallanan@apple.com> | 2011-10-27 19:41:13 +0000 |
| commit | 9829801437b0bea7caa218df91eb6a6c4ffa2a34 (patch) | |
| tree | 662b51d15583dbf7fa3c67c1b425021069d11d26 | |
| parent | 95fd2ca69f21f715d846d45178b1e57a76ee76ec (diff) | |
| download | bcm5719-llvm-9829801437b0bea7caa218df91eb6a6c4ffa2a34.tar.gz bcm5719-llvm-9829801437b0bea7caa218df91eb6a6c4ffa2a34.zip | |
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
| -rw-r--r-- | lldb/include/lldb/Expression/ClangExpressionVariable.h | 3 | ||||
| -rw-r--r-- | lldb/include/lldb/Symbol/ClangASTContext.h | 3 | ||||
| -rw-r--r-- | lldb/source/Expression/ClangExpressionDeclMap.cpp | 108 | ||||
| -rw-r--r-- | 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 ced83e358f5..39b22bad00a 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 13abb86f5b9..9cd7d2ea275 100644 --- a/lldb/include/lldb/Symbol/ClangASTContext.h +++ b/lldb/include/lldb/Symbol/ClangASTContext.h @@ -710,6 +710,9 @@ public: 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); static bool diff --git a/lldb/source/Expression/ClangExpressionDeclMap.cpp b/lldb/source/Expression/ClangExpressionDeclMap.cpp index 64a2508fb87..d92ea4e9c45 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<lldb_private::Value> 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 8e7e4f6c54b..021bd66101c 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<LValueReferenceType>(qual_type)->desugar().getAsOpaquePtr(); + return true; + case clang::Type::RValueReference: + if (target_type) + *target_type = cast<LValueReferenceType>(qual_type)->desugar().getAsOpaquePtr(); + return true; + case clang::Type::Typedef: + return ClangASTContext::IsReferenceType (cast<TypedefType>(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr()); + case clang::Type::Elaborated: + return ClangASTContext::IsReferenceType (cast<ElaboratedType>(qual_type)->getNamedType().getAsOpaquePtr()); + default: + break; + } + + return false; +} bool ClangASTContext::IsPointerOrReferenceType (clang_type_t clang_type, clang_type_t*target_type) |

