summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSean Callanan <scallanan@apple.com>2011-10-27 19:41:13 +0000
committerSean Callanan <scallanan@apple.com>2011-10-27 19:41:13 +0000
commit9829801437b0bea7caa218df91eb6a6c4ffa2a34 (patch)
tree662b51d15583dbf7fa3c67c1b425021069d11d26
parent95fd2ca69f21f715d846d45178b1e57a76ee76ec (diff)
downloadbcm5719-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.h3
-rw-r--r--lldb/include/lldb/Symbol/ClangASTContext.h3
-rw-r--r--lldb/source/Expression/ClangExpressionDeclMap.cpp108
-rw-r--r--lldb/source/Symbol/ClangASTContext.cpp29
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)
OpenPOWER on IntegriCloud