summaryrefslogtreecommitdiffstats
path: root/lldb/source/Core/ValueObject.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source/Core/ValueObject.cpp')
-rw-r--r--lldb/source/Core/ValueObject.cpp406
1 files changed, 406 insertions, 0 deletions
diff --git a/lldb/source/Core/ValueObject.cpp b/lldb/source/Core/ValueObject.cpp
index 918be0923c3..1c8a7051217 100644
--- a/lldb/source/Core/ValueObject.cpp
+++ b/lldb/source/Core/ValueObject.cpp
@@ -1366,6 +1366,412 @@ ValueObject::GetExpressionPath (Stream &s, bool qualify_cxx_base_classes, GetExp
}
}
+lldb::ValueObjectSP
+ValueObject::GetValueForExpressionPath(const char* expression,
+ const char** first_unparsed,
+ ExpressionPathScanEndReason* reason_to_stop,
+ ExpressionPathEndResultType* final_value_type,
+ const GetValueForExpressionPathOptions& options,
+ ExpressionPathAftermath* final_task_on_target)
+{
+
+ const char* dummy_first_unparsed;
+ ExpressionPathScanEndReason dummy_reason_to_stop;
+ ExpressionPathEndResultType dummy_final_value_type;
+ ExpressionPathAftermath dummy_final_task_on_target = ValueObject::eNothing;
+
+ ValueObjectSP ret_val = GetValueForExpressionPath_Impl(expression,
+ first_unparsed ? first_unparsed : &dummy_first_unparsed,
+ reason_to_stop ? reason_to_stop : &dummy_reason_to_stop,
+ final_value_type ? final_value_type : &dummy_final_value_type,
+ options,
+ final_task_on_target ? final_task_on_target : &dummy_final_task_on_target);
+
+ if (!final_task_on_target || *final_task_on_target == ValueObject::eNothing)
+ {
+ return ret_val;
+ }
+ if (ret_val.get() && *final_value_type == ePlain) // I can only deref and takeaddress of plain objects
+ {
+ if (*final_task_on_target == ValueObject::eDereference)
+ {
+ Error error;
+ ValueObjectSP final_value = ret_val->Dereference(error);
+ if (error.Fail() || !final_value.get())
+ {
+ *reason_to_stop = ValueObject::eDereferencingFailed;
+ *final_value_type = ValueObject::eInvalid;
+ return ValueObjectSP();
+ }
+ else
+ {
+ *final_task_on_target = ValueObject::eNothing;
+ return final_value;
+ }
+ }
+ if (*final_task_on_target == ValueObject::eTakeAddress)
+ {
+ Error error;
+ ValueObjectSP final_value = ret_val->AddressOf(error);
+ if (error.Fail() || !final_value.get())
+ {
+ *reason_to_stop = ValueObject::eTakingAddressFailed;
+ *final_value_type = ValueObject::eInvalid;
+ return ValueObjectSP();
+ }
+ else
+ {
+ *final_task_on_target = ValueObject::eNothing;
+ return final_value;
+ }
+ }
+ }
+ return ret_val; // final_task_on_target will still have its original value, so you know I did not do it
+}
+
+lldb::ValueObjectSP
+ValueObject::GetValueForExpressionPath_Impl(const char* expression_cstr,
+ const char** first_unparsed,
+ ExpressionPathScanEndReason* reason_to_stop,
+ ExpressionPathEndResultType* final_result,
+ const GetValueForExpressionPathOptions& options,
+ ExpressionPathAftermath* what_next)
+{
+ ValueObjectSP root = GetSP();
+
+ if (!root.get())
+ return ValueObjectSP();
+
+ *first_unparsed = expression_cstr;
+
+ while (true)
+ {
+
+ const char* expression_cstr = *first_unparsed; // hide the top level expression_cstr
+
+ lldb::clang_type_t root_clang_type = root->GetClangType();
+
+ if (!expression_cstr || *expression_cstr == '\0')
+ {
+ *reason_to_stop = ValueObject::eEndOfString;
+ return root;
+ }
+
+ switch (*expression_cstr)
+ {
+ case '-':
+ {
+ if (options.m_check_dot_vs_arrow_syntax &&
+ !ClangASTContext::IsPointerType(root_clang_type)) // if you are trying to use -> on a non-pointer and I must catch the error
+ {
+ *first_unparsed = expression_cstr;
+ *reason_to_stop = ValueObject::eArrowInsteadOfDot;
+ *final_result = ValueObject::eInvalid;
+ return ValueObjectSP();
+ }
+ const uint32_t pointer_type_flags = ClangASTContext::GetTypeInfo (root_clang_type, NULL, NULL);
+ if ((pointer_type_flags & ClangASTContext::eTypeIsObjC) && // if yo are trying to extract an ObjC IVar when this is forbidden
+ (pointer_type_flags & ClangASTContext::eTypeIsPointer) &&
+ options.m_no_fragile_ivar)
+ {
+ *first_unparsed = expression_cstr;
+ *reason_to_stop = ValueObject::eFragileIVarNotAllowed;
+ *final_result = ValueObject::eInvalid;
+ return ValueObjectSP();
+ }
+ if (expression_cstr[1] != '>')
+ {
+ *first_unparsed = expression_cstr;
+ *reason_to_stop = ValueObject::eUnexpectedSymbol;
+ *final_result = ValueObject::eInvalid;
+ return ValueObjectSP();
+ }
+ expression_cstr++; // skip the -
+ }
+ case '.': // or fallthrough from ->
+ {
+ if (options.m_check_dot_vs_arrow_syntax && *expression_cstr == '.' &&
+ ClangASTContext::IsPointerType(root_clang_type)) // if you are trying to use . on a pointer and I must catch the error
+ {
+ *first_unparsed = expression_cstr;
+ *reason_to_stop = ValueObject::eDotInsteadOfArrow;
+ *final_result = ValueObject::eInvalid;
+ return ValueObjectSP();
+ }
+ expression_cstr++; // skip .
+ const char *next_separator = strpbrk(expression_cstr+1,"-.[");
+ ConstString child_name;
+ if (!next_separator) // if no other separator just expand this last layer
+ {
+ child_name.SetCString (expression_cstr);
+ root = root->GetChildMemberWithName(child_name, true);
+ if (root.get()) // we know we are done, so just return
+ {
+ *first_unparsed = '\0';
+ *reason_to_stop = ValueObject::eEndOfString;
+ *final_result = ValueObject::ePlain;
+ return root;
+ }
+ else
+ {
+ *first_unparsed = expression_cstr;
+ *reason_to_stop = ValueObject::eNoSuchChild;
+ *final_result = ValueObject::eInvalid;
+ return ValueObjectSP();
+ }
+ }
+ else // other layers do expand
+ {
+ child_name.SetCStringWithLength(expression_cstr, next_separator - expression_cstr);
+ root = root->GetChildMemberWithName(child_name, true);
+ if (root.get()) // store the new root and move on
+ {
+ *first_unparsed = next_separator;
+ *final_result = ValueObject::ePlain;
+ continue;
+ }
+ else
+ {
+ *first_unparsed = expression_cstr;
+ *reason_to_stop = ValueObject::eNoSuchChild;
+ *final_result = ValueObject::eInvalid;
+ return ValueObjectSP();
+ }
+ }
+ break;
+ }
+ case '[':
+ {
+ if (!ClangASTContext::IsArrayType(root_clang_type) && !ClangASTContext::IsPointerType(root_clang_type)) // if this is not a T[] nor a T*
+ {
+ if (!ClangASTContext::IsScalarType(root_clang_type)) // if this is not even a scalar, this syntax is just plain wrong!
+ {
+ *first_unparsed = expression_cstr;
+ *reason_to_stop = ValueObject::eRangeOperatorInvalid;
+ *final_result = ValueObject::eInvalid;
+ return ValueObjectSP();
+ }
+ else if (!options.m_allow_bitfields_syntax) // if this is a scalar, check that we can expand bitfields
+ {
+ *first_unparsed = expression_cstr;
+ *reason_to_stop = ValueObject::eRangeOperatorNotAllowed;
+ *final_result = ValueObject::eInvalid;
+ return ValueObjectSP();
+ }
+ }
+ if (*(expression_cstr+1) == ']') // if this is an unbounded range it only works for arrays
+ {
+ if (!ClangASTContext::IsArrayType(root_clang_type))
+ {
+ *first_unparsed = expression_cstr;
+ *reason_to_stop = ValueObject::eEmptyRangeNotAllowed;
+ *final_result = ValueObject::eInvalid;
+ return ValueObjectSP();
+ }
+ else // even if something follows, we cannot expand unbounded ranges, just let the caller do it
+ {
+ *first_unparsed = expression_cstr+2;
+ *reason_to_stop = ValueObject::eArrayRangeOperatorMet;
+ *final_result = ValueObject::eUnboundedRange;
+ return root;
+ }
+ }
+ const char *separator_position = ::strchr(expression_cstr+1,'-');
+ const char *close_bracket_position = ::strchr(expression_cstr+1,']');
+ if (!close_bracket_position) // if there is no ], this is a syntax error
+ {
+ *first_unparsed = expression_cstr;
+ *reason_to_stop = ValueObject::eUnexpectedSymbol;
+ *final_result = ValueObject::eInvalid;
+ return ValueObjectSP();
+ }
+ if (!separator_position || separator_position > close_bracket_position) // if no separator, this is either [] or [N]
+ {
+ char *end = NULL;
+ unsigned long index = ::strtoul (expression_cstr+1, &end, 0);
+ if (!end || end != close_bracket_position) // if something weird is in our way return an error
+ {
+ *first_unparsed = expression_cstr;
+ *reason_to_stop = ValueObject::eUnexpectedSymbol;
+ *final_result = ValueObject::eInvalid;
+ return ValueObjectSP();
+ }
+ if (end - expression_cstr == 1) // if this is [], only return a valid value for arrays
+ {
+ if (ClangASTContext::IsArrayType(root_clang_type))
+ {
+ *first_unparsed = expression_cstr+2;
+ *reason_to_stop = ValueObject::eArrayRangeOperatorMet;
+ *final_result = ValueObject::eUnboundedRange;
+ return root;
+ }
+ else
+ {
+ *first_unparsed = expression_cstr;
+ *reason_to_stop = ValueObject::eEmptyRangeNotAllowed;
+ *final_result = ValueObject::eInvalid;
+ return ValueObjectSP();
+ }
+ }
+ // from here on we do have a valid index
+ if (ClangASTContext::IsArrayType(root_clang_type))
+ {
+ root = root->GetChildAtIndex(index, true);
+ if (!root.get())
+ {
+ *first_unparsed = expression_cstr;
+ *reason_to_stop = ValueObject::eNoSuchChild;
+ *final_result = ValueObject::eInvalid;
+ return ValueObjectSP();
+ }
+ else
+ {
+ *first_unparsed = end+1; // skip ]
+ *final_result = ValueObject::ePlain;
+ continue;
+ }
+ }
+ else if (ClangASTContext::IsPointerType(root_clang_type))
+ {
+ if (*what_next == ValueObject::eDereference && // if this is a ptr-to-scalar, I am accessing it by index and I would have deref'ed anyway, then do it now and use this as a bitfield
+ ClangASTContext::IsScalarType(clang::QualType::getFromOpaquePtr(root_clang_type).getTypePtr()->getPointeeType().getAsOpaquePtr()))
+ {
+ Error error;
+ root = root->Dereference(error);
+ if (error.Fail() || !root.get())
+ {
+ *first_unparsed = expression_cstr;
+ *reason_to_stop = ValueObject::eDereferencingFailed;
+ *final_result = ValueObject::eInvalid;
+ return ValueObjectSP();
+ }
+ else
+ {
+ *what_next = eNothing;
+ continue;
+ }
+ }
+ else
+ {
+ root = root->GetSyntheticArrayMemberFromPointer(index, true);
+ if (!root.get())
+ {
+ *first_unparsed = expression_cstr;
+ *reason_to_stop = ValueObject::eNoSuchChild;
+ *final_result = ValueObject::eInvalid;
+ return ValueObjectSP();
+ }
+ else
+ {
+ *first_unparsed = end+1; // skip ]
+ *final_result = ValueObject::ePlain;
+ continue;
+ }
+ }
+ }
+ else /*if (ClangASTContext::IsScalarType(root_clang_type))*/
+ {
+ root = root->GetSyntheticBitFieldChild(index, index, true);
+ if (!root.get())
+ {
+ *first_unparsed = expression_cstr;
+ *reason_to_stop = ValueObject::eNoSuchChild;
+ *final_result = ValueObject::eInvalid;
+ return ValueObjectSP();
+ }
+ else // we do not know how to expand members of bitfields, so we just return and let the caller do any further processing
+ {
+ *first_unparsed = end+1; // skip ]
+ *reason_to_stop = ValueObject::eBitfieldRangeOperatorMet;
+ *final_result = ValueObject::eBitfield;
+ return root;
+ }
+ }
+ }
+ else // we have a low and a high index
+ {
+ char *end = NULL;
+ unsigned long index_lower = ::strtoul (expression_cstr+1, &end, 0);
+ if (!end || end != separator_position) // if something weird is in our way return an error
+ {
+ *first_unparsed = expression_cstr;
+ *reason_to_stop = ValueObject::eUnexpectedSymbol;
+ *final_result = ValueObject::eInvalid;
+ return ValueObjectSP();
+ }
+ unsigned long index_higher = ::strtoul (separator_position+1, &end, 0);
+ if (!end || end != close_bracket_position) // if something weird is in our way return an error
+ {
+ *first_unparsed = expression_cstr;
+ *reason_to_stop = ValueObject::eUnexpectedSymbol;
+ *final_result = ValueObject::eInvalid;
+ return ValueObjectSP();
+ }
+ if (index_lower > index_higher) // swap indices if required
+ {
+ unsigned long temp = index_lower;
+ index_lower = index_higher;
+ index_higher = temp;
+ }
+ if (ClangASTContext::IsScalarType(root_clang_type)) // expansion only works for scalars
+ {
+ root = root->GetSyntheticBitFieldChild(index_lower, index_higher, true);
+ if (!root.get())
+ {
+ *first_unparsed = expression_cstr;
+ *reason_to_stop = ValueObject::eNoSuchChild;
+ *final_result = ValueObject::eInvalid;
+ return ValueObjectSP();
+ }
+ else
+ {
+ *first_unparsed = end+1; // skip ]
+ *reason_to_stop = ValueObject::eBitfieldRangeOperatorMet;
+ *final_result = ValueObject::eBitfield;
+ return root;
+ }
+ }
+ else if (ClangASTContext::IsPointerType(root_clang_type) && // if this is a ptr-to-scalar, I am accessing it by index and I would have deref'ed anyway, then do it now and use this as a bitfield
+ *what_next == ValueObject::eDereference &&
+ ClangASTContext::IsScalarType(clang::QualType::getFromOpaquePtr(root_clang_type).getTypePtr()->getPointeeType().getAsOpaquePtr()))
+ {
+ Error error;
+ root = root->Dereference(error);
+ if (error.Fail() || !root.get())
+ {
+ *first_unparsed = expression_cstr;
+ *reason_to_stop = ValueObject::eDereferencingFailed;
+ *final_result = ValueObject::eInvalid;
+ return ValueObjectSP();
+ }
+ else
+ {
+ *what_next = ValueObject::eNothing;
+ continue;
+ }
+ }
+ else
+ {
+ *first_unparsed = expression_cstr;
+ *reason_to_stop = ValueObject::eArrayRangeOperatorMet;
+ *final_result = ValueObject::eBoundedRange;
+ return root;
+ }
+ }
+ break;
+ }
+ default: // some non-separator is in the way
+ {
+ *first_unparsed = expression_cstr;
+ *reason_to_stop = ValueObject::eUnexpectedSymbol;
+ *final_result = ValueObject::eInvalid;
+ return ValueObjectSP();
+ break;
+ }
+ }
+ }
+}
+
void
ValueObject::DumpValueObject
(
OpenPOWER on IntegriCloud