Add a commnad to set a condition for a watchpoint.  Example:

    watchpoint modify -c 'global==5'

modifies the last created watchpoint so that the condition expression
is evaluated at the stop point to decide whether we should proceed with
the stopping.

Also add SBWatchpont::SetCondition(const char *condition) to set condition
programmatically.

Test cases to come later.


git-svn-id: https://llvm.org/svn/llvm-project/llvdb/trunk@142227 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/source/Target/StopInfo.cpp b/source/Target/StopInfo.cpp
index 8384747..c422a1d 100644
--- a/source/Target/StopInfo.cpp
+++ b/source/Target/StopInfo.cpp
@@ -346,6 +346,12 @@
     ShouldStop (Event *event_ptr)
     {
         // ShouldStop() method is idempotent and should not affect hit count.
+        // See Process::RunPrivateStateThread()->Process()->HandlePrivateEvent()
+        // -->Process()::ShouldBroadcastEvent()->ThreadList::ShouldStop()->
+        // Thread::ShouldStop()->ThreadPlanBase::ShouldStop()->
+        // StopInfoWatchpoint::ShouldStop() and
+        // Event::DoOnRemoval()->Process::ProcessEventData::DoOnRemoval()->
+        // StopInfoWatchpoint::PerformAction().
         if (m_should_stop_is_valid)
             return m_should_stop;
 
@@ -376,6 +382,118 @@
         return m_should_stop;
     }
     
+    // Perform any action that is associated with this stop.  This is done as the
+    // Event is removed from the event queue.
+    virtual void
+    PerformAction (Event *event_ptr)
+    {
+        LogSP log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS);
+        // We're going to calculate if we should stop or not in some way during the course of
+        // this code.  Also by default we're going to stop, so set that here.
+        m_should_stop = true;
+        
+        WatchpointSP wp_sp =
+            m_thread.GetProcess().GetTarget().GetWatchpointList().FindByID(GetValue());
+        if (wp_sp)
+        {
+            StoppointCallbackContext context (event_ptr, 
+                                              &m_thread.GetProcess(), 
+                                              &m_thread, 
+                                              m_thread.GetStackFrameAtIndex(0).get(),
+                                              false);
+            bool stop_requested = wp_sp->InvokeCallback (&context);
+            // Also make sure that the callback hasn't continued the target.  
+            // If it did, when we'll set m_should_start to false and get out of here.
+            if (GetPrivateState() == eStateRunning)
+                m_should_stop = false;
+            
+            if (m_should_stop && !stop_requested)
+            {
+                // We have been vetoed.
+                m_should_stop = false;
+            }
+
+            if (m_should_stop && wp_sp->GetConditionText() != NULL)
+            {
+                // We need to make sure the user sees any parse errors in their condition, so we'll hook the
+                // constructor errors up to the debugger's Async I/O.
+                StoppointCallbackContext context (event_ptr, 
+                                                  &m_thread.GetProcess(), 
+                                                  &m_thread, 
+                                                  m_thread.GetStackFrameAtIndex(0).get(),
+                                                  false);
+                ExecutionResults result_code;
+                ValueObjectSP result_value_sp;
+                const bool discard_on_error = true;
+                Error error;
+                result_code = ClangUserExpression::EvaluateWithError (context.exe_ctx,
+                                                                      eExecutionPolicyAlways,
+                                                                      discard_on_error,
+                                                                      wp_sp->GetConditionText(),
+                                                                      NULL,
+                                                                      result_value_sp,
+                                                                      error);
+                if (result_code == eExecutionCompleted)
+                {
+                    if (result_value_sp)
+                    {
+                        Scalar scalar_value;
+                        if (result_value_sp->ResolveValue (scalar_value))
+                        {
+                            if (scalar_value.ULongLong(1) == 0)
+                            {
+                                // We have been vetoed.  This takes precedence over querying
+                                // the watchpoint whether it should stop (aka ignore count and
+                                // friends).  See also StopInfoWatchpoint::ShouldStop() as well
+                                // as Process::ProcessEventData::DoOnRemoval().
+                                m_should_stop = false;
+                            }
+                            else
+                                m_should_stop = true;
+                            if (log)
+                                log->Printf("Condition successfully evaluated, result is %s.\n", 
+                                            m_should_stop ? "true" : "false");
+                        }
+                        else
+                        {
+                            m_should_stop = true;
+                            if (log)
+                                log->Printf("Failed to get an integer result from the expression.");
+                        }
+                    }
+                }
+                else
+                {
+                    Debugger &debugger = context.exe_ctx.GetTargetRef().GetDebugger();
+                    StreamSP error_sp = debugger.GetAsyncErrorStream ();
+                    error_sp->Printf ("Stopped due to an error evaluating condition of breakpoint ");
+                    wp_sp->GetDescription (error_sp.get(), eDescriptionLevelBrief);
+                    error_sp->Printf (": \"%s\"", 
+                                      wp_sp->GetConditionText());
+                    error_sp->EOL();
+                    const char *err_str = error.AsCString("<Unknown Error>");
+                    if (log)
+                        log->Printf("Error evaluating condition: \"%s\"\n", err_str);
+
+                    error_sp->PutCString (err_str);
+                    error_sp->EOL();                       
+                    error_sp->Flush();
+                    // If the condition fails to be parsed or run, we should stop.
+                    m_should_stop = true;
+                }
+            }
+        }
+        else
+        {
+            LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
+
+            if (log)
+                log->Printf ("Process::%s could not find watchpoint id: %lld...", __FUNCTION__, m_value);
+        }
+        if (log)
+            log->Printf ("Process::%s returning from action with m_should_stop: %d.", __FUNCTION__, m_should_stop);
+    }
+        
     virtual const char *
     GetDescription ()
     {