Add capability to set ignore count for watchpoint on the command line:

    watchpoint ignore -i <count> [<watchpt-id | watchpt-id-list>]

Add tests of watchpoint ignore_count for command line as well as API.


git-svn-id: https://llvm.org/svn/llvm-project/llvdb/trunk@141217 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/source/Commands/CommandObjectWatchpoint.cpp b/source/Commands/CommandObjectWatchpoint.cpp
index 151d3d7..7c07a03 100644
--- a/source/Commands/CommandObjectWatchpoint.cpp
+++ b/source/Commands/CommandObjectWatchpoint.cpp
@@ -155,16 +155,19 @@
     CommandObjectSP enable_command_object (new CommandObjectWatchpointEnable (interpreter));
     CommandObjectSP disable_command_object (new CommandObjectWatchpointDisable (interpreter));
     CommandObjectSP delete_command_object (new CommandObjectWatchpointDelete (interpreter));
+    CommandObjectSP ignore_command_object (new CommandObjectWatchpointIgnore (interpreter));
 
     list_command_object->SetCommandName ("watchpoint list");
     enable_command_object->SetCommandName("watchpoint enable");
     disable_command_object->SetCommandName("watchpoint disable");
     delete_command_object->SetCommandName("watchpoint delete");
+    ignore_command_object->SetCommandName("watchpoint ignore");
 
     status = LoadSubCommand ("list",       list_command_object);
     status = LoadSubCommand ("enable",     enable_command_object);
     status = LoadSubCommand ("disable",    disable_command_object);
     status = LoadSubCommand ("delete",     delete_command_object);
+    status = LoadSubCommand ("ignore",     ignore_command_object);
 }
 
 CommandObjectMultiwordWatchpoint::~CommandObjectMultiwordWatchpoint()
@@ -555,3 +558,138 @@
     return result.Succeeded();
 }
 
+//-------------------------------------------------------------------------
+// CommandObjectWatchpointIgnore::CommandOptions
+//-------------------------------------------------------------------------
+#pragma mark Ignore::CommandOptions
+
+CommandObjectWatchpointIgnore::CommandOptions::CommandOptions(CommandInterpreter &interpreter) :
+    Options (interpreter),
+    m_ignore_count (0)
+{
+}
+
+CommandObjectWatchpointIgnore::CommandOptions::~CommandOptions ()
+{
+}
+
+OptionDefinition
+CommandObjectWatchpointIgnore::CommandOptions::g_option_table[] =
+{
+    { LLDB_OPT_SET_ALL, true, "ignore-count", 'i', required_argument, NULL, NULL, eArgTypeCount, "Set the number of times this watchpoint is skipped before stopping." },
+    { 0,                false, NULL,            0 , 0,                 NULL, 0,    eArgTypeNone, NULL }
+};
+
+const OptionDefinition*
+CommandObjectWatchpointIgnore::CommandOptions::GetDefinitions ()
+{
+    return g_option_table;
+}
+
+Error
+CommandObjectWatchpointIgnore::CommandOptions::SetOptionValue (uint32_t option_idx, const char *option_arg)
+{
+    Error error;
+    char short_option = (char) m_getopt_table[option_idx].val;
+
+    switch (short_option)
+    {
+        case 'i':
+        {
+            m_ignore_count = Args::StringToUInt32(option_arg, UINT32_MAX, 0);
+            if (m_ignore_count == UINT32_MAX)
+               error.SetErrorStringWithFormat ("Invalid ignore count '%s'.\n", option_arg);
+        }
+        break;
+        default:
+            error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option);
+            break;
+    }
+
+    return error;
+}
+
+void
+CommandObjectWatchpointIgnore::CommandOptions::OptionParsingStarting ()
+{
+    m_ignore_count = 0;
+}
+
+//-------------------------------------------------------------------------
+// CommandObjectWatchpointIgnore
+//-------------------------------------------------------------------------
+#pragma mark Ignore
+
+CommandObjectWatchpointIgnore::CommandObjectWatchpointIgnore(CommandInterpreter &interpreter) :
+    CommandObject(interpreter,
+                  "watchpoint ignore",
+                  "Set ignore count on the specified watchpoint(s).  If no watchpoints are specified, set them all.",
+                  NULL),
+    m_options (interpreter)
+{
+    CommandArgumentEntry arg;
+    CommandObject::AddIDsArgumentData(arg, eArgTypeWatchpointID, eArgTypeWatchpointIDRange);
+    // Add the entry for the first argument for this command to the object's arguments vector.
+    m_arguments.push_back(arg);
+}
+
+CommandObjectWatchpointIgnore::~CommandObjectWatchpointIgnore()
+{
+}
+
+Options *
+CommandObjectWatchpointIgnore::GetOptions ()
+{
+    return &m_options;
+}
+
+bool
+CommandObjectWatchpointIgnore::Execute(Args& args, CommandReturnObject &result)
+{
+    Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
+    if (!CheckTargetForWatchpointOperations(target, result))
+        return false;
+
+    Mutex::Locker locker;
+    target->GetWatchpointLocationList().GetListMutex(locker);
+    
+    const WatchpointLocationList &watchpoints = target->GetWatchpointLocationList();
+
+    size_t num_watchpoints = watchpoints.GetSize();
+
+    if (num_watchpoints == 0)
+    {
+        result.AppendError("No watchpoints exist to be ignored.");
+        result.SetStatus(eReturnStatusFailed);
+        return false;
+    }
+
+    if (args.GetArgumentCount() == 0)
+    {
+        target->IgnoreAllWatchpointLocations(m_options.m_ignore_count);
+        result.AppendMessageWithFormat("All watchpoints ignored. (%lu watchpoints)\n", num_watchpoints);
+        result.SetStatus (eReturnStatusSuccessFinishNoResult);
+    }
+    else
+    {
+        // Particular watchpoints selected; ignore them.
+        std::vector<uint32_t> wp_ids;
+        if (!VerifyWatchpointIDs(args, wp_ids))
+        {
+            result.AppendError("Invalid watchpoints specification.");
+            result.SetStatus(eReturnStatusFailed);
+            return false;
+        }
+
+        int count = 0;
+        const size_t size = wp_ids.size();
+        for (size_t i = 0; i < size; ++i)
+            if (target->IgnoreWatchpointLocationByID(wp_ids[i], m_options.m_ignore_count))
+                ++count;
+        result.AppendMessageWithFormat("%d watchpoints ignored.\n",count);
+        result.SetStatus (eReturnStatusSuccessFinishNoResult);
+    }
+
+    return result.Succeeded();
+}
+
diff --git a/source/Commands/CommandObjectWatchpoint.h b/source/Commands/CommandObjectWatchpoint.h
index fd5beed..508188e 100644
--- a/source/Commands/CommandObjectWatchpoint.h
+++ b/source/Commands/CommandObjectWatchpoint.h
@@ -140,6 +140,56 @@
 private:
 };
 
+//-------------------------------------------------------------------------
+// CommandObjectWatchpointIgnore
+//-------------------------------------------------------------------------
+
+class CommandObjectWatchpointIgnore : public CommandObject
+{
+public:
+    CommandObjectWatchpointIgnore (CommandInterpreter &interpreter);
+
+    virtual
+    ~CommandObjectWatchpointIgnore ();
+
+    virtual bool
+    Execute (Args& command,
+             CommandReturnObject &result);
+
+    virtual Options *
+    GetOptions ();
+
+    class CommandOptions : public Options
+    {
+    public:
+
+        CommandOptions (CommandInterpreter &interpreter);
+
+        virtual
+        ~CommandOptions ();
+
+        virtual Error
+        SetOptionValue (uint32_t option_idx, const char *option_arg);
+
+        void
+        OptionParsingStarting ();
+
+        const OptionDefinition *
+        GetDefinitions ();
+
+        // Options table: Required for subclasses of Options.
+
+        static OptionDefinition g_option_table[];
+
+        // Instance variables to hold the values for command options.
+
+        uint32_t m_ignore_count;
+    };
+
+private:
+    CommandOptions m_options;
+};
+
 } // namespace lldb_private
 
 #endif  // liblldb_CommandObjectWatchpoint_h_
diff --git a/source/Target/Target.cpp b/source/Target/Target.cpp
index 7209382..036a018 100644
--- a/source/Target/Target.cpp
+++ b/source/Target/Target.cpp
@@ -672,6 +672,30 @@
     return true; // Success!
 }
 
+// Assumption: Caller holds the list mutex lock for m_watchpoint_location_list
+// during these operations.
+bool
+Target::IgnoreAllWatchpointLocations (uint32_t ignore_count)
+{
+    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS));
+    if (log)
+        log->Printf ("Target::%s\n", __FUNCTION__);
+
+    if (!ProcessIsValid())
+        return false;
+
+    size_t num_watchpoints = m_watchpoint_location_list.GetSize();
+    for (size_t i = 0; i < num_watchpoints; ++i)
+    {
+        WatchpointLocationSP wp_loc_sp = m_watchpoint_location_list.GetByIndex(i);
+        if (!wp_loc_sp)
+            return false;
+
+        wp_loc_sp->SetIgnoreCount(ignore_count);
+    }
+    return true; // Success!
+}
+
 // Assumption: Caller holds the list mutex lock for m_watchpoint_location_list.
 bool
 Target::DisableWatchpointLocationByID (lldb::watch_id_t watch_id)
@@ -734,6 +758,26 @@
     return false;
 }
 
+// Assumption: Caller holds the list mutex lock for m_watchpoint_location_list.
+bool
+Target::IgnoreWatchpointLocationByID (lldb::watch_id_t watch_id, uint32_t ignore_count)
+{
+    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS));
+    if (log)
+        log->Printf ("Target::%s (watch_id = %i)\n", __FUNCTION__, watch_id);
+
+    if (!ProcessIsValid())
+        return false;
+
+    WatchpointLocationSP wp_loc_sp = m_watchpoint_location_list.FindByID (watch_id);
+    if (wp_loc_sp)
+    {
+        wp_loc_sp->SetIgnoreCount(ignore_count);
+        return true;
+    }
+    return false;
+}
+
 ModuleSP
 Target::GetExecutableModule ()
 {