<commit_before>#ifndef MJOLNIR_CORE_CONSTRAINT_FORCE_FIELD_HPP
#define MJOLNIR_CORE_CONSTRAINT_FORCE_FIELD_HPP
#include <mjolnir/core/System.hpp>
#include <mjolnir/core/SimulatorTraits.hpp>
#include <mjolnir/util/logger.hpp>

namespace mjolnir
{

template<typename traitsT>
class ConstraintForceField
{

// Constraint class for g-BAOAB Langevin integrator developed by the following papers
// Leimkuhler B., Matthews C., Proc. R. Soc. A Math. Phys. Eng. Sci. (2016)
  public:
    using traits_type          = traitsT;
    using system_type          = System<traits_type>;
    using real_type            = typename traits_type::real_type;
    using topology_type        = typename system_type::topology_type;
    using connection_kind_type = typename topology_type::connection_kind_type;

    using indices_v0_pair_type = std::pair<std::array<std::size_t, 2>, real_type>;
    using container_type       = std::vector<indices_v0_pair_type>;

  public:

    ConstraintForceField()  = default;
    ConstraintForceField(const connection_kind_type kind,
                         const container_type&& constraints,
                         const std::size_t      max_iteration,
                         const real_type        tolerance)
        : max_iteration_(max_iteration), tolerance_(tolerance), kind_(kind),
          constraints_(std::move(constraints))
    {}
    ~ConstraintForceField() = default;
    ConstraintForceField(ConstraintForceField&&)            = default;
    ConstraintForceField& operator=(ConstraintForceField&&) = default;
    ConstraintForceField(const ConstraintForceField& other) = default;

    void write_topology(typename system_type::topology_type& topol)
    {
        if(this->kind_.empty() || this->kind_ == "none") {return;}

        for(auto& idxc : this->constraints_)
        {
            const auto i = idxc.first[0];
            const auto j = idxc.first[1];
            topol.add_connection(i, j, this->kind_);
        }
        return;
    }

    std::size_t           max_iteration() const noexcept {return max_iteration_;}
    real_type             tolerance()     const noexcept {return tolerance_;}
    const container_type& constraints()   const noexcept {return constraints_;}

    bool                  empty()         const noexcept {return constraints_.empty();}

  private:
    std::size_t          max_iteration_;
    real_type            tolerance_;
    connection_kind_type kind_;

    container_type         constraints_;
};

#ifdef MJOLNIR_SEPARATE_BUILD
extern template class ConstraintForceField<SimulatorTraits<double, UnlimitedBoundary>>;
extern template class ConstraintForceField<SimulatorTraits<float,  UnlimitedBoundary>>;
extern template class ConstraintForceField<SimulatorTraits<double, CuboidalPeriodicBoundary>>;
extern template class ConstraintForceField<SimulatorTraits<float,  CuboidalPeriodicBoundary>>;
#endif

} // mjolnir
#endif /* MJOLNIR_GLOBAL_FORCE_FIELD */
<commit_msg>refactor: some style issues like extraneous spaces<commit_after>#ifndef MJOLNIR_CORE_CONSTRAINT_FORCE_FIELD_HPP
#define MJOLNIR_CORE_CONSTRAINT_FORCE_FIELD_HPP
#include <mjolnir/core/System.hpp>
#include <mjolnir/core/SimulatorTraits.hpp>
#include <mjolnir/util/logger.hpp>

namespace mjolnir
{

// Currently, it supports only one constraint.
// Constraint class for g-BAOAB Langevin integrator developed by the following papers
// Leimkuhler B., Matthews C., Proc. R. Soc. A Math. Phys. Eng. Sci. (2016)
template<typename traitsT>
class ConstraintForceField
{
  public:
    using traits_type          = traitsT;
    using system_type          = System<traits_type>;
    using real_type            = typename traits_type::real_type;
    using topology_type        = typename system_type::topology_type;
    using connection_kind_type = typename topology_type::connection_kind_type;

    using indices_type         = std::array<std::size_t, 2>;
    using indices_v0_pair_type = std::pair<indices_type, real_type>;
    using container_type       = std::vector<indices_v0_pair_type>;

  public:

    ConstraintForceField(const connection_kind_type kind,
                         const container_type&& constraints,
                         const std::size_t      max_iteration,
                         const real_type        tolerance)
        : max_iteration_(max_iteration), tolerance_(tolerance), kind_(kind),
          constraints_(std::move(constraints))
    {}
    ConstraintForceField()  = default;
    ~ConstraintForceField() = default;
    ConstraintForceField(const ConstraintForceField&) = default;
    ConstraintForceField(ConstraintForceField&&)      = default;
    ConstraintForceField& operator=(const ConstraintForceField&) = default;
    ConstraintForceField& operator=(ConstraintForceField&&)      = default;

    void write_topology(topology_type& topol) const
    {
        if(this->kind_.empty() || this->kind_ == "none") {return;}

        for(const auto& idxc : this->constraints_)
        {
            const auto i = idxc.first[0];
            const auto j = idxc.first[1];
            topol.add_connection(i, j, this->kind_);
        }
        return;
    }

    std::size_t           max_iteration() const noexcept {return max_iteration_;}
    real_type             tolerance()     const noexcept {return tolerance_;}
    container_type const& constraints()   const noexcept {return constraints_;}
    bool                  empty()         const noexcept {return constraints_.empty();}

  private:

    std::size_t          max_iteration_;
    real_type            tolerance_;
    connection_kind_type kind_;
    container_type       constraints_;
};

#ifdef MJOLNIR_SEPARATE_BUILD
extern template class ConstraintForceField<SimulatorTraits<double, UnlimitedBoundary>>;
extern template class ConstraintForceField<SimulatorTraits<float,  UnlimitedBoundary>>;
extern template class ConstraintForceField<SimulatorTraits<double, CuboidalPeriodicBoundary>>;
extern template class ConstraintForceField<SimulatorTraits<float,  CuboidalPeriodicBoundary>>;
#endif

} // mjolnir
#endif // MJOLNIR_CORE_CONSTRAINT_FORCE_FIELD_HPP
<|endoftext|>


<commit_before>#ifndef MJOLNIR_OMP_RANDOM_NUMBER_GENERATOR
#define MJOLNIR_OMP_RANDOM_NUMBER_GENERATOR
#include <mjolnir/util/logger.hpp>
#include <mjolnir/util/aligned_allocator.hpp>
#include <mjolnir/util/aligned_storage.hpp>
#include <mjolnir/core/RandomNumberGenerator.hpp>
#include <mjolnir/omp/OpenMPSimulatorTraits.hpp>

namespace mjolnir
{

template<typename realT, template<typename, typename> class boundaryT>
class RandomNumberGenerator<OpenMPSimulatorTraits<realT, boundaryT>>
{
  public:
    using traits_type     = OpenMPSimulatorTraits<realT, boundaryT>;
    using real_type       = typename traits_type::real_type;
    using coordinate_type = typename traits_type::coordinate_type;

    static constexpr std::size_t cache_alignment = 64;

    using rng_type = aligned_storage<std::mt19937, cache_alignment>;
    using nrm_type = aligned_storage<std::normal_distribution<real_type>,
                                     cache_alignment>;

  public:
    explicit RandomNumberGenerator(const std::uint32_t seed)
        : seed_(seed),
          rngs_(omp_get_max_threads()),
          nrms_(omp_get_max_threads(),
                nrm_type(std::normal_distribution<real_type>(0.0, 1.0)))
    {
        MJOLNIR_GET_DEFAULT_LOGGER();
        MJOLNIR_LOG_FUNCTION();
        std::seed_seq              sseq{seed};
        std::vector<std::uint32_t> buf(omp_get_max_threads());
        sseq.generate(buf.begin(), buf.end());
        for(std::size_t i=0, e=omp_get_max_threads(); i<e; ++i)
        {
            MJOLNIR_LOG_INFO("the ", i, "-th RNG is seeded by ", buf.at(i));
            rngs_.at(i).value.seed(buf.at(i));
        }
    }
    ~RandomNumberGenerator() = default;

    real_type uniform_real01()
    {
        auto& rng = this->rngs_.at(omp_get_thread_num()).value;
        return std::generate_canonical<
            real_type, std::numeric_limits<real_type>::digits>(rng);
    }
    real_type uniform_real(const real_type min, const real_type max)
    {
        return this->uniform_real01() * (max - min) + min;
    }

    real_type gaussian()
    {
        const std::size_t thread_id = omp_get_thread_num();
        auto& rng = this->rngs_.at(thread_id).value;
        auto& nrm = this->nrms_.at(thread_id).value;
        return nrm(rng);
    }
    real_type gaussian(const real_type mean, const real_type stddev)
    {
        const std::size_t thread_id = omp_get_thread_num();
        auto& rng = this->rngs_.at(thread_id).value;
        auto& nrm = this->nrms_.at(thread_id).value;
        return nrm(rng) * stddev + mean;
    }

  private:
    std::uint32_t seed_;

    std::vector<rng_type, aligned_allocator<rng_type>> rngs_;
    std::vector<nrm_type, aligned_allocator<nrm_type>> nrms_;
};

template<typename realT, template<typename, typename> class boundaryT>
constexpr std::size_t
RandomNumberGenerator<OpenMPSimulatorTraits<realT, boundaryT>>::cache_alignment;

#ifdef MJOLNIR_SEPARATE_BUILD
extern template class RandomNumberGenerator<OpenMPSimulatorTraits<double, UnlimitedBoundary>>;
extern template class RandomNumberGenerator<OpenMPSimulatorTraits<float,  UnlimitedBoundary>>;
extern template class RandomNumberGenerator<OpenMPSimulatorTraits<double, CuboidalPeriodicBoundary>>;
extern template class RandomNumberGenerator<OpenMPSimulatorTraits<float,  CuboidalPeriodicBoundary>>;
#endif

} // mjolnir
#endif /*MJOLNIR_CORE_RANDOM_NUMBER_GENERATOR*/
<commit_msg>feat: add save/load to RandomNumberGenerator<OMP><commit_after>#ifndef MJOLNIR_OMP_RANDOM_NUMBER_GENERATOR
#define MJOLNIR_OMP_RANDOM_NUMBER_GENERATOR
#include <mjolnir/util/logger.hpp>
#include <mjolnir/util/aligned_allocator.hpp>
#include <mjolnir/util/aligned_storage.hpp>
#include <mjolnir/core/RandomNumberGenerator.hpp>
#include <mjolnir/omp/OpenMPSimulatorTraits.hpp>

namespace mjolnir
{

template<typename realT, template<typename, typename> class boundaryT>
class RandomNumberGenerator<OpenMPSimulatorTraits<realT, boundaryT>>
{
  public:
    using traits_type     = OpenMPSimulatorTraits<realT, boundaryT>;
    using real_type       = typename traits_type::real_type;
    using coordinate_type = typename traits_type::coordinate_type;

    static constexpr std::size_t cache_alignment = 64;

    using rng_type = aligned_storage<std::mt19937, cache_alignment>;
    using nrm_type = aligned_storage<std::normal_distribution<real_type>,
                                     cache_alignment>;

  public:
    explicit RandomNumberGenerator(const std::uint32_t seed)
        : seed_(seed),
          rngs_(omp_get_max_threads()),
          nrms_(omp_get_max_threads(),
                nrm_type(std::normal_distribution<real_type>(0.0, 1.0)))
    {
        MJOLNIR_GET_DEFAULT_LOGGER();
        MJOLNIR_LOG_FUNCTION();
        std::seed_seq              sseq{seed};
        std::vector<std::uint32_t> buf(omp_get_max_threads());
        sseq.generate(buf.begin(), buf.end());
        for(std::size_t i=0, e=omp_get_max_threads(); i<e; ++i)
        {
            MJOLNIR_LOG_INFO("the ", i, "-th RNG is seeded by ", buf.at(i));
            rngs_.at(i).value.seed(buf.at(i));
        }
    }
    ~RandomNumberGenerator() = default;

    explicit RandomNumberGenerator(const std::string& internal_state)
        : rngs_(omp_get_max_threads()),
          nrms_(omp_get_max_threads(),
                nrm_type(std::normal_distribution<real_type>(0.0, 1.0)))
    {
        std::istringstream iss(internal_state);
        iss >> this->seed_;
        for(auto& rng : this->rngs_)
        {
            iss >> rng.value;
        }
        if(iss.fail())
        {
            throw_exception<std::runtime_error>("[error] mjolnir::"
                "RandomNumberGenerator<OMP>: parse error in ", internal_state);
        }
    }
    std::string internal_state() const
    {
        std::ostringstream oss;
        oss << this->seed_ << ' ';
        for(const auto& rng : this->rngs_)
        {
            oss << rng.value << ' ';
        }
        return oss.str();
    }

    real_type uniform_real01()
    {
        auto& rng = this->rngs_.at(omp_get_thread_num()).value;
        return std::generate_canonical<
            real_type, std::numeric_limits<real_type>::digits>(rng);
    }
    real_type uniform_real(const real_type min, const real_type max)
    {
        return this->uniform_real01() * (max - min) + min;
    }

    real_type gaussian()
    {
        const std::size_t thread_id = omp_get_thread_num();
        auto& rng = this->rngs_.at(thread_id).value;
        auto& nrm = this->nrms_.at(thread_id).value;
        return nrm(rng);
    }
    real_type gaussian(const real_type mean, const real_type stddev)
    {
        const std::size_t thread_id = omp_get_thread_num();
        auto& rng = this->rngs_.at(thread_id).value;
        auto& nrm = this->nrms_.at(thread_id).value;
        return nrm(rng) * stddev + mean;
    }

  private:
    std::uint32_t seed_;

    std::vector<rng_type, aligned_allocator<rng_type>> rngs_;
    std::vector<nrm_type, aligned_allocator<nrm_type>> nrms_;
};

template<typename realT, template<typename, typename> class boundaryT>
constexpr std::size_t
RandomNumberGenerator<OpenMPSimulatorTraits<realT, boundaryT>>::cache_alignment;

#ifdef MJOLNIR_SEPARATE_BUILD
extern template class RandomNumberGenerator<OpenMPSimulatorTraits<double, UnlimitedBoundary>>;
extern template class RandomNumberGenerator<OpenMPSimulatorTraits<float,  UnlimitedBoundary>>;
extern template class RandomNumberGenerator<OpenMPSimulatorTraits<double, CuboidalPeriodicBoundary>>;
extern template class RandomNumberGenerator<OpenMPSimulatorTraits<float,  CuboidalPeriodicBoundary>>;
#endif

} // mjolnir
#endif /*MJOLNIR_CORE_RANDOM_NUMBER_GENERATOR*/
<|endoftext|>


<commit_before>#pragma once

#include <thread>
#include <mutex>
#include <queue>
#include <atomic>
#include <functional>
#include <condition_variable>
#include <future>

#include <iostream>

using std::thread;
using std::atomic;
using std::mutex;
using std::condition_variable;
using std::unique_lock;
using std::lock_guard;

using std::queue;
using std::function;
using std::bind;

class async_queue {
    thread queue_thread;
    queue<function<void()>> work_queue;
    atomic<bool> done;
    mutex queue_mutex;
    mutex work_mutex;
    condition_variable cond;

    void queue_runner() {
        //std::cout << "Starting: " << std::this_thread::get_id() << std::endl;
        while (!done) {
            unique_lock<mutex> work_lock(work_mutex, std::defer_lock);
            function<void()> func;
            {
                unique_lock<mutex> lock(queue_mutex);
                cond.wait(lock, [this]() {
                        return work_queue.empty() == false || done;
                    });

                if(done) break;

                work_lock.lock();
                swap(func, work_queue.front());
                work_queue.pop();
            }
            if (!func) {printf("bad function: %zu\n", work_queue.size());}
            else func();
        }
    }

public:
    /// \brief Enqueues a new function onto the work queue
    ///
    /// \param func A function which will be enqueued on the work queue
    /// \param args The argument of the funciton \p func
    template <typename F, typename... Args>
    void enqueue(const F func, Args... args) {
        if(std::this_thread::get_id() == queue_thread.get_id()) {
            func(args...);
        } else {
            auto no_arg_func = std::bind(func, std::forward<Args>(args)...);
            {
                lock_guard<mutex> lock(queue_mutex);
                work_queue.push(no_arg_func);
            }

            cond.notify_one();
        }
        return;
    }

    /// \brief Check if the current thread of execution is same as the queue thread
    ///
    /// \return A boolean indicating if current thread is same as the queue thread
    bool is_worker() const {
        return std::this_thread::get_id() == queue_thread.get_id();
    }

    /// \brief Blocks until all work has completed
    ///
    /// This function will block the calling thread until all of the queued
    /// functions have completed
    void sync() {
        //std::cout << "Syncing" << std::endl;
        std::promise<void> p;
        std::future<void> fut = p.get_future();
        auto f = [] (std::promise<void>& pr) {
            pr.set_value();
        };
        this->enqueue(f, ref(p));
        fut.wait();
        //std::cout << "Done Syncing" << std::endl;
    }

    /// \brief Creates a new work queue
    async_queue()
        : work_queue()
        , done(false) {
        thread tmp(&async_queue::queue_runner, this);
        swap(queue_thread, tmp);
    }

    ~async_queue() {
        done.store(true);
        cond.notify_one();
        queue_thread.join();
    }
};
<commit_msg>Remove usings from async_queue header<commit_after>
#pragma once
#include <atomic>
#include <condition_variable>
#include <functional>
#include <future>
#include <mutex>
#include <queue>
#include <thread>

class async_queue {
    std::thread queue_thread;
    std::queue<std::function<void()>> work_queue;
    std::atomic<bool> done;
    std::mutex queue_mutex;
    std::mutex work_mutex;
    std::condition_variable cond;

    void queue_runner() {
        //std::cout << "Starting: " << std::this_thread::get_id() << std::endl;
        while (!done) {
          std::unique_lock<std::mutex> work_lock(work_mutex, std::defer_lock);
          std::function<void()> func;
            {
              std::unique_lock<std::mutex> lock(queue_mutex);
                cond.wait(lock, [this]() {
                        return work_queue.empty() == false || done;
                    });

                if(done) break;

                work_lock.lock();
                swap(func, work_queue.front());
                work_queue.pop();
            }
            if (!func) {printf("bad function: %zu\n", work_queue.size());}
            else func();
        }
    }

public:
    /// \brief Enqueues a new function onto the work queue
    ///
    /// \param func A function which will be enqueued on the work queue
    /// \param args The argument of the funciton \p func
    template <typename F, typename... Args>
    void enqueue(const F func, Args... args) {
        if(std::this_thread::get_id() == queue_thread.get_id()) {
            func(args...);
        } else {
            auto no_arg_func = std::bind(func, std::forward<Args>(args)...);
            {
              std::lock_guard<std::mutex> lock(queue_mutex);
                work_queue.push(no_arg_func);
            }

            cond.notify_one();
        }
        return;
    }

    /// \brief Check if the current thread of execution is same as the queue thread
    ///
    /// \return A boolean indicating if current thread is same as the queue thread
    bool is_worker() const {
        return std::this_thread::get_id() == queue_thread.get_id();
    }

    /// \brief Blocks until all work has completed
    ///
    /// This function will block the calling thread until all of the queued
    /// functions have completed
    void sync() {
        //std::cout << "Syncing" << std::endl;
        std::promise<void> p;
        std::future<void> fut = p.get_future();
        auto f = [] (std::promise<void>& pr) {
            pr.set_value();
        };
        this->enqueue(f, ref(p));
        fut.wait();
        //std::cout << "Done Syncing" << std::endl;
    }

    /// \brief Creates a new work queue
    async_queue()
        : work_queue()
        , done(false) {
      std::thread tmp(&async_queue::queue_runner, this);
      std::swap(queue_thread, tmp);
    }

    ~async_queue() {
        done.store(true);
        cond.notify_one();
        queue_thread.join();
    }
};
<|endoftext|>


<commit_before>// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <iostream>
#include <string>

#include "base/macros.h"
#include "mojo/application/application_runner_chromium.h"
#include "mojo/public/c/system/main.h"
#include "mojo/public/cpp/application/application_connection.h"
#include "mojo/public/cpp/application/application_delegate.h"
#include "mojo/public/cpp/application/interface_factory.h"
#include "mojo/public/cpp/bindings/interface_ptr.h"
#include "mojo/services/console/public/interfaces/console.mojom.h"

namespace mojo {

class ConsoleImpl : public InterfaceImpl<Console> {
 public:
  explicit ConsoleImpl(const std::string& app_name) : app_name_(app_name) {}
  ~ConsoleImpl() override {}

  void ReadLine(const Callback<void(bool, String)>& callback) override {
    std::cout << "[" << app_name_ << "]> ";
    std::cout.flush();

    std::string line;
    std::getline(std::cin, line);

    // This will send an empty string on eof.
    String return_value = String::From(line);
    bool is_good = std::cin.good();
    if (!is_good)
      return_value = String::From("");

    callback.Run(is_good, return_value);
  }

  void PrintLines(Array<mojo::String> data,
                  const Callback<void(bool)>& callback) override {
    for (size_t i = 0; i < data.size(); ++i)
      std::cout << "[" << app_name_ << "] " << data[i].get() << std::endl;

    callback.Run(true);
  }

 private:
  const std::string app_name_;

  DISALLOW_COPY_AND_ASSIGN(ConsoleImpl);
};

class ConsoleDelegate : public ApplicationDelegate,
                        public InterfaceFactory<Console> {
 public:
  ConsoleDelegate() {}
  ~ConsoleDelegate() override {}

  // ApplicationDelegate implementation.
  bool ConfigureIncomingConnection(ApplicationConnection* connection) override {
    connection->AddService(this);
    return true;
  }

  // InterfaceFactory<Console> implementation.
  void Create(ApplicationConnection* connection,
              InterfaceRequest<Console> request) override {
    BindToRequest(new ConsoleImpl(connection->GetRemoteApplicationURL()),
                  &request);
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(ConsoleDelegate);
};

}  // namespace mojo

MojoResult MojoMain(MojoHandle shell_handle) {
  mojo::ApplicationRunnerChromium runner(new mojo::ConsoleDelegate);
  return runner.Run(shell_handle);
}
<commit_msg>Use StrongBinding instead of InterfaceImpl in console<commit_after>// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <iostream>
#include <string>

#include "base/macros.h"
#include "mojo/application/application_runner_chromium.h"
#include "mojo/public/c/system/main.h"
#include "mojo/public/cpp/application/application_connection.h"
#include "mojo/public/cpp/application/application_delegate.h"
#include "mojo/public/cpp/application/interface_factory.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
#include "mojo/services/console/public/interfaces/console.mojom.h"

namespace mojo {

class ConsoleImpl : public Console {
 public:
  ConsoleImpl(const std::string& app_name, InterfaceRequest<Console> request)
      : app_name_(app_name), binding_(this, request.Pass()) {}
  ~ConsoleImpl() override {}

  void ReadLine(const Callback<void(bool, String)>& callback) override {
    std::cout << "[" << app_name_ << "]> ";
    std::cout.flush();

    std::string line;
    std::getline(std::cin, line);

    // This will send an empty string on eof.
    String return_value = String::From(line);
    bool is_good = std::cin.good();
    if (!is_good)
      return_value = String::From("");

    callback.Run(is_good, return_value);
  }

  void PrintLines(Array<mojo::String> data,
                  const Callback<void(bool)>& callback) override {
    for (size_t i = 0; i < data.size(); ++i)
      std::cout << "[" << app_name_ << "] " << data[i].get() << std::endl;

    callback.Run(true);
  }

 private:
  const std::string app_name_;
  StrongBinding<Console> binding_;

  DISALLOW_COPY_AND_ASSIGN(ConsoleImpl);
};

class ConsoleDelegate : public ApplicationDelegate,
                        public InterfaceFactory<Console> {
 public:
  ConsoleDelegate() {}
  ~ConsoleDelegate() override {}

  // ApplicationDelegate implementation.
  bool ConfigureIncomingConnection(ApplicationConnection* connection) override {
    connection->AddService(this);
    return true;
  }

  // InterfaceFactory<Console> implementation.
  void Create(ApplicationConnection* connection,
              InterfaceRequest<Console> request) override {
    new ConsoleImpl(connection->GetRemoteApplicationURL(), request.Pass());
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(ConsoleDelegate);
};

}  // namespace mojo

MojoResult MojoMain(MojoHandle shell_handle) {
  mojo::ApplicationRunnerChromium runner(new mojo::ConsoleDelegate);
  return runner.Run(shell_handle);
}
<|endoftext|>


<commit_before>#include "mainwindow.h"
#include "ui_mainwindow.h"

#include <QDebug>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    qRegisterMetaType<MyParam>("MyParam"); // For (A)
    connect(this, SIGNAL(BlaBla(MyParam)), this, SLOT(on_blabla(MyParam)), Qt::QueuedConnection); // (A) queued signal and slot connections
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::on_pushButton_clicked()
{
    MyParam p;
    p.op = 13;
    p.x = 1;
    p.y = 9;
    emit BlaBla(p);
}

void MainWindow::on_blabla(MyParam param) // (A) if queued (otherwise NOT needed)
{
    qDebug() << "op:" << param.op ;
    qDebug() << "x: " << param.x ;
    qDebug() << "y: " << param.y ;
}

void MainWindow::ProcessVar(QVariant var)
{
    int tid = var.userType();

    const int id = qMetaTypeId<MyParam>();  // (B) otherwise compile error
    const int id2 = qMetaTypeId<My2>();
    if ( id == tid);
    {
        MyParam p = var.value<MyParam>();
        qDebug() << "In variant: " << p.op << ": " << p.x << ", " << p.y;
    }

    int l;
    l = 1; // set breakpoint here, for view id, id2 (in debugger)
}

void MainWindow::on_pushButton_2_clicked()
{
    MyParam p;
    p.op = 222;
    p.x = 21;
    p.y = 29;

    QVariant var;
    var.setValue(p);
    ProcessVar(var);  // (B) pass custom type in variant
}
<commit_msg>make const<commit_after>#include "mainwindow.h"
#include "ui_mainwindow.h"

#include <QDebug>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    qRegisterMetaType<MyParam>("MyParam"); // For (A)
    connect(this, SIGNAL(BlaBla(MyParam)), this, SLOT(on_blabla(MyParam)), Qt::QueuedConnection); // (A) queued signal and slot connections
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::on_pushButton_clicked()
{
    MyParam p;
    p.op = 13;
    p.x = 1;
    p.y = 9;
    emit BlaBla(p);
}

void MainWindow::on_blabla(MyParam param) // (A) if queued (otherwise NOT needed)
{
    qDebug() << "op:" << param.op ;
    qDebug() << "x: " << param.x ;
    qDebug() << "y: " << param.y ;
}

void MainWindow::ProcessVar(QVariant var)
{
    const int tid = var.userType();

    const int id = qMetaTypeId<MyParam>();  // (B) otherwise compile error
    const int id2 = qMetaTypeId<My2>();
    if ( id == tid);
    {
        MyParam p = var.value<MyParam>();
        qDebug() << "In variant: " << p.op << ": " << p.x << ", " << p.y;
    }

    int l;
    l = 1; // set breakpoint here, for view id, id2 (in debugger)
}

void MainWindow::on_pushButton_2_clicked()
{
    MyParam p;
    p.op = 222;
    p.x = 21;
    p.y = 29;

    QVariant var;
    var.setValue(p);
    ProcessVar(var);  // (B) pass custom type in variant
}
<|endoftext|>


<commit_before>/*
 * This file is part of accounts-ui
 *
 * Copyright (C) 2009-2010 Nokia Corporation.
 *
 * Contact: Alberto Mardegan <alberto.mardegan@nokia.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * version 2.1 as published by the Free Software Foundation.
 *
 * This library is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA
 */

//project
#include "accountsettingspage.h"
#include "provider-plugin-process.h"
#include "service-settings-widget.h"
#include "credentialdialog.h"
#include "service-model.h"
#include "sort-service-model.h"
#include "account-sync-handler.h"

//accounts-qt lib
#include <Accounts/Account>

//Meegotouch
#include <MContainer>
#include <MLayout>
#include <MLinearLayoutPolicy>
#include <MMessageBox>
#include <MLocale>
#include <MAction>
#include <MLabel>
#include <MGridLayoutPolicy>
#include <MButton>
#include <MContentItem>
#include <MApplicationIfProxy>
#include <MMessageBox>

//Qt
#include <QDebug>
#include <QTimer>
#include <QMultiMap>

//Accounts-Ui
#include "abstract-account-setup-context.h"

#define INFO_BANNER_TIMEOUT 3000

namespace AccountsUI {

class AccountSettingsPagePrivate
{
public:
    AccountSettingsPagePrivate()
            : context(0),
            service(0),
            account(0),
            showAllServices(0),
            usernameAndStatus(0),
            serviceSettingLayout(0),
            layoutServicePolicy(0),
            enableButton(0),
            syncHandler(0),
            changePasswordDialogStarted(false)
    {}

    ~AccountSettingsPagePrivate() {}

    AbstractAccountSetupContext *context;
    const Accounts::Service *service;
    Accounts::Account* account;
    QList<AbstractServiceSetupContext *> contexts;
    MAction *showAllServices;
    MContentItem *usernameAndStatus;
    QString serviceType;
    MLayout *serviceSettingLayout;
    MGridLayoutPolicy *layoutServicePolicy;
    MButton *enableButton;
    Accounts::ServiceList serviceList;
    QList<AbstractSetupContext*> abstractContexts;
    AccountSyncHandler *syncHandler;
    bool changePasswordDialogStarted;
    QMultiMap<QString, ServiceSettingsWidget*> settingsWidgets;
};

void AccountSettingsPage::setServicesToBeShown()
{
    Q_D(AccountSettingsPage);
    /* List the services available on the account and load all the respective
     * plugins. */
    int row = 0;
    //% "%1 Settings"
    setTitle(qtTrId("qtn_acc_ser_prof_set_title").arg(d->context->account()->providerName()));

    ServiceModel *serviceModel = new ServiceModel(d->context->account(), this);
    SortServiceModel *sortModel = new SortServiceModel(this);
    sortModel->setSourceModel(serviceModel);
    sortModel->setEnabledServices(d->context->account()->enabledServices());
    sortModel->sort(ServiceModel::ServiceNameColumn);

    QAbstractProxyModel *proxy = 0;
    // selecting the service type
    if (!d->context->serviceType().isEmpty()) {
        FilterTypeServiceModel *filterServiceModel = new FilterTypeServiceModel(this);
        filterServiceModel->setSourceModel(sortModel);
        filterServiceModel->setFilterFixedString(d->context->serviceType());
        proxy = filterServiceModel;
    } else
        proxy = sortModel;

    for (int i = 0; i < proxy->rowCount(); i++) {
        QModelIndex index = proxy->index(i, 0);
        const QVariant vServiceHelper = index.data(ServiceModel::ServiceHelperColumn);
        ServiceHelper *serviceHelper = vServiceHelper.value<ServiceHelper *>();
        AbstractServiceSetupContext *context =
            serviceHelper->serviceSetupContext(d->context, this);
        d->contexts.append(context);
    }

    /* iterate through the contexts we created for each service, and get the
     * UI widgets to embed */
    QMap<QString, bool> enabledServiceTypes;

    foreach (AbstractServiceSetupContext *context, d->contexts) {
        d->abstractContexts.append(context);
        d->service = context->service();
        const Accounts::Service *service = context->service();
        ServiceSettingsWidget *settingsWidget;
        if (d->serviceList.count() <= 1)
            settingsWidget = new ServiceSettingsWidget(context, this);
        else {
            d->account->selectService(service);

            bool enabled = false;
            if (d->account->enabled() &&
                !enabledServiceTypes.contains(service->serviceType())) {
                enabledServiceTypes.insert(service->serviceType(), true);
                enabled = true;
            }

            settingsWidget = new ServiceSettingsWidget(context,
                                                       this,
                                                       false,
                                                       false,
                                                       enabled);

            d->settingsWidgets.insertMulti(service->serviceType(), settingsWidget);
        }

        settingsWidget->setHeaderVisible(false);
        d->layoutServicePolicy->addItem(settingsWidget, row++, 0);
    }

    /*
     * no need in extra processing of any signals during content creation
     * */
    foreach (ServiceSettingsWidget *settingsWidget, d->settingsWidgets)
        connect (settingsWidget, SIGNAL(serviceButtonEnabled(const QString&)),
                 this, SLOT(disableSameServiceTypes(const QString&)));
}

AccountSettingsPage::AccountSettingsPage(AbstractAccountSetupContext *context)
        : MApplicationPage(),
          d_ptr(new AccountSettingsPagePrivate())
{
    Q_D(AccountSettingsPage);

    Q_ASSERT (context != NULL);
    d->context = context;
    d->account = d->context->account();
    d->abstractContexts.append(d->context);
    d->serviceType = d->context->serviceType();

    d->syncHandler = new AccountSyncHandler(this);
    connect(d->syncHandler, SIGNAL(syncStateChanged(const SyncState&)),
            this, SLOT(onSyncStateChanged(const SyncState&)));
    setStyleName("AccountSettingsPage");
}

AccountSettingsPage::~AccountSettingsPage()
{
    delete d_ptr;
}

void AccountSettingsPage::createContent()
{
    Q_D(AccountSettingsPage);

    //we need a central widget to get the right layout size under the menubar
    MWidget* centralWidget = new MWidget();
    MLayout* layout = new MLayout(centralWidget);
    MLinearLayoutPolicy *layoutPolicy = new MLinearLayoutPolicy(layout, Qt::Vertical);

    if (d->context) {
        QGraphicsLayoutItem *accountSettingsWidget = d->context->widget();
        if (accountSettingsWidget != 0) {
            layoutPolicy->addItem(accountSettingsWidget);
        } else {
            MWidget *upperWidget = new MWidget(this);
            MLayout *upperLayout = new MLayout(upperWidget);
            MLinearLayoutPolicy *upperLayoutPolicy = new MLinearLayoutPolicy(upperLayout, Qt::Vertical);

            MLayout *horizontalLayout = new MLayout();
            MLinearLayoutPolicy *horizontalLayoutPolicy = new MLinearLayoutPolicy(horizontalLayout, Qt::Horizontal);
            d->usernameAndStatus = new MContentItem(MContentItem::TwoTextLabels);
            horizontalLayoutPolicy->addItem(d->usernameAndStatus);
            d->serviceList = d->account->services();
            d->enableButton = new MButton();
            d->enableButton->setViewType(MButton::switchType);
            d->enableButton->setCheckable(true);
            d->account->selectService(NULL);
            if ( d->account->enabled())
                d->enableButton->setChecked(true);
            else
                d->enableButton->setChecked(false);
            connect(d->enableButton, SIGNAL(toggled(bool)), this, SLOT(enable(bool)));
            horizontalLayoutPolicy->addItem(d->enableButton);
            if (d->context->account()) {
                d->usernameAndStatus->setTitle(d->context->account()->displayName());
                d->context->account()->selectService(NULL);
                if (!d->context->account()->enabled()) {
                    //% "Disabled"
                    d->usernameAndStatus->setSubtitle(qtTrId("qtn_acc_disabled"));
                } else {
                    d->usernameAndStatus->setSubtitle(QString::null);
                }
            }
            upperLayoutPolicy->addItem(horizontalLayout);

            //% "Change password"
            MButton *changePassword = new MButton(qtTrId("qtn_acc_change_password"));
            upperLayoutPolicy->addItem(changePassword);
            connect(changePassword, SIGNAL(clicked()), this, SLOT(openChangePasswordDialog()));

            layoutPolicy->addItem(upperWidget);
        }
    }

    MWidget *serviceWidget = new MWidget(this);
    d->serviceSettingLayout = new MLayout(serviceWidget);
    d->layoutServicePolicy = new MGridLayoutPolicy(d->serviceSettingLayout);
    layoutPolicy->addItem(serviceWidget);

    /* Sets the service widgets and add it into the layout policy*/
    setServicesToBeShown();

    MContentItem *synchItem = new MContentItem(MContentItem::SingleTextLabel);
    //% "Synchronization"
    synchItem->setTitle(qtTrId("qtn_acc_sync"));
    layoutPolicy->addItem(synchItem);
    connect(synchItem, SIGNAL(clicked()),
            this, SLOT(openSynchUi()));

    layoutPolicy->addStretch();
    setCentralWidget(centralWidget);

    //% "Delete"
    MAction* action = new MAction(qtTrId("qtn_comm_command_delete"), this);
    action->setLocation(MAction::ApplicationMenuLocation);
    addAction(action);

    connect(action, SIGNAL(triggered()),
            this, SLOT(removeAccount()));

    if (d->context && !d->context->serviceType().isEmpty()) {
        QStringList serviceType;
        Accounts::ServiceList services = d->context->account()->services();
        foreach (Accounts::Service *service, services) {
            serviceType.append(service->serviceType());
        }
        serviceType.removeDuplicates();
        if (serviceType.count() > 1) {
            //% "All Services"
            d->showAllServices = new MAction(qtTrId("qtn_acc_settings_all_services"), this);
            d->showAllServices->setLocation(MAction::ApplicationMenuLocation);
            addAction(d->showAllServices);
            connect(d->showAllServices, SIGNAL(triggered()),
                    this, SLOT(showAllServices()));
        }
    }

    //Saving the settings on back button press
    connect(this, SIGNAL(backButtonClicked()),
            this, SLOT(saveSettings()));
}

const AbstractAccountSetupContext *AccountSettingsPage::context()
{
    Q_D(AccountSettingsPage);
    return d->context;
}

void AccountSettingsPage::enable(bool state)
{
    Q_D(AccountSettingsPage);

    if (d->serviceList.count() == 1) {
        d->account->selectService(d->serviceList.at(0));
        d->account->setEnabled(state);
    }

    d->context->account()->selectService(NULL);
    if (state) {
        if (d->usernameAndStatus)
            d->usernameAndStatus->setSubtitle(QString::null);
    } else {
        if (d->usernameAndStatus)
            //% "Disabled"
            d->usernameAndStatus->setSubtitle(qtTrId("qtn_acc_disabled"));
    }

    d->account->setEnabled(state);
}

void AccountSettingsPage::removeAccount()
{
    Q_D(AccountSettingsPage);
    //% "Delete %1 from your device?"
    QString dialogTitle =
        qtTrId("qtn_acc_remove_account").arg(d->context->account()->displayName());
    MMessageBox removeMBox(dialogTitle, M::YesButton | M::NoButton);
    removeMBox.setStyleName("RemoveDialog");

    if (removeMBox.exec() == M::YesButton) {
        d->context->account()->remove();
        d->context->account()->sync();
        ProviderPluginProcess::instance()->quit();
    }
}

void AccountSettingsPage::saveSettings()
{
    Q_D(AccountSettingsPage);
    setProgressIndicatorVisible(true);
    qDebug() << Q_FUNC_INFO;
    d->syncHandler->store(d->abstractContexts);
}

void AccountSettingsPage::onSyncStateChanged(const SyncState &state)
{
    qDebug() << Q_FUNC_INFO;

    Q_D(AccountSettingsPage);
    switch (state) {
        case NotValidated:
            qDebug() << Q_FUNC_INFO << "NotValidated";
            setProgressIndicatorVisible(false);
            break;
        case Validated:
            qDebug() << Q_FUNC_INFO << "Validated";
            d->syncHandler->store(d->abstractContexts);
            break;
        case NotStored:
            qDebug() << Q_FUNC_INFO << "NotStored";
            connect(d->context->account(), SIGNAL(synced()),
                    ProviderPluginProcess::instance(), SLOT(quit()));
            d->context->account()->sync();
            break;
        case Stored:
            qDebug() << Q_FUNC_INFO << "Stored";
            connect(d->context->account(), SIGNAL(synced()),
                    ProviderPluginProcess::instance(), SLOT(quit()));
            d->context->account()->sync();
            break;
        default:
            return;
    }
}

void AccountSettingsPage::openChangePasswordDialog()
{
    Q_D(AccountSettingsPage);
    //ignore multiple clicks
    if (d->changePasswordDialogStarted)
    {
        qDebug() << Q_FUNC_INFO << "Change password dialog is started already";
        return;
    }

    d->changePasswordDialogStarted = true;

    CredentialDialog *credentialDialog = new CredentialDialog(d->account->credentialsId());
    credentialDialog->setParent(this);

    if (!credentialDialog) {
        qCritical() << "Cannot create change password dialog";
        return;
    }
    connect (credentialDialog, SIGNAL(safeToDeleteMe(CredentialDialog*)),
             this, SLOT(deleteCredentialsDialog()));
    //% "Change Password"
    credentialDialog->setTitle(qtTrId("qtn_acc_login_title_change"));
    credentialDialog->exec();
}

void AccountSettingsPage::deleteCredentialsDialog()
{
    Q_D(AccountSettingsPage);
    d->changePasswordDialogStarted = false;
    CredentialDialog *credentialDialog;

    if (sender() != NULL &&
        (credentialDialog = qobject_cast<CredentialDialog *>(sender())) != NULL)
        credentialDialog->deleteLater();
}

void AccountSettingsPage::openSynchUi()
{
    setProgressIndicatorVisible(true);

    //Start Sync-Ui
    MApplicationIfProxy mApplicationIfProxy("com.nokia.syncui", this);

    if (mApplicationIfProxy.connection().isConnected()) {
        mApplicationIfProxy.launch();
    } else {
        MInfoBanner* infoBanner = new MInfoBanner();

        //% "Unable to launch Synchronisation"
        infoBanner->setBodyText(qtTrId("qtn_acc_synchronisation_err_undefined"));
        infoBanner->appear(MSceneWindow::DestroyWhenDone);
        QTimer::singleShot(INFO_BANNER_TIMEOUT, infoBanner, SLOT(disappear()));
    }
    setProgressIndicatorVisible(false);
}

void AccountSettingsPage::showAllServices()
{
    Q_D(AccountSettingsPage);
    d->serviceType = QLatin1String("");
    setServicesToBeShown();
    d->showAllServices->setVisible(false);
}

/*
 * The same serviceTypes cannot be enabled in meantime
 * */
void AccountSettingsPage::disableSameServiceTypes(const QString &serviceType)
{
    Q_D(AccountSettingsPage);
    qDebug() << Q_FUNC_INFO << __LINE__;
    if (!sender())
    {
        qCritical() << "disableSameServiceTypes() must be called via signaling";
        return;
    }

    if (d->settingsWidgets.count(serviceType) == 1)
        return;

    foreach (ServiceSettingsWidget *widget, d->settingsWidgets.values(serviceType)) {
        if (widget == sender())
            continue;

        widget->setServiceButtonEnable(false);
    }
}

} // namespace
<commit_msg>Fixed bug 198580 - Hidden service doesn't get visible after checking CDS<commit_after>/*
 * This file is part of accounts-ui
 *
 * Copyright (C) 2009-2010 Nokia Corporation.
 *
 * Contact: Alberto Mardegan <alberto.mardegan@nokia.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * version 2.1 as published by the Free Software Foundation.
 *
 * This library is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA
 */

//project
#include "accountsettingspage.h"
#include "provider-plugin-process.h"
#include "service-settings-widget.h"
#include "credentialdialog.h"
#include "service-model.h"
#include "sort-service-model.h"
#include "account-sync-handler.h"

//accounts-qt lib
#include <Accounts/Account>

//Meegotouch
#include <MContainer>
#include <MLayout>
#include <MLinearLayoutPolicy>
#include <MMessageBox>
#include <MLocale>
#include <MAction>
#include <MLabel>
#include <MGridLayoutPolicy>
#include <MButton>
#include <MContentItem>
#include <MApplicationIfProxy>
#include <MMessageBox>

//Qt
#include <QDebug>
#include <QTimer>
#include <QMultiMap>

//Accounts-Ui
#include "abstract-account-setup-context.h"

#define INFO_BANNER_TIMEOUT 3000

namespace AccountsUI {

class AccountSettingsPagePrivate
{
public:
    AccountSettingsPagePrivate()
            : context(0),
            service(0),
            account(0),
            showAllServices(0),
            usernameAndStatus(0),
            serviceSettingLayout(0),
            layoutServicePolicy(0),
            enableButton(0),
            syncHandler(0),
            changePasswordDialogStarted(false)
    {}

    ~AccountSettingsPagePrivate() {}

    AbstractAccountSetupContext *context;
    const Accounts::Service *service;
    Accounts::Account* account;
    QList<AbstractServiceSetupContext *> contexts;
    MAction *showAllServices;
    MContentItem *usernameAndStatus;
    QString serviceType;
    MLayout *serviceSettingLayout;
    MGridLayoutPolicy *layoutServicePolicy;
    MButton *enableButton;
    Accounts::ServiceList serviceList;
    QList<AbstractSetupContext*> abstractContexts;
    AccountSyncHandler *syncHandler;
    bool changePasswordDialogStarted;
    QMultiMap<QString, ServiceSettingsWidget*> settingsWidgets;
};

void AccountSettingsPage::setServicesToBeShown()
{
    Q_D(AccountSettingsPage);
    /* List the services available on the account and load all the respective
     * plugins. */
    int row = 0;
    //% "%1 Settings"
    setTitle(qtTrId("qtn_acc_ser_prof_set_title").arg(d->context->account()->providerName()));

    ServiceModel *serviceModel = new ServiceModel(d->context->account(), this);
    SortServiceModel *sortModel = new SortServiceModel(this);
    sortModel->setSourceModel(serviceModel);
    sortModel->setEnabledServices(d->context->account()->enabledServices());
    sortModel->sort(ServiceModel::ServiceNameColumn);

    QAbstractProxyModel *proxy = 0;
    // selecting the service type
    if (!d->context->serviceType().isEmpty()) {
        FilterTypeServiceModel *filterServiceModel = new FilterTypeServiceModel(this);
        filterServiceModel->setSourceModel(sortModel);
        filterServiceModel->setFilterFixedString(d->context->serviceType());
        proxy = filterServiceModel;
    } else
        proxy = sortModel;

    for (int i = 0; i < proxy->rowCount(); i++) {
        QModelIndex index = proxy->index(i, 0);
        const QVariant vServiceHelper = index.data(ServiceModel::ServiceHelperColumn);
        ServiceHelper *serviceHelper = vServiceHelper.value<ServiceHelper *>();
        AbstractServiceSetupContext *context =
            serviceHelper->serviceSetupContext(d->context, this);
        d->contexts.append(context);
    }

    /* iterate through the contexts we created for each service, and get the
     * UI widgets to embed */
    QMap<QString, bool> enabledServiceTypes;

    foreach (AbstractServiceSetupContext *context, d->contexts) {
        d->abstractContexts.append(context);
        d->service = context->service();
        const Accounts::Service *service = context->service();
        ServiceSettingsWidget *settingsWidget;

        d->account->selectService(service);

        bool enabled = false;
        if (d->account->enabled() &&
            !enabledServiceTypes.contains(service->serviceType())) {
            enabledServiceTypes.insert(service->serviceType(), true);
            enabled = true;
        }
        if (d->serviceList.count() > 1)
            settingsWidget = new ServiceSettingsWidget(context,
                                                   this,
                                                   false,
                                                   false,
                                                   enabled);
        else
            settingsWidget = new ServiceSettingsWidget(context,
                                                       this,
                                                       true,
                                                       true,
                                                       enabled);

        d->settingsWidgets.insertMulti(service->serviceType(), settingsWidget);

        settingsWidget->setHeaderVisible(false);
        d->layoutServicePolicy->addItem(settingsWidget, row++, 0);
    }

    /*
     * no need in extra processing of any signals during content creation
     * */
    foreach (ServiceSettingsWidget *settingsWidget, d->settingsWidgets)
        connect (settingsWidget, SIGNAL(serviceButtonEnabled(const QString&)),
                 this, SLOT(disableSameServiceTypes(const QString&)));
}

AccountSettingsPage::AccountSettingsPage(AbstractAccountSetupContext *context)
        : MApplicationPage(),
          d_ptr(new AccountSettingsPagePrivate())
{
    Q_D(AccountSettingsPage);

    Q_ASSERT (context != NULL);
    d->context = context;
    d->account = d->context->account();
    d->abstractContexts.append(d->context);
    d->serviceType = d->context->serviceType();

    d->syncHandler = new AccountSyncHandler(this);
    connect(d->syncHandler, SIGNAL(syncStateChanged(const SyncState&)),
            this, SLOT(onSyncStateChanged(const SyncState&)));
    setStyleName("AccountSettingsPage");
}

AccountSettingsPage::~AccountSettingsPage()
{
    delete d_ptr;
}

void AccountSettingsPage::createContent()
{
    Q_D(AccountSettingsPage);

    //we need a central widget to get the right layout size under the menubar
    MWidget* centralWidget = new MWidget();
    MLayout* layout = new MLayout(centralWidget);
    MLinearLayoutPolicy *layoutPolicy = new MLinearLayoutPolicy(layout, Qt::Vertical);

    if (d->context) {
        QGraphicsLayoutItem *accountSettingsWidget = d->context->widget();
        if (accountSettingsWidget != 0) {
            layoutPolicy->addItem(accountSettingsWidget);
        } else {
            MWidget *upperWidget = new MWidget(this);
            MLayout *upperLayout = new MLayout(upperWidget);
            MLinearLayoutPolicy *upperLayoutPolicy = new MLinearLayoutPolicy(upperLayout, Qt::Vertical);

            MLayout *horizontalLayout = new MLayout();
            MLinearLayoutPolicy *horizontalLayoutPolicy = new MLinearLayoutPolicy(horizontalLayout, Qt::Horizontal);
            d->usernameAndStatus = new MContentItem(MContentItem::TwoTextLabels);
            horizontalLayoutPolicy->addItem(d->usernameAndStatus);
            d->serviceList = d->account->services();
            d->enableButton = new MButton();
            d->enableButton->setViewType(MButton::switchType);
            d->enableButton->setCheckable(true);
            d->account->selectService(NULL);
            if ( d->account->enabled())
                d->enableButton->setChecked(true);
            else
                d->enableButton->setChecked(false);
            connect(d->enableButton, SIGNAL(toggled(bool)), this, SLOT(enable(bool)));
            horizontalLayoutPolicy->addItem(d->enableButton);
            if (d->context->account()) {
                d->usernameAndStatus->setTitle(d->context->account()->displayName());
                d->context->account()->selectService(NULL);
                if (!d->context->account()->enabled()) {
                    //% "Disabled"
                    d->usernameAndStatus->setSubtitle(qtTrId("qtn_acc_disabled"));
                } else {
                    d->usernameAndStatus->setSubtitle(QString::null);
                }
            }
            upperLayoutPolicy->addItem(horizontalLayout);

            //% "Change password"
            MButton *changePassword = new MButton(qtTrId("qtn_acc_change_password"));
            upperLayoutPolicy->addItem(changePassword);
            connect(changePassword, SIGNAL(clicked()), this, SLOT(openChangePasswordDialog()));

            layoutPolicy->addItem(upperWidget);
        }
    }

    MWidget *serviceWidget = new MWidget(this);
    d->serviceSettingLayout = new MLayout(serviceWidget);
    d->layoutServicePolicy = new MGridLayoutPolicy(d->serviceSettingLayout);
    layoutPolicy->addItem(serviceWidget);

    /* Sets the service widgets and add it into the layout policy*/
    setServicesToBeShown();

    MContentItem *synchItem = new MContentItem(MContentItem::SingleTextLabel);
    //% "Synchronization"
    synchItem->setTitle(qtTrId("qtn_acc_sync"));
    layoutPolicy->addItem(synchItem);
    connect(synchItem, SIGNAL(clicked()),
            this, SLOT(openSynchUi()));

    layoutPolicy->addStretch();
    setCentralWidget(centralWidget);

    //% "Delete"
    MAction* action = new MAction(qtTrId("qtn_comm_command_delete"), this);
    action->setLocation(MAction::ApplicationMenuLocation);
    addAction(action);

    connect(action, SIGNAL(triggered()),
            this, SLOT(removeAccount()));

    if (d->context && !d->context->serviceType().isEmpty()) {
        QStringList serviceType;
        Accounts::ServiceList services = d->context->account()->services();
        foreach (Accounts::Service *service, services) {
            serviceType.append(service->serviceType());
        }
        serviceType.removeDuplicates();
        if (serviceType.count() > 1) {
            //% "All Services"
            d->showAllServices = new MAction(qtTrId("qtn_acc_settings_all_services"), this);
            d->showAllServices->setLocation(MAction::ApplicationMenuLocation);
            addAction(d->showAllServices);
            connect(d->showAllServices, SIGNAL(triggered()),
                    this, SLOT(showAllServices()));
        }
    }

    //Saving the settings on back button press
    connect(this, SIGNAL(backButtonClicked()),
            this, SLOT(saveSettings()));
}

const AbstractAccountSetupContext *AccountSettingsPage::context()
{
    Q_D(AccountSettingsPage);
    return d->context;
}

void AccountSettingsPage::enable(bool state)
{
    Q_D(AccountSettingsPage);

    if (d->serviceList.count() == 1) {
        d->account->selectService(d->serviceList.at(0));
        d->account->setEnabled(state);
    }

    d->context->account()->selectService(NULL);
    if (state) {
        if (d->usernameAndStatus)
            d->usernameAndStatus->setSubtitle(QString::null);
    } else {
        if (d->usernameAndStatus)
            //% "Disabled"
            d->usernameAndStatus->setSubtitle(qtTrId("qtn_acc_disabled"));
    }

    d->account->setEnabled(state);
}

void AccountSettingsPage::removeAccount()
{
    Q_D(AccountSettingsPage);
    //% "Delete %1 from your device?"
    QString dialogTitle =
        qtTrId("qtn_acc_remove_account").arg(d->context->account()->displayName());
    MMessageBox removeMBox(dialogTitle, M::YesButton | M::NoButton);
    removeMBox.setStyleName("RemoveDialog");

    if (removeMBox.exec() == M::YesButton) {
        d->context->account()->remove();
        d->context->account()->sync();
        ProviderPluginProcess::instance()->quit();
    }
}

void AccountSettingsPage::saveSettings()
{
    Q_D(AccountSettingsPage);
    setProgressIndicatorVisible(true);
    qDebug() << Q_FUNC_INFO;
    d->syncHandler->store(d->abstractContexts);
}

void AccountSettingsPage::onSyncStateChanged(const SyncState &state)
{
    qDebug() << Q_FUNC_INFO;

    Q_D(AccountSettingsPage);
    switch (state) {
        case NotValidated:
            qDebug() << Q_FUNC_INFO << "NotValidated";
            setProgressIndicatorVisible(false);
            break;
        case Validated:
            qDebug() << Q_FUNC_INFO << "Validated";
            d->syncHandler->store(d->abstractContexts);
            break;
        case NotStored:
            qDebug() << Q_FUNC_INFO << "NotStored";
            connect(d->context->account(), SIGNAL(synced()),
                    ProviderPluginProcess::instance(), SLOT(quit()));
            d->context->account()->sync();
            break;
        case Stored:
            qDebug() << Q_FUNC_INFO << "Stored";
            connect(d->context->account(), SIGNAL(synced()),
                    ProviderPluginProcess::instance(), SLOT(quit()));
            d->context->account()->sync();
            break;
        default:
            return;
    }
}

void AccountSettingsPage::openChangePasswordDialog()
{
    Q_D(AccountSettingsPage);
    //ignore multiple clicks
    if (d->changePasswordDialogStarted)
    {
        qDebug() << Q_FUNC_INFO << "Change password dialog is started already";
        return;
    }

    d->changePasswordDialogStarted = true;

    CredentialDialog *credentialDialog = new CredentialDialog(d->account->credentialsId());
    credentialDialog->setParent(this);

    if (!credentialDialog) {
        qCritical() << "Cannot create change password dialog";
        return;
    }
    connect (credentialDialog, SIGNAL(safeToDeleteMe(CredentialDialog*)),
             this, SLOT(deleteCredentialsDialog()));
    //% "Change Password"
    credentialDialog->setTitle(qtTrId("qtn_acc_login_title_change"));
    credentialDialog->exec();
}

void AccountSettingsPage::deleteCredentialsDialog()
{
    Q_D(AccountSettingsPage);
    d->changePasswordDialogStarted = false;
    CredentialDialog *credentialDialog;

    if (sender() != NULL &&
        (credentialDialog = qobject_cast<CredentialDialog *>(sender())) != NULL)
        credentialDialog->deleteLater();
}

void AccountSettingsPage::openSynchUi()
{
    setProgressIndicatorVisible(true);

    //Start Sync-Ui
    MApplicationIfProxy mApplicationIfProxy("com.nokia.syncui", this);

    if (mApplicationIfProxy.connection().isConnected()) {
        mApplicationIfProxy.launch();
    } else {
        MInfoBanner* infoBanner = new MInfoBanner();

        //% "Unable to launch Synchronisation"
        infoBanner->setBodyText(qtTrId("qtn_acc_synchronisation_err_undefined"));
        infoBanner->appear(MSceneWindow::DestroyWhenDone);
        QTimer::singleShot(INFO_BANNER_TIMEOUT, infoBanner, SLOT(disappear()));
    }
    setProgressIndicatorVisible(false);
}

void AccountSettingsPage::showAllServices()
{
    Q_D(AccountSettingsPage);
    d->serviceType = QLatin1String("");
    setServicesToBeShown();
    d->showAllServices->setVisible(false);
}

/*
 * The same serviceTypes cannot be enabled in meantime
 * */
void AccountSettingsPage::disableSameServiceTypes(const QString &serviceType)
{
    Q_D(AccountSettingsPage);
    qDebug() << Q_FUNC_INFO << __LINE__;
    if (!sender())
    {
        qCritical() << "disableSameServiceTypes() must be called via signaling";
        return;
    }

    if (d->settingsWidgets.count(serviceType) == 1)
        return;

    foreach (ServiceSettingsWidget *widget, d->settingsWidgets.values(serviceType)) {
        if (widget == sender())
            continue;

        widget->setServiceButtonEnable(false);
    }
}

} // namespace
<|endoftext|>


<commit_before>//==- UnreachableCodeChecker.cpp - Generalized dead code checker -*- C++ -*-==//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// This file implements a generalized unreachable code checker using a
// path-sensitive analysis. We mark any path visited, and then walk the CFG as a
// post-analysis to determine what was never visited.
//
// A similar flow-sensitive only check exists in Analysis/ReachableCode.cpp
//===----------------------------------------------------------------------===//

#include "clang/AST/ParentMap.h"
#include "clang/Basic/Builtins.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Checker/PathSensitive/CheckerVisitor.h"
#include "clang/Checker/PathSensitive/ExplodedGraph.h"
#include "clang/Checker/PathSensitive/SVals.h"
#include "clang/Checker/PathSensitive/CheckerHelpers.h"
#include "clang/Checker/BugReporter/BugReporter.h"
#include "GRExprEngineExperimentalChecks.h"
#include "llvm/ADT/SmallPtrSet.h"

// The number of CFGBlock pointers we want to reserve memory for. This is used
// once for each function we analyze.
#define DEFAULT_CFGBLOCKS 256

using namespace clang;

namespace {
class UnreachableCodeChecker : public CheckerVisitor<UnreachableCodeChecker> {
public:
  static void *getTag();
  void VisitEndAnalysis(ExplodedGraph &G,
                        BugReporter &B,
                        GRExprEngine &Eng);
private:
  static inline const Stmt *getUnreachableStmt(const CFGBlock *CB);
  void FindUnreachableEntryPoints(const CFGBlock *CB);
  static bool isInvalidPath(const CFGBlock *CB, const ParentMap &PM);
  static inline bool isEmptyCFGBlock(const CFGBlock *CB);

  llvm::SmallSet<unsigned, DEFAULT_CFGBLOCKS> reachable;
  llvm::SmallSet<unsigned, DEFAULT_CFGBLOCKS> visited;
};
}

void *UnreachableCodeChecker::getTag() {
  static int x = 0;
  return &x;
}

void clang::RegisterUnreachableCodeChecker(GRExprEngine &Eng) {
  Eng.registerCheck(new UnreachableCodeChecker());
}

void UnreachableCodeChecker::VisitEndAnalysis(ExplodedGraph &G,
                                              BugReporter &B,
                                              GRExprEngine &Eng) {
  // Bail out if we didn't cover all paths
  if (Eng.hasWorkRemaining())
    return;

  CFG *C = 0;
  ParentMap *PM = 0;
  // Iterate over ExplodedGraph
  for (ExplodedGraph::node_iterator I = G.nodes_begin(), E = G.nodes_end();
      I != E; ++I) {
    const ProgramPoint &P = I->getLocation();
    const LocationContext *LC = P.getLocationContext();

    // Save the CFG if we don't have it already
    if (!C)
      C = LC->getAnalysisContext()->getUnoptimizedCFG();
    if (!PM)
      PM = &LC->getParentMap();

    if (const BlockEntrance *BE = dyn_cast<BlockEntrance>(&P)) {
      const CFGBlock *CB = BE->getBlock();
      reachable.insert(CB->getBlockID());
    }
  }

  // Bail out if we didn't get the CFG or the ParentMap.
  if (!C || !PM)
    return;

  ASTContext &Ctx = B.getContext();

  // Find CFGBlocks that were not covered by any node
  for (CFG::const_iterator I = C->begin(); I != C->end(); ++I) {
    const CFGBlock *CB = *I;
    // Check if the block is unreachable
    if (reachable.count(CB->getBlockID()))
      continue;

    // Check if the block is empty (an artificial block)
    if (isEmptyCFGBlock(CB))
      continue;

    // Find the entry points for this block
    FindUnreachableEntryPoints(CB);

    // This block may have been pruned; check if we still want to report it
    if (reachable.count(CB->getBlockID()))
      continue;

    // Check for false positives
    if (CB->size() > 0 && isInvalidPath(CB, *PM))
      continue;

    // Special case for __builtin_unreachable.
    // FIXME: This should be extended to include other unreachable markers,
    // such as llvm_unreachable.
    if (!CB->empty()) {
      CFGElement First = CB->front();
      if (CFGStmt S = First.getAs<CFGStmt>()) {
        if (const CallExpr *CE = dyn_cast<CallExpr>(S.getStmt())) {
          if (CE->isBuiltinCall(Ctx) == Builtin::BI__builtin_unreachable)
            continue;
        }
      }
    }

    // We found a block that wasn't covered - find the statement to report
    SourceRange SR;
    SourceLocation SL;
    if (const Stmt *S = getUnreachableStmt(CB)) {
      SR = S->getSourceRange();
      SL = S->getLocStart();
      if (SR.isInvalid() || SL.isInvalid())
        continue;
    }
    else
      continue;

    // Check if the SourceLocation is in a system header
    const SourceManager &SM = B.getSourceManager();
    if (SM.isInSystemHeader(SL) || SM.isInExternCSystemHeader(SL))
      continue;

    B.EmitBasicReport("Unreachable code", "Dead code", "This statement is never"
        " executed", SL, SR);
  }
}

// Recursively finds the entry point(s) for this dead CFGBlock.
void UnreachableCodeChecker::FindUnreachableEntryPoints(const CFGBlock *CB) {
  bool allPredecessorsReachable = true;

  visited.insert(CB->getBlockID());

  for (CFGBlock::const_pred_iterator I = CB->pred_begin(); I != CB->pred_end();
      ++I) {
    // Recurse over all unreachable blocks
    if (!reachable.count((*I)->getBlockID())) {
      // At least one predeccessor was unreachable
      allPredecessorsReachable = false;

      // Only visit the block once
      if (!visited.count((*I)->getBlockID()))
        FindUnreachableEntryPoints(*I);
    }
  }

  // If at least one predecessor is unreachable, mark this block as reachable
  // so we don't report this block.
  if (!allPredecessorsReachable) {
    reachable.insert(CB->getBlockID());
  }
}

// Find the Stmt* in a CFGBlock for reporting a warning
const Stmt *UnreachableCodeChecker::getUnreachableStmt(const CFGBlock *CB) {
  for (CFGBlock::const_iterator I = CB->begin(), E = CB->end(); I != E; ++I) {
    if (CFGStmt S = I->getAs<CFGStmt>())
      return S;
  }
  if (const Stmt *S = CB->getTerminator())
    return S;
  else
    return 0;
}

// Determines if the path to this CFGBlock contained an element that infers this
// block is a false positive. We assume that FindUnreachableEntryPoints has
// already marked only the entry points to any dead code, so we need only to
// find the condition that led to this block (the predecessor of this block.)
// There will never be more than one predecessor.
bool UnreachableCodeChecker::isInvalidPath(const CFGBlock *CB,
                                           const ParentMap &PM) {
  // We only expect a predecessor size of 0 or 1. If it is >1, then an external
  // condition has broken our assumption (for example, a sink being placed by
  // another check). In these cases, we choose not to report.
  if (CB->pred_size() > 1)
    return true;

  // If there are no predecessors, then this block is trivially unreachable
  if (CB->pred_size() == 0)
    return false;

  const CFGBlock *pred = *CB->pred_begin();

  // Get the predecessor block's terminator conditon
  const Stmt *cond = pred->getTerminatorCondition();

  //assert(cond && "CFGBlock's predecessor has a terminator condition");
  // The previous assertion is invalid in some cases (eg do/while). Leaving
  // reporting of these situations on at the moment to help triage these cases.
  if (!cond)
    return false;

  // Run each of the checks on the conditions
  if (containsMacro(cond) || containsEnum(cond)
      || containsStaticLocal(cond) || containsBuiltinOffsetOf(cond)
      || containsStmt<SizeOfAlignOfExpr>(cond))
    return true;

  return false;
}

// Returns true if the given CFGBlock is empty
bool UnreachableCodeChecker::isEmptyCFGBlock(const CFGBlock *CB) {
  return CB->getLabel() == 0       // No labels
      && CB->size() == 0           // No statements
      && CB->getTerminator() == 0; // No terminator
}
<commit_msg>UnreachableCodeChecker does not need to inherit from CheckerVisitor, only Checker. It does not use any AST Stmt hooks, only VisitEndAnalysis.<commit_after>//==- UnreachableCodeChecker.cpp - Generalized dead code checker -*- C++ -*-==//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// This file implements a generalized unreachable code checker using a
// path-sensitive analysis. We mark any path visited, and then walk the CFG as a
// post-analysis to determine what was never visited.
//
// A similar flow-sensitive only check exists in Analysis/ReachableCode.cpp
//===----------------------------------------------------------------------===//

#include "clang/AST/ParentMap.h"
#include "clang/Basic/Builtins.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Checker/PathSensitive/CheckerVisitor.h"
#include "clang/Checker/PathSensitive/ExplodedGraph.h"
#include "clang/Checker/PathSensitive/SVals.h"
#include "clang/Checker/PathSensitive/CheckerHelpers.h"
#include "clang/Checker/BugReporter/BugReporter.h"
#include "GRExprEngineExperimentalChecks.h"
#include "llvm/ADT/SmallPtrSet.h"

// The number of CFGBlock pointers we want to reserve memory for. This is used
// once for each function we analyze.
#define DEFAULT_CFGBLOCKS 256

using namespace clang;

namespace {
class UnreachableCodeChecker : public Checker {
public:
  static void *getTag();
  void VisitEndAnalysis(ExplodedGraph &G,
                        BugReporter &B,
                        GRExprEngine &Eng);
private:
  static inline const Stmt *getUnreachableStmt(const CFGBlock *CB);
  void FindUnreachableEntryPoints(const CFGBlock *CB);
  static bool isInvalidPath(const CFGBlock *CB, const ParentMap &PM);
  static inline bool isEmptyCFGBlock(const CFGBlock *CB);

  llvm::SmallSet<unsigned, DEFAULT_CFGBLOCKS> reachable;
  llvm::SmallSet<unsigned, DEFAULT_CFGBLOCKS> visited;
};
}

void *UnreachableCodeChecker::getTag() {
  static int x = 0;
  return &x;
}

void clang::RegisterUnreachableCodeChecker(GRExprEngine &Eng) {
  Eng.registerCheck(new UnreachableCodeChecker());
}

void UnreachableCodeChecker::VisitEndAnalysis(ExplodedGraph &G,
                                              BugReporter &B,
                                              GRExprEngine &Eng) {
  // Bail out if we didn't cover all paths
  if (Eng.hasWorkRemaining())
    return;

  CFG *C = 0;
  ParentMap *PM = 0;
  // Iterate over ExplodedGraph
  for (ExplodedGraph::node_iterator I = G.nodes_begin(), E = G.nodes_end();
      I != E; ++I) {
    const ProgramPoint &P = I->getLocation();
    const LocationContext *LC = P.getLocationContext();

    // Save the CFG if we don't have it already
    if (!C)
      C = LC->getAnalysisContext()->getUnoptimizedCFG();
    if (!PM)
      PM = &LC->getParentMap();

    if (const BlockEntrance *BE = dyn_cast<BlockEntrance>(&P)) {
      const CFGBlock *CB = BE->getBlock();
      reachable.insert(CB->getBlockID());
    }
  }

  // Bail out if we didn't get the CFG or the ParentMap.
  if (!C || !PM)
    return;

  ASTContext &Ctx = B.getContext();

  // Find CFGBlocks that were not covered by any node
  for (CFG::const_iterator I = C->begin(); I != C->end(); ++I) {
    const CFGBlock *CB = *I;
    // Check if the block is unreachable
    if (reachable.count(CB->getBlockID()))
      continue;

    // Check if the block is empty (an artificial block)
    if (isEmptyCFGBlock(CB))
      continue;

    // Find the entry points for this block
    FindUnreachableEntryPoints(CB);

    // This block may have been pruned; check if we still want to report it
    if (reachable.count(CB->getBlockID()))
      continue;

    // Check for false positives
    if (CB->size() > 0 && isInvalidPath(CB, *PM))
      continue;

    // Special case for __builtin_unreachable.
    // FIXME: This should be extended to include other unreachable markers,
    // such as llvm_unreachable.
    if (!CB->empty()) {
      CFGElement First = CB->front();
      if (CFGStmt S = First.getAs<CFGStmt>()) {
        if (const CallExpr *CE = dyn_cast<CallExpr>(S.getStmt())) {
          if (CE->isBuiltinCall(Ctx) == Builtin::BI__builtin_unreachable)
            continue;
        }
      }
    }

    // We found a block that wasn't covered - find the statement to report
    SourceRange SR;
    SourceLocation SL;
    if (const Stmt *S = getUnreachableStmt(CB)) {
      SR = S->getSourceRange();
      SL = S->getLocStart();
      if (SR.isInvalid() || SL.isInvalid())
        continue;
    }
    else
      continue;

    // Check if the SourceLocation is in a system header
    const SourceManager &SM = B.getSourceManager();
    if (SM.isInSystemHeader(SL) || SM.isInExternCSystemHeader(SL))
      continue;

    B.EmitBasicReport("Unreachable code", "Dead code", "This statement is never"
        " executed", SL, SR);
  }
}

// Recursively finds the entry point(s) for this dead CFGBlock.
void UnreachableCodeChecker::FindUnreachableEntryPoints(const CFGBlock *CB) {
  bool allPredecessorsReachable = true;

  visited.insert(CB->getBlockID());

  for (CFGBlock::const_pred_iterator I = CB->pred_begin(); I != CB->pred_end();
      ++I) {
    // Recurse over all unreachable blocks
    if (!reachable.count((*I)->getBlockID())) {
      // At least one predeccessor was unreachable
      allPredecessorsReachable = false;

      // Only visit the block once
      if (!visited.count((*I)->getBlockID()))
        FindUnreachableEntryPoints(*I);
    }
  }

  // If at least one predecessor is unreachable, mark this block as reachable
  // so we don't report this block.
  if (!allPredecessorsReachable) {
    reachable.insert(CB->getBlockID());
  }
}

// Find the Stmt* in a CFGBlock for reporting a warning
const Stmt *UnreachableCodeChecker::getUnreachableStmt(const CFGBlock *CB) {
  for (CFGBlock::const_iterator I = CB->begin(), E = CB->end(); I != E; ++I) {
    if (CFGStmt S = I->getAs<CFGStmt>())
      return S;
  }
  if (const Stmt *S = CB->getTerminator())
    return S;
  else
    return 0;
}

// Determines if the path to this CFGBlock contained an element that infers this
// block is a false positive. We assume that FindUnreachableEntryPoints has
// already marked only the entry points to any dead code, so we need only to
// find the condition that led to this block (the predecessor of this block.)
// There will never be more than one predecessor.
bool UnreachableCodeChecker::isInvalidPath(const CFGBlock *CB,
                                           const ParentMap &PM) {
  // We only expect a predecessor size of 0 or 1. If it is >1, then an external
  // condition has broken our assumption (for example, a sink being placed by
  // another check). In these cases, we choose not to report.
  if (CB->pred_size() > 1)
    return true;

  // If there are no predecessors, then this block is trivially unreachable
  if (CB->pred_size() == 0)
    return false;

  const CFGBlock *pred = *CB->pred_begin();

  // Get the predecessor block's terminator conditon
  const Stmt *cond = pred->getTerminatorCondition();

  //assert(cond && "CFGBlock's predecessor has a terminator condition");
  // The previous assertion is invalid in some cases (eg do/while). Leaving
  // reporting of these situations on at the moment to help triage these cases.
  if (!cond)
    return false;

  // Run each of the checks on the conditions
  if (containsMacro(cond) || containsEnum(cond)
      || containsStaticLocal(cond) || containsBuiltinOffsetOf(cond)
      || containsStmt<SizeOfAlignOfExpr>(cond))
    return true;

  return false;
}

// Returns true if the given CFGBlock is empty
bool UnreachableCodeChecker::isEmptyCFGBlock(const CFGBlock *CB) {
  return CB->getLabel() == 0       // No labels
      && CB->size() == 0           // No statements
      && CB->getTerminator() == 0; // No terminator
}
<|endoftext|>


<commit_before>#ifndef LIB_DRAW_VIEW_HPP
#define LIB_DRAW_VIEW_HPP

#include <lib/include/types.hpp>

namespace lib
{
	namespace draw
	{
		class Camera
		{
		public:
			explicit Camera() {}
			explicit Camera(const Rectf32 &rectangle) : m_target{ rectangle } {}
			inline const Rectf32 &target() const { return m_target; }
			inline Rectf32 &target() { return m_target; }
			inline void setSize(const vector2df &size)
			{
				m_target.width = size.x;
				m_target.height = size.y;
			}

		private:
			Rectf32 m_target;
		};
	}
}

#endif
<commit_msg>Added helpful function<commit_after>#ifndef LIB_DRAW_VIEW_HPP
#define LIB_DRAW_VIEW_HPP

#include <lib/include/types.hpp>

namespace lib
{
	namespace draw
	{
		class Camera
		{
		public:
			explicit Camera() {}
			explicit Camera(const Rectf32 &rectangle) : m_target{ rectangle } {}
			inline const Rectf32 &target() const { return m_target; }
			inline void setSize(const vector2df &size)
			{
				m_target.width = size.x;
				m_target.height = size.y;
			}

		private:
			Rectf32 m_target;
		};
	}
}

#endif
<|endoftext|>


<commit_before>//===- MachineCopyPropagation.cpp - Machine Copy Propagation Pass ---------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This is an extremely simple MachineInstr-level copy propagation pass.
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "codegen-cp"
#include "llvm/CodeGen/Passes.h"
#include "llvm/Pass.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/Target/TargetRegisterInfo.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
using namespace llvm;

STATISTIC(NumDeletes, "Number of dead copies deleted");

namespace {
  class MachineCopyPropagation : public MachineFunctionPass {
    const TargetRegisterInfo *TRI;
    MachineRegisterInfo *MRI;

  public:
    static char ID; // Pass identification, replacement for typeid
    MachineCopyPropagation() : MachineFunctionPass(ID) {
     initializeMachineCopyPropagationPass(*PassRegistry::getPassRegistry());
    }

    virtual bool runOnMachineFunction(MachineFunction &MF);

  private:
    typedef SmallVector<unsigned, 4> DestList;
    typedef DenseMap<unsigned, DestList> SourceMap;

    void SourceNoLongerAvailable(unsigned Reg,
                                 SourceMap &SrcMap,
                                 DenseMap<unsigned, MachineInstr*> &AvailCopyMap);
    bool CopyPropagateBlock(MachineBasicBlock &MBB);
  };
}
char MachineCopyPropagation::ID = 0;
char &llvm::MachineCopyPropagationID = MachineCopyPropagation::ID;

INITIALIZE_PASS(MachineCopyPropagation, "machine-cp",
                "Machine Copy Propagation Pass", false, false)

void
MachineCopyPropagation::SourceNoLongerAvailable(unsigned Reg,
                              SourceMap &SrcMap,
                              DenseMap<unsigned, MachineInstr*> &AvailCopyMap) {
  for (MCRegAliasIterator AI(Reg, TRI, true); AI.isValid(); ++AI) {
    SourceMap::iterator SI = SrcMap.find(*AI);
    if (SI != SrcMap.end()) {
      const DestList& Defs = SI->second;
      for (DestList::const_iterator I = Defs.begin(), E = Defs.end();
           I != E; ++I) {
        unsigned MappedDef = *I;
        // Source of copy is no longer available for propagation.
        if (AvailCopyMap.erase(MappedDef)) {
          for (MCSubRegIterator SR(MappedDef, TRI); SR.isValid(); ++SR)
            AvailCopyMap.erase(*SR);
        }
      }
    }
  }
}

static bool NoInterveningSideEffect(const MachineInstr *CopyMI,
                                    const MachineInstr *MI) {
  const MachineBasicBlock *MBB = CopyMI->getParent();
  if (MI->getParent() != MBB)
    return false;
  MachineBasicBlock::const_iterator I = CopyMI;
  MachineBasicBlock::const_iterator E = MBB->end();
  MachineBasicBlock::const_iterator E2 = MI;

  ++I;
  while (I != E && I != E2) {
    if (I->hasUnmodeledSideEffects() || I->isCall() ||
        I->isTerminator())
      return false;
    ++I;
  }
  return true;
}

/// isNopCopy - Return true if the specified copy is really a nop. That is
/// if the source of the copy is the same of the definition of the copy that
/// supplied the source. If the source of the copy is a sub-register than it
/// must check the sub-indices match. e.g.
/// ecx = mov eax
/// al  = mov cl
/// But not
/// ecx = mov eax
/// al  = mov ch
static bool isNopCopy(MachineInstr *CopyMI, unsigned Def, unsigned Src,
                      const TargetRegisterInfo *TRI) {
  unsigned SrcSrc = CopyMI->getOperand(1).getReg();
  if (Def == SrcSrc)
    return true;
  if (TRI->isSubRegister(SrcSrc, Def)) {
    unsigned SrcDef = CopyMI->getOperand(0).getReg();
    unsigned SubIdx = TRI->getSubRegIndex(SrcSrc, Def);
    if (!SubIdx)
      return false;
    return SubIdx == TRI->getSubRegIndex(SrcDef, Src);
  }

  return false;
}

bool MachineCopyPropagation::CopyPropagateBlock(MachineBasicBlock &MBB) {
  SmallSetVector<MachineInstr*, 8> MaybeDeadCopies;  // Candidates for deletion
  DenseMap<unsigned, MachineInstr*> AvailCopyMap;    // Def -> available copies map
  DenseMap<unsigned, MachineInstr*> CopyMap;         // Def -> copies map
  SourceMap SrcMap; // Src -> Def map

  bool Changed = false;
  for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end(); I != E; ) {
    MachineInstr *MI = &*I;
    ++I;

    if (MI->isCopy()) {
      unsigned Def = MI->getOperand(0).getReg();
      unsigned Src = MI->getOperand(1).getReg();

      if (TargetRegisterInfo::isVirtualRegister(Def) ||
          TargetRegisterInfo::isVirtualRegister(Src))
        report_fatal_error("MachineCopyPropagation should be run after"
                           " register allocation!");

      DenseMap<unsigned, MachineInstr*>::iterator CI = AvailCopyMap.find(Src);
      if (CI != AvailCopyMap.end()) {
        MachineInstr *CopyMI = CI->second;
        if (!MRI->isReserved(Def) &&
            (!MRI->isReserved(Src) || NoInterveningSideEffect(CopyMI, MI)) &&
            isNopCopy(CopyMI, Def, Src, TRI)) {
          // The two copies cancel out and the source of the first copy
          // hasn't been overridden, eliminate the second one. e.g.
          //  %ECX<def> = COPY %EAX<kill>
          //  ... nothing clobbered EAX.
          //  %EAX<def> = COPY %ECX
          // =>
          //  %ECX<def> = COPY %EAX
          //
          // Also avoid eliminating a copy from reserved registers unless the
          // definition is proven not clobbered. e.g.
          // %RSP<def> = COPY %RAX
          // CALL
          // %RAX<def> = COPY %RSP

          // Clear any kills of Def between CopyMI and MI. This extends the
          // live range.
          for (MachineBasicBlock::iterator I = CopyMI, E = MI; I != E; ++I)
            I->clearRegisterKills(Def, TRI);

          MI->eraseFromParent();
          Changed = true;
          ++NumDeletes;
          continue;
        }
      }

      // If Src is defined by a previous copy, it cannot be eliminated.
      for (MCRegAliasIterator AI(Src, TRI, true); AI.isValid(); ++AI) {
        CI = CopyMap.find(*AI);
        if (CI != CopyMap.end())
          MaybeDeadCopies.remove(CI->second);
      }

      // Copy is now a candidate for deletion.
      MaybeDeadCopies.insert(MI);

      // If 'Src' is previously source of another copy, then this earlier copy's
      // source is no longer available. e.g.
      // %xmm9<def> = copy %xmm2
      // ...
      // %xmm2<def> = copy %xmm0
      // ...
      // %xmm2<def> = copy %xmm9
      SourceNoLongerAvailable(Def, SrcMap, AvailCopyMap);

      // Remember Def is defined by the copy.
      // ... Make sure to clear the def maps of aliases first.
      for (MCRegAliasIterator AI(Def, TRI, false); AI.isValid(); ++AI) {
        CopyMap.erase(*AI);
        AvailCopyMap.erase(*AI);
      }
      CopyMap[Def] = MI;
      AvailCopyMap[Def] = MI;
      for (MCSubRegIterator SR(Def, TRI); SR.isValid(); ++SR) {
        CopyMap[*SR] = MI;
        AvailCopyMap[*SR] = MI;
      }

      // Remember source that's copied to Def. Once it's clobbered, then
      // it's no longer available for copy propagation.
      if (std::find(SrcMap[Src].begin(), SrcMap[Src].end(), Def) ==
          SrcMap[Src].end()) {
        SrcMap[Src].push_back(Def);
      }

      continue;
    }

    // Not a copy.
    SmallVector<unsigned, 2> Defs;
    int RegMaskOpNum = -1;
    for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
      MachineOperand &MO = MI->getOperand(i);
      if (MO.isRegMask())
        RegMaskOpNum = i;
      if (!MO.isReg())
        continue;
      unsigned Reg = MO.getReg();
      if (!Reg)
        continue;

      if (TargetRegisterInfo::isVirtualRegister(Reg))
        report_fatal_error("MachineCopyPropagation should be run after"
                           " register allocation!");

      if (MO.isDef()) {
        Defs.push_back(Reg);
        continue;
      }

      // If 'Reg' is defined by a copy, the copy is no longer a candidate
      // for elimination.
      for (MCRegAliasIterator AI(Reg, TRI, true); AI.isValid(); ++AI) {
        DenseMap<unsigned, MachineInstr*>::iterator CI = CopyMap.find(*AI);
        if (CI != CopyMap.end())
          MaybeDeadCopies.remove(CI->second);
      }
    }

    // The instruction has a register mask operand which means that it clobbers
    // a large set of registers.  It is possible to use the register mask to
    // prune the available copies, but treat it like a basic block boundary for
    // now.
    if (RegMaskOpNum >= 0) {
      // Erase any MaybeDeadCopies whose destination register is clobbered.
      const MachineOperand &MaskMO = MI->getOperand(RegMaskOpNum);
      for (SmallSetVector<MachineInstr*, 8>::iterator
           DI = MaybeDeadCopies.begin(), DE = MaybeDeadCopies.end();
           DI != DE; ++DI) {
        unsigned Reg = (*DI)->getOperand(0).getReg();
        if (MRI->isReserved(Reg) || !MaskMO.clobbersPhysReg(Reg))
          continue;
        (*DI)->eraseFromParent();
        Changed = true;
        ++NumDeletes;
      }

      // Clear all data structures as if we were beginning a new basic block.
      MaybeDeadCopies.clear();
      AvailCopyMap.clear();
      CopyMap.clear();
      SrcMap.clear();
      continue;
    }

    for (unsigned i = 0, e = Defs.size(); i != e; ++i) {
      unsigned Reg = Defs[i];

      // No longer defined by a copy.
      for (MCRegAliasIterator AI(Reg, TRI, true); AI.isValid(); ++AI) {
        CopyMap.erase(*AI);
        AvailCopyMap.erase(*AI);
      }

      // If 'Reg' is previously source of a copy, it is no longer available for
      // copy propagation.
      SourceNoLongerAvailable(Reg, SrcMap, AvailCopyMap);
    }
  }

  // If MBB doesn't have successors, delete the copies whose defs are not used.
  // If MBB does have successors, then conservative assume the defs are live-out
  // since we don't want to trust live-in lists.
  if (MBB.succ_empty()) {
    for (SmallSetVector<MachineInstr*, 8>::iterator
           DI = MaybeDeadCopies.begin(), DE = MaybeDeadCopies.end();
         DI != DE; ++DI) {
      if (!MRI->isReserved((*DI)->getOperand(0).getReg())) {
        (*DI)->eraseFromParent();
        Changed = true;
        ++NumDeletes;
      }
    }
  }

  return Changed;
}

bool MachineCopyPropagation::runOnMachineFunction(MachineFunction &MF) {
  bool Changed = false;

  TRI = MF.getTarget().getRegisterInfo();
  MRI = &MF.getRegInfo();

  for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I)
    Changed |= CopyPropagateBlock(*I);

  return Changed;
}
<commit_msg>Remove unneeded #include.<commit_after>//===- MachineCopyPropagation.cpp - Machine Copy Propagation Pass ---------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This is an extremely simple MachineInstr-level copy propagation pass.
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "codegen-cp"
#include "llvm/CodeGen/Passes.h"
#include "llvm/Pass.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/Target/TargetRegisterInfo.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
using namespace llvm;

STATISTIC(NumDeletes, "Number of dead copies deleted");

namespace {
  class MachineCopyPropagation : public MachineFunctionPass {
    const TargetRegisterInfo *TRI;
    MachineRegisterInfo *MRI;

  public:
    static char ID; // Pass identification, replacement for typeid
    MachineCopyPropagation() : MachineFunctionPass(ID) {
     initializeMachineCopyPropagationPass(*PassRegistry::getPassRegistry());
    }

    virtual bool runOnMachineFunction(MachineFunction &MF);

  private:
    typedef SmallVector<unsigned, 4> DestList;
    typedef DenseMap<unsigned, DestList> SourceMap;

    void SourceNoLongerAvailable(unsigned Reg,
                                 SourceMap &SrcMap,
                                 DenseMap<unsigned, MachineInstr*> &AvailCopyMap);
    bool CopyPropagateBlock(MachineBasicBlock &MBB);
  };
}
char MachineCopyPropagation::ID = 0;
char &llvm::MachineCopyPropagationID = MachineCopyPropagation::ID;

INITIALIZE_PASS(MachineCopyPropagation, "machine-cp",
                "Machine Copy Propagation Pass", false, false)

void
MachineCopyPropagation::SourceNoLongerAvailable(unsigned Reg,
                              SourceMap &SrcMap,
                              DenseMap<unsigned, MachineInstr*> &AvailCopyMap) {
  for (MCRegAliasIterator AI(Reg, TRI, true); AI.isValid(); ++AI) {
    SourceMap::iterator SI = SrcMap.find(*AI);
    if (SI != SrcMap.end()) {
      const DestList& Defs = SI->second;
      for (DestList::const_iterator I = Defs.begin(), E = Defs.end();
           I != E; ++I) {
        unsigned MappedDef = *I;
        // Source of copy is no longer available for propagation.
        if (AvailCopyMap.erase(MappedDef)) {
          for (MCSubRegIterator SR(MappedDef, TRI); SR.isValid(); ++SR)
            AvailCopyMap.erase(*SR);
        }
      }
    }
  }
}

static bool NoInterveningSideEffect(const MachineInstr *CopyMI,
                                    const MachineInstr *MI) {
  const MachineBasicBlock *MBB = CopyMI->getParent();
  if (MI->getParent() != MBB)
    return false;
  MachineBasicBlock::const_iterator I = CopyMI;
  MachineBasicBlock::const_iterator E = MBB->end();
  MachineBasicBlock::const_iterator E2 = MI;

  ++I;
  while (I != E && I != E2) {
    if (I->hasUnmodeledSideEffects() || I->isCall() ||
        I->isTerminator())
      return false;
    ++I;
  }
  return true;
}

/// isNopCopy - Return true if the specified copy is really a nop. That is
/// if the source of the copy is the same of the definition of the copy that
/// supplied the source. If the source of the copy is a sub-register than it
/// must check the sub-indices match. e.g.
/// ecx = mov eax
/// al  = mov cl
/// But not
/// ecx = mov eax
/// al  = mov ch
static bool isNopCopy(MachineInstr *CopyMI, unsigned Def, unsigned Src,
                      const TargetRegisterInfo *TRI) {
  unsigned SrcSrc = CopyMI->getOperand(1).getReg();
  if (Def == SrcSrc)
    return true;
  if (TRI->isSubRegister(SrcSrc, Def)) {
    unsigned SrcDef = CopyMI->getOperand(0).getReg();
    unsigned SubIdx = TRI->getSubRegIndex(SrcSrc, Def);
    if (!SubIdx)
      return false;
    return SubIdx == TRI->getSubRegIndex(SrcDef, Src);
  }

  return false;
}

bool MachineCopyPropagation::CopyPropagateBlock(MachineBasicBlock &MBB) {
  SmallSetVector<MachineInstr*, 8> MaybeDeadCopies;  // Candidates for deletion
  DenseMap<unsigned, MachineInstr*> AvailCopyMap;    // Def -> available copies map
  DenseMap<unsigned, MachineInstr*> CopyMap;         // Def -> copies map
  SourceMap SrcMap; // Src -> Def map

  bool Changed = false;
  for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end(); I != E; ) {
    MachineInstr *MI = &*I;
    ++I;

    if (MI->isCopy()) {
      unsigned Def = MI->getOperand(0).getReg();
      unsigned Src = MI->getOperand(1).getReg();

      if (TargetRegisterInfo::isVirtualRegister(Def) ||
          TargetRegisterInfo::isVirtualRegister(Src))
        report_fatal_error("MachineCopyPropagation should be run after"
                           " register allocation!");

      DenseMap<unsigned, MachineInstr*>::iterator CI = AvailCopyMap.find(Src);
      if (CI != AvailCopyMap.end()) {
        MachineInstr *CopyMI = CI->second;
        if (!MRI->isReserved(Def) &&
            (!MRI->isReserved(Src) || NoInterveningSideEffect(CopyMI, MI)) &&
            isNopCopy(CopyMI, Def, Src, TRI)) {
          // The two copies cancel out and the source of the first copy
          // hasn't been overridden, eliminate the second one. e.g.
          //  %ECX<def> = COPY %EAX<kill>
          //  ... nothing clobbered EAX.
          //  %EAX<def> = COPY %ECX
          // =>
          //  %ECX<def> = COPY %EAX
          //
          // Also avoid eliminating a copy from reserved registers unless the
          // definition is proven not clobbered. e.g.
          // %RSP<def> = COPY %RAX
          // CALL
          // %RAX<def> = COPY %RSP

          // Clear any kills of Def between CopyMI and MI. This extends the
          // live range.
          for (MachineBasicBlock::iterator I = CopyMI, E = MI; I != E; ++I)
            I->clearRegisterKills(Def, TRI);

          MI->eraseFromParent();
          Changed = true;
          ++NumDeletes;
          continue;
        }
      }

      // If Src is defined by a previous copy, it cannot be eliminated.
      for (MCRegAliasIterator AI(Src, TRI, true); AI.isValid(); ++AI) {
        CI = CopyMap.find(*AI);
        if (CI != CopyMap.end())
          MaybeDeadCopies.remove(CI->second);
      }

      // Copy is now a candidate for deletion.
      MaybeDeadCopies.insert(MI);

      // If 'Src' is previously source of another copy, then this earlier copy's
      // source is no longer available. e.g.
      // %xmm9<def> = copy %xmm2
      // ...
      // %xmm2<def> = copy %xmm0
      // ...
      // %xmm2<def> = copy %xmm9
      SourceNoLongerAvailable(Def, SrcMap, AvailCopyMap);

      // Remember Def is defined by the copy.
      // ... Make sure to clear the def maps of aliases first.
      for (MCRegAliasIterator AI(Def, TRI, false); AI.isValid(); ++AI) {
        CopyMap.erase(*AI);
        AvailCopyMap.erase(*AI);
      }
      CopyMap[Def] = MI;
      AvailCopyMap[Def] = MI;
      for (MCSubRegIterator SR(Def, TRI); SR.isValid(); ++SR) {
        CopyMap[*SR] = MI;
        AvailCopyMap[*SR] = MI;
      }

      // Remember source that's copied to Def. Once it's clobbered, then
      // it's no longer available for copy propagation.
      if (std::find(SrcMap[Src].begin(), SrcMap[Src].end(), Def) ==
          SrcMap[Src].end()) {
        SrcMap[Src].push_back(Def);
      }

      continue;
    }

    // Not a copy.
    SmallVector<unsigned, 2> Defs;
    int RegMaskOpNum = -1;
    for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
      MachineOperand &MO = MI->getOperand(i);
      if (MO.isRegMask())
        RegMaskOpNum = i;
      if (!MO.isReg())
        continue;
      unsigned Reg = MO.getReg();
      if (!Reg)
        continue;

      if (TargetRegisterInfo::isVirtualRegister(Reg))
        report_fatal_error("MachineCopyPropagation should be run after"
                           " register allocation!");

      if (MO.isDef()) {
        Defs.push_back(Reg);
        continue;
      }

      // If 'Reg' is defined by a copy, the copy is no longer a candidate
      // for elimination.
      for (MCRegAliasIterator AI(Reg, TRI, true); AI.isValid(); ++AI) {
        DenseMap<unsigned, MachineInstr*>::iterator CI = CopyMap.find(*AI);
        if (CI != CopyMap.end())
          MaybeDeadCopies.remove(CI->second);
      }
    }

    // The instruction has a register mask operand which means that it clobbers
    // a large set of registers.  It is possible to use the register mask to
    // prune the available copies, but treat it like a basic block boundary for
    // now.
    if (RegMaskOpNum >= 0) {
      // Erase any MaybeDeadCopies whose destination register is clobbered.
      const MachineOperand &MaskMO = MI->getOperand(RegMaskOpNum);
      for (SmallSetVector<MachineInstr*, 8>::iterator
           DI = MaybeDeadCopies.begin(), DE = MaybeDeadCopies.end();
           DI != DE; ++DI) {
        unsigned Reg = (*DI)->getOperand(0).getReg();
        if (MRI->isReserved(Reg) || !MaskMO.clobbersPhysReg(Reg))
          continue;
        (*DI)->eraseFromParent();
        Changed = true;
        ++NumDeletes;
      }

      // Clear all data structures as if we were beginning a new basic block.
      MaybeDeadCopies.clear();
      AvailCopyMap.clear();
      CopyMap.clear();
      SrcMap.clear();
      continue;
    }

    for (unsigned i = 0, e = Defs.size(); i != e; ++i) {
      unsigned Reg = Defs[i];

      // No longer defined by a copy.
      for (MCRegAliasIterator AI(Reg, TRI, true); AI.isValid(); ++AI) {
        CopyMap.erase(*AI);
        AvailCopyMap.erase(*AI);
      }

      // If 'Reg' is previously source of a copy, it is no longer available for
      // copy propagation.
      SourceNoLongerAvailable(Reg, SrcMap, AvailCopyMap);
    }
  }

  // If MBB doesn't have successors, delete the copies whose defs are not used.
  // If MBB does have successors, then conservative assume the defs are live-out
  // since we don't want to trust live-in lists.
  if (MBB.succ_empty()) {
    for (SmallSetVector<MachineInstr*, 8>::iterator
           DI = MaybeDeadCopies.begin(), DE = MaybeDeadCopies.end();
         DI != DE; ++DI) {
      if (!MRI->isReserved((*DI)->getOperand(0).getReg())) {
        (*DI)->eraseFromParent();
        Changed = true;
        ++NumDeletes;
      }
    }
  }

  return Changed;
}

bool MachineCopyPropagation::runOnMachineFunction(MachineFunction &MF) {
  bool Changed = false;

  TRI = MF.getTarget().getRegisterInfo();
  MRI = &MF.getRegInfo();

  for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I)
    Changed |= CopyPropagateBlock(*I);

  return Changed;
}
<|endoftext|>