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/CommandObjectFrame.cpp b/source/Commands/CommandObjectFrame.cpp
index 6a5c132..f2ff3cf 100644
--- a/source/Commands/CommandObjectFrame.cpp
+++ b/source/Commands/CommandObjectFrame.cpp
@@ -63,7 +63,10 @@
                              "frame info",
                              "List information about the currently selected frame in the current thread.",
                              "frame info",
-                             eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
+                             eFlagRequiresFrame         |
+                             eFlagTryTargetAPILock      |
+                             eFlagProcessMustBeLaunched |
+                             eFlagProcessMustBePaused   )
     {
     }
 
@@ -73,21 +76,10 @@
 
 protected:
     bool
-    DoExecute (Args& command,
-             CommandReturnObject &result)
+    DoExecute (Args& command, CommandReturnObject &result)
     {
-        ExecutionContext exe_ctx(m_interpreter.GetExecutionContext());
-        StackFrame *frame = exe_ctx.GetFramePtr();
-        if (frame)
-        {
-            frame->DumpUsingSettingsFormat (&result.GetOutputStream());
-            result.SetStatus (eReturnStatusSuccessFinishResult);
-        }
-        else
-        {
-            result.AppendError ("no current frame");
-            result.SetStatus (eReturnStatusFailed);
-        }
+        m_exe_ctx.GetFrameRef().DumpUsingSettingsFormat (&result.GetOutputStream());
+        result.SetStatus (eReturnStatusSuccessFinishResult);
         return result.Succeeded();
     }
 };
@@ -162,7 +154,10 @@
                              "frame select",
                              "Select a frame by index from within the current thread and make it the current frame.",
                              NULL,
-                             eFlagProcessMustBeLaunched | eFlagProcessMustBePaused),
+                             eFlagRequiresThread        |
+                             eFlagTryTargetAPILock      |
+                             eFlagProcessMustBeLaunched |
+                             eFlagProcessMustBePaused   ),
         m_options (interpreter)
     {
         CommandArgumentEntry arg;
@@ -193,111 +188,104 @@
 
 protected:
     bool
-    DoExecute (Args& command,
-             CommandReturnObject &result)
+    DoExecute (Args& command, CommandReturnObject &result)
     {
-        ExecutionContext exe_ctx (m_interpreter.GetExecutionContext());
-        Thread *thread = exe_ctx.GetThreadPtr();
-        if (thread)
+        // No need to check "thread" for validity as eFlagRequiresThread ensures it is valid
+        Thread *thread = m_exe_ctx.GetThreadPtr();
+
+        uint32_t frame_idx = UINT32_MAX;
+        if (m_options.relative_frame_offset != INT32_MIN)
         {
-            uint32_t frame_idx = UINT32_MAX;
-            if (m_options.relative_frame_offset != INT32_MIN)
+            // The one and only argument is a signed relative frame index
+            frame_idx = thread->GetSelectedFrameIndex ();
+            if (frame_idx == UINT32_MAX)
+                frame_idx = 0;
+            
+            if (m_options.relative_frame_offset < 0)
             {
-                // The one and only argument is a signed relative frame index
-                frame_idx = thread->GetSelectedFrameIndex ();
-                if (frame_idx == UINT32_MAX)
-                    frame_idx = 0;
-                
-                if (m_options.relative_frame_offset < 0)
-                {
-                    if (frame_idx >= -m_options.relative_frame_offset)
-                        frame_idx += m_options.relative_frame_offset;
-                    else
-                    {
-                        if (frame_idx == 0)
-                        {
-                            //If you are already at the bottom of the stack, then just warn and don't reset the frame.
-                            result.AppendError("Already at the bottom of the stack");
-                            result.SetStatus(eReturnStatusFailed);
-                            return false;
-                        }
-                        else
-                            frame_idx = 0;
-                    }
-                }
-                else if (m_options.relative_frame_offset > 0)
-                {
-                    // I don't want "up 20" where "20" takes you past the top of the stack to produce
-                    // an error, but rather to just go to the top.  So I have to count the stack here...
-                    const uint32_t num_frames = thread->GetStackFrameCount();
-                    if (num_frames - frame_idx > m_options.relative_frame_offset)
-                        frame_idx += m_options.relative_frame_offset;
-                    else
-                    {
-                        if (frame_idx == num_frames - 1)
-                        {
-                            //If we are already at the top of the stack, just warn and don't reset the frame.
-                            result.AppendError("Already at the top of the stack");
-                            result.SetStatus(eReturnStatusFailed);
-                            return false;
-                        }
-                        else
-                            frame_idx = num_frames - 1;
-                    }
-                }
-            }
-            else 
-            {
-                if (command.GetArgumentCount() == 1)
-                {
-                    const char *frame_idx_cstr = command.GetArgumentAtIndex(0);
-                    frame_idx = Args::StringToUInt32 (frame_idx_cstr, UINT32_MAX, 0);
-                }
-                else if (command.GetArgumentCount() == 0)
-                {
-                    frame_idx = thread->GetSelectedFrameIndex ();
-                    if (frame_idx == UINT32_MAX)
-                    {
-                        frame_idx = 0;
-                    }
-                }
+                if (frame_idx >= -m_options.relative_frame_offset)
+                    frame_idx += m_options.relative_frame_offset;
                 else
                 {
-                    result.AppendError ("invalid arguments.\n");
-                    m_options.GenerateOptionUsage (result.GetErrorStream(), this);
+                    if (frame_idx == 0)
+                    {
+                        //If you are already at the bottom of the stack, then just warn and don't reset the frame.
+                        result.AppendError("Already at the bottom of the stack");
+                        result.SetStatus(eReturnStatusFailed);
+                        return false;
+                    }
+                    else
+                        frame_idx = 0;
                 }
             }
-
-            const bool broadcast = true;
-            bool success = thread->SetSelectedFrameByIndex (frame_idx, broadcast);
-            if (success)
+            else if (m_options.relative_frame_offset > 0)
             {
-                exe_ctx.SetFrameSP(thread->GetSelectedFrame ());
-                StackFrame *frame = exe_ctx.GetFramePtr();
-                if (frame)
+                // I don't want "up 20" where "20" takes you past the top of the stack to produce
+                // an error, but rather to just go to the top.  So I have to count the stack here...
+                const uint32_t num_frames = thread->GetStackFrameCount();
+                if (num_frames - frame_idx > m_options.relative_frame_offset)
+                    frame_idx += m_options.relative_frame_offset;
+                else
                 {
-                    bool already_shown = false;
-                    SymbolContext frame_sc(frame->GetSymbolContext(eSymbolContextLineEntry));
-                    if (m_interpreter.GetDebugger().GetUseExternalEditor() && frame_sc.line_entry.file && frame_sc.line_entry.line != 0)
+                    if (frame_idx == num_frames - 1)
                     {
-                        already_shown = Host::OpenFileInExternalEditor (frame_sc.line_entry.file, frame_sc.line_entry.line);
+                        //If we are already at the top of the stack, just warn and don't reset the frame.
+                        result.AppendError("Already at the top of the stack");
+                        result.SetStatus(eReturnStatusFailed);
+                        return false;
                     }
-
-                    bool show_frame_info = true;
-                    bool show_source = !already_shown;
-                    if (frame->GetStatus (result.GetOutputStream(), show_frame_info, show_source))
-                    {
-                        result.SetStatus (eReturnStatusSuccessFinishResult);
-                        return result.Succeeded();
-                    }
+                    else
+                        frame_idx = num_frames - 1;
                 }
             }
-            result.AppendErrorWithFormat ("Frame index (%u) out of range.\n", frame_idx);
         }
-        else
+        else 
         {
-            result.AppendError ("no current thread");
+            if (command.GetArgumentCount() == 1)
+            {
+                const char *frame_idx_cstr = command.GetArgumentAtIndex(0);
+                frame_idx = Args::StringToUInt32 (frame_idx_cstr, UINT32_MAX, 0);
+            }
+            else if (command.GetArgumentCount() == 0)
+            {
+                frame_idx = thread->GetSelectedFrameIndex ();
+                if (frame_idx == UINT32_MAX)
+                {
+                    frame_idx = 0;
+                }
+            }
+            else
+            {
+                result.AppendError ("invalid arguments.\n");
+                m_options.GenerateOptionUsage (result.GetErrorStream(), this);
+            }
         }
+
+        const bool broadcast = true;
+        bool success = thread->SetSelectedFrameByIndex (frame_idx, broadcast);
+        if (success)
+        {
+            m_exe_ctx.SetFrameSP(thread->GetSelectedFrame ());
+            StackFrame *frame = m_exe_ctx.GetFramePtr();
+            if (frame)
+            {
+                bool already_shown = false;
+                SymbolContext frame_sc(frame->GetSymbolContext(eSymbolContextLineEntry));
+                if (m_interpreter.GetDebugger().GetUseExternalEditor() && frame_sc.line_entry.file && frame_sc.line_entry.line != 0)
+                {
+                    already_shown = Host::OpenFileInExternalEditor (frame_sc.line_entry.file, frame_sc.line_entry.line);
+                }
+
+                bool show_frame_info = true;
+                bool show_source = !already_shown;
+                if (frame->GetStatus (result.GetOutputStream(), show_frame_info, show_source))
+                {
+                    result.SetStatus (eReturnStatusSuccessFinishResult);
+                    return result.Succeeded();
+                }
+            }
+        }
+        result.AppendErrorWithFormat ("Frame index (%u) out of range.\n", frame_idx);
         result.SetStatus (eReturnStatusFailed);
         return false;
     }
@@ -331,7 +319,10 @@
                              "Children of aggregate variables can be specified such as "
                              "'var->child.x'.",
                              NULL,
-                             eFlagProcessMustBeLaunched | eFlagProcessMustBePaused),
+                             eFlagRequiresFrame |
+                             eFlagTryTargetAPILock |
+                             eFlagProcessMustBeLaunched |
+                             eFlagProcessMustBePaused),
         m_option_group (interpreter),
         m_option_variable(true), // Include the frame specific options by passing "true"
         m_option_format (eFormatDefault),
@@ -372,14 +363,8 @@
     virtual bool
     DoExecute (Args& command, CommandReturnObject &result)
     {
-        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 view frame variables.");
-            result.SetStatus (eReturnStatusFailed);
-            return false;
-        }
+        // No need to check "frame" for validity as eFlagRequiresFrame ensures it is valid
+        StackFrame *frame = m_exe_ctx.GetFramePtr();
 
         Stream &s = result.GetOutputStream();