Expanded the flags that can be set for a command object in lldb_private::CommandObject. This list of available flags are:

enum
{
    //----------------------------------------------------------------------
    // eFlagRequiresTarget
    //
    // Ensures a valid target is contained in m_exe_ctx prior to executing
    // the command. If a target doesn't exist or is invalid, the command
    // will fail and CommandObject::GetInvalidTargetDescription() will be
    // returned as the error. CommandObject subclasses can override the
    // virtual function for GetInvalidTargetDescription() to provide custom
    // strings when needed.
    //----------------------------------------------------------------------
    eFlagRequiresTarget         = (1u << 0),
    //----------------------------------------------------------------------
    // eFlagRequiresProcess
    //
    // Ensures a valid process is contained in m_exe_ctx prior to executing
    // the command. If a process doesn't exist or is invalid, the command
    // will fail and CommandObject::GetInvalidProcessDescription() will be
    // returned as the error. CommandObject subclasses can override the
    // virtual function for GetInvalidProcessDescription() to provide custom
    // strings when needed.
    //----------------------------------------------------------------------
    eFlagRequiresProcess        = (1u << 1),
    //----------------------------------------------------------------------
    // eFlagRequiresThread
    //
    // Ensures a valid thread is contained in m_exe_ctx prior to executing
    // the command. If a thread doesn't exist or is invalid, the command
    // will fail and CommandObject::GetInvalidThreadDescription() will be
    // returned as the error. CommandObject subclasses can override the
    // virtual function for GetInvalidThreadDescription() to provide custom
    // strings when needed.
    //----------------------------------------------------------------------
    eFlagRequiresThread         = (1u << 2),
    //----------------------------------------------------------------------
    // eFlagRequiresFrame
    //
    // Ensures a valid frame is contained in m_exe_ctx prior to executing
    // the command. If a frame doesn't exist or is invalid, the command
    // will fail and CommandObject::GetInvalidFrameDescription() will be
    // returned as the error. CommandObject subclasses can override the
    // virtual function for GetInvalidFrameDescription() to provide custom
    // strings when needed.
    //----------------------------------------------------------------------
    eFlagRequiresFrame          = (1u << 3),
    //----------------------------------------------------------------------
    // eFlagRequiresRegContext
    //
    // Ensures a valid register context (from the selected frame if there
    // is a frame in m_exe_ctx, or from the selected thread from m_exe_ctx)
    // is availble from m_exe_ctx prior to executing the command. If a
    // target doesn't exist or is invalid, the command will fail and
    // CommandObject::GetInvalidRegContextDescription() will be returned as
    // the error. CommandObject subclasses can override the virtual function
    // for GetInvalidRegContextDescription() to provide custom strings when
    // needed.
    //----------------------------------------------------------------------
    eFlagRequiresRegContext     = (1u << 4),
    //----------------------------------------------------------------------
    // eFlagTryTargetAPILock
    //
    // Attempts to acquire the target lock if a target is selected in the
    // command interpreter. If the command object fails to acquire the API
    // lock, the command will fail with an appropriate error message.
    //----------------------------------------------------------------------
    eFlagTryTargetAPILock       = (1u << 5),
    //----------------------------------------------------------------------
    // eFlagProcessMustBeLaunched
    //
    // Verifies that there is a launched process in m_exe_ctx, if there
    // isn't, the command will fail with an appropriate error message.
    //----------------------------------------------------------------------
    eFlagProcessMustBeLaunched  = (1u << 6),
    //----------------------------------------------------------------------
    // eFlagProcessMustBePaused
    //
    // Verifies that there is a paused process in m_exe_ctx, if there
    // isn't, the command will fail with an appropriate error message.
    //----------------------------------------------------------------------
    eFlagProcessMustBePaused    = (1u << 7)
};

Now each command object contains a "ExecutionContext m_exe_ctx;" member variable that gets initialized prior to running the command. The validity of the target objects in m_exe_ctx are checked to ensure that any target/process/thread/frame/reg context that are required are valid prior to executing the command. Each command object also contains a Mutex::Locker m_api_locker which gets used if eFlagTryTargetAPILock is set. This centralizes a lot of checking code that was previously and inconsistently implemented across many commands.




git-svn-id: https://llvm.org/svn/llvm-project/lldb/trunk@171990 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/source/Commands/CommandObjectWatchpoint.cpp b/source/Commands/CommandObjectWatchpoint.cpp
index f63e4a8..f4d3c13 100644
--- a/source/Commands/CommandObjectWatchpoint.cpp
+++ b/source/Commands/CommandObjectWatchpoint.cpp
@@ -934,7 +934,10 @@
                              "If watchpoint setting fails, consider disable/delete existing ones "
                              "to free up resources.",
                              NULL,
-                            eFlagProcessMustBeLaunched | eFlagProcessMustBePaused),
+                             eFlagRequiresFrame         |
+                             eFlagTryTargetAPILock      |
+                             eFlagProcessMustBeLaunched |
+                             eFlagProcessMustBePaused   ),
         m_option_group (interpreter),
         m_option_watchpoint ()
     {
@@ -988,18 +991,10 @@
     }
     
     virtual bool
-    DoExecute (Args& command,
-             CommandReturnObject &result)
+    DoExecute (Args& command, CommandReturnObject &result)
     {
         Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
-        ExecutionContext exe_ctx(m_interpreter.GetExecutionContext());
-        StackFrame *frame = exe_ctx.GetFramePtr();
-        if (frame == NULL)
-        {
-            result.AppendError ("you must be stopped in a valid stack frame to set a watchpoint.");
-            result.SetStatus (eReturnStatusFailed);
-            return false;
-        }
+        StackFrame *frame = m_exe_ctx.GetFramePtr();
 
         // If no argument is present, issue an error message.  There's no way to set a watchpoint.
         if (command.GetArgumentCount() <= 0)
@@ -1025,7 +1020,8 @@
         Stream &output_stream = result.GetOutputStream();
 
         // A simple watch variable gesture allows only one argument.
-        if (command.GetArgumentCount() != 1) {
+        if (command.GetArgumentCount() != 1)
+        {
             result.GetErrorStream().Printf("error: specify exactly one variable to watch for\n");
             result.SetStatus(eReturnStatusFailed);
             return false;
@@ -1041,14 +1037,15 @@
                                                               var_sp,
                                                               error);
         
-        if (!valobj_sp) {
+        if (!valobj_sp)
+        {
             // Not in the frame; let's check the globals.
             
             VariableList variable_list;
             ValueObjectList valobj_list;
             
             Error error (Variable::GetValuesForVariableExpressionPath (command.GetArgumentAtIndex(0),
-                                                                       exe_ctx.GetBestExecutionContextScope(),
+                                                                       m_exe_ctx.GetBestExecutionContextScope(),
                                                                        GetVariableCallback,
                                                                        target,
                                                                        variable_list,
@@ -1060,17 +1057,21 @@
         
         ClangASTType type;
         
-        if (valobj_sp) {
+        if (valobj_sp)
+        {
             AddressType addr_type;
             addr = valobj_sp->GetAddressOf(false, &addr_type);
-            if (addr_type == eAddressTypeLoad) {
+            if (addr_type == eAddressTypeLoad)
+            {
                 // We're in business.
                 // Find out the size of this variable.
                 size = m_option_watchpoint.watch_size == 0 ? valobj_sp->GetByteSize()
                                                            : m_option_watchpoint.watch_size;
             }
             type.SetClangType(valobj_sp->GetClangAST(), valobj_sp->GetClangType());
-        } else {
+        }
+        else
+        {
             const char *error_cstr = error.AsCString(NULL);
             if (error_cstr)
                 result.GetErrorStream().Printf("error: %s\n", error_cstr);
@@ -1084,10 +1085,12 @@
         uint32_t watch_type = m_option_watchpoint.watch_type;
         error.Clear();
         Watchpoint *wp = target->CreateWatchpoint(addr, size, &type, watch_type, error).get();
-        if (wp) {
+        if (wp)
+        {
             wp->SetWatchSpec(command.GetArgumentAtIndex(0));
             wp->SetWatchVariable(true);
-            if (var_sp && var_sp->GetDeclaration().GetFile()) {
+            if (var_sp && var_sp->GetDeclaration().GetFile())
+            {
                 StreamString ss;
                 // True to show fullpath for declaration file.
                 var_sp->GetDeclaration().DumpStopContext(&ss, true);
@@ -1097,7 +1100,9 @@
             wp->GetDescription(&output_stream, lldb::eDescriptionLevelFull);
             output_stream.EOL();
             result.SetStatus(eReturnStatusSuccessFinishResult);
-        } else {
+        }
+        else
+        {
             result.AppendErrorWithFormat("Watchpoint creation failed (addr=0x%" PRIx64 ", size=%lu, variable expression='%s').\n",
                                          addr, size, command.GetArgumentAtIndex(0));
             if (error.AsCString(NULL))
@@ -1135,7 +1140,10 @@
                           "If watchpoint setting fails, consider disable/delete existing ones "
                           "to free up resources.",
                           NULL,
-                          eFlagProcessMustBeLaunched | eFlagProcessMustBePaused),
+                          eFlagRequiresFrame         |
+                          eFlagTryTargetAPILock      |
+                          eFlagProcessMustBeLaunched |
+                          eFlagProcessMustBePaused   ),
         m_option_group (interpreter),
         m_option_watchpoint ()
     {
@@ -1182,14 +1190,7 @@
     DoExecute (const char *raw_command, CommandReturnObject &result)
     {
         Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
-        ExecutionContext exe_ctx(m_interpreter.GetExecutionContext());
-        StackFrame *frame = exe_ctx.GetFramePtr();
-        if (frame == NULL)
-        {
-            result.AppendError ("you must be stopped in a valid stack frame to set a watchpoint.");
-            result.SetStatus (eReturnStatusFailed);
-            return false;
-        }
+        StackFrame *frame = m_exe_ctx.GetFramePtr();
 
         Args command(raw_command);
 
@@ -1247,7 +1248,8 @@
                                                                    frame, 
                                                                    valobj_sp,
                                                                    options);
-        if (expr_result != eExecutionCompleted) {
+        if (expr_result != eExecutionCompleted)
+        {
             result.GetErrorStream().Printf("error: expression evaluation of address to watch failed\n");
             result.GetErrorStream().Printf("expression evaluated: %s\n", expr_str.c_str());
             result.SetStatus(eReturnStatusFailed);
@@ -1257,7 +1259,8 @@
         // Get the address to watch.
         bool success = false;
         addr = valobj_sp->GetValueAsUnsigned(0, &success);
-        if (!success) {
+        if (!success)
+        {
             result.GetErrorStream().Printf("error: expression did not evaluate to an address\n");
             result.SetStatus(eReturnStatusFailed);
             return false;
@@ -1276,8 +1279,10 @@
         
         Error error;
         Watchpoint *wp = target->CreateWatchpoint(addr, size, &type, watch_type, error).get();
-        if (wp) {
-            if (var_sp && var_sp->GetDeclaration().GetFile()) {
+        if (wp)
+        {
+            if (var_sp && var_sp->GetDeclaration().GetFile())
+            {
                 StreamString ss;
                 // True to show fullpath for declaration file.
                 var_sp->GetDeclaration().DumpStopContext(&ss, true);
@@ -1287,7 +1292,9 @@
             wp->GetDescription(&output_stream, lldb::eDescriptionLevelFull);
             output_stream.EOL();
             result.SetStatus(eReturnStatusSuccessFinishResult);
-        } else {
+        }
+        else
+        {
             result.AppendErrorWithFormat("Watchpoint creation failed (addr=0x%" PRIx64 ", size=%lu).\n",
                                          addr, size);
             if (error.AsCString(NULL))