tfiala created this revision.
tfiala added reviewers: clayborg, labath, ovyalov.
tfiala added a subscriber: lldb-commits.

This change implements dumping the executable, triple,
args and environment when using ProcessInfo::Dump().

It also tweaks the way Args::Dump() works so that it prints
a configurable label rather than argv[{index}]={value}.  By
default it behaves the same, but if the Dump() method with
the additional arg is provided, it can be overridden.  The
environment variables dumped as part of ProcessInfo::Dump()
make use of that.

lldb-server has been modified to dump the gdb-remote stub's
ProcessInfo before launching if the "gdb-remote process" channel
is logged.

http://reviews.llvm.org/D20722

Files:
  include/lldb/Breakpoint/BreakpointLocationCollection.h
  include/lldb/Core/Logging.h
  source/Breakpoint/BreakpointLocationCollection.cpp
  source/Core/Logging.cpp
  source/Core/Mangled.cpp
  
source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp
  
source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.h
  source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp
  source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
  source/Symbol/ClangASTContext.cpp
  source/Target/ProcessInfo.cpp

Index: source/Target/ProcessInfo.cpp
===================================================================
--- source/Target/ProcessInfo.cpp
+++ source/Target/ProcessInfo.cpp
@@ -69,19 +69,15 @@
 void
 ProcessInfo::Dump (Stream &s, Platform *platform) const
 {
-    // Print executable name.
-    s << "ProcessInfo\nExecutable:\n\t" << GetName() << "\n\n";
-
-    // Triple.
+    s << "Executable: " << GetName() << "\n";
     s << "Triple: ";
     m_arch.DumpTriple(s);
+    s << "\n";
 
-    // Print arguments
-    s << "\nArguments:\n";
+    s << "Arguments:\n";
     m_arguments.Dump(&s);
 
-    // Print environment.
-    s << "\nEnvironment:\n";
+    s << "Environment:\n";
     m_environment.Dump(&s, "env");
 }
 
Index: source/Symbol/ClangASTContext.cpp
===================================================================
--- source/Symbol/ClangASTContext.cpp
+++ source/Symbol/ClangASTContext.cpp
@@ -2013,10 +2013,33 @@
                                      bool is_variadic, 
                                      unsigned type_quals)
 {
-    assert (ast != nullptr);
+    if (ast == nullptr)
+        return CompilerType(); // invalid AST
+
+    if (!result_type || !ClangUtil::IsClangType(result_type))
+        return CompilerType(); // invalid return type
+
     std::vector<QualType> qual_type_args;
+    if (num_args > 0 && args == nullptr)
+        return CompilerType(); // invalid argument array passed in
+
+    // Verify that all arguments are valid and the right type
     for (unsigned i=0; i<num_args; ++i)
-        qual_type_args.push_back(ClangUtil::GetQualType(args[i]));
+    {
+        if (args[i])
+        {
+            // Make sure we have a clang type in args[i] and not a type from another
+            // language whose name might match
+            const bool is_clang_type = ClangUtil::IsClangType(args[i]);
+            lldbassert(is_clang_type);
+            if (is_clang_type)
+                qual_type_args.push_back(ClangUtil::GetQualType(args[i]));
+            else
+                return CompilerType(); //  invalid argument type (must be a clang type)
+        }
+        else
+            return CompilerType(); // invalid argument type (empty)
+    }
 
     // TODO: Detect calling convention in DWARF?
     FunctionProtoType::ExtProtoInfo proto_info;
@@ -8594,18 +8617,28 @@
     clang::QualType qual_type(ClangUtil::GetQualType(type));
     if (!qual_type.isNull())
     {
-        clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl();
-        
-        if (cxx_record_decl)
+        // Make sure we use the same methodology as ClangASTContext::StartTagDeclarationDefinition()
+        // as to how we start/end the definition. Previously we were calling 
+        const clang::TagType *tag_type = qual_type->getAs<clang::TagType>();
+        if (tag_type)
         {
-            if (!cxx_record_decl->isCompleteDefinition())
-                cxx_record_decl->completeDefinition();
-            cxx_record_decl->setHasLoadedFieldsFromExternalStorage(true);
-            cxx_record_decl->setHasExternalLexicalStorage (false);
-            cxx_record_decl->setHasExternalVisibleStorage (false);
-            return true;
+            clang::TagDecl *tag_decl = tag_type->getDecl();
+            if (tag_decl)
+            {
+                clang::CXXRecordDecl *cxx_record_decl = llvm::dyn_cast_or_null<clang::CXXRecordDecl>(tag_decl);
+                
+                if (cxx_record_decl)
+                {
+                    if (!cxx_record_decl->isCompleteDefinition())
+                        cxx_record_decl->completeDefinition();
+                    cxx_record_decl->setHasLoadedFieldsFromExternalStorage(true);
+                    cxx_record_decl->setHasExternalLexicalStorage (false);
+                    cxx_record_decl->setHasExternalVisibleStorage (false);
+                    return true;
+                }
+            }
         }
-        
+
         const clang::EnumType *enutype = qual_type->getAs<clang::EnumType>();
         
         if (enutype)
Index: source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
===================================================================
--- source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
+++ source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
@@ -896,8 +896,16 @@
                         if (die.HasChildren() == false)
                         {
                             // No children for this struct/union/class, lets finish it
-                            ClangASTContext::StartTagDeclarationDefinition (clang_type);
-                            ClangASTContext::CompleteTagDeclarationDefinition (clang_type);
+                            if (ClangASTContext::StartTagDeclarationDefinition (clang_type))
+                            {
+                                ClangASTContext::CompleteTagDeclarationDefinition (clang_type);
+                            }
+                            else
+                            {
+                                dwarf->GetObjectFile()->GetModule()->ReportError("DWARF DIE at 0x%8.8x named \"%s\" was not able to start its definition.\nPlease file a bug and attach the file at the start of this error message",
+                                                                                 die.GetOffset(),
+                                                                                 type_name_cstr);
+                            }
 
                             if (tag == DW_TAG_structure_type) // this only applies in C
                             {
@@ -1085,15 +1093,23 @@
                                                  clang_type,
                                                  Type::eResolveStateForward));
 
-                        ClangASTContext::StartTagDeclarationDefinition (clang_type);
-                        if (die.HasChildren())
+                        if (ClangASTContext::StartTagDeclarationDefinition (clang_type))
                         {
-                            SymbolContext cu_sc(die.GetLLDBCompileUnit());
-                            bool is_signed = false;
-                            enumerator_clang_type.IsIntegerType(is_signed);
-                            ParseChildEnumerators(cu_sc, clang_type, is_signed, type_sp->GetByteSize(), die);
+                            if (die.HasChildren())
+                            {
+                                SymbolContext cu_sc(die.GetLLDBCompileUnit());
+                                bool is_signed = false;
+                                enumerator_clang_type.IsIntegerType(is_signed);
+                                ParseChildEnumerators(cu_sc, clang_type, is_signed, type_sp->GetByteSize(), die);
+                            }
+                            ClangASTContext::CompleteTagDeclarationDefinition (clang_type);
+                        }
+                        else
+                        {
+                            dwarf->GetObjectFile()->GetModule()->ReportError("DWARF DIE at 0x%8.8x named \"%s\" was not able to start its definition.\nPlease file a bug and attach the file at the start of this error message",
+                                                                             die.GetOffset(),
+                                                                             type_name_cstr);
                         }
-                        ClangASTContext::CompleteTagDeclarationDefinition (clang_type);
                     }
                 }
                     break;
@@ -1735,8 +1751,16 @@
                                 // to layout the class. Since we provide layout assistance, all
                                 // ivars in this class and other classes will be fine, this is
                                 // the best we can do short of crashing.
-                                ClangASTContext::StartTagDeclarationDefinition(array_element_type);
-                                ClangASTContext::CompleteTagDeclarationDefinition(array_element_type);
+                                if (ClangASTContext::StartTagDeclarationDefinition(array_element_type))
+                                {
+                                    ClangASTContext::CompleteTagDeclarationDefinition(array_element_type);
+                                }
+                                else
+                                {
+                                    module_sp->ReportError ("DWARF DIE at 0x%8.8x was not able to start its definition.\nPlease file a bug and attach the file at the start of this error message",
+                                                            type_die_ref.die_offset,
+                                                            type_name_cstr);
+                                }
                             }
 
                             uint64_t array_element_bit_stride = byte_stride * 8 + bit_stride;
@@ -2242,8 +2266,10 @@
                                     // below. Since we provide layout assistance, all ivars in this
                                     // class and other classes will be fine, this is the best we can do
                                     // short of crashing.
-                                    ClangASTContext::StartTagDeclarationDefinition (base_class_type);
-                                    ClangASTContext::CompleteTagDeclarationDefinition (base_class_type);
+                                    if (ClangASTContext::StartTagDeclarationDefinition (base_class_type))
+                                    {
+                                        ClangASTContext::CompleteTagDeclarationDefinition (base_class_type);
+                                    }
                                 }
                             }
                         }
@@ -2339,15 +2365,17 @@
             return (bool)clang_type;
 
         case DW_TAG_enumeration_type:
-            ClangASTContext::StartTagDeclarationDefinition (clang_type);
-            if (die.HasChildren())
+            if (ClangASTContext::StartTagDeclarationDefinition (clang_type))
             {
-                SymbolContext sc(die.GetLLDBCompileUnit());
-                bool is_signed = false;
-                clang_type.IsIntegerType(is_signed);
-                ParseChildEnumerators(sc, clang_type, is_signed, type->GetByteSize(), die);
+                if (die.HasChildren())
+                {
+                    SymbolContext sc(die.GetLLDBCompileUnit());
+                    bool is_signed = false;
+                    clang_type.IsIntegerType(is_signed);
+                    ParseChildEnumerators(sc, clang_type, is_signed, type->GetByteSize(), die);
+                }
+                ClangASTContext::CompleteTagDeclarationDefinition (clang_type);
             }
-            ClangASTContext::CompleteTagDeclarationDefinition (clang_type);
             return (bool)clang_type;
 
         default:
@@ -3089,8 +3117,18 @@
                                     // to layout the class. Since we provide layout assistance, all
                                     // ivars in this class and other classes will be fine, this is
                                     // the best we can do short of crashing.
-                                    ClangASTContext::StartTagDeclarationDefinition(member_clang_type);
-                                    ClangASTContext::CompleteTagDeclarationDefinition(member_clang_type);
+                                    if (ClangASTContext::StartTagDeclarationDefinition(member_clang_type))
+                                    {
+                                        ClangASTContext::CompleteTagDeclarationDefinition(member_clang_type);
+                                    }
+                                    else
+                                    {
+                                        module_sp->ReportError ("DWARF DIE at 0x%8.8x (class %s) has a member variable 0x%8.8x (%s) whose type claims to be a C++ class but we were not able to start its definition.\nPlease file a bug and attach the file at the start of this error message",
+                                                                parent_die.GetOffset(),
+                                                                parent_die.GetName(),
+                                                                die.GetOffset(),
+                                                                name);
+                                    }
                                 }
 
                                 field_decl = ClangASTContext::AddFieldToRecordType (class_clang_type,
Index: source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp
===================================================================
--- source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp
+++ source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp
@@ -132,7 +132,10 @@
     assert(ok);
 
     std::ostringstream url;
+    // debugserver does not accept the URL scheme prefix.
+#if !defined(__APPLE__)
     url << m_socket_scheme << "://";
+#endif
     uint16_t* port_ptr = &port;
     if (m_socket_protocol == Socket::ProtocolTcp)
         url << platform_ip << ":" << port;
Index: source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.h
===================================================================
--- source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.h
+++ source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.h
@@ -65,7 +65,6 @@
 
 private:
     static const char *g_lookup_implementation_function_name;
-    static const char *g_lookup_implementation_function_code;
     static const char *g_lookup_implementation_with_stret_function_code;
     static const char *g_lookup_implementation_no_stret_function_code;
 
@@ -195,6 +194,7 @@
     MsgsendMap m_msgSend_map;
     lldb::ProcessWP m_process_wp;
     lldb::ModuleSP m_objc_module_sp;
+    const char *m_lookup_implementation_function_code;
     std::unique_ptr<UtilityFunction> m_impl_code;
     std::mutex m_impl_function_mutex;
     lldb::addr_t m_impl_fn_addr;
Index: source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp
===================================================================
--- source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp
+++ source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp
@@ -44,7 +44,6 @@
 using namespace lldb_private;
 
 const char *AppleObjCTrampolineHandler::g_lookup_implementation_function_name = "__lldb_objc_find_implementation_for_selector";
-const char *AppleObjCTrampolineHandler::g_lookup_implementation_function_code = NULL;
 const char *AppleObjCTrampolineHandler::g_lookup_implementation_with_stret_function_code = "                               \n\
 extern \"C\"                                                                                                    \n\
 {                                                                                                               \n\
@@ -658,6 +657,7 @@
                                                         const ModuleSP &objc_module_sp) :
     m_process_wp (),
     m_objc_module_sp (objc_module_sp),
+    m_lookup_implementation_function_code(nullptr),
     m_impl_fn_addr (LLDB_INVALID_ADDRESS),
     m_impl_stret_fn_addr (LLDB_INVALID_ADDRESS),
     m_msg_forward_addr (LLDB_INVALID_ADDRESS)
@@ -704,11 +704,11 @@
         // It there is no stret return lookup function, assume that it is the same as the straight lookup:
         m_impl_stret_fn_addr = m_impl_fn_addr;
         // Also we will use the version of the lookup code that doesn't rely on the stret version of the function.
-        g_lookup_implementation_function_code = g_lookup_implementation_no_stret_function_code;
+        m_lookup_implementation_function_code = g_lookup_implementation_no_stret_function_code;
     }
     else
     {
-        g_lookup_implementation_function_code = g_lookup_implementation_with_stret_function_code;
+        m_lookup_implementation_function_code = g_lookup_implementation_with_stret_function_code;
     }
         
     // Look up the addresses for the objc dispatch functions and cache them.  For now I'm inspecting the symbol
@@ -757,10 +757,10 @@
 
         if (!m_impl_code.get())
         {
-            if (g_lookup_implementation_function_code != NULL)
+            if (m_lookup_implementation_function_code != NULL)
             {
                 Error error;
-                m_impl_code.reset (exe_ctx.GetTargetRef().GetUtilityFunctionForLanguage (g_lookup_implementation_function_code,
+                m_impl_code.reset (exe_ctx.GetTargetRef().GetUtilityFunctionForLanguage (m_lookup_implementation_function_code,
                                                                                          eLanguageTypeObjC,
                                                                                          g_lookup_implementation_function_name,
                                                                                          error));
Index: source/Core/Mangled.cpp
===================================================================
--- source/Core/Mangled.cpp
+++ source/Core/Mangled.cpp
@@ -34,6 +34,8 @@
 #include "llvm/ADT/DenseMap.h"
 
 #include "lldb/Core/ConstString.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/Logging.h"
 #include "lldb/Core/Mangled.h"
 #include "lldb/Core/RegularExpression.h"
 #include "lldb/Core/Stream.h"
@@ -271,6 +273,8 @@
                             "Mangled::GetDemangledName (m_mangled = %s)",
                             m_mangled.GetCString());
 
+        Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_DEMANGLE);
+
         // Don't bother running anything that isn't mangled
         const char *mangled_name = m_mangled.GetCString();
         ManglingScheme mangling_scheme{cstring_mangling_scheme(mangled_name)};
@@ -285,6 +289,8 @@
                 case eManglingSchemeMSVC:
                 {
 #if defined(_MSC_VER)
+                    if (log)
+                        log->Printf("demangle msvc: %s", mangled_name);
                     const size_t demangled_length = 2048;
                     demangled_name = static_cast<char *>(::malloc(demangled_length));
                     ::ZeroMemory(demangled_name, demangled_length);
@@ -295,6 +301,14 @@
                             UNDNAME_NO_MEMBER_TYPE         | // Strip virtual, static, etc specifiers
                             UNDNAME_NO_MS_KEYWORDS           // Strip all MS extension keywords
                         );
+                    if (log)
+                    {
+                        if (demangled_name && demangled_name[0])
+                            log->Printf("demangled msvc: %s -> \"%s\"", mangled_name, demangled_name);
+                        else
+                            log->Printf("demangled msvc: %s -> error: 0x%" PRIx64, mangled_name, result);
+                    }
+
                     if (result == 0)
                     {
                         free(demangled_name);
@@ -306,6 +320,8 @@
                 case eManglingSchemeItanium:
                 {
 #ifdef LLDB_USE_BUILTIN_DEMANGLER
+                    if (log)
+                        log->Printf("demangle itanium: %s", mangled_name);
                     // Try to use the fast-path demangler first for the
                     // performance win, falling back to the full demangler only
                     // when necessary
@@ -315,6 +331,13 @@
 #else
                     demangled_name = abi::__cxa_demangle(mangled_name, NULL, NULL, NULL);
 #endif
+                    if (log)
+                    {
+                        if (demangled_name)
+                            log->Printf("demangled itanium: %s -> \"%s\"", mangled_name, demangled_name);
+                        else
+                            log->Printf("demangled itanium: %s -> error: failed to demangle", mangled_name);
+                    }
                     break;
                 }
                 case eManglingSchemeNone:
Index: source/Core/Logging.cpp
===================================================================
--- source/Core/Logging.cpp
+++ source/Core/Logging.cpp
@@ -150,6 +150,7 @@
                 else if (0 == ::strcasecmp(arg, "jit"))         flag_bits &= ~LIBLLDB_LOG_JIT_LOADER;
                 else if (0 == ::strcasecmp(arg, "language"))    flag_bits &= ~LIBLLDB_LOG_LANGUAGE;
                 else if (0 == ::strncasecmp(arg, "formatters", 10))   flag_bits &= ~LIBLLDB_LOG_DATAFORMATTERS;
+                else if (0 == ::strncasecmp(arg, "demangle", 8))      flag_bits &= ~LIBLLDB_LOG_DEMANGLE;
                 else
                 {
                     feedback_strm->Printf ("error:  unrecognized log category '%s'\n", arg);
@@ -225,6 +226,7 @@
             else if (0 == ::strcasecmp(arg, "jit"))         flag_bits |= LIBLLDB_LOG_JIT_LOADER;
             else if (0 == ::strcasecmp(arg, "language"))    flag_bits |= LIBLLDB_LOG_LANGUAGE;
             else if (0 == ::strncasecmp(arg, "formatters", 10))   flag_bits |= LIBLLDB_LOG_DATAFORMATTERS;
+            else if (0 == ::strncasecmp(arg, "demangle", 8))      flag_bits |= LIBLLDB_LOG_DEMANGLE;
             else
             {
                 feedback_strm->Printf("error: unrecognized log category '%s'\n", arg);
@@ -251,6 +253,7 @@
                  "  communication - log communication activities\n"
                  "  connection - log connection details\n"
                  "  default - enable the default set of logging categories for liblldb\n"
+                 "  demangle - log mangled names to catch demangler crashes\n"
                  "  dyld - log shared library related activities\n"
                  "  events - log broadcaster, listener and event queue activities\n"
                  "  expr - log expressions\n"
Index: source/Breakpoint/BreakpointLocationCollection.cpp
===================================================================
--- source/Breakpoint/BreakpointLocationCollection.cpp
+++ source/Breakpoint/BreakpointLocationCollection.cpp
@@ -26,7 +26,8 @@
 // BreakpointLocationCollection constructor
 //----------------------------------------------------------------------
 BreakpointLocationCollection::BreakpointLocationCollection() :
-    m_break_loc_collection()
+    m_break_loc_collection(),
+    m_collection_mutex()
 {
 }
 
@@ -40,14 +41,16 @@
 void
 BreakpointLocationCollection::Add(const BreakpointLocationSP &bp_loc)
 {
+    std::lock_guard<std::mutex> guard(m_collection_mutex);
     BreakpointLocationSP old_bp_loc = FindByIDPair (bp_loc->GetBreakpoint().GetID(), bp_loc->GetID());
     if (!old_bp_loc.get())
         m_break_loc_collection.push_back(bp_loc);
 }
 
 bool
 BreakpointLocationCollection::Remove (lldb::break_id_t bp_id, lldb::break_id_t bp_loc_id)
 {
+    std::lock_guard<std::mutex> guard(m_collection_mutex);
     collection::iterator pos = GetIDPairIterator(bp_id, bp_loc_id);    // Predicate
     if (pos != m_break_loc_collection.end())
     {
@@ -117,6 +120,7 @@
 BreakpointLocationSP
 BreakpointLocationCollection::GetByIndex (size_t i)
 {
+    std::lock_guard<std::mutex> guard(m_collection_mutex);
     BreakpointLocationSP stop_sp;
     if (i < m_break_loc_collection.size())
         stop_sp = m_break_loc_collection[i];
@@ -127,6 +131,7 @@
 const BreakpointLocationSP
 BreakpointLocationCollection::GetByIndex (size_t i) const
 {
+    std::lock_guard<std::mutex> guard(m_collection_mutex);
     BreakpointLocationSP stop_sp;
     if (i < m_break_loc_collection.size())
         stop_sp = m_break_loc_collection[i];
@@ -156,6 +161,7 @@
 bool 
 BreakpointLocationCollection::ValidForThisThread (Thread *thread)
 {
+    std::lock_guard<std::mutex> guard(m_collection_mutex);
     collection::iterator pos,
         begin = m_break_loc_collection.begin(),
         end = m_break_loc_collection.end();
@@ -171,6 +177,7 @@
 bool 
 BreakpointLocationCollection::IsInternal () const
 {
+    std::lock_guard<std::mutex> guard(m_collection_mutex);
     collection::const_iterator pos,
         begin = m_break_loc_collection.begin(),
         end = m_break_loc_collection.end();
@@ -191,6 +198,7 @@
 void
 BreakpointLocationCollection::GetDescription (Stream *s, lldb::DescriptionLevel level)
 {
+    std::lock_guard<std::mutex> guard(m_collection_mutex);
     collection::iterator pos,
         begin = m_break_loc_collection.begin(),
         end = m_break_loc_collection.end();
Index: include/lldb/Core/Logging.h
===================================================================
--- include/lldb/Core/Logging.h
+++ include/lldb/Core/Logging.h
@@ -49,6 +49,7 @@
 #define LIBLLDB_LOG_JIT_LOADER          (1u << 27)
 #define LIBLLDB_LOG_LANGUAGE            (1u << 28)
 #define LIBLLDB_LOG_DATAFORMATTERS      (1u << 29)
+#define LIBLLDB_LOG_DEMANGLE            (1u << 30)
 #define LIBLLDB_LOG_ALL                 (UINT32_MAX)
 #define LIBLLDB_LOG_DEFAULT             (LIBLLDB_LOG_PROCESS              |\
                                          LIBLLDB_LOG_THREAD               |\
Index: include/lldb/Breakpoint/BreakpointLocationCollection.h
===================================================================
--- include/lldb/Breakpoint/BreakpointLocationCollection.h
+++ include/lldb/Breakpoint/BreakpointLocationCollection.h
@@ -13,6 +13,8 @@
 // C Includes
 // C++ Includes
 #include <vector>
+#include <mutex>
+
 // Other libraries and framework includes
 // Project includes
 #include "lldb/lldb-private.h"
@@ -201,7 +203,8 @@
     collection::const_iterator
     GetIDPairConstIterator(lldb::break_id_t break_id, lldb::break_id_t break_loc_id) const;
 
-    collection m_break_loc_collection;
+    collection     m_break_loc_collection;
+    mutable std::mutex  m_collection_mutex;
 
 public:
     typedef AdaptedIterable<collection, lldb::BreakpointLocationSP, vector_adapter> BreakpointLocationCollectionIterable;
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to