unlink Label when LabelManager is destroyed
diff --git a/readme.md b/readme.md
index 5e52ac4..38297fb 100644
--- a/readme.md
+++ b/readme.md
@@ -1,5 +1,5 @@
 
-# Xbyak 5.74 ; JIT assembler for x86(IA32), x64(AMD64, x86-64) by C++
+# Xbyak 5.75 ; JIT assembler for x86(IA32), x64(AMD64, x86-64) by C++
 
 ## Abstract
 
@@ -392,6 +392,7 @@
 http://opensource.org/licenses/BSD-3-Clause
 
 ## History
+* 2018/Oct/29 ver 5.75 unlink LabelManager from Label when msg is destroyed
 * 2018/Oct/21 ver 5.74 support RegRip +/- int. Xbyak::CastTo is removed
 * 2018/Oct/15 util::AddressFrame uses push/pop instead of mov
 * 2018/Sep/19 ver 5.73 fix evex encoding of vpslld, vpslldq, vpsllw, etc for (reg, mem, imm8)
diff --git a/readme.txt b/readme.txt
index 420bb0e..ee0a578 100644
--- a/readme.txt
+++ b/readme.txt
@@ -1,5 +1,5 @@
 

-    C++用x86(IA-32), x64(AMD64, x86-64) JITアセンブラ Xbyak 5.74

+    C++用x86(IA-32), x64(AMD64, x86-64) JITアセンブラ Xbyak 5.75

 

 -----------------------------------------------------------------------------

 ◎概要

@@ -373,6 +373,7 @@
 -----------------------------------------------------------------------------

 ◎履歴

 

+2018/10/29 LabelManagerのデストラクタでLabelから参照を切り離す

 2018/10/21 RegRip +/intの形をサポート Xbyak::CastToを削除

 2018/10/15 util::StackFrameでmovの代わりにpush/popを使う

 2018/09/19 ver 5.73 vpslld, vpslldq, vpsllwなどの(reg, mem, imm8)に対するevexエンコーディング修整

diff --git a/test/jmp.cpp b/test/jmp.cpp
index 6a3b461..9fe8ff6 100644
--- a/test/jmp.cpp
+++ b/test/jmp.cpp
@@ -1016,9 +1016,9 @@
 };
 
 struct CodeLabelTable : Xbyak::CodeGenerator {
-	static const int ret0 = 3;
-	static const int ret1 = 5;
-	static const int ret2 = 8;
+	enum { ret0 = 3 };
+	enum { ret1 = 5 };
+	enum { ret2 = 8 };
 	CodeLabelTable()
 	{
 		using namespace Xbyak;
@@ -1225,3 +1225,48 @@
 	code.setProtectModeRW();
 }
 #endif
+
+struct ReleaseTestCode : Xbyak::CodeGenerator {
+	ReleaseTestCode(Label& L1, Label& L2, Label& L3)
+	{
+		L(L1);
+		jmp(L1);
+		L(L2);
+		jmp(L3); // not assigned
+	}
+};
+
+/*
+	code must unlink label if code is destroyed
+*/
+CYBOZU_TEST_AUTO(release_label_after_code)
+{
+	puts("---");
+	{
+		Label L1, L2, L3, L4, L5;
+		{
+			ReleaseTestCode code(L1, L2, L3);
+			CYBOZU_TEST_ASSERT(L1.getId() > 0);
+			CYBOZU_TEST_ASSERT(L1.getAddress() != 0);
+			CYBOZU_TEST_ASSERT(L2.getId() > 0);
+			CYBOZU_TEST_ASSERT(L2.getAddress() != 0);
+			CYBOZU_TEST_ASSERT(L3.getId() > 0);
+			CYBOZU_TEST_ASSERT(L3.getAddress() == 0); // L3 is not assigned
+			code.assignL(L4, L1);
+			L5 = L1;
+			printf("id=%d %d %d %d %d\n", L1.getId(), L2.getId(), L3.getId(), L4.getId(), L5.getId());
+		}
+		puts("code is released");
+		CYBOZU_TEST_ASSERT(L1.getId() == 0);
+		CYBOZU_TEST_ASSERT(L1.getAddress() == 0);
+		CYBOZU_TEST_ASSERT(L2.getId() == 0);
+		CYBOZU_TEST_ASSERT(L2.getAddress() == 0);
+//		CYBOZU_TEST_ASSERT(L3.getId() == 0); // L3 is not assigned so not cleared
+		CYBOZU_TEST_ASSERT(L3.getAddress() == 0);
+		CYBOZU_TEST_ASSERT(L4.getId() == 0);
+		CYBOZU_TEST_ASSERT(L4.getAddress() == 0);
+		CYBOZU_TEST_ASSERT(L5.getId() == 0);
+		CYBOZU_TEST_ASSERT(L5.getAddress() == 0);
+		printf("id=%d %d %d %d %d\n", L1.getId(), L2.getId(), L3.getId(), L4.getId(), L5.getId());
+	}
+}
diff --git a/xbyak/xbyak.h b/xbyak/xbyak.h
index 0b0d835..03a2419 100644
--- a/xbyak/xbyak.h
+++ b/xbyak/xbyak.h
@@ -40,6 +40,8 @@
 // This covers -std=(gnu|c)++(0x|11|1y), -stdlib=libc++, and modern Microsoft.
 #if ((defined(_MSC_VER) && (_MSC_VER >= 1600)) || defined(_LIBCPP_VERSION) ||\
 	 			 ((__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__)))
+	#include <unordered_set>
+	#define XBYAK_STD_UNORDERED_SET std::unordered_set
 	#include <unordered_map>
 	#define XBYAK_STD_UNORDERED_MAP std::unordered_map
 	#define XBYAK_STD_UNORDERED_MULTIMAP std::unordered_multimap
@@ -49,16 +51,22 @@
 	libstdcxx 20070719 (from GCC 4.2.1, the last GPL 2 version).
 */
 #elif XBYAK_GNUC_PREREQ(4, 5) || (XBYAK_GNUC_PREREQ(4, 2) && __GLIBCXX__ >= 20070719) || defined(__INTEL_COMPILER) || defined(__llvm__)
+	#include <tr1/unordered_set>
+	#define XBYAK_STD_UNORDERED_SET std::tr1::unordered_set
 	#include <tr1/unordered_map>
 	#define XBYAK_STD_UNORDERED_MAP std::tr1::unordered_map
 	#define XBYAK_STD_UNORDERED_MULTIMAP std::tr1::unordered_multimap
 
 #elif defined(_MSC_VER) && (_MSC_VER >= 1500) && (_MSC_VER < 1600)
+	#include <unordered_set>
+	#define XBYAK_STD_UNORDERED_SET std::tr1::unordered_set
 	#include <unordered_map>
 	#define XBYAK_STD_UNORDERED_MAP std::tr1::unordered_map
 	#define XBYAK_STD_UNORDERED_MULTIMAP std::tr1::unordered_multimap
 
 #else
+	#include <set>
+	#define XBYAK_STD_UNORDERED_SET std::set
 	#include <map>
 	#define XBYAK_STD_UNORDERED_MAP std::map
 	#define XBYAK_STD_UNORDERED_MULTIMAP std::multimap
@@ -105,7 +113,7 @@
 
 enum {
 	DEFAULT_MAX_CODE_SIZE = 4096,
-	VERSION = 0x5740 /* 0xABCD = A.BC(D) */
+	VERSION = 0x5750 /* 0xABCD = A.BC(D) */
 };
 
 #ifndef MIE_INTEGER_TYPE_DEFINED
@@ -1129,6 +1137,7 @@
 	Label(const Label& rhs);
 	Label& operator=(const Label& rhs);
 	~Label();
+	void clear() { mgr = 0; id = 0; }
 	int getId() const { return id; }
 	const uint8 *getAddress() const;
 
@@ -1167,6 +1176,7 @@
 	};
 	typedef XBYAK_STD_UNORDERED_MAP<int, ClabelVal> ClabelDefList;
 	typedef XBYAK_STD_UNORDERED_MULTIMAP<int, const JmpLabel> ClabelUndefList;
+	typedef XBYAK_STD_UNORDERED_SET<Label*> LabelPtrList;
 
 	CodeArray *base_;
 	// global : stateList_.front(), local : stateList_.back()
@@ -1174,6 +1184,7 @@
 	mutable int labelId_;
 	ClabelDefList clabelDefList_;
 	ClabelUndefList clabelUndefList_;
+	LabelPtrList labelPtrList_;
 
 	int getId(const Label& label) const
 	{
@@ -1222,9 +1233,14 @@
 		return true;
 	}
 	friend class Label;
-	void incRefCount(int id) { clabelDefList_[id].refCount++; }
-	void decRefCount(int id)
+	void incRefCount(int id, Label *label)
 	{
+		clabelDefList_[id].refCount++;
+		labelPtrList_.insert(label);
+	}
+	void decRefCount(int id, Label *label)
+	{
+		labelPtrList_.erase(label);
 		ClabelDefList::iterator i = clabelDefList_.find(id);
 		if (i == clabelDefList_.end()) return;
 		if (i->second.refCount == 1) {
@@ -1243,11 +1259,23 @@
 #endif
 		return !list.empty();
 	}
+	// detach all labels linked to LabelManager
+	void resetLabelPtrList()
+	{
+		for (LabelPtrList::iterator i = labelPtrList_.begin(), ie = labelPtrList_.end(); i != ie; ++i) {
+			(*i)->clear();
+		}
+		labelPtrList_.clear();
+	}
 public:
 	LabelManager()
 	{
 		reset();
 	}
+	~LabelManager()
+	{
+		resetLabelPtrList();
+	}
 	void reset()
 	{
 		base_ = 0;
@@ -1257,6 +1285,7 @@
 		stateList_.push_back(SlabelState());
 		clabelDefList_.clear();
 		clabelUndefList_.clear();
+		resetLabelPtrList();
 	}
 	void enterLocal()
 	{
@@ -1289,10 +1318,11 @@
 		SlabelState& st = *label.c_str() == '.' ? stateList_.back() : stateList_.front();
 		define_inner(st.defList, st.undefList, label, base_->getSize());
 	}
-	void defineClabel(const Label& label)
+	void defineClabel(Label& label)
 	{
 		define_inner(clabelDefList_, clabelUndefList_, getId(label), base_->getSize());
 		label.mgr = this;
+		labelPtrList_.insert(&label);
 	}
 	void assign(Label& dst, const Label& src)
 	{
@@ -1300,6 +1330,7 @@
 		if (i == clabelDefList_.end()) throw Error(ERR_LABEL_ISNOT_SET_BY_L);
 		define_inner(clabelDefList_, clabelUndefList_, dst.id, i->second.offset);
 		dst.mgr = this;
+		labelPtrList_.insert(&dst);
 	}
 	bool getOffset(size_t *offset, std::string& label) const
 	{
@@ -1347,19 +1378,19 @@
 {
 	id = rhs.id;
 	mgr = rhs.mgr;
-	if (mgr) mgr->incRefCount(id);
+	if (mgr) mgr->incRefCount(id, this);
 }
 inline Label& Label::operator=(const Label& rhs)
 {
 	if (id) throw Error(ERR_LABEL_IS_ALREADY_SET_BY_L);
 	id = rhs.id;
 	mgr = rhs.mgr;
-	if (mgr) mgr->incRefCount(id);
+	if (mgr) mgr->incRefCount(id, this);
 	return *this;
 }
 inline Label::~Label()
 {
-	if (id && mgr) mgr->decRefCount(id);
+	if (id && mgr) mgr->decRefCount(id, this);
 }
 inline const uint8* Label::getAddress() const
 {
@@ -2163,7 +2194,7 @@
 	const Segment es, cs, ss, ds, fs, gs;
 #endif
 	void L(const std::string& label) { labelMgr_.defineSlabel(label); }
-	void L(const Label& label) { labelMgr_.defineClabel(label); }
+	void L(Label& label) { labelMgr_.defineClabel(label); }
 	Label L() { Label label; L(label); return label; }
 	void inLocalLabel() { labelMgr_.enterLocal(); }
 	void outLocalLabel() { labelMgr_.leaveLocal(); }
diff --git a/xbyak/xbyak_mnemonic.h b/xbyak/xbyak_mnemonic.h
index 0dc268a..4f81090 100644
--- a/xbyak/xbyak_mnemonic.h
+++ b/xbyak/xbyak_mnemonic.h
@@ -1,4 +1,4 @@
-const char *getVersionString() const { return "5.74"; }
+const char *getVersionString() const { return "5.75"; }
 void adc(const Operand& op, uint32 imm) { opRM_I(op, imm, 0x10, 2); }
 void adc(const Operand& op1, const Operand& op2) { opRM_RM(op1, op2, 0x10); }
 void adcx(const Reg32e& reg, const Operand& op) { opGen(reg, op, 0xF6, 0x66, isREG32_REG32orMEM, NONE, 0x38); }