<commit_before>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2009 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#include <mapnik/noncopyable.hpp>
#include <mapnik/util/variant.hpp>
// boost
#include <memory>
//sqlite3
#include <sqlite3.h>

//stl
#ifdef MAPNIK_DEBUG
#include <iostream>
#include <cassert>
#endif
#include <string>
#include <vector>

namespace mapnik {  namespace sqlite {

    class database : private mapnik::noncopyable
    {
        friend class prepared_statement;

        struct database_closer
        {
            void operator () (sqlite3 * db)
            {
#ifdef MAPNIK_DEBUG
                std::cerr << "close database " << db << "\n";
#endif
                sqlite3_close(db);
            }
        };

        using sqlite_db = std::shared_ptr<sqlite3>;
        sqlite_db db_;

    public:
        database(std::string const& name);
        ~database();
        bool execute(std::string const& sql);
    };

    struct null_type {};
    struct blob
    {
        blob(const char* buf, unsigned size)
            : buf_(buf), size_(size) {}

        const char * buf_;
        unsigned size_;
    };

    using value_type = mapnik::util::variant<int,double,std::string, blob,null_type>;
    using record_type = std::vector<value_type>;

    class prepared_statement : mapnik::noncopyable
    {
        struct binder : public mapnik::util::static_visitor<bool>
        {
            binder(sqlite3_stmt * stmt, unsigned index)
                : stmt_(stmt), index_(index) {}

            bool operator() (null_type )
            {
                if (sqlite3_bind_null(stmt_, index_) != SQLITE_OK)
                {
                    std::cerr << "cannot bind nullptr\n";
                    return false;
                }
                return true;
            }

            bool operator() (int val)
            {
                if (sqlite3_bind_int(stmt_, index_ , val ) != SQLITE_OK)
                {
                    std::cerr << "cannot bind " << val << "\n";
                    return false;
                }
                return true;
            }

            bool operator() (double val)
            {
                if (sqlite3_bind_double(stmt_, index_ , val ) != SQLITE_OK)
                {
                    std::cerr << "cannot bind " << val << "\n";
                    return false;
                }
                return true;
            }

            bool operator() (std::string const& val)
            {
                if (sqlite3_bind_text(stmt_, index_, val.c_str(), val.length(), SQLITE_STATIC) != SQLITE_OK)
                {
                    std::cerr << "cannot bind " << val << "\n";
                    return false;
                }
                return true;
            }

            bool operator() (blob const& val)
            {
                if (sqlite3_bind_blob(stmt_, index_, val.buf_, val.size_, SQLITE_STATIC) != SQLITE_OK)
                {
                    std::cerr << "cannot bind BLOB\n";
                    return false;
                }
                return true;
            }

            sqlite3_stmt * stmt_;
            unsigned index_;
        };
    public:
        prepared_statement(database & db, std::string const& sql)
            : db_(db.db_.get()), stmt_(0)
        {
            const char * tail;
            //char * err_msg;
            int res = sqlite3_prepare_v2(db_, sql.c_str(),-1, &stmt_,&tail);
            if (res != SQLITE_OK)
            {
                std::cerr << "ERR:"<< res << "\n";
                throw;
            }
        }

        ~prepared_statement()
        {
            int res = sqlite3_finalize(stmt_);
            if (res != SQLITE_OK)
            {
                std::cerr << "ERR:" << res << "\n";
            }
        }

        bool insert_record(record_type const& rec) const
        {
#ifdef MAPNIK_DEBUG
            assert( unsigned(sqlite3_bind_parameter_count(stmt_)) == rec.size());
#endif
            record_type::const_iterator itr = rec.begin();
            record_type::const_iterator end = rec.end();
            int count = 1;
            for (; itr!=end;++itr)
            {
                binder op(stmt_,count++);
                if (!util::apply_visitor(op,*itr))
                {
                    return false;
                }
            }

            sqlite3_step(stmt_);
            sqlite3_reset(stmt_);

            return true;
        }

    private:
        sqlite3 * db_;
        sqlite3_stmt * stmt_;
    };
    }
}
<commit_msg>we do need <iostrea> in non-debug<commit_after>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2009 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#include <mapnik/noncopyable.hpp>
#include <mapnik/util/variant.hpp>
// boost
#include <memory>
//sqlite3
#include <sqlite3.h>

//stl
#ifdef MAPNIK_DEBUG
#include <cassert>
#endif

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

namespace mapnik {  namespace sqlite {

    class database : private mapnik::noncopyable
    {
        friend class prepared_statement;

        struct database_closer
        {
            void operator () (sqlite3 * db)
            {
#ifdef MAPNIK_DEBUG
                std::cerr << "close database " << db << "\n";
#endif
                sqlite3_close(db);
            }
        };

        using sqlite_db = std::shared_ptr<sqlite3>;
        sqlite_db db_;

    public:
        database(std::string const& name);
        ~database();
        bool execute(std::string const& sql);
    };

    struct null_type {};
    struct blob
    {
        blob(const char* buf, unsigned size)
            : buf_(buf), size_(size) {}

        const char * buf_;
        unsigned size_;
    };

    using value_type = mapnik::util::variant<int,double,std::string, blob,null_type>;
    using record_type = std::vector<value_type>;

    class prepared_statement : mapnik::noncopyable
    {
        struct binder : public mapnik::util::static_visitor<bool>
        {
            binder(sqlite3_stmt * stmt, unsigned index)
                : stmt_(stmt), index_(index) {}

            bool operator() (null_type )
            {
                if (sqlite3_bind_null(stmt_, index_) != SQLITE_OK)
                {
                    std::cerr << "cannot bind nullptr\n";
                    return false;
                }
                return true;
            }

            bool operator() (int val)
            {
                if (sqlite3_bind_int(stmt_, index_ , val ) != SQLITE_OK)
                {
                    std::cerr << "cannot bind " << val << "\n";
                    return false;
                }
                return true;
            }

            bool operator() (double val)
            {
                if (sqlite3_bind_double(stmt_, index_ , val ) != SQLITE_OK)
                {
                    std::cerr << "cannot bind " << val << "\n";
                    return false;
                }
                return true;
            }

            bool operator() (std::string const& val)
            {
                if (sqlite3_bind_text(stmt_, index_, val.c_str(), val.length(), SQLITE_STATIC) != SQLITE_OK)
                {
                    std::cerr << "cannot bind " << val << "\n";
                    return false;
                }
                return true;
            }

            bool operator() (blob const& val)
            {
                if (sqlite3_bind_blob(stmt_, index_, val.buf_, val.size_, SQLITE_STATIC) != SQLITE_OK)
                {
                    std::cerr << "cannot bind BLOB\n";
                    return false;
                }
                return true;
            }

            sqlite3_stmt * stmt_;
            unsigned index_;
        };
    public:
        prepared_statement(database & db, std::string const& sql)
            : db_(db.db_.get()), stmt_(0)
        {
            const char * tail;
            //char * err_msg;
            int res = sqlite3_prepare_v2(db_, sql.c_str(),-1, &stmt_,&tail);
            if (res != SQLITE_OK)
            {
                std::cerr << "ERR:"<< res << "\n";
                throw;
            }
        }

        ~prepared_statement()
        {
            int res = sqlite3_finalize(stmt_);
            if (res != SQLITE_OK)
            {
                std::cerr << "ERR:" << res << "\n";
            }
        }

        bool insert_record(record_type const& rec) const
        {
#ifdef MAPNIK_DEBUG
            assert( unsigned(sqlite3_bind_parameter_count(stmt_)) == rec.size());
#endif
            record_type::const_iterator itr = rec.begin();
            record_type::const_iterator end = rec.end();
            int count = 1;
            for (; itr!=end;++itr)
            {
                binder op(stmt_,count++);
                if (!util::apply_visitor(op,*itr))
                {
                    return false;
                }
            }

            sqlite3_step(stmt_);
            sqlite3_reset(stmt_);

            return true;
        }

    private:
        sqlite3 * db_;
        sqlite3_stmt * stmt_;
    };
    }
}
<|endoftext|>


<commit_before>// @(#)root/test:$Name:  $:$Id: MainEvent.cxx,v 1.15 2001/04/20 17:56:50 rdm Exp $
// Author: Rene Brun   19/01/97

////////////////////////////////////////////////////////////////////////
//
//             A simple example with a ROOT tree
//             =================================
//
//  This program creates :
//    - a ROOT file
//    - a tree
//  Additional arguments can be passed to the program to control the flow
//  of execution. (see comments describing the arguments in the code).
//      Event  nevent comp split fill
//  All arguments are optional. Default is:
//      Event  400      1    1     1
//
//  In this example, the tree consists of one single "super branch"
//  The statement ***tree->Branch("event", event, 64000,split);*** below
//  will parse the structure described in Event.h and will make
//  a new branch for each data member of the class if split is set to 1.
//    - 5 branches corresponding to the basic types fNtrack,fNseg,fNvertex
//           ,fFlag and fTemperature.
//    - 3 branches corresponding to the members of the subobject EventHeader.
//    - one branch for each data member of the class Track of TClonesArray.
//    - one branch for the object fH (histogram of class TH1F).
//
//  if split = 0 only one single branch is created and the complete event
//  is serialized in one single buffer.
//  if split = -1 the event is split using the old TBranchObject mechanism
//  if split > 0  the event is split ising the new TBranchElement mechanism.
//
//  if comp = 0 no compression at all.
//  if comp = 1 event is compressed.
//  if comp = 2 same as 1. In addition branches with floats in the TClonesArray
//                         are also compressed.
//  The 4th argument fill can be set to 0 if one wants to time
//     the percentage of time spent in creating the event structure and
//     not write the event in the file.
//  In this example, one loops over nevent events.
//  The branch "event" is created at the first event.
//  The branch address is set for all other events.
//  For each event, the event header is filled and ntrack tracks
//  are generated and added to the TClonesArray list.
//  For each event the event histogram is saved as well as the list
//  of all tracks.
//
//  The number of events can be given as the first argument to the program.
//  By default 400 events are generated.
//  The compression option can be activated/deactivated via the second argument.
//
//   ---Running/Linking instructions----
//  This program consists of the following files and procedures.
//    - Event.h event class description
//    - Event.C event class implementation
//    - MainEvent.C the main program to demo this class might be used (this file)
//    - EventCint.C  the CINT dictionary for the event and Track classes
//        this file is automatically generated by rootcint (see Makefile),
//        when the class definition in Event.h is modified.
//
//   ---Analyzing the Event.root file with the interactive root
//        example of a simple session
//   Root > TFile f("Event.root")
//   Root > T.Draw("fNtrack")   //histogram the number of tracks per event
//   Root > T.Draw("fPx")       //histogram fPx for all tracks in all events
//   Root > T.Draw("fXfirst:fYfirst","fNtrack>600")
//                              //scatter-plot for x versus y of first point of each track
//   Root > T.Draw("fH.GetRMS()")  //histogram of the RMS of the event histogram
//
//   Look also in the same directory at the following macros:
//     - eventa.C  an example how to read the tree
//     - eventb.C  how to read events conditionally
//
////////////////////////////////////////////////////////////////////////

#include <stdlib.h>

#include "TROOT.h"
#include "TFile.h"
#include "TNetFile.h"
#include "TRandom.h"
#include "TTree.h"
#include "TBranch.h"
#include "TClonesArray.h"
#include "TStopwatch.h"

#include "Event.h"

//______________________________________________________________________________
int main(int argc, char **argv)
{
   Int_t nevent = 400;     // by default create 400 events
   Int_t comp   = 1;       // by default file is compressed
   Int_t split  = 1;       // by default, split Event in sub branches
   Int_t write  = 1;       // by default the tree is filled
   Int_t hfill  = 0;       // by default histograms are not filled
   Int_t read   = 0;
   Int_t arg4   = 1;
   Int_t arg5   = 600;     //default number of tracks per event
   Int_t netf   = 0;

   if (argc > 1)  nevent = atoi(argv[1]);
   if (argc > 2)  comp   = atoi(argv[2]);
   if (argc > 3)  split  = atoi(argv[3]);
   if (argc > 4)  arg4   = atoi(argv[4]);
   if (argc > 5)  arg5   = atoi(argv[5]);
   if (arg4 ==  0) { write = 0; hfill = 0; read = 1;}
   if (arg4 ==  1) { write = 1; hfill = 0;}
   if (arg4 ==  2) { write = 0; hfill = 0;}
   if (arg4 == 10) { write = 0; hfill = 1;}
   if (arg4 == 11) { write = 1; hfill = 1;}
   if (arg4 == 20) { write = 0; read  = 1;}  //read sequential
   if (arg4 == 25) { write = 0; read  = 2;}  //read random
   if (arg4 >= 30) { netf  = 1; }            //use TNetFile
   if (arg4 == 30) { write = 0; read  = 1;}  //netfile + read sequential
   if (arg4 == 35) { write = 0; read  = 2;}  //netfile + read random
   if (arg4 == 36) { write = 1; }            //netfile + write sequential
   Int_t branchStyle = 1; //new style by default
   if (split < 0) {branchStyle = 0; split = -split;}

   TFile *hfile;
   TTree *tree;
   Event *event = 0;

   // Fill event, header and tracks with some random numbers
   //   Create a timer object to benchmark this loop
   TStopwatch timer;
   timer.Start();
   Int_t nb = 0;
   Int_t ev;
   Int_t bufsize;
   Double_t told = 0;
   Double_t tnew = 0;
   Int_t printev = 100;
   if (arg5 < 100) printev = 1000;
   if (arg5 < 10)  printev = 10000;

   Track::Class()->IgnoreTObjectStreamer();

//         Read case
   if (read) {
      if (netf) {
         hfile = new TNetFile("root://localhost/root/test/EventNet.root");
         hfile->UseCache(10);
      } else
         hfile = new TFile("Event.root");
      tree = (TTree*)hfile->Get("T");
      TBranch *branch = tree->GetBranch("event");
      branch->SetAddress(&event);
      Int_t nentries = (Int_t)tree->GetEntries();
      nevent = TMath::Max(nevent,nentries);
      if (read == 1) {  //read sequential
         for (ev = 0; ev < nevent; ev++) {
            if (ev%printev == 0) {
               tnew = timer.RealTime();
               printf("event:%d, rtime=%f s\n",ev,tnew-told);
               told=tnew;
               timer.Continue();
            }
            nb += tree->GetEntry(ev);        //read complete event in memory
         }
      } else {    //read random
         Int_t evrandom;
         for (ev = 0; ev < nevent; ev++) {
            if (ev%printev == 0) cout<<"event="<<ev<<endl;
            evrandom = Int_t(nevent*gRandom->Rndm(1));
            nb += tree->GetEntry(evrandom);  //read complete event in memory
         }
      }
   } else {
//         Write case
      // Create a new ROOT binary machine independent file.
      // Note that this file may contain any kind of ROOT objects, histograms,
      // pictures, graphics objects, detector geometries, tracks, events, etc..
      // This file is now becoming the current directory.
      if (netf) {
         hfile = new TNetFile("root://localhost/root/test/EventNet.root","RECREATE","TTree benchmark ROOT file");
         hfile->UseCache(10);
      } else
         hfile = new TFile("Event.root","RECREATE","TTree benchmark ROOT file");
      hfile->SetCompressionLevel(comp);

     // Create histogram to show write_time in function of time
     Float_t curtime = -0.5;
     Int_t ntime = nevent/printev;
     TH1F *htime = new TH1F("htime","Real-Time to write versus time",ntime,0,ntime);
     HistogramManager *hm = 0;
     if (hfill) {
        TDirectory *hdir = new TDirectory("histograms", "all histograms");
        hm = new HistogramManager(hdir);
     }

     // Create a ROOT Tree and one superbranch
      TTree *tree = new TTree("T","An example of a ROOT tree");
      tree->SetAutoSave(1000000000);  // autosave when 1 Gbyte written
      bufsize = 64000;
      if (split)  bufsize /= 4;
      event = new Event();
      TTree::SetBranchStyle(branchStyle);
      TBranch *branch = tree->Branch("event", "Event", &event, bufsize,split);
      branch->SetAutoDelete(kFALSE);
      char etype[20];

      for (ev = 0; ev < nevent; ev++) {
         if (ev%printev == 0) {
            tnew = timer.RealTime();
            printf("event:%d, rtime=%f s\n",ev,tnew-told);
            htime->Fill(curtime,tnew-told);
            curtime += 1;
            told=tnew;
            timer.Continue();
         }

         Float_t sigmat, sigmas;
         gRandom->Rannor(sigmat,sigmas);
         Int_t ntrack   = Int_t(arg5 +arg5*sigmat/120.);
         Float_t random = gRandom->Rndm(1);

         sprintf(etype,"type%d",ev%5);
         event->SetType(etype);
         event->SetHeader(ev, 200, 960312, random);
         event->SetNseg(Int_t(10*ntrack+20*sigmas));
         event->SetNvertex(Int_t(1+20*gRandom->Rndm()));
         event->SetFlag(UInt_t(random+0.5));
         event->SetTemperature(random+20.);

         for(UChar_t m = 0; m < 10; m++) {
            event->SetMeasure(m, Int_t(gRandom->Gaus(m,m+1)));
         }
         for(UChar_t i0 = 0; i0 < 4; i0++) {
            for(UChar_t i1 = 0; i1 < 4; i1++) {
               event->SetMatrix(i0,i1,gRandom->Gaus(i0*i1,1));
            }
         }

         //  Create and Fill the Track objects
         for (Int_t t = 0; t < ntrack; t++) event->AddTrack(random);

         if (write) nb += tree->Fill();  //fill the tree

         if (hm) hm->Hfill(event);      //fill histograms

         event->Clear();
      }
      if (write) {
         hfile->Write();
         tree->Print();
      }
   }

   //  Stop timer and print results
   timer.Stop();
   Float_t mbytes = 0.000001*nb;
   Double_t rtime = timer.RealTime();
   Double_t ctime = timer.CpuTime();

   printf("\n%d events and %d bytes processed.\n",nevent,nb);
   printf("RealTime=%f seconds, CpuTime=%f seconds\n",rtime,ctime);
   if (read) {
      printf("You read %f Mbytes/Realtime seconds\n",mbytes/rtime);
      printf("You read %f Mbytes/Cputime seconds\n",mbytes/ctime);
   } else {
      printf("compression level=%d, split=%d, arg4=%d\n",comp,split,arg4);
      printf("You write %f Mbytes/Realtime seconds\n",mbytes/rtime);
      printf("You write %f Mbytes/Cputime seconds\n",mbytes/ctime);
      //printf("file compression factor = %f\n",hfile.GetCompressionFactor());
   }
   hfile->Close();
   return 0;
}
<commit_msg>From Philippe: The following convention is now used for split: //  if split = 0 only one single branch is created and the complete event //  is serialized in one single buffer. //  if split = -2 the event is split using the old TBranchObject mechanism //  if split = -1 the event is streamed using the old TBranchObject mechanism //  if split > 0  the event is split ising the new TBranchElement mechanism.<commit_after>// @(#)root/test:$Name:  $:$Id: MainEvent.cxx,v 1.16 2001/04/24 14:32:46 brun Exp $
// Author: Rene Brun   19/01/97

////////////////////////////////////////////////////////////////////////
//
//             A simple example with a ROOT tree
//             =================================
//
//  This program creates :
//    - a ROOT file
//    - a tree
//  Additional arguments can be passed to the program to control the flow
//  of execution. (see comments describing the arguments in the code).
//      Event  nevent comp split fill
//  All arguments are optional. Default is:
//      Event  400      1    1     1
//
//  In this example, the tree consists of one single "super branch"
//  The statement ***tree->Branch("event", event, 64000,split);*** below
//  will parse the structure described in Event.h and will make
//  a new branch for each data member of the class if split is set to 1.
//    - 5 branches corresponding to the basic types fNtrack,fNseg,fNvertex
//           ,fFlag and fTemperature.
//    - 3 branches corresponding to the members of the subobject EventHeader.
//    - one branch for each data member of the class Track of TClonesArray.
//    - one branch for the object fH (histogram of class TH1F).
//
//  if split = 0 only one single branch is created and the complete event
//  is serialized in one single buffer.
//  if split = -2 the event is split using the old TBranchObject mechanism
//  if split = -1 the event is streamed using the old TBranchObject mechanism
//  if split > 0  the event is split ising the new TBranchElement mechanism.
//
//  if comp = 0 no compression at all.
//  if comp = 1 event is compressed.
//  if comp = 2 same as 1. In addition branches with floats in the TClonesArray
//                         are also compressed.
//  The 4th argument fill can be set to 0 if one wants to time
//     the percentage of time spent in creating the event structure and
//     not write the event in the file.
//  In this example, one loops over nevent events.
//  The branch "event" is created at the first event.
//  The branch address is set for all other events.
//  For each event, the event header is filled and ntrack tracks
//  are generated and added to the TClonesArray list.
//  For each event the event histogram is saved as well as the list
//  of all tracks.
//
//  The number of events can be given as the first argument to the program.
//  By default 400 events are generated.
//  The compression option can be activated/deactivated via the second argument.
//
//   ---Running/Linking instructions----
//  This program consists of the following files and procedures.
//    - Event.h event class description
//    - Event.C event class implementation
//    - MainEvent.C the main program to demo this class might be used (this file)
//    - EventCint.C  the CINT dictionary for the event and Track classes
//        this file is automatically generated by rootcint (see Makefile),
//        when the class definition in Event.h is modified.
//
//   ---Analyzing the Event.root file with the interactive root
//        example of a simple session
//   Root > TFile f("Event.root")
//   Root > T.Draw("fNtrack")   //histogram the number of tracks per event
//   Root > T.Draw("fPx")       //histogram fPx for all tracks in all events
//   Root > T.Draw("fXfirst:fYfirst","fNtrack>600")
//                              //scatter-plot for x versus y of first point of each track
//   Root > T.Draw("fH.GetRMS()")  //histogram of the RMS of the event histogram
//
//   Look also in the same directory at the following macros:
//     - eventa.C  an example how to read the tree
//     - eventb.C  how to read events conditionally
//
////////////////////////////////////////////////////////////////////////

#include <stdlib.h>

#include "TROOT.h"
#include "TFile.h"
#include "TNetFile.h"
#include "TRandom.h"
#include "TTree.h"
#include "TBranch.h"
#include "TClonesArray.h"
#include "TStopwatch.h"

#include "Event.h"

//______________________________________________________________________________
int main(int argc, char **argv)
{
   Int_t nevent = 400;     // by default create 400 events
   Int_t comp   = 1;       // by default file is compressed
   Int_t split  = 1;       // by default, split Event in sub branches
   Int_t write  = 1;       // by default the tree is filled
   Int_t hfill  = 0;       // by default histograms are not filled
   Int_t read   = 0;
   Int_t arg4   = 1;
   Int_t arg5   = 600;     //default number of tracks per event
   Int_t netf   = 0;

   if (argc > 1)  nevent = atoi(argv[1]);
   if (argc > 2)  comp   = atoi(argv[2]);
   if (argc > 3)  split  = atoi(argv[3]);
   if (argc > 4)  arg4   = atoi(argv[4]);
   if (argc > 5)  arg5   = atoi(argv[5]);
   if (arg4 ==  0) { write = 0; hfill = 0; read = 1;}
   if (arg4 ==  1) { write = 1; hfill = 0;}
   if (arg4 ==  2) { write = 0; hfill = 0;}
   if (arg4 == 10) { write = 0; hfill = 1;}
   if (arg4 == 11) { write = 1; hfill = 1;}
   if (arg4 == 20) { write = 0; read  = 1;}  //read sequential
   if (arg4 == 25) { write = 0; read  = 2;}  //read random
   if (arg4 >= 30) { netf  = 1; }            //use TNetFile
   if (arg4 == 30) { write = 0; read  = 1;}  //netfile + read sequential
   if (arg4 == 35) { write = 0; read  = 2;}  //netfile + read random
   if (arg4 == 36) { write = 1; }            //netfile + write sequential
   Int_t branchStyle = 1; //new style by default
   if (split < 0) {branchStyle = 0; split = 1-split;}

   TFile *hfile;
   TTree *tree;
   Event *event = 0;

   // Fill event, header and tracks with some random numbers
   //   Create a timer object to benchmark this loop
   TStopwatch timer;
   timer.Start();
   Int_t nb = 0;
   Int_t ev;
   Int_t bufsize;
   Double_t told = 0;
   Double_t tnew = 0;
   Int_t printev = 100;
   if (arg5 < 100) printev = 1000;
   if (arg5 < 10)  printev = 10000;

   Track::Class()->IgnoreTObjectStreamer();

//         Read case
   if (read) {
      if (netf) {
         hfile = new TNetFile("root://localhost/root/test/EventNet.root");
         hfile->UseCache(10);
      } else
         hfile = new TFile("Event.root");
      tree = (TTree*)hfile->Get("T");
      TBranch *branch = tree->GetBranch("event");
      branch->SetAddress(&event);
      Int_t nentries = (Int_t)tree->GetEntries();
      nevent = TMath::Max(nevent,nentries);
      if (read == 1) {  //read sequential
         for (ev = 0; ev < nevent; ev++) {
            if (ev%printev == 0) {
               tnew = timer.RealTime();
               printf("event:%d, rtime=%f s\n",ev,tnew-told);
               told=tnew;
               timer.Continue();
            }
            nb += tree->GetEntry(ev);        //read complete event in memory
         }
      } else {    //read random
         Int_t evrandom;
         for (ev = 0; ev < nevent; ev++) {
            if (ev%printev == 0) cout<<"event="<<ev<<endl;
            evrandom = Int_t(nevent*gRandom->Rndm(1));
            nb += tree->GetEntry(evrandom);  //read complete event in memory
         }
      }
   } else {
//         Write case
      // Create a new ROOT binary machine independent file.
      // Note that this file may contain any kind of ROOT objects, histograms,
      // pictures, graphics objects, detector geometries, tracks, events, etc..
      // This file is now becoming the current directory.
      if (netf) {
         hfile = new TNetFile("root://localhost/root/test/EventNet.root","RECREATE","TTree benchmark ROOT file");
         hfile->UseCache(10);
      } else
         hfile = new TFile("Event.root","RECREATE","TTree benchmark ROOT file");
      hfile->SetCompressionLevel(comp);

     // Create histogram to show write_time in function of time
     Float_t curtime = -0.5;
     Int_t ntime = nevent/printev;
     TH1F *htime = new TH1F("htime","Real-Time to write versus time",ntime,0,ntime);
     HistogramManager *hm = 0;
     if (hfill) {
        TDirectory *hdir = new TDirectory("histograms", "all histograms");
        hm = new HistogramManager(hdir);
     }

     // Create a ROOT Tree and one superbranch
      TTree *tree = new TTree("T","An example of a ROOT tree");
      tree->SetAutoSave(1000000000);  // autosave when 1 Gbyte written
      bufsize = 64000;
      if (split)  bufsize /= 4;
      event = new Event();
      TTree::SetBranchStyle(branchStyle);
      TBranch *branch = tree->Branch("event", "Event", &event, bufsize,split);
      branch->SetAutoDelete(kFALSE);
      char etype[20];

      for (ev = 0; ev < nevent; ev++) {
         if (ev%printev == 0) {
            tnew = timer.RealTime();
            printf("event:%d, rtime=%f s\n",ev,tnew-told);
            htime->Fill(curtime,tnew-told);
            curtime += 1;
            told=tnew;
            timer.Continue();
         }

         Float_t sigmat, sigmas;
         gRandom->Rannor(sigmat,sigmas);
         Int_t ntrack   = Int_t(arg5 +arg5*sigmat/120.);
         Float_t random = gRandom->Rndm(1);

         sprintf(etype,"type%d",ev%5);
         event->SetType(etype);
         event->SetHeader(ev, 200, 960312, random);
         event->SetNseg(Int_t(10*ntrack+20*sigmas));
         event->SetNvertex(Int_t(1+20*gRandom->Rndm()));
         event->SetFlag(UInt_t(random+0.5));
         event->SetTemperature(random+20.);

         for(UChar_t m = 0; m < 10; m++) {
            event->SetMeasure(m, Int_t(gRandom->Gaus(m,m+1)));
         }
         for(UChar_t i0 = 0; i0 < 4; i0++) {
            for(UChar_t i1 = 0; i1 < 4; i1++) {
               event->SetMatrix(i0,i1,gRandom->Gaus(i0*i1,1));
            }
         }

         //  Create and Fill the Track objects
         for (Int_t t = 0; t < ntrack; t++) event->AddTrack(random);

         if (write) nb += tree->Fill();  //fill the tree

         if (hm) hm->Hfill(event);      //fill histograms

         event->Clear();
      }
      if (write) {
         hfile->Write();
         tree->Print();
      }
   }

   //  Stop timer and print results
   timer.Stop();
   Float_t mbytes = 0.000001*nb;
   Double_t rtime = timer.RealTime();
   Double_t ctime = timer.CpuTime();

   printf("\n%d events and %d bytes processed.\n",nevent,nb);
   printf("RealTime=%f seconds, CpuTime=%f seconds\n",rtime,ctime);
   if (read) {
      printf("You read %f Mbytes/Realtime seconds\n",mbytes/rtime);
      printf("You read %f Mbytes/Cputime seconds\n",mbytes/ctime);
   } else {
      printf("compression level=%d, split=%d, arg4=%d\n",comp,split,arg4);
      printf("You write %f Mbytes/Realtime seconds\n",mbytes/rtime);
      printf("You write %f Mbytes/Cputime seconds\n",mbytes/ctime);
      //printf("file compression factor = %f\n",hfile.GetCompressionFactor());
   }
   hfile->Close();
   return 0;
}
<|endoftext|>


<commit_before>/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "orc/OrcFile.hh"
#include "wrap/gtest-wrapper.h"
#include "TestDriver.hh"

#include <sstream>

TEST(Reader, simpleTest) {
  orc::ReaderOptions opts;
  std::ostringstream filename;
  filename << exampleDirectory << "/demo-11-none.orc";
  std::unique_ptr<orc::Reader> reader =
    orc::createReader(orc::readLocalFile(filename.str()), opts);

  EXPECT_EQ(orc::CompressionKind_NONE, reader->getCompression());
  EXPECT_EQ(256 * 1024, reader->getCompressionSize());
  EXPECT_EQ(385, reader->getNumberOfStripes());
  EXPECT_EQ(1920800, reader->getNumberOfRows());
  EXPECT_EQ(10000, reader->getRowIndexStride());
  EXPECT_EQ(5069718, reader->getContentLength());
  EXPECT_EQ(filename.str(), reader->getStreamName());
  EXPECT_EQ(0, reader->getMetadataKeys().size());
  EXPECT_EQ(false, reader->hasMetadataValue("foo"));
  EXPECT_EQ(18446744073709551615UL, reader->getRowNumber());

  const orc::Type& rootType = reader->getType();
  EXPECT_EQ(0, rootType.getColumnId());
  EXPECT_EQ(orc::STRUCT, rootType.getKind());
  ASSERT_EQ(9, rootType.getSubtypeCount());
  EXPECT_EQ("_col0", rootType.getFieldName(0));
  EXPECT_EQ("_col1", rootType.getFieldName(1));
  EXPECT_EQ("_col2", rootType.getFieldName(2));
  EXPECT_EQ("_col3", rootType.getFieldName(3));
  EXPECT_EQ("_col4", rootType.getFieldName(4));
  EXPECT_EQ("_col5", rootType.getFieldName(5));
  EXPECT_EQ("_col6", rootType.getFieldName(6));
  EXPECT_EQ("_col7", rootType.getFieldName(7));
  EXPECT_EQ("_col8", rootType.getFieldName(8));
  EXPECT_EQ(orc::INT, rootType.getSubtype(0).getKind());
  EXPECT_EQ(orc::STRING, rootType.getSubtype(1).getKind());
  EXPECT_EQ(orc::STRING, rootType.getSubtype(2).getKind());
  EXPECT_EQ(orc::STRING, rootType.getSubtype(3).getKind());
  EXPECT_EQ(orc::INT, rootType.getSubtype(4).getKind());
  EXPECT_EQ(orc::STRING, rootType.getSubtype(5).getKind());
  EXPECT_EQ(orc::INT, rootType.getSubtype(6).getKind());
  EXPECT_EQ(orc::INT, rootType.getSubtype(7).getKind());
  EXPECT_EQ(orc::INT, rootType.getSubtype(8).getKind());
  for(unsigned int i=0; i < 9; ++i) {
    EXPECT_EQ(i + 1, rootType.getSubtype(i).getColumnId()) << "fail on " << i;
  }
  const bool* selected = reader->getSelectedColumns();
  for(int i=0; i < 10; ++i) {
    EXPECT_EQ(true, selected[i]) << "fail on " << i;
  }

  unsigned long rowCount = 0;
  std::unique_ptr<orc::ColumnVectorBatch> batch = reader->createRowBatch(1024);
  while (reader->next(*batch)) {
    EXPECT_EQ(rowCount, reader->getRowNumber());
    rowCount += batch->numElements;
  }
  EXPECT_EQ(1920800, rowCount);
  EXPECT_EQ(1920000, reader->getRowNumber());
}
<commit_msg>Correct unit test to use proper assertion macro.<commit_after>/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "orc/OrcFile.hh"
#include "wrap/gtest-wrapper.h"
#include "TestDriver.hh"

#include <sstream>

TEST(Reader, simpleTest) {
  orc::ReaderOptions opts;
  std::ostringstream filename;
  filename << exampleDirectory << "/demo-11-none.orc";
  std::unique_ptr<orc::Reader> reader =
    orc::createReader(orc::readLocalFile(filename.str()), opts);

  EXPECT_EQ(orc::CompressionKind_NONE, reader->getCompression());
  EXPECT_EQ(256 * 1024, reader->getCompressionSize());
  EXPECT_EQ(385, reader->getNumberOfStripes());
  EXPECT_EQ(1920800, reader->getNumberOfRows());
  EXPECT_EQ(10000, reader->getRowIndexStride());
  EXPECT_EQ(5069718, reader->getContentLength());
  EXPECT_EQ(filename.str(), reader->getStreamName());
  EXPECT_EQ(0, reader->getMetadataKeys().size());
  EXPECT_FALSE(reader->hasMetadataValue("foo"));
  EXPECT_EQ(18446744073709551615UL, reader->getRowNumber());

  const orc::Type& rootType = reader->getType();
  EXPECT_EQ(0, rootType.getColumnId());
  EXPECT_EQ(orc::STRUCT, rootType.getKind());
  ASSERT_EQ(9, rootType.getSubtypeCount());
  EXPECT_EQ("_col0", rootType.getFieldName(0));
  EXPECT_EQ("_col1", rootType.getFieldName(1));
  EXPECT_EQ("_col2", rootType.getFieldName(2));
  EXPECT_EQ("_col3", rootType.getFieldName(3));
  EXPECT_EQ("_col4", rootType.getFieldName(4));
  EXPECT_EQ("_col5", rootType.getFieldName(5));
  EXPECT_EQ("_col6", rootType.getFieldName(6));
  EXPECT_EQ("_col7", rootType.getFieldName(7));
  EXPECT_EQ("_col8", rootType.getFieldName(8));
  EXPECT_EQ(orc::INT, rootType.getSubtype(0).getKind());
  EXPECT_EQ(orc::STRING, rootType.getSubtype(1).getKind());
  EXPECT_EQ(orc::STRING, rootType.getSubtype(2).getKind());
  EXPECT_EQ(orc::STRING, rootType.getSubtype(3).getKind());
  EXPECT_EQ(orc::INT, rootType.getSubtype(4).getKind());
  EXPECT_EQ(orc::STRING, rootType.getSubtype(5).getKind());
  EXPECT_EQ(orc::INT, rootType.getSubtype(6).getKind());
  EXPECT_EQ(orc::INT, rootType.getSubtype(7).getKind());
  EXPECT_EQ(orc::INT, rootType.getSubtype(8).getKind());
  for(unsigned int i=0; i < 9; ++i) {
    EXPECT_EQ(i + 1, rootType.getSubtype(i).getColumnId()) << "fail on " << i;
  }
  const bool* selected = reader->getSelectedColumns();
  for(int i=0; i < 10; ++i) {
    EXPECT_EQ(true, selected[i]) << "fail on " << i;
  }

  unsigned long rowCount = 0;
  std::unique_ptr<orc::ColumnVectorBatch> batch = reader->createRowBatch(1024);
  while (reader->next(*batch)) {
    EXPECT_EQ(rowCount, reader->getRowNumber());
    rowCount += batch->numElements;
  }
  EXPECT_EQ(1920800, rowCount);
  EXPECT_EQ(1920000, reader->getRowNumber());
}
<|endoftext|>


<commit_before>/*
 * Copyright 2019 Kacper Kasper <kacperkasper@gmail.com>
 * All rights reserved. Distributed under the terms of the MIT license.
 */

#include <gtest/gtest.h>

#include "support/Utils.h"

// GetFileName

TEST(GetFileNameTest, HandlesNoExtension) {
	const std::string name = "test";
	const std::string result = GetFileName(name);
	const std::string expected = "test";
	ASSERT_EQ(result, expected);
}

TEST(GetFileNameTest, HandlesDotFile) {
	// FIXME: that's wrong
	const std::string name = ".test";
	const std::string result = GetFileName(name);
	const std::string expected = ".test";
	ASSERT_EQ(result, expected);
}

TEST(GetFileNameTest, HandlesDotFileWithExtension) {
	const std::string name = ".test.second";
	const std::string result = GetFileName(name);
	const std::string expected = ".test";
	ASSERT_EQ(result, expected);
}

TEST(GetFileNameTest, HandlesDotFileWithEmptyExtension) {
	const std::string name = ".test.";
	const std::string result = GetFileName(name);
	const std::string expected = ".test";
	ASSERT_EQ(result, expected);
}

TEST(GetFileNameTest, HandlesFileWithEmptyExtension) {
	const std::string name = "test.";
	const std::string result = GetFileName(name);
	const std::string expected = "test";
	ASSERT_EQ(result, expected);
}

TEST(GetFileNameTest, HandlesFileWithExtension) {
	const std::string name = "test.txt";
	const std::string result = GetFileName(name);
	const std::string expected = "test";
	ASSERT_EQ(result, expected);
}

TEST(GetFileNameTest, HandlesFileWithLongerExtension) {
	const std::string name = "testing.extension";
	const std::string result = GetFileName(name);
	const std::string expected = "testing";
	ASSERT_EQ(result, expected);
}

TEST(GetFileNameTest, HandlesFileWithTwoExtensions) {
	const std::string name = "testing.long.extension";
	const std::string result = GetFileName(name);
	const std::string expected = "testing.long";
	ASSERT_EQ(result, expected);
}

// GetFileExtension

TEST(GetFileExtensionTest, HandlesNoExtension) {
	const std::string name = "test";
	const std::string result = GetFileExtension(name);
	const std::string expected = "";
	ASSERT_EQ(result, expected);
}

TEST(GetFileExtensionTest, HandlesDotFile) {
	const std::string name = ".test";
	const std::string result = GetFileExtension(name);
	const std::string expected = "";
	ASSERT_EQ(result, expected);
}

TEST(GetFileExtensionTest, HandlesDotFileWithExtension) {
	const std::string name = ".test.second";
	const std::string result = GetFileExtension(name);
	const std::string expected = "second";
	ASSERT_EQ(result, expected);
}

TEST(GetFileExtensionTest, HandlesDotFileWithEmptyExtension) {
	const std::string name = ".test.";
	const std::string result = GetFileExtension(name);
	const std::string expected = "";
	ASSERT_EQ(result, expected);
}

TEST(GetFileExtensionTest, HandlesFileWithEmptyExtension) {
	const std::string name = "test.";
	const std::string result = GetFileExtension(name);
	const std::string expected = "";
	ASSERT_EQ(result, expected);
}

TEST(GetFileExtensionTest, HandlesFileWithExtension) {
	const std::string name = "test.txt";
	const std::string result = GetFileExtension(name);
	const std::string expected = "txt";
	ASSERT_EQ(result, expected);
}

TEST(GetFileExtensionTest, HandlesFileWithLongerExtension) {
	const std::string name = "testing.extension";
	const std::string result = GetFileExtension(name);
	const std::string expected = "extension";
	ASSERT_EQ(result, expected);
}

TEST(GetFileExtensionTest, HandlesFileWithTwoExtensions) {
	const std::string name = "testing.long.extension";
	const std::string result = GetFileExtension(name);
	const std::string expected = "extension";
	ASSERT_EQ(result, expected);
}
<commit_msg>Make unit tests less verbose<commit_after>/*
 * Copyright 2019 Kacper Kasper <kacperkasper@gmail.com>
 * All rights reserved. Distributed under the terms of the MIT license.
 */

#include <gtest/gtest.h>

#include "support/Utils.h"

// GetFileName

TEST(GetFileNameTest, HandlesNoExtension) {
	const std::string result = GetFileName("test");
	ASSERT_EQ(result, "test");
}

TEST(GetFileNameTest, HandlesDotFile) {
	const std::string result = GetFileName(".test");
	ASSERT_EQ(result, ".test");
}

TEST(GetFileNameTest, HandlesDotFileWithExtension) {
	const std::string result = GetFileName(".test.second");
	ASSERT_EQ(result, ".test");
}

TEST(GetFileNameTest, HandlesDotFileWithEmptyExtension) {
	const std::string result = GetFileName(".test.");
	ASSERT_EQ(result, ".test");
}

TEST(GetFileNameTest, HandlesFileWithEmptyExtension) {
	const std::string result = GetFileName("test.");
	ASSERT_EQ(result, "test");
}

TEST(GetFileNameTest, HandlesFileWithExtension) {
	const std::string result = GetFileName("test.txt");
	ASSERT_EQ(result, "test");
}

TEST(GetFileNameTest, HandlesFileWithLongerExtension) {
	const std::string result = GetFileName("testing.extension");
	ASSERT_EQ(result, "testing");
}

TEST(GetFileNameTest, HandlesFileWithTwoExtensions) {
	const std::string result = GetFileName("testing.long.extension");
	ASSERT_EQ(result, "testing.long");
}

// GetFileExtension

TEST(GetFileExtensionTest, HandlesNoExtension) {
	const std::string result = GetFileExtension("test");
	ASSERT_EQ(result, "");
}

TEST(GetFileExtensionTest, HandlesDotFile) {
	const std::string result = GetFileExtension(".test");
	ASSERT_EQ(result, "");
}

TEST(GetFileExtensionTest, HandlesDotFileWithExtension) {
	const std::string result = GetFileExtension(".test.second");
	ASSERT_EQ(result, "second");
}

TEST(GetFileExtensionTest, HandlesDotFileWithEmptyExtension) {
	const std::string result = GetFileExtension(".test.");
	ASSERT_EQ(result, "");
}

TEST(GetFileExtensionTest, HandlesFileWithEmptyExtension) {
	const std::string result = GetFileExtension("test.");
	ASSERT_EQ(result, "");
}

TEST(GetFileExtensionTest, HandlesFileWithExtension) {
	const std::string result = GetFileExtension("test.txt");
	ASSERT_EQ(result, "txt");
}

TEST(GetFileExtensionTest, HandlesFileWithLongerExtension) {
	const std::string result = GetFileExtension("testing.extension");
	ASSERT_EQ(result, "extension");
}

TEST(GetFileExtensionTest, HandlesFileWithTwoExtensions) {
	const std::string result = GetFileExtension("testing.long.extension");
	ASSERT_EQ(result, "extension");
}
<|endoftext|>


<commit_before>//===--- Substitution.cpp - Type substitutions ----------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
//  This file implements the Substitution class and operations on it.
//
//===----------------------------------------------------------------------===//

#include "swift/AST/Substitution.h"

#include "swift/AST/ASTContext.h"
#include "swift/AST/GenericEnvironment.h"
#include "swift/AST/Module.h"
#include "swift/AST/ProtocolConformance.h"
#include "swift/AST/SubstitutionMap.h"
#include "swift/AST/Types.h"
#include "llvm/ADT/DenseMap.h"

using namespace swift;

bool Substitution::operator==(const Substitution &other) const {
  // The archetypes may be missing, but we can compare them directly
  // because archetypes are always canonical.
  return
    Replacement->isEqual(other.Replacement) &&
    Conformance.equals(other.Conformance);
}

Substitution::Substitution(Type Replacement,
                           ArrayRef<ProtocolConformanceRef> Conformance)
  : Replacement(Replacement), Conformance(Conformance)
{
  // The replacement type must be materializable.
  assert(Replacement->isMaterializable()
         && "cannot substitute with a non-materializable type");
}

Substitution Substitution::subst(ModuleDecl *module,
                                 const SubstitutionMap &subMap) const {
  return subst(module, QuerySubstitutionMap{subMap},
               LookUpConformanceInSubstitutionMap(subMap));
}

Substitution Substitution::subst(ModuleDecl *module,
                                 TypeSubstitutionFn subs,
                                 LookupConformanceFn conformances) const {
  // Substitute the replacement.
  Type substReplacement = Replacement.subst(subs, conformances, None);
  assert(substReplacement && "substitution replacement failed");

  if (substReplacement->isEqual(Replacement))
    return *this;

  if (Conformance.empty()) {
    return {substReplacement, Conformance};
  }

  bool conformancesChanged = false;
  SmallVector<ProtocolConformanceRef, 4> substConformances;
  substConformances.reserve(Conformance.size());

  for (auto c : Conformance) {
    // If we have a concrete conformance, we need to substitute the
    // conformance to apply to the new type.
    if (c.isConcrete()) {
      auto substC = c.getConcrete()->subst(module, substReplacement,
                                           subs, conformances);
      substConformances.push_back(ProtocolConformanceRef(substC));
      if (c != substConformances.back())
        conformancesChanged = true;
      continue;
    }

    // Otherwise, we may need to fill in the conformance.
    ProtocolDecl *proto = c.getAbstract();
    Optional<ProtocolConformanceRef> conformance;

    // If the original type was an archetype, check the conformance map.
    if (Replacement->is<SubstitutableType>()
        || Replacement->is<DependentMemberType>()) {
      conformance = conformances(Replacement->getCanonicalType(),
                                 substReplacement,
                                 proto->getDeclaredType());
    }

    // If that didn't find anything, we can still synthesize AnyObject
    // conformances from thin air.  FIXME: gross.
    if (!conformance &&
        proto->isSpecificProtocol(KnownProtocolKind::AnyObject)) {
      auto classDecl
        = substReplacement->getClassOrBoundGenericClass();
      assert(classDecl);
      SmallVector<ProtocolConformance *, 1> lookupResults;
      classDecl->lookupConformance(classDecl->getParentModule(),
                                   proto, lookupResults);
      conformance = ProtocolConformanceRef(lookupResults.front());
    }

    assert(conformance);
    if (conformance->isConcrete())
      conformancesChanged = true;
    substConformances.push_back(*conformance);
  }
  assert(substConformances.size() == Conformance.size());

  ArrayRef<ProtocolConformanceRef> substConfs;
  if (conformancesChanged)
    substConfs = Replacement->getASTContext().AllocateCopy(substConformances);
  else
    substConfs = Conformance;

  return Substitution{substReplacement, substConfs};
}
<commit_msg>Handle archetypes inside Substitution::subst<commit_after>//===--- Substitution.cpp - Type substitutions ----------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
//  This file implements the Substitution class and operations on it.
//
//===----------------------------------------------------------------------===//

#include "swift/AST/Substitution.h"

#include "swift/AST/ASTContext.h"
#include "swift/AST/GenericEnvironment.h"
#include "swift/AST/Module.h"
#include "swift/AST/ProtocolConformance.h"
#include "swift/AST/SubstitutionMap.h"
#include "swift/AST/Types.h"
#include "llvm/ADT/DenseMap.h"

using namespace swift;

bool Substitution::operator==(const Substitution &other) const {
  // The archetypes may be missing, but we can compare them directly
  // because archetypes are always canonical.
  return
    Replacement->isEqual(other.Replacement) &&
    Conformance.equals(other.Conformance);
}

Substitution::Substitution(Type Replacement,
                           ArrayRef<ProtocolConformanceRef> Conformance)
  : Replacement(Replacement), Conformance(Conformance)
{
  // The replacement type must be materializable.
  assert(Replacement->isMaterializable()
         && "cannot substitute with a non-materializable type");
}

Substitution Substitution::subst(ModuleDecl *module,
                                 const SubstitutionMap &subMap) const {
  return subst(module, QuerySubstitutionMap{subMap},
               LookUpConformanceInSubstitutionMap(subMap));
}

Substitution Substitution::subst(ModuleDecl *module,
                                 TypeSubstitutionFn subs,
                                 LookupConformanceFn conformances) const {
  // Substitute the replacement.
  Type substReplacement = Replacement.subst(subs, conformances, None);
  assert(substReplacement && "substitution replacement failed");

  if (substReplacement->isEqual(Replacement))
    return *this;

  if (Conformance.empty()) {
    return {substReplacement, Conformance};
  }

  bool conformancesChanged = false;
  SmallVector<ProtocolConformanceRef, 4> substConformances;
  substConformances.reserve(Conformance.size());

  for (auto c : Conformance) {
    // If we have a concrete conformance, we need to substitute the
    // conformance to apply to the new type.
    if (c.isConcrete()) {
      auto substC = c.getConcrete()->subst(module, substReplacement,
                                           subs, conformances);
      substConformances.push_back(ProtocolConformanceRef(substC));
      if (c != substConformances.back())
        conformancesChanged = true;
      continue;
    }

    // Otherwise, we may need to fill in the conformance.
    ProtocolDecl *proto = c.getAbstract();
    Optional<ProtocolConformanceRef> conformance;

    // If the original type was an archetype, check the conformance map.
    if (Replacement->is<SubstitutableType>()
        || Replacement->is<DependentMemberType>()) {
      conformance = conformances(Replacement->getCanonicalType(),
                                 substReplacement,
                                 proto->getDeclaredType());
    }

    // If that didn't find anything, we can still synthesize AnyObject
    // conformances from thin air.  FIXME: gross.
    if (!conformance &&
        proto->isSpecificProtocol(KnownProtocolKind::AnyObject)) {
      auto archetype =
        dyn_cast<ArchetypeType>(substReplacement->getCanonicalType());
      // If classDecl is not nullptr, it is a concrete class.
      auto classDecl = substReplacement->getClassOrBoundGenericClass();
      if (!classDecl && archetype->getSuperclass()) {
        // Replacement type is an archetype with a superclass constraint.
        classDecl = archetype->getSuperclass()->getClassOrBoundGenericClass();
        assert(classDecl);
      }
      if (classDecl) {
        // Create a concrete conformance based on the conforming class.
        SmallVector<ProtocolConformance *, 1> lookupResults;
        classDecl->lookupConformance(classDecl->getParentModule(), proto,
                                     lookupResults);
        conformance = ProtocolConformanceRef(lookupResults.front());
      } else if (archetype && archetype->requiresClass()) {
        // Replacement type is an archetype with a class constraint.
        // Create an abstract conformance.
        conformance = ProtocolConformanceRef(proto);
      }
    }

    assert(conformance);
    if (conformance->isConcrete())
      conformancesChanged = true;
    substConformances.push_back(*conformance);
  }
  assert(substConformances.size() == Conformance.size());

  ArrayRef<ProtocolConformanceRef> substConfs;
  if (conformancesChanged)
    substConfs = Replacement->getASTContext().AllocateCopy(substConformances);
  else
    substConfs = Conformance;

  return Substitution{substReplacement, substConfs};
}
<|endoftext|>


<commit_before>// RUN: %check_clang_tidy %s readability-deleted-default %t

class NoDefault {
public:
  NoDefault() = delete;
  NoDefault(NoDefault &&Other) = delete;
  NoDefault(const NoDefault &Other) = delete;
};

class MissingEverything {
public:
  MissingEverything() = default;
  // CHECK-MESSAGES: warning: default constructor is explicitly defaulted but implicitly deleted, probably because a non-static data member or a base class is lacking a default constructor; definition can either be removed or explicitly deleted [readability-deleted-default]
  MissingEverything(MissingEverything &&Other) = default;
  // CHECK-MESSAGES: warning: move constructor is explicitly defaulted but implicitly deleted, probably because a non-static data member or a base class is neither copyable nor movable; definition can either be removed or explicitly deleted [readability-deleted-default]
  MissingEverything(const MissingEverything &Other) = default;
  // CHECK-MESSAGES: warning: copy constructor is explicitly defaulted but implicitly deleted, probably because a non-static data member or a base class is not copyable; definition can either be removed or explicitly deleted [readability-deleted-default]
  MissingEverything &operator=(MissingEverything &&Other) = default;
  // CHECK-MESSAGES: warning: move assignment operator is explicitly defaulted but implicitly deleted, probably because a base class or a non-static data member is not assignable, e.g. because the latter is marked 'const'; definition can either be removed or explicitly deleted [readability-deleted-default]
  MissingEverything &operator=(const MissingEverything &Other) = default;
  // CHECK-MESSAGES: warning: copy assignment operator is explicitly defaulted but implicitly deleted, probably because a base class or a non-static data member is not assignable, e.g. because the latter is marked 'const'; definition can either be removed or explicitly deleted [readability-deleted-default]

private:
  NoDefault ND;
};

class NotAssignable {
public:
  NotAssignable(NotAssignable &&Other) = default;
  NotAssignable(const NotAssignable &Other) = default;
  NotAssignable &operator=(NotAssignable &&Other) = default;
  // CHECK-MESSAGES: warning: move assignment operator is explicitly defaulted but implicitly deleted
  NotAssignable &operator=(const NotAssignable &Other) = default;
  // CHECK-MESSAGES: warning: copy assignment operator is explicitly defaulted but implicitly deleted

private:
  const int I = 0;
};

class Movable {
public:
  Movable() = default;
  Movable(Movable &&Other) = default;
  Movable(const Movable &Other) = delete;
  Movable &operator=(Movable &&Other) = default;
  Movable &operator=(const Movable &Other) = delete;
};

class NotCopyable {
public:
  NotCopyable(NotCopyable &&Other) = default;
  NotCopyable(const NotCopyable &Other) = default;
  // CHECK-MESSAGES: warning: copy constructor is explicitly defaulted but implicitly deleted
  NotCopyable &operator=(NotCopyable &&Other) = default;
  NotCopyable &operator=(const NotCopyable &Other) = default;
  // CHECK-MESSAGES: warning: copy assignment operator is explicitly defaulted but implicitly deleted
private:
  Movable M;
};

template <typename T> class Templated {
public:
  // No warning here, it is a templated class.
  Templated() = default;
  Templated(Templated &&Other) = default;
  Templated(const Templated &Other) = default;
  Templated &operator=(Templated &&Other) = default;
  Templated &operator=(const Templated &Other) = default;

  class InnerTemplated {
  public:
    // This class is not in itself templated, but we still don't have warning.
    InnerTemplated() = default;
    InnerTemplated(InnerTemplated &&Other) = default;
    InnerTemplated(const InnerTemplated &Other) = default;
    InnerTemplated &operator=(InnerTemplated &&Other) = default;
    InnerTemplated &operator=(const InnerTemplated &Other) = default;

  private:
    T TVar;
  };

  class InnerNotTemplated {
  public:
    // This one could technically have warnings, but currently doesn't.
    InnerNotTemplated() = default;
    InnerNotTemplated(InnerNotTemplated &&Other) = default;
    InnerNotTemplated(const InnerNotTemplated &Other) = default;
    InnerNotTemplated &operator=(InnerNotTemplated &&Other) = default;
    InnerNotTemplated &operator=(const InnerNotTemplated &Other) = default;

  private:
    int I;
  };

private:
  const T TVar{};
};

int FunctionWithInnerClass() {
  class InnerNotAssignable {
  public:
    InnerNotAssignable &operator=(InnerNotAssignable &&Other) = default;
    // CHECK-MESSAGES: warning: move assignment operator is explicitly defaulted but implicitly deleted
  private:
    const int I = 0;
  };
  return 1;
};

template <typename T>
int TemplateFunctionWithInnerClass() {
  class InnerNotAssignable {
  public:
    InnerNotAssignable &operator=(InnerNotAssignable &&Other) = default;
  private:
    const T TVar{};
  };
  return 1;
};

void Foo() {
  Templated<const int> V1;
  Templated<int>::InnerTemplated V2;
  Templated<float>::InnerNotTemplated V3;
  TemplateFunctionWithInnerClass<int>();
}
<commit_msg>clang-tools-extra/test/clang-tidy/readability-deleted-default.cpp: Add -fno-ms-compatibility.<commit_after>// RUN: %check_clang_tidy %s readability-deleted-default %t -- -- -std=c++11 -fno-ms-compatibility

class NoDefault {
public:
  NoDefault() = delete;
  NoDefault(NoDefault &&Other) = delete;
  NoDefault(const NoDefault &Other) = delete;
};

class MissingEverything {
public:
  MissingEverything() = default;
  // CHECK-MESSAGES: warning: default constructor is explicitly defaulted but implicitly deleted, probably because a non-static data member or a base class is lacking a default constructor; definition can either be removed or explicitly deleted [readability-deleted-default]
  MissingEverything(MissingEverything &&Other) = default;
  // CHECK-MESSAGES: warning: move constructor is explicitly defaulted but implicitly deleted, probably because a non-static data member or a base class is neither copyable nor movable; definition can either be removed or explicitly deleted [readability-deleted-default]
  MissingEverything(const MissingEverything &Other) = default;
  // CHECK-MESSAGES: warning: copy constructor is explicitly defaulted but implicitly deleted, probably because a non-static data member or a base class is not copyable; definition can either be removed or explicitly deleted [readability-deleted-default]
  MissingEverything &operator=(MissingEverything &&Other) = default;
  // CHECK-MESSAGES: warning: move assignment operator is explicitly defaulted but implicitly deleted, probably because a base class or a non-static data member is not assignable, e.g. because the latter is marked 'const'; definition can either be removed or explicitly deleted [readability-deleted-default]
  MissingEverything &operator=(const MissingEverything &Other) = default;
  // CHECK-MESSAGES: warning: copy assignment operator is explicitly defaulted but implicitly deleted, probably because a base class or a non-static data member is not assignable, e.g. because the latter is marked 'const'; definition can either be removed or explicitly deleted [readability-deleted-default]

private:
  NoDefault ND;
};

class NotAssignable {
public:
  NotAssignable(NotAssignable &&Other) = default;
  NotAssignable(const NotAssignable &Other) = default;
  NotAssignable &operator=(NotAssignable &&Other) = default;
  // CHECK-MESSAGES: warning: move assignment operator is explicitly defaulted but implicitly deleted
  NotAssignable &operator=(const NotAssignable &Other) = default;
  // CHECK-MESSAGES: warning: copy assignment operator is explicitly defaulted but implicitly deleted

private:
  const int I = 0;
};

class Movable {
public:
  Movable() = default;
  Movable(Movable &&Other) = default;
  Movable(const Movable &Other) = delete;
  Movable &operator=(Movable &&Other) = default;
  Movable &operator=(const Movable &Other) = delete;
};

class NotCopyable {
public:
  NotCopyable(NotCopyable &&Other) = default;
  NotCopyable(const NotCopyable &Other) = default;
  // CHECK-MESSAGES: warning: copy constructor is explicitly defaulted but implicitly deleted
  NotCopyable &operator=(NotCopyable &&Other) = default;
  NotCopyable &operator=(const NotCopyable &Other) = default;
  // CHECK-MESSAGES: warning: copy assignment operator is explicitly defaulted but implicitly deleted
private:
  Movable M;
};

template <typename T> class Templated {
public:
  // No warning here, it is a templated class.
  Templated() = default;
  Templated(Templated &&Other) = default;
  Templated(const Templated &Other) = default;
  Templated &operator=(Templated &&Other) = default;
  Templated &operator=(const Templated &Other) = default;

  class InnerTemplated {
  public:
    // This class is not in itself templated, but we still don't have warning.
    InnerTemplated() = default;
    InnerTemplated(InnerTemplated &&Other) = default;
    InnerTemplated(const InnerTemplated &Other) = default;
    InnerTemplated &operator=(InnerTemplated &&Other) = default;
    InnerTemplated &operator=(const InnerTemplated &Other) = default;

  private:
    T TVar;
  };

  class InnerNotTemplated {
  public:
    // This one could technically have warnings, but currently doesn't.
    InnerNotTemplated() = default;
    InnerNotTemplated(InnerNotTemplated &&Other) = default;
    InnerNotTemplated(const InnerNotTemplated &Other) = default;
    InnerNotTemplated &operator=(InnerNotTemplated &&Other) = default;
    InnerNotTemplated &operator=(const InnerNotTemplated &Other) = default;

  private:
    int I;
  };

private:
  const T TVar{};
};

int FunctionWithInnerClass() {
  class InnerNotAssignable {
  public:
    InnerNotAssignable &operator=(InnerNotAssignable &&Other) = default;
    // CHECK-MESSAGES: warning: move assignment operator is explicitly defaulted but implicitly deleted
  private:
    const int I = 0;
  };
  return 1;
};

template <typename T>
int TemplateFunctionWithInnerClass() {
  class InnerNotAssignable {
  public:
    InnerNotAssignable &operator=(InnerNotAssignable &&Other) = default;
  private:
    const T TVar{};
  };
  return 1;
};

void Foo() {
  Templated<const int> V1;
  Templated<int>::InnerTemplated V2;
  Templated<float>::InnerNotTemplated V3;
  TemplateFunctionWithInnerClass<int>();
}
<|endoftext|>


<commit_before>//===- IVUsers.cpp - Induction Variable Users -------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements bookkeeping for "interesting" users of expressions
// computed from induction variables.
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "iv-users"
#include "llvm/Analysis/IVUsers.h"
#include "llvm/Constants.h"
#include "llvm/Instructions.h"
#include "llvm/Type.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Analysis/Dominators.h"
#include "llvm/Analysis/LoopPass.h"
#include "llvm/Analysis/ScalarEvolutionExpressions.h"
#include "llvm/Assembly/AsmAnnotationWriter.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
using namespace llvm;

char IVUsers::ID = 0;
static RegisterPass<IVUsers>
X("iv-users", "Induction Variable Users", false, true);

Pass *llvm::createIVUsersPass() {
  return new IVUsers();
}

/// isInteresting - Test whether the given expression is "interesting" when
/// used by the given expression, within the context of analyzing the
/// given loop.
static bool isInteresting(const SCEV *S, const Instruction *I, const Loop *L) {
  // Anything loop-invariant is interesting.
  if (!isa<SCEVUnknown>(S) && S->isLoopInvariant(L))
    return true;

  // An addrec is interesting if it's affine or if it has an interesting start.
  if (const SCEVAddRecExpr *AR = dyn_cast<SCEVAddRecExpr>(S)) {
    // Keep things simple. Don't touch loop-variant strides.
    if (AR->getLoop() == L)
      return AR->isAffine() || !L->contains(I);
    // Otherwise recurse to see if the start value is interesting.
    return isInteresting(AR->getStart(), I, L);
  }

  // An add is interesting if any of its operands is.
  if (const SCEVAddExpr *Add = dyn_cast<SCEVAddExpr>(S)) {
    for (SCEVAddExpr::op_iterator OI = Add->op_begin(), OE = Add->op_end();
         OI != OE; ++OI)
      if (isInteresting(*OI, I, L))
        return true;
    return false;
  }

  // Nothing else is interesting here.
  return false;
}

/// AddUsersIfInteresting - Inspect the specified instruction.  If it is a
/// reducible SCEV, recursively add its users to the IVUsesByStride set and
/// return true.  Otherwise, return false.
bool IVUsers::AddUsersIfInteresting(Instruction *I) {
  if (!SE->isSCEVable(I->getType()))
    return false;   // Void and FP expressions cannot be reduced.

  // LSR is not APInt clean, do not touch integers bigger than 64-bits.
  if (SE->getTypeSizeInBits(I->getType()) > 64)
    return false;

  if (!Processed.insert(I))
    return true;    // Instruction already handled.

  // Get the symbolic expression for this instruction.
  const SCEV *ISE = SE->getSCEV(I);
  if (isa<SCEVCouldNotCompute>(ISE)) return false;

  // If we've come to an uninteresting expression, stop the traversal and
  // call this a user.
  if (!isInteresting(ISE, I, L))
    return false;

  SmallPtrSet<Instruction *, 4> UniqueUsers;
  for (Value::use_iterator UI = I->use_begin(), E = I->use_end();
       UI != E; ++UI) {
    Instruction *User = cast<Instruction>(*UI);
    if (!UniqueUsers.insert(User))
      continue;

    // Do not infinitely recurse on PHI nodes.
    if (isa<PHINode>(User) && Processed.count(User))
      continue;

    // Descend recursively, but not into PHI nodes outside the current loop.
    // It's important to see the entire expression outside the loop to get
    // choices that depend on addressing mode use right, although we won't
    // consider references outside the loop in all cases.
    // If User is already in Processed, we don't want to recurse into it again,
    // but do want to record a second reference in the same instruction.
    bool AddUserToIVUsers = false;
    if (LI->getLoopFor(User->getParent()) != L) {
      if (isa<PHINode>(User) || Processed.count(User) ||
          !AddUsersIfInteresting(User)) {
        DEBUG(dbgs() << "FOUND USER in other loop: " << *User << '\n'
                     << "   OF SCEV: " << *ISE << '\n');
        AddUserToIVUsers = true;
      }
    } else if (Processed.count(User) ||
               !AddUsersIfInteresting(User)) {
      DEBUG(dbgs() << "FOUND USER: " << *User << '\n'
                   << "   OF SCEV: " << *ISE << '\n');
      AddUserToIVUsers = true;
    }

    if (AddUserToIVUsers) {
      // Okay, we found a user that we cannot reduce.
      IVUses.push_back(new IVStrideUse(this, ISE, User, I));
      IVStrideUse &NewUse = IVUses.back();
      // Transform the expression into a normalized form.
      NewUse.Expr =
        TransformForPostIncUse(NormalizeAutodetect, NewUse.Expr,
                               User, I,
                               NewUse.PostIncLoops,
                               *SE, *DT);
      DEBUG(dbgs() << "   NORMALIZED TO: " << *NewUse.Expr << '\n');
    }
  }
  return true;
}

IVStrideUse &IVUsers::AddUser(const SCEV *Expr,
                              Instruction *User, Value *Operand) {
  IVUses.push_back(new IVStrideUse(this, Expr, User, Operand));
  return IVUses.back();
}

IVUsers::IVUsers()
 : LoopPass(&ID) {
}

void IVUsers::getAnalysisUsage(AnalysisUsage &AU) const {
  AU.addRequired<LoopInfo>();
  AU.addRequired<DominatorTree>();
  AU.addRequired<ScalarEvolution>();
  AU.setPreservesAll();
}

bool IVUsers::runOnLoop(Loop *l, LPPassManager &LPM) {

  L = l;
  LI = &getAnalysis<LoopInfo>();
  DT = &getAnalysis<DominatorTree>();
  SE = &getAnalysis<ScalarEvolution>();

  // Find all uses of induction variables in this loop, and categorize
  // them by stride.  Start by finding all of the PHI nodes in the header for
  // this loop.  If they are induction variables, inspect their uses.
  for (BasicBlock::iterator I = L->getHeader()->begin(); isa<PHINode>(I); ++I)
    AddUsersIfInteresting(I);

  return false;
}

/// getReplacementExpr - Return a SCEV expression which computes the
/// value of the OperandValToReplace of the given IVStrideUse.
const SCEV *IVUsers::getReplacementExpr(const IVStrideUse &U) const {
  PostIncLoopSet &Loops = const_cast<PostIncLoopSet &>(U.PostIncLoops);
  return TransformForPostIncUse(Denormalize, U.getExpr(),
                                U.getUser(), U.getOperandValToReplace(),
                                Loops, *SE, *DT);
}

void IVUsers::print(raw_ostream &OS, const Module *M) const {
  OS << "IV Users for loop ";
  WriteAsOperand(OS, L->getHeader(), false);
  if (SE->hasLoopInvariantBackedgeTakenCount(L)) {
    OS << " with backedge-taken count "
       << *SE->getBackedgeTakenCount(L);
  }
  OS << ":\n";

  // Use a default AssemblyAnnotationWriter to suppress the default info
  // comments, which aren't relevant here.
  AssemblyAnnotationWriter Annotator;
  for (ilist<IVStrideUse>::const_iterator UI = IVUses.begin(),
       E = IVUses.end(); UI != E; ++UI) {
    OS << "  ";
    WriteAsOperand(OS, UI->getOperandValToReplace(), false);
    OS << " = "
       << *getReplacementExpr(*UI);
    for (PostIncLoopSet::const_iterator
         I = UI->PostIncLoops.begin(),
         E = UI->PostIncLoops.end(); I != E; ++I) {
      OS << " (post-inc with loop ";
      WriteAsOperand(OS, (*I)->getHeader(), false);
      OS << ")";
    }
    OS << " in  ";
    UI->getUser()->print(OS, &Annotator);
    OS << '\n';
  }
}

void IVUsers::dump() const {
  print(dbgs());
}

void IVUsers::releaseMemory() {
  Processed.clear();
  IVUses.clear();
}

static const SCEVAddRecExpr *findAddRecForLoop(const SCEV *S, const Loop *L) {
  if (const SCEVAddRecExpr *AR = dyn_cast<SCEVAddRecExpr>(S)) {
    if (AR->getLoop() == L)
      return AR;
    return findAddRecForLoop(AR->getStart(), L);
  }

  if (const SCEVAddExpr *Add = dyn_cast<SCEVAddExpr>(S)) {
    for (SCEVAddExpr::op_iterator I = Add->op_begin(), E = Add->op_end();
         I != E; ++I)
      if (const SCEVAddRecExpr *AR = findAddRecForLoop(*I, L))
        return AR;
    return 0;
  }

  return 0;
}

const SCEV *IVStrideUse::getStride(const Loop *L) const {
  if (const SCEVAddRecExpr *AR = findAddRecForLoop(getExpr(), L))
    return AR->getStepRecurrence(*Parent->SE);
  return 0;
}

void IVStrideUse::transformToPostInc(const Loop *L) {
  PostIncLoopSet Loops;
  Loops.insert(L);
  Expr = TransformForPostIncUse(Normalize, Expr,
                                getUser(), getOperandValToReplace(),
                                Loops, *Parent->SE, *Parent->DT);
  PostIncLoops.insert(L);
}

void IVStrideUse::deleted() {
  // Remove this user from the list.
  Parent->IVUses.erase(this);
  // this now dangles!
}
<commit_msg>Delete a dead check.<commit_after>//===- IVUsers.cpp - Induction Variable Users -------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements bookkeeping for "interesting" users of expressions
// computed from induction variables.
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "iv-users"
#include "llvm/Analysis/IVUsers.h"
#include "llvm/Constants.h"
#include "llvm/Instructions.h"
#include "llvm/Type.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Analysis/Dominators.h"
#include "llvm/Analysis/LoopPass.h"
#include "llvm/Analysis/ScalarEvolutionExpressions.h"
#include "llvm/Assembly/AsmAnnotationWriter.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
using namespace llvm;

char IVUsers::ID = 0;
static RegisterPass<IVUsers>
X("iv-users", "Induction Variable Users", false, true);

Pass *llvm::createIVUsersPass() {
  return new IVUsers();
}

/// isInteresting - Test whether the given expression is "interesting" when
/// used by the given expression, within the context of analyzing the
/// given loop.
static bool isInteresting(const SCEV *S, const Instruction *I, const Loop *L) {
  // Anything loop-invariant is interesting.
  if (!isa<SCEVUnknown>(S) && S->isLoopInvariant(L))
    return true;

  // An addrec is interesting if it's affine or if it has an interesting start.
  if (const SCEVAddRecExpr *AR = dyn_cast<SCEVAddRecExpr>(S)) {
    // Keep things simple. Don't touch loop-variant strides.
    if (AR->getLoop() == L)
      return AR->isAffine() || !L->contains(I);
    // Otherwise recurse to see if the start value is interesting.
    return isInteresting(AR->getStart(), I, L);
  }

  // An add is interesting if any of its operands is.
  if (const SCEVAddExpr *Add = dyn_cast<SCEVAddExpr>(S)) {
    for (SCEVAddExpr::op_iterator OI = Add->op_begin(), OE = Add->op_end();
         OI != OE; ++OI)
      if (isInteresting(*OI, I, L))
        return true;
    return false;
  }

  // Nothing else is interesting here.
  return false;
}

/// AddUsersIfInteresting - Inspect the specified instruction.  If it is a
/// reducible SCEV, recursively add its users to the IVUsesByStride set and
/// return true.  Otherwise, return false.
bool IVUsers::AddUsersIfInteresting(Instruction *I) {
  if (!SE->isSCEVable(I->getType()))
    return false;   // Void and FP expressions cannot be reduced.

  // LSR is not APInt clean, do not touch integers bigger than 64-bits.
  if (SE->getTypeSizeInBits(I->getType()) > 64)
    return false;

  if (!Processed.insert(I))
    return true;    // Instruction already handled.

  // Get the symbolic expression for this instruction.
  const SCEV *ISE = SE->getSCEV(I);

  // If we've come to an uninteresting expression, stop the traversal and
  // call this a user.
  if (!isInteresting(ISE, I, L))
    return false;

  SmallPtrSet<Instruction *, 4> UniqueUsers;
  for (Value::use_iterator UI = I->use_begin(), E = I->use_end();
       UI != E; ++UI) {
    Instruction *User = cast<Instruction>(*UI);
    if (!UniqueUsers.insert(User))
      continue;

    // Do not infinitely recurse on PHI nodes.
    if (isa<PHINode>(User) && Processed.count(User))
      continue;

    // Descend recursively, but not into PHI nodes outside the current loop.
    // It's important to see the entire expression outside the loop to get
    // choices that depend on addressing mode use right, although we won't
    // consider references outside the loop in all cases.
    // If User is already in Processed, we don't want to recurse into it again,
    // but do want to record a second reference in the same instruction.
    bool AddUserToIVUsers = false;
    if (LI->getLoopFor(User->getParent()) != L) {
      if (isa<PHINode>(User) || Processed.count(User) ||
          !AddUsersIfInteresting(User)) {
        DEBUG(dbgs() << "FOUND USER in other loop: " << *User << '\n'
                     << "   OF SCEV: " << *ISE << '\n');
        AddUserToIVUsers = true;
      }
    } else if (Processed.count(User) ||
               !AddUsersIfInteresting(User)) {
      DEBUG(dbgs() << "FOUND USER: " << *User << '\n'
                   << "   OF SCEV: " << *ISE << '\n');
      AddUserToIVUsers = true;
    }

    if (AddUserToIVUsers) {
      // Okay, we found a user that we cannot reduce.
      IVUses.push_back(new IVStrideUse(this, ISE, User, I));
      IVStrideUse &NewUse = IVUses.back();
      // Transform the expression into a normalized form.
      NewUse.Expr =
        TransformForPostIncUse(NormalizeAutodetect, NewUse.Expr,
                               User, I,
                               NewUse.PostIncLoops,
                               *SE, *DT);
      DEBUG(dbgs() << "   NORMALIZED TO: " << *NewUse.Expr << '\n');
    }
  }
  return true;
}

IVStrideUse &IVUsers::AddUser(const SCEV *Expr,
                              Instruction *User, Value *Operand) {
  IVUses.push_back(new IVStrideUse(this, Expr, User, Operand));
  return IVUses.back();
}

IVUsers::IVUsers()
 : LoopPass(&ID) {
}

void IVUsers::getAnalysisUsage(AnalysisUsage &AU) const {
  AU.addRequired<LoopInfo>();
  AU.addRequired<DominatorTree>();
  AU.addRequired<ScalarEvolution>();
  AU.setPreservesAll();
}

bool IVUsers::runOnLoop(Loop *l, LPPassManager &LPM) {

  L = l;
  LI = &getAnalysis<LoopInfo>();
  DT = &getAnalysis<DominatorTree>();
  SE = &getAnalysis<ScalarEvolution>();

  // Find all uses of induction variables in this loop, and categorize
  // them by stride.  Start by finding all of the PHI nodes in the header for
  // this loop.  If they are induction variables, inspect their uses.
  for (BasicBlock::iterator I = L->getHeader()->begin(); isa<PHINode>(I); ++I)
    AddUsersIfInteresting(I);

  return false;
}

/// getReplacementExpr - Return a SCEV expression which computes the
/// value of the OperandValToReplace of the given IVStrideUse.
const SCEV *IVUsers::getReplacementExpr(const IVStrideUse &U) const {
  PostIncLoopSet &Loops = const_cast<PostIncLoopSet &>(U.PostIncLoops);
  return TransformForPostIncUse(Denormalize, U.getExpr(),
                                U.getUser(), U.getOperandValToReplace(),
                                Loops, *SE, *DT);
}

void IVUsers::print(raw_ostream &OS, const Module *M) const {
  OS << "IV Users for loop ";
  WriteAsOperand(OS, L->getHeader(), false);
  if (SE->hasLoopInvariantBackedgeTakenCount(L)) {
    OS << " with backedge-taken count "
       << *SE->getBackedgeTakenCount(L);
  }
  OS << ":\n";

  // Use a default AssemblyAnnotationWriter to suppress the default info
  // comments, which aren't relevant here.
  AssemblyAnnotationWriter Annotator;
  for (ilist<IVStrideUse>::const_iterator UI = IVUses.begin(),
       E = IVUses.end(); UI != E; ++UI) {
    OS << "  ";
    WriteAsOperand(OS, UI->getOperandValToReplace(), false);
    OS << " = "
       << *getReplacementExpr(*UI);
    for (PostIncLoopSet::const_iterator
         I = UI->PostIncLoops.begin(),
         E = UI->PostIncLoops.end(); I != E; ++I) {
      OS << " (post-inc with loop ";
      WriteAsOperand(OS, (*I)->getHeader(), false);
      OS << ")";
    }
    OS << " in  ";
    UI->getUser()->print(OS, &Annotator);
    OS << '\n';
  }
}

void IVUsers::dump() const {
  print(dbgs());
}

void IVUsers::releaseMemory() {
  Processed.clear();
  IVUses.clear();
}

static const SCEVAddRecExpr *findAddRecForLoop(const SCEV *S, const Loop *L) {
  if (const SCEVAddRecExpr *AR = dyn_cast<SCEVAddRecExpr>(S)) {
    if (AR->getLoop() == L)
      return AR;
    return findAddRecForLoop(AR->getStart(), L);
  }

  if (const SCEVAddExpr *Add = dyn_cast<SCEVAddExpr>(S)) {
    for (SCEVAddExpr::op_iterator I = Add->op_begin(), E = Add->op_end();
         I != E; ++I)
      if (const SCEVAddRecExpr *AR = findAddRecForLoop(*I, L))
        return AR;
    return 0;
  }

  return 0;
}

const SCEV *IVStrideUse::getStride(const Loop *L) const {
  if (const SCEVAddRecExpr *AR = findAddRecForLoop(getExpr(), L))
    return AR->getStepRecurrence(*Parent->SE);
  return 0;
}

void IVStrideUse::transformToPostInc(const Loop *L) {
  PostIncLoopSet Loops;
  Loops.insert(L);
  Expr = TransformForPostIncUse(Normalize, Expr,
                                getUser(), getOperandValToReplace(),
                                Loops, *Parent->SE, *Parent->DT);
  PostIncLoops.insert(L);
}

void IVStrideUse::deleted() {
  // Remove this user from the list.
  Parent->IVUses.erase(this);
  // this now dangles!
}
<|endoftext|>


<commit_before>#include "tbb.h"

int main(int argc, char* argv[])
{
    return 0;
}
<commit_msg>TBB headers in tbb/*<commit_after>#include "tbb/tbb.h"

int main(int argc, char* argv[])
{
    return 0;
}
<|endoftext|>


<commit_before>//===--- TargetInfo.cpp - Information about Target machine ----------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This file implements the TargetInfo and TargetInfoImpl interfaces.
//
//===----------------------------------------------------------------------===//

#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/AST/Builtins.h"
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/STLExtras.h"
using namespace clang;

// TargetInfo Constructor.
TargetInfo::TargetInfo(const std::string &T) : Triple(T) {
  // Set defaults.  These should be overridden by concrete targets as needed.
  CharIsSigned = true;
  WCharWidth = WCharAlign = 32;
  FloatFormat = &llvm::APFloat::IEEEsingle;
  DoubleFormat = &llvm::APFloat::IEEEdouble;
  LongDoubleFormat = &llvm::APFloat::IEEEdouble;
}

// Out of line virtual dtor for TargetInfo.
TargetInfo::~TargetInfo() {}

//===----------------------------------------------------------------------===//

static void removeGCCRegisterPrefix(const char *&Name) {
  if (Name[0] == '%' || Name[0] == '#')
    Name++;
}

/// isValidGCCRegisterName - Returns whether the passed in string
/// is a valid register name according to GCC. This is used by Sema for
/// inline asm statements.
bool TargetInfo::isValidGCCRegisterName(const char *Name) const {
  const char * const *Names;
  unsigned NumNames;

  // Get rid of any register prefix.
  removeGCCRegisterPrefix(Name);

  if (strcmp(Name, "memory") == 0 ||
      strcmp(Name, "cc") == 0)
    return true;

  getGCCRegNames(Names, NumNames);

  // If we have a number it maps to an entry in the register name array.
  if (isdigit(Name[0])) {
    char *End;
    int n = (int)strtol(Name, &End, 0);
    if (*End == 0)
      return n >= 0 && (unsigned)n < NumNames;
  }

  // Check register names.
  for (unsigned i = 0; i < NumNames; i++) {
    if (strcmp(Name, Names[i]) == 0)
      return true;
  }

  // Now check aliases.
  const GCCRegAlias *Aliases;
  unsigned NumAliases;

  getGCCRegAliases(Aliases, NumAliases);
  for (unsigned i = 0; i < NumAliases; i++) {
    for (unsigned j = 0 ; j < llvm::array_lengthof(Aliases[i].Aliases); j++) {
      if (!Aliases[i].Aliases[j])
        break;
      if (strcmp(Aliases[i].Aliases[j], Name) == 0)
        return true;
    }
  }

  return false;
}

const char *TargetInfo::getNormalizedGCCRegisterName(const char *Name) const {
  assert(isValidGCCRegisterName(Name) && "Invalid register passed in");

  removeGCCRegisterPrefix(Name);

  const char * const *Names;
  unsigned NumNames;

  getGCCRegNames(Names, NumNames);

  // First, check if we have a number.
  if (isdigit(Name[0])) {
    char *End;
    int n = (int)strtol(Name, &End, 0);
    if (*End == 0) {
      assert(n >= 0 && (unsigned)n < NumNames &&
             "Out of bounds register number!");
      return Names[n];
    }
  }

  // Now check aliases.
  const GCCRegAlias *Aliases;
  unsigned NumAliases;

  getGCCRegAliases(Aliases, NumAliases);
  for (unsigned i = 0; i < NumAliases; i++) {
    for (unsigned j = 0 ; j < llvm::array_lengthof(Aliases[i].Aliases); j++) {
      if (!Aliases[i].Aliases[j])
        break;
      if (strcmp(Aliases[i].Aliases[j], Name) == 0)
        return Aliases[i].Register;
    }
  }

  return Name;
}

bool TargetInfo::validateOutputConstraint(const char *Name,
                                          ConstraintInfo &info) const
{
  // An output constraint must start with '=' or '+'
  if (*Name != '=' && *Name != '+')
    return false;

  if (*Name == '+')
    info = CI_ReadWrite;
  else
    info = CI_None;

  Name++;
  while (*Name) {
    switch (*Name) {
    default:
      if (!validateAsmConstraint(*Name, info)) {
        // FIXME: This assert is in place temporarily
        // so we can add more constraints as we hit it.
        // Eventually, an unknown constraint should just be treated as 'g'.
        assert(0 && "Unknown output constraint type!");
      }
    case '&': // early clobber.
      break;
    case 'r': // general register.
      info = (ConstraintInfo)(info|CI_AllowsRegister);
      break;
    case 'm': // memory operand.
      info = (ConstraintInfo)(info|CI_AllowsMemory);
      break;
    case 'g': // general register, memory operand or immediate integer.
      info = (ConstraintInfo)(info|CI_AllowsMemory|CI_AllowsRegister);
      break;
    }

    Name++;
  }

  return true;
}

bool TargetInfo::validateInputConstraint(const char *Name,
                                         unsigned NumOutputs,
                                         ConstraintInfo &info) const {
  while (*Name) {
    switch (*Name) {
    default:
      // Check if we have a matching constraint
      if (*Name >= '0' && *Name <= '9') {
        unsigned i = *Name - '0';

        // Check if matching constraint is out of bounds.
        if (i >= NumOutputs)
          return false;
      } else if (!validateAsmConstraint(*Name, info)) {
        // FIXME: This assert is in place temporarily
        // so we can add more constraints as we hit it.
        // Eventually, an unknown constraint should just be treated as 'g'.
        assert(0 && "Unknown input constraint type!");
      }
    case '%': // commutative
      // FIXME: Fail if % is used with the last operand.
      break;
    case 'i': // immediate integer.
    case 'I':
    case 'n': // immediate integer with a known value.
      break;
    case 'r': // general register.
      info = (ConstraintInfo)(info|CI_AllowsRegister);
      break;
    case 'm': // memory operand.
      info = (ConstraintInfo)(info|CI_AllowsMemory);
      break;
    case 'g': // general register, memory operand or immediate integer.
      info = (ConstraintInfo)(info|CI_AllowsMemory|CI_AllowsRegister);
      break;
    }

    Name++;
  }

  return true;
}
<commit_msg>add a missing #include<commit_after>//===--- TargetInfo.cpp - Information about Target machine ----------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This file implements the TargetInfo and TargetInfoImpl interfaces.
//
//===----------------------------------------------------------------------===//

#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/AST/Builtins.h"
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/STLExtras.h"
#include <cstdlib>
using namespace clang;

// TargetInfo Constructor.
TargetInfo::TargetInfo(const std::string &T) : Triple(T) {
  // Set defaults.  These should be overridden by concrete targets as needed.
  CharIsSigned = true;
  WCharWidth = WCharAlign = 32;
  FloatFormat = &llvm::APFloat::IEEEsingle;
  DoubleFormat = &llvm::APFloat::IEEEdouble;
  LongDoubleFormat = &llvm::APFloat::IEEEdouble;
}

// Out of line virtual dtor for TargetInfo.
TargetInfo::~TargetInfo() {}

//===----------------------------------------------------------------------===//

static void removeGCCRegisterPrefix(const char *&Name) {
  if (Name[0] == '%' || Name[0] == '#')
    Name++;
}

/// isValidGCCRegisterName - Returns whether the passed in string
/// is a valid register name according to GCC. This is used by Sema for
/// inline asm statements.
bool TargetInfo::isValidGCCRegisterName(const char *Name) const {
  const char * const *Names;
  unsigned NumNames;

  // Get rid of any register prefix.
  removeGCCRegisterPrefix(Name);

  if (strcmp(Name, "memory") == 0 ||
      strcmp(Name, "cc") == 0)
    return true;

  getGCCRegNames(Names, NumNames);

  // If we have a number it maps to an entry in the register name array.
  if (isdigit(Name[0])) {
    char *End;
    int n = (int)strtol(Name, &End, 0);
    if (*End == 0)
      return n >= 0 && (unsigned)n < NumNames;
  }

  // Check register names.
  for (unsigned i = 0; i < NumNames; i++) {
    if (strcmp(Name, Names[i]) == 0)
      return true;
  }

  // Now check aliases.
  const GCCRegAlias *Aliases;
  unsigned NumAliases;

  getGCCRegAliases(Aliases, NumAliases);
  for (unsigned i = 0; i < NumAliases; i++) {
    for (unsigned j = 0 ; j < llvm::array_lengthof(Aliases[i].Aliases); j++) {
      if (!Aliases[i].Aliases[j])
        break;
      if (strcmp(Aliases[i].Aliases[j], Name) == 0)
        return true;
    }
  }

  return false;
}

const char *TargetInfo::getNormalizedGCCRegisterName(const char *Name) const {
  assert(isValidGCCRegisterName(Name) && "Invalid register passed in");

  removeGCCRegisterPrefix(Name);

  const char * const *Names;
  unsigned NumNames;

  getGCCRegNames(Names, NumNames);

  // First, check if we have a number.
  if (isdigit(Name[0])) {
    char *End;
    int n = (int)strtol(Name, &End, 0);
    if (*End == 0) {
      assert(n >= 0 && (unsigned)n < NumNames &&
             "Out of bounds register number!");
      return Names[n];
    }
  }

  // Now check aliases.
  const GCCRegAlias *Aliases;
  unsigned NumAliases;

  getGCCRegAliases(Aliases, NumAliases);
  for (unsigned i = 0; i < NumAliases; i++) {
    for (unsigned j = 0 ; j < llvm::array_lengthof(Aliases[i].Aliases); j++) {
      if (!Aliases[i].Aliases[j])
        break;
      if (strcmp(Aliases[i].Aliases[j], Name) == 0)
        return Aliases[i].Register;
    }
  }

  return Name;
}

bool TargetInfo::validateOutputConstraint(const char *Name,
                                          ConstraintInfo &info) const
{
  // An output constraint must start with '=' or '+'
  if (*Name != '=' && *Name != '+')
    return false;

  if (*Name == '+')
    info = CI_ReadWrite;
  else
    info = CI_None;

  Name++;
  while (*Name) {
    switch (*Name) {
    default:
      if (!validateAsmConstraint(*Name, info)) {
        // FIXME: This assert is in place temporarily
        // so we can add more constraints as we hit it.
        // Eventually, an unknown constraint should just be treated as 'g'.
        assert(0 && "Unknown output constraint type!");
      }
    case '&': // early clobber.
      break;
    case 'r': // general register.
      info = (ConstraintInfo)(info|CI_AllowsRegister);
      break;
    case 'm': // memory operand.
      info = (ConstraintInfo)(info|CI_AllowsMemory);
      break;
    case 'g': // general register, memory operand or immediate integer.
      info = (ConstraintInfo)(info|CI_AllowsMemory|CI_AllowsRegister);
      break;
    }

    Name++;
  }

  return true;
}

bool TargetInfo::validateInputConstraint(const char *Name,
                                         unsigned NumOutputs,
                                         ConstraintInfo &info) const {
  while (*Name) {
    switch (*Name) {
    default:
      // Check if we have a matching constraint
      if (*Name >= '0' && *Name <= '9') {
        unsigned i = *Name - '0';

        // Check if matching constraint is out of bounds.
        if (i >= NumOutputs)
          return false;
      } else if (!validateAsmConstraint(*Name, info)) {
        // FIXME: This assert is in place temporarily
        // so we can add more constraints as we hit it.
        // Eventually, an unknown constraint should just be treated as 'g'.
        assert(0 && "Unknown input constraint type!");
      }
    case '%': // commutative
      // FIXME: Fail if % is used with the last operand.
      break;
    case 'i': // immediate integer.
    case 'I':
    case 'n': // immediate integer with a known value.
      break;
    case 'r': // general register.
      info = (ConstraintInfo)(info|CI_AllowsRegister);
      break;
    case 'm': // memory operand.
      info = (ConstraintInfo)(info|CI_AllowsMemory);
      break;
    case 'g': // general register, memory operand or immediate integer.
      info = (ConstraintInfo)(info|CI_AllowsMemory|CI_AllowsRegister);
      break;
    }

    Name++;
  }

  return true;
}
<|endoftext|>