//===-- ExecutionContext.h --------------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#ifndef liblldb_ExecutionContext_h_
#define liblldb_ExecutionContext_h_

// C Includes
// C++ Includes
// Other libraries and framework includes
// Project includes
#include "lldb/lldb-private.h"
#include "lldb/Target/StackID.h"
#include "lldb/Host/Mutex.h"

namespace lldb_private {

//===----------------------------------------------------------------------===//
/// Execution context objects refer to objects in the execution of the
/// program that is being debugged. The consist of one or more of the 
/// following objects: target, process, thread, and frame. Many objects
/// in the debugger need to track different executions contexts. For
/// example, a local function variable might have an execution context
/// that refers to a stack frame. A global or static variable might 
/// refer to a target since a stack frame isn't required in order to
/// evaluate a global or static variable (a process isn't necessarily
/// needed for a global variable since we might be able to read the
/// variable value from a data section in one of the object files in 
/// a target). There are two types of objects that hold onto execution
/// contexts: ExecutionContextRef and ExecutionContext. Both of these
/// objects are described below.
/// 
/// Not all objects in an ExectionContext objects will be valid. If you want
/// to refer strongly (ExectionContext) or weakly (ExectionContextRef) to
/// a process, then only the process and target references will be valid.
/// For threads, only the thread, process and target references will be
/// filled in. For frames, all of the objects will be filled in.
///
/// These classes are designed to be used as baton objects that get passed
/// to a wide variety of functions that require execution contexts.
//===----------------------------------------------------------------------===//

//----------------------------------------------------------------------
/// @class ExecutionContextRef ExecutionContext.h "lldb/Target/ExecutionContext.h"
/// @brief A class that holds a weak reference to an execution context.
///
/// ExecutionContextRef objects are designed to hold onto an execution
/// context that might change over time. For example, if an object wants
/// to refer to a stack frame, it should hold onto an ExecutionContextRef
/// to a frame object. The backing object that represents the stack frame
/// might change over time and instances of this object can track the logical
/// object that refers to a frame even if it does change.
///
/// These objects also don't keep execution objects around longer than they
/// should since they use weak pointers. For example if an object refers
/// to a stack frame and a stack frame is no longer in a thread, then a
/// ExecutionContextRef object that refers to that frame will not be able
/// to get a shared pointer to those objects since they are no longer around.
/// 
/// ExecutionContextRef objects can also be used as objects in classes
/// that want to track a "previous execution context". Since the weak 
/// references to the execution objects (target, process, thread and frame)
/// don't keep these objects around, they are safe to keep around. 
///
/// The general rule of thumb is all long lived objects that want to
/// refer to execution contexts should use ExecutionContextRef objects.
/// The ExecutionContext class is used to temporarily get shared 
/// pointers to any execution context objects that are still around
/// so they are guaranteed to exist during a function that requires the
/// objects. ExecutionContext objects should NOT be used for long term
/// storage since they will keep objects alive with extra shared pointer 
/// references to these  objects.
//----------------------------------------------------------------------
class ExecutionContextRef
{
public:
    //------------------------------------------------------------------
    /// Default Constructor.
    //------------------------------------------------------------------
    ExecutionContextRef();

    //------------------------------------------------------------------
    /// Copy Constructor.
    //------------------------------------------------------------------
    ExecutionContextRef (const ExecutionContextRef &rhs);

    //------------------------------------------------------------------
    /// Construct using an ExecutionContext object that might be nullptr.
    /// 
    /// If \a exe_ctx_ptr is valid, then make weak references to any
    /// valid objects in the ExecutionContext, otherwise no weak 
    /// references to any execution context objects will be made.
    //------------------------------------------------------------------
    ExecutionContextRef (const ExecutionContext *exe_ctx_ptr);
    
    //------------------------------------------------------------------
    /// Construct using an ExecutionContext object.
    /// 
    /// Make weak references to any valid objects in the ExecutionContext.
    //------------------------------------------------------------------
    ExecutionContextRef (const ExecutionContext &exe_ctx);

    //------------------------------------------------------------------
    /// Construct using the target and all the selected items inside of it
    /// (the process and its selected thread, and the thread's selected
    /// frame). If there is no selected thread, default to the first thread
    /// If there is no selected frame, default to the first frame. 
    //------------------------------------------------------------------
    ExecutionContextRef (Target *target, bool adopt_selected);

    //------------------------------------------------------------------
    /// Construct using an execution context scope.
    ///
    /// If the ExecutionContextScope object is valid and refers to a frame,
    /// make weak references too the frame, thread, process and target.
    /// If the ExecutionContextScope object is valid and refers to a thread,
    /// make weak references too the thread, process and target.
    /// If the ExecutionContextScope object is valid and refers to a process,
    /// make weak references too the process and target.
    /// If the ExecutionContextScope object is valid and refers to a target,
    /// make weak references too the target.
    //------------------------------------------------------------------
    ExecutionContextRef (ExecutionContextScope *exe_scope);

    //------------------------------------------------------------------
    /// Construct using an execution context scope.
    ///
    /// If the ExecutionContextScope object refers to a frame,
    /// make weak references too the frame, thread, process and target.
    /// If the ExecutionContextScope object refers to a thread,
    /// make weak references too the thread, process and target.
    /// If the ExecutionContextScope object refers to a process,
    /// make weak references too the process and target.
    /// If the ExecutionContextScope object refers to a target,
    /// make weak references too the target.
    //------------------------------------------------------------------
    ExecutionContextRef (ExecutionContextScope &exe_scope);

    ~ExecutionContextRef();

    //------------------------------------------------------------------
    /// Assignment operator
    /// 
    /// Copy all weak references in \a rhs.
    //------------------------------------------------------------------
    ExecutionContextRef &
    operator =(const ExecutionContextRef &rhs);

    //------------------------------------------------------------------
    /// Assignment operator from a ExecutionContext
    /// 
    /// Make weak references to any strongly referenced objects in \a exe_ctx.
    //------------------------------------------------------------------
    ExecutionContextRef &
    operator =(const ExecutionContext &exe_ctx);

    //------------------------------------------------------------------
    /// Clear the object's state.
    ///
    /// Sets the process and thread to nullptr, and the frame index to an
    /// invalid value.
    //------------------------------------------------------------------
    void
    Clear ();

    //------------------------------------------------------------------
    /// Set accessor that creates a weak reference to the target 
    /// referenced in \a target_sp.
    ///
    /// If \a target_sp is valid this object will create a weak 
    /// reference to that object, otherwise any previous target weak
    /// reference contained in this object will be reset.
    ///
    /// Only the weak reference to the target will be updated, no other
    /// weak references will be modified. If you want this execution
    /// context to make a weak reference to the target's process, use 
    /// the ExecutionContextRef::SetContext() functions.
    ///
    /// @see ExecutionContextRef::SetContext(const lldb::TargetSP &, bool)
    //------------------------------------------------------------------
    void
    SetTargetSP (const lldb::TargetSP &target_sp);
    
    //------------------------------------------------------------------
    /// Set accessor that creates a weak reference to the process 
    /// referenced in \a process_sp.
    ///
    /// If \a process_sp is valid this object will create a weak 
    /// reference to that object, otherwise any previous process weak
    /// reference contained in this object will be reset.
    ///
    /// Only the weak reference to the process will be updated, no other
    /// weak references will be modified. If you want this execution
    /// context to make a weak reference to the target, use the
    /// ExecutionContextRef::SetContext() functions.
    ///
    /// @see ExecutionContextRef::SetContext(const lldb::ProcessSP &)
    //------------------------------------------------------------------
    void
    SetProcessSP (const lldb::ProcessSP &process_sp);
    
    //------------------------------------------------------------------
    /// Set accessor that creates a weak reference to the thread 
    /// referenced in \a thread_sp.
    ///
    /// If \a thread_sp is valid this object will create a weak 
    /// reference to that object, otherwise any previous thread weak
    /// reference contained in this object will be reset.
    ///
    /// Only the weak reference to the thread will be updated, no other
    /// weak references will be modified. If you want this execution
    /// context to make a weak reference to the thread's process and 
    /// target, use the ExecutionContextRef::SetContext() functions.
    ///
    /// @see ExecutionContextRef::SetContext(const lldb::ThreadSP &)
    //------------------------------------------------------------------
    void
    SetThreadSP (const lldb::ThreadSP &thread_sp);
    
    //------------------------------------------------------------------
    /// Set accessor that creates a weak reference to the frame 
    /// referenced in \a frame_sp.
    ///
    /// If \a frame_sp is valid this object will create a weak 
    /// reference to that object, otherwise any previous frame weak
    /// reference contained in this object will be reset.
    ///
    /// Only the weak reference to the frame will be updated, no other
    /// weak references will be modified. If you want this execution
    /// context to make a weak reference to the frame's thread, process
    /// and target, use the ExecutionContextRef::SetContext() functions.
    ///
    /// @see ExecutionContextRef::SetContext(const lldb::StackFrameSP &)
    //------------------------------------------------------------------
    void
    SetFrameSP (const lldb::StackFrameSP &frame_sp);

    void
    SetTargetPtr (Target* target, bool adopt_selected);
    
    void
    SetProcessPtr (Process *process);
    
    void
    SetThreadPtr (Thread *thread);
    
    void
    SetFramePtr (StackFrame *frame);

    //------------------------------------------------------------------
    /// Get accessor that creates a strong reference from the weak target
    /// reference contained in this object.
    ///
    /// @returns
    ///     A shared pointer to a target that is not guaranteed to be valid.
    //------------------------------------------------------------------
    lldb::TargetSP
    GetTargetSP () const;
    
    //------------------------------------------------------------------
    /// Get accessor that creates a strong reference from the weak process
    /// reference contained in this object.
    ///
    /// @returns
    ///     A shared pointer to a process that is not guaranteed to be valid.
    //------------------------------------------------------------------
    lldb::ProcessSP
    GetProcessSP () const;
    
    //------------------------------------------------------------------
    /// Get accessor that creates a strong reference from the weak thread
    /// reference contained in this object.
    ///
    /// @returns
    ///     A shared pointer to a thread that is not guaranteed to be valid.
    //------------------------------------------------------------------
    lldb::ThreadSP
    GetThreadSP () const;
    
    //------------------------------------------------------------------
    /// Get accessor that creates a strong reference from the weak frame
    /// reference contained in this object.
    ///
    /// @returns
    ///     A shared pointer to a frame that is not guaranteed to be valid.
    //------------------------------------------------------------------
    lldb::StackFrameSP
    GetFrameSP () const;

    //------------------------------------------------------------------
    /// Create an ExecutionContext object from this object.
    ///
    /// Create strong references to any execution context objects that
    /// are still valid. Any of the returned shared pointers in the
    /// ExecutionContext objects is not guaranteed to be valid.
    /// @returns
    ///     An execution context object that has strong references to
    ///     any valid weak references in this object.
    //------------------------------------------------------------------
    ExecutionContext
    Lock (bool thread_and_frame_only_if_stopped) const;

    //------------------------------------------------------------------
    /// Returns true if this object has a weak reference to a thread.
    /// The return value is only an indication of whether this object has
    /// a weak reference and does not indicate whether the weak reference
    /// is valid or not.
    //------------------------------------------------------------------
    bool
    HasThreadRef () const
    {
        return m_tid != LLDB_INVALID_THREAD_ID;
    }

    //------------------------------------------------------------------
    /// Returns true if this object has a weak reference to a frame.
    /// The return value is only an indication of whether this object has
    /// a weak reference and does not indicate whether the weak reference
    /// is valid or not.
    //------------------------------------------------------------------
    bool
    HasFrameRef () const
    {
        return m_stack_id.IsValid();
    }

    void
    ClearThread ()
    {
        m_thread_wp.reset();
        m_tid = LLDB_INVALID_THREAD_ID;
    }
    
    void
    ClearFrame ()
    {
        m_stack_id.Clear();
    }

protected:
    //------------------------------------------------------------------
    // Member variables
    //------------------------------------------------------------------
    lldb::TargetWP m_target_wp;             ///< A weak reference to a target
    lldb::ProcessWP m_process_wp;           ///< A weak reference to a process
    mutable lldb::ThreadWP m_thread_wp;     ///< A weak reference to a thread
    lldb::tid_t m_tid;                      ///< The thread ID that this object refers to in case the backing object changes
    StackID m_stack_id;                     ///< The stack ID that this object refers to in case the backing object changes
};

//----------------------------------------------------------------------
/// @class ExecutionContext ExecutionContext.h "lldb/Target/ExecutionContext.h"
/// @brief A class that contains an execution context.
///
/// This baton object can be passed into any function that requires
/// a context that specifies a target, process, thread and frame.
/// These objects are designed to be used for short term execution
/// context object storage while a function might be trying to evaluate
/// something that requires a thread or frame. ExecutionContextRef 
/// objects can be used to initialize one of these objects to turn
/// the weak execution context object references to the target, process,
/// thread and frame into strong references (shared pointers) so that
/// functions can guarantee that these objects won't go away in the
/// middle of a function.
///
/// ExecutionContext objects should be used as short lived objects
/// (typically on the stack) in order to lock down an execution context
/// for local use and for passing down to other functions that also
/// require specific contexts. They should NOT be used for long term
/// storage, for long term storage use ExecutionContextRef objects.
//----------------------------------------------------------------------
class ExecutionContext
{
public:
    //------------------------------------------------------------------
    /// Default Constructor.
    //------------------------------------------------------------------
    ExecutionContext();

    //------------------------------------------------------------------
    // Copy constructor
    //------------------------------------------------------------------
    ExecutionContext (const ExecutionContext &rhs);

    //------------------------------------------------------------------
    // Adopt the target and optionally its current context.
    //------------------------------------------------------------------
    ExecutionContext (Target* t, bool fill_current_process_thread_frame = true);
    
    //------------------------------------------------------------------
    // Create execution contexts from shared pointers
    //------------------------------------------------------------------
    ExecutionContext (const lldb::TargetSP &target_sp, bool get_process);
    ExecutionContext (const lldb::ProcessSP &process_sp);
    ExecutionContext (const lldb::ThreadSP &thread_sp);
    ExecutionContext (const lldb::StackFrameSP &frame_sp);

    //------------------------------------------------------------------
    // Create execution contexts from weak pointers
    //------------------------------------------------------------------
    ExecutionContext (const lldb::TargetWP &target_wp, bool get_process);
    ExecutionContext (const lldb::ProcessWP &process_wp);
    ExecutionContext (const lldb::ThreadWP &thread_wp);
    ExecutionContext (const lldb::StackFrameWP &frame_wp);    
    ExecutionContext (const ExecutionContextRef &exe_ctx_ref);
    ExecutionContext (const ExecutionContextRef *exe_ctx_ref, bool thread_and_frame_only_if_stopped = false);
    
    // These two variants take in a locker, and grab the target, lock the API mutex into locker, then
    // fill in the rest of the shared pointers.
    ExecutionContext (const ExecutionContextRef &exe_ctx_ref, Mutex::Locker &locker);
    ExecutionContext (const ExecutionContextRef *exe_ctx_ref, Mutex::Locker &locker);
    //------------------------------------------------------------------
    // Create execution contexts from execution context scopes
    //------------------------------------------------------------------
    ExecutionContext (ExecutionContextScope *exe_scope);
    ExecutionContext (ExecutionContextScope &exe_scope);

    //------------------------------------------------------------------
    /// Construct with process, thread, and frame index.
    ///
    /// Initialize with process \a p, thread \a t, and frame index \a f.
    ///
    /// @param[in] process
    ///     The process for this execution context.
    ///
    /// @param[in] thread
    ///     The thread for this execution context.
    ///
    /// @param[in] frame
    ///     The frame index for this execution context.
    //------------------------------------------------------------------
    ExecutionContext(Process* process,
                     Thread *thread = nullptr,
                     StackFrame * frame = nullptr);


    ~ExecutionContext();

    ExecutionContext &
    operator =(const ExecutionContext &rhs);

    bool
    operator ==(const ExecutionContext &rhs) const;
    
    bool
    operator !=(const ExecutionContext &rhs) const;

    //------------------------------------------------------------------
    /// Clear the object's state.
    ///
    /// Sets the process and thread to nullptr, and the frame index to an
    /// invalid value.
    //------------------------------------------------------------------
    void
    Clear ();

    RegisterContext *
    GetRegisterContext () const;

    ExecutionContextScope *
    GetBestExecutionContextScope () const;

    uint32_t
    GetAddressByteSize() const;
    
    lldb::ByteOrder
    GetByteOrder() const;

    //------------------------------------------------------------------
    /// Returns a pointer to the target object.
    ///
    /// The returned pointer might be nullptr. Calling HasTargetScope(), 
    /// HasProcessScope(), HasThreadScope(), or HasFrameScope() 
    /// can help to pre-validate this pointer so that this accessor can
    /// freely be used without having to check for nullptr each time.
    ///
    /// @see ExecutionContext::HasTargetScope() const
    /// @see ExecutionContext::HasProcessScope() const
    /// @see ExecutionContext::HasThreadScope() const
    /// @see ExecutionContext::HasFrameScope() const
    //------------------------------------------------------------------
    Target *
    GetTargetPtr () const;

    //------------------------------------------------------------------
    /// Returns a pointer to the process object.
    ///
    /// The returned pointer might be nullptr. Calling HasProcessScope(), 
    /// HasThreadScope(), or HasFrameScope()  can help to pre-validate 
    /// this pointer so that this accessor can freely be used without
    /// having to check for nullptr each time.
    ///
    /// @see ExecutionContext::HasProcessScope() const
    /// @see ExecutionContext::HasThreadScope() const
    /// @see ExecutionContext::HasFrameScope() const
    //------------------------------------------------------------------
    Process *
    GetProcessPtr () const;

    //------------------------------------------------------------------
    /// Returns a pointer to the thread object.
    ///
    /// The returned pointer might be nullptr. Calling HasThreadScope() or
    /// HasFrameScope() can help to pre-validate this pointer so that 
    /// this accessor can freely be used without having to check for 
    /// nullptr each time.
    ///
    /// @see ExecutionContext::HasThreadScope() const
    /// @see ExecutionContext::HasFrameScope() const
    //------------------------------------------------------------------
    Thread *
    GetThreadPtr () const
    {
        return m_thread_sp.get();
    }
    
    //------------------------------------------------------------------
    /// Returns a pointer to the frame object.
    ///
    /// The returned pointer might be nullptr. Calling HasFrameScope(),
    /// can help to pre-validate this pointer so that this accessor can
    /// freely be used without having to check for nullptr each time.
    ///
    /// @see ExecutionContext::HasFrameScope() const
    //------------------------------------------------------------------
    StackFrame *
    GetFramePtr () const
    {
        return m_frame_sp.get();
    }

    //------------------------------------------------------------------
    /// Returns a reference to the target object.
    ///
    /// Clients should call HasTargetScope(), HasProcessScope(), 
    /// HasThreadScope(), or HasFrameScope() prior to calling this 
    /// function to ensure that this ExecutionContext object contains
    /// a valid target.
    ///
    /// @see ExecutionContext::HasTargetScope() const
    /// @see ExecutionContext::HasProcessScope() const
    /// @see ExecutionContext::HasThreadScope() const
    /// @see ExecutionContext::HasFrameScope() const
    //------------------------------------------------------------------
    Target &
    GetTargetRef () const;
    
    //------------------------------------------------------------------
    /// Returns a reference to the process object.
    ///
    /// Clients should call HasProcessScope(), HasThreadScope(), or 
    /// HasFrameScope() prior to calling this  function to ensure that 
    /// this ExecutionContext object contains a valid target.
    ///
    /// @see ExecutionContext::HasProcessScope() const
    /// @see ExecutionContext::HasThreadScope() const
    /// @see ExecutionContext::HasFrameScope() const
    //------------------------------------------------------------------
    Process &
    GetProcessRef () const;
    
    //------------------------------------------------------------------
    /// Returns a reference to the thread object.
    ///
    /// Clients should call HasThreadScope(), or  HasFrameScope() prior
    /// to calling this  function to ensure that  this ExecutionContext
    /// object contains a valid target.
    ///
    /// @see ExecutionContext::HasThreadScope() const
    /// @see ExecutionContext::HasFrameScope() const
    //------------------------------------------------------------------
    Thread &
    GetThreadRef () const;
    
    //------------------------------------------------------------------
    /// Returns a reference to the thread object.
    ///
    /// Clients should call HasFrameScope() prior to calling this 
    /// function to ensure that  this ExecutionContext object contains
    /// a valid target.
    ///
    /// @see ExecutionContext::HasFrameScope() const
    //------------------------------------------------------------------
    StackFrame &
    GetFrameRef () const;
    
    //------------------------------------------------------------------
    /// Get accessor to get the target shared pointer.
    ///
    /// The returned shared pointer is not guaranteed to be valid.
    //------------------------------------------------------------------
    const lldb::TargetSP &
    GetTargetSP () const
    {
        return m_target_sp;
    }
    
    //------------------------------------------------------------------
    /// Get accessor to get the process shared pointer.
    ///
    /// The returned shared pointer is not guaranteed to be valid.
    //------------------------------------------------------------------
    const lldb::ProcessSP &
    GetProcessSP () const
    {
        return m_process_sp;
    }

    //------------------------------------------------------------------
    /// Get accessor to get the thread shared pointer.
    ///
    /// The returned shared pointer is not guaranteed to be valid.
    //------------------------------------------------------------------
    const lldb::ThreadSP &
    GetThreadSP () const
    {
        return m_thread_sp;
    }
        
    //------------------------------------------------------------------
    /// Get accessor to get the frame shared pointer.
    ///
    /// The returned shared pointer is not guaranteed to be valid.
    //------------------------------------------------------------------
    const lldb::StackFrameSP &
    GetFrameSP () const
    {
        return m_frame_sp;
    }

    //------------------------------------------------------------------
    /// Set accessor to set only the target shared pointer.
    //------------------------------------------------------------------
    void
    SetTargetSP (const lldb::TargetSP &target_sp);
    
    //------------------------------------------------------------------
    /// Set accessor to set only the process shared pointer.
    //------------------------------------------------------------------
    void
    SetProcessSP (const lldb::ProcessSP &process_sp);
    
    //------------------------------------------------------------------
    /// Set accessor to set only the thread shared pointer.
    //------------------------------------------------------------------
    void
    SetThreadSP (const lldb::ThreadSP &thread_sp);
    
    //------------------------------------------------------------------
    /// Set accessor to set only the frame shared pointer.
    //------------------------------------------------------------------
    void
    SetFrameSP (const lldb::StackFrameSP &frame_sp);

    //------------------------------------------------------------------
    /// Set accessor to set only the target shared pointer from a target
    /// pointer.
    //------------------------------------------------------------------
    void
    SetTargetPtr (Target* target);
    
    //------------------------------------------------------------------
    /// Set accessor to set only the process shared pointer from a 
    /// process pointer.
    //------------------------------------------------------------------
    void
    SetProcessPtr (Process *process);
    
    //------------------------------------------------------------------
    /// Set accessor to set only the thread shared pointer from a thread
    /// pointer.
    //------------------------------------------------------------------
    void
    SetThreadPtr (Thread *thread);
    
    //------------------------------------------------------------------
    /// Set accessor to set only the frame shared pointer from a frame
    /// pointer.
    //------------------------------------------------------------------
    void
    SetFramePtr (StackFrame *frame);

    //------------------------------------------------------------------
    // Set the execution context using a target shared pointer. 
    //
    // If "target_sp" is valid, sets the target context to match and
    // if "get_process" is true, sets the process shared pointer if
    // the target currently has a process.
    //------------------------------------------------------------------
    void
    SetContext (const lldb::TargetSP &target_sp, bool get_process);
    
    //------------------------------------------------------------------
    // Set the execution context using a process shared pointer.
    //
    // If "process_sp" is valid, then set the process and target in this
    // context. Thread and frame contexts will be cleared.
    // If "process_sp" is not valid, all shared pointers are reset.
    //------------------------------------------------------------------
    void
    SetContext (const lldb::ProcessSP &process_sp);
    
    //------------------------------------------------------------------
    // Set the execution context using a thread shared pointer.
    //
    // If "thread_sp" is valid, then set the thread, process and target
    // in this context. The frame context will be cleared. 
    // If "thread_sp" is not valid, all shared pointers are reset.
    //------------------------------------------------------------------
    void
    SetContext (const lldb::ThreadSP &thread_sp);
    
    //------------------------------------------------------------------
    // Set the execution context using a frame shared pointer.
    //
    // If "frame_sp" is valid, then set the frame, thread, process and 
    // target in this context
    // If "frame_sp" is not valid, all shared pointers are reset.
    //------------------------------------------------------------------
    void
    SetContext (const lldb::StackFrameSP &frame_sp);

    //------------------------------------------------------------------
    /// Returns true the ExecutionContext object contains a valid 
    /// target.
    ///
    /// This function can be called after initializing an ExecutionContext
    /// object, and if it returns true, calls to GetTargetPtr() and 
    /// GetTargetRef() do not need to be checked for validity.
    //------------------------------------------------------------------
    bool
    HasTargetScope () const;

    //------------------------------------------------------------------
    /// Returns true the ExecutionContext object contains a valid 
    /// target and process.
    ///
    /// This function can be called after initializing an ExecutionContext
    /// object, and if it returns true, calls to GetTargetPtr() and 
    /// GetTargetRef(), GetProcessPtr(), and GetProcessRef(), do not
    /// need to be checked for validity.
    //------------------------------------------------------------------
    bool
    HasProcessScope () const;

    //------------------------------------------------------------------
    /// Returns true the ExecutionContext object contains a valid 
    /// target, process, and thread.
    ///
    /// This function can be called after initializing an ExecutionContext
    /// object, and if it returns true, calls to GetTargetPtr(), 
    /// GetTargetRef(), GetProcessPtr(), GetProcessRef(), GetThreadPtr(),
    /// and GetThreadRef() do not need to be checked for validity.
    //------------------------------------------------------------------
    bool
    HasThreadScope () const;
    
    //------------------------------------------------------------------
    /// Returns true the ExecutionContext object contains a valid 
    /// target, process, thread and frame.
    ///
    /// This function can be called after initializing an ExecutionContext
    /// object, and if it returns true, calls to GetTargetPtr(), 
    /// GetTargetRef(), GetProcessPtr(), GetProcessRef(), GetThreadPtr(),
    /// GetThreadRef(), GetFramePtr(), and GetFrameRef() do not need
    /// to be checked for validity.
    //------------------------------------------------------------------
    bool
    HasFrameScope () const;
    
protected:
    //------------------------------------------------------------------
    // Member variables
    //------------------------------------------------------------------
    lldb::TargetSP m_target_sp;     ///< The target that owns the process/thread/frame
    lldb::ProcessSP m_process_sp;   ///< The process that owns the thread/frame
    lldb::ThreadSP m_thread_sp;     ///< The thread that owns the frame
    lldb::StackFrameSP m_frame_sp;  ///< The stack frame in thread.
};

} // namespace lldb_private

#endif // liblldb_ExecutionContext_h_
