Add SBTarget::GetLastCreatedWatchpointLocation() API and export to the Python interface.
Also add rich comparison methods (__eq__ and __ne__) for SBWatchpointLocation.
Modify TestWatchpointLocationIter.py to exercise the new APIs.

Add fuzz testings for the recently added SBTarget APIs related to watchpoint manipulations.


git-svn-id: https://llvm.org/svn/llvm-project/llvdb/trunk@140633 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/lldb/API/SBTarget.h b/include/lldb/API/SBTarget.h
index 023e5e7..97dc66b 100644
--- a/include/lldb/API/SBTarget.h
+++ b/include/lldb/API/SBTarget.h
@@ -448,6 +448,9 @@
     GetNumWatchpointLocations () const;
 
     lldb::SBWatchpointLocation
+    GetLastCreatedWatchpointLocation ();
+
+    lldb::SBWatchpointLocation
     GetWatchpointLocationAtIndex (uint32_t idx) const;
 
     bool
diff --git a/include/lldb/Breakpoint/WatchpointLocationList.h b/include/lldb/Breakpoint/WatchpointLocationList.h
index 0799159..84b3f3c 100644
--- a/include/lldb/Breakpoint/WatchpointLocationList.h
+++ b/include/lldb/Breakpoint/WatchpointLocationList.h
@@ -187,6 +187,7 @@
     size_t
     GetSize() const
     {
+        Mutex::Locker locker(m_mutex);
         return m_address_to_location.size();
     }
 
diff --git a/include/lldb/Target/Target.h b/include/lldb/Target/Target.h
index 53e7596..835def2 100644
--- a/include/lldb/Target/Target.h
+++ b/include/lldb/Target/Target.h
@@ -298,6 +298,12 @@
                               size_t size,
                               uint32_t type);
 
+    lldb::WatchpointLocationSP
+    GetLastCreatedWatchpointLocation ()
+    {
+        return m_last_created_watchpoint_location;
+    }
+
     WatchpointLocationList &
     GetWatchpointLocationList()
     {
@@ -866,6 +872,7 @@
     BreakpointList  m_internal_breakpoint_list;
     lldb::BreakpointSP m_last_created_breakpoint;
     WatchpointLocationList  m_watchpoint_location_list;
+    lldb::WatchpointLocationSP m_last_created_watchpoint_location;
     // We want to tightly control the process destruction process so
     // we can correctly tear down everything that we need to, so the only
     // class that knows about the process lifespan is this target class.
diff --git a/scripts/Python/interface/SBTarget.i b/scripts/Python/interface/SBTarget.i
index 3bf14b1..6feb216 100644
--- a/scripts/Python/interface/SBTarget.i
+++ b/scripts/Python/interface/SBTarget.i
@@ -439,6 +439,9 @@
     GetNumWatchpointLocations () const;
 
     lldb::SBWatchpointLocation
+    GetLastCreatedWatchpointLocation ();
+
+    lldb::SBWatchpointLocation
     GetWatchpointLocationAtIndex (uint32_t idx) const;
 
     bool
diff --git a/scripts/Python/modify-python-lldb.py b/scripts/Python/modify-python-lldb.py
index 4624677..ac523be 100644
--- a/scripts/Python/modify-python-lldb.py
+++ b/scripts/Python/modify-python-lldb.py
@@ -199,11 +199,12 @@
 #
 # This dictionary defines a mapping from classname to equality method name(s).
 #
-e = { 'SBAddress':    ['GetFileAddress', 'GetModule'],
-      'SBBreakpoint': ['GetID'],
-      'SBFileSpec':   ['GetFilename', 'GetDirectory'],
-      'SBModule':     ['GetFileSpec', 'GetUUIDString'],
-      'SBType':       ['GetByteSize', 'GetName']
+e = { 'SBAddress':            ['GetFileAddress', 'GetModule'],
+      'SBBreakpoint':         ['GetID'],
+      'SBWatchpointLocation': ['GetID'],
+      'SBFileSpec':           ['GetFilename', 'GetDirectory'],
+      'SBModule':             ['GetFileSpec', 'GetUUIDString'],
+      'SBType':               ['GetByteSize', 'GetName']
       }
 
 def list_to_frag(list):
diff --git a/source/API/SBTarget.cpp b/source/API/SBTarget.cpp
index fa074b2..f4ad92d 100644
--- a/source/API/SBTarget.cpp
+++ b/source/API/SBTarget.cpp
@@ -871,19 +871,40 @@
 {
     if (m_opaque_sp)
     {
-        // The breakpoint list is thread safe, no need to lock
+        // The watchpoint location list is thread safe, no need to lock
         return m_opaque_sp->GetWatchpointLocationList().GetSize();
     }
     return 0;
 }
 
 SBWatchpointLocation
+SBTarget::GetLastCreatedWatchpointLocation ()
+{
+    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
+
+    SBWatchpointLocation sb_watchpoint_location;
+    if (m_opaque_sp)
+    {
+        Mutex::Locker api_locker (m_opaque_sp->GetAPIMutex());
+        sb_watchpoint_location = m_opaque_sp->GetLastCreatedWatchpointLocation();
+    }
+
+    if (log)
+    {
+        log->Printf ("SBTarget(%p)::GetLastCreateWatchpointLocation () => SBWatchpointLocation(%p)", 
+                     m_opaque_sp.get(), sb_watchpoint_location.get());
+    }
+
+    return sb_watchpoint_location;
+}
+
+SBWatchpointLocation
 SBTarget::GetWatchpointLocationAtIndex (uint32_t idx) const
 {
     SBWatchpointLocation sb_watchpoint_location;
     if (m_opaque_sp)
     {
-        // The breakpoint list is thread safe, no need to lock
+        // The watchpoint location list is thread safe, no need to lock
         *sb_watchpoint_location = m_opaque_sp->GetWatchpointLocationList().GetByIndex(idx);
     }
     return sb_watchpoint_location;
diff --git a/source/Target/Target.cpp b/source/Target/Target.cpp
index 6a742c2..7209382 100644
--- a/source/Target/Target.cpp
+++ b/source/Target/Target.cpp
@@ -167,6 +167,7 @@
     m_breakpoint_list.RemoveAll(notify);
     m_internal_breakpoint_list.RemoveAll(notify);
     m_last_created_breakpoint.reset();
+    m_last_created_watchpoint_location.reset();
     m_search_filter_sp.reset();
     m_image_search_paths.Clear(notify);
     m_scratch_ast_context_ap.reset();
@@ -452,7 +453,10 @@
                         rc.Success() ? "succeeded" : "failed",
                         wp_loc_sp->GetID());
 
-    if (rc.Fail()) wp_loc_sp.reset();
+    if (rc.Fail())
+        wp_loc_sp.reset();
+    else
+        m_last_created_watchpoint_location = wp_loc_sp;
     return wp_loc_sp;
 }
 
diff --git a/test/python_api/default-constructor/sb_target.py b/test/python_api/default-constructor/sb_target.py
index 36db20f..e1a5db6 100644
--- a/test/python_api/default-constructor/sb_target.py
+++ b/test/python_api/default-constructor/sb_target.py
@@ -40,6 +40,14 @@
     obj.EnableAllBreakpoints()
     obj.DisableAllBreakpoints()
     obj.DeleteAllBreakpoints()
+    obj.GetNumWatchpointLocations()
+    obj.GetLastCreatedWatchpointLocation()
+    obj.GetWatchpointLocationAtIndex(0)
+    obj.WatchpointLocationDelete(0)
+    obj.FindWatchpointLocationByID(0)
+    obj.EnableAllWatchpointLocations()
+    obj.DisableAllWatchpointLocations()
+    obj.DeleteAllWatchpointLocations()
     obj.GetBroadcaster()
     obj.GetDescription(lldb.SBStream(), lldb.eDescriptionLevelBrief)
     obj.Clear()
diff --git a/test/python_api/watchpoint/TestWatchpointLocationIter.py b/test/python_api/watchpoint/TestWatchpointLocationIter.py
index d54c210..fdaa04a 100644
--- a/test/python_api/watchpoint/TestWatchpointLocationIter.py
+++ b/test/python_api/watchpoint/TestWatchpointLocationIter.py
@@ -65,7 +65,9 @@
 
         # There should be only 1 watchpoint location under the target.
         self.assertTrue(target.GetNumWatchpointLocations() == 1)
-        wp_loc = target.GetWatchpointLocationAtIndex(0) 
+        wp_loc = target.GetWatchpointLocationAtIndex(0)
+        last_created = target.GetLastCreatedWatchpointLocation()
+        self.assertTrue(wp_loc == last_created)
         self.assertTrue(wp_loc.IsEnabled())
         watch_id = wp_loc.GetID()
         self.assertTrue(watch_id != 0)