final fix for the global constructors issue
new GetValueForExpressionPath() method in ValueObject to navigate expression paths in a more bitfield vs slices aware way
changes to the varformats.html document (WIP)
git-svn-id: https://llvm.org/svn/llvm-project/llvdb/trunk@134679 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/source/Core/Debugger.cpp b/source/Core/Debugger.cpp
index 763fa25..e7b97a5 100644
--- a/source/Core/Debugger.cpp
+++ b/source/Core/Debugger.cpp
@@ -694,7 +694,7 @@
}
}
-// #define VERBOSE_FORMATPROMPT_OUTPUT
+//#define VERBOSE_FORMATPROMPT_OUTPUT
#ifdef VERBOSE_FORMATPROMPT_OUTPUT
#define IFERROR_PRINT_IT if (error.Fail()) \
{ \
@@ -832,35 +832,41 @@
ExpandIndexedExpression(ValueObject* vobj,
uint32_t index,
StackFrame* frame,
- Error error)
+ bool deref_pointer)
{
- ValueObjectSP item;
- bool is_array = ClangASTContext::IsArrayType(vobj->GetClangType());
-
- if (is_array)
- return vobj->GetChildAtIndex(index, true);
+ const char* ptr_deref_format = "[%d]";
+ std::auto_ptr<char> ptr_deref_buffer(new char[10]);
+ ::sprintf(ptr_deref_buffer.get(), ptr_deref_format, index);
+#ifdef VERBOSE_FORMATPROMPT_OUTPUT
+ printf("name to deref: %s\n",ptr_deref_buffer.get());
+#endif //VERBOSE_FORMATPROMPT_OUTPUT
+ const char* first_unparsed;
+ ValueObject::GetValueForExpressionPathOptions options;
+ ValueObject::ExpressionPathEndResultType final_value_type;
+ ValueObject::ExpressionPathScanEndReason reason_to_stop;
+ ValueObject::ExpressionPathAftermath what_next = (deref_pointer ? ValueObject::eDereference : ValueObject::eNothing);
+ ValueObjectSP item = vobj->GetValueForExpressionPath (ptr_deref_buffer.get(),
+ &first_unparsed,
+ &reason_to_stop,
+ &final_value_type,
+ options,
+ &what_next);
+ if (!item)
+ {
+#ifdef VERBOSE_FORMATPROMPT_OUTPUT
+ printf("ERROR: unparsed portion = %s, why stopping = %d,"
+ " final_value_type %d\n",
+ first_unparsed, reason_to_stop, final_value_type);
+#endif //VERBOSE_FORMATPROMPT_OUTPUT
+ }
+#ifdef VERBOSE_FORMATPROMPT_OUTPUT
else
{
- const char* ptr_deref_format = "%s[%d]";
- char* ptr_deref_buffer = new char[1024];
- StreamString expr_path_string;
- vobj->GetExpressionPath(expr_path_string, true, ValueObject::eHonorPointers);
- const char* expr_path = expr_path_string.GetData();
-#ifdef VERBOSE_FORMATPROMPT_OUTPUT
- printf("name to deref in phase 0: %s\n",expr_path);
-#endif //VERBOSE_FORMATPROMPT_OUTPUT
- ::sprintf(ptr_deref_buffer, ptr_deref_format, expr_path, index);
-#ifdef VERBOSE_FORMATPROMPT_OUTPUT
- printf("name to deref in phase 1: %s\n",ptr_deref_buffer);
-#endif //VERBOSE_FORMATPROMPT_OUTPUT
- lldb::VariableSP var_sp;
- item = frame->GetValueForVariableExpressionPath (ptr_deref_buffer,
- eNoDynamicValues,
- 0,
- var_sp,
- error);
- delete ptr_deref_buffer;
+ printf("ALL RIGHT: unparsed portion = %s, why stopping = %d,"
+ " final_value_type %d\n",
+ first_unparsed, reason_to_stop, final_value_type);
}
+#endif //VERBOSE_FORMATPROMPT_OUTPUT
return item;
}
@@ -954,8 +960,9 @@
const RegisterInfo *reg_info = NULL;
RegisterContext *reg_ctx = NULL;
bool do_deref_pointer = false;
- bool did_deref_pointer = true;
-
+ ValueObject::ExpressionPathScanEndReason reason_to_stop;
+ ValueObject::ExpressionPathEndResultType final_value_type;
+
// Each variable must set success to true below...
bool var_success = false;
switch (var_name_begin[0])
@@ -971,6 +978,10 @@
case 'v':
{
+ ValueObject::ExpressionPathAftermath what_next = (do_deref_pointer ?
+ ValueObject::eDereference : ValueObject::eNothing);
+ ValueObject::GetValueForExpressionPathOptions options;
+ options.DontCheckDotVsArrowSyntax().DoAllowBitfieldSyntax().DoAllowFragileIVar();
ValueObject::ValueObjectRepresentationStyle val_obj_display = ValueObject::eDisplaySummary;
ValueObject* target = NULL;
lldb::Format custom_format = eFormatInvalid;
@@ -980,6 +991,8 @@
int64_t index_lower = -1;
int64_t index_higher = -1;
bool is_array_range = false;
+ const char* first_unparsed;
+
if (!vobj) break;
// simplest case ${var}, just print vobj's value
if (::strncmp (var_name_begin, "var}", strlen("var}")) == 0)
@@ -1025,57 +1038,47 @@
&index_higher);
Error error;
- target = ExpandExpressionPath (vobj,
- exe_ctx->frame,
- &do_deref_pointer,
- var_name_begin,
- var_name_final,
- error).get();
-
- if (error.Fail() || !target)
+
+ std::auto_ptr<char> expr_path(new char[var_name_final-var_name_begin-1]);
+ ::memset(expr_path.get(), 0, var_name_final-var_name_begin-1);
+ memcpy(expr_path.get(), var_name_begin+3,var_name_final-var_name_begin-3);
+
+#ifdef VERBOSE_FORMATPROMPT_OUTPUT
+ printf("symbol to expand: %s\n",expr_path.get());
+#endif //VERBOSE_FORMATPROMPT_OUTPUT
+
+ target = vobj->GetValueForExpressionPath(expr_path.get(),
+ &first_unparsed,
+ &reason_to_stop,
+ &final_value_type,
+ options,
+ &what_next).get();
+
+ if (!target)
{
#ifdef VERBOSE_FORMATPROMPT_OUTPUT
- printf("ERROR: %s\n",error.AsCString("unknown"));
+ printf("ERROR: unparsed portion = %s, why stopping = %d,"
+ " final_value_type %d\n",
+ first_unparsed, reason_to_stop, final_value_type);
#endif //VERBOSE_FORMATPROMPT_OUTPUT
- if (var_name_final_if_array_range)
- {
- target = ExpandExpressionPath(vobj,
- exe_ctx->frame,
- &do_deref_pointer,
- var_name_begin,
- var_name_final_if_array_range,
- error).get();
- }
-
- if (var_name_final_if_array_range && (error.Fail() || !target))
- {
- bool fake_do_deref = false;
- target = ExpandExpressionPath(vobj,
- exe_ctx->frame,
- &fake_do_deref,
- var_name_begin,
- var_name_final_if_array_range,
- error).get();
-
- did_deref_pointer = false;
-
- if (target && ClangASTContext::IsArrayType(target->GetClangType()))
- error.Clear();
- else
- error.SetErrorString("error in expression");
- }
-
- IFERROR_PRINT_IT
- else
- is_array_range = true;
+ break;
}
-
- if (did_deref_pointer)
- do_deref_pointer = false; // I have honored the request to deref
-
+#ifdef VERBOSE_FORMATPROMPT_OUTPUT
+ else
+ {
+ printf("ALL RIGHT: unparsed portion = %s, why stopping = %d,"
+ " final_value_type %d\n",
+ first_unparsed, reason_to_stop, final_value_type);
+ }
+#endif //VERBOSE_FORMATPROMPT_OUTPUT
}
else
break;
+
+ is_array_range = (final_value_type == ValueObject::eBoundedRange ||
+ final_value_type == ValueObject::eUnboundedRange);
+
+ do_deref_pointer = (what_next == ValueObject::eDereference);
if (do_deref_pointer && !is_array_range)
{
@@ -1092,30 +1095,22 @@
var_success = target->DumpPrintableRepresentation(s,val_obj_display, custom_format);
else
{
- bool is_array = ClangASTContext::IsArrayType(vobj->GetClangType());
- bool is_pointer = ClangASTContext::IsPointerType(vobj->GetClangType());
+ bool is_array = ClangASTContext::IsArrayType(target->GetClangType());
+ bool is_pointer = ClangASTContext::IsPointerType(target->GetClangType());
if (!is_array && !is_pointer)
break;
- char* special_directions = NULL;
+ const char* special_directions = NULL;
+ StreamString special_directions_writer;
if (close_bracket_position && (var_name_end-close_bracket_position > 1))
{
- int base_len = var_name_end-close_bracket_position;
- special_directions = new char[7+base_len];
- int star_offset = (do_deref_pointer ? 1 : 0);
- special_directions[0] = '$';
- special_directions[1] = '{';
- if (do_deref_pointer)
- special_directions[2] = '*';
- special_directions[2+star_offset] = 'v';
- special_directions[3+star_offset] = 'a';
- special_directions[4+star_offset] = 'r';
- memcpy(special_directions+5+star_offset, close_bracket_position+1, base_len);
- special_directions[base_len+5+star_offset] = '\0';
-#ifdef VERBOSE_FORMATPROMPT_OUTPUT
- printf("%s\n",special_directions);
-#endif //VERBOSE_FORMATPROMPT_OUTPUT
+ ConstString additional_data;
+ additional_data.SetCStringWithLength(close_bracket_position+1, var_name_end-close_bracket_position-1);
+ special_directions_writer.Printf("${%svar%s}",
+ do_deref_pointer ? "*" : "",
+ additional_data.GetCString());
+ special_directions = special_directions_writer.GetData();
}
// let us display items index_lower thru index_higher of this array
@@ -1127,13 +1122,24 @@
for (;index_lower<=index_higher;index_lower++)
{
- Error error;
- ValueObject* item = ExpandIndexedExpression(vobj,
+ ValueObject* item = ExpandIndexedExpression(target,
index_lower,
exe_ctx->frame,
- error).get();
+ false).get();
- IFERROR_PRINT_IT
+ if (!item)
+ {
+#ifdef VERBOSE_FORMATPROMPT_OUTPUT
+ printf("ERROR\n");
+#endif //VERBOSE_FORMATPROMPT_OUTPUT
+ }
+#ifdef VERBOSE_FORMATPROMPT_OUTPUT
+ else
+ {
+ printf("special_directions: %s\n",special_directions);
+ }
+#endif //VERBOSE_FORMATPROMPT_OUTPUT
+
if (!special_directions)
var_success &= item->DumpPrintableRepresentation(s,val_obj_display, custom_format);
else
diff --git a/source/Core/ValueObject.cpp b/source/Core/ValueObject.cpp
index 918be09..1c8a705 100644
--- a/source/Core/ValueObject.cpp
+++ b/source/Core/ValueObject.cpp
@@ -1366,6 +1366,412 @@
}
}
+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
(
diff --git a/source/Interpreter/CommandObject.cpp b/source/Interpreter/CommandObject.cpp
index 95c0ad6..4449007 100644
--- a/source/Interpreter/CommandObject.cpp
+++ b/source/Interpreter/CommandObject.cpp
@@ -469,9 +469,9 @@
StreamString name_str;
name_str.Printf ("<%s>", entry->arg_name);
- if (entry->help_function.help_callback)
+ if (entry->help_function)
{
- const char* help_text = (*entry->help_function.help_callback)();
+ const char* help_text = entry->help_function();
if (!entry->help_function.self_formatting)
{
interpreter.OutputFormattedHelpText (str, name_str.GetData(), "--", help_text,