<commit_before>/*
* TLS Server
* (C) 2004-2011,2012 Jack Lloyd
*
* Released under the terms of the Botan license
*/

#include <botan/tls_server.h>
#include <botan/internal/tls_handshake_state.h>
#include <botan/internal/tls_messages.h>
#include <botan/internal/stl_util.h>
#include <botan/internal/assert.h>
#include <memory>

namespace Botan {

namespace TLS {

namespace {

bool check_for_resume(Session& session_info,
                      Session_Manager& session_manager,
                      Client_Hello* client_hello)
   {
   MemoryVector<byte> client_session_id = client_hello->session_id();

   if(client_session_id.empty()) // not resuming
      return false;

   // not found
   if(!session_manager.load_from_session_id(client_session_id, session_info))
      return false;

   // wrong version
   if(client_hello->version() != session_info.version())
      return false;

   // client didn't send original ciphersuite
   if(!value_exists(client_hello->ciphersuites(),
                    session_info.ciphersuite_code()))
      return false;

   // client didn't send original compression method
   if(!value_exists(client_hello->compression_methods(),
                    session_info.compression_method()))
      return false;

   // client sent a different SRP identity (!!!)
   if(client_hello->srp_identifier() != "")
      {
      if(client_hello->srp_identifier() != session_info.srp_identifier())
         return false;
      }

   // client sent a different SNI hostname (!!!)
   if(client_hello->sni_hostname() != "")
      {
      if(client_hello->sni_hostname() != session_info.sni_hostname())
         return false;
      }

   return true;
   }

std::map<std::string, std::vector<X509_Certificate> >
get_server_certs(const std::string& hostname,
                 Credentials_Manager& creds)
   {
   const char* cert_types[] = { "RSA", "DSA", "ECDSA", 0 };

   std::map<std::string, std::vector<X509_Certificate> > cert_chains;

   for(size_t i = 0; cert_types[i]; ++i)
      {
      std::vector<X509_Certificate> certs =
         creds.cert_chain_single_type(cert_types[i], "tls-server", hostname);

      if(!certs.empty())
         cert_chains[cert_types[i]] = certs;
      }

   return cert_chains;
   }

}

/*
* TLS Server Constructor
*/
Server::Server(std::tr1::function<void (const byte[], size_t)> output_fn,
               std::tr1::function<void (const byte[], size_t, Alert)> proc_fn,
               std::tr1::function<bool (const Session&)> handshake_fn,
               Session_Manager& session_manager,
               Credentials_Manager& creds,
               const Policy& policy,
               RandomNumberGenerator& rng,
               const std::vector<std::string>& next_protocols) :
   Channel(output_fn, proc_fn, handshake_fn),
   policy(policy),
   rng(rng),
   session_manager(session_manager),
   creds(creds),
   m_possible_protocols(next_protocols)
   {
   }

/*
* Send a hello request to the client
*/
void Server::renegotiate()
   {
   if(state)
      return; // currently in handshake

   state = new Handshake_State;
   state->set_expected_next(CLIENT_HELLO);
   Hello_Request hello_req(writer);
   }

void Server::alert_notify(const Alert& alert)
   {
   if(alert.type() == Alert::NO_RENEGOTIATION)
      {
      if(handshake_completed && state)
         {
         delete state;
         state = 0;
         }
      }
   }

/*
* Split up and process handshake messages
*/
void Server::read_handshake(byte rec_type,
                            const MemoryRegion<byte>& rec_buf)
   {
   if(rec_type == HANDSHAKE && !state)
      {
      state = new Handshake_State;
      state->set_expected_next(CLIENT_HELLO);
      }

   Channel::read_handshake(rec_type, rec_buf);
   }

/*
* Process a handshake message
*/
void Server::process_handshake_msg(Handshake_Type type,
                                   const MemoryRegion<byte>& contents)
   {
   if(state == 0)
      throw Unexpected_Message("Unexpected handshake message from client");

   state->confirm_transition_to(type);

   /*
   * The change cipher spec message isn't technically a handshake
   * message so it's not included in the hash. The finished and
   * certificate verify messages are verified based on the current
   * state of the hash *before* this message so we delay adding them
   * to the hash computation until we've processed them below.
   */
   if(type != HANDSHAKE_CCS && type != FINISHED && type != CERTIFICATE_VERIFY)
      {
      if(type == CLIENT_HELLO_SSLV2)
         state->hash.update(contents);
      else
         state->hash.update(type, contents);
      }

   if(type == CLIENT_HELLO || type == CLIENT_HELLO_SSLV2)
      {
      state->client_hello = new Client_Hello(contents, type);

      m_hostname = state->client_hello->sni_hostname();

      Protocol_Version client_version = state->client_hello->version();

      if(client_version < policy.min_version())
         throw TLS_Exception(Alert::PROTOCOL_VERSION,
                             "Client version is unacceptable by policy");

      if(client_version <= policy.pref_version())
         state->version = client_version;
      else
         state->version = policy.pref_version();

      secure_renegotiation.update(state->client_hello);

      writer.set_version(state->version);
      reader.set_version(state->version);

      Session session_info;
      const bool resuming = check_for_resume(session_info,
                                             session_manager,
                                             state->client_hello);

      if(resuming)
         {
         // resume session

         state->server_hello = new Server_Hello(
            writer,
            state->hash,
            session_info.session_id(),
            Protocol_Version(session_info.version()),
            session_info.ciphersuite_code(),
            session_info.compression_method(),
            session_info.fragment_size(),
            secure_renegotiation.supported(),
            secure_renegotiation.for_server_hello(),
            state->client_hello->next_protocol_notification(),
            m_possible_protocols,
            rng);

         if(session_info.fragment_size())
            {
            reader.set_maximum_fragment_size(session_info.fragment_size());
            writer.set_maximum_fragment_size(session_info.fragment_size());
            }

         state->suite = Ciphersuite::by_id(state->server_hello->ciphersuite());

         state->keys = Session_Keys(state, session_info.master_secret(), true);

         writer.send(CHANGE_CIPHER_SPEC, 1);

         writer.activate(SERVER, state->suite, state->keys,
                         state->server_hello->compression_method());

         state->server_finished = new Finished(writer, state, SERVER);

         if(!handshake_fn(session_info))
            session_manager.remove_entry(session_info.session_id());

         state->set_expected_next(HANDSHAKE_CCS);
         }
      else // new session
         {
         std::map<std::string, std::vector<X509_Certificate> > cert_chains;

         cert_chains = get_server_certs(m_hostname, creds);

         if(m_hostname != "" && cert_chains.empty())
            {
            send_alert(Alert(Alert::UNRECOGNIZED_NAME));
            cert_chains = get_server_certs("", creds);
            }

         std::vector<std::string> available_cert_types;

         for(std::map<std::string, std::vector<X509_Certificate> >::const_iterator i = cert_chains.begin();
             i != cert_chains.end(); ++i)
            {
            if(!i->second.empty())
               available_cert_types.push_back(i->first);
            }

         state->server_hello = new Server_Hello(
            writer,
            state->hash,
            state->version,
            *(state->client_hello),
            available_cert_types,
            policy,
            secure_renegotiation.supported(),
            secure_renegotiation.for_server_hello(),
            state->client_hello->next_protocol_notification(),
            m_possible_protocols,
            rng);

         if(state->client_hello->fragment_size())
            {
            reader.set_maximum_fragment_size(state->client_hello->fragment_size());
            writer.set_maximum_fragment_size(state->client_hello->fragment_size());
            }

         state->suite = Ciphersuite::by_id(state->server_hello->ciphersuite());

         const std::string sig_algo = state->suite.sig_algo();
         const std::string kex_algo = state->suite.kex_algo();

         if(sig_algo != "")
            {
            BOTAN_ASSERT(!cert_chains[sig_algo].empty(),
                         "Attempting to send empty certificate chain");

            state->server_certs = new Certificate(writer,
                                                  state->hash,
                                                  cert_chains[sig_algo]);
            }

         Private_Key* private_key = 0;

         if(kex_algo == "RSA" || sig_algo != "")
            {
            private_key = creds.private_key_for(state->server_certs->cert_chain()[0],
                                                "tls-server",
                                                m_hostname);

            if(!private_key)
               throw Internal_Error("No private key located for associated server cert");
            }

         if(kex_algo == "RSA")
            {
            state->server_rsa_kex_key = private_key;
            }
         else
            {
            state->server_kex =
               new Server_Key_Exchange(writer, state, policy, creds, rng, private_key);
            }

         std::vector<X509_Certificate> client_auth_CAs =
            creds.trusted_certificate_authorities("tls-server", m_hostname);

         if(!client_auth_CAs.empty() && state->suite.sig_algo() != "")
            {
            state->cert_req = new Certificate_Req(writer,
                                                  state->hash,
                                                  policy,
                                                  client_auth_CAs,
                                                  state->version);

            state->set_expected_next(CERTIFICATE);
            }

         secure_renegotiation.update(state->server_hello);

         /*
         * If the client doesn't have a cert they want to use they are
         * allowed to send either an empty cert message or proceed
         * directly to the client key exchange, so allow either case.
         */
         state->set_expected_next(CLIENT_KEX);

         state->server_hello_done = new Server_Hello_Done(writer, state->hash);
         }
      }
   else if(type == CERTIFICATE)
      {
      state->client_certs = new Certificate(contents);

      // Is this allowed by the protocol?
      if(state->client_certs->count() > 1)
         throw TLS_Exception(Alert::CERTIFICATE_UNKNOWN,
                             "Client sent more than one certificate");

      state->set_expected_next(CLIENT_KEX);
      }
   else if(type == CLIENT_KEX)
      {
      if(state->received_handshake_msg(CERTIFICATE) && !state->client_certs->empty())
         state->set_expected_next(CERTIFICATE_VERIFY);
      else
         state->set_expected_next(HANDSHAKE_CCS);

      state->client_kex = new Client_Key_Exchange(contents, state, creds, policy, rng);

      state->keys = Session_Keys(state, state->client_kex->pre_master_secret(), false);
      }
   else if(type == CERTIFICATE_VERIFY)
      {
      state->client_verify = new Certificate_Verify(contents, state->version);

      const std::vector<X509_Certificate>& client_certs =
         state->client_certs->cert_chain();

      const bool sig_valid =
         state->client_verify->verify(client_certs[0], state);

      state->hash.update(type, contents);

      /*
      * Using DECRYPT_ERROR looks weird here, but per RFC 4346 is for
      * "A handshake cryptographic operation failed, including being
      * unable to correctly verify a signature, ..."
      */
      if(!sig_valid)
         throw TLS_Exception(Alert::DECRYPT_ERROR, "Client cert verify failed");

      try
         {
         creds.verify_certificate_chain("tls-server", "", client_certs);
         }
      catch(std::exception& e)
         {
         throw TLS_Exception(Alert::BAD_CERTIFICATE, e.what());
         }

      state->set_expected_next(HANDSHAKE_CCS);
      }
   else if(type == HANDSHAKE_CCS)
      {
      if(state->server_hello->next_protocol_notification())
         state->set_expected_next(NEXT_PROTOCOL);
      else
         state->set_expected_next(FINISHED);

      reader.activate(SERVER, state->suite, state->keys,
                      state->server_hello->compression_method());
      }
   else if(type == NEXT_PROTOCOL)
      {
      state->set_expected_next(FINISHED);

      state->next_protocol = new Next_Protocol(contents);

      m_next_protocol = state->next_protocol->protocol();
      }
   else if(type == FINISHED)
      {
      state->set_expected_next(HANDSHAKE_NONE);

      state->client_finished = new Finished(contents);

      if(!state->client_finished->verify(state, CLIENT))
         throw TLS_Exception(Alert::DECRYPT_ERROR,
                             "Finished message didn't verify");

      // already sent it if resuming
      if(!state->server_finished)
         {
         state->hash.update(type, contents);

         writer.send(CHANGE_CIPHER_SPEC, 1);

         writer.activate(SERVER, state->suite, state->keys,
                         state->server_hello->compression_method());

         state->server_finished = new Finished(writer, state, SERVER);

         if(state->client_certs && state->client_verify)
            peer_certs = state->client_certs->cert_chain();
         }

      Session session_info(
         state->server_hello->session_id(),
         state->keys.master_secret(),
         state->server_hello->version(),
         state->server_hello->ciphersuite(),
         state->server_hello->compression_method(),
         SERVER,
         secure_renegotiation.supported(),
         state->server_hello->fragment_size(),
         peer_certs,
         m_hostname,
         ""
         );

      if(handshake_fn(session_info))
         session_manager.save(session_info);
      else
         session_manager.remove_entry(session_info.session_id());

      secure_renegotiation.update(state->client_finished,
                                  state->server_finished);

      delete state;
      state = 0;
      handshake_completed = true;
      }
   else
      throw Unexpected_Message("Unknown handshake message received");
   }

}

}
<commit_msg>We would call the handshake callback twice on session resumption: misplaced braces.<commit_after>/*
* TLS Server
* (C) 2004-2011,2012 Jack Lloyd
*
* Released under the terms of the Botan license
*/

#include <botan/tls_server.h>
#include <botan/internal/tls_handshake_state.h>
#include <botan/internal/tls_messages.h>
#include <botan/internal/stl_util.h>
#include <botan/internal/assert.h>
#include <memory>

namespace Botan {

namespace TLS {

namespace {

bool check_for_resume(Session& session_info,
                      Session_Manager& session_manager,
                      Client_Hello* client_hello)
   {
   MemoryVector<byte> client_session_id = client_hello->session_id();

   if(client_session_id.empty()) // not resuming
      return false;

   // not found
   if(!session_manager.load_from_session_id(client_session_id, session_info))
      return false;

   // wrong version
   if(client_hello->version() != session_info.version())
      return false;

   // client didn't send original ciphersuite
   if(!value_exists(client_hello->ciphersuites(),
                    session_info.ciphersuite_code()))
      return false;

   // client didn't send original compression method
   if(!value_exists(client_hello->compression_methods(),
                    session_info.compression_method()))
      return false;

   // client sent a different SRP identity (!!!)
   if(client_hello->srp_identifier() != "")
      {
      if(client_hello->srp_identifier() != session_info.srp_identifier())
         return false;
      }

   // client sent a different SNI hostname (!!!)
   if(client_hello->sni_hostname() != "")
      {
      if(client_hello->sni_hostname() != session_info.sni_hostname())
         return false;
      }

   return true;
   }

std::map<std::string, std::vector<X509_Certificate> >
get_server_certs(const std::string& hostname,
                 Credentials_Manager& creds)
   {
   const char* cert_types[] = { "RSA", "DSA", "ECDSA", 0 };

   std::map<std::string, std::vector<X509_Certificate> > cert_chains;

   for(size_t i = 0; cert_types[i]; ++i)
      {
      std::vector<X509_Certificate> certs =
         creds.cert_chain_single_type(cert_types[i], "tls-server", hostname);

      if(!certs.empty())
         cert_chains[cert_types[i]] = certs;
      }

   return cert_chains;
   }

}

/*
* TLS Server Constructor
*/
Server::Server(std::tr1::function<void (const byte[], size_t)> output_fn,
               std::tr1::function<void (const byte[], size_t, Alert)> proc_fn,
               std::tr1::function<bool (const Session&)> handshake_fn,
               Session_Manager& session_manager,
               Credentials_Manager& creds,
               const Policy& policy,
               RandomNumberGenerator& rng,
               const std::vector<std::string>& next_protocols) :
   Channel(output_fn, proc_fn, handshake_fn),
   policy(policy),
   rng(rng),
   session_manager(session_manager),
   creds(creds),
   m_possible_protocols(next_protocols)
   {
   }

/*
* Send a hello request to the client
*/
void Server::renegotiate()
   {
   if(state)
      return; // currently in handshake

   state = new Handshake_State;
   state->set_expected_next(CLIENT_HELLO);
   Hello_Request hello_req(writer);
   }

void Server::alert_notify(const Alert& alert)
   {
   if(alert.type() == Alert::NO_RENEGOTIATION)
      {
      if(handshake_completed && state)
         {
         delete state;
         state = 0;
         }
      }
   }

/*
* Split up and process handshake messages
*/
void Server::read_handshake(byte rec_type,
                            const MemoryRegion<byte>& rec_buf)
   {
   if(rec_type == HANDSHAKE && !state)
      {
      state = new Handshake_State;
      state->set_expected_next(CLIENT_HELLO);
      }

   Channel::read_handshake(rec_type, rec_buf);
   }

/*
* Process a handshake message
*/
void Server::process_handshake_msg(Handshake_Type type,
                                   const MemoryRegion<byte>& contents)
   {
   if(state == 0)
      throw Unexpected_Message("Unexpected handshake message from client");

   state->confirm_transition_to(type);

   /*
   * The change cipher spec message isn't technically a handshake
   * message so it's not included in the hash. The finished and
   * certificate verify messages are verified based on the current
   * state of the hash *before* this message so we delay adding them
   * to the hash computation until we've processed them below.
   */
   if(type != HANDSHAKE_CCS && type != FINISHED && type != CERTIFICATE_VERIFY)
      {
      if(type == CLIENT_HELLO_SSLV2)
         state->hash.update(contents);
      else
         state->hash.update(type, contents);
      }

   if(type == CLIENT_HELLO || type == CLIENT_HELLO_SSLV2)
      {
      state->client_hello = new Client_Hello(contents, type);

      m_hostname = state->client_hello->sni_hostname();

      Protocol_Version client_version = state->client_hello->version();

      if(client_version < policy.min_version())
         throw TLS_Exception(Alert::PROTOCOL_VERSION,
                             "Client version is unacceptable by policy");

      if(client_version <= policy.pref_version())
         state->version = client_version;
      else
         state->version = policy.pref_version();

      secure_renegotiation.update(state->client_hello);

      writer.set_version(state->version);
      reader.set_version(state->version);

      Session session_info;
      const bool resuming = check_for_resume(session_info,
                                             session_manager,
                                             state->client_hello);

      if(resuming)
         {
         // resume session

         state->server_hello = new Server_Hello(
            writer,
            state->hash,
            session_info.session_id(),
            Protocol_Version(session_info.version()),
            session_info.ciphersuite_code(),
            session_info.compression_method(),
            session_info.fragment_size(),
            secure_renegotiation.supported(),
            secure_renegotiation.for_server_hello(),
            state->client_hello->next_protocol_notification(),
            m_possible_protocols,
            rng);

         if(session_info.fragment_size())
            {
            reader.set_maximum_fragment_size(session_info.fragment_size());
            writer.set_maximum_fragment_size(session_info.fragment_size());
            }

         state->suite = Ciphersuite::by_id(state->server_hello->ciphersuite());

         state->keys = Session_Keys(state, session_info.master_secret(), true);

         writer.send(CHANGE_CIPHER_SPEC, 1);

         writer.activate(SERVER, state->suite, state->keys,
                         state->server_hello->compression_method());

         state->server_finished = new Finished(writer, state, SERVER);

         if(!handshake_fn(session_info))
            session_manager.remove_entry(session_info.session_id());

         state->set_expected_next(HANDSHAKE_CCS);
         }
      else // new session
         {
         std::map<std::string, std::vector<X509_Certificate> > cert_chains;

         cert_chains = get_server_certs(m_hostname, creds);

         if(m_hostname != "" && cert_chains.empty())
            {
            send_alert(Alert(Alert::UNRECOGNIZED_NAME));
            cert_chains = get_server_certs("", creds);
            }

         std::vector<std::string> available_cert_types;

         for(std::map<std::string, std::vector<X509_Certificate> >::const_iterator i = cert_chains.begin();
             i != cert_chains.end(); ++i)
            {
            if(!i->second.empty())
               available_cert_types.push_back(i->first);
            }

         state->server_hello = new Server_Hello(
            writer,
            state->hash,
            state->version,
            *(state->client_hello),
            available_cert_types,
            policy,
            secure_renegotiation.supported(),
            secure_renegotiation.for_server_hello(),
            state->client_hello->next_protocol_notification(),
            m_possible_protocols,
            rng);

         if(state->client_hello->fragment_size())
            {
            reader.set_maximum_fragment_size(state->client_hello->fragment_size());
            writer.set_maximum_fragment_size(state->client_hello->fragment_size());
            }

         state->suite = Ciphersuite::by_id(state->server_hello->ciphersuite());

         const std::string sig_algo = state->suite.sig_algo();
         const std::string kex_algo = state->suite.kex_algo();

         if(sig_algo != "")
            {
            BOTAN_ASSERT(!cert_chains[sig_algo].empty(),
                         "Attempting to send empty certificate chain");

            state->server_certs = new Certificate(writer,
                                                  state->hash,
                                                  cert_chains[sig_algo]);
            }

         Private_Key* private_key = 0;

         if(kex_algo == "RSA" || sig_algo != "")
            {
            private_key = creds.private_key_for(state->server_certs->cert_chain()[0],
                                                "tls-server",
                                                m_hostname);

            if(!private_key)
               throw Internal_Error("No private key located for associated server cert");
            }

         if(kex_algo == "RSA")
            {
            state->server_rsa_kex_key = private_key;
            }
         else
            {
            state->server_kex =
               new Server_Key_Exchange(writer, state, policy, creds, rng, private_key);
            }

         std::vector<X509_Certificate> client_auth_CAs =
            creds.trusted_certificate_authorities("tls-server", m_hostname);

         if(!client_auth_CAs.empty() && state->suite.sig_algo() != "")
            {
            state->cert_req = new Certificate_Req(writer,
                                                  state->hash,
                                                  policy,
                                                  client_auth_CAs,
                                                  state->version);

            state->set_expected_next(CERTIFICATE);
            }

         secure_renegotiation.update(state->server_hello);

         /*
         * If the client doesn't have a cert they want to use they are
         * allowed to send either an empty cert message or proceed
         * directly to the client key exchange, so allow either case.
         */
         state->set_expected_next(CLIENT_KEX);

         state->server_hello_done = new Server_Hello_Done(writer, state->hash);
         }
      }
   else if(type == CERTIFICATE)
      {
      state->client_certs = new Certificate(contents);

      // Is this allowed by the protocol?
      if(state->client_certs->count() > 1)
         throw TLS_Exception(Alert::CERTIFICATE_UNKNOWN,
                             "Client sent more than one certificate");

      state->set_expected_next(CLIENT_KEX);
      }
   else if(type == CLIENT_KEX)
      {
      if(state->received_handshake_msg(CERTIFICATE) && !state->client_certs->empty())
         state->set_expected_next(CERTIFICATE_VERIFY);
      else
         state->set_expected_next(HANDSHAKE_CCS);

      state->client_kex = new Client_Key_Exchange(contents, state, creds, policy, rng);

      state->keys = Session_Keys(state, state->client_kex->pre_master_secret(), false);
      }
   else if(type == CERTIFICATE_VERIFY)
      {
      state->client_verify = new Certificate_Verify(contents, state->version);

      const std::vector<X509_Certificate>& client_certs =
         state->client_certs->cert_chain();

      const bool sig_valid =
         state->client_verify->verify(client_certs[0], state);

      state->hash.update(type, contents);

      /*
      * Using DECRYPT_ERROR looks weird here, but per RFC 4346 is for
      * "A handshake cryptographic operation failed, including being
      * unable to correctly verify a signature, ..."
      */
      if(!sig_valid)
         throw TLS_Exception(Alert::DECRYPT_ERROR, "Client cert verify failed");

      try
         {
         creds.verify_certificate_chain("tls-server", "", client_certs);
         }
      catch(std::exception& e)
         {
         throw TLS_Exception(Alert::BAD_CERTIFICATE, e.what());
         }

      state->set_expected_next(HANDSHAKE_CCS);
      }
   else if(type == HANDSHAKE_CCS)
      {
      if(state->server_hello->next_protocol_notification())
         state->set_expected_next(NEXT_PROTOCOL);
      else
         state->set_expected_next(FINISHED);

      reader.activate(SERVER, state->suite, state->keys,
                      state->server_hello->compression_method());
      }
   else if(type == NEXT_PROTOCOL)
      {
      state->set_expected_next(FINISHED);

      state->next_protocol = new Next_Protocol(contents);

      m_next_protocol = state->next_protocol->protocol();
      }
   else if(type == FINISHED)
      {
      state->set_expected_next(HANDSHAKE_NONE);

      state->client_finished = new Finished(contents);

      if(!state->client_finished->verify(state, CLIENT))
         throw TLS_Exception(Alert::DECRYPT_ERROR,
                             "Finished message didn't verify");

      if(!state->server_finished)
         {
         state->hash.update(type, contents);

         writer.send(CHANGE_CIPHER_SPEC, 1);

         writer.activate(SERVER, state->suite, state->keys,
                         state->server_hello->compression_method());

         state->server_finished = new Finished(writer, state, SERVER);

         if(state->client_certs && state->client_verify)
            peer_certs = state->client_certs->cert_chain();

         // already sent finished if resuming, so this is a new session

         Session session_info(
            state->server_hello->session_id(),
            state->keys.master_secret(),
            state->server_hello->version(),
            state->server_hello->ciphersuite(),
            state->server_hello->compression_method(),
            SERVER,
            secure_renegotiation.supported(),
            state->server_hello->fragment_size(),
            peer_certs,
            m_hostname,
            ""
            );

         if(handshake_fn(session_info))
            session_manager.save(session_info);
         }

      secure_renegotiation.update(state->client_finished,
                                  state->server_finished);

      delete state;
      state = 0;
      handshake_completed = true;
      }
   else
      throw Unexpected_Message("Unknown handshake message received");
   }

}

}
<|endoftext|>


<commit_before>#define CATCH_CONFIG_MAIN
#include "catch.hpp"

#include "config.h"
#if GAF_TEST_HEADER_ONLY
#define GENERATED_MYGAF_IMPLEMENTATION
#endif

#include "mygaf.h"

TEST_CASE("constructor") {
  const Foo foo;
  REQUIRE(foo.GetHello() == 0);
  REQUIRE(foo.GetWorld() == 0.0f);

  const Bar bar;
  REQUIRE(bar.GetFoo().GetHello() == 0);
  REQUIRE(bar.GetFoo().GetWorld() == 0.0f);
  REQUIRE(bar.GetBar() == 0);
}

TEST_CASE("setter") {
  Foo foo;
  foo.SetHello(42);
  foo.SetWorld(4.2f);
  Bar bar;
  bar.SetFoo(foo);
  bar.SetBar(24);
  foo.SetHello(5);
  foo.SetWorld(5.5f);

  REQUIRE(bar.GetFoo().GetHello() == 42);
  REQUIRE(bar.GetFoo().GetWorld() == 4.2f);
  REQUIRE(bar.GetBar() == 24);

  bar.GetFooPtr()->SetHello(13);
  bar.GetFooPtr()->SetWorld(3.7f);
  REQUIRE(bar.GetFoo().GetHello() == 13);
  REQUIRE(bar.GetFoo().GetWorld() == 3.7f);
}

#ifdef GAF_TEST_JSON

TEST_CASE("json_basic") {
  Foo foo;
  const char* const load = foo.ReadJsonSource(" {\"hello\": 12, \"world\": 2.4} ");
  REQUIRE(load == nullptr);
  REQUIRE(foo.GetHello() == 12);
  REQUIRE(foo.GetWorld() == 2.4f);
}

#endif
<commit_msg>added advanced unittest<commit_after>#define CATCH_CONFIG_MAIN
#include "catch.hpp"

#include "config.h"
#if GAF_TEST_HEADER_ONLY
#define GENERATED_MYGAF_IMPLEMENTATION
#endif

#include "mygaf.h"

TEST_CASE("constructor") {
  const Foo foo;
  REQUIRE(foo.GetHello() == 0);
  REQUIRE(foo.GetWorld() == 0.0f);

  const Bar bar;
  REQUIRE(bar.GetFoo().GetHello() == 0);
  REQUIRE(bar.GetFoo().GetWorld() == 0.0f);
  REQUIRE(bar.GetBar() == 0);
}

TEST_CASE("setter") {
  Foo foo;
  foo.SetHello(42);
  foo.SetWorld(4.2f);
  Bar bar;
  bar.SetFoo(foo);
  bar.SetBar(24);
  foo.SetHello(5);
  foo.SetWorld(5.5f);

  REQUIRE(bar.GetFoo().GetHello() == 42);
  REQUIRE(bar.GetFoo().GetWorld() == 4.2f);
  REQUIRE(bar.GetBar() == 24);

  bar.GetFooPtr()->SetHello(13);
  bar.GetFooPtr()->SetWorld(3.7f);
  REQUIRE(bar.GetFoo().GetHello() == 13);
  REQUIRE(bar.GetFoo().GetWorld() == 3.7f);
}

#ifdef GAF_TEST_JSON

TEST_CASE("json_basic") {
  Foo foo;
  const char* const load = foo.ReadJsonSource(" {\"hello\": 12, \"world\": 2.4} ");
  REQUIRE(load == nullptr);
  REQUIRE(foo.GetHello() == 12);
  REQUIRE(foo.GetWorld() == 2.4f);
}

TEST_CASE("json_advanced") {
  Bar bar;
  const char* const load = bar.ReadJsonSource("{\"bar\": 42, \"foo\": {\"hello\": 12, \"world\": 2.4}}");
  REQUIRE(load == nullptr);
  CHECK(bar.GetFoo().GetHello() == 12);
  CHECK(bar.GetFoo().GetWorld() == 2.4f);
  CHECK(bar.GetBar() == 42);
}

#endif
<|endoftext|>


<commit_before>/**
 * @file
 *
 * @brief
 *
 * @copyright BSD License (see LICENSE.md or https://www.libelektra.org)
 */

#include <iostream>
#include <memory>
#include <string>
#include <vector>

#include <coloredkdbio.hpp>

#include <cmdline.hpp>
#include <command.hpp>
#include <external.hpp>
#include <factory.hpp>
#include <signal.h>
#include <toolexcept.hpp>

#include <kdb.hpp>
#include <key.hpp>

using namespace kdb;
using namespace std;

int displayHelp (std::string app, Factory const & f)
{
	std::cout << "Usage: " << app << " <command> [args]\n" << std::endl;
	std::cout << app << " is a program to manage elektra's key database.\n"
		  << "Please run a command with -H or --help as args to show a help text for\n"
		  << "a specific command.\n"
		  << std::endl;
	std::cout << "Known commands are:" << std::endl;
	std::vector<std::string> commands;
	try
	{
		commands = f.getPrettyCommands ();
	}
	catch (kdb::KDBException const & ce)
	{
		std::cerr << "Sorry, I have a severe problem, it seems like I am not installed correctly!\n"
			  << "kdbOpen() failed with the info:" << std::endl
			  << ce.what () << std::endl
			  << "Please report the issue at https://issues.libelektra.org/";
		return 8;
	}
	for (auto & command : commands)
	{
		std::cout << command << std::endl;
	}
	return 0;
}

void displayVersion ()
{
	kdb::KDB kdb;
	kdb::KeySet versions;
	kdb::Key k ("system/elektra/version", KEY_END);
	kdb.get (versions, k);
	kdb::Key kdb_version = versions.lookup ("system/elektra/version/constants/KDB_VERSION");
	if (!kdb_version)
	{
		cerr << "Could not lookup KDB_VERSION key" << endl;
	}
	else
	{
		cout << "KDB_VERSION: " << kdb_version.getString () << endl;
	}
	kdb::Key so_version = versions.lookup ("system/elektra/version/constants/SO_VERSION");
	if (!so_version)
	{
		cerr << "Could not lookup SO_VERSION key" << endl;
	}
	else
	{
		cout << "SO_VERSION: " << so_version.getString () << endl;
	}
}

void printSignal (int signum)
{
	switch (signum)
	{
	case SIGILL:
		cerr << "SIGILL";
		break;
	case SIGABRT:
		cerr << "SIGABRT";
		break;
	case SIGFPE:
		cerr << "SIGFPE";
		break;
	case SIGSEGV:
		cerr << "SIGSEGV";
		break;
	}
}

void catchSignal (int signum)
{
	cerr << endl << "Sorry, I crashed by the signal ";
	printSignal (signum);
	cerr << endl << "This should not have happened!" << endl;
	cerr << endl << "Please report the issue at https://issues.libelektra.org/" << std::endl;
	signal (SIGABRT, SIG_DFL);
	abort ();
}

void setupSignal (int signum)
{
	if (signal (signum, catchSignal) == SIG_ERR)
	{
		cerr << "Sorry, I could not setup signal ";
		printSignal (signum);
		cerr << " because: " << strerror (errno) << std::endl;
		cerr << "Please report the issue at https://issues.libelektra.org/" << std::endl;
	}
}

void setupSignals ()
{
	setupSignal (SIGILL);
	setupSignal (SIGABRT);
	setupSignal (SIGFPE);
	setupSignal (SIGSEGV);
}

int main (int argc, char ** argv)
{
	setupSignals ();
	Factory f;

	if (argc < 2)
	{
		return displayHelp (argv[0], f);
	}

	string command = argv[1];
	if (command == "help" || command == "-H" || command == "--help")
	{
		if (argc >= 3)
		{
			runManPage (argv[2]);
		}
		else
		{
			runManPage ();
		}

		return displayHelp (argv[0], f);
	}

	if (command == "-V" || command == "--version")
	{
		displayVersion ();
		return 0;
	}

	try
	{
		std::vector<char *> origArguments (argv + 1, argv + argc);
		origArguments.push_back (0);
		CommandPtr cmd = f.get (command);
		Cmdline cl (argc, argv, cmd.get ());

		if (cl.help)
		{
			runManPage (command, cl.profile);
			// does not return, but may throw
		}

		// version and invalidOpt might be implemented
		// differently for external command
		if (dynamic_cast<ExternalCommand *> (cmd.get ()))
		{
			tryExternalCommand (&origArguments[0]);
			// does not return, but may throw
		}

		if (cl.version)
		{
			displayVersion ();
			return 0;
		}

		if (cl.invalidOpt)
		{
			cerr << cl << endl;
			return 1;
		}

		try
		{
			return cmd->execute (cl);
		}
		catch (std::invalid_argument const & ia)
		{
			cerr << "Sorry, I could not process the arguments: " << ia.what () << endl << endl;
			cerr << cl << endl;
			return 2;
		}
	}
	catch (CommandException const & ce)
	{
		std::cerr << "The command " << getErrorColor (ANSI_COLOR::BOLD) << argv[0] << " " << command
			  << getErrorColor (ANSI_COLOR::RESET) << " terminated " << getErrorColor (ANSI_COLOR::RED) << "unsuccessfully"
			  << getErrorColor (ANSI_COLOR::RESET) << " with the info:\n"
			  << ce.what () << std::endl;
		if (ce.errorCode () != 3 && (ce.errorCode () < 11 || ce.errorCode () > 20))
		{
			std::cerr << "Command used invalid return value (" << ce.errorCode ()
				  << "), please report the issue at https://issues.libelektra.org/" << std::endl;
			return 3;
		}
		return ce.errorCode ();
	}
	catch (UnknownCommand const & uc)
	{
		std::cerr << "The command " << getErrorColor (ANSI_COLOR::BOLD) << argv[0] << " " << command
			  << getErrorColor (ANSI_COLOR::RESET) << " is " << getErrorColor (ANSI_COLOR::RED) << "not known"
			  << getErrorColor (ANSI_COLOR::RESET) << std::endl;
		displayHelp (argv[0], f);
		return 4;
	}
	catch (kdb::KDBException const & ce)
	{
		std::cerr << "The command " << getErrorColor (ANSI_COLOR::BOLD) << argv[0] << " " << command
			  << getErrorColor (ANSI_COLOR::RESET) << getErrorColor (ANSI_COLOR::RED) << " failed"
			  << getErrorColor (ANSI_COLOR::RESET) << " while accessing the key database with the info:\n"
			  << ce.what () << std::endl;
		return 5;
	}
	catch (std::exception const & ce)
	{
		std::cerr << "The command " << getErrorColor (ANSI_COLOR::BOLD) << argv[0] << " " << command
			  << getErrorColor (ANSI_COLOR::RESET) << " terminated " << getErrorColor (ANSI_COLOR::RED) << "unsuccessfully"
			  << getErrorColor (ANSI_COLOR::RESET) << " with the info:" << endl
			  << ce.what () << endl
			  << "Please report the issue at https://issues.libelektra.org/" << std::endl;
		return 7;
	}
	catch (...)
	{
		std::cerr << "The command " << getErrorColor (ANSI_COLOR::BOLD) << argv[0] << " " << command
			  << getErrorColor (ANSI_COLOR::RESET) << " terminated with an " << getErrorColor (ANSI_COLOR::RED)
			  << "unknown error" << getErrorColor (ANSI_COLOR::RESET) << endl
			  << "Please report the issue at https://issues.libelektra.org/" << std::endl;
		displayHelp (argv[0], f);
		return 7;
	}
}
<commit_msg>spelling: elektra -> Elektra<commit_after>/**
 * @file
 *
 * @brief
 *
 * @copyright BSD License (see LICENSE.md or https://www.libelektra.org)
 */

#include <iostream>
#include <memory>
#include <string>
#include <vector>

#include <coloredkdbio.hpp>

#include <cmdline.hpp>
#include <command.hpp>
#include <external.hpp>
#include <factory.hpp>
#include <signal.h>
#include <toolexcept.hpp>

#include <kdb.hpp>
#include <key.hpp>

using namespace kdb;
using namespace std;

int displayHelp (std::string app, Factory const & f)
{
	std::cout << "Usage: " << app << " <command> [args]\n" << std::endl;
	std::cout << app << " is a program to manage Elektra's key database.\n"
		  << "Please run a command with -H or --help as args to show a help text for\n"
		  << "a specific command.\n"
		  << std::endl;
	std::cout << "Known commands are:" << std::endl;
	std::vector<std::string> commands;
	try
	{
		commands = f.getPrettyCommands ();
	}
	catch (kdb::KDBException const & ce)
	{
		std::cerr << "Sorry, I have a severe problem, it seems like I am not installed correctly!\n"
			  << "kdbOpen() failed with the info:" << std::endl
			  << ce.what () << std::endl
			  << "Please report the issue at https://issues.libelektra.org/";
		return 8;
	}
	for (auto & command : commands)
	{
		std::cout << command << std::endl;
	}
	return 0;
}

void displayVersion ()
{
	kdb::KDB kdb;
	kdb::KeySet versions;
	kdb::Key k ("system/elektra/version", KEY_END);
	kdb.get (versions, k);
	kdb::Key kdb_version = versions.lookup ("system/elektra/version/constants/KDB_VERSION");
	if (!kdb_version)
	{
		cerr << "Could not lookup KDB_VERSION key" << endl;
	}
	else
	{
		cout << "KDB_VERSION: " << kdb_version.getString () << endl;
	}
	kdb::Key so_version = versions.lookup ("system/elektra/version/constants/SO_VERSION");
	if (!so_version)
	{
		cerr << "Could not lookup SO_VERSION key" << endl;
	}
	else
	{
		cout << "SO_VERSION: " << so_version.getString () << endl;
	}
}

void printSignal (int signum)
{
	switch (signum)
	{
	case SIGILL:
		cerr << "SIGILL";
		break;
	case SIGABRT:
		cerr << "SIGABRT";
		break;
	case SIGFPE:
		cerr << "SIGFPE";
		break;
	case SIGSEGV:
		cerr << "SIGSEGV";
		break;
	}
}

void catchSignal (int signum)
{
	cerr << endl << "Sorry, I crashed by the signal ";
	printSignal (signum);
	cerr << endl << "This should not have happened!" << endl;
	cerr << endl << "Please report the issue at https://issues.libelektra.org/" << std::endl;
	signal (SIGABRT, SIG_DFL);
	abort ();
}

void setupSignal (int signum)
{
	if (signal (signum, catchSignal) == SIG_ERR)
	{
		cerr << "Sorry, I could not setup signal ";
		printSignal (signum);
		cerr << " because: " << strerror (errno) << std::endl;
		cerr << "Please report the issue at https://issues.libelektra.org/" << std::endl;
	}
}

void setupSignals ()
{
	setupSignal (SIGILL);
	setupSignal (SIGABRT);
	setupSignal (SIGFPE);
	setupSignal (SIGSEGV);
}

int main (int argc, char ** argv)
{
	setupSignals ();
	Factory f;

	if (argc < 2)
	{
		return displayHelp (argv[0], f);
	}

	string command = argv[1];
	if (command == "help" || command == "-H" || command == "--help")
	{
		if (argc >= 3)
		{
			runManPage (argv[2]);
		}
		else
		{
			runManPage ();
		}

		return displayHelp (argv[0], f);
	}

	if (command == "-V" || command == "--version")
	{
		displayVersion ();
		return 0;
	}

	try
	{
		std::vector<char *> origArguments (argv + 1, argv + argc);
		origArguments.push_back (0);
		CommandPtr cmd = f.get (command);
		Cmdline cl (argc, argv, cmd.get ());

		if (cl.help)
		{
			runManPage (command, cl.profile);
			// does not return, but may throw
		}

		// version and invalidOpt might be implemented
		// differently for external command
		if (dynamic_cast<ExternalCommand *> (cmd.get ()))
		{
			tryExternalCommand (&origArguments[0]);
			// does not return, but may throw
		}

		if (cl.version)
		{
			displayVersion ();
			return 0;
		}

		if (cl.invalidOpt)
		{
			cerr << cl << endl;
			return 1;
		}

		try
		{
			return cmd->execute (cl);
		}
		catch (std::invalid_argument const & ia)
		{
			cerr << "Sorry, I could not process the arguments: " << ia.what () << endl << endl;
			cerr << cl << endl;
			return 2;
		}
	}
	catch (CommandException const & ce)
	{
		std::cerr << "The command " << getErrorColor (ANSI_COLOR::BOLD) << argv[0] << " " << command
			  << getErrorColor (ANSI_COLOR::RESET) << " terminated " << getErrorColor (ANSI_COLOR::RED) << "unsuccessfully"
			  << getErrorColor (ANSI_COLOR::RESET) << " with the info:\n"
			  << ce.what () << std::endl;
		if (ce.errorCode () != 3 && (ce.errorCode () < 11 || ce.errorCode () > 20))
		{
			std::cerr << "Command used invalid return value (" << ce.errorCode ()
				  << "), please report the issue at https://issues.libelektra.org/" << std::endl;
			return 3;
		}
		return ce.errorCode ();
	}
	catch (UnknownCommand const & uc)
	{
		std::cerr << "The command " << getErrorColor (ANSI_COLOR::BOLD) << argv[0] << " " << command
			  << getErrorColor (ANSI_COLOR::RESET) << " is " << getErrorColor (ANSI_COLOR::RED) << "not known"
			  << getErrorColor (ANSI_COLOR::RESET) << std::endl;
		displayHelp (argv[0], f);
		return 4;
	}
	catch (kdb::KDBException const & ce)
	{
		std::cerr << "The command " << getErrorColor (ANSI_COLOR::BOLD) << argv[0] << " " << command
			  << getErrorColor (ANSI_COLOR::RESET) << getErrorColor (ANSI_COLOR::RED) << " failed"
			  << getErrorColor (ANSI_COLOR::RESET) << " while accessing the key database with the info:\n"
			  << ce.what () << std::endl;
		return 5;
	}
	catch (std::exception const & ce)
	{
		std::cerr << "The command " << getErrorColor (ANSI_COLOR::BOLD) << argv[0] << " " << command
			  << getErrorColor (ANSI_COLOR::RESET) << " terminated " << getErrorColor (ANSI_COLOR::RED) << "unsuccessfully"
			  << getErrorColor (ANSI_COLOR::RESET) << " with the info:" << endl
			  << ce.what () << endl
			  << "Please report the issue at https://issues.libelektra.org/" << std::endl;
		return 7;
	}
	catch (...)
	{
		std::cerr << "The command " << getErrorColor (ANSI_COLOR::BOLD) << argv[0] << " " << command
			  << getErrorColor (ANSI_COLOR::RESET) << " terminated with an " << getErrorColor (ANSI_COLOR::RED)
			  << "unknown error" << getErrorColor (ANSI_COLOR::RESET) << endl
			  << "Please report the issue at https://issues.libelektra.org/" << std::endl;
		displayHelp (argv[0], f);
		return 7;
	}
}
<|endoftext|>


<commit_before>//===-- Frontend.cpp - frontend utility methods ---------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// This file contains utility methods for parsing and performing semantic
// on modules.
//
//===----------------------------------------------------------------------===//

#include "swift/Frontend/Frontend.h"
#include "swift/Subsystems.h"
#include "swift/AST/ASTContext.h"
#include "swift/AST/DiagnosticsFrontend.h"
#include "swift/AST/Module.h"
#include "swift/Basic/SourceManager.h"
#include "swift/Parse/DelayedParsingCallbacks.h"
#include "swift/Parse/Lexer.h"
#include "swift/SIL/SILModule.h"
#include "swift/Serialization/SerializedModuleLoader.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"

using namespace swift;

void swift::CompilerInstance::createSILModule() {
  assert(getMainModule());
  TheSILModule = SILModule::createEmptyModule(getMainModule());
}

void swift::CompilerInstance::setTargetConfigurations(IRGenOptions &IRGenOpts,
                             LangOptions &LangOpts) {

  llvm::Triple triple = llvm::Triple(IRGenOpts.Triple);

  // Set the "os" target configuration.
  if (triple.isMacOSX()) {
    LangOpts.TargetConfigOptions["os"] = "OSX";
  } else if (triple.isiOS()) {
    LangOpts.TargetConfigOptions["os"] = "iOS";
  } else {
    assert(false && "Unsupported target OS");
  }

  // Set the "arch" target configuration.
  switch (triple.getArch()) {
  case llvm::Triple::ArchType::arm:
    LangOpts.TargetConfigOptions["arch"] = "arm";
    break;
  case llvm::Triple::ArchType::x86:
    LangOpts.TargetConfigOptions["arch"] = "i386";
    break;
  case llvm::Triple::ArchType::x86_64:
    LangOpts.TargetConfigOptions["arch"] = "x86_64";
    break;
  default:
    // FIXME: Use `case llvm::Triple::arm64` when underlying LLVM is new enough
    if (StringRef("arm64") == llvm::Triple::getArchTypeName(triple.getArch()))
      LangOpts.TargetConfigOptions["arch"] = "arm64";
      break;
    llvm_unreachable("Unsupported target architecture");
  }
}

bool swift::CompilerInstance::setup(const CompilerInvocation &Invok) {
  Invocation = Invok;

  // Honor -Xllvm.
  if (!Invok.getFrontendOptions().LLVMArgs.empty()) {
    llvm::SmallVector<const char *, 4> Args;
    Args.push_back("swift (LLVM option parsing)");
    for (unsigned i = 0, e = Invok.getFrontendOptions().LLVMArgs.size(); i != e;
         ++i)
      Args.push_back(Invok.getFrontendOptions().LLVMArgs[i].c_str());
    Args.push_back(nullptr);
    llvm::cl::ParseCommandLineOptions(Args.size()-1, Args.data());
  }

  // Initialize the target build configuration settings ("os" and "arch").
  setTargetConfigurations(Invocation.getIRGenOptions(),
                          Invocation.getLangOptions());

  Context.reset(new ASTContext(Invocation.getLangOptions(),
                               Invocation.getSearchPathOptions(),
                               SourceMgr, Diagnostics));

  if (Invocation.getFrontendOptions().EnableSourceImport) {
    bool immediate = Invocation.getFrontendOptions().actionIsImmediate();
    Context->addModuleLoader(SourceLoader::create(*Context, !immediate));
  }

  SML = SerializedModuleLoader::create(*Context);
  Context->addModuleLoader(SML);

  // Wire up the Clang importer. If the user has specified an SDK, use it.
  // Otherwise, we just keep it around as our interface to Clang's ABI
  // knowledge.
  auto ImporterCtor = swift::getClangImporterCtor();
  if (ImporterCtor) {
    auto clangImporter =
        ImporterCtor(*Context, Invocation.getTargetTriple(),
                     Invocation.getClangImporterOptions());
    if (!clangImporter) {
      Diagnostics.diagnose(SourceLoc(), diag::error_clang_importer_create_fail);
      return true;
    }

    Context->addModuleLoader(clangImporter, /*isClang*/true);
  } else if (!Invocation.getSDKPath().empty()) {
    Diagnostics.diagnose(SourceLoc(),
                         diag::error_clang_importer_not_linked_in);
    return true;
  }

  assert(Lexer::isIdentifier(Invocation.getModuleName()));

  auto CodeCompletePoint = Invocation.getCodeCompletionPoint();
  if (CodeCompletePoint.first) {
    auto MemBuf = CodeCompletePoint.first;
    // CompilerInvocation doesn't own the buffers, copy to a new buffer.
    unsigned CodeCompletionBufferID = SourceMgr.addMemBufferCopy(MemBuf);
    BufferIDs.push_back(CodeCompletionBufferID);
    SourceMgr.setCodeCompletionPoint(CodeCompletionBufferID,
                                     CodeCompletePoint.second);
  }

  bool MainMode = (Invocation.getInputKind() == SourceFileKind::Main);
  bool SILMode = (Invocation.getInputKind() == SourceFileKind::SIL);

  const Optional<SelectedInput> &PrimaryInput =
    Invocation.getFrontendOptions().PrimaryInput;

  // Add the memory buffers first, these will be associated with a filename
  // and they can replace the contents of an input filename.
  for (unsigned i = 0, e = Invocation.getInputBuffers().size(); i != e; ++i) {
    // CompilerInvocation doesn't own the buffers, copy to a new buffer.
    unsigned BufferID =
        SourceMgr.addMemBufferCopy(Invocation.getInputBuffers()[i]);
    BufferIDs.push_back(BufferID);

    if (SILMode)
      MainBufferID = BufferID;

    if (PrimaryInput && PrimaryInput->isBuffer() && PrimaryInput->Index == i)
      PrimaryBufferID = BufferID;
  }

  for (unsigned i = 0, e = Invocation.getInputFilenames().size(); i != e; ++i) {
    auto &File = Invocation.getInputFilenames()[i];

    // FIXME: Working with filenames is fragile, maybe use the real path
    // or have some kind of FileManager.
    using namespace llvm::sys::path;
    {
      Optional<unsigned> ExistingBufferID =
        SourceMgr.getIDForBufferIdentifier(File);
      if (ExistingBufferID.hasValue()) {
        if (SILMode || (MainMode && filename(File) == "main.swift"))
          MainBufferID = ExistingBufferID.getValue();

        if (PrimaryInput && PrimaryInput->isFilename() &&
            PrimaryInput->Index == i)
          PrimaryBufferID = ExistingBufferID.getValue();

        continue; // replaced by a memory buffer.
      }
    }

    // Open the input file.
    std::unique_ptr<llvm::MemoryBuffer> InputFile;
    if (llvm::error_code Err =
          llvm::MemoryBuffer::getFileOrSTDIN(File, InputFile)) {
      Diagnostics.diagnose(SourceLoc(), diag::error_open_input_file,
                           File, Err.message());
      return true;
    }

    unsigned BufferID = SourceMgr.addNewSourceBuffer(std::move(InputFile));

    // Transfer ownership of the MemoryBuffer to the SourceMgr.
    BufferIDs.push_back(BufferID);

    if (SILMode || (MainMode && filename(File) == "main.swift"))
      MainBufferID = BufferID;

    if (PrimaryInput && PrimaryInput->isFilename() && PrimaryInput->Index == i)
      PrimaryBufferID = BufferID;
  }

  if (MainMode && MainBufferID == NO_SUCH_BUFFER && BufferIDs.size() == 1)
    MainBufferID = BufferIDs.front();

  return false;
}

void CompilerInstance::performParse() {
  const SourceFileKind Kind = Invocation.getInputKind();
  Identifier ID = Context->getIdentifier(Invocation.getModuleName());
  MainModule = Module::create(ID, *Context);
  Context->LoadedModules[ID.str()] = MainModule;

  if (Kind == SourceFileKind::SIL) {
    assert(BufferIDs.size() == 1);
    assert(MainBufferID != NO_SUCH_BUFFER);
    createSILModule();
  }

  if (Kind == SourceFileKind::REPL) {
    auto *SingleInputFile =
      new (*Context) SourceFile(*MainModule, Kind, {},
                                Invocation.getParseStdlib());
    MainModule->addFile(*SingleInputFile);
    return;
  }

  std::unique_ptr<DelayedParsingCallbacks> DelayedCB;
  if (Invocation.isCodeCompletion()) {
    DelayedCB.reset(
        new CodeCompleteDelayedCallbacks(SourceMgr.getCodeCompletionLoc()));
  } else if (Invocation.isDelayedFunctionBodyParsing()) {
    DelayedCB.reset(new AlwaysDelayedCallbacks);
  }

  PersistentParserState PersistentState;

  // Make sure the main file is the first file in the module. This may only be
  // a source file, or it may be a SIL file, which requires pumping the parser.
  // We parse it last, though, to make sure that it can use decls from other
  // files in the module.
  if (MainBufferID != NO_SUCH_BUFFER) {
    assert(Kind == SourceFileKind::Main || Kind == SourceFileKind::SIL);

    if (Kind == SourceFileKind::Main)
      SourceMgr.setHashbangBufferID(MainBufferID);

    auto *SingleInputFile =
      new (*Context) SourceFile(*MainModule, Kind, MainBufferID,
                                Invocation.getParseStdlib());
    MainModule->addFile(*SingleInputFile);

    if (MainBufferID == PrimaryBufferID)
      PrimarySourceFile = SingleInputFile;
  }

  bool hadLoadError = false;

  // Parse all the library files first.
  for (auto BufferID : BufferIDs) {
    if (BufferID == MainBufferID)
      continue;

    auto Buffer = SourceMgr->getMemoryBuffer(BufferID);
    if (SerializedModuleLoader::isSerializedAST(Buffer->getBuffer())) {
      std::unique_ptr<llvm::MemoryBuffer> Input(
        llvm::MemoryBuffer::getMemBuffer(Buffer->getBuffer(),
                                         Buffer->getBufferIdentifier(),
                                         false));
      if (!SML->loadAST(*MainModule, SourceLoc(), std::move(Input)))
        hadLoadError = true;
      continue;
    }

    auto *NextInput = new (*Context) SourceFile(*MainModule,
                                                SourceFileKind::Library,
                                                BufferID,
                                                Invocation.getParseStdlib());
    MainModule->addFile(*NextInput);

    if (BufferID == PrimaryBufferID)
      PrimarySourceFile = NextInput;

    bool Done;
    parseIntoSourceFile(*NextInput, BufferID, &Done, nullptr,
                        &PersistentState, DelayedCB.get());
    assert(Done && "Parser returned early?");
    (void) Done;

    performNameBinding(*NextInput);
  }

  if (hadLoadError)
    return;

  // Parse the main file last.
  if (MainBufferID != NO_SUCH_BUFFER) {
    SourceFile &MainFile = MainModule->getMainSourceFile(Kind);
    SILParserState SILContext(TheSILModule.get());
    unsigned CurTUElem = 0;
    bool Done;
    do {
      // Pump the parser multiple times if necessary.  It will return early
      // after parsing any top level code in a main module, or in SIL mode when
      // there are chunks of swift decls (e.g. imports and types) interspersed
      // with 'sil' definitions.
      parseIntoSourceFile(MainFile, MainFile.getBufferID().getValue(), &Done,
                          TheSILModule ? &SILContext : nullptr,
                          &PersistentState, DelayedCB.get());
      if (!Invocation.getParseOnly() && (PrimaryBufferID == NO_SUCH_BUFFER ||
                                         MainBufferID == PrimaryBufferID))
        performTypeChecking(MainFile, PersistentState.getTopLevelContext(),
                            CurTUElem);
      CurTUElem = MainFile.Decls.size();
    } while (!Done);
  }

  if (!Invocation.getParseOnly()) {
    // Type-check each top-level input besides the main source file.
    for (auto File : MainModule->getFiles())
      if (auto SF = dyn_cast<SourceFile>(File))
        if (PrimaryBufferID == NO_SUCH_BUFFER ||
            (SF->getBufferID().hasValue() &&
             SF->getBufferID().getValue() == PrimaryBufferID))
          performTypeChecking(*SF, PersistentState.getTopLevelContext());

    // Even if there were no source files, we should still record known
    // protocols.
    if (Context->getStdlibModule())
      Context->recordKnownProtocols(Context->getStdlibModule());
  }

  if (DelayedCB) {
    performDelayedParsing(MainModule, PersistentState,
                          Invocation.getCodeCompletionFactory());
  }
}

<commit_msg>Simplify code, NFC<commit_after>//===-- Frontend.cpp - frontend utility methods ---------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// This file contains utility methods for parsing and performing semantic
// on modules.
//
//===----------------------------------------------------------------------===//

#include "swift/Frontend/Frontend.h"
#include "swift/Subsystems.h"
#include "swift/AST/ASTContext.h"
#include "swift/AST/DiagnosticsFrontend.h"
#include "swift/AST/Module.h"
#include "swift/Basic/SourceManager.h"
#include "swift/Parse/DelayedParsingCallbacks.h"
#include "swift/Parse/Lexer.h"
#include "swift/SIL/SILModule.h"
#include "swift/Serialization/SerializedModuleLoader.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"

using namespace swift;

void swift::CompilerInstance::createSILModule() {
  assert(getMainModule());
  TheSILModule = SILModule::createEmptyModule(getMainModule());
}

void swift::CompilerInstance::setTargetConfigurations(IRGenOptions &IRGenOpts,
                             LangOptions &LangOpts) {

  llvm::Triple triple = llvm::Triple(IRGenOpts.Triple);

  // Set the "os" target configuration.
  if (triple.isMacOSX()) {
    LangOpts.TargetConfigOptions["os"] = "OSX";
  } else if (triple.isiOS()) {
    LangOpts.TargetConfigOptions["os"] = "iOS";
  } else {
    assert(false && "Unsupported target OS");
  }

  // Set the "arch" target configuration.
  switch (triple.getArch()) {
  case llvm::Triple::ArchType::arm:
    LangOpts.TargetConfigOptions["arch"] = "arm";
    break;
  case llvm::Triple::ArchType::x86:
    LangOpts.TargetConfigOptions["arch"] = "i386";
    break;
  case llvm::Triple::ArchType::x86_64:
    LangOpts.TargetConfigOptions["arch"] = "x86_64";
    break;
  default:
    // FIXME: Use `case llvm::Triple::arm64` when underlying LLVM is new enough
    if (StringRef("arm64") == llvm::Triple::getArchTypeName(triple.getArch()))
      LangOpts.TargetConfigOptions["arch"] = "arm64";
      break;
    llvm_unreachable("Unsupported target architecture");
  }
}

bool swift::CompilerInstance::setup(const CompilerInvocation &Invok) {
  Invocation = Invok;

  // Honor -Xllvm.
  if (!Invok.getFrontendOptions().LLVMArgs.empty()) {
    llvm::SmallVector<const char *, 4> Args;
    Args.push_back("swift (LLVM option parsing)");
    for (unsigned i = 0, e = Invok.getFrontendOptions().LLVMArgs.size(); i != e;
         ++i)
      Args.push_back(Invok.getFrontendOptions().LLVMArgs[i].c_str());
    Args.push_back(nullptr);
    llvm::cl::ParseCommandLineOptions(Args.size()-1, Args.data());
  }

  // Initialize the target build configuration settings ("os" and "arch").
  setTargetConfigurations(Invocation.getIRGenOptions(),
                          Invocation.getLangOptions());

  Context.reset(new ASTContext(Invocation.getLangOptions(),
                               Invocation.getSearchPathOptions(),
                               SourceMgr, Diagnostics));

  if (Invocation.getFrontendOptions().EnableSourceImport) {
    bool immediate = Invocation.getFrontendOptions().actionIsImmediate();
    Context->addModuleLoader(SourceLoader::create(*Context, !immediate));
  }

  SML = SerializedModuleLoader::create(*Context);
  Context->addModuleLoader(SML);

  // Wire up the Clang importer. If the user has specified an SDK, use it.
  // Otherwise, we just keep it around as our interface to Clang's ABI
  // knowledge.
  auto ImporterCtor = swift::getClangImporterCtor();
  if (ImporterCtor) {
    auto clangImporter =
        ImporterCtor(*Context, Invocation.getTargetTriple(),
                     Invocation.getClangImporterOptions());
    if (!clangImporter) {
      Diagnostics.diagnose(SourceLoc(), diag::error_clang_importer_create_fail);
      return true;
    }

    Context->addModuleLoader(clangImporter, /*isClang*/true);
  } else if (!Invocation.getSDKPath().empty()) {
    Diagnostics.diagnose(SourceLoc(),
                         diag::error_clang_importer_not_linked_in);
    return true;
  }

  assert(Lexer::isIdentifier(Invocation.getModuleName()));

  auto CodeCompletePoint = Invocation.getCodeCompletionPoint();
  if (CodeCompletePoint.first) {
    auto MemBuf = CodeCompletePoint.first;
    // CompilerInvocation doesn't own the buffers, copy to a new buffer.
    unsigned CodeCompletionBufferID = SourceMgr.addMemBufferCopy(MemBuf);
    BufferIDs.push_back(CodeCompletionBufferID);
    SourceMgr.setCodeCompletionPoint(CodeCompletionBufferID,
                                     CodeCompletePoint.second);
  }

  bool MainMode = (Invocation.getInputKind() == SourceFileKind::Main);
  bool SILMode = (Invocation.getInputKind() == SourceFileKind::SIL);

  const Optional<SelectedInput> &PrimaryInput =
    Invocation.getFrontendOptions().PrimaryInput;

  // Add the memory buffers first, these will be associated with a filename
  // and they can replace the contents of an input filename.
  for (unsigned i = 0, e = Invocation.getInputBuffers().size(); i != e; ++i) {
    // CompilerInvocation doesn't own the buffers, copy to a new buffer.
    unsigned BufferID =
        SourceMgr.addMemBufferCopy(Invocation.getInputBuffers()[i]);
    BufferIDs.push_back(BufferID);

    if (SILMode)
      MainBufferID = BufferID;

    if (PrimaryInput && PrimaryInput->isBuffer() && PrimaryInput->Index == i)
      PrimaryBufferID = BufferID;
  }

  for (unsigned i = 0, e = Invocation.getInputFilenames().size(); i != e; ++i) {
    auto &File = Invocation.getInputFilenames()[i];

    // FIXME: Working with filenames is fragile, maybe use the real path
    // or have some kind of FileManager.
    using namespace llvm::sys::path;
    if (Optional<unsigned> ExistingBufferID =
            SourceMgr.getIDForBufferIdentifier(File)) {
      if (SILMode || (MainMode && filename(File) == "main.swift"))
        MainBufferID = ExistingBufferID.getValue();

      if (PrimaryInput && PrimaryInput->isFilename() &&
          PrimaryInput->Index == i)
        PrimaryBufferID = ExistingBufferID.getValue();

      continue; // replaced by a memory buffer.
    }

    // Open the input file.
    std::unique_ptr<llvm::MemoryBuffer> InputFile;
    if (llvm::error_code Err =
          llvm::MemoryBuffer::getFileOrSTDIN(File, InputFile)) {
      Diagnostics.diagnose(SourceLoc(), diag::error_open_input_file,
                           File, Err.message());
      return true;
    }

    unsigned BufferID = SourceMgr.addNewSourceBuffer(std::move(InputFile));

    // Transfer ownership of the MemoryBuffer to the SourceMgr.
    BufferIDs.push_back(BufferID);

    if (SILMode || (MainMode && filename(File) == "main.swift"))
      MainBufferID = BufferID;

    if (PrimaryInput && PrimaryInput->isFilename() && PrimaryInput->Index == i)
      PrimaryBufferID = BufferID;
  }

  if (MainMode && MainBufferID == NO_SUCH_BUFFER && BufferIDs.size() == 1)
    MainBufferID = BufferIDs.front();

  return false;
}

void CompilerInstance::performParse() {
  const SourceFileKind Kind = Invocation.getInputKind();
  Identifier ID = Context->getIdentifier(Invocation.getModuleName());
  MainModule = Module::create(ID, *Context);
  Context->LoadedModules[ID.str()] = MainModule;

  if (Kind == SourceFileKind::SIL) {
    assert(BufferIDs.size() == 1);
    assert(MainBufferID != NO_SUCH_BUFFER);
    createSILModule();
  }

  if (Kind == SourceFileKind::REPL) {
    auto *SingleInputFile =
      new (*Context) SourceFile(*MainModule, Kind, {},
                                Invocation.getParseStdlib());
    MainModule->addFile(*SingleInputFile);
    return;
  }

  std::unique_ptr<DelayedParsingCallbacks> DelayedCB;
  if (Invocation.isCodeCompletion()) {
    DelayedCB.reset(
        new CodeCompleteDelayedCallbacks(SourceMgr.getCodeCompletionLoc()));
  } else if (Invocation.isDelayedFunctionBodyParsing()) {
    DelayedCB.reset(new AlwaysDelayedCallbacks);
  }

  PersistentParserState PersistentState;

  // Make sure the main file is the first file in the module. This may only be
  // a source file, or it may be a SIL file, which requires pumping the parser.
  // We parse it last, though, to make sure that it can use decls from other
  // files in the module.
  if (MainBufferID != NO_SUCH_BUFFER) {
    assert(Kind == SourceFileKind::Main || Kind == SourceFileKind::SIL);

    if (Kind == SourceFileKind::Main)
      SourceMgr.setHashbangBufferID(MainBufferID);

    auto *SingleInputFile =
      new (*Context) SourceFile(*MainModule, Kind, MainBufferID,
                                Invocation.getParseStdlib());
    MainModule->addFile(*SingleInputFile);

    if (MainBufferID == PrimaryBufferID)
      PrimarySourceFile = SingleInputFile;
  }

  bool hadLoadError = false;

  // Parse all the library files first.
  for (auto BufferID : BufferIDs) {
    if (BufferID == MainBufferID)
      continue;

    auto Buffer = SourceMgr->getMemoryBuffer(BufferID);
    if (SerializedModuleLoader::isSerializedAST(Buffer->getBuffer())) {
      std::unique_ptr<llvm::MemoryBuffer> Input(
        llvm::MemoryBuffer::getMemBuffer(Buffer->getBuffer(),
                                         Buffer->getBufferIdentifier(),
                                         false));
      if (!SML->loadAST(*MainModule, SourceLoc(), std::move(Input)))
        hadLoadError = true;
      continue;
    }

    auto *NextInput = new (*Context) SourceFile(*MainModule,
                                                SourceFileKind::Library,
                                                BufferID,
                                                Invocation.getParseStdlib());
    MainModule->addFile(*NextInput);

    if (BufferID == PrimaryBufferID)
      PrimarySourceFile = NextInput;

    bool Done;
    parseIntoSourceFile(*NextInput, BufferID, &Done, nullptr,
                        &PersistentState, DelayedCB.get());
    assert(Done && "Parser returned early?");
    (void) Done;

    performNameBinding(*NextInput);
  }

  if (hadLoadError)
    return;

  // Parse the main file last.
  if (MainBufferID != NO_SUCH_BUFFER) {
    SourceFile &MainFile = MainModule->getMainSourceFile(Kind);
    SILParserState SILContext(TheSILModule.get());
    unsigned CurTUElem = 0;
    bool Done;
    do {
      // Pump the parser multiple times if necessary.  It will return early
      // after parsing any top level code in a main module, or in SIL mode when
      // there are chunks of swift decls (e.g. imports and types) interspersed
      // with 'sil' definitions.
      parseIntoSourceFile(MainFile, MainFile.getBufferID().getValue(), &Done,
                          TheSILModule ? &SILContext : nullptr,
                          &PersistentState, DelayedCB.get());
      if (!Invocation.getParseOnly() && (PrimaryBufferID == NO_SUCH_BUFFER ||
                                         MainBufferID == PrimaryBufferID))
        performTypeChecking(MainFile, PersistentState.getTopLevelContext(),
                            CurTUElem);
      CurTUElem = MainFile.Decls.size();
    } while (!Done);
  }

  if (!Invocation.getParseOnly()) {
    // Type-check each top-level input besides the main source file.
    for (auto File : MainModule->getFiles())
      if (auto SF = dyn_cast<SourceFile>(File))
        if (PrimaryBufferID == NO_SUCH_BUFFER ||
            (SF->getBufferID().hasValue() &&
             SF->getBufferID().getValue() == PrimaryBufferID))
          performTypeChecking(*SF, PersistentState.getTopLevelContext());

    // Even if there were no source files, we should still record known
    // protocols.
    if (Context->getStdlibModule())
      Context->recordKnownProtocols(Context->getStdlibModule());
  }

  if (DelayedCB) {
    performDelayedParsing(MainModule, PersistentState,
                          Invocation.getCodeCompletionFactory());
  }
}

<|endoftext|>


<commit_before>//===---- GenConstant.cpp - Swift IR Generation For Constants ---*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
//  This file implements IR generation for constant values.
//
//===----------------------------------------------------------------------===//

#include "llvm/IR/Constants.h"

#include "GenConstant.h"
#include "GenStruct.h"
#include "GenTuple.h"
#include "TypeInfo.h"
#include "swift/Basic/Range.h"

using namespace swift;
using namespace irgen;

llvm::Constant *irgen::emitConstantInt(IRGenModule &IGM,
                                       IntegerLiteralInst *ILI) {
  APInt value = ILI->getValue();
  BuiltinIntegerWidth width
    = ILI->getType().castTo<BuiltinIntegerType>()->getWidth();

  // The value may need truncation if its type had an abstract size.
  if (width.isFixedWidth()) {
    // nothing to do
  } else if (width.isPointerWidth()) {
    unsigned pointerWidth = IGM.getPointerSize().getValueInBits();
    assert(pointerWidth <= value.getBitWidth()
           && "lost precision at AST/SIL level?!");
    if (pointerWidth < value.getBitWidth())
      value = value.trunc(pointerWidth);
  } else {
    llvm_unreachable("impossible width value");
  }

  return llvm::ConstantInt::get(IGM.LLVMContext, value);
}

llvm::Constant *irgen::emitConstantFP(IRGenModule &IGM, FloatLiteralInst *FLI) {
  return llvm::ConstantFP::get(IGM.LLVMContext, FLI->getValue());
}

llvm::Constant *irgen::emitAddrOfConstantString(IRGenModule &IGM,
                                                StringLiteralInst *SLI) {
  switch (SLI->getEncoding()) {
  case StringLiteralInst::Encoding::UTF8:
    return IGM.getAddrOfGlobalString(SLI->getValue());

  case StringLiteralInst::Encoding::UTF16: {
    // This is always a GEP of a GlobalVariable with a nul terminator.
    auto addr = IGM.getAddrOfGlobalUTF16String(SLI->getValue());

    // Cast to Builtin.RawPointer.
    return llvm::ConstantExpr::getBitCast(addr, IGM.Int8PtrTy);
  }

  case StringLiteralInst::Encoding::ObjCSelector:
    llvm_unreachable("cannot get the address of an Objective-C selector");
  }
  llvm_unreachable("bad string encoding");
}

static llvm::Constant *emitConstantValue(IRGenModule &IGM, SILValue operand) {
  if (auto *SI = dyn_cast<StructInst>(operand))
    return emitConstantStruct(IGM, SI);
  else if (auto *TI = dyn_cast<TupleInst>(operand))
    return emitConstantTuple(IGM, TI);
  else if (auto *ILI = dyn_cast<IntegerLiteralInst>(operand))
    return emitConstantInt(IGM, ILI);
  else if (auto *FLI = dyn_cast<FloatLiteralInst>(operand))
    return emitConstantFP(IGM, FLI);
  else if (auto *SLI = dyn_cast<StringLiteralInst>(operand))
    return emitAddrOfConstantString(IGM, SLI);
  else
    llvm_unreachable("Unsupported SILInstruction in static initializer!");
}

static template <typename InstTy, typename NextIndexFunc>
llvm::Constant *emitConstantStructOrTuple(IRGenModule &IGM, InstTy inst,
                                          NextIndexFunc nextIndex) {
  auto type = inst->getType();
  auto *sTy = cast<llvm::StructType>(IGM.getTypeInfo(type).getStorageType());

  SmallVector<llvm::Constant *, 32> elts(sTy->getNumElements(), nullptr);

  // run over the Swift initialisers, putting them into the struct as
  // appropriate.
  for (unsigned i = 0, e = inst->getElements().size(); i != e; i++) {
    auto operand = inst->getOperand(i);
    unsigned index = nextIndex(IGM, type, i);

    assert(elts[index] == nullptr &&
           "Unexpected constant struct field overlap");

    elts[index] = emitConstantValue(IGM, operand);
  }

  // fill in any gaps, which are the explicit padding that swiftc inserts.
  for (unsigned i = 0, e = elts.size(); i != e; i++) {
    auto &elt = elts[i];
    if (elt == nullptr) {
      auto *eltTy = sTy->getElementType(i);
      assert(eltTy->isArrayTy() &&
             eltTy->getArrayElementType()->isIntegerTy(8) &&
             "Unexpected non-byte-array type for constrant struct padding");
      elt = llvm::UndefValue::get(eltTy);
    }
  }

  return llvm::ConstantStruct::get(sTy, elts);
}

llvm::Constant *irgen::emitConstantStruct(IRGenModule &IGM, StructInst *SI) {
  // The only way to get a struct's stored properties (which we need to map to
  // their physical/LLVM index) is to iterate over the properties
  // progressively. Fortunately the iteration order matches the order of
  // operands in a StructInst.
  auto StoredProperties = SI->getStructDecl()->getStoredProperties();
  auto Iter = StoredProperties.begin();

  return emitConstantStructOrTuple(
      IGM, SI, [&Iter](IRGenModule &IGM, SILType Type, unsigned _i) mutable {
        (void)_i;
        auto *FD = *Iter++;
        return irgen::getPhysicalStructFieldIndex(IGM, Type, FD);
      });
}

llvm::Constant *irgen::emitConstantTuple(IRGenModule &IGM, TupleInst *TI) {
  return emitConstantStructOrTuple(IGM, TI, irgen::getTupleElementStructIndex);
}
<commit_msg>[IRGen] Streamline integer literal emission.<commit_after>//===---- GenConstant.cpp - Swift IR Generation For Constants ---*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
//  This file implements IR generation for constant values.
//
//===----------------------------------------------------------------------===//

#include "llvm/IR/Constants.h"

#include "GenConstant.h"
#include "GenStruct.h"
#include "GenTuple.h"
#include "TypeInfo.h"
#include "swift/Basic/Range.h"

using namespace swift;
using namespace irgen;

llvm::Constant *irgen::emitConstantInt(IRGenModule &IGM,
                                       IntegerLiteralInst *ILI) {
  APInt value = ILI->getValue();
  BuiltinIntegerWidth width
    = ILI->getType().castTo<BuiltinIntegerType>()->getWidth();

  // The value may need truncation if its type had an abstract size.
  if (!width.isFixedWidth()) {
    assert(width.isPointerWidth() && "impossible width value");

    unsigned pointerWidth = IGM.getPointerSize().getValueInBits();
    assert(pointerWidth <= value.getBitWidth()
           && "lost precision at AST/SIL level?!");
    if (pointerWidth < value.getBitWidth())
      value = value.trunc(pointerWidth);
  }

  return llvm::ConstantInt::get(IGM.LLVMContext, value);
}

llvm::Constant *irgen::emitConstantFP(IRGenModule &IGM, FloatLiteralInst *FLI) {
  return llvm::ConstantFP::get(IGM.LLVMContext, FLI->getValue());
}

llvm::Constant *irgen::emitAddrOfConstantString(IRGenModule &IGM,
                                                StringLiteralInst *SLI) {
  switch (SLI->getEncoding()) {
  case StringLiteralInst::Encoding::UTF8:
    return IGM.getAddrOfGlobalString(SLI->getValue());

  case StringLiteralInst::Encoding::UTF16: {
    // This is always a GEP of a GlobalVariable with a nul terminator.
    auto addr = IGM.getAddrOfGlobalUTF16String(SLI->getValue());

    // Cast to Builtin.RawPointer.
    return llvm::ConstantExpr::getBitCast(addr, IGM.Int8PtrTy);
  }

  case StringLiteralInst::Encoding::ObjCSelector:
    llvm_unreachable("cannot get the address of an Objective-C selector");
  }
  llvm_unreachable("bad string encoding");
}

static llvm::Constant *emitConstantValue(IRGenModule &IGM, SILValue operand) {
  if (auto *SI = dyn_cast<StructInst>(operand))
    return emitConstantStruct(IGM, SI);
  else if (auto *TI = dyn_cast<TupleInst>(operand))
    return emitConstantTuple(IGM, TI);
  else if (auto *ILI = dyn_cast<IntegerLiteralInst>(operand))
    return emitConstantInt(IGM, ILI);
  else if (auto *FLI = dyn_cast<FloatLiteralInst>(operand))
    return emitConstantFP(IGM, FLI);
  else if (auto *SLI = dyn_cast<StringLiteralInst>(operand))
    return emitAddrOfConstantString(IGM, SLI);
  else
    llvm_unreachable("Unsupported SILInstruction in static initializer!");
}

static template <typename InstTy, typename NextIndexFunc>
llvm::Constant *emitConstantStructOrTuple(IRGenModule &IGM, InstTy inst,
                                          NextIndexFunc nextIndex) {
  auto type = inst->getType();
  auto *sTy = cast<llvm::StructType>(IGM.getTypeInfo(type).getStorageType());

  SmallVector<llvm::Constant *, 32> elts(sTy->getNumElements(), nullptr);

  // run over the Swift initialisers, putting them into the struct as
  // appropriate.
  for (unsigned i = 0, e = inst->getElements().size(); i != e; i++) {
    auto operand = inst->getOperand(i);
    unsigned index = nextIndex(IGM, type, i);

    assert(elts[index] == nullptr &&
           "Unexpected constant struct field overlap");

    elts[index] = emitConstantValue(IGM, operand);
  }

  // fill in any gaps, which are the explicit padding that swiftc inserts.
  for (unsigned i = 0, e = elts.size(); i != e; i++) {
    auto &elt = elts[i];
    if (elt == nullptr) {
      auto *eltTy = sTy->getElementType(i);
      assert(eltTy->isArrayTy() &&
             eltTy->getArrayElementType()->isIntegerTy(8) &&
             "Unexpected non-byte-array type for constrant struct padding");
      elt = llvm::UndefValue::get(eltTy);
    }
  }

  return llvm::ConstantStruct::get(sTy, elts);
}

llvm::Constant *irgen::emitConstantStruct(IRGenModule &IGM, StructInst *SI) {
  // The only way to get a struct's stored properties (which we need to map to
  // their physical/LLVM index) is to iterate over the properties
  // progressively. Fortunately the iteration order matches the order of
  // operands in a StructInst.
  auto StoredProperties = SI->getStructDecl()->getStoredProperties();
  auto Iter = StoredProperties.begin();

  return emitConstantStructOrTuple(
      IGM, SI, [&Iter](IRGenModule &IGM, SILType Type, unsigned _i) mutable {
        (void)_i;
        auto *FD = *Iter++;
        return irgen::getPhysicalStructFieldIndex(IGM, Type, FD);
      });
}

llvm::Constant *irgen::emitConstantTuple(IRGenModule &IGM, TupleInst *TI) {
  return emitConstantStructOrTuple(IGM, TI, irgen::getTupleElementStructIndex);
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2007-2008 Digital Bazaar, Inc.  All rights reserved.
 */
#include <iostream>
#include <sstream>

#include "db/test/Test.h"
#include "db/test/Tester.h"
#include "db/test/TestRunner.h"
#include "db/io/ByteArrayInputStream.h"
#include "db/mail/SmtpClient.h"
#include "db/mail/MailTemplateParser.h"
#include "db/mail/MailSpool.h"
#include "db/net/Url.h"

using namespace std;
using namespace db::io;
using namespace db::net;
using namespace db::test;
using namespace db::rt;

void runSmtpClientTest(TestRunner& tr)
{
   tr.test("SmtpClient");

   // set url of mail server
   Url url("smtp://localhost:25");

   // set mail
   db::mail::Mail mail;
   mail.setSender("testuser@bitmunk.com");
   mail.addTo("support@bitmunk.com");
   mail.addCc("support@bitmunk.com");
   mail.setSubject("This is an autogenerated unit test email");
   mail.setBody("This is the test body");

   // send mail
   db::mail::SmtpClient c;
   c.sendMail(&url, &mail);

   tr.passIfNoException();
}

void runMailTemplateParser(TestRunner& tr)
{
   tr.test("MailTemplateParser");

   // create mail template
   const char* tpl =
      "Subject: This is an autogenerated unit test email\r\n"
      "From: testuser@bitmunk.com\r\n"
      "To: support@bitmunk.com\r\n"
      "Cc: support@bitmunk.com\r\n"
      "Bcc: $bccAddress1\r\n"
      "\r\n"
      "This is the test body. I want \\$10.00.\n"
      "I used a variable: \\$bccAddress1 with the value of "
      "'$bccAddress1'.\n"
      "Slash before variable \\\\$bccAddress1.\n"
      "2 slashes before variable \\\\\\\\$bccAddress1.\n"
      "Slash before escaped variable \\\\\\$bccAddress1.\n"
      "2 slashes before escaped variable \\\\\\\\\\$bccAddress1.\n"
      "$eggs$bacon$ham$sausage.";

   // create template parser
   db::mail::MailTemplateParser parser;

   // create input stream
   ByteArrayInputStream bais(tpl, strlen(tpl));

   // create variables
   DynamicObject vars;
   vars["bccAddress1"] = "support@bitmunk.com";
   vars["eggs"] = "This is a ";
   //vars["bacon"] -- no bacon
   vars["ham"] = "number ";
   vars["sausage"] = 5;

   // parse mail
   db::mail::Mail mail;
   parser.parse(&mail, vars, &bais);

   const char* expect =
      "This is the test body. I want $10.00.\r\n"
      "I used a variable: $bccAddress1 with the value of "
      "'support@bitmunk.com'.\r\n"
      "Slash before variable \\support@bitmunk.com.\r\n"
      "2 slashes before variable \\\\support@bitmunk.com.\r\n"
      "Slash before escaped variable \\$bccAddress1.\r\n"
      "2 slashes before escaped variable \\\\$bccAddress1.\r\n"
      "This is a number 5.\r\n";

   // get mail message
   db::mail::Message msg = mail.getMessage();

   // assert body parsed properly
   const char* body = msg["body"]->getString();
   assertStrCmp(body, expect);

   // create template from mail
   string generatedTemplate = mail.toTemplate();
   cout << "Generated template=\n" << generatedTemplate << std::endl;

//   // print out mail message
//   cout << "\nHeaders=\n";
//   DynamicObjectIterator i = msg["headers"].getIterator();
//   while(i->hasNext())
//   {
//      DynamicObject header = i->next();
//      DynamicObjectIterator doi = header.getIterator();
//      while(doi->hasNext())
//      {
//         cout << i->getName() << ": " << doi->next()->getString() << endl;
//      }
//   }
//
//   cout << "Expect=\n" << expect << endl;
//   cout << "Body=\n" << msg["body"]->getString() << endl;

//   // set url of mail server
//   Url url("smtp://localhost:25");
//
//   // send mail
//   db::mail::SmtpClient c;
//   c.sendMail(&url, &mail);

   tr.passIfNoException();
}

void mailSpoolTest(TestRunner& tr)
{
   tr.test("MailSpool");

   // create mail template
   const char* tpl =
      "Subject: This is an autogenerated unit test email\r\n"
      "From: testuser@bitmunk.com\r\n"
      "To: support@bitmunk.com\r\n"
      "Cc: support@bitmunk.com\r\n"
      "Bcc: $bccAddress1\r\n"
      "\r\n"
      "This is the test body. I want \\$10.00.\n"
      "I used a variable: \\$bccAddress1 with the value of "
      "'$bccAddress1'.\n"
      "Slash before variable \\\\$bccAddress1.\n"
      "2 slashes before variable \\\\\\\\$bccAddress1.\n"
      "Slash before escaped variable \\\\\\$bccAddress1.\n"
      "2 slashes before escaped variable \\\\\\\\\\$bccAddress1.\n"
      "$eggs$bacon$ham$sausage.";

   // create template parser
   db::mail::MailTemplateParser parser;

   // create input stream
   ByteArrayInputStream bais(tpl, strlen(tpl));

   // create variables
   DynamicObject vars;
   vars["bccAddress1"] = "support@bitmunk.com";
   vars["eggs"] = "This is a ";
   //vars["bacon"] -- no bacon
   vars["ham"] = "number ";
   vars["sausage"] = 5;

   // parse mail
   db::mail::Mail mail;
   parser.parse(&mail, vars, &bais);

   // get template
   string tpl1 = mail.toTemplate();

   // clean up old spool files
   File file("/tmp/bmtestspool");
   File idxFile("/tmp/bmtestspool.idx");
   idxFile->remove();
   file->remove();

   // create mail spool
   db::mail::MailSpool spool;
   spool.setFile(file);
   assertNoException();

   // spool mail
   spool.spool(&mail);
   assertNoException();

   // spool mail
   spool.spool(&mail);
   assertNoException();

   // spool mail
   spool.spool(&mail);
   assertNoException();

   // get mail
   db::mail::Mail m2;
   spool.getFirst(&m2);
   assertNoException();

   // assert templates are equal
   string tpl2 = m2.toTemplate();
   assertStrCmp(tpl1.c_str(), tpl2.c_str());

   // unwind
   spool.unwind();
   spool.unwind();
   assertNoException();

   // get mail
   db::mail::Mail m3;
   spool.getFirst(&m3);
   assertNoException();

   // assert templates are equal
   string tpl3 = m3.toTemplate();
   assertStrCmp(tpl1.c_str(), tpl3.c_str());

   // unwind
   spool.unwind();

   // get first mail (should exception, spool is empty)
   spool.getFirst(&m3);
   assertException();
   Exception::clearLast();

   tr.passIfNoException();
}

class DbMailTester : public db::test::Tester
{
public:
   DbMailTester()
   {
      setName("mail");
   }

   /**
    * Run automatic unit tests.
    */
   virtual int runAutomaticTests(TestRunner& tr)
   {
      //runSmtpClientTest(tr);
      runMailTemplateParser(tr);
      mailSpoolTest(tr);
      return 0;
   }

   /**
    * Runs interactive unit tests.
    */
   virtual int runInteractiveTests(TestRunner& tr)
   {
      return 0;
   }
};

#ifndef DB_TEST_NO_MAIN
DB_TEST_MAIN(DbMailTester)
#endif
<commit_msg>Check template output.<commit_after>/*
 * Copyright (c) 2007-2008 Digital Bazaar, Inc.  All rights reserved.
 */
#include <iostream>
#include <sstream>

#include "db/test/Test.h"
#include "db/test/Tester.h"
#include "db/test/TestRunner.h"
#include "db/io/ByteArrayInputStream.h"
#include "db/mail/SmtpClient.h"
#include "db/mail/MailTemplateParser.h"
#include "db/mail/MailSpool.h"
#include "db/net/Url.h"

using namespace std;
using namespace db::io;
using namespace db::net;
using namespace db::test;
using namespace db::rt;

void runSmtpClientTest(TestRunner& tr)
{
   tr.test("SmtpClient");

   // set url of mail server
   Url url("smtp://localhost:25");

   // set mail
   db::mail::Mail mail;
   mail.setSender("testuser@bitmunk.com");
   mail.addTo("support@bitmunk.com");
   mail.addCc("support@bitmunk.com");
   mail.setSubject("This is an autogenerated unit test email");
   mail.setBody("This is the test body");

   // send mail
   db::mail::SmtpClient c;
   c.sendMail(&url, &mail);

   tr.passIfNoException();
}

void runMailTemplateParser(TestRunner& tr)
{
   tr.test("MailTemplateParser");

   // create mail template
   const char* tpl =
      "Subject: This is an autogenerated unit test email\r\n"
      "From: testuser@bitmunk.com\r\n"
      "To: support@bitmunk.com\r\n"
      "Cc: support@bitmunk.com\r\n"
      "Bcc: $bccAddress1\r\n"
      "\r\n"
      "This is the test body. I want \\$10.00.\n"
      "I used a variable: \\$bccAddress1 with the value of "
      "'$bccAddress1'.\n"
      "Slash before variable \\\\$bccAddress1.\n"
      "2 slashes before variable \\\\\\\\$bccAddress1.\n"
      "Slash before escaped variable \\\\\\$bccAddress1.\n"
      "2 slashes before escaped variable \\\\\\\\\\$bccAddress1.\n"
      "$eggs$bacon$ham$sausage.";

   // create template parser
   db::mail::MailTemplateParser parser;

   // create input stream
   ByteArrayInputStream bais(tpl, strlen(tpl));

   // create variables
   DynamicObject vars;
   vars["bccAddress1"] = "support@bitmunk.com";
   vars["eggs"] = "This is a ";
   //vars["bacon"] -- no bacon
   vars["ham"] = "number ";
   vars["sausage"] = 5;

   // parse mail
   db::mail::Mail mail;
   parser.parse(&mail, vars, &bais);

   const char* expect =
      "This is the test body. I want $10.00.\r\n"
      "I used a variable: $bccAddress1 with the value of "
      "'support@bitmunk.com'.\r\n"
      "Slash before variable \\support@bitmunk.com.\r\n"
      "2 slashes before variable \\\\support@bitmunk.com.\r\n"
      "Slash before escaped variable \\$bccAddress1.\r\n"
      "2 slashes before escaped variable \\\\$bccAddress1.\r\n"
      "This is a number 5.\r\n";

   // get mail message
   db::mail::Message msg = mail.getMessage();

   // assert body parsed properly
   const char* body = msg["body"]->getString();
   assertStrCmp(body, expect);

   // create template from mail
   string generatedTemplate = mail.toTemplate();

   const char* genExpect =
      "CC: support@bitmunk.com\r\n"
      "From: testuser@bitmunk.com\r\n"
      "Subject: This is an autogenerated unit test email\r\n"
      "To: support@bitmunk.com\r\n"
      "\r\n"
      "This is the test body. I want \\$10.00.\r\n"
      "I used a variable: \\$bccAddress1 with the value of 'support@bitmunk.com'.\r\n"
      "Slash before variable \\\\support@bitmunk.com.\r\n"
      "2 slashes before variable \\\\\\\\support@bitmunk.com.\r\n"
      "Slash before escaped variable \\\\\\$bccAddress1.\r\n"
      "2 slashes before escaped variable \\\\\\\\\\$bccAddress1.\r\n"
      "This is a number 5.\r\n";

   assertStrCmp(generatedTemplate.c_str(), genExpect);
   //cout << "Generated template=\n" << generatedTemplate << std::endl;

//   // print out mail message
//   cout << "\nHeaders=\n";
//   DynamicObjectIterator i = msg["headers"].getIterator();
//   while(i->hasNext())
//   {
//      DynamicObject header = i->next();
//      DynamicObjectIterator doi = header.getIterator();
//      while(doi->hasNext())
//      {
//         cout << i->getName() << ": " << doi->next()->getString() << endl;
//      }
//   }
//
//   cout << "Expect=\n" << expect << endl;
//   cout << "Body=\n" << msg["body"]->getString() << endl;

//   // set url of mail server
//   Url url("smtp://localhost:25");
//
//   // send mail
//   db::mail::SmtpClient c;
//   c.sendMail(&url, &mail);

   tr.passIfNoException();
}

void mailSpoolTest(TestRunner& tr)
{
   tr.test("MailSpool");

   // create mail template
   const char* tpl =
      "Subject: This is an autogenerated unit test email\r\n"
      "From: testuser@bitmunk.com\r\n"
      "To: support@bitmunk.com\r\n"
      "Cc: support@bitmunk.com\r\n"
      "Bcc: $bccAddress1\r\n"
      "\r\n"
      "This is the test body. I want \\$10.00.\n"
      "I used a variable: \\$bccAddress1 with the value of "
      "'$bccAddress1'.\n"
      "Slash before variable \\\\$bccAddress1.\n"
      "2 slashes before variable \\\\\\\\$bccAddress1.\n"
      "Slash before escaped variable \\\\\\$bccAddress1.\n"
      "2 slashes before escaped variable \\\\\\\\\\$bccAddress1.\n"
      "$eggs$bacon$ham$sausage.";

   // create template parser
   db::mail::MailTemplateParser parser;

   // create input stream
   ByteArrayInputStream bais(tpl, strlen(tpl));

   // create variables
   DynamicObject vars;
   vars["bccAddress1"] = "support@bitmunk.com";
   vars["eggs"] = "This is a ";
   //vars["bacon"] -- no bacon
   vars["ham"] = "number ";
   vars["sausage"] = 5;

   // parse mail
   db::mail::Mail mail;
   parser.parse(&mail, vars, &bais);

   // get template
   string tpl1 = mail.toTemplate();

   // clean up old spool files
   File file("/tmp/bmtestspool");
   File idxFile("/tmp/bmtestspool.idx");
   idxFile->remove();
   file->remove();

   // create mail spool
   db::mail::MailSpool spool;
   spool.setFile(file);
   assertNoException();

   // spool mail
   spool.spool(&mail);
   assertNoException();

   // spool mail
   spool.spool(&mail);
   assertNoException();

   // spool mail
   spool.spool(&mail);
   assertNoException();

   // get mail
   db::mail::Mail m2;
   spool.getFirst(&m2);
   assertNoException();

   // assert templates are equal
   string tpl2 = m2.toTemplate();
   assertStrCmp(tpl1.c_str(), tpl2.c_str());

   // unwind
   spool.unwind();
   spool.unwind();
   assertNoException();

   // get mail
   db::mail::Mail m3;
   spool.getFirst(&m3);
   assertNoException();

   // assert templates are equal
   string tpl3 = m3.toTemplate();
   assertStrCmp(tpl1.c_str(), tpl3.c_str());

   // unwind
   spool.unwind();

   // get first mail (should exception, spool is empty)
   spool.getFirst(&m3);
   assertException();
   Exception::clearLast();

   tr.passIfNoException();
}

class DbMailTester : public db::test::Tester
{
public:
   DbMailTester()
   {
      setName("mail");
   }

   /**
    * Run automatic unit tests.
    */
   virtual int runAutomaticTests(TestRunner& tr)
   {
      //runSmtpClientTest(tr);
      runMailTemplateParser(tr);
      mailSpoolTest(tr);
      return 0;
   }

   /**
    * Runs interactive unit tests.
    */
   virtual int runInteractiveTests(TestRunner& tr)
   {
      return 0;
   }
};

#ifndef DB_TEST_NO_MAIN
DB_TEST_MAIN(DbMailTester)
#endif
<|endoftext|>


<commit_before>// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2009 Gael Guennebaud <gael.guennebaud@inria.fr>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.

#define EIGEN2_SUPPORT

#include "main.h"

template<typename MatrixType> void eigen2support(const MatrixType& m)
{
  typedef typename MatrixType::Index Index;
  typedef typename MatrixType::Scalar Scalar;

  Index rows = m.rows();
  Index cols = m.cols();

  MatrixType m1 = MatrixType::Random(rows, cols),
             m3(rows, cols);

  Scalar  s1 = internal::random<Scalar>(),
          s2 = internal::random<Scalar>();

  // scalar addition
  VERIFY_IS_APPROX(m1.cwise() + s1, s1 + m1.cwise());
  VERIFY_IS_APPROX(m1.cwise() + s1, MatrixType::Constant(rows,cols,s1) + m1);
  VERIFY_IS_APPROX((m1*Scalar(2)).cwise() - s2, (m1+m1) - MatrixType::Constant(rows,cols,s2) );
  m3 = m1;
  m3.cwise() += s2;
  VERIFY_IS_APPROX(m3, m1.cwise() + s2);
  m3 = m1;
  m3.cwise() -= s1;
  VERIFY_IS_APPROX(m3, m1.cwise() - s1);

  VERIFY_IS_EQUAL((m1.corner(TopLeft,1,1)), (m1.block(0,0,1,1)));
  VERIFY_IS_EQUAL((m1.template corner<1,1>(TopLeft)), (m1.template block<1,1>(0,0)));
  VERIFY_IS_EQUAL((m1.col(0).start(1)), (m1.col(0).segment(0,1)));
  VERIFY_IS_EQUAL((m1.col(0).template start<1>()), (m1.col(0).segment(0,1)));
  VERIFY_IS_EQUAL((m1.col(0).end(1)), (m1.col(0).segment(rows-1,1)));
  VERIFY_IS_EQUAL((m1.col(0).template end<1>()), (m1.col(0).segment(rows-1,1)));

  using std::cos;
  using numext::real;
  using numext::abs2;
  VERIFY_IS_EQUAL(ei_cos(s1), cos(s1));
  VERIFY_IS_EQUAL(ei_real(s1), real(s1));
  VERIFY_IS_EQUAL(ei_abs2(s1), abs2(s1));

  m1.minor(0,0);
}

void test_eigen2support()
{
  for(int i = 0; i < g_repeat; i++) {
    CALL_SUBTEST_1( eigen2support(Matrix<double,1,1>()) );
    CALL_SUBTEST_2( eigen2support(MatrixXd(1,1)) );
    CALL_SUBTEST_4( eigen2support(Matrix3f()) );
    CALL_SUBTEST_5( eigen2support(Matrix4d()) );
    CALL_SUBTEST_2( eigen2support(MatrixXf(200,200)) );
    CALL_SUBTEST_6( eigen2support(MatrixXcd(100,100)) );
  }
}
<commit_msg>Disable another Eigen2 deprecated warning<commit_after>// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2009 Gael Guennebaud <gael.guennebaud@inria.fr>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.

#define EIGEN2_SUPPORT
#define EIGEN_NO_EIGEN2_DEPRECATED_WARNING

#include "main.h"

template<typename MatrixType> void eigen2support(const MatrixType& m)
{
  typedef typename MatrixType::Index Index;
  typedef typename MatrixType::Scalar Scalar;

  Index rows = m.rows();
  Index cols = m.cols();

  MatrixType m1 = MatrixType::Random(rows, cols),
             m3(rows, cols);

  Scalar  s1 = internal::random<Scalar>(),
          s2 = internal::random<Scalar>();

  // scalar addition
  VERIFY_IS_APPROX(m1.cwise() + s1, s1 + m1.cwise());
  VERIFY_IS_APPROX(m1.cwise() + s1, MatrixType::Constant(rows,cols,s1) + m1);
  VERIFY_IS_APPROX((m1*Scalar(2)).cwise() - s2, (m1+m1) - MatrixType::Constant(rows,cols,s2) );
  m3 = m1;
  m3.cwise() += s2;
  VERIFY_IS_APPROX(m3, m1.cwise() + s2);
  m3 = m1;
  m3.cwise() -= s1;
  VERIFY_IS_APPROX(m3, m1.cwise() - s1);

  VERIFY_IS_EQUAL((m1.corner(TopLeft,1,1)), (m1.block(0,0,1,1)));
  VERIFY_IS_EQUAL((m1.template corner<1,1>(TopLeft)), (m1.template block<1,1>(0,0)));
  VERIFY_IS_EQUAL((m1.col(0).start(1)), (m1.col(0).segment(0,1)));
  VERIFY_IS_EQUAL((m1.col(0).template start<1>()), (m1.col(0).segment(0,1)));
  VERIFY_IS_EQUAL((m1.col(0).end(1)), (m1.col(0).segment(rows-1,1)));
  VERIFY_IS_EQUAL((m1.col(0).template end<1>()), (m1.col(0).segment(rows-1,1)));

  using std::cos;
  using numext::real;
  using numext::abs2;
  VERIFY_IS_EQUAL(ei_cos(s1), cos(s1));
  VERIFY_IS_EQUAL(ei_real(s1), real(s1));
  VERIFY_IS_EQUAL(ei_abs2(s1), abs2(s1));

  m1.minor(0,0);
}

void test_eigen2support()
{
  for(int i = 0; i < g_repeat; i++) {
    CALL_SUBTEST_1( eigen2support(Matrix<double,1,1>()) );
    CALL_SUBTEST_2( eigen2support(MatrixXd(1,1)) );
    CALL_SUBTEST_4( eigen2support(Matrix3f()) );
    CALL_SUBTEST_5( eigen2support(Matrix4d()) );
    CALL_SUBTEST_2( eigen2support(MatrixXf(200,200)) );
    CALL_SUBTEST_6( eigen2support(MatrixXcd(100,100)) );
  }
}
<|endoftext|>