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,