Procházet zdrojové kódy

removed Var iterators, fixed SOO alignment

- removed unnecessary using directives in Data library
- removed iterator pointers from Var (reduce size, always return copy)
- added Alignment header (adapted from LLVM infrastructure)
- added alignment guards to SOO implementations
Aleksandar Fabijanic před 12 roky
rodič
revize
e5eaffb790

+ 2 - 0
CHANGELOG

@@ -68,6 +68,8 @@ Release 1.5.2 (2013-06-xx)
 - added JSON conversion to Dynamic Struct and Array
 - added VarIterator
 - modified behavior of empty Var (empty == empty)
+- added Alignment.h header for C++03 alignment needs
+
 
 Release 1.5.1 (2013-01-11)
 ==========================

+ 0 - 1
Data/include/Poco/Data/LOB.h

@@ -222,7 +222,6 @@ inline void swap(LOB<T>& b1, LOB<T>& b2)
 
 namespace std
 {
-	using std::swap;
 	template<>
 	inline void swap<Poco::Data::BLOB>(Poco::Data::BLOB& b1, 
 		Poco::Data::BLOB& b2)

+ 0 - 1
Data/include/Poco/Data/RowIterator.h

@@ -159,7 +159,6 @@ inline bool RowIterator::operator != (const RowIterator& other) const
 
 namespace std
 {
-	using std::swap;
 	template<>
 	inline void swap<Poco::Data::RowIterator>(Poco::Data::RowIterator& s1, 
 		Poco::Data::RowIterator& s2)

+ 0 - 1
Data/include/Poco/Data/Session.h

@@ -503,7 +503,6 @@ inline void swap(Session& s1, Session& s2)
 
 namespace std
 {
-	using std::swap;
 	template<>
 	inline void swap<Poco::Data::Session>(Poco::Data::Session& s1, 
 		Poco::Data::Session& s2)

+ 0 - 1
Data/include/Poco/Data/Statement.h

@@ -820,7 +820,6 @@ inline void swap(Statement& s1, Statement& s2)
 
 namespace std
 {
-	using std::swap;
 	template<>
 	inline void swap<Poco::Data::Statement>(Poco::Data::Statement& s1, 
 		Poco::Data::Statement& s2)

+ 1 - 0
Foundation/Foundation_vs110.vcxproj

@@ -983,6 +983,7 @@
     <ClCompile Include="src\HashStatistic.cpp" />
   </ItemGroup>
   <ItemGroup>
+    <ClInclude Include="include\Poco\Alignment.h" />
     <ClInclude Include="include\Poco\Any.h" />
     <ClInclude Include="include\Poco\Array.h" />
     <ClInclude Include="include\Poco\Ascii.h" />

+ 3 - 0
Foundation/Foundation_vs110.vcxproj.filters

@@ -1883,6 +1883,9 @@
     <ClInclude Include="include\Poco\Optional.h">
       <Filter>Core\Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="include\Poco\Alignment.h">
+      <Filter>Core\Header Files</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ResourceCompile Include="src\pocomsg.rc">

+ 230 - 0
Foundation/include/Poco/Alignment.h

@@ -0,0 +1,230 @@
+//
+// Alignment.h
+//
+// $Id: //poco/svn/Foundation/include/Poco/Alignment.h#2 $
+//
+// Library: Foundation
+// Package: Dynamic
+// Module:  Alignment
+//
+// Definition of the Alignment class.
+//
+// Copyright (c) 2007, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// Permission is hereby granted, free of charge, to any person or organization
+// obtaining a copy of the software and accompanying documentation covered by
+// this license (the "Software") to use, reproduce, display, distribute,
+// execute, and transmit the Software, and to prepare derivative works of the
+// Software, and to permit third-parties to whom the Software is furnished to
+// do so, all subject to the following:
+// 
+// The copyright notices in the Software and this entire statement, including
+// the above license grant, this restriction and the following disclaimer,
+// must be included in all copies of the Software, in whole or in part, and
+// all derivative works of the Software, unless such copies or derivative
+// works are solely in the form of machine-executable object code generated by
+// a source language processor.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+//
+
+
+// Adapted for POCO from LLVM Compiler Infrastructure code:
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source License
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the AlignOf function that computes alignments for
+// arbitrary types.
+//
+//===----------------------------------------------------------------------===//
+
+
+#ifndef Foundation_AlignOf_INCLUDED
+#define Foundation_AlignOf_INCLUDED
+
+
+namespace Poco {
+
+
+template <typename T>
+struct AlignmentCalcImpl
+{
+	char x;
+	T t;
+private:
+	AlignmentCalcImpl() {} // Never instantiate.
+};
+
+
+template <typename T>
+struct AlignOf
+	/// A templated class that contains an enum value representing
+	/// the alignment of the template argument.  For example,
+	/// AlignOf<int>::Alignment represents the alignment of type "int".  The
+	/// alignment calculated is the minimum alignment, and not necessarily
+	/// the "desired" alignment returned by GCC's __alignof__ (for example).  Note
+	/// that because the alignment is an enum value, it can be used as a
+	/// compile-time constant (e.g., for template instantiation).
+{
+	enum
+	{
+		Alignment = static_cast<unsigned int>(sizeof(AlignmentCalcImpl<T>) - sizeof(T))
+	};
+
+	enum { Alignment_GreaterEqual_2Bytes  = Alignment >= 2  ? 1 : 0 };
+	enum { Alignment_GreaterEqual_4Bytes  = Alignment >= 4  ? 1 : 0 };
+	enum { Alignment_GreaterEqual_8Bytes  = Alignment >= 8  ? 1 : 0 };
+	enum { Alignment_GreaterEqual_16Bytes = Alignment >= 16 ? 1 : 0 };
+	
+	enum { Alignment_LessEqual_2Bytes  = Alignment <= 2  ? 1 : 0 };
+	enum { Alignment_LessEqual_4Bytes  = Alignment <= 4  ? 1 : 0 };
+	enum { Alignment_LessEqual_8Bytes  = Alignment <= 8  ? 1 : 0 };
+	enum { Alignment_LessEqual_16Bytes = Alignment <= 16 ? 1 : 0 };
+
+};
+
+
+template <typename T>
+inline unsigned alignOf()
+	/// A templated function that returns the minimum alignment of
+	/// of a type.  This provides no extra functionality beyond the AlignOf
+	/// class besides some cosmetic cleanliness.  Example usage:
+	/// alignOf<int>() returns the alignment of an int.
+{
+	return AlignOf<T>::Alignment;
+}
+
+
+template <size_t Alignment> struct AlignedCharArrayImpl;
+	/// Helper for building an aligned character array type.
+	///
+	/// This template is used to explicitly build up a collection of aligned
+	/// character types. We have to build these up using a macro and explicit
+	/// specialization to cope with old versions of MSVC and GCC where only an
+	/// integer literal can be used to specify an alignment constraint. Once built
+	/// up here, we can then begin to indirect between these using normal C++
+	/// template parameters.
+
+
+// MSVC requires special handling here.
+#ifndef _MSC_VER
+
+	#if __has_feature(cxx_alignas)
+		#define POCO_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(x) \
+			template <> struct AlignedCharArrayImpl<x> \
+			{ \
+				char alignas(x) aligned; \
+			}
+	#elif defined(__GNUC__) || defined(__IBM_ATTRIBUTES)
+		#define POCO_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(x) \
+			template <> struct AlignedCharArrayImpl<x> \
+			{ \
+				char aligned __attribute__((aligned(x))); \
+			}
+	#else
+		# error No supported align as directive.
+	#endif
+
+	POCO_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(1);
+	POCO_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(2);
+	POCO_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(4);
+	POCO_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(8);
+	POCO_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(16);
+	POCO_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(32);
+	POCO_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(64);
+	POCO_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(128);
+	POCO_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(512);
+	POCO_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(1024);
+	POCO_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(2048);
+	POCO_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(4096);
+	POCO_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(8192);
+
+	#undef POCO_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT
+
+#else // _MSC_VER
+
+	// We provide special variations of this template for the most common
+	// alignments because __declspec(align(...)) doesn't actually work when it is
+	// a member of a by-value function argument in MSVC, even if the alignment
+	// request is something reasonably like 8-byte or 16-byte.
+	template <> struct AlignedCharArrayImpl<1> { char aligned; };
+	template <> struct AlignedCharArrayImpl<2> { short aligned; };
+	template <> struct AlignedCharArrayImpl<4> { int aligned; };
+	template <> struct AlignedCharArrayImpl<8> { double aligned; };
+
+	#define POCO_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(x) \
+		template <> struct AlignedCharArrayImpl<x> { \
+			__declspec(align(x)) char aligned; \
+		}
+
+	POCO_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(16);
+	POCO_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(32);
+	POCO_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(64);
+	POCO_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(128);
+	POCO_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(512);
+	POCO_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(1024);
+	POCO_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(2048);
+	POCO_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(4096);
+	POCO_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(8192);
+	// Any larger and MSVC complains.
+	#undef POCO_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT
+
+#endif // _MSC_VER
+
+
+template <typename T1, typename T2 = char, typename T3 = char, typename T4 = char>
+union AlignedCharArrayUnion
+	/// This union template exposes a suitably aligned and sized character
+	/// array member which can hold elements of any of up to four types.
+	///
+	/// These types may be arrays, structs, or any other types. The goal is to
+	/// produce a union type containing a character array which, when used, forms
+	/// storage suitable to placement new any of these types over. Support for more
+	/// than four types can be added at the cost of more boiler plate.
+{
+private:
+	class AlignerImpl
+	{
+		T1 t1;
+		T2 t2;
+		T3 t3;
+		T4 t4;
+	
+		AlignerImpl(); // Never defined or instantiated.
+	};
+
+	union SizerImpl
+	{
+		char arr1[sizeof(T1)];
+		char arr2[sizeof(T2)];
+		char arr3[sizeof(T3)];
+		char arr4[sizeof(T4)];
+	};
+
+public:
+	char buffer[sizeof(SizerImpl)];
+		/// The character array buffer for use by clients.
+		///
+		/// No other member of this union should be referenced. They exist purely to
+		/// constrain the layout of this character array.
+
+private:
+	Poco::AlignedCharArrayImpl<AlignOf<AlignerImpl>::Alignment> _nonceMember;
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_AlignOf_INCLUDED

+ 22 - 12
Foundation/include/Poco/Any.h

@@ -40,10 +40,13 @@
 
 #include "Poco/Exception.h"
 #include "Poco/MetaProgramming.h"
+#include "Poco/Alignment.h"
 #include <algorithm>
 #include <typeinfo>
 #include <cstring>
-
+#ifdef POCO_ENABLE_CPP11
+	#include <type_traits>
+#endif
 
 namespace Poco {
 
@@ -64,7 +67,7 @@ template <class> class VarHolderImpl;
 template <typename PlaceholderT, unsigned int SizeV = POCO_SMALL_OBJECT_SIZE>
 union Placeholder
 	/// ValueHolder union (used by Poco::Any and Poco::Dynamic::Var for small
-	/// object optimization).
+	/// object optimization, when enabled).
 	/// 
 	/// If Holder<Type> fits into POCO_SMALL_OBJECT_SIZE bytes of storage, 
 	/// it will be placement-new-allocated into the local buffer
@@ -86,23 +89,23 @@ public:
 
 	void erase()
 	{
-		std::memset(holder, 0, sizeof(Placeholder));
+		std::memset(holder.h, 0, sizeof(Placeholder));
 	}
 
 	bool isLocal() const
 	{
-		return holder[SizeV] != 0;
+		return holder.h[SizeV] != 0;
 	}
 
 	void setLocal(bool local) const
 	{
-		holder[SizeV] = local ? 1 : 0;
+		holder.h[SizeV] = local ? 1 : 0;
 	}
 
 	PlaceholderT* content() const
 	{
 		if(isLocal())
-			return reinterpret_cast<PlaceholderT*>(holder);
+			return reinterpret_cast<PlaceholderT*>(holder.h);
 		else
 			return pHolder;
 	}
@@ -112,9 +115,16 @@ public:
 private:
 #endif
 	
-	PlaceholderT*         pHolder;
+	PlaceholderT* pHolder;
 #ifndef POCO_NO_SOO
-	mutable unsigned char holder[SizeV + 1];
+	#ifndef POCO_ENABLE_CPP11
+		#error "Any SOO can only be enabled with C++11 support"
+	#endif
+	mutable union
+	{
+		std::aligned_storage<SizeV + 1> a;
+		unsigned char                   h[SizeV + 1];
+	} holder;
 #endif
 
 	friend class Any;
@@ -130,7 +140,7 @@ private:
 template <typename PlaceholderT>
 union Placeholder
 	/// ValueHolder union (used by Poco::Any and Poco::Dynamic::Var for small
-	/// object optimization).
+	/// object optimization, when enabled).
 	/// 
 	/// If Holder<Type> fits into POCO_SMALL_OBJECT_SIZE bytes of storage, 
 	/// it will be placement-new-allocated into the local buffer
@@ -275,7 +285,7 @@ public:
 		/// Returns true if the Any is empty.
 	{
 		char buf[POCO_SMALL_OBJECT_SIZE] = { 0 };
-		return 0 == std::memcmp(_valueHolder.holder, buf, POCO_SMALL_OBJECT_SIZE);
+		return 0 == std::memcmp(_valueHolder.holder.h, buf, POCO_SMALL_OBJECT_SIZE);
 	}
 	
 	const std::type_info & type() const
@@ -318,7 +328,7 @@ private:
 		{
 			if ((sizeof(Holder<ValueType>) <= POCO_SMALL_OBJECT_SIZE))
 			{
-				new ((ValueHolder*) pPlaceholder->holder) Holder(_held);
+				new ((ValueHolder*) pPlaceholder->holder.h) Holder(_held);
 				pPlaceholder->setLocal(true);
 			}
 			else
@@ -344,7 +354,7 @@ private:
 	{
 		if (sizeof(Holder<ValueType>) <= Placeholder<ValueType>::Size::value)
 		{
-			new (reinterpret_cast<ValueHolder*>(_valueHolder.holder)) Holder<ValueType>(value);
+			new (reinterpret_cast<ValueHolder*>(_valueHolder.holder.h)) Holder<ValueType>(value);
 			_valueHolder.setLocal(true);
 		}
 		else

+ 8 - 2
Foundation/include/Poco/Config.h

@@ -45,7 +45,7 @@
 
 
 // Define to enable C++11 support
-//	#define POCO_ENABLE_CPP11
+// #define POCO_ENABLE_CPP11
 
 
 // Define to disable implicit linking
@@ -100,11 +100,17 @@
 // candidates) will be auto-allocated on the stack in 
 // cases when value holder fits into POCO_SMALL_OBJECT_SIZE
 // (see below).
+// 
+// !!! NOTE: Any/Dynamic::Var SOO may NOT work reliably
+// !!! without C++11 (std::aligned_storage in particular)
+// 
 #define POCO_NO_SOO
 
 
 // Small object size in bytes. When assigned to Any or Var,
-// objects longer than this value will be alocated on the heap.
+// objects larger than this value will be alocated on the heap,
+// while those smaller will be placement new-ed into an
+// internal buffer.
 #if !defined(POCO_SMALL_OBJECT_SIZE) && !defined(POCO_NO_SOO)
 	#define POCO_SMALL_OBJECT_SIZE 32
 #endif

+ 13 - 22
Foundation/include/Poco/Dynamic/Var.h

@@ -110,14 +110,10 @@ public:
 	Var(const T& val)
 		/// Creates the Var from the given value.
 #ifdef POCO_NO_SOO
-		: _pHolder(new VarHolderImpl<T>(val)),
-		  _pBegin(new Iterator(this, false)),
-		  _pEnd(new Iterator(this, true))
+		: _pHolder(new VarHolderImpl<T>(val))
 	{
 	}
 #else
-		: _pBegin(new Iterator(this, false)),
-		  _pEnd(new Iterator(this, true))
 	{
 		construct(val);
 	}
@@ -135,10 +131,10 @@ public:
 	void swap(Var& other);
 		/// Swaps the content of the this Var with the other Var.
 
-	ConstIterator& begin() const;
+	ConstIterator begin() const;
 		/// Returns the const Var iterator.
 
-	ConstIterator& end() const;
+	ConstIterator end() const;
 		/// Returns the const Var iterator.
 
 	Iterator begin();
@@ -629,7 +625,7 @@ private:
 	{
 		if (sizeof(VarHolderImpl<ValueType>) <= Placeholder<ValueType>::Size::value)
 		{
-			new (reinterpret_cast<VarHolder*>(_placeholder.holder)) VarHolderImpl<ValueType>(value);
+			new (reinterpret_cast<VarHolder*>(_placeholder.holder.h)) VarHolderImpl<ValueType>(value);
 			_placeholder.setLocal(true);
 		}
 		else
@@ -644,7 +640,7 @@ private:
 		std::string val(value);
 		if (sizeof(VarHolderImpl<std::string>) <= Placeholder<std::string>::Size::value)
 		{
-			new (reinterpret_cast<VarHolder*>(_placeholder.holder)) VarHolderImpl<std::string>(val);
+			new (reinterpret_cast<VarHolder*>(_placeholder.holder.h)) VarHolderImpl<std::string>(val);
 			_placeholder.setLocal(true);
 		}
 		else
@@ -676,9 +672,6 @@ private:
 	Placeholder<VarHolder> _placeholder;
 
 #endif // POCO_NO_SOO
-	
-	Iterator* _pBegin;
-	Iterator* _pEnd;
 };
 
 
@@ -732,30 +725,28 @@ inline const std::type_info& Var::type() const
 }
 
 
-inline Var::ConstIterator& Var::begin() const
+inline Var::ConstIterator Var::begin() const
 {
-	if (isEmpty()) _pBegin->setPosition(Iterator::POSITION_END);
-	else if (*_pBegin == *_pEnd) _pBegin->setPosition(0);
+	if (isEmpty()) return ConstIterator(const_cast<Var*>(this), true);
 
-	return *_pBegin;
+	return ConstIterator(const_cast<Var*>(this), false);
 }
 
-inline Var::ConstIterator& Var::end() const
+inline Var::ConstIterator Var::end() const
 {
-	return *_pEnd;
+	return ConstIterator(const_cast<Var*>(this), true);
 }
 
 inline Var::Iterator Var::begin()
 {
-	if (isEmpty()) _pBegin->setPosition(Iterator::POSITION_END);
-	else if (*_pBegin == *_pEnd) _pBegin->setPosition(0);
+	if (isEmpty()) return Iterator(const_cast<Var*>(this), true);
 
-	return *_pBegin;
+	return Iterator(const_cast<Var*>(this), false);
 }
 
 inline Var::Iterator Var::end()
 {
-	return *_pEnd;
+	return Iterator(this, true);
 }
 
 

+ 2 - 2
Foundation/include/Poco/Dynamic/VarHolder.h

@@ -286,9 +286,9 @@ protected:
 		poco_check_ptr (pVarHolder);
 		if ((sizeof(VarHolderImpl<T>) <= Placeholder<T>::Size::value))
 		{
-			new ((VarHolder*) pVarHolder->holder) VarHolderImpl<T>(val);
+			new ((VarHolder*) pVarHolder->holder.h) VarHolderImpl<T>(val);
 			pVarHolder->setLocal(true);
-			return (VarHolder*) pVarHolder->holder;
+			return (VarHolder*) pVarHolder->holder.h;
 		}
 		else
 		{

+ 4 - 14
Foundation/src/Var.cpp

@@ -47,26 +47,20 @@ namespace Poco {
 namespace Dynamic {
 
 
-Var::Var() :
+Var::Var()
 #ifdef POCO_NO_SOO
-	_pHolder(0),
+	: _pHolder(0)
 #endif
-	_pBegin(new Iterator(this, true)),
-	_pEnd(new Iterator(this, true))
 {
 }
 
 
 Var::Var(const char* pVal)
 #ifdef POCO_NO_SOO 
-	: _pHolder(new VarHolderImpl<std::string>(pVal)),
-	  _pBegin(new Iterator(this, false)),
-	  _pEnd(new Iterator(this, true))
+	: _pHolder(new VarHolderImpl<std::string>(pVal))
 {
 }
 #else
-	: _pBegin(new Iterator(this, false)),
-	  _pEnd(new Iterator(this, true))
 {
 	construct(std::string(pVal));
 }
@@ -75,14 +69,10 @@ Var::Var(const char* pVal)
 
 Var::Var(const Var& other)
 #ifdef POCO_NO_SOO
-	: _pHolder(other._pHolder ? other._pHolder->clone() : 0),
-	  _pBegin(new Iterator(*other._pBegin)),
-	  _pEnd(new Iterator(*other._pEnd))
+	: _pHolder(other._pHolder ? other._pHolder->clone() : 0)
 {
 }
 #else
-	: _pBegin(new Iterator(*other._pBegin)),
-	  _pEnd(new Iterator(*other._pEnd))
 {
 	if ((this != &other) && !other.isEmpty())
 			construct(other);

+ 27 - 2
Net/include/Poco/Net/IPAddress.h

@@ -44,6 +44,11 @@
 #include "Poco/Net/SocketDefs.h"
 #include "Poco/Net/IPAddressImpl.h"
 #include <vector>
+#ifdef POCO_ENABLE_CPP11
+	#include <type_traits>
+#else
+	#include "Poco/Alignment.h"
+#endif
 
 
 namespace Poco {
@@ -387,9 +392,23 @@ private:
 	typedef Impl* Ptr;
 
 	Ptr pImpl() const;
+
 	void destruct();
 
-	char _memory[sizeof(Poco::Net::Impl::IPv6AddressImpl)];
+	char* storage();
+
+#ifdef POCO_ENABLE_CPP11
+	static const unsigned sz = sizeof(Poco::Net::Impl::IPv6AddressImpl);
+	union
+	{
+		std::aligned_storage<sz> a;
+		char                     buffer[sz];
+	}
+#else // !POCO_ENABLE_CPP11
+	AlignedCharArrayUnion <Poco::Net::Impl::IPv6AddressImpl, 
+		Poco::Net::Impl::IPv4AddressImpl>
+#endif // POCO_ENABLE_CPP11
+	_memory;
 };
 
 
@@ -401,7 +420,13 @@ inline void IPAddress::destruct()
 
 inline IPAddress::Ptr IPAddress::pImpl() const
 {
-	return reinterpret_cast<Ptr>(const_cast<char *>(_memory));
+	return reinterpret_cast<Ptr>(const_cast<char *>(_memory.buffer));
+}
+
+
+inline char* IPAddress::storage()
+{
+	return _memory.buffer;
 }
 
 

+ 22 - 2
Net/include/Poco/Net/SocketAddress.h

@@ -153,9 +153,23 @@ private:
 	typedef Impl* Ptr;
 
 	Ptr pImpl() const;
+
 	void destruct();
 
-	char _memory[sizeof(Poco::Net::Impl::IPv6SocketAddressImpl)];
+	char* storage();
+
+#ifdef POCO_ENABLE_CPP11
+	static const unsigned sz = sizeof(Poco::Net::Impl::IPv6SocketAddressImpl);
+	union
+	{
+		std::aligned_storage<sz> a;
+		char                     buffer[sz];
+	}
+#else // !POCO_ENABLE_CPP11
+	AlignedCharArrayUnion <Poco::Net::Impl::IPv6SocketAddressImpl, 
+		Poco::Net::Impl::IPv4SocketAddressImpl>
+#endif // POCO_ENABLE_CPP11
+	_memory;
 };
 
 
@@ -172,7 +186,13 @@ inline void SocketAddress::destruct()
 
 inline SocketAddress::Ptr SocketAddress::pImpl() const
 {
-	return reinterpret_cast<Ptr>(const_cast<char *>(_memory));
+	return reinterpret_cast<Ptr>(const_cast<char *>(_memory.buffer));
+}
+
+
+inline char* SocketAddress::storage()
+{
+	return _memory.buffer;
 }
 
 

+ 25 - 25
Net/src/IPAddress.cpp

@@ -64,26 +64,26 @@ namespace Net {
 
 IPAddress::IPAddress()
 {
-	new (_memory) IPv4AddressImpl();
+	new (storage()) IPv4AddressImpl();
 }
 
 
 IPAddress::IPAddress(const IPAddress& addr)
 {
 	if (addr.family() == IPv4)
-		new (_memory) IPv4AddressImpl(addr.addr());
+		new (storage()) IPv4AddressImpl(addr.addr());
 	else
-		new (_memory) IPv6AddressImpl(addr.addr());
+		new (storage()) IPv6AddressImpl(addr.addr());
 }
 
 
 IPAddress::IPAddress(Family family)
 {
 	if (family == IPv4)
-		new (_memory) IPv4AddressImpl();
+		new (storage()) IPv4AddressImpl();
 #if defined(POCO_HAVE_IPv6)
 	else if (family == IPv6)
-		new (_memory) IPv6AddressImpl();
+		new (storage()) IPv6AddressImpl();
 #endif
 	else
 		throw Poco::InvalidArgumentException("Invalid or unsupported address family passed to IPAddress()");
@@ -95,14 +95,14 @@ IPAddress::IPAddress(const std::string& addr)
 	IPv4AddressImpl empty4 = IPv4AddressImpl();
 	if (addr.empty() || trim(addr) == "0.0.0.0")
 	{
-		new (_memory) IPv4AddressImpl(empty4.addr());
+		new (storage()) IPv4AddressImpl(empty4.addr());
 		return;
 	}
 
 	IPv4AddressImpl addr4(IPv4AddressImpl::parse(addr));
 	if (addr4 != empty4)
 	{
-		new (_memory) IPv4AddressImpl(addr4.addr());
+		new (storage()) IPv4AddressImpl(addr4.addr());
 		return;
 	}
 
@@ -110,14 +110,14 @@ IPAddress::IPAddress(const std::string& addr)
 	IPv6AddressImpl empty6 = IPv6AddressImpl();
 	if (addr.empty() || trim(addr) == "::")
 	{
-		new (_memory) IPv6AddressImpl(empty6.addr());
+		new (storage()) IPv6AddressImpl(empty6.addr());
 		return;
 	}
 
 	IPv6AddressImpl addr6(IPv6AddressImpl::parse(addr));
 	if (addr6 != IPv6AddressImpl())
 	{
-		new (_memory) IPv6AddressImpl(addr6.addr());
+		new (storage()) IPv6AddressImpl(addr6.addr());
 		return;
 	}
 #endif
@@ -131,14 +131,14 @@ IPAddress::IPAddress(const std::string& addr, Family family)
 	if (family == IPv4)
 	{
 		IPv4AddressImpl addr4(IPv4AddressImpl::parse(addr));
-		new (_memory) IPv4AddressImpl(addr4.addr());
+		new (storage()) IPv4AddressImpl(addr4.addr());
 		return;
 	}
 #if defined(POCO_HAVE_IPv6)
 	else if (family == IPv6)
 	{
 		IPv6AddressImpl addr6(IPv6AddressImpl::parse(addr));
-		new (_memory) IPv6AddressImpl(addr6.addr());
+		new (storage()) IPv6AddressImpl(addr6.addr());
 		return;
 	}
 #endif
@@ -149,10 +149,10 @@ IPAddress::IPAddress(const std::string& addr, Family family)
 IPAddress::IPAddress(const void* addr, poco_socklen_t length)
 {
 	if (length == sizeof(struct in_addr))
-		new (_memory) IPv4AddressImpl(addr);
+		new (storage()) IPv4AddressImpl(addr);
 #if defined(POCO_HAVE_IPv6)
 	else if (length == sizeof(struct in6_addr))
-		new (_memory) IPv6AddressImpl(addr);
+		new (storage()) IPv6AddressImpl(addr);
 #endif
 	else throw Poco::InvalidArgumentException("Invalid address length passed to IPAddress()");
 }
@@ -161,10 +161,10 @@ IPAddress::IPAddress(const void* addr, poco_socklen_t length)
 IPAddress::IPAddress(const void* addr, poco_socklen_t length, Poco::UInt32 scope)
 {
 	if (length == sizeof(struct in_addr))
-		new (_memory) IPv4AddressImpl(addr);
+		new (storage()) IPv4AddressImpl(addr);
 #if defined(POCO_HAVE_IPv6)
 	else if (length == sizeof(struct in6_addr))
-		new (_memory) IPv6AddressImpl(addr, scope);
+		new (storage()) IPv6AddressImpl(addr, scope);
 #endif
 	else throw Poco::InvalidArgumentException("Invalid address length passed to IPAddress()");
 }
@@ -175,13 +175,13 @@ IPAddress::IPAddress(unsigned prefix, Family family)
 	if (family == IPv4)
 	{
 		if (prefix <= 32)
-			new (_memory) IPv4AddressImpl(prefix);
+			new (storage()) IPv4AddressImpl(prefix);
 	}
 #if defined(POCO_HAVE_IPv6)
 	else if (family == IPv6)
 	{
 		if (prefix <= 128)
-			new (_memory) IPv6AddressImpl(prefix);
+			new (storage()) IPv6AddressImpl(prefix);
 	}
 #endif
 	else throw Poco::InvalidArgumentException("Invalid or unsupported address family passed to IPAddress()");
@@ -194,10 +194,10 @@ IPAddress::IPAddress(const SOCKET_ADDRESS& socket_address)
 {
 	ADDRESS_FAMILY family = socket_address.lpSockaddr->sa_family;
 	if (family == AF_INET)
-		new (_memory) IPv4AddressImpl(&reinterpret_cast<const struct sockaddr_in*>(socket_address.lpSockaddr)->sin_addr);
+		new (storage()) IPv4AddressImpl(&reinterpret_cast<const struct sockaddr_in*>(socket_address.lpSockaddr)->sin_addr);
 #if defined(POCO_HAVE_IPv6)
 	else if (family == AF_INET6)
-		new (_memory) IPv6AddressImpl(&reinterpret_cast<const struct sockaddr_in6*>(socket_address.lpSockaddr)->sin6_addr,
+		new (storage()) IPv6AddressImpl(&reinterpret_cast<const struct sockaddr_in6*>(socket_address.lpSockaddr)->sin6_addr,
                                         reinterpret_cast<const struct sockaddr_in6*>(socket_address.lpSockaddr)->sin6_scope_id);
 #endif
 	else throw Poco::InvalidArgumentException("Invalid or unsupported address family passed to IPAddress()");
@@ -209,10 +209,10 @@ IPAddress::IPAddress(const struct sockaddr& sockaddr)
 {
 	unsigned short family = sockaddr.sa_family;
 	if (family == AF_INET)
-		new (_memory) IPv4AddressImpl(&reinterpret_cast<const struct sockaddr_in*>(&sockaddr)->sin_addr);
+		new (storage()) IPv4AddressImpl(&reinterpret_cast<const struct sockaddr_in*>(&sockaddr)->sin_addr);
 #if defined(POCO_HAVE_IPv6)
 	else if (family == AF_INET6)
-		new (_memory) IPv6AddressImpl(&reinterpret_cast<const struct sockaddr_in6*>(&sockaddr)->sin6_addr,
+		new (storage()) IPv6AddressImpl(&reinterpret_cast<const struct sockaddr_in6*>(&sockaddr)->sin6_addr,
                                        reinterpret_cast<const struct sockaddr_in6*>(&sockaddr)->sin6_scope_id);
 #endif
 	else throw Poco::InvalidArgumentException("Invalid or unsupported address family passed to IPAddress()");
@@ -231,9 +231,9 @@ IPAddress& IPAddress::operator = (const IPAddress& addr)
 	{
 		destruct();
 		if (addr.family() == IPAddress::IPv4)
-			new (_memory) IPv4AddressImpl(addr.addr());
+			new (storage()) IPv4AddressImpl(addr.addr());
 		else
-			new (_memory) IPv6AddressImpl(addr.addr());
+			new (storage()) IPv6AddressImpl(addr.addr());
 	}
 	return *this;
 }
@@ -546,14 +546,14 @@ bool IPAddress::tryParse(const std::string& addr, IPAddress& result)
 	if (impl4 != IPv4AddressImpl())
 	{
 		
-		new (result._memory) IPv4AddressImpl(impl4.addr());
+		new (result.storage()) IPv4AddressImpl(impl4.addr());
 		return true;
 	}
 #if defined(POCO_HAVE_IPv6)
 	IPv6AddressImpl impl6(IPv6AddressImpl::parse(addr));
 	if (impl6 != IPv6AddressImpl())
 	{
-		new (result._memory) IPv6AddressImpl(impl6.addr());
+		new (result.storage()) IPv6AddressImpl(impl6.addr());
 		return true;
 	}
 #endif

+ 9 - 9
Net/src/SocketAddress.cpp

@@ -75,7 +75,7 @@ struct AFLT
 
 SocketAddress::SocketAddress()
 {
-	new (_memory) IPv4SocketAddressImpl;
+	new (storage()) IPv4SocketAddressImpl;
 }
 
 
@@ -135,19 +135,19 @@ SocketAddress::SocketAddress(const std::string& hostAndPort)
 SocketAddress::SocketAddress(const SocketAddress& socketAddress)
 {
 	if (socketAddress.family() == IPAddress::IPv4)
-		new (_memory) IPv4SocketAddressImpl(reinterpret_cast<const sockaddr_in*>(socketAddress.addr()));
+		new (storage()) IPv4SocketAddressImpl(reinterpret_cast<const sockaddr_in*>(socketAddress.addr()));
 	else
-		new (_memory) IPv6SocketAddressImpl(reinterpret_cast<const sockaddr_in6*>(socketAddress.addr()));
+		new (storage()) IPv6SocketAddressImpl(reinterpret_cast<const sockaddr_in6*>(socketAddress.addr()));
 }
 
 
 SocketAddress::SocketAddress(const struct sockaddr* sockAddr, poco_socklen_t length)
 {
 	if (length == sizeof(struct sockaddr_in))
-		new (_memory) IPv4SocketAddressImpl(reinterpret_cast<const struct sockaddr_in*>(sockAddr));
+		new (storage()) IPv4SocketAddressImpl(reinterpret_cast<const struct sockaddr_in*>(sockAddr));
 #if defined(POCO_HAVE_IPv6)
 	else if (length == sizeof(struct sockaddr_in6))
-		new (_memory) IPv6SocketAddressImpl(reinterpret_cast<const struct sockaddr_in6*>(sockAddr));
+		new (storage()) IPv6SocketAddressImpl(reinterpret_cast<const struct sockaddr_in6*>(sockAddr));
 #endif
 	else throw Poco::InvalidArgumentException("Invalid address length passed to SocketAddress()");
 }
@@ -175,9 +175,9 @@ SocketAddress& SocketAddress::operator = (const SocketAddress& socketAddress)
 	{
 		destruct();
 		if (socketAddress.family() == IPAddress::IPv4)
-			new (_memory) IPv4SocketAddressImpl(reinterpret_cast<const sockaddr_in*>(socketAddress.addr()));
+			new (storage()) IPv4SocketAddressImpl(reinterpret_cast<const sockaddr_in*>(socketAddress.addr()));
 		else
-			new (_memory) IPv6SocketAddressImpl(reinterpret_cast<const sockaddr_in6*>(socketAddress.addr()));
+			new (storage()) IPv6SocketAddressImpl(reinterpret_cast<const sockaddr_in6*>(socketAddress.addr()));
 	}
 	return *this;
 }
@@ -232,10 +232,10 @@ std::string SocketAddress::toString() const
 void SocketAddress::init(const IPAddress& hostAddress, Poco::UInt16 portNumber)
 {
 	if (hostAddress.family() == IPAddress::IPv4)
-		new (_memory) IPv4SocketAddressImpl(hostAddress.addr(), htons(portNumber));
+		new (storage()) IPv4SocketAddressImpl(hostAddress.addr(), htons(portNumber));
 #if defined(POCO_HAVE_IPv6)
 	else if (hostAddress.family() == IPAddress::IPv6)
-		new (_memory) IPv6SocketAddressImpl(hostAddress.addr(), htons(portNumber), hostAddress.scope());
+		new (storage()) IPv6SocketAddressImpl(hostAddress.addr(), htons(portNumber), hostAddress.scope());
 #endif
 	else throw Poco::NotImplementedException("unsupported IP address family");
 }

+ 93 - 48
doc/90100-Acknowledgements.page

@@ -184,65 +184,110 @@ following copyrighted material, the use of which is hereby acknowledged.
 
 !!!SQlite 3.7.14
 
-The original author of SQLite has dedicated the code to the 
-public domain (http://www.sqlite.org/copyright.html). 
-Anyone is free to copy, modify, publish, use, compile, sell, or distribute the 
-original SQLite code, either in source code form or as a compiled binary, 
-for any purpose, commercial or non-commercial, and by any means.
+    The original author of SQLite has dedicated the code to the 
+    public domain (http://www.sqlite.org/copyright.html). 
+    Anyone is free to copy, modify, publish, use, compile, sell, or distribute the 
+    original SQLite code, either in source code form or as a compiled binary, 
+    for any purpose, commercial or non-commercial, and by any means.
 ----
 
 
 !!!double-conversion
 
-Copyright 2010 the V8 project authors. All rights reserved.
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are
-met:
-
-    * Redistributions of source code must retain the above copyright
-      notice, this list of conditions and the following disclaimer.
-    * Redistributions in binary form must reproduce the above
-      copyright notice, this list of conditions and the following
-      disclaimer in the documentation and/or other materials provided
-      with the distribution.
-    * Neither the name of Google Inc. nor the names of its
-      contributors may be used to endorse or promote products derived
-      from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+    Copyright 2010 the V8 project authors. All rights reserved.
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions are
+    met:
+
+        * Redistributions of source code must retain the above copyright
+          notice, this list of conditions and the following disclaimer.
+        * Redistributions in binary form must reproduce the above
+          copyright notice, this list of conditions and the following
+          disclaimer in the documentation and/or other materials provided
+          with the distribution.
+        * Neither the name of Google Inc. nor the names of its
+          contributors may be used to endorse or promote products derived
+          from this software without specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 ----
 
 
 !!!JSON_parser
 
-Copyright (c) 2005 JSON.org
+    Copyright (c) 2005 JSON.org
+
+    Permission is hereby granted, free of charge, to any person obtaining a copy
+    of this software and associated documentation files (the "Software"), to deal
+    in the Software without restriction, including without limitation the rights
+    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+    copies of the Software, and to permit persons to whom the Software is
+    furnished to do so, subject to the following conditions:
+    
+    The above copyright notice and this permission notice shall be included in all
+    copies or substantial portions of the Software.
+
+    The Software shall be used for Good, not Evil.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+    SOFTWARE.
+----
+
+
+!!!Code from the LLVM Compiler Infrastructure
 
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
+    University of Illinois/NCSA
+    Open Source License
 
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
+    Copyright (c) 2007-2012 University of Illinois at Urbana-Champaign.
+    All rights reserved.
 
-The Software shall be used for Good, not Evil.
+    Developed by:
 
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
+        LLVM Team
+    
+        University of Illinois at Urbana-Champaign
+    
+        http://llvm.org
+    
+    Permission is hereby granted, free of charge, to any person obtaining a copy of
+    this software and associated documentation files (the "Software"), to deal with
+    the Software without restriction, including without limitation the rights to
+    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+    of the Software, and to permit persons to whom the Software is furnished to do
+    so, subject to the following conditions:
+    
+        * Redistributions of source code must retain the above copyright notice,
+          this list of conditions and the following disclaimers.
+    
+        * Redistributions in binary form must reproduce the above copyright notice,
+          this list of conditions and the following disclaimers in the
+          documentation and/or other materials provided with the distribution.
+    
+        * Neither the names of the LLVM Team, University of Illinois at
+          Urbana-Champaign, nor the names of its contributors may be used to
+          endorse or promote products derived from this Software without specific
+          prior written permission.
+    
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+    FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+    CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
+    SOFTWARE.

+ 43 - 0
doc/Acknowledgements.html

@@ -251,5 +251,48 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 SOFTWARE.
 </pre></p>
 
+<h3>Code from the LLVM Compiler Infrastructure</h3>
+<p><pre>University of Illinois/NCSA
+Open Source License
+
+Copyright (c) 2007-2012 University of Illinois at Urbana-Champaign.
+All rights reserved.
+
+Developed by:
+
+    LLVM Team
+
+    University of Illinois at Urbana-Champaign
+
+    http://llvm.org
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal with
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+    * Redistributions of source code must retain the above copyright notice,
+      this list of conditions and the following disclaimers.
+
+    * Redistributions in binary form must reproduce the above copyright notice,
+      this list of conditions and the following disclaimers in the
+      documentation and/or other materials provided with the distribution.
+
+    * Neither the names of the LLVM Team, University of Illinois at
+      Urbana-Champaign, nor the names of its contributors may be used to
+      endorse or promote products derived from this Software without specific
+      prior written permission.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
+SOFTWARE.
+</pre></p>
+
 </body>
 </html>