<commit_before>#pragma once
/*
* Covariant Mozart Utility Library: Any
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program.  If not, see <http://www.gnu.org/licenses/>.
*
* Copyright (C) 2016 Michael Lee(李登淳)
* Email: China-LDC@outlook.com
* Github: https://github.com/mikecovlee
* Website: http://ldc.atd3.cn
*
* Version: 17.4.2
*/
#include "./base.hpp"
#include <functional>
#include <iostream>

namespace std {
	template<typename T> std::string to_string(const T&)
	{
		throw cov::error("E000D");
	}
	template<> std::string to_string<std::string>(const std::string& str)
	{
		return str;
	}
	template<> std::string to_string<bool>(const bool& v)
	{
		if(v)
			return "true";
		else
			return "false";
	}
}

namespace cov {
	template < typename _Tp > class compare_helper {
		template < typename T,typename X=bool >struct matcher;
		template < typename T > static constexpr bool match(T*)
		{
			return false;
		}
		template < typename T > static constexpr bool match(matcher < T, decltype(std::declval<T>()==std::declval<T>()) > *)
		{
			return true;
		}
	public:
		static constexpr bool value = match < _Tp > (nullptr);
	};
	template<typename,bool> struct compare_if;
	template<typename T>struct compare_if<T,true> {
		static bool compare(const T& a,const T& b)
		{
			return a==b;
		}
	};
	template<typename T>struct compare_if<T,false> {
		static bool compare(const T& a,const T& b)
		{
			return &a==&b;
		}
	};
	template<typename T>bool compare(const T& a,const T& b)
	{
		return compare_if<T,compare_helper<T>::value>::compare(a,b);
	}
	template < typename _Tp > class hash_helper {
		template < typename T,decltype(&std::hash<T>::operator()) X >struct matcher;
		template < typename T > static constexpr bool match(T*)
		{
			return false;
		}
		template < typename T > static constexpr bool match(matcher<T,&std::hash<T>::operator()>*)
		{
			return true;
		}
	public:
		static constexpr bool value = match < _Tp > (nullptr);
	};
	template<typename,bool> struct hash_if;
	template<typename T>struct hash_if<T,true> {
		static std::size_t hash(const T& val)
		{
			static std::hash<T> gen;
			return gen(val);
		}
	};
	template<typename T>struct hash_if<T,false> {
		static std::size_t hash(const T& val)
		{
			throw cov::error("E000F");
		}
	};
	template<typename T>std::size_t hash(const T& val)
	{
		return hash_if<T,hash_helper<T>::value>::hash(val);
	}
	class any final {
		class baseHolder {
		public:
			baseHolder() = default;
			virtual ~ baseHolder() = default;
			virtual const std::type_info & type() const = 0;
			virtual baseHolder *duplicate() = 0;
			virtual bool compare(const baseHolder *) const = 0;
			virtual std::string to_string() const = 0;
			virtual std::size_t hash() const = 0;
		};
		template < typename T > class holder:public baseHolder {
		protected:
			T mDat;
		public:
			holder() = default;
			holder(const T& dat):mDat(dat) {}
			virtual ~ holder() = default;
			virtual const std::type_info & type() const override
			{
				return typeid(T);
			}
			virtual baseHolder *duplicate() override
			{
				return new holder(mDat);
			}
			virtual bool compare(const baseHolder * obj)const override
			{
				if (obj->type() == this->type()) {
					const holder < T > *ptr = dynamic_cast < const holder < T > *>(obj);
					return ptr!=nullptr?cov::compare(mDat,ptr->data()):false;
				}
				return false;
			}
			virtual std::string to_string() const override
			{
				return std::move(std::to_string(mDat));
			}
			virtual std::size_t hash() const override
			{
				return cov::hash<T>(mDat);
			}
			T & data()
			{
				return mDat;
			}
			const T & data() const
			{
				return mDat;
			}
			void data(const T & dat)
			{
				mDat = dat;
			}
		};
		using size_t=unsigned long;
		struct proxy {
			mutable size_t refcount=1;
			baseHolder* data=nullptr;
			proxy()=default;
			proxy(size_t rc,baseHolder* d):refcount(rc),data(d) {}
			~proxy()
			{
				delete data;
			}
		};
		proxy* mDat=nullptr;
		proxy* duplicate() const noexcept
		{
			if(mDat!=nullptr) {
				++mDat->refcount;
			}
			return mDat;
		}
		void recycle() noexcept
		{
			if(mDat!=nullptr) {
				--mDat->refcount;
				if(mDat->refcount==0) {
					delete mDat;
					mDat=nullptr;
				}
			}
		}
	public:
		static any infer_value(const std::string&);
		void swap(any& obj) noexcept
		{
			proxy* tmp=this->mDat;
			this->mDat=obj.mDat;
			obj.mDat=tmp;
		}
		void swap(any&& obj) noexcept
		{
			proxy* tmp=this->mDat;
			this->mDat=obj.mDat;
			obj.mDat=tmp;
		}
		void clone() noexcept
		{
			if(mDat!=nullptr) {
				proxy* dat=new proxy(1,mDat->data->duplicate());
				recycle();
				mDat=dat;
			}
		}
		bool usable() const noexcept
		{
			return mDat != nullptr;
		}
		any()=default;
		template < typename T > any(const T & dat):mDat(new proxy(1,new holder < T > (dat))) {}
		any(const any & v):mDat(v.duplicate()) {}
		any(any&& v) noexcept
		{
			swap(std::forward<any>(v));
		}
		~any()
		{
			recycle();
		}
		const std::type_info & type() const
		{
			return this->mDat != nullptr?this->mDat->data->type():typeid(void);
		}
		std::string to_string() const
		{
			if(this->mDat == nullptr)
				return "Null";
			return std::move(this->mDat->data->to_string());
		}
		std::size_t hash() const
		{
			if(this->mDat == nullptr)
				return cov::hash<void*>(nullptr);
			return this->mDat->data->hash();
		}
		any & operator=(const any & var)
		{
			if(&var!=this) {
				recycle();
				mDat = var.duplicate();
			}
			return *this;
		}
		any & operator=(any&& var) noexcept
		{
			if(&var!=this)
				swap(std::forward<any>(var));
			return *this;
		}
		bool operator==(const any & var) const
		{
			return usable()?this->mDat->data->compare(var.mDat->data):!var.usable();
		}
		bool operator!=(const any & var)const
		{
			return usable()?!this->mDat->data->compare(var.mDat->data):var.usable();
		}
		template < typename T > T & val(bool raw=false)
		{
			if(typeid(T) != this->type())
				throw cov::error("E0006");
			if(this->mDat == nullptr)
				throw cov::error("E0005");
			if(!raw)
				clone();
			return dynamic_cast < holder < T > *>(this->mDat->data)->data();
		}
		template < typename T > const T & val(bool raw=false) const
		{
			if(typeid(T) != this->type())
				throw cov::error("E0006");
			if(this->mDat == nullptr)
				throw cov::error("E0005");
			return dynamic_cast < const holder < T > *>(this->mDat->data)->data();
		}
		template < typename T > const T& const_val() const
		{
			if(typeid(T) != this->type())
				throw cov::error("E0006");
			if(this->mDat == nullptr)
				throw cov::error("E0005");
			return dynamic_cast < const holder < T > *>(this->mDat->data)->data();
		}
		template < typename T > operator T&()
		{
			return this->val<T>();
		}
		template < typename T > operator const T&() const
		{
			return this->const_val<T>();
		}
		void assign(const any& obj,bool raw=false)
		{
			if(&obj!=this) {
				if(mDat!=obj.mDat&&mDat!=nullptr&&obj.mDat!=nullptr&&raw) {
					delete mDat->data;
					mDat->data=obj.mDat->data->duplicate();
				} else {
					recycle();
					if(obj.mDat!=nullptr)
						mDat=new proxy(1,obj.mDat->data->duplicate());
					else
						mDat=nullptr;
				}
			}
		}
		template < typename T > void assign(const T & dat,bool raw=false)
		{
			if(raw) {
				delete mDat->data;
				mDat->data=new holder < T > (dat);
			} else {
				recycle();
				mDat = new proxy(1,new holder < T > (dat));
			}
		}
		template < typename T > any & operator=(const T & dat)
		{
			assign(dat);
			return *this;
		}
		bool is_same(const any& obj) const
		{
			return this->mDat==obj.mDat;
		}
	};
	template<int N> class any::holder<char[N]>:public any::holder<std::string> {
	public:
		using holder<std::string>::holder;
	};
	template<> class any::holder<std::type_info>:public any::holder<std::type_index> {
	public:
		using holder<std::type_index>::holder;
	};
}

cov::any cov::any::infer_value(const std::string& str)
{
	if(str=="true"||str=="True"||str=="TRUE")
		return true;
	if(str=="false"||str=="False"||str=="FALSE")
		return false;
	enum types {
		interger,floating,other
	} type=types::interger;
	for(auto& it:str) {
		if(!std::isdigit(it)&&it!='.') {
			type=other;
			break;
		}
		if(!std::isdigit(it)&&it=='.') {
			if(type==interger) {
				type=floating;
				continue;
			}
			if(type==floating) {
				type=other;
				break;
			}
		}
	}
	switch(type) {
	case interger:
		try {
			return std::stoi(str);
		} catch(std::out_of_range) {
			try {
				return std::stol(str);
			} catch(std::out_of_range) {
				try {
					return std::stoll(str);
				} catch(std::out_of_range) {
					return str;
				}
			}
		}
	case floating:
		return std::stod(str);
	case other:
		break;
	}
	return str;
}

std::istream& operator>>(std::istream& in,cov::any& val)
{
	static std::string str;
	in>>str;
	val=cov::any::infer_value(str);
	return in;
}

std::ostream& operator<<(std::ostream& out,const cov::any& val)
{
	out<<val.to_string();
	return out;
}

namespace std {
	template<> struct hash<cov::any> {
		std::size_t operator()(const cov::any& val) const
		{
			return val.hash();
		}
	};
}
<commit_msg>更新cov::any，解决自赋值时段错误的问题<commit_after>#pragma once
/*
* Covariant Mozart Utility Library: Any
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program.  If not, see <http://www.gnu.org/licenses/>.
*
* Copyright (C) 2016 Michael Lee(李登淳)
* Email: China-LDC@outlook.com
* Github: https://github.com/mikecovlee
* Website: http://ldc.atd3.cn
*
* Version: 17.4.2
*/
#include "./base.hpp"
#include <functional>
#include <iostream>

namespace std {
	template<typename T> std::string to_string(const T&)
	{
		throw cov::error("E000D");
	}
	template<> std::string to_string<std::string>(const std::string& str)
	{
		return str;
	}
	template<> std::string to_string<bool>(const bool& v)
	{
		if(v)
			return "true";
		else
			return "false";
	}
}

namespace cov {
	template < typename _Tp > class compare_helper {
		template < typename T,typename X=bool >struct matcher;
		template < typename T > static constexpr bool match(T*)
		{
			return false;
		}
		template < typename T > static constexpr bool match(matcher < T, decltype(std::declval<T>()==std::declval<T>()) > *)
		{
			return true;
		}
	public:
		static constexpr bool value = match < _Tp > (nullptr);
	};
	template<typename,bool> struct compare_if;
	template<typename T>struct compare_if<T,true> {
		static bool compare(const T& a,const T& b)
		{
			return a==b;
		}
	};
	template<typename T>struct compare_if<T,false> {
		static bool compare(const T& a,const T& b)
		{
			return &a==&b;
		}
	};
	template<typename T>bool compare(const T& a,const T& b)
	{
		return compare_if<T,compare_helper<T>::value>::compare(a,b);
	}
	template < typename _Tp > class hash_helper {
		template < typename T,decltype(&std::hash<T>::operator()) X >struct matcher;
		template < typename T > static constexpr bool match(T*)
		{
			return false;
		}
		template < typename T > static constexpr bool match(matcher<T,&std::hash<T>::operator()>*)
		{
			return true;
		}
	public:
		static constexpr bool value = match < _Tp > (nullptr);
	};
	template<typename,bool> struct hash_if;
	template<typename T>struct hash_if<T,true> {
		static std::size_t hash(const T& val)
		{
			static std::hash<T> gen;
			return gen(val);
		}
	};
	template<typename T>struct hash_if<T,false> {
		static std::size_t hash(const T& val)
		{
			throw cov::error("E000F");
		}
	};
	template<typename T>std::size_t hash(const T& val)
	{
		return hash_if<T,hash_helper<T>::value>::hash(val);
	}
	class any final {
		class baseHolder {
		public:
			baseHolder() = default;
			virtual ~ baseHolder() = default;
			virtual const std::type_info & type() const = 0;
			virtual baseHolder *duplicate() = 0;
			virtual bool compare(const baseHolder *) const = 0;
			virtual std::string to_string() const = 0;
			virtual std::size_t hash() const = 0;
		};
		template < typename T > class holder:public baseHolder {
		protected:
			T mDat;
		public:
			holder() = default;
			holder(const T& dat):mDat(dat) {}
			virtual ~ holder() = default;
			virtual const std::type_info & type() const override
			{
				return typeid(T);
			}
			virtual baseHolder *duplicate() override
			{
				return new holder(mDat);
			}
			virtual bool compare(const baseHolder * obj)const override
			{
				if (obj->type() == this->type()) {
					const holder < T > *ptr = dynamic_cast < const holder < T > *>(obj);
					return ptr!=nullptr?cov::compare(mDat,ptr->data()):false;
				}
				return false;
			}
			virtual std::string to_string() const override
			{
				return std::move(std::to_string(mDat));
			}
			virtual std::size_t hash() const override
			{
				return cov::hash<T>(mDat);
			}
			T & data()
			{
				return mDat;
			}
			const T & data() const
			{
				return mDat;
			}
			void data(const T & dat)
			{
				mDat = dat;
			}
		};
		using size_t=unsigned long;
		struct proxy {
			mutable size_t refcount=1;
			baseHolder* data=nullptr;
			proxy()=default;
			proxy(size_t rc,baseHolder* d):refcount(rc),data(d) {}
			~proxy()
			{
				delete data;
			}
		};
		proxy* mDat=nullptr;
		proxy* duplicate() const noexcept
		{
			if(mDat!=nullptr) {
				++mDat->refcount;
			}
			return mDat;
		}
		void recycle() noexcept
		{
			if(mDat!=nullptr) {
				--mDat->refcount;
				if(mDat->refcount==0) {
					delete mDat;
					mDat=nullptr;
				}
			}
		}
	public:
		static any infer_value(const std::string&);
		void swap(any& obj) noexcept
		{
			proxy* tmp=this->mDat;
			this->mDat=obj.mDat;
			obj.mDat=tmp;
		}
		void swap(any&& obj) noexcept
		{
			proxy* tmp=this->mDat;
			this->mDat=obj.mDat;
			obj.mDat=tmp;
		}
		void clone() noexcept
		{
			if(mDat!=nullptr) {
				proxy* dat=new proxy(1,mDat->data->duplicate());
				recycle();
				mDat=dat;
			}
		}
		bool usable() const noexcept
		{
			return mDat != nullptr;
		}
		any()=default;
		template < typename T > any(const T & dat):mDat(new proxy(1,new holder < T > (dat))) {}
		any(const any & v):mDat(v.duplicate()) {}
		any(any&& v) noexcept
		{
			swap(std::forward<any>(v));
		}
		~any()
		{
			recycle();
		}
		const std::type_info & type() const
		{
			return this->mDat != nullptr?this->mDat->data->type():typeid(void);
		}
		std::string to_string() const
		{
			if(this->mDat == nullptr)
				return "Null";
			return std::move(this->mDat->data->to_string());
		}
		std::size_t hash() const
		{
			if(this->mDat == nullptr)
				return cov::hash<void*>(nullptr);
			return this->mDat->data->hash();
		}
		any & operator=(const any & var)
		{
			if(&var!=this) {
				recycle();
				mDat = var.duplicate();
			}
			return *this;
		}
		any & operator=(any&& var) noexcept
		{
			if(&var!=this)
				swap(std::forward<any>(var));
			return *this;
		}
		bool operator==(const any & var) const
		{
			return usable()?this->mDat->data->compare(var.mDat->data):!var.usable();
		}
		bool operator!=(const any & var)const
		{
			return usable()?!this->mDat->data->compare(var.mDat->data):var.usable();
		}
		template < typename T > T & val(bool raw=false)
		{
			if(typeid(T) != this->type())
				throw cov::error("E0006");
			if(this->mDat == nullptr)
				throw cov::error("E0005");
			if(!raw)
				clone();
			return dynamic_cast < holder < T > *>(this->mDat->data)->data();
		}
		template < typename T > const T & val(bool raw=false) const
		{
			if(typeid(T) != this->type())
				throw cov::error("E0006");
			if(this->mDat == nullptr)
				throw cov::error("E0005");
			return dynamic_cast < const holder < T > *>(this->mDat->data)->data();
		}
		template < typename T > const T& const_val() const
		{
			if(typeid(T) != this->type())
				throw cov::error("E0006");
			if(this->mDat == nullptr)
				throw cov::error("E0005");
			return dynamic_cast < const holder < T > *>(this->mDat->data)->data();
		}
		template < typename T > operator T&()
		{
			return this->val<T>();
		}
		template < typename T > operator const T&() const
		{
			return this->const_val<T>();
		}
		void assign(const any& obj,bool raw=false)
		{
			if(&obj!=this&&obj.mDat!=mDat) {
				if(mDat!=nullptr&&obj.mDat!=nullptr&&raw) {
					delete mDat->data;
					mDat->data=obj.mDat->data->duplicate();
				} else {
					recycle();
					if(obj.mDat!=nullptr)
						mDat=new proxy(1,obj.mDat->data->duplicate());
					else
						mDat=nullptr;
				}
			}
		}
		template < typename T > void assign(const T & dat,bool raw=false)
		{
			if(raw) {
				delete mDat->data;
				mDat->data=new holder < T > (dat);
			} else {
				recycle();
				mDat = new proxy(1,new holder < T > (dat));
			}
		}
		template < typename T > any & operator=(const T & dat)
		{
			assign(dat);
			return *this;
		}
		bool is_same(const any& obj) const
		{
			return this->mDat==obj.mDat;
		}
	};
	template<int N> class any::holder<char[N]>:public any::holder<std::string> {
	public:
		using holder<std::string>::holder;
	};
	template<> class any::holder<std::type_info>:public any::holder<std::type_index> {
	public:
		using holder<std::type_index>::holder;
	};
}

cov::any cov::any::infer_value(const std::string& str)
{
	if(str=="true"||str=="True"||str=="TRUE")
		return true;
	if(str=="false"||str=="False"||str=="FALSE")
		return false;
	enum types {
		interger,floating,other
	} type=types::interger;
	for(auto& it:str) {
		if(!std::isdigit(it)&&it!='.') {
			type=other;
			break;
		}
		if(!std::isdigit(it)&&it=='.') {
			if(type==interger) {
				type=floating;
				continue;
			}
			if(type==floating) {
				type=other;
				break;
			}
		}
	}
	switch(type) {
	case interger:
		try {
			return std::stoi(str);
		} catch(std::out_of_range) {
			try {
				return std::stol(str);
			} catch(std::out_of_range) {
				try {
					return std::stoll(str);
				} catch(std::out_of_range) {
					return str;
				}
			}
		}
	case floating:
		return std::stod(str);
	case other:
		break;
	}
	return str;
}

std::istream& operator>>(std::istream& in,cov::any& val)
{
	static std::string str;
	in>>str;
	val=cov::any::infer_value(str);
	return in;
}

std::ostream& operator<<(std::ostream& out,const cov::any& val)
{
	out<<val.to_string();
	return out;
}

namespace std {
	template<> struct hash<cov::any> {
		std::size_t operator()(const cov::any& val) const
		{
			return val.hash();
		}
	};
}
<|endoftext|>


<commit_before>#include "util/testing.h"

#include <event2/thread.h>
#include <gflags/gflags.h>
#include <glog/logging.h>
#include <gtest/gtest.h>

namespace cert_trans {
namespace test {

void InitTesting(const char* name, int* argc, char*** argv,
                 bool remove_flags) {
  ::testing::InitGoogleTest(argc, *argv);
  google::ParseCommandLineFlags(argc, argv, remove_flags);
  google::InitGoogleLogging(name);
  evthread_use_pthreads();
}

}  // namespace test
}  // namespace cert_trans
<commit_msg>Show stack traces on fatal signals for tests too.<commit_after>#include "util/testing.h"

#include <event2/thread.h>
#include <gflags/gflags.h>
#include <glog/logging.h>
#include <gtest/gtest.h>

namespace cert_trans {
namespace test {

void InitTesting(const char* name, int* argc, char*** argv,
                 bool remove_flags) {
  ::testing::InitGoogleTest(argc, *argv);
  google::ParseCommandLineFlags(argc, argv, remove_flags);
  google::InitGoogleLogging(name);
  google::InstallFailureSignalHandler();
  evthread_use_pthreads();
}

}  // namespace test
}  // namespace cert_trans
<|endoftext|>


<commit_before>//------------------------------------------------------------------------------
// CLING - the C++ LLVM-based InterpreterG :)
// version: $Id$
// author:  Vassil Vassilev <vasil.georgiev.vasilev@cern.ch>
//------------------------------------------------------------------------------

#include "cling/Interpreter/ValuePrinter.h"

#include "cling/Interpreter/CValuePrinter.h"
#include "cling/Interpreter/ValuePrinterInfo.h"
#include "cling/Interpreter/Value.h"

#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/Expr.h"
#include "clang/AST/Type.h"

#include "llvm/Support/raw_ostream.h"

#include <string>

// Implements the CValuePrinter interface.
extern "C" void cling_PrintValue(void* /*clang::Expr**/ E,
                      void* /*clang::ASTContext**/ C,
                      const void* value) {
  clang::Expr* Exp = (clang::Expr*)E;
  clang::ASTContext* Context = (clang::ASTContext*)C;
  cling::ValuePrinterInfo VPI(Exp, Context);
  cling::printValuePublic(llvm::outs(), value, value, VPI);

  cling::flushOStream(llvm::outs());
}

static void StreamChar(llvm::raw_ostream& o, const char v) {
  o << '"' << v << "\"\n";
}

static void StreamCharPtr(llvm::raw_ostream& o, const char* const v) {
  o << '"';
  const char* p = v;
  for (;*p && p - v < 128; ++p) {
    o << *p;
  }
  if (*p) o << "\"...\n";
  else o << "\"\n";
}

static void StreamRef(llvm::raw_ostream& o, const void* v) {
  o <<"&" << v << "\n";
}

static void StreamPtr(llvm::raw_ostream& o, const void* v) {
  o << v << "\n";
}

static void StreamObj(llvm::raw_ostream& o, const void* v,
                      const cling::ValuePrinterInfo& VPI) {
  const clang::Type* Ty = VPI.getExpr()->getType().getTypePtr();
  if (clang::CXXRecordDecl* CXXRD = Ty->getAsCXXRecordDecl())
    if (CXXRD->getQualifiedNameAsString().compare("cling::Value") == 0) {
      cling::Value* V = (cling::Value*)v;
      if (V->isValid()) {
        o << "boxes [";
        const clang::ASTContext& C = *VPI.getASTContext();
        o <<
          "(" <<
          V->type.getAsString(C.getPrintingPolicy()) <<
          ") ";
        clang::QualType valType = V->type.getDesugaredType(C);
        if (valType->isPointerType())
          o << V->value.PointerVal;
        else if (valType->isFloatingType())
          o << V->value.DoubleVal;
        else if (valType->isIntegerType())
          o << V->value.IntVal.getSExtValue();
        else if (valType->isBooleanType())
          o << V->value.IntVal.getBoolValue();
        o << "]\n";

        return;
      } else
        o << "<<<invalid>>> ";
    }

  // TODO: Print the object members.
  o << "@" << v << "\n";
}

static void StreamValue(llvm::raw_ostream& o, const void* const p,
                        const cling::ValuePrinterInfo& VPI) {
  clang::QualType Ty = VPI.getExpr()->getType();
  const clang::ASTContext& C = *VPI.getASTContext();
  Ty = Ty.getDesugaredType(C);
  if (const clang::BuiltinType *BT
           = llvm::dyn_cast<clang::BuiltinType>(Ty.getCanonicalType())) {
    switch (BT->getKind()) {
    case clang::BuiltinType::Bool:
      if (*(bool*)p) o << "true\n";
      else o << "false\n"; break;
    case clang::BuiltinType::Char_U:
    case clang::BuiltinType::UChar:
    case clang::BuiltinType::Char_S:
    case clang::BuiltinType::SChar:  StreamChar(o, *(char*)p); break;
    case clang::BuiltinType::Short:  o << *(short*)p << "\n"; break;
    case clang::BuiltinType::UShort: o << *(unsigned short*)p << "\n"; break;
    case clang::BuiltinType::Int:    o << *(int*)p << "\n"; break;
    case clang::BuiltinType::UInt:   o << *(unsigned int*)p << "\n"; break;
    case clang::BuiltinType::Long:   o << *(long*)p << "\n"; break;
    case clang::BuiltinType::ULong:  o << *(unsigned long*)p << "\n"; break;
    case clang::BuiltinType::LongLong:  o << *(long long*)p << "\n"; break;
    case clang::BuiltinType::ULongLong: o << *(unsigned long long*)p << "\n";
      break;
    case clang::BuiltinType::Float:  o << *(float*)p << "\n"; break;
    case clang::BuiltinType::Double: o << *(double*)p << "\n"; break;
    default:
      StreamObj(o, p, VPI);
    }
  }
  else if (Ty.getAsString().compare("class std::basic_string<char>") == 0) {
    StreamObj(o, p, VPI);
    o <<"c_str: ";
    StreamCharPtr(o, ((const char*) (*(const std::string*)p).c_str()));
  }
  else if (Ty->isEnumeralType()) {
    StreamObj(o, p, VPI);
    clang::EnumDecl* ED = Ty->getAs<clang::EnumType>()->getDecl();
    uint64_t value = *(uint64_t*)p;
    bool IsFirst = true;
    llvm::APSInt ValAsAPSInt = C.MakeIntValue(value, Ty);
    for (clang::EnumDecl::enumerator_iterator I = ED->enumerator_begin(),
           E = ED->enumerator_end(); I != E; ++I) {
      if (I->getInitVal() == ValAsAPSInt) {
        if (!IsFirst) {
          o << " ? ";
        }
        o << "(" << I->getQualifiedNameAsString() << ")";
        IsFirst = false;
      }
    }
    o << " : (int) " << ValAsAPSInt.toString(/*Radix = */10) << "\n";
  }
  else if (Ty->isReferenceType())
    StreamRef(o, p);
  else if (Ty->isPointerType()) {
    clang::QualType PointeeTy = Ty->getPointeeType();
    if (PointeeTy->isCharType())
      StreamCharPtr(o, (const char*)p);
    else
      StreamPtr(o, p);
  }
  else
    StreamObj(o, p, VPI);
}

namespace cling {
  void printValuePublicDefault(llvm::raw_ostream& o, const void* const p,
                               const ValuePrinterInfo& VPI) {
    const clang::Expr* E = VPI.getExpr();
    o << "(";
    o << E->getType().getAsString();
    if (E->isRValue()) // show the user that the var cannot be changed
      o << " const";
    o << ") ";
    StreamValue(o, p, VPI);
  }

  void flushOStream(llvm::raw_ostream& o) {
    o.flush();
  }

} // end namespace cling
<commit_msg>Improve const-correctness in casts.<commit_after>//------------------------------------------------------------------------------
// CLING - the C++ LLVM-based InterpreterG :)
// version: $Id$
// author:  Vassil Vassilev <vasil.georgiev.vasilev@cern.ch>
//------------------------------------------------------------------------------

#include "cling/Interpreter/ValuePrinter.h"

#include "cling/Interpreter/CValuePrinter.h"
#include "cling/Interpreter/ValuePrinterInfo.h"
#include "cling/Interpreter/Value.h"

#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/Expr.h"
#include "clang/AST/Type.h"

#include "llvm/Support/raw_ostream.h"

#include <string>

// Implements the CValuePrinter interface.
extern "C" void cling_PrintValue(void* /*clang::Expr**/ E,
                      void* /*clang::ASTContext**/ C,
                      const void* value) {
  clang::Expr* Exp = (clang::Expr*)E;
  clang::ASTContext* Context = (clang::ASTContext*)C;
  cling::ValuePrinterInfo VPI(Exp, Context);
  cling::printValuePublic(llvm::outs(), value, value, VPI);

  cling::flushOStream(llvm::outs());
}

static void StreamChar(llvm::raw_ostream& o, const char v) {
  o << '"' << v << "\"\n";
}

static void StreamCharPtr(llvm::raw_ostream& o, const char* const v) {
  o << '"';
  const char* p = v;
  for (;*p && p - v < 128; ++p) {
    o << *p;
  }
  if (*p) o << "\"...\n";
  else o << "\"\n";
}

static void StreamRef(llvm::raw_ostream& o, const void* v) {
  o <<"&" << v << "\n";
}

static void StreamPtr(llvm::raw_ostream& o, const void* v) {
  o << v << "\n";
}

static void StreamObj(llvm::raw_ostream& o, const void* v,
                      const cling::ValuePrinterInfo& VPI) {
  const clang::Type* Ty = VPI.getExpr()->getType().getTypePtr();
  if (clang::CXXRecordDecl* CXXRD = Ty->getAsCXXRecordDecl())
    if (CXXRD->getQualifiedNameAsString().compare("cling::Value") == 0) {
      cling::Value* V = (cling::Value*)v;
      if (V->isValid()) {
        o << "boxes [";
        const clang::ASTContext& C = *VPI.getASTContext();
        o <<
          "(" <<
          V->type.getAsString(C.getPrintingPolicy()) <<
          ") ";
        clang::QualType valType = V->type.getDesugaredType(C);
        if (valType->isPointerType())
          o << V->value.PointerVal;
        else if (valType->isFloatingType())
          o << V->value.DoubleVal;
        else if (valType->isIntegerType())
          o << V->value.IntVal.getSExtValue();
        else if (valType->isBooleanType())
          o << V->value.IntVal.getBoolValue();
        o << "]\n";

        return;
      } else
        o << "<<<invalid>>> ";
    }

  // TODO: Print the object members.
  o << "@" << v << "\n";
}

static void StreamValue(llvm::raw_ostream& o, const void* const p,
                        const cling::ValuePrinterInfo& VPI) {
  clang::QualType Ty = VPI.getExpr()->getType();
  const clang::ASTContext& C = *VPI.getASTContext();
  Ty = Ty.getDesugaredType(C);
  if (const clang::BuiltinType *BT
           = llvm::dyn_cast<clang::BuiltinType>(Ty.getCanonicalType())) {
    switch (BT->getKind()) {
    case clang::BuiltinType::Bool:
      if (*(const bool*)p) o << "true\n";
      else o << "false\n"; break;
    case clang::BuiltinType::Char_U:
    case clang::BuiltinType::UChar:
    case clang::BuiltinType::Char_S:
    case clang::BuiltinType::SChar:  StreamChar(o, *(const char*)p); break;
    case clang::BuiltinType::Short:  o << *(const short*)p << "\n"; break;
    case clang::BuiltinType::UShort:
      o << *(const unsigned short*)p << "\n";
      break;
    case clang::BuiltinType::Int:    o << *(const int*)p << "\n"; break;
    case clang::BuiltinType::UInt:
      o << *(const unsigned int*)p << "\n";
      break;
    case clang::BuiltinType::Long:   o << *(const long*)p << "\n"; break;
    case clang::BuiltinType::ULong:
      o << *(const unsigned long*)p << "\n";
      break;
    case clang::BuiltinType::LongLong:
      o << *(const long long*)p << "\n";
      break;
    case clang::BuiltinType::ULongLong:
      o << *(const unsigned long long*)p << "\n";
      break;
    case clang::BuiltinType::Float:  o << *(const float*)p << "\n"; break;
    case clang::BuiltinType::Double: o << *(const double*)p << "\n"; break;
    default:
      StreamObj(o, p, VPI);
    }
  }
  else if (Ty.getAsString().compare("class std::basic_string<char>") == 0) {
    StreamObj(o, p, VPI);
    o <<"c_str: ";
    StreamCharPtr(o, ((const char*) (*(const std::string*)p).c_str()));
  }
  else if (Ty->isEnumeralType()) {
    StreamObj(o, p, VPI);
    clang::EnumDecl* ED = Ty->getAs<clang::EnumType>()->getDecl();
    uint64_t value = *(const uint64_t*)p;
    bool IsFirst = true;
    llvm::APSInt ValAsAPSInt = C.MakeIntValue(value, Ty);
    for (clang::EnumDecl::enumerator_iterator I = ED->enumerator_begin(),
           E = ED->enumerator_end(); I != E; ++I) {
      if (I->getInitVal() == ValAsAPSInt) {
        if (!IsFirst) {
          o << " ? ";
        }
        o << "(" << I->getQualifiedNameAsString() << ")";
        IsFirst = false;
      }
    }
    o << " : (int) " << ValAsAPSInt.toString(/*Radix = */10) << "\n";
  }
  else if (Ty->isReferenceType())
    StreamRef(o, p);
  else if (Ty->isPointerType()) {
    clang::QualType PointeeTy = Ty->getPointeeType();
    if (PointeeTy->isCharType())
      StreamCharPtr(o, (const char*)p);
    else
      StreamPtr(o, p);
  }
  else
    StreamObj(o, p, VPI);
}

namespace cling {
  void printValuePublicDefault(llvm::raw_ostream& o, const void* const p,
                               const ValuePrinterInfo& VPI) {
    const clang::Expr* E = VPI.getExpr();
    o << "(";
    o << E->getType().getAsString();
    if (E->isRValue()) // show the user that the var cannot be changed
      o << " const";
    o << ") ";
    StreamValue(o, p, VPI);
  }

  void flushOStream(llvm::raw_ostream& o) {
    o.flush();
  }

} // end namespace cling
<|endoftext|>


<commit_before>//------------------------------------------------------------------------------
// CLING - the C++ LLVM-based InterpreterG :)
// version: $Id$
// author:  Vassil Vassilev <vvasilev@cern.ch>
//------------------------------------------------------------------------------

#include "MetaParser.h"

#include "MetaLexer.h"
#include "MetaSema.h"

#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Path.h"

namespace cling {

  MetaParser::MetaParser(MetaSema* Actions) {
    m_Lexer.reset(0);
    m_Actions.reset(Actions);
  }

  void MetaParser::enterNewInputLine(llvm::StringRef Line) {
    m_Lexer.reset(new MetaLexer(Line));
    m_TokenCache.clear();
  }

  void MetaParser::consumeToken() {
    if (m_TokenCache.size())
      m_TokenCache.erase(m_TokenCache.begin());

    lookAhead(0);
  }

  void MetaParser::consumeAnyStringToken(tok::TokenKind stopAt/*=tok::space*/) {
    consumeToken();
    // we have to merge the tokens from the queue until we reach eof token or
    // space token
    SkipWhitespace();
    // Add the new token in which we will merge the others.
    Token& MergedTok = m_TokenCache.front();

    if (MergedTok.is(stopAt) || MergedTok.is(tok::eof)
        || MergedTok.is(tok::comment))
      return;

    Token Tok = lookAhead(1);
    while (Tok.isNot(stopAt) && Tok.isNot(tok::eof) && Tok.isNot(tok::comment)){
      //MergedTok.setLength(MergedTok.getLength() + Tok.getLength());
      m_TokenCache.erase(m_TokenCache.begin() + 1);
      Tok = lookAhead(1);
    }
    MergedTok.setKind(tok::raw_ident);
    MergedTok.setLength(Tok.getBufStart() - MergedTok.getBufStart());
  }

  const Token& MetaParser::lookAhead(unsigned N) {
    if (N < m_TokenCache.size())
      return m_TokenCache[N];

    for (unsigned C = N+1 - m_TokenCache.size(); C > 0; --C) {
      m_TokenCache.push_back(Token());
      m_Lexer->Lex(m_TokenCache.back());
    }
    return m_TokenCache.back();
  }

  void MetaParser::SkipWhitespace() {
    while(getCurTok().is(tok::space))
      consumeToken();
  }

  bool MetaParser::isMetaCommand() {
    return isCommandSymbol() && isCommand();
  }

  bool MetaParser::isCommandSymbol() {
    consumeToken();
    if (getCurTok().is(tok::dot) /*TODO: || Tok.is(//.)*/)
      return true;
    return false;
  }

  bool MetaParser::isCommand() {
    consumeToken();
    return isLCommand() || isxCommand() || isXCommand() || isqCommand()
      || isUCommand() || isICommand() || israwInputCommand()
      || isprintASTCommand() || isdynamicExtensionsCommand() || ishelpCommand()
      || isfileExCommand() || isfilesCommand();
  }

  // L := 'L' FilePath
  // FilePath := AnyString
  // AnyString := .*^(' ' | '\t')
  bool MetaParser::isLCommand() {
    bool result = false;
    if (getCurTok().is(tok::ident) && getCurTok().getIdent().equals("L")) {
      consumeAnyStringToken();
      if (getCurTok().is(tok::raw_ident)) {
        result = true;
        m_Actions->ActOnLCommand(llvm::sys::Path(getCurTok().getIdent()));
        consumeToken();
        if (getCurTok().is(tok::comment)) {
          consumeAnyStringToken();
          m_Actions->ActOnComment(getCurTok().getIdent());
        }
      }
    }
    // TODO: Some fine grained diagnostics
    return result;
  }

  // xCommand := 'x' FilePath[ArgList]
  // FilePath := AnyString
  // ArgList := (ExtraArgList) ' ' [ArgList]
  // ExtraArgList := AnyString [, ExtraArgList]
  bool MetaParser::isxCommand() {
    bool result = false;
    if (getCurTok().is(tok::ident) && getCurTok().getIdent().equals("x")) {
      // There might be ArgList
      consumeAnyStringToken(tok::l_paren);
      llvm::sys::Path file(getCurTok().getIdent());
      llvm::StringRef args;
      result = true;
      consumeToken();
      if (getCurTok().is(tok::l_paren) && isExtraArgList()) {
        args = getCurTok().getIdent();
        consumeToken(); // consume the closing paren
      }
      m_Actions->ActOnxCommand(file, args);
      if (getCurTok().is(tok::comment)) {
        consumeAnyStringToken();
        m_Actions->ActOnComment(getCurTok().getIdent());
      }

    }

    return result;
  }

  // ExtraArgList := AnyString [, ExtraArgList]
  bool MetaParser::isExtraArgList() {
    // This might be expanded if we need better arg parsing.
    consumeAnyStringToken(tok::r_paren);

    return getCurTok().is(tok::raw_ident);
  }

  bool MetaParser::isXCommand() {
    // TODO: For now we don't distinguish both cases. In future we will have to.
    return isxCommand();
  }

  bool MetaParser::isqCommand() {
    bool result = false;
    if (getCurTok().is(tok::ident) && getCurTok().getIdent().equals("q")) {
      result = true;
      m_Actions->ActOnqCommand();
    }
    return result;
  }

  bool MetaParser::isUCommand() {
    if (getCurTok().is(tok::ident) && getCurTok().getIdent().equals("q")) {
      m_Actions->ActOnUCommand();
      return true;
    }
    return false;
  }

  bool MetaParser::isICommand() {
    if (getCurTok().is(tok::ident) && getCurTok().getIdent().equals("I")) {
      consumeAnyStringToken();
      llvm::sys::Path path;
      if (getCurTok().is(tok::raw_ident))
        path = getCurTok().getIdent();
      m_Actions->ActOnICommand(path);
      return true;
    }
    return false;
  }

  bool MetaParser::israwInputCommand() {
    if (getCurTok().is(tok::ident) &&
        getCurTok().getIdent().equals("rawInput")) {
      MetaSema::SwitchMode mode = MetaSema::kToggle;
      consumeToken();
      SkipWhitespace();
      if (getCurTok().is(tok::constant))
        mode = (MetaSema::SwitchMode)getCurTok().getConstant();
      m_Actions->ActOnrawInputCommand(mode);
      return true;
    }
    return false;
  }

  bool MetaParser::isprintASTCommand() {
    if (getCurTok().is(tok::ident) &&
        getCurTok().getIdent().equals("printAST")) {
      MetaSema::SwitchMode mode = MetaSema::kToggle;
      consumeToken();
      SkipWhitespace();
      if (getCurTok().is(tok::constant))
        mode = (MetaSema::SwitchMode)getCurTok().getConstant();
      m_Actions->ActOnprintASTCommand(mode);
      return true;
    }
    return false;
  }

  bool MetaParser::isdynamicExtensionsCommand() {
    if (getCurTok().is(tok::ident) &&
        getCurTok().getIdent().equals("dynamicExtensions")) {
      MetaSema::SwitchMode mode = MetaSema::kToggle;
      consumeToken();
      SkipWhitespace();
      if (getCurTok().is(tok::constant))
        mode = (MetaSema::SwitchMode)getCurTok().getConstant();
      m_Actions->ActOndynamicExtensionsCommand(mode);
      return true;
    }
    return false;
  }

  bool MetaParser::ishelpCommand() {
    if (getCurTok().is(tok::ident) && getCurTok().getIdent().equals("help")) {
      m_Actions->ActOnhelpCommand();
      return true;
    }
    return false;
  }

  bool MetaParser::isfileExCommand() {
    if (getCurTok().is(tok::ident) && getCurTok().getIdent().equals("fileEx")) {
      m_Actions->ActOnfileExCommand();
      return true;
    }
    return false;
  }

  bool MetaParser::isfilesCommand() {
    if (getCurTok().is(tok::ident) && getCurTok().getIdent().equals("files")) {
      m_Actions->ActOnfilesCommand();
      return true;
    }
    return false;
  }

} // end namespace cling
<commit_msg>Add support for .X. Ignore comments in LexAnyStringToken for now.<commit_after>//------------------------------------------------------------------------------
// CLING - the C++ LLVM-based InterpreterG :)
// version: $Id$
// author:  Vassil Vassilev <vvasilev@cern.ch>
//------------------------------------------------------------------------------

#include "MetaParser.h"

#include "MetaLexer.h"
#include "MetaSema.h"

#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Path.h"

namespace cling {

  MetaParser::MetaParser(MetaSema* Actions) {
    m_Lexer.reset(0);
    m_Actions.reset(Actions);
  }

  void MetaParser::enterNewInputLine(llvm::StringRef Line) {
    m_Lexer.reset(new MetaLexer(Line));
    m_TokenCache.clear();
  }

  void MetaParser::consumeToken() {
    if (m_TokenCache.size())
      m_TokenCache.erase(m_TokenCache.begin());

    lookAhead(0);
  }

  void MetaParser::consumeAnyStringToken(tok::TokenKind stopAt/*=tok::space*/) {
    consumeToken();
    // we have to merge the tokens from the queue until we reach eof token or
    // space token
    SkipWhitespace();
    // Add the new token in which we will merge the others.
    Token& MergedTok = m_TokenCache.front();

    if (MergedTok.is(stopAt) || MergedTok.is(tok::eof)
        || MergedTok.is(tok::comment))
      return;

    Token Tok = lookAhead(1);
    while (Tok.isNot(stopAt) && Tok.isNot(tok::eof)){
      //MergedTok.setLength(MergedTok.getLength() + Tok.getLength());
      m_TokenCache.erase(m_TokenCache.begin() + 1);
      Tok = lookAhead(1);
    }
    MergedTok.setKind(tok::raw_ident);
    MergedTok.setLength(Tok.getBufStart() - MergedTok.getBufStart());
  }

  const Token& MetaParser::lookAhead(unsigned N) {
    if (N < m_TokenCache.size())
      return m_TokenCache[N];

    for (unsigned C = N+1 - m_TokenCache.size(); C > 0; --C) {
      m_TokenCache.push_back(Token());
      m_Lexer->Lex(m_TokenCache.back());
    }
    return m_TokenCache.back();
  }

  void MetaParser::SkipWhitespace() {
    while(getCurTok().is(tok::space))
      consumeToken();
  }

  bool MetaParser::isMetaCommand() {
    return isCommandSymbol() && isCommand();
  }

  bool MetaParser::isCommandSymbol() {
    consumeToken();
    if (getCurTok().is(tok::dot) /*TODO: || Tok.is(//.)*/)
      return true;
    return false;
  }

  bool MetaParser::isCommand() {
    consumeToken();
    return isLCommand() || isxCommand() /*|| isXCommand() */|| isqCommand()
      || isUCommand() || isICommand() || israwInputCommand()
      || isprintASTCommand() || isdynamicExtensionsCommand() || ishelpCommand()
      || isfileExCommand() || isfilesCommand();
  }

  // L := 'L' FilePath
  // FilePath := AnyString
  // AnyString := .*^(' ' | '\t')
  bool MetaParser::isLCommand() {
    bool result = false;
    if (getCurTok().is(tok::ident) && getCurTok().getIdent().equals("L")) {
      consumeAnyStringToken();
      if (getCurTok().is(tok::raw_ident)) {
        result = true;
        m_Actions->ActOnLCommand(llvm::sys::Path(getCurTok().getIdent()));
        consumeToken();
        if (getCurTok().is(tok::comment)) {
          consumeAnyStringToken();
          m_Actions->ActOnComment(getCurTok().getIdent());
        }
      }
    }
    // TODO: Some fine grained diagnostics
    return result;
  }

  // xCommand := 'x' FilePath[ArgList]
  // FilePath := AnyString
  // ArgList := (ExtraArgList) ' ' [ArgList]
  // ExtraArgList := AnyString [, ExtraArgList]
  bool MetaParser::isxCommand() {
    bool result = false;
    if (getCurTok().is(tok::ident) && (getCurTok().getIdent().equals("x")
                                       || getCurTok().getIdent().equals("X"))) {
      // There might be ArgList
      consumeAnyStringToken(tok::l_paren);
      llvm::sys::Path file(getCurTok().getIdent());
      llvm::StringRef args;
      result = true;
      consumeToken();
      if (getCurTok().is(tok::l_paren) && isExtraArgList()) {
        args = getCurTok().getIdent();
        consumeToken(); // consume the closing paren
      }
      m_Actions->ActOnxCommand(file, args);
      if (getCurTok().is(tok::comment)) {
        consumeAnyStringToken();
        m_Actions->ActOnComment(getCurTok().getIdent());
      }

    }

    return result;
  }

  // ExtraArgList := AnyString [, ExtraArgList]
  bool MetaParser::isExtraArgList() {
    // This might be expanded if we need better arg parsing.
    consumeAnyStringToken(tok::r_paren);

    return getCurTok().is(tok::raw_ident);
  }

  bool MetaParser::isXCommand() {
    // TODO: For now we don't distinguish both cases. In future we will have to.
    return isxCommand();
  }

  bool MetaParser::isqCommand() {
    bool result = false;
    if (getCurTok().is(tok::ident) && getCurTok().getIdent().equals("q")) {
      result = true;
      m_Actions->ActOnqCommand();
    }
    return result;
  }

  bool MetaParser::isUCommand() {
    if (getCurTok().is(tok::ident) && getCurTok().getIdent().equals("q")) {
      m_Actions->ActOnUCommand();
      return true;
    }
    return false;
  }

  bool MetaParser::isICommand() {
    if (getCurTok().is(tok::ident) && getCurTok().getIdent().equals("I")) {
      consumeAnyStringToken();
      llvm::sys::Path path;
      if (getCurTok().is(tok::raw_ident))
        path = getCurTok().getIdent();
      m_Actions->ActOnICommand(path);
      return true;
    }
    return false;
  }

  bool MetaParser::israwInputCommand() {
    if (getCurTok().is(tok::ident) &&
        getCurTok().getIdent().equals("rawInput")) {
      MetaSema::SwitchMode mode = MetaSema::kToggle;
      consumeToken();
      SkipWhitespace();
      if (getCurTok().is(tok::constant))
        mode = (MetaSema::SwitchMode)getCurTok().getConstant();
      m_Actions->ActOnrawInputCommand(mode);
      return true;
    }
    return false;
  }

  bool MetaParser::isprintASTCommand() {
    if (getCurTok().is(tok::ident) &&
        getCurTok().getIdent().equals("printAST")) {
      MetaSema::SwitchMode mode = MetaSema::kToggle;
      consumeToken();
      SkipWhitespace();
      if (getCurTok().is(tok::constant))
        mode = (MetaSema::SwitchMode)getCurTok().getConstant();
      m_Actions->ActOnprintASTCommand(mode);
      return true;
    }
    return false;
  }

  bool MetaParser::isdynamicExtensionsCommand() {
    if (getCurTok().is(tok::ident) &&
        getCurTok().getIdent().equals("dynamicExtensions")) {
      MetaSema::SwitchMode mode = MetaSema::kToggle;
      consumeToken();
      SkipWhitespace();
      if (getCurTok().is(tok::constant))
        mode = (MetaSema::SwitchMode)getCurTok().getConstant();
      m_Actions->ActOndynamicExtensionsCommand(mode);
      return true;
    }
    return false;
  }

  bool MetaParser::ishelpCommand() {
    if (getCurTok().is(tok::ident) && getCurTok().getIdent().equals("help")) {
      m_Actions->ActOnhelpCommand();
      return true;
    }
    return false;
  }

  bool MetaParser::isfileExCommand() {
    if (getCurTok().is(tok::ident) && getCurTok().getIdent().equals("fileEx")) {
      m_Actions->ActOnfileExCommand();
      return true;
    }
    return false;
  }

  bool MetaParser::isfilesCommand() {
    if (getCurTok().is(tok::ident) && getCurTok().getIdent().equals("files")) {
      m_Actions->ActOnfilesCommand();
      return true;
    }
    return false;
  }

} // end namespace cling
<|endoftext|>


<commit_before>// @(#)root/test:$name:  $:$id: stressSpectrum.cxx,v 1.15 2002/10/25 10:47:51 rdm exp $
// Author: Rene Brun 17/01/2006

/////////////////////////////////////////////////////////////////
//
//    TSPectrum test suite
//    ====================
//
// This stress program tests many elements of the TSpectrum, TSpectrum2 classes.
//
// To run in batch, do
//   stressSpectrum        : run 100 experiments with graphics (default)
//   stressSpectrum 1000   : run 1000 experiments with graphics
//   stressSpectrum -b 200 : run 200 experiments in batch mode
//   stressSpectrum -b     : run 100 experiments in batch mode
//
// To run interactively, do
// root -b
//  Root > .x stressSpectrum.cxx      : run 100 experiments with graphics (default)
//  Root > .x stressSpectrum.cxx(20)  : run 20 experiments
//  Root > .x stressSpectrum.cxx+(30) : run 30 experiments via ACLIC
//
// Several tests are run sequentially. Each test will produce one line (Test OK or Test FAILED) .
// At the end of the test a table is printed showing the global results
// Real Time and Cpu Time.
// One single number (ROOTMARKS) is also calculated showing the relative
// performance of your machine compared to a reference machine
// a Pentium IV 3.0 Ghz) with 512 MBytes of memory
// and 120 GBytes IDE disk.
//
// An example of output when all the tests run OK is shown below:
//
//////////////////////////////////////////////////////////////////////////
//                                                                      //
//****************************************************************************
//*  Starting  stress S P E C T R U M                                        *
//****************************************************************************
//Peak1 : found = 70.21/ 73.75, good = 65.03/ 68.60, ghost = 8.54/ 8.39,--- OK
//Peak2 : found =163/300, good =163, ghost =8,----------------------------  OK
//****************************************************************************
//stressSpectrum: Real Time =  19.86 seconds Cpu Time =  19.04 seconds
//****************************************************************************
//*  ROOTMARKS = 810.9   *  Root5.09/01   20051216/1229
//****************************************************************************

#include <stdlib.h>
#include "TApplication.h"
#include "TBenchmark.h"
#include "TCanvas.h"
#include "TH2.h"
#include "TF2.h"
#include "TRandom.h"
#include "TSpectrum.h"
#include "TSpectrum2.h"
#include "TStyle.h"
#include "Riostream.h"
#include "TROOT.h"
#include "TMath.h"

Int_t npeaks;
Double_t fpeaks(Double_t *x, Double_t *par) {
   Double_t result = par[0] + par[1]*x[0];
   for (Int_t p=0;p<npeaks;p++) {
      Double_t norm  = par[3*p+2];
      Double_t mean  = par[3*p+3];
      Double_t sigma = par[3*p+4];
      result += norm*TMath::Gaus(x[0],mean,sigma);
   }
   return result;
}
Double_t fpeaks2(Double_t *x, Double_t *par) {
   Double_t result = 0.1;
   for (Int_t p=0;p<npeaks;p++) {
      Double_t norm   = par[5*p+0];
      Double_t mean1  = par[5*p+1];
      Double_t sigma1 = par[5*p+2];
      Double_t mean2  = par[5*p+3];
      Double_t sigma2 = par[5*p+4];
      result += norm*TMath::Gaus(x[0],mean1,sigma1)*TMath::Gaus(x[1],mean2,sigma2);
   }
   return result;
}
void findPeaks(Int_t pmin, Int_t pmax, Int_t &nfound, Int_t &ngood, Int_t &nghost) {
   npeaks = (Int_t)gRandom->Uniform(pmin,pmax);
   Int_t nbins = 500;
   Double_t dxbins = 2;
   TH1F *h = new TH1F("h","test",nbins,0,nbins*dxbins);
   //generate n peaks at random
   Double_t par[3000];
   par[0] = 0.8;
   par[1] = -0.6/1000;
   Int_t p,pf;
   for (p=0;p<npeaks;p++) {
      par[3*p+2] = 1;
      par[3*p+3] = 10+gRandom->Rndm()*(nbins-20)*dxbins;
      par[3*p+4] = 3+2*gRandom->Rndm();
   }
   TF1 *f = new TF1("f",fpeaks,0,nbins*dxbins,2+3*npeaks);
   f->SetNpx(1000);
   f->SetParameters(par);
   h->FillRandom("f",200000);
   TSpectrum *s = new TSpectrum(4*npeaks);
   nfound = s->Search(h,2,"goff");
   //Search found peaks
   ngood = 0;
   Float_t *xpeaks = s->GetPositionX();
   for (p=0;p<npeaks;p++) {
      for (Int_t pf=0;pf<nfound;pf++) {
         Double_t dx = TMath::Abs(xpeaks[pf] - par[3*p+3]);
         if (dx <dxbins) ngood++;
      }
   }
   //Search ghost peaks
   nghost = 0;
   for (pf=0;pf<nfound;pf++) {
      Int_t nf=0;
      for (Int_t p=0;p<npeaks;p++) {
         Double_t dx = TMath::Abs(xpeaks[pf] - par[3*p+3]);
         if (dx <dxbins) nf++;
      }
      if (nf == 0) nghost++;
   }
   delete f;
   delete h;
   delete s;
}

void stress1(Int_t ntimes) {
   Int_t pmin = 5;
   Int_t pmax = 55;
   TCanvas *c1 = new TCanvas("c1","Spectrum results",10,10,800,800);
   c1->Divide(2,2);
   gStyle->SetOptFit();
   TH1F *hpeaks = new TH1F("hpeaks","Number of peaks",pmax-pmin,pmin,pmax);
   TH1F *hfound = new TH1F("hfound","% peak founds",100,0,100);
   TH1F *hgood  = new TH1F("hgood", "% good peaks",100,0,100);
   TH1F *hghost = new TH1F("hghost","% ghost peaks",100,0,100);
   Int_t nfound,ngood,nghost;
   for (Int_t i=0;i<ntimes;i++) {
      findPeaks(pmin,pmax,nfound,ngood,nghost);
      hpeaks->Fill(npeaks);
      hfound->Fill(100*Double_t(nfound)/Double_t(npeaks));
      hgood->Fill(100*Double_t(ngood)/Double_t(npeaks));
      hghost->Fill(100*Double_t(nghost)/Double_t(npeaks));
      //printf("npeaks = %d, nfound = %d, ngood = %d, nghost = %d\n",npeaks,nfound,ngood,nghost);
   }
   c1->cd(1);
   hpeaks->Fit("pol1","lq");
   c1->cd(2);
   hfound->Fit("gaus","lq");
   c1->cd(3);
   hgood->Fit("gaus","lq");
   c1->cd(4);
   hghost->Fit("gaus","lq","",0,30);
   c1->cd();
   Double_t p1  = hfound->GetFunction("gaus")->GetParameter(1);
   Double_t ep1 = hfound->GetFunction("gaus")->GetParError(1);
   Double_t p2  = hgood->GetFunction("gaus")->GetParameter(1);
   Double_t ep2 = hgood->GetFunction("gaus")->GetParError(1);
   Double_t p3  = hghost->GetFunction("gaus")->GetParameter(1);
   Double_t ep3 = hghost->GetFunction("gaus")->GetParError(1);
   Double_t p1ref = 70.21; //ref numbers obtained with ntimes=1000
   Double_t p2ref = 65.03;
   Double_t p3ref =  8.54;

   //printf("p1=%g+-%g, p2=%g+-%g, p3=%g+-%g\n",p1,ep1,p2,ep2,p3,ep3);

   char sok[20];
   if (TMath::Abs(p1ref-p1) < 2*ep1 && TMath::Abs(p2ref-p2) < 2*ep2  && TMath::Abs(p3ref-p3) < 2*ep3 ) {
      snprintf(sok,20,"OK");
   } else {
      snprintf(sok,20,"failed");
   }
   printf("Peak1 : found =%6.2f/%6.2f, good =%6.2f/%6.2f, ghost =%5.2f/%5.2f,--- %s\n",
          p1,p1ref,p2,p2ref,p3,p3ref,sok);
}
void stress2(Int_t np2) {
   npeaks = np2;
   TRandom r;
   Int_t nbinsx = 200;
   Int_t nbinsy = 200;
   Double_t xmin   = 0;
   Double_t xmax   = (Double_t)nbinsx;
   Double_t ymin   = 0;
   Double_t ymax   = (Double_t)nbinsy;
   Double_t dx = (xmax-xmin)/nbinsx;
   Double_t dy = (ymax-ymin)/nbinsy;
   TH2F *h2 = new TH2F("h2","test",nbinsx,xmin,xmax,nbinsy,ymin,ymax);
   h2->SetStats(0);
   //generate n peaks at random
   Double_t par[3000];
   Int_t p;
   for (p=0;p<npeaks;p++) {
      par[5*p+0] = r.Uniform(0.2,1);
      par[5*p+1] = r.Uniform(xmin,xmax);
      par[5*p+2] = r.Uniform(dx,5*dx);
      par[5*p+3] = r.Uniform(ymin,ymax);
      par[5*p+4] = r.Uniform(dy,5*dy);
   }
   TF2 *f2 = new TF2("f2",fpeaks2,xmin,xmax,ymin,ymax,5*npeaks);
   f2->SetNpx(100);
   f2->SetNpy(100);
   f2->SetParameters(par);
   h2->FillRandom("f2",500000);
   //now the real stuff
   TSpectrum2 *s = new TSpectrum2(2*npeaks);
   Int_t nfound = s->Search(h2,2,"goff noMarkov");

   //searching good and ghost peaks (approximation)
   Int_t pf,ngood = 0;
   Float_t *xpeaks = s->GetPositionX();
   Float_t *ypeaks = s->GetPositionY();
   for (p=0;p<npeaks;p++) {
      for (Int_t pf=0;pf<nfound;pf++) {
         Double_t diffx = TMath::Abs(xpeaks[pf] - par[5*p+1]);
         Double_t diffy = TMath::Abs(ypeaks[pf] - par[5*p+3]);
         if (diffx < 2*dx && diffy < 2*dy) ngood++;
      }
   }
   if (ngood > nfound) ngood = nfound;
   //Search ghost peaks (approximation)
   Int_t nghost = 0;
   for (pf=0;pf<nfound;pf++) {
      Int_t nf=0;
      for (Int_t p=0;p<npeaks;p++) {
         Double_t diffx = TMath::Abs(xpeaks[pf] - par[5*p+1]);
         Double_t diffy = TMath::Abs(ypeaks[pf] - par[5*p+3]);
         if (diffx < 2*dx && diffy < 2*dy) nf++;
      }
      if (nf == 0) nghost++;
   }

   delete s;
   delete f2;
   delete h2;
   Int_t nfoundRef = 163;
   Int_t ngoodRef  = 163;
   Int_t nghostRef = 8;
   char sok[20];
   if (  TMath::Abs(nfound - nfoundRef) < 5
      && TMath::Abs(ngood - ngoodRef) < 5
      && TMath::Abs(nghost - nghostRef) < 5)  {
      snprintf(sok,20,"OK");
   } else {
      snprintf(sok,20,"failed");
   }
   printf("Peak2 : found =%d/%d, good =%d, ghost =%2d,---------------------------- %s\n",
          nfound,npeaks,ngood,nghost,sok);
}

#ifndef __CINT__
void stressSpectrum(Int_t ntimes) {
#else
void stressSpectrum(Int_t ntimes=100) {
#endif
   std::cout << "****************************************************************************" <<std::endl;
   std::cout << "*  Starting  stress S P E C T R U M                                        *" <<std::endl;
   std::cout << "****************************************************************************" <<std::endl;
   gBenchmark->Start("stressSpectrum");
   stress1(ntimes);
   stress2(300);
   gBenchmark->Stop ("stressSpectrum");
   Double_t reftime100 = 19.04; //pcbrun compiled
   Double_t ct = gBenchmark->GetCpuTime("stressSpectrum");
   const Double_t rootmarks = 800*reftime100*ntimes/(100*ct);
   printf("****************************************************************************\n");

   gBenchmark->Print("stressSpectrum");
   printf("****************************************************************************\n");
   printf("*  ROOTMARKS =%6.1f   *  Root%-8s  %d/%d\n",rootmarks,gROOT->GetVersion(),
         gROOT->GetVersionDate(),gROOT->GetVersionTime());
   printf("****************************************************************************\n");
}

#ifndef __CINT__

int main(int argc, char **argv)
{
   TApplication theApp("App", &argc, argv);
   gROOT->SetBatch();
   gBenchmark = new TBenchmark();
   Int_t ntimes = 100;
   if (argc > 1)  ntimes = atoi(argv[1]);
   stressSpectrum(ntimes);
   return 0;
}

#endif
<commit_msg>GetPositionX() returns Double_t*! (How did this work before?)<commit_after>// @(#)root/test:$name:  $:$id: stressSpectrum.cxx,v 1.15 2002/10/25 10:47:51 rdm exp $
// Author: Rene Brun 17/01/2006

/////////////////////////////////////////////////////////////////
//
//    TSPectrum test suite
//    ====================
//
// This stress program tests many elements of the TSpectrum, TSpectrum2 classes.
//
// To run in batch, do
//   stressSpectrum        : run 100 experiments with graphics (default)
//   stressSpectrum 1000   : run 1000 experiments with graphics
//   stressSpectrum -b 200 : run 200 experiments in batch mode
//   stressSpectrum -b     : run 100 experiments in batch mode
//
// To run interactively, do
// root -b
//  Root > .x stressSpectrum.cxx      : run 100 experiments with graphics (default)
//  Root > .x stressSpectrum.cxx(20)  : run 20 experiments
//  Root > .x stressSpectrum.cxx+(30) : run 30 experiments via ACLIC
//
// Several tests are run sequentially. Each test will produce one line (Test OK or Test FAILED) .
// At the end of the test a table is printed showing the global results
// Real Time and Cpu Time.
// One single number (ROOTMARKS) is also calculated showing the relative
// performance of your machine compared to a reference machine
// a Pentium IV 3.0 Ghz) with 512 MBytes of memory
// and 120 GBytes IDE disk.
//
// An example of output when all the tests run OK is shown below:
//
//////////////////////////////////////////////////////////////////////////
//                                                                      //
//****************************************************************************
//*  Starting  stress S P E C T R U M                                        *
//****************************************************************************
//Peak1 : found = 70.21/ 73.75, good = 65.03/ 68.60, ghost = 8.54/ 8.39,--- OK
//Peak2 : found =163/300, good =163, ghost =8,----------------------------  OK
//****************************************************************************
//stressSpectrum: Real Time =  19.86 seconds Cpu Time =  19.04 seconds
//****************************************************************************
//*  ROOTMARKS = 810.9   *  Root5.09/01   20051216/1229
//****************************************************************************

#include <stdlib.h>
#include "TApplication.h"
#include "TBenchmark.h"
#include "TCanvas.h"
#include "TH2.h"
#include "TF2.h"
#include "TRandom.h"
#include "TSpectrum.h"
#include "TSpectrum2.h"
#include "TStyle.h"
#include "Riostream.h"
#include "TROOT.h"
#include "TMath.h"

Int_t npeaks;
Double_t fpeaks(Double_t *x, Double_t *par) {
   Double_t result = par[0] + par[1]*x[0];
   for (Int_t p=0;p<npeaks;p++) {
      Double_t norm  = par[3*p+2];
      Double_t mean  = par[3*p+3];
      Double_t sigma = par[3*p+4];
      result += norm*TMath::Gaus(x[0],mean,sigma);
   }
   return result;
}
Double_t fpeaks2(Double_t *x, Double_t *par) {
   Double_t result = 0.1;
   for (Int_t p=0;p<npeaks;p++) {
      Double_t norm   = par[5*p+0];
      Double_t mean1  = par[5*p+1];
      Double_t sigma1 = par[5*p+2];
      Double_t mean2  = par[5*p+3];
      Double_t sigma2 = par[5*p+4];
      result += norm*TMath::Gaus(x[0],mean1,sigma1)*TMath::Gaus(x[1],mean2,sigma2);
   }
   return result;
}
void findPeaks(Int_t pmin, Int_t pmax, Int_t &nfound, Int_t &ngood, Int_t &nghost) {
   npeaks = (Int_t)gRandom->Uniform(pmin,pmax);
   Int_t nbins = 500;
   Double_t dxbins = 2;
   TH1F *h = new TH1F("h","test",nbins,0,nbins*dxbins);
   //generate n peaks at random
   Double_t par[3000];
   par[0] = 0.8;
   par[1] = -0.6/1000;
   Int_t p,pf;
   for (p=0;p<npeaks;p++) {
      par[3*p+2] = 1;
      par[3*p+3] = 10+gRandom->Rndm()*(nbins-20)*dxbins;
      par[3*p+4] = 3+2*gRandom->Rndm();
   }
   TF1 *f = new TF1("f",fpeaks,0,nbins*dxbins,2+3*npeaks);
   f->SetNpx(1000);
   f->SetParameters(par);
   h->FillRandom("f",200000);
   TSpectrum *s = new TSpectrum(4*npeaks);
   nfound = s->Search(h,2,"goff");
   //Search found peaks
   ngood = 0;
   Double_t *xpeaks = s->GetPositionX();
   for (p=0;p<npeaks;p++) {
      for (Int_t pf=0;pf<nfound;pf++) {
         Double_t dx = TMath::Abs(xpeaks[pf] - par[3*p+3]);
         if (dx <dxbins) ngood++;
      }
   }
   //Search ghost peaks
   nghost = 0;
   for (pf=0;pf<nfound;pf++) {
      Int_t nf=0;
      for (Int_t p=0;p<npeaks;p++) {
         Double_t dx = TMath::Abs(xpeaks[pf] - par[3*p+3]);
         if (dx <dxbins) nf++;
      }
      if (nf == 0) nghost++;
   }
   delete f;
   delete h;
   delete s;
}

void stress1(Int_t ntimes) {
   Int_t pmin = 5;
   Int_t pmax = 55;
   TCanvas *c1 = new TCanvas("c1","Spectrum results",10,10,800,800);
   c1->Divide(2,2);
   gStyle->SetOptFit();
   TH1F *hpeaks = new TH1F("hpeaks","Number of peaks",pmax-pmin,pmin,pmax);
   TH1F *hfound = new TH1F("hfound","% peak founds",100,0,100);
   TH1F *hgood  = new TH1F("hgood", "% good peaks",100,0,100);
   TH1F *hghost = new TH1F("hghost","% ghost peaks",100,0,100);
   Int_t nfound,ngood,nghost;
   for (Int_t i=0;i<ntimes;i++) {
      findPeaks(pmin,pmax,nfound,ngood,nghost);
      hpeaks->Fill(npeaks);
      hfound->Fill(100*Double_t(nfound)/Double_t(npeaks));
      hgood->Fill(100*Double_t(ngood)/Double_t(npeaks));
      hghost->Fill(100*Double_t(nghost)/Double_t(npeaks));
      //printf("npeaks = %d, nfound = %d, ngood = %d, nghost = %d\n",npeaks,nfound,ngood,nghost);
   }
   c1->cd(1);
   hpeaks->Fit("pol1","lq");
   c1->cd(2);
   hfound->Fit("gaus","lq");
   c1->cd(3);
   hgood->Fit("gaus","lq");
   c1->cd(4);
   hghost->Fit("gaus","lq","",0,30);
   c1->cd();
   Double_t p1  = hfound->GetFunction("gaus")->GetParameter(1);
   Double_t ep1 = hfound->GetFunction("gaus")->GetParError(1);
   Double_t p2  = hgood->GetFunction("gaus")->GetParameter(1);
   Double_t ep2 = hgood->GetFunction("gaus")->GetParError(1);
   Double_t p3  = hghost->GetFunction("gaus")->GetParameter(1);
   Double_t ep3 = hghost->GetFunction("gaus")->GetParError(1);
   Double_t p1ref = 70.21; //ref numbers obtained with ntimes=1000
   Double_t p2ref = 65.03;
   Double_t p3ref =  8.54;

   //printf("p1=%g+-%g, p2=%g+-%g, p3=%g+-%g\n",p1,ep1,p2,ep2,p3,ep3);

   char sok[20];
   if (TMath::Abs(p1ref-p1) < 2*ep1 && TMath::Abs(p2ref-p2) < 2*ep2  && TMath::Abs(p3ref-p3) < 2*ep3 ) {
      snprintf(sok,20,"OK");
   } else {
      snprintf(sok,20,"failed");
   }
   printf("Peak1 : found =%6.2f/%6.2f, good =%6.2f/%6.2f, ghost =%5.2f/%5.2f,--- %s\n",
          p1,p1ref,p2,p2ref,p3,p3ref,sok);
}
void stress2(Int_t np2) {
   npeaks = np2;
   TRandom r;
   Int_t nbinsx = 200;
   Int_t nbinsy = 200;
   Double_t xmin   = 0;
   Double_t xmax   = (Double_t)nbinsx;
   Double_t ymin   = 0;
   Double_t ymax   = (Double_t)nbinsy;
   Double_t dx = (xmax-xmin)/nbinsx;
   Double_t dy = (ymax-ymin)/nbinsy;
   TH2F *h2 = new TH2F("h2","test",nbinsx,xmin,xmax,nbinsy,ymin,ymax);
   h2->SetStats(0);
   //generate n peaks at random
   Double_t par[3000];
   Int_t p;
   for (p=0;p<npeaks;p++) {
      par[5*p+0] = r.Uniform(0.2,1);
      par[5*p+1] = r.Uniform(xmin,xmax);
      par[5*p+2] = r.Uniform(dx,5*dx);
      par[5*p+3] = r.Uniform(ymin,ymax);
      par[5*p+4] = r.Uniform(dy,5*dy);
   }
   TF2 *f2 = new TF2("f2",fpeaks2,xmin,xmax,ymin,ymax,5*npeaks);
   f2->SetNpx(100);
   f2->SetNpy(100);
   f2->SetParameters(par);
   h2->FillRandom("f2",500000);
   //now the real stuff
   TSpectrum2 *s = new TSpectrum2(2*npeaks);
   Int_t nfound = s->Search(h2,2,"goff noMarkov");

   //searching good and ghost peaks (approximation)
   Int_t pf,ngood = 0;
   Double_t *xpeaks = s->GetPositionX();
   Double_t *ypeaks = s->GetPositionY();
   for (p=0;p<npeaks;p++) {
      for (Int_t pf=0;pf<nfound;pf++) {
         Double_t diffx = TMath::Abs(xpeaks[pf] - par[5*p+1]);
         Double_t diffy = TMath::Abs(ypeaks[pf] - par[5*p+3]);
         if (diffx < 2*dx && diffy < 2*dy) ngood++;
      }
   }
   if (ngood > nfound) ngood = nfound;
   //Search ghost peaks (approximation)
   Int_t nghost = 0;
   for (pf=0;pf<nfound;pf++) {
      Int_t nf=0;
      for (Int_t p=0;p<npeaks;p++) {
         Double_t diffx = TMath::Abs(xpeaks[pf] - par[5*p+1]);
         Double_t diffy = TMath::Abs(ypeaks[pf] - par[5*p+3]);
         if (diffx < 2*dx && diffy < 2*dy) nf++;
      }
      if (nf == 0) nghost++;
   }

   delete s;
   delete f2;
   delete h2;
   Int_t nfoundRef = 163;
   Int_t ngoodRef  = 163;
   Int_t nghostRef = 8;
   char sok[20];
   if (  TMath::Abs(nfound - nfoundRef) < 5
      && TMath::Abs(ngood - ngoodRef) < 5
      && TMath::Abs(nghost - nghostRef) < 5)  {
      snprintf(sok,20,"OK");
   } else {
      snprintf(sok,20,"failed");
   }
   printf("Peak2 : found =%d/%d, good =%d, ghost =%2d,---------------------------- %s\n",
          nfound,npeaks,ngood,nghost,sok);
}

#ifndef __CINT__
void stressSpectrum(Int_t ntimes) {
#else
void stressSpectrum(Int_t ntimes=100) {
#endif
   std::cout << "****************************************************************************" <<std::endl;
   std::cout << "*  Starting  stress S P E C T R U M                                        *" <<std::endl;
   std::cout << "****************************************************************************" <<std::endl;
   gBenchmark->Start("stressSpectrum");
   stress1(ntimes);
   stress2(300);
   gBenchmark->Stop ("stressSpectrum");
   Double_t reftime100 = 19.04; //pcbrun compiled
   Double_t ct = gBenchmark->GetCpuTime("stressSpectrum");
   const Double_t rootmarks = 800*reftime100*ntimes/(100*ct);
   printf("****************************************************************************\n");

   gBenchmark->Print("stressSpectrum");
   printf("****************************************************************************\n");
   printf("*  ROOTMARKS =%6.1f   *  Root%-8s  %d/%d\n",rootmarks,gROOT->GetVersion(),
         gROOT->GetVersionDate(),gROOT->GetVersionTime());
   printf("****************************************************************************\n");
}

#ifndef __CINT__

int main(int argc, char **argv)
{
   TApplication theApp("App", &argc, argv);
   gROOT->SetBatch();
   gBenchmark = new TBenchmark();
   Int_t ntimes = 100;
   if (argc > 1)  ntimes = atoi(argv[1]);
   stressSpectrum(ntimes);
   return 0;
}

#endif
<|endoftext|>


<commit_before>//===-- BypassSlowDivision.cpp - Bypass slow division ---------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains an optimization for div and rem on architectures that
// execute short instructions significantly faster than longer instructions.
// For example, on Intel Atom 32-bit divides are slow enough that during
// runtime it is profitable to check the value of the operands, and if they are
// positive and less than 256 use an unsigned 8-bit divide.
//
//===----------------------------------------------------------------------===//

#include "llvm/Transforms/Utils/BypassSlowDivision.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/Instructions.h"
#include "llvm/Transforms/Utils/Local.h"

using namespace llvm;

#define DEBUG_TYPE "bypass-slow-division"

namespace {
  struct DivOpInfo {
    bool SignedOp;
    Value *Dividend;
    Value *Divisor;

    DivOpInfo(bool InSignedOp, Value *InDividend, Value *InDivisor)
      : SignedOp(InSignedOp), Dividend(InDividend), Divisor(InDivisor) {}
  };

  struct DivPhiNodes {
    PHINode *Quotient;
    PHINode *Remainder;

    DivPhiNodes(PHINode *InQuotient, PHINode *InRemainder)
      : Quotient(InQuotient), Remainder(InRemainder) {}
  };
}

namespace llvm {
  template<>
  struct DenseMapInfo<DivOpInfo> {
    static bool isEqual(const DivOpInfo &Val1, const DivOpInfo &Val2) {
      return Val1.SignedOp == Val2.SignedOp &&
             Val1.Dividend == Val2.Dividend &&
             Val1.Divisor == Val2.Divisor;
    }

    static DivOpInfo getEmptyKey() {
      return DivOpInfo(false, nullptr, nullptr);
    }

    static DivOpInfo getTombstoneKey() {
      return DivOpInfo(true, nullptr, nullptr);
    }

    static unsigned getHashValue(const DivOpInfo &Val) {
      return (unsigned)(reinterpret_cast<uintptr_t>(Val.Dividend) ^
                        reinterpret_cast<uintptr_t>(Val.Divisor)) ^
                        (unsigned)Val.SignedOp;
    }
  };

  typedef DenseMap<DivOpInfo, DivPhiNodes> DivCacheTy;
}

// insertFastDiv - Substitutes the div/rem instruction with code that checks the
// value of the operands and uses a shorter-faster div/rem instruction when
// possible and the longer-slower div/rem instruction otherwise.
static bool insertFastDiv(Instruction *I, IntegerType *BypassType,
                          bool UseDivOp, bool UseSignedOp,
                          DivCacheTy &PerBBDivCache) {
  Function *F = I->getParent()->getParent();
  // Get instruction operands
  Value *Dividend = I->getOperand(0);
  Value *Divisor = I->getOperand(1);

  if (isa<ConstantInt>(Divisor)) {
    // Division by a constant should have been been solved and replaced earlier
    // in the pipeline.
    return false;
  }

  // If the numerator is a constant, bail if it doesn't fit into BypassType.
  if (ConstantInt *ConstDividend = dyn_cast<ConstantInt>(Dividend))
    if (ConstDividend->getValue().getActiveBits() > BypassType->getBitWidth())
      return false;

  // Basic Block is split before divide
  BasicBlock *MainBB = &*I->getParent();
  BasicBlock *SuccessorBB = MainBB->splitBasicBlock(I);

  // Add new basic block for slow divide operation
  BasicBlock *SlowBB =
      BasicBlock::Create(F->getContext(), "", MainBB->getParent(), SuccessorBB);
  SlowBB->moveBefore(SuccessorBB);
  IRBuilder<> SlowBuilder(SlowBB, SlowBB->begin());
  Value *SlowQuotientV;
  Value *SlowRemainderV;
  if (UseSignedOp) {
    SlowQuotientV = SlowBuilder.CreateSDiv(Dividend, Divisor);
    SlowRemainderV = SlowBuilder.CreateSRem(Dividend, Divisor);
  } else {
    SlowQuotientV = SlowBuilder.CreateUDiv(Dividend, Divisor);
    SlowRemainderV = SlowBuilder.CreateURem(Dividend, Divisor);
  }
  SlowBuilder.CreateBr(SuccessorBB);

  // Add new basic block for fast divide operation
  BasicBlock *FastBB =
      BasicBlock::Create(F->getContext(), "", MainBB->getParent(), SuccessorBB);
  FastBB->moveBefore(SlowBB);
  IRBuilder<> FastBuilder(FastBB, FastBB->begin());
  Value *ShortDivisorV = FastBuilder.CreateCast(Instruction::Trunc, Divisor,
                                                BypassType);
  Value *ShortDividendV = FastBuilder.CreateCast(Instruction::Trunc, Dividend,
                                                 BypassType);

  // udiv/urem because optimization only handles positive numbers
  Value *ShortQuotientV = FastBuilder.CreateUDiv(ShortDividendV, ShortDivisorV);
  Value *ShortRemainderV = FastBuilder.CreateURem(ShortDividendV,
                                                  ShortDivisorV);
  Value *FastQuotientV = FastBuilder.CreateCast(Instruction::ZExt,
                                                ShortQuotientV,
                                                Dividend->getType());
  Value *FastRemainderV = FastBuilder.CreateCast(Instruction::ZExt,
                                                 ShortRemainderV,
                                                 Dividend->getType());
  FastBuilder.CreateBr(SuccessorBB);

  // Phi nodes for result of div and rem
  IRBuilder<> SuccessorBuilder(SuccessorBB, SuccessorBB->begin());
  PHINode *QuoPhi = SuccessorBuilder.CreatePHI(I->getType(), 2);
  QuoPhi->addIncoming(SlowQuotientV, SlowBB);
  QuoPhi->addIncoming(FastQuotientV, FastBB);
  PHINode *RemPhi = SuccessorBuilder.CreatePHI(I->getType(), 2);
  RemPhi->addIncoming(SlowRemainderV, SlowBB);
  RemPhi->addIncoming(FastRemainderV, FastBB);

  // Replace I with appropriate phi node
  if (UseDivOp)
    I->replaceAllUsesWith(QuoPhi);
  else
    I->replaceAllUsesWith(RemPhi);
  I->eraseFromParent();

  // Combine operands into a single value with OR for value testing below
  MainBB->getInstList().back().eraseFromParent();
  IRBuilder<> MainBuilder(MainBB, MainBB->end());

  // We should have bailed out above if the divisor is a constant, but the
  // dividend may still be a constant.  Set OrV to our non-constant operands
  // OR'ed together.
  assert(!isa<ConstantInt>(Divisor));

  Value *OrV;
  if (!isa<ConstantInt>(Dividend))
    OrV = MainBuilder.CreateOr(Dividend, Divisor);
  else
    OrV = Divisor;

  // BitMask is inverted to check if the operands are
  // larger than the bypass type
  uint64_t BitMask = ~BypassType->getBitMask();
  Value *AndV = MainBuilder.CreateAnd(OrV, BitMask);

  // Compare operand values and branch
  Value *ZeroV = ConstantInt::getSigned(Dividend->getType(), 0);
  Value *CmpV = MainBuilder.CreateICmpEQ(AndV, ZeroV);
  MainBuilder.CreateCondBr(CmpV, FastBB, SlowBB);

  // Cache phi nodes to be used later in place of other instances
  // of div or rem with the same sign, dividend, and divisor
  DivOpInfo Key(UseSignedOp, Dividend, Divisor);
  DivPhiNodes Value(QuoPhi, RemPhi);
  PerBBDivCache.insert(std::pair<DivOpInfo, DivPhiNodes>(Key, Value));
  return true;
}

// reuseOrInsertFastDiv - Reuses previously computed dividend or remainder from
// the current BB if operands and operation are identical. Otherwise calls
// insertFastDiv to perform the optimization and caches the resulting dividend
// and remainder.
static bool reuseOrInsertFastDiv(Instruction *I, IntegerType *BypassType,
                                 bool UseDivOp, bool UseSignedOp,
                                 DivCacheTy &PerBBDivCache) {
  // Get instruction operands
  DivOpInfo Key(UseSignedOp, I->getOperand(0), I->getOperand(1));
  DivCacheTy::iterator CacheI = PerBBDivCache.find(Key);

  if (CacheI == PerBBDivCache.end()) {
    // If previous instance does not exist, insert fast div
    return insertFastDiv(I, BypassType, UseDivOp, UseSignedOp, PerBBDivCache);
  }

  // Replace operation value with previously generated phi node
  DivPhiNodes &Value = CacheI->second;
  if (UseDivOp) {
    // Replace all uses of div instruction with quotient phi node
    I->replaceAllUsesWith(Value.Quotient);
  } else {
    // Replace all uses of rem instruction with remainder phi node
    I->replaceAllUsesWith(Value.Remainder);
  }

  // Remove redundant operation
  I->eraseFromParent();
  return true;
}

// bypassSlowDivision - This optimization identifies DIV instructions in a BB
// that can be profitably bypassed and carried out with a shorter, faster
// divide.
bool llvm::bypassSlowDivision(
    BasicBlock *BB, const DenseMap<unsigned int, unsigned int> &BypassWidths) {
  DivCacheTy DivCache;

  bool MadeChange = false;
  Instruction* Next = &*BB->begin();
  while (Next != nullptr) {
    // We may add instructions immediately after I, but we want to skip over
    // them.
    Instruction* I = Next;
    Next = Next->getNextNode();

    // Get instruction details
    unsigned Opcode = I->getOpcode();
    bool UseDivOp = Opcode == Instruction::SDiv || Opcode == Instruction::UDiv;
    bool UseRemOp = Opcode == Instruction::SRem || Opcode == Instruction::URem;
    bool UseSignedOp = Opcode == Instruction::SDiv ||
                       Opcode == Instruction::SRem;

    // Only optimize div or rem ops
    if (!UseDivOp && !UseRemOp)
      continue;

    // Skip division on vector types, only optimize integer instructions
    if (!I->getType()->isIntegerTy())
      continue;

    // Get bitwidth of div/rem instruction
    IntegerType *T = cast<IntegerType>(I->getType());
    unsigned int bitwidth = T->getBitWidth();

    // Continue if bitwidth is not bypassed
    DenseMap<unsigned int, unsigned int>::const_iterator BI = BypassWidths.find(bitwidth);
    if (BI == BypassWidths.end())
      continue;

    // Get type for div/rem instruction with bypass bitwidth
    IntegerType *BT = IntegerType::get(I->getContext(), BI->second);

    MadeChange |= reuseOrInsertFastDiv(I, BT, UseDivOp, UseSignedOp, DivCache);
  }

  // Above we eagerly create divs and rems, as pairs, so that we can efficiently
  // create divrem machine instructions.  Now erase any unused divs / rems so we
  // don't leave extra instructions sitting around.
  for (auto &KV : DivCache)
    for (Instruction *Phi : {KV.second.Quotient, KV.second.Remainder})
      RecursivelyDeleteTriviallyDeadInstructions(Phi);

  return MadeChange;
}
<commit_msg>[BypassSlowDivision] Refactor fast division insertion logic (NFC)<commit_after>//===-- BypassSlowDivision.cpp - Bypass slow division ---------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains an optimization for div and rem on architectures that
// execute short instructions significantly faster than longer instructions.
// For example, on Intel Atom 32-bit divides are slow enough that during
// runtime it is profitable to check the value of the operands, and if they are
// positive and less than 256 use an unsigned 8-bit divide.
//
//===----------------------------------------------------------------------===//

#include "llvm/Transforms/Utils/BypassSlowDivision.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/Instructions.h"
#include "llvm/Transforms/Utils/Local.h"

using namespace llvm;

#define DEBUG_TYPE "bypass-slow-division"

namespace {
  struct DivOpInfo {
    bool SignedOp;
    Value *Dividend;
    Value *Divisor;

    DivOpInfo(bool InSignedOp, Value *InDividend, Value *InDivisor)
      : SignedOp(InSignedOp), Dividend(InDividend), Divisor(InDivisor) {}
  };

  struct QuotRemPair {
    Value *Quotient;
    Value *Remainder;

    QuotRemPair(Value *InQuotient, Value *InRemainder)
        : Quotient(InQuotient), Remainder(InRemainder) {}
  };

  /// A quotient and remainder, plus a BB from which they logically "originate".
  /// If you use Quotient or Remainder in a Phi node, you should use BB as its
  /// corresponding predecessor.
  struct QuotRemWithBB {
    BasicBlock *BB = nullptr;
    Value *Quotient = nullptr;
    Value *Remainder = nullptr;
  };
}

namespace llvm {
  template<>
  struct DenseMapInfo<DivOpInfo> {
    static bool isEqual(const DivOpInfo &Val1, const DivOpInfo &Val2) {
      return Val1.SignedOp == Val2.SignedOp &&
             Val1.Dividend == Val2.Dividend &&
             Val1.Divisor == Val2.Divisor;
    }

    static DivOpInfo getEmptyKey() {
      return DivOpInfo(false, nullptr, nullptr);
    }

    static DivOpInfo getTombstoneKey() {
      return DivOpInfo(true, nullptr, nullptr);
    }

    static unsigned getHashValue(const DivOpInfo &Val) {
      return (unsigned)(reinterpret_cast<uintptr_t>(Val.Dividend) ^
                        reinterpret_cast<uintptr_t>(Val.Divisor)) ^
                        (unsigned)Val.SignedOp;
    }
  };

  typedef DenseMap<DivOpInfo, QuotRemPair> DivCacheTy;
  typedef DenseMap<unsigned, unsigned> BypassWidthsTy;
}

namespace {
class FastDivInsertionTask {
  bool IsValidTask = false;
  Instruction *SlowDivOrRem = nullptr;
  IntegerType *BypassType = nullptr;
  BasicBlock *MainBB = nullptr;

  QuotRemWithBB createSlowBB(BasicBlock *Successor);
  QuotRemWithBB createFastBB(BasicBlock *Successor);
  QuotRemPair createDivRemPhiNodes(QuotRemWithBB &LHS, QuotRemWithBB &RHS,
                                   BasicBlock *PhiBB);
  Value *insertOperandRuntimeCheck();
  Optional<QuotRemPair> insertFastDivAndRem();

  bool isSignedOp() {
    return SlowDivOrRem->getOpcode() == Instruction::SDiv ||
           SlowDivOrRem->getOpcode() == Instruction::SRem;
  }
  bool isDivisionOp() {
    return SlowDivOrRem->getOpcode() == Instruction::SDiv ||
           SlowDivOrRem->getOpcode() == Instruction::UDiv;
  }
  Type *getSlowType() { return SlowDivOrRem->getType(); }

public:
  FastDivInsertionTask(Instruction *I, const BypassWidthsTy &BypassWidths);
  Value *getReplacement(DivCacheTy &Cache);
};
} // anonymous namespace

FastDivInsertionTask::FastDivInsertionTask(Instruction *I,
                                           const BypassWidthsTy &BypassWidths) {
  switch (I->getOpcode()) {
  case Instruction::UDiv:
  case Instruction::SDiv:
  case Instruction::URem:
  case Instruction::SRem:
    SlowDivOrRem = I;
    break;
  default:
    // I is not a div/rem operation.
    return;
  }

  // Skip division on vector types. Only optimize integer instructions.
  IntegerType *SlowType = dyn_cast<IntegerType>(SlowDivOrRem->getType());
  if (!SlowType)
    return;

  // Skip if this bitwidth is not bypassed.
  auto BI = BypassWidths.find(SlowType->getBitWidth());
  if (BI == BypassWidths.end())
    return;

  // Get type for div/rem instruction with bypass bitwidth.
  IntegerType *BT = IntegerType::get(I->getContext(), BI->second);
  BypassType = BT;

  // The original basic block.
  MainBB = I->getParent();

  // The instruction is indeed a slow div or rem operation.
  IsValidTask = true;
}

/// Reuses previously-computed dividend or remainder from the current BB if
/// operands and operation are identical. Otherwise calls insertFastDivAndRem to
/// perform the optimization and caches the resulting dividend and remainder.
/// If no replacement can be generated, nullptr is returned.
Value *FastDivInsertionTask::getReplacement(DivCacheTy &Cache) {
  // First, make sure that the task is valid.
  if (!IsValidTask)
    return nullptr;

  // Then, look for a value in Cache.
  Value *Dividend = SlowDivOrRem->getOperand(0);
  Value *Divisor = SlowDivOrRem->getOperand(1);
  DivOpInfo Key(isSignedOp(), Dividend, Divisor);
  auto CacheI = Cache.find(Key);

  if (CacheI == Cache.end()) {
    // If previous instance does not exist, try to insert fast div.
    Optional<QuotRemPair> OptResult = insertFastDivAndRem();
    // Bail out if insertFastDivAndRem has failed.
    if (!OptResult)
      return nullptr;
    CacheI = Cache.insert({Key, *OptResult}).first;
  }

  QuotRemPair &Value = CacheI->second;
  return isDivisionOp() ? Value.Quotient : Value.Remainder;
}

/// Add new basic block for slow div and rem operations and put it before
/// SuccessorBB.
QuotRemWithBB FastDivInsertionTask::createSlowBB(BasicBlock *SuccessorBB) {
  QuotRemWithBB DivRemPair;
  DivRemPair.BB = BasicBlock::Create(MainBB->getParent()->getContext(), "",
                                     MainBB->getParent(), SuccessorBB);
  IRBuilder<> Builder(DivRemPair.BB, DivRemPair.BB->begin());

  Value *Dividend = SlowDivOrRem->getOperand(0);
  Value *Divisor = SlowDivOrRem->getOperand(1);

  if (isSignedOp()) {
    DivRemPair.Quotient = Builder.CreateSDiv(Dividend, Divisor);
    DivRemPair.Remainder = Builder.CreateSRem(Dividend, Divisor);
  } else {
    DivRemPair.Quotient = Builder.CreateUDiv(Dividend, Divisor);
    DivRemPair.Remainder = Builder.CreateURem(Dividend, Divisor);
  }

  Builder.CreateBr(SuccessorBB);
  return DivRemPair;
}

/// Add new basic block for fast div and rem operations and put it before
/// SuccessorBB.
QuotRemWithBB FastDivInsertionTask::createFastBB(BasicBlock *SuccessorBB) {
  QuotRemWithBB DivRemPair;
  DivRemPair.BB = BasicBlock::Create(MainBB->getParent()->getContext(), "",
                                     MainBB->getParent(), SuccessorBB);
  IRBuilder<> Builder(DivRemPair.BB, DivRemPair.BB->begin());

  Value *Dividend = SlowDivOrRem->getOperand(0);
  Value *Divisor = SlowDivOrRem->getOperand(1);
  Value *ShortDivisorV =
      Builder.CreateCast(Instruction::Trunc, Divisor, BypassType);
  Value *ShortDividendV =
      Builder.CreateCast(Instruction::Trunc, Dividend, BypassType);

  // udiv/urem because this optimization only handles positive numbers.
  Value *ShortQV = Builder.CreateUDiv(ShortDividendV, ShortDivisorV);
  Value *ShortRV = Builder.CreateURem(ShortDividendV, ShortDivisorV);
  DivRemPair.Quotient =
      Builder.CreateCast(Instruction::ZExt, ShortQV, getSlowType());
  DivRemPair.Remainder =
      Builder.CreateCast(Instruction::ZExt, ShortRV, getSlowType());
  Builder.CreateBr(SuccessorBB);

  return DivRemPair;
}

/// Creates Phi nodes for result of Div and Rem.
QuotRemPair FastDivInsertionTask::createDivRemPhiNodes(QuotRemWithBB &LHS,
                                                       QuotRemWithBB &RHS,
                                                       BasicBlock *PhiBB) {
  IRBuilder<> Builder(PhiBB, PhiBB->begin());
  PHINode *QuoPhi = Builder.CreatePHI(getSlowType(), 2);
  QuoPhi->addIncoming(LHS.Quotient, LHS.BB);
  QuoPhi->addIncoming(RHS.Quotient, RHS.BB);
  PHINode *RemPhi = Builder.CreatePHI(getSlowType(), 2);
  RemPhi->addIncoming(LHS.Remainder, LHS.BB);
  RemPhi->addIncoming(RHS.Remainder, RHS.BB);
  return QuotRemPair(QuoPhi, RemPhi);
}

/// Creates a runtime check to test whether both the divisor and dividend fit
/// into BypassType. The check is inserted at the end of MainBB. True return
/// value means that the operands fit.
Value *FastDivInsertionTask::insertOperandRuntimeCheck() {
  IRBuilder<> Builder(MainBB, MainBB->end());
  Value *Dividend = SlowDivOrRem->getOperand(0);
  Value *Divisor = SlowDivOrRem->getOperand(1);

  // We should have bailed out above if the divisor is a constant, but the
  // dividend may still be a constant.  Set OrV to our non-constant operands
  // OR'ed together.
  assert(!isa<ConstantInt>(Divisor));

  Value *OrV;
  if (!isa<ConstantInt>(Dividend))
    OrV = Builder.CreateOr(Dividend, Divisor);
  else
    OrV = Divisor;

  // BitMask is inverted to check if the operands are
  // larger than the bypass type
  uint64_t BitMask = ~BypassType->getBitMask();
  Value *AndV = Builder.CreateAnd(OrV, BitMask);

  // Compare operand values
  Value *ZeroV = ConstantInt::getSigned(getSlowType(), 0);
  return Builder.CreateICmpEQ(AndV, ZeroV);
}

/// Substitutes the div/rem instruction with code that checks the value of the
/// operands and uses a shorter-faster div/rem instruction when possible.
Optional<QuotRemPair> FastDivInsertionTask::insertFastDivAndRem() {
  Value *Dividend = SlowDivOrRem->getOperand(0);
  Value *Divisor = SlowDivOrRem->getOperand(1);

  if (isa<ConstantInt>(Divisor)) {
    // Keep division by a constant for DAGCombiner.
    return None;
  }

  // If the numerator is a constant, bail if it doesn't fit into BypassType.
  if (ConstantInt *ConstDividend = dyn_cast<ConstantInt>(Dividend))
    if (ConstDividend->getValue().getActiveBits() > BypassType->getBitWidth())
      return None;

  // Split the basic block before the div/rem.
  BasicBlock *SuccessorBB = MainBB->splitBasicBlock(SlowDivOrRem);
  // Remove the unconditional branch from MainBB to SuccessorBB.
  MainBB->getInstList().back().eraseFromParent();
  QuotRemWithBB Fast = createFastBB(SuccessorBB);
  QuotRemWithBB Slow = createSlowBB(SuccessorBB);
  QuotRemPair Result = createDivRemPhiNodes(Fast, Slow, SuccessorBB);
  Value *CmpV = insertOperandRuntimeCheck();
  IRBuilder<> Builder(MainBB, MainBB->end());
  Builder.CreateCondBr(CmpV, Fast.BB, Slow.BB);
  return Result;
}

/// This optimization identifies DIV/REM instructions in a BB that can be
/// profitably bypassed and carried out with a shorter, faster divide.
bool llvm::bypassSlowDivision(BasicBlock *BB,
                              const BypassWidthsTy &BypassWidths) {
  DivCacheTy PerBBDivCache;

  bool MadeChange = false;
  Instruction* Next = &*BB->begin();
  while (Next != nullptr) {
    // We may add instructions immediately after I, but we want to skip over
    // them.
    Instruction* I = Next;
    Next = Next->getNextNode();

    FastDivInsertionTask Task(I, BypassWidths);
    if (Value *Replacement = Task.getReplacement(PerBBDivCache)) {
      I->replaceAllUsesWith(Replacement);
      I->eraseFromParent();
      MadeChange = true;
    }
  }

  // Above we eagerly create divs and rems, as pairs, so that we can efficiently
  // create divrem machine instructions.  Now erase any unused divs / rems so we
  // don't leave extra instructions sitting around.
  for (auto &KV : PerBBDivCache)
    for (Value *V : {KV.second.Quotient, KV.second.Remainder})
      RecursivelyDeleteTriviallyDeadInstructions(V);

  return MadeChange;
}
<|endoftext|>


<commit_before>//==- CheckSizeofPointer.cpp - Check for sizeof on pointers ------*- C++ -*-==//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This file defines a check for unintended use of sizeof() on pointer
//  expressions.
//
//===----------------------------------------------------------------------===//

#include "clang/Analysis/PathSensitive/BugReporter.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/Analysis/LocalCheckers.h"
#include "llvm/Support/Compiler.h"

using namespace clang;

namespace {
class VISIBILITY_HIDDEN WalkAST : public StmtVisitor<WalkAST> {
  BugReporter &BR;

public:
  WalkAST(BugReporter &br) : BR(br) {}
  void VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E);
  void VisitStmt(Stmt *S) { VisitChildren(S); }
  void VisitChildren(Stmt *S);
};
}

void WalkAST::VisitChildren(Stmt *S) {
  for (Stmt::child_iterator I = S->child_begin(), E = S->child_end(); I!=E; ++I)
    if (Stmt *child = *I)
      Visit(child);
}

// CWE-467: Use of sizeof() on a Pointer Type
void WalkAST::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) {
  if (!E->isSizeOf())
    return;

  // If an explicit type is used in the code, usually the coder knows what he is
  // doing.
  if (E->isArgumentType())
    return;

  QualType T = E->getTypeOfArgument();
  if (T->isPointerType()) {
    SourceRange R = E->getSourceRange();
    BR.EmitBasicReport("Potential unintended use of sizeof() on pointer type",
                       "Logic",
                       "The code calls sizeof() on a pointer type. "
                       "This can produce an unexpected result.",
                       E->getLocStart(), &R, 1);
  }
}

void clang::CheckSizeofPointer(const Decl *D, BugReporter &BR) {
  WalkAST walker(BR);
  walker.Visit(D->getBody());
}
<commit_msg>Now we can safely use the argument expression's source range.<commit_after>//==- CheckSizeofPointer.cpp - Check for sizeof on pointers ------*- C++ -*-==//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This file defines a check for unintended use of sizeof() on pointer
//  expressions.
//
//===----------------------------------------------------------------------===//

#include "clang/Analysis/PathSensitive/BugReporter.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/Analysis/LocalCheckers.h"
#include "llvm/Support/Compiler.h"

using namespace clang;

namespace {
class VISIBILITY_HIDDEN WalkAST : public StmtVisitor<WalkAST> {
  BugReporter &BR;

public:
  WalkAST(BugReporter &br) : BR(br) {}
  void VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E);
  void VisitStmt(Stmt *S) { VisitChildren(S); }
  void VisitChildren(Stmt *S);
};
}

void WalkAST::VisitChildren(Stmt *S) {
  for (Stmt::child_iterator I = S->child_begin(), E = S->child_end(); I!=E; ++I)
    if (Stmt *child = *I)
      Visit(child);
}

// CWE-467: Use of sizeof() on a Pointer Type
void WalkAST::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) {
  if (!E->isSizeOf())
    return;

  // If an explicit type is used in the code, usually the coder knows what he is
  // doing.
  if (E->isArgumentType())
    return;

  QualType T = E->getTypeOfArgument();
  if (T->isPointerType()) {
    SourceRange R = E->getArgumentExpr()->getSourceRange();
    BR.EmitBasicReport("Potential unintended use of sizeof() on pointer type",
                       "Logic",
                       "The code calls sizeof() on a pointer type. "
                       "This can produce an unexpected result.",
                       E->getLocStart(), &R, 1);
  }
}

void clang::CheckSizeofPointer(const Decl *D, BugReporter &BR) {
  WalkAST walker(BR);
  walker.Visit(D->getBody());
}
<|endoftext|>


<commit_before>//
//  array.hpp
//  DS
//
//  Created by Rahul Goel on 7/26/17.
//  Copyright © 2017 Rahul Goel. All rights reserved.
//

#ifndef array_hpp
#define array_hpp

#include <stdio.h>

//1. To Left - Rotate given array of size n by d elements With Different methods - O(n) Time
void array_rotateLeftBydElements(int arr[],int size,int d);

//2. To cyclically Right- Rotate given array arr by one-element with size n - O(n) Time
void array_rotateCyclicallyby1(int arr[],int size);

//3. Search an element d in a sorted and rotated array arr with size n - O(log(n)) Time
void array_searchInSortedAndRotatedarray(int arr[],int size, int d);

//4. To print all elements in given array
void array_printelements(int arr[],int size);

#endif /* array_hpp */
<commit_msg>array new programs added<commit_after>//
//  array.hpp
//  DS
//
//  Created by Rahul Goel on 7/26/17.
//  Copyright © 2017 Rahul Goel. All rights reserved.
//

#ifndef array_hpp
#define array_hpp

#include <stdio.h>

//1. To Left - Rotate given array of size n by d elements With Different methods - O(n) Time
void array_rotateLeftBydElements(int arr[],int size,int d);

//2. To cyclically Right- Rotate given array arr by one-element with size n - O(n) Time
void array_rotateCyclicallyby1(int arr[],int size);

//3. Search an element d in a sorted and rotated array arr with size n - O(log(n)) Time
void array_searchInSortedAndRotatedarray(int arr[],int size, int d);

//4. To print all elements in given array - Time - O(n)
void array_printelements(int arr[],int size);

//5.  Equilibrium point : In given array arr find position on which sum of all the left elements are equal to all the right elements if exists, if not return -1 Time - O(n)
int array_equilibriumpoint(int arr[], int n);

//6. Missing number in given array - If array contain elements from 1 t0 n-1 expect one number missing Time - O(n)
int array_missingnumber(int arr[], int n);

//7. Kadane's algorithm : For given array arr (with +ve and -ve values) find contiguous sub-array with max sum.

//8. Find contiguous sub array which adds to given number. (Array contains only positive numbers)

//9. Find contiguous sub array which adds to given number. (Array may contain negative numbers as well)

//10. Program to sort the given array with only 0,1,2 in ascending order. Or (Dutch National Flag Problem)

//11. Leaders in Array : an element is leader if it is greater than all elements to its right side. Rightmost element in array is always leader. Time O(n)
void array_leaderis(int arr[], int n);

//12. kth smallest element in given array of size n where k<n and all elements are distinct.
void array_kthSmallestElement(int arr[],int n);

//13. Find element that appears once in array whereas every other element occur thrice.
int array_appearOnce(int arr[],int n);

#endif /* array_hpp */
<|endoftext|>