diff --git a/lldb/source/Interpreter/OptionValueDictionary.cpp b/lldb/source/Interpreter/OptionValueDictionary.cpp
index 24eeec3..cf8715e 100644
--- a/lldb/source/Interpreter/OptionValueDictionary.cpp
+++ b/lldb/source/Interpreter/OptionValueDictionary.cpp
@@ -22,423 +22,371 @@
 using namespace lldb;
 using namespace lldb_private;
 
-void
-OptionValueDictionary::DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask)
-{
-    const Type dict_type = ConvertTypeMaskToType (m_type_mask);
-    if (dump_mask & eDumpOptionType)
-    {
-        if (m_type_mask != eTypeInvalid)
-            strm.Printf ("(%s of %ss)", GetTypeAsCString(), GetBuiltinTypeAsCString(dict_type));
-        else
-            strm.Printf ("(%s)", GetTypeAsCString());
-    }
-    if (dump_mask & eDumpOptionValue)
-    {
-        if (dump_mask & eDumpOptionType)
-            strm.PutCString (" =");
-
-        collection::iterator pos, end = m_values.end();
-
-        strm.IndentMore();
-        
-        for (pos = m_values.begin(); pos != end; ++pos)
-        {
-            OptionValue *option_value = pos->second.get();
-            strm.EOL();
-            strm.Indent(pos->first.GetCString());
-            
-            const uint32_t extra_dump_options = m_raw_value_dump ? eDumpOptionRaw : 0;
-            switch (dict_type)
-            {
-                default:
-                case eTypeArray:
-                case eTypeDictionary:
-                case eTypeProperties:
-                case eTypeFileSpecList:
-                case eTypePathMap:
-                    strm.PutChar (' ');
-                    option_value->DumpValue(exe_ctx, strm, dump_mask | extra_dump_options);
-                    break;
-
-                case eTypeBoolean:
-                case eTypeChar:
-                case eTypeEnum:
-                case eTypeFileSpec:
-                case eTypeFormat:
-                case eTypeSInt64:
-                case eTypeString:
-                case eTypeUInt64:
-                case eTypeUUID:
-                    // No need to show the type for dictionaries of simple items
-                    strm.PutCString("=");
-                    option_value->DumpValue(exe_ctx, strm, (dump_mask & (~eDumpOptionType)) | extra_dump_options);
-                    break;
-            }
-        }
-        strm.IndentLess();
-    }
-
-}
-
-size_t
-OptionValueDictionary::GetArgs (Args &args) const
-{
-    args.Clear();
-    collection::const_iterator pos, end = m_values.end();
-    for (pos = m_values.begin(); pos != end; ++pos)
-    {
-        StreamString strm;
-        strm.Printf("%s=", pos->first.GetCString());
-        pos->second->DumpValue(nullptr, strm, eDumpOptionValue|eDumpOptionRaw);
-        args.AppendArgument(strm.GetString().c_str());
-    }
-    return args.GetArgumentCount();
-}
-
-Error
-OptionValueDictionary::SetArgs (const Args &args, VarSetOperationType op)
-{
-    Error error;
-    const size_t argc = args.GetArgumentCount();
-    switch (op)
-    {
-    case eVarSetOperationClear:
-        Clear();
-        break;
-        
-    case eVarSetOperationAppend:
-    case eVarSetOperationReplace:
-    case eVarSetOperationAssign:
-        if (argc > 0)
-        {
-            for (size_t i=0; i<argc; ++i)
-            {
-                llvm::StringRef key_and_value(args.GetArgumentAtIndex(i));
-                if (!key_and_value.empty())
-                {
-                    if (key_and_value.find('=') == llvm::StringRef::npos)
-                    {
-                        error.SetErrorString("assign operation takes one or more key=value arguments");
-                        return error;
-                    }
-
-                    std::pair<llvm::StringRef, llvm::StringRef> kvp(key_and_value.split('='));
-                    llvm::StringRef key = kvp.first;
-                    bool key_valid = false;
-                    if (!key.empty())
-                    {
-                        if (key.front() == '[')
-                        {
-                            // Key name starts with '[', so the key value must be in single or double quotes like:
-                            // ['<key>']
-                            // ["<key>"]
-                            if ((key.size() > 2) && (key.back() == ']'))
-                            {
-                                // Strip leading '[' and trailing ']'
-                                key = key.substr(1, key.size()-2);
-                                const char quote_char = key.front();
-                                if ((quote_char == '\'') || (quote_char == '"'))
-                                {
-                                    if ((key.size() > 2) && (key.back() == quote_char))
-                                    {
-                                        // Strip the quotes
-                                        key = key.substr(1, key.size()-2);
-                                        key_valid = true;
-                                    }
-                                }
-                                else
-                                {
-                                    // square brackets, no quotes
-                                    key_valid = true;
-                                }
-                            }
-                        }
-                        else
-                        {
-                            // No square brackets or quotes
-                            key_valid = true;
-                        }
-                    }
-                    if (!key_valid)
-                    {
-                        error.SetErrorStringWithFormat("invalid key \"%s\", the key must be a bare string or surrounded by brackets with optional quotes: [<key>] or ['<key>'] or [\"<key>\"]", kvp.first.str().c_str());
-                        return error;
-                    }
-
-                    lldb::OptionValueSP value_sp (CreateValueFromCStringForTypeMask (kvp.second.data(),
-                                                                                     m_type_mask,
-                                                                                     error));
-                    if (value_sp)
-                    {
-                        if (error.Fail())
-                            return error;
-                        m_value_was_set = true;
-                        SetValueForKey (ConstString(key), value_sp, true);
-                    }
-                    else
-                    {
-                        error.SetErrorString("dictionaries that can contain multiple types must subclass OptionValueArray");
-                    }
-                }
-                else
-                {
-                    error.SetErrorString("empty argument");
-                }
-            }
-        }
-        else
-        {
-            error.SetErrorString("assign operation takes one or more key=value arguments");
-        }
-        break;
-        
-    case eVarSetOperationRemove:
-        if (argc > 0)
-        {
-            for (size_t i=0; i<argc; ++i)
-            {
-                ConstString key(args.GetArgumentAtIndex(i));
-                if (!DeleteValueForKey(key))
-                {
-                    error.SetErrorStringWithFormat("no value found named '%s', aborting remove operation", key.GetCString());
-                    break;
-                }
-            }
-        }
-        else
-        {
-            error.SetErrorString("remove operation takes one or more key arguments");
-        }
-        break;
-        
-    case eVarSetOperationInsertBefore:
-    case eVarSetOperationInsertAfter:
-    case eVarSetOperationInvalid:
-        error = OptionValue::SetValueFromString (llvm::StringRef(), op);
-        break;
-    }
-    return error;
-}
-
-Error
-OptionValueDictionary::SetValueFromString (llvm::StringRef value, VarSetOperationType op)
-{
-    Args args(value.str().c_str());
-    Error error = SetArgs (args, op);
-    if (error.Success())
-        NotifyValueChanged();
-    return error;
-}
-
-lldb::OptionValueSP
-OptionValueDictionary::GetSubValue (const ExecutionContext *exe_ctx, const char *name, bool will_modify, Error &error) const
-{
-    lldb::OptionValueSP value_sp;
-
-    if (name && name[0])
-    {
-        const char *sub_name = nullptr;
-        ConstString key;
-        const char *open_bracket = ::strchr (name, '[');
-
-        if (open_bracket)
-        {
-            const char *key_start = open_bracket + 1;
-            const char *key_end = nullptr;
-            switch (open_bracket[1])
-            {
-                case '\'':
-                    ++key_start;
-                    key_end = strchr(key_start, '\'');
-                    if (key_end)
-                    {
-                        if (key_end[1] == ']')
-                        {
-                            if (key_end[2])
-                                sub_name = key_end + 2;
-                        }
-                        else
-                        {
-                            error.SetErrorStringWithFormat ("invalid value path '%s', single quoted key names must be formatted as ['<key>'] where <key> is a string that doesn't contain quotes", name);
-                            return value_sp;
-                        }
-                    }
-                    else
-                    {
-                        error.SetErrorString ("missing '] key name terminator, key name started with ['");
-                        return value_sp;
-                    }
-                    break;
-                case '"':
-                    ++key_start;
-                    key_end = strchr(key_start, '"');
-                    if (key_end)
-                    {
-                        if (key_end[1] == ']')
-                        {
-                            if (key_end[2])
-                                sub_name = key_end + 2;
-                            break;
-                        }
-                        error.SetErrorStringWithFormat ("invalid value path '%s', double quoted key names must be formatted as [\"<key>\"] where <key> is a string that doesn't contain quotes", name);
-                        return value_sp;
-                    }
-                    else
-                    {
-                        error.SetErrorString ("missing \"] key name terminator, key name started with [\"");
-                        return value_sp;
-                    }
-                    break;
-
-                default:
-                    key_end = strchr(key_start, ']');
-                    if (key_end)
-                    {
-                        if (key_end[1])
-                            sub_name = key_end + 1;
-                    }
-                    else
-                    {
-                        error.SetErrorString ("missing ] key name terminator, key name started with [");
-                        return value_sp;
-                    }
-                    break;
-            }
-            
-            if (key_start && key_end)
-            {
-                key.SetCStringWithLength (key_start, key_end - key_start);
-        
-                value_sp = GetValueForKey (key);
-                if (value_sp)
-                {
-                    if (sub_name)
-                        return value_sp->GetSubValue (exe_ctx, sub_name, will_modify, error);
-                }
-                else
-                {
-                    error.SetErrorStringWithFormat("dictionary does not contain a value for the key name '%s'", key.GetCString());
-                }
-            }
-        }
-        if (!value_sp && error.AsCString() == nullptr)
-        {
-            error.SetErrorStringWithFormat ("invalid value path '%s', %s values only support '[<key>]' subvalues where <key> a string value optionally delimited by single or double quotes",
-                                            name,
-                                            GetTypeAsCString());
-        }
-    }
-    return value_sp;
-}
-
-Error
-OptionValueDictionary::SetSubValue (const ExecutionContext *exe_ctx, VarSetOperationType op, const char *name, const char *value)
-{
-    Error error;
-    const bool will_modify = true;
-    lldb::OptionValueSP value_sp (GetSubValue (exe_ctx, name, will_modify, error));
-    if (value_sp)
-        error = value_sp->SetValueFromString(value, op);
+void OptionValueDictionary::DumpValue(const ExecutionContext *exe_ctx,
+                                      Stream &strm, uint32_t dump_mask) {
+  const Type dict_type = ConvertTypeMaskToType(m_type_mask);
+  if (dump_mask & eDumpOptionType) {
+    if (m_type_mask != eTypeInvalid)
+      strm.Printf("(%s of %ss)", GetTypeAsCString(),
+                  GetBuiltinTypeAsCString(dict_type));
     else
-    {
-        if (error.AsCString() == nullptr)
-            error.SetErrorStringWithFormat("invalid value path '%s'", name);
+      strm.Printf("(%s)", GetTypeAsCString());
+  }
+  if (dump_mask & eDumpOptionValue) {
+    if (dump_mask & eDumpOptionType)
+      strm.PutCString(" =");
+
+    collection::iterator pos, end = m_values.end();
+
+    strm.IndentMore();
+
+    for (pos = m_values.begin(); pos != end; ++pos) {
+      OptionValue *option_value = pos->second.get();
+      strm.EOL();
+      strm.Indent(pos->first.GetCString());
+
+      const uint32_t extra_dump_options = m_raw_value_dump ? eDumpOptionRaw : 0;
+      switch (dict_type) {
+      default:
+      case eTypeArray:
+      case eTypeDictionary:
+      case eTypeProperties:
+      case eTypeFileSpecList:
+      case eTypePathMap:
+        strm.PutChar(' ');
+        option_value->DumpValue(exe_ctx, strm, dump_mask | extra_dump_options);
+        break;
+
+      case eTypeBoolean:
+      case eTypeChar:
+      case eTypeEnum:
+      case eTypeFileSpec:
+      case eTypeFormat:
+      case eTypeSInt64:
+      case eTypeString:
+      case eTypeUInt64:
+      case eTypeUUID:
+        // No need to show the type for dictionaries of simple items
+        strm.PutCString("=");
+        option_value->DumpValue(exe_ctx, strm,
+                                (dump_mask & (~eDumpOptionType)) |
+                                    extra_dump_options);
+        break;
+      }
     }
-    return error;
+    strm.IndentLess();
+  }
 }
 
+size_t OptionValueDictionary::GetArgs(Args &args) const {
+  args.Clear();
+  collection::const_iterator pos, end = m_values.end();
+  for (pos = m_values.begin(); pos != end; ++pos) {
+    StreamString strm;
+    strm.Printf("%s=", pos->first.GetCString());
+    pos->second->DumpValue(nullptr, strm, eDumpOptionValue | eDumpOptionRaw);
+    args.AppendArgument(strm.GetString().c_str());
+  }
+  return args.GetArgumentCount();
+}
+
+Error OptionValueDictionary::SetArgs(const Args &args, VarSetOperationType op) {
+  Error error;
+  const size_t argc = args.GetArgumentCount();
+  switch (op) {
+  case eVarSetOperationClear:
+    Clear();
+    break;
+
+  case eVarSetOperationAppend:
+  case eVarSetOperationReplace:
+  case eVarSetOperationAssign:
+    if (argc > 0) {
+      for (size_t i = 0; i < argc; ++i) {
+        llvm::StringRef key_and_value(args.GetArgumentAtIndex(i));
+        if (!key_and_value.empty()) {
+          if (key_and_value.find('=') == llvm::StringRef::npos) {
+            error.SetErrorString(
+                "assign operation takes one or more key=value arguments");
+            return error;
+          }
+
+          std::pair<llvm::StringRef, llvm::StringRef> kvp(
+              key_and_value.split('='));
+          llvm::StringRef key = kvp.first;
+          bool key_valid = false;
+          if (!key.empty()) {
+            if (key.front() == '[') {
+              // Key name starts with '[', so the key value must be in single or
+              // double quotes like:
+              // ['<key>']
+              // ["<key>"]
+              if ((key.size() > 2) && (key.back() == ']')) {
+                // Strip leading '[' and trailing ']'
+                key = key.substr(1, key.size() - 2);
+                const char quote_char = key.front();
+                if ((quote_char == '\'') || (quote_char == '"')) {
+                  if ((key.size() > 2) && (key.back() == quote_char)) {
+                    // Strip the quotes
+                    key = key.substr(1, key.size() - 2);
+                    key_valid = true;
+                  }
+                } else {
+                  // square brackets, no quotes
+                  key_valid = true;
+                }
+              }
+            } else {
+              // No square brackets or quotes
+              key_valid = true;
+            }
+          }
+          if (!key_valid) {
+            error.SetErrorStringWithFormat(
+                "invalid key \"%s\", the key must be a bare string or "
+                "surrounded by brackets with optional quotes: [<key>] or "
+                "['<key>'] or [\"<key>\"]",
+                kvp.first.str().c_str());
+            return error;
+          }
+
+          lldb::OptionValueSP value_sp(CreateValueFromCStringForTypeMask(
+              kvp.second.data(), m_type_mask, error));
+          if (value_sp) {
+            if (error.Fail())
+              return error;
+            m_value_was_set = true;
+            SetValueForKey(ConstString(key), value_sp, true);
+          } else {
+            error.SetErrorString("dictionaries that can contain multiple types "
+                                 "must subclass OptionValueArray");
+          }
+        } else {
+          error.SetErrorString("empty argument");
+        }
+      }
+    } else {
+      error.SetErrorString(
+          "assign operation takes one or more key=value arguments");
+    }
+    break;
+
+  case eVarSetOperationRemove:
+    if (argc > 0) {
+      for (size_t i = 0; i < argc; ++i) {
+        ConstString key(args.GetArgumentAtIndex(i));
+        if (!DeleteValueForKey(key)) {
+          error.SetErrorStringWithFormat(
+              "no value found named '%s', aborting remove operation",
+              key.GetCString());
+          break;
+        }
+      }
+    } else {
+      error.SetErrorString("remove operation takes one or more key arguments");
+    }
+    break;
+
+  case eVarSetOperationInsertBefore:
+  case eVarSetOperationInsertAfter:
+  case eVarSetOperationInvalid:
+    error = OptionValue::SetValueFromString(llvm::StringRef(), op);
+    break;
+  }
+  return error;
+}
+
+Error OptionValueDictionary::SetValueFromString(llvm::StringRef value,
+                                                VarSetOperationType op) {
+  Args args(value.str().c_str());
+  Error error = SetArgs(args, op);
+  if (error.Success())
+    NotifyValueChanged();
+  return error;
+}
 
 lldb::OptionValueSP
-OptionValueDictionary::GetValueForKey (const ConstString &key) const
-{
-    lldb::OptionValueSP value_sp;
-    collection::const_iterator pos = m_values.find (key);
-    if (pos != m_values.end())
-        value_sp = pos->second;
-    return value_sp;
+OptionValueDictionary::GetSubValue(const ExecutionContext *exe_ctx,
+                                   const char *name, bool will_modify,
+                                   Error &error) const {
+  lldb::OptionValueSP value_sp;
+
+  if (name && name[0]) {
+    const char *sub_name = nullptr;
+    ConstString key;
+    const char *open_bracket = ::strchr(name, '[');
+
+    if (open_bracket) {
+      const char *key_start = open_bracket + 1;
+      const char *key_end = nullptr;
+      switch (open_bracket[1]) {
+      case '\'':
+        ++key_start;
+        key_end = strchr(key_start, '\'');
+        if (key_end) {
+          if (key_end[1] == ']') {
+            if (key_end[2])
+              sub_name = key_end + 2;
+          } else {
+            error.SetErrorStringWithFormat("invalid value path '%s', single "
+                                           "quoted key names must be formatted "
+                                           "as ['<key>'] where <key> is a "
+                                           "string that doesn't contain quotes",
+                                           name);
+            return value_sp;
+          }
+        } else {
+          error.SetErrorString(
+              "missing '] key name terminator, key name started with ['");
+          return value_sp;
+        }
+        break;
+      case '"':
+        ++key_start;
+        key_end = strchr(key_start, '"');
+        if (key_end) {
+          if (key_end[1] == ']') {
+            if (key_end[2])
+              sub_name = key_end + 2;
+            break;
+          }
+          error.SetErrorStringWithFormat("invalid value path '%s', double "
+                                         "quoted key names must be formatted "
+                                         "as [\"<key>\"] where <key> is a "
+                                         "string that doesn't contain quotes",
+                                         name);
+          return value_sp;
+        } else {
+          error.SetErrorString(
+              "missing \"] key name terminator, key name started with [\"");
+          return value_sp;
+        }
+        break;
+
+      default:
+        key_end = strchr(key_start, ']');
+        if (key_end) {
+          if (key_end[1])
+            sub_name = key_end + 1;
+        } else {
+          error.SetErrorString(
+              "missing ] key name terminator, key name started with [");
+          return value_sp;
+        }
+        break;
+      }
+
+      if (key_start && key_end) {
+        key.SetCStringWithLength(key_start, key_end - key_start);
+
+        value_sp = GetValueForKey(key);
+        if (value_sp) {
+          if (sub_name)
+            return value_sp->GetSubValue(exe_ctx, sub_name, will_modify, error);
+        } else {
+          error.SetErrorStringWithFormat(
+              "dictionary does not contain a value for the key name '%s'",
+              key.GetCString());
+        }
+      }
+    }
+    if (!value_sp && error.AsCString() == nullptr) {
+      error.SetErrorStringWithFormat("invalid value path '%s', %s values only "
+                                     "support '[<key>]' subvalues where <key> "
+                                     "a string value optionally delimited by "
+                                     "single or double quotes",
+                                     name, GetTypeAsCString());
+    }
+  }
+  return value_sp;
+}
+
+Error OptionValueDictionary::SetSubValue(const ExecutionContext *exe_ctx,
+                                         VarSetOperationType op,
+                                         const char *name, const char *value) {
+  Error error;
+  const bool will_modify = true;
+  lldb::OptionValueSP value_sp(GetSubValue(exe_ctx, name, will_modify, error));
+  if (value_sp)
+    error = value_sp->SetValueFromString(value, op);
+  else {
+    if (error.AsCString() == nullptr)
+      error.SetErrorStringWithFormat("invalid value path '%s'", name);
+  }
+  return error;
+}
+
+lldb::OptionValueSP
+OptionValueDictionary::GetValueForKey(const ConstString &key) const {
+  lldb::OptionValueSP value_sp;
+  collection::const_iterator pos = m_values.find(key);
+  if (pos != m_values.end())
+    value_sp = pos->second;
+  return value_sp;
 }
 
 const char *
-OptionValueDictionary::GetStringValueForKey (const ConstString &key)
-{
-    collection::const_iterator pos = m_values.find (key);
-    if (pos != m_values.end())
-    {
-        OptionValueString *string_value = pos->second->GetAsString();
-        if (string_value)
-            return string_value->GetCurrentValue();
-    }
-    return nullptr;
+OptionValueDictionary::GetStringValueForKey(const ConstString &key) {
+  collection::const_iterator pos = m_values.find(key);
+  if (pos != m_values.end()) {
+    OptionValueString *string_value = pos->second->GetAsString();
+    if (string_value)
+      return string_value->GetCurrentValue();
+  }
+  return nullptr;
 }
 
-
-bool
-OptionValueDictionary::SetStringValueForKey (const ConstString &key, 
-                                             const char *value, 
-                                             bool can_replace)
-{
-    collection::const_iterator pos = m_values.find (key);
-    if (pos != m_values.end())
-    {
-        if (!can_replace)
-            return false;
-        if (pos->second->GetType() == OptionValue::eTypeString)
-        {
-            pos->second->SetValueFromString(value);
-            return true;
-        }
+bool OptionValueDictionary::SetStringValueForKey(const ConstString &key,
+                                                 const char *value,
+                                                 bool can_replace) {
+  collection::const_iterator pos = m_values.find(key);
+  if (pos != m_values.end()) {
+    if (!can_replace)
+      return false;
+    if (pos->second->GetType() == OptionValue::eTypeString) {
+      pos->second->SetValueFromString(value);
+      return true;
     }
-    m_values[key] = OptionValueSP (new OptionValueString (value));
+  }
+  m_values[key] = OptionValueSP(new OptionValueString(value));
+  return true;
+}
+
+bool OptionValueDictionary::SetValueForKey(const ConstString &key,
+                                           const lldb::OptionValueSP &value_sp,
+                                           bool can_replace) {
+  // Make sure the value_sp object is allowed to contain
+  // values of the type passed in...
+  if (value_sp && (m_type_mask & value_sp->GetTypeAsMask())) {
+    if (!can_replace) {
+      collection::const_iterator pos = m_values.find(key);
+      if (pos != m_values.end())
+        return false;
+    }
+    m_values[key] = value_sp;
     return true;
-
+  }
+  return false;
 }
 
-bool
-OptionValueDictionary::SetValueForKey (const ConstString &key, 
-                                       const lldb::OptionValueSP &value_sp, 
-                                       bool can_replace)
-{
-    // Make sure the value_sp object is allowed to contain
-    // values of the type passed in...
-    if (value_sp && (m_type_mask & value_sp->GetTypeAsMask()))
-    {
-        if (!can_replace)
-        {
-            collection::const_iterator pos = m_values.find (key);
-            if (pos != m_values.end())
-                return false;
-        }
-        m_values[key] = value_sp;
-        return true;
-    }
-    return false;
+bool OptionValueDictionary::DeleteValueForKey(const ConstString &key) {
+  collection::iterator pos = m_values.find(key);
+  if (pos != m_values.end()) {
+    m_values.erase(pos);
+    return true;
+  }
+  return false;
 }
 
-bool
-OptionValueDictionary::DeleteValueForKey (const ConstString &key)
-{
-    collection::iterator pos = m_values.find (key);
-    if (pos != m_values.end())
-    {
-        m_values.erase(pos);
-        return true;
-    }
-    return false;
+lldb::OptionValueSP OptionValueDictionary::DeepCopy() const {
+  OptionValueDictionary *copied_dict =
+      new OptionValueDictionary(m_type_mask, m_raw_value_dump);
+  lldb::OptionValueSP copied_value_sp(copied_dict);
+  collection::const_iterator pos, end = m_values.end();
+  for (pos = m_values.begin(); pos != end; ++pos) {
+    StreamString strm;
+    strm.Printf("%s=", pos->first.GetCString());
+    copied_dict->SetValueForKey(pos->first, pos->second->DeepCopy(), true);
+  }
+  return copied_value_sp;
 }
-
-lldb::OptionValueSP
-OptionValueDictionary::DeepCopy () const
-{
-    OptionValueDictionary *copied_dict = new OptionValueDictionary (m_type_mask, m_raw_value_dump);
-    lldb::OptionValueSP copied_value_sp(copied_dict);
-    collection::const_iterator pos, end = m_values.end();
-    for (pos = m_values.begin(); pos != end; ++pos)
-    {
-        StreamString strm;
-        strm.Printf("%s=", pos->first.GetCString());
-        copied_dict->SetValueForKey (pos->first, pos->second->DeepCopy(), true);
-    }
-    return copied_value_sp;
-}
-
