Index: phobos2/std/zip.d
===================================================================
--- phobos2/std/zip.d	(revision 209)
+++ phobos2/std/zip.d	(working copy)
@@ -21,7 +21,6 @@
 private import std.zlib;
 private import std.date;
 private import std.intrinsic;
-import std.conv;
 
 //debug=print;
 
@@ -318,7 +317,7 @@
 		endcommentlength = getUshort(i + 20);
 		if (i + 22 + endcommentlength > data.length)
 		    continue;
-		comment = to!(string)(data[i + 22 .. i + 22 + endcommentlength]);
+		comment = cast(string)(data[i + 22 .. i + 22 + endcommentlength]);
 		endrecOffset = i;
 		break;
 	    }
@@ -379,11 +378,11 @@
 	    if (i + namelen + extralen + commentlen > directoryOffset + directorySize)
 		throw new ZipException("invalid directory entry 2");
 
-	    de.name = to!(string)(data[i .. i + namelen]);
+	    de.name = cast(string)(data[i .. i + namelen]);
 	    i += namelen;
 	    de.extra = data[i .. i + extralen];
 	    i += extralen;
-	    de.comment = to!(string)(data[i .. i + commentlen]);
+	    de.comment = cast(string)(data[i .. i + commentlen]);
 	    i += commentlen;
 
 	    directory[de.name] = de;
Index: phobos2/std/variant.d
===================================================================
--- phobos2/std/variant.d	(revision 209)
+++ phobos2/std/variant.d	(working copy)
@@ -239,10 +239,8 @@
             break;
         case OpID.get:
             return !tryPutting(cast(A*) pStore, *cast(TypeInfo*) parm, parm);
-            break; // for conformity
         case OpID.testConversion:
             return !tryPutting(null, *cast(TypeInfo*) parm, null);
-            break;
         case OpID.compare:
             auto me = cast(A*) pStore;
             auto rhsP = cast(VariantN *) parm;
@@ -297,7 +295,6 @@
                 }
             }
             return int.min; // dunno
-            break;
         case OpID.toString:
             auto target = cast(string*) parm;
             auto me = cast(A*) pStore;
Index: phobos2/std/loader.d
===================================================================
--- phobos2/std/loader.d	(revision 209)
+++ phobos2/std/loader.d	(working copy)
@@ -858,7 +858,15 @@
 
     this(uint errcode)
     {
+      version (linux)
+      {
+	char[80] buf = void;
+	super(std.string.toString(strerror_r(errcode, buf.ptr, buf.length)).idup);
+      }
+      else
+      {
 	super(std.string.toString(strerror(errcode)).idup);
+      }
     }
 }
 
Index: phobos2/std/windows/charset.d
===================================================================
--- phobos2/std/windows/charset.d	(revision 209)
+++ phobos2/std/windows/charset.d	(working copy)
@@ -13,21 +13,7 @@
 private import std.utf;
 private import std.string;
 
-/**
- * If non-zero, the application should use the W versions of Windows API
- * functions and std.utf.toUTF16z and toUTF8, rather than toMBSz and
- * fromMBSz.
- */
-int useWfuncs = 1;
 
-static this()
-{
-    // Win 95, 98, ME do not implement the W functions
-    // TODO: detect MSLU?
-    useWfuncs = (GetVersion() < 0x80000000);
-}
-
-
 /******************************************
  * Converts the UTF-8 string s into a null-terminated string in a Windows
  * 8-bit character set.
Index: phobos2/std/process.d
===================================================================
--- phobos2/std/process.d	(revision 209)
+++ phobos2/std/process.d	(working copy)
@@ -151,9 +151,10 @@
 
 Lerror:
     retval = getErrno;
+    char[80] buf = void;
     throw new Exception(
         "Cannot spawn " ~ toString(pathname) ~ "; "
-                      ~ toString(strerror(retval))
+                      ~ toString(strerror_r(retval, buf.ptr, buf.length))
                       ~ " [errno " ~ toString(retval) ~ "]");
 }   // _spawnvp
 private
Index: phobos2/std/math.d
===================================================================
--- phobos2/std/math.d	(revision 209)
+++ phobos2/std/math.d	(working copy)
@@ -84,7 +84,7 @@
 {
     this(string msg)
     {
-	super(msg ~ "not implemented");
+	super(msg ~ " not implemented");
     }
 }
 
@@ -905,6 +905,8 @@
  *	$(TR $(TD $(PLUSMN)$(INFIN)) $(TD $(PLUSMN)$(INFIN)) )
  *	$(TR $(TD $(PLUSMN)0.0)      $(TD $(PLUSMN)0.0) )
  *	)
+ *
+ * Note: Not supported on windows
  */
 real scalbn(real x, int n)
 {
@@ -1180,6 +1182,8 @@
 /***************************************
  * Rounds x to the nearest integer value, using the current rounding
  * mode.
+ *
+ * Note: Not supported on windows
  */
 long lrint(real x)
 {
@@ -1233,6 +1237,8 @@
  *
  * If the fractional part of x is exactly 0.5, the return value is rounded
  * away from zero.
+ *
+ * Note: Not supported on windows
  */
 long lround(real x)
 {
@@ -1286,6 +1292,8 @@
  *	$(TR $(TD anything)             $(TD $(PLUSMN)0.0)      $(TD $(NAN))          $(TD ?)   $(TD yes))
  *	$(TR $(TD != $(PLUSMN)$(INFIN)) $(TD $(PLUSMN)$(INFIN)) $(TD x)               $(TD ?)   $(TD no))
  *	)
+ *
+ * Note: remquo not supported on windows
  */
 real remainder(real x, real y) { return std.c.math.remainderl(x, y); }
 
@@ -1497,10 +1505,15 @@
  * the function result is infinite. The FE_INEXACT and FE_UNDERFLOW 
  * exceptions will be raised if the function value is subnormal, and x is 
  * not equal to y. 
+ *
+ * Note: real nextafter(real, real) not supported on windows
  */
 real nextafter(real x, real y)
 {
-    return std.c.math.nextafterl(x, y);
+    version (Windows)
+        throw new NotImplemented("nextafter");
+    else
+        return std.c.math.nextafterl(x, y);
 }
 
 /// ditto
@@ -1518,14 +1531,29 @@
 unittest
 {
     float a = 1;
+    assert(is(typeof(nextafter(a, a)) == float));
+    assert(nextafter(a, a.infinity) > a);
+
     double b = 2;
+    assert(is(typeof(nextafter(b, b)) == double));
+    assert(nextafter(b, b.infinity) > b);
+
+    // BUG 1772: temporarily disable real tests for nextafter
+    // with reals on windows until dmc's runtime supports them.
     real c = 3;
-    assert(is(typeof(nextafter(a, a)) == float));
-    assert(is(typeof(nextafter(b, b)) == double));
     assert(is(typeof(nextafter(c, c)) == real));
-    assert(nextafter(a, a.infinity) > a);
-    assert(nextafter(b, b.infinity) > b);
-    assert(nextafter(c, c.infinity) > c);
+    version(Windows) {
+        bool threw = false;
+        try {
+            nextafter(c, c.infinity);
+            assert(false, "shouldn't be reachable");
+        } catch (NotImplemented e) {
+            threw = true;
+        }
+        if (!threw) assert(false, "failed to throw");
+    } else {
+        assert(nextafter(c, c.infinity) > c);
+    }
 }
 
 //real nexttoward(real x, real y) { return std.c.math.nexttowardl(x, y); }
Index: phobos2/std/utf.d
===================================================================
--- phobos2/std/utf.d	(revision 209)
+++ phobos2/std/utf.d	(working copy)
@@ -412,7 +412,7 @@
     }
     body
     {
-	invariant(string) msg;
+	string msg;
 	dchar V;
 	size_t i = idx;
 	uint u = s[i];
Index: phobos2/std/conv.d
===================================================================
--- phobos2/std/conv.d	(revision 209)
+++ phobos2/std/conv.d	(working copy)
@@ -1370,7 +1370,11 @@
     // issue 1589
     version (Windows)
     {
-        if (icmp(s, "nan") == 0) return F.nan;
+        if (icmp(s, "nan") == 0)
+        {
+            s = s[3 .. $];
+            return F.nan;
+        }
     }
 
     // BUG: should set __locale_decpoint to "." for DMC
@@ -1988,7 +1992,6 @@
         // Display the original string in the error message.
     throw new ConvError("getComplexStrings() \"" ~ s ~ "\"" ~ " s1=\""
                              ~ s1 ~ "\"" ~ " s2=\"" ~ s2 ~ "\"");
-        return 0;
 }
 
 // feq() functions now used only in unittesting
Index: phobos2/std/regexp.d
===================================================================
--- phobos2/std/regexp.d	(revision 209)
+++ phobos2/std/regexp.d	(working copy)
@@ -3176,7 +3176,7 @@
     result.length = 0;
     for (size_t f = 0; f < format.length; f++)
     {
-	auto c = format[f];
+	char c = format[f];
       L1:
 	if (c != '$')
 	{
@@ -3286,7 +3286,7 @@
     result.length = 0;
     for (size_t i; i < format.length; i++)
     {
-	auto c = format[i];
+	char c = format[i];
 	switch (c)
 	{
 	    case '&':
Index: phobos2/std/getopt.d
===================================================================
--- phobos2/std/getopt.d	(revision 209)
+++ phobos2/std/getopt.d	(working copy)
@@ -439,9 +439,9 @@
 {
     if (!arg.length || arg[0] != optChar) return false;
     arg = arg[1 .. $];
-    final isLong = arg.length > 1 && arg[0] == optChar;
+    const isLong = arg.length > 1 && arg[0] == optChar;
     if (isLong) arg = arg[1 .. $];
-    final eqPos = find(arg, assignChar);
+    const eqPos = find(arg, assignChar);
     if (eqPos >= 0) {
         value = arg[eqPos + 1 .. $];
         arg = arg[0 .. eqPos];
@@ -450,7 +450,7 @@
     }
     //writeln("Arg: ", arg, " pattern: ", optPattern, " value: ", value);
     // Split the option
-    final variants = split(optPattern, "|");
+    const variants = split(optPattern, "|");
     foreach (v ; variants) {
         if (arg == v || !cfg.caseSensitive && toupper(arg) == toupper(v))
             return true;
Index: phobos2/std/socketstream.d
===================================================================
--- phobos2/std/socketstream.d	(revision 209)
+++ phobos2/std/socketstream.d	(working copy)
@@ -101,7 +101,7 @@
 	/**
 	 * Attempts to write the entire block, waiting if necessary.
 	 */
-	override size_t writeBlock(const(void)* _buffer, size_t size)
+	override size_t writeBlock(const void* _buffer, size_t size)
 	{
 	  ubyte* buffer = cast(ubyte*)_buffer;
 	  assertWriteable();
Index: phobos2/std/traits.d
===================================================================
--- phobos2/std/traits.d	(revision 209)
+++ phobos2/std/traits.d	(working copy)
@@ -534,6 +534,9 @@
   else static if (is(T == ushort)) alias ushort unsigned;
   else static if (is(T == uint)) alias uint unsigned;
   else static if (is(T == ulong)) alias ulong unsigned;
+  else static if (is(T == char)) alias char unsigned;
+  else static if (is(T == wchar)) alias wchar unsigned;
+  else static if (is(T == dchar)) alias dchar unsigned;
   else static if(is(T == enum)) 
        static if (T.sizeof == 1) alias ubyte unsigned;
        else static if (T.sizeof == 2) alias ushort unsigned;
@@ -549,3 +552,16 @@
     assert(is(U == uint));
 }
 
+/******
+ * Returns the mutable version of the type T.
+ */
+
+template Mutable(T)
+{
+    static if (is(T U == const(U)))
+	alias U Mutable;
+    else static if (is(T U == invariant(U)))
+	alias U Mutable;
+    else
+	alias T Mutable;
+}
Index: phobos2/std/string.d
===================================================================
--- phobos2/std/string.d	(revision 209)
+++ phobos2/std/string.d	(working copy)
@@ -72,8 +72,8 @@
 			   "abcdefghijklmnopqrstuvwxyz";	/// A..Za..z
 invariant char[6] whitespace = " \t\v\r\n\f";			/// ASCII whitespace
 
-const dchar LS = '\u2028';	/// UTF line separator
-const dchar PS = '\u2029';	/// UTF paragraph separator
+enum dchar LS = '\u2028';	/// UTF line separator
+enum dchar PS = '\u2029';	/// UTF paragraph separator
 
 /// Newline sequence for this system
 version (Windows)
@@ -1128,7 +1128,7 @@
  * string; use sep[] as the separator.
  */
 
-string join(in string[] words, in string sep)
+string join(string[] words, string sep)
 {
     char[] result;
 
Index: phobos2/std/stdio.d
===================================================================
--- phobos2/std/stdio.d	(revision 209)
+++ phobos2/std/stdio.d	(working copy)
@@ -112,7 +112,15 @@
     }
 
     this(uint errno)
-    {	const(char*) s = std.string.strerror(errno);
+    {
+	version (linux)
+	{   char[80] buf = void;
+	    auto s = std.string.strerror_r(errno, buf.ptr, buf.length);
+	}
+	else
+	{
+	    auto s = std.string.strerror(errno);
+	}
 	super(std.string.toString(s).idup);
     }
 
Index: phobos2/std/c/string.d
===================================================================
--- phobos2/std/c/string.d	(revision 209)
+++ phobos2/std/c/string.d	(working copy)
@@ -37,6 +37,7 @@
     alias __builtin_strcmp strcmp;	///
     alias __builtin_strcat strcat;	///
     alias __builtin_memcmp memcmp;	///
+    const(char)* strerror_r(int errnum, char* buf, size_t buflen);	///
 }
 else
 {
@@ -68,3 +69,9 @@
 {
     int memicmp(in char* s1, in char* s2, size_t n);	///
 }
+
+version (linux)
+{
+    const(char)* strerror_r(int errnum, char* buf, size_t buflen);	///
+}
+
Index: phobos2/std/c/windows/windows.d
===================================================================
--- phobos2/std/c/windows/windows.d	(revision 209)
+++ phobos2/std/c/windows/windows.d	(working copy)
@@ -251,8 +251,11 @@
     FILE_VOLUME_IS_COMPRESSED       = 0x00008000,  
 }
 
-const DWORD MAILSLOT_NO_MESSAGE = cast(DWORD)-1;
-const DWORD MAILSLOT_WAIT_FOREVER = cast(DWORD)-1; 
+enum
+{
+    DWORD MAILSLOT_NO_MESSAGE = cast(DWORD)-1,
+    DWORD MAILSLOT_WAIT_FOREVER = cast(DWORD)-1, 
+}
 
 enum : uint
 {
@@ -275,9 +278,12 @@
     TRUNCATE_EXISTING   = 5,
 }
 
-final HANDLE INVALID_HANDLE_VALUE = cast(HANDLE)-1;
-const DWORD INVALID_SET_FILE_POINTER = cast(DWORD)-1;
-const DWORD INVALID_FILE_SIZE = cast(DWORD)0xFFFFFFFF;
+enum
+{
+    HANDLE INVALID_HANDLE_VALUE = cast(HANDLE)-1,
+    DWORD INVALID_SET_FILE_POINTER = cast(DWORD)-1,
+    DWORD INVALID_FILE_SIZE = cast(DWORD)0xFFFFFFFF,
+}
 
 struct OVERLAPPED {
     DWORD   Internal;
Index: phobos2/std/c/stdio.d
===================================================================
--- phobos2/std/c/stdio.d	(revision 209)
+++ phobos2/std/c/stdio.d	(working copy)
@@ -35,23 +35,23 @@
 }
 else version (Win32)
 {
-    const int _NFILE = 60;	///
-    const int BUFSIZ = 0x4000;	///
-    const int EOF = -1;		///
-    const int FOPEN_MAX = 20;	///
-    const int FILENAME_MAX = 256;  /// 255 plus NULL
-    const int TMP_MAX = 32767;	///
-    const int _SYS_OPEN = 20;	///
-    const int SYS_OPEN = _SYS_OPEN;	///
-    const wchar WEOF = 0xFFFF;		///
+    int _NFILE = 60;	///
+    int BUFSIZ = 0x4000;	///
+    int EOF = -1;		///
+    int FOPEN_MAX = 20;	///
+    int FILENAME_MAX = 256;  /// 255 plus NULL
+    int TMP_MAX = 32767;	///
+    int _SYS_OPEN = 20;	///
+    int SYS_OPEN = _SYS_OPEN;	///
+    wchar WEOF = 0xFFFF;		///
 }
 else version (linux)
 {
-    const int EOF = -1;
-    const int FOPEN_MAX = 16;
-    const int FILENAME_MAX = 4095;
-    const int TMP_MAX = 238328;
-    const int L_tmpnam = 20;
+    int EOF = -1;
+    int FOPEN_MAX = 16;
+    int FILENAME_MAX = 4095;
+    int TMP_MAX = 238328;
+    int L_tmpnam = 20;
 }
 
 enum { SEEK_SET, SEEK_CUR, SEEK_END }
@@ -216,9 +216,9 @@
     {
  	static assert(libc.FILE_struct_size != 0);
 	extern FILE[3] __sF;
-	final FILE * stdin  = &__sF[0];
-	final FILE * stdout = &__sF[1];
-	final FILE * stderr = &__sF[2];
+	FILE * stdin  = &__sF[0];
+	FILE * stdout = &__sF[1];
+	FILE * stderr = &__sF[2];
     }
     else static if (size_t.sizeof == 8)
     {
Index: phobos2/std/typecons.d
===================================================================
--- phobos2/std/typecons.d	(revision 209)
+++ phobos2/std/typecons.d	(working copy)
@@ -216,7 +216,7 @@
             return "if (v == "~name~"."~T[0]~") return `"~T[0]~"`;\n"
                 ~enumPrinterImpl!(name, false, T[1 .. $]);
         else
-            return "";
+            return "return null;";
     }
 }
 
Index: phobos2/std/file.d
===================================================================
--- phobos2/std/file.d	(revision 209)
+++ phobos2/std/file.d	(working copy)
@@ -641,7 +641,7 @@
  * ----
  */
 
-string[] listdir(in string pathname, in string pattern)
+string[] listdir(string pathname, string pattern)
 {   string[] result;
     
     bool callback(DirEntry* de)
@@ -661,7 +661,7 @@
 
 /** Ditto */
 
-string[] listdir(in string pathname, RegExp r)
+string[] listdir(string pathname, RegExp r)
 {   string[] result;
     
     bool callback(DirEntry* de)
@@ -719,7 +719,7 @@
  * ----
  */
 
-void listdir(in string pathname, bool delegate(in string filename) callback)
+void listdir(in string pathname, bool delegate(string filename) callback)
 {
     bool listing(DirEntry* de)
     {
@@ -871,8 +871,6 @@
 
 alias std.c.unix.unix unix;
 
-extern (C) char* strerror(int);
-
 /***********************************
  */
 
@@ -892,7 +890,8 @@
     }
 
     this(string name, uint errno)
-    {	const(char*) s = strerror(errno);
+    {	char[80] buf = void;
+	auto s = strerror_r(errno, buf.ptr, buf.length);
 	this(name, std.string.toString(s).idup);
 	this.errno = errno;
     }
@@ -965,9 +964,8 @@
 void write(in string name, in void[] buffer)
 {
     int fd;
-    const(char*) namez;
 
-    namez = toStringz(name);
+    auto namez = toStringz(name);
     fd = unix.open(namez, O_CREAT | O_WRONLY | O_TRUNC, 0660);
     if (fd == -1)
         goto err;
@@ -1052,9 +1050,8 @@
     uint size;
     int fd;
     struct_stat statbuf;
-    const(char*) namez;
 
-    namez = toStringz(name);
+    auto namez = toStringz(name);
     //printf("file.getSize('%s')\n",namez);
     fd = unix.open(namez, O_RDONLY);
     if (fd == -1)
@@ -1094,9 +1091,8 @@
 uint getAttributes(in string name)
 {
     struct_stat statbuf;
-    const(char*) namez;
 
-    namez = toStringz(name);
+    auto namez = toStringz(name);
     if (unix.stat(namez, &statbuf))
     {
 	throw new FileException(name.idup, getErrno());
@@ -1323,9 +1319,8 @@
     {
 	int fd;
 	struct_stat statbuf;
-	const(char*) namez;
 
-	namez = toStringz(name);
+	auto namez = toStringz(name);
 	if (std.c.unix.unix.stat(namez, &statbuf))
 	{
 	    //printf("\tstat error, errno = %d\n",getErrno());
Index: phobos2/std/socket.d
===================================================================
--- phobos2/std/socket.d	(revision 209)
+++ phobos2/std/socket.d	(working copy)
@@ -108,12 +108,10 @@
 		{
 			if(errorCode > 0)
 			{
-				const(char)* cs;
-				size_t len;
+				char[80] buf;
+				auto cs = strerror_r(errorCode, buf.ptr, buf.length);
+				auto len = strlen(cs);
 				
-				cs = strerror(errorCode);
-				len = strlen(cs);
-				
 				if(cs[len - 1] == '\n')
 					len--;
 				if(cs[len - 1] == '\r')
Index: phobos2/std/format.d
===================================================================
--- phobos2/std/format.d	(revision 209)
+++ phobos2/std/format.d	(working copy)
@@ -511,7 +511,7 @@
 	uint base = 10;
 	int uc;
 	char[ulong.sizeof * 8] tmpbuf;	// long enough to print long in binary
-	const(char*) prefix = "";
+	const(char)* prefix = "";
 	string s;
 
 	void putstr(const char[] s)
@@ -2116,8 +2116,9 @@
  * Formats an integral number 'arg' according to 'f' and writes it to
  * 'w'.
  */ 
-private void formatIntegral(Writer, D)(ref Writer w, D arg, FormatInfo f)
+private void formatIntegral(Writer, D)(ref Writer w, D argx, FormatInfo f)
 {
+    Mutable!(D) arg = argx;
     if (f.spec == 'r')
     {
         // raw write, skip all else and write the thing
@@ -2182,7 +2183,7 @@
     {
         char buffer[64]; // 64 bits in base 2 at most
         uint i = buffer.length;
-        auto n = cast(unsigned!(D)) arg;
+        auto n = cast(unsigned!(Mutable!(D))) arg;
         do
         {
             --i;
@@ -2286,7 +2287,7 @@
     sprintfSpec[i] = 0;
     //writeln(sprintfSpec);
     char[512] buf;
-    final n = snprintf(buf.ptr, buf.length,
+    auto n = snprintf(buf.ptr, buf.length,
                        sprintfSpec.ptr,
                        f.width,
                        // negative precision is same as no precision specified
@@ -2452,7 +2453,7 @@
 void formattedWrite(Writer, F, A...)(ref Writer w, const(F)[] fmt, A args)
 {
     const len = args.length;
-    void function(ref Writer, const void*, FormatInfo) funs[len] = void;
+    void function(ref Writer, const(void)*, FormatInfo) funs[len] = void;
     const(void)* argsAddresses[len] = void;
     foreach (i, arg; args)
     {
Index: phobos2/win32.mak
===================================================================
--- phobos2/win32.mak	(revision 209)
+++ phobos2/win32.mak	(working copy)
@@ -123,7 +123,6 @@
 	$(DOC)\std_process.html \
 	$(DOC)\std_regexp.html \
 	$(DOC)\std_signals.html \
-	$(DOC)\std_slist.html \
 	$(DOC)\std_socket.html \
 	$(DOC)\std_socketstream.html \
 	$(DOC)\std_stdint.html \
@@ -165,7 +164,7 @@
 	std\cstream.d std\demangle.d std\cover.d std\bitarray.d \
 	std\signals.d std\cpuid.d std\typetuple.d std\traits.d std\bind.d \
 	std\metastrings.d std\hiddenfunc.d std\contracts.d std\getopt.d \
-	std\variant.d std\slist.d std\numeric.d std\bitmanip.d \
+	std\variant.d std\numeric.d std\bitmanip.d \
 	std\functional.d std\algorithm.d std\typecons.d
 
 SRC_STD_C= std\c\process.d std\c\stdlib.d std\c\time.d std\c\stdio.d \
@@ -792,9 +791,6 @@
 $(DOC)\std_signals.html : std.ddoc std\signals.d
 	$(DMD) -c -o- $(DFLAGS) -Df$(DOC)\std_signals.html std.ddoc std\signals.d
 
-$(DOC)\std_slist.html : std.ddoc std\slist.d
-	$(DMD) -c -o- $(DFLAGS) -Df$(DOC)\std_slist.html std.ddoc std\slist.d
-
 $(DOC)\std_socket.html : std.ddoc std\socket.d
 	$(DMD) -c -o- $(DFLAGS) -Df$(DOC)\std_socket.html std.ddoc std\socket.d
 
Index: phobos2/internal/object.d
===================================================================
--- phobos2/internal/object.d	(revision 209)
+++ phobos2/internal/object.d	(working copy)
@@ -913,9 +913,9 @@
 	    // A sorry hash algorithm.
 	    // Should use the one for strings.
 	    // BUG: relies on the GC not moving objects
-	    auto q = p;
+	    auto q = cast(const(ubyte)*)p;
 	    for (size_t i = 0; i < init.length; i++)
-	    {	h = h * 9 + *cast(ubyte*)q;
+	    {	h = h * 9 + *q;
 		q++;
 	    }
 	}
Index: dmd2/mtype.c
===================================================================
--- dmd2/mtype.c	(revision 209)
+++ dmd2/mtype.c	(working copy)
@@ -709,6 +709,18 @@
     return FALSE;
 }
 
+/**************************
+ * Given:
+ *	T a, b;
+ * Can we assign:
+ *	a = b;
+ * ?
+ */
+int Type::isAssignable()
+{
+    return TRUE;
+}
+
 int Type::checkBoolean()
 {
     return isscalar();
@@ -1729,9 +1741,14 @@
 MATCH TypeBasic::implicitConvTo(Type *to)
 {
     //printf("TypeBasic::implicitConvTo(%s) from %s\n", to->toChars(), toChars());
-    if (this == to || ty == to->ty)
+    if (this == to)
 	return MATCHexact;
 
+    if (ty == to->ty)
+    {
+	return (mod == to->mod) ? MATCHexact : MATCHconst;
+    }
+
     if (ty == Tvoid || to->ty == Tvoid)
 	return MATCHnomatch;
     if (1 || global.params.Dversion == 1)
@@ -2269,6 +2286,8 @@
 	    MATCH m = next->implicitConvTo(tsa->next);
 	    if (m >= MATCHconst)
 	    {
+		if (mod != to->mod)
+		    m = MATCHconst;
 		return m;
 	    }
 	}
@@ -2454,7 +2473,11 @@
 
 	MATCH m = next->constConv(ta->next);
 	if (m != MATCHnomatch)
+	{
+	    if (m == MATCHexact && mod != to->mod)
+		m = MATCHconst;
 	    return m;
+	}
 
 	/* Conversion of array of derived to array of base
 	 */
@@ -2773,7 +2796,11 @@
 
         MATCH m = next->constConv(tp->next);
         if (m != MATCHnomatch)
+	{
+	    if (m == MATCHexact && mod != to->mod)
+		m = MATCHconst;
             return m;
+	}
 
         /* Conversion of ptr to derived to ptr to base
          */
@@ -4199,6 +4226,7 @@
 
 Type *TypeEnum::semantic(Loc loc, Scope *sc)
 {
+    //printf("TypeEnum::semantic() %s\n", toChars());
     sym->semantic(sc);
     return merge();
 }
@@ -4248,8 +4276,6 @@
 {   char *name;
 
     name = sym->mangle();
-//    if (name[0] == '_' && name[1] == 'D')
-//	name += 2;
     Type::toDecoBuffer(buf, flag);
     buf->printf("%s", name);
 }
@@ -4265,28 +4291,18 @@
 
 Expression *TypeEnum::dotExp(Scope *sc, Expression *e, Identifier *ident)
 {
-    EnumMember *m;
-    Dsymbol *s;
-    Expression *em;
-
 #if LOGDOTEXP
     printf("TypeEnum::dotExp(e = '%s', ident = '%s') '%s'\n", e->toChars(), ident->toChars(), toChars());
 #endif
-    if (!sym->symtab)
-	goto Lfwd;
-    s = sym->symtab->lookup(ident);
+    Dsymbol *s = sym->search(e->loc, ident, 0);
     if (!s)
     {
 	return getProperty(e->loc, ident);
     }
-    m = s->isEnumMember();
-    em = m->value->copy();
+    EnumMember *m = s->isEnumMember();
+    Expression *em = m->value->copy();
     em->loc = e->loc;
     return em;
-
-Lfwd:
-    error(e->loc, "forward reference of %s.%s", toChars(), ident->toChars());
-    return new IntegerExp(0, 0, this);
 }
 
 Expression *TypeEnum::getProperty(Loc loc, Identifier *ident)
@@ -4294,27 +4310,23 @@
 
     if (ident == Id::max)
     {
-	if (!sym->symtab)
+	if (!sym->maxval)
 	    goto Lfwd;
-	e = new IntegerExp(0, sym->maxval, this);
+	e = sym->maxval;
     }
     else if (ident == Id::min)
     {
-	if (!sym->symtab)
+	if (!sym->minval)
 	    goto Lfwd;
-	e = new IntegerExp(0, sym->minval, this);
+	e = sym->minval;
     }
     else if (ident == Id::init)
     {
-	if (!sym->symtab)
-	    goto Lfwd;
 	e = defaultInit(loc);
     }
     else
     {
-	if (!sym->memtype)
-	    goto Lfwd;
-	e = sym->memtype->getProperty(loc, ident);
+	e = toBasetype()->getProperty(loc, ident);
     }
     return e;
 
@@ -4349,7 +4361,7 @@
 
     //printf("TypeEnum::implicitConvTo()\n");
     if (ty == to->ty && sym == ((TypeEnum *)to)->sym)
-	m = MATCHexact;		// exact match
+	m = (mod == to->mod) ? MATCHexact : MATCHconst;
     else if (sym->memtype->implicitConvTo(to))
 	m = MATCHconvert;	// match with conversions
     else
@@ -4374,14 +4386,18 @@
     printf("TypeEnum::defaultInit() '%s'\n", toChars());
 #endif
     // Initialize to first member of enum
-    Expression *e;
-    e = new IntegerExp(loc, sym->defaultval, this);
-    return e;
+    //printf("%s\n", sym->defaultval->type->toChars());
+    if (!sym->defaultval)
+    {
+	error(loc, "forward reference of %s.init", toChars());
+	return new IntegerExp(0, 0, this);
+    }
+    return sym->defaultval;
 }
 
 int TypeEnum::isZeroInit()
 {
-    return (sym->defaultval == 0);
+    return sym->defaultval->isBool(FALSE);
 }
 
 int TypeEnum::hasPointers()
@@ -4511,6 +4527,11 @@
     return sym->basetype->isscalar();
 }
 
+int TypeTypedef::isAssignable()
+{
+    return sym->basetype->isAssignable();
+}
+
 int TypeTypedef::checkBoolean()
 {
     return sym->basetype->checkBoolean();
@@ -4623,11 +4644,13 @@
 char *TypeStruct::toChars()
 {
     //printf("sym.parent: %s, deco = %s\n", sym->parent->toChars(), deco);
+    if (mod)
+	return Type::toChars();
     TemplateInstance *ti = sym->parent->isTemplateInstance();
     if (ti && ti->toAlias() == sym)
+    {
 	return ti->toChars();
-    if (mod)
-	return Type::toChars();
+    }
     return sym->toChars();
 }
 
@@ -4879,6 +4902,19 @@
     return FALSE;
 }
 
+int TypeStruct::isAssignable()
+{
+    /* If any of the fields are const or invariant,
+     * then one cannot assign this struct.
+     */
+    for (size_t i = 0; i < sym->fields.dim; i++)
+    {   VarDeclaration *v = (VarDeclaration *)sym->fields.data[i];
+	if (v->isConst() || v->isInvariant())
+	    return FALSE;
+    }
+    return TRUE;
+}
+
 int TypeStruct::hasPointers()
 {
     StructDeclaration *s = sym;
@@ -4901,7 +4937,15 @@
 
     //printf("TypeStruct::implicitConvTo()\n");
     if (ty == to->ty && sym == ((TypeStruct *)to)->sym)
-	m = MATCHexact;		// exact match
+    {	m = MATCHexact;		// exact match
+	if (mod != to->mod)
+	{
+	    if (to->mod == MODconst)
+		m = MATCHconst;
+	    else
+		m = MATCHnomatch;
+	}
+    }
     else
 	m = MATCHnomatch;	// no match
     return m;
@@ -5793,7 +5837,8 @@
 	mod = 0;
     type->toDecoBuffer(buf, mod);
 #else
-    type->toHeadMutable()->toDecoBuffer(buf, 0);
+    //type->toHeadMutable()->toDecoBuffer(buf, 0);
+    type->toDecoBuffer(buf, 0);
 #endif
 }
 
Index: dmd2/optimize.c
===================================================================
--- dmd2/optimize.c	(revision 209)
+++ dmd2/optimize.c	(working copy)
@@ -50,7 +50,7 @@
 {
     //printf("expandVar(result = %d, v = %s)\n", result, v ? v->toChars() : "null");
     Expression *e = NULL;
-    if (v && (v->isConst() || v->isInvariant()))
+    if (v && (v->isConst() || v->isInvariant() || v->storage_class & STCmanifest))
     {
 	Type *tb = v->type->toBasetype();
 	if (result & WANTinterpret ||
@@ -844,13 +844,14 @@
 {   Expression *e;
 
     //printf("CmpExp::optimize() %s\n", toChars());
-    e1 = e1->optimize(result);
-    e2 = e2->optimize(result);
-    if (e1->isConst() == 1 && e2->isConst() == 1)
-    {
-	e = Cmp(op, type, this->e1, this->e2);
-    }
-    else
+    e1 = e1->optimize(WANTvalue | (result & WANTinterpret));
+    e2 = e2->optimize(WANTvalue | (result & WANTinterpret));
+
+    Expression *e1 = fromConstInitializer(result, this->e1);
+    Expression *e2 = fromConstInitializer(result, this->e2);
+
+    e = Cmp(op, type, e1, e2);
+    if (e == EXP_CANT_INTERPRET)
 	e = this;
     return e;
 }
Index: dmd2/init.c
===================================================================
--- dmd2/init.c	(revision 209)
+++ dmd2/init.c	(working copy)
@@ -185,7 +185,7 @@
 		s = ad->search(loc, id, 0);
 		if (!s)
 		{
-		    error("'%s' is not a member of '%s'", id->toChars(), t->toChars());
+		    error(loc, "'%s' is not a member of '%s'", id->toChars(), t->toChars());
 		    continue;
 		}
 
@@ -582,7 +582,8 @@
     }
 
     Type *t = exp->type;
-    return t->ty == Tsarray ? t : t->toHeadMutable();
+    return t;
+    //return t->ty == Tsarray ? t : t->toHeadMutable();
 }
 
 Expression *ExpInitializer::toExpression()
Index: dmd2/mtype.h
===================================================================
--- dmd2/mtype.h	(revision 209)
+++ dmd2/mtype.h	(working copy)
@@ -233,6 +233,7 @@
     virtual int isunsigned();
     virtual int isauto();
     virtual int isString();
+    virtual int isAssignable();
     virtual int checkBoolean();	// if can be converted to boolean value
     virtual void checkDeprecated(Loc loc, Scope *sc);
     int isConst()	{ return mod == MODconst; }
@@ -601,6 +602,7 @@
     unsigned memalign(unsigned salign);
     Expression *defaultInit(Loc loc);
     int isZeroInit();
+    int isAssignable();
     int checkBoolean();
     dt_t **toDt(dt_t **pdt);
     MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes);
@@ -672,6 +674,7 @@
     int isscalar();
     int isunsigned();
     int checkBoolean();
+    int isAssignable();
     Type *toBasetype();
     MATCH implicitConvTo(Type *to);
     MATCH constConv(Type *to);
Index: dmd2/statement.c
===================================================================
--- dmd2/statement.c	(revision 209)
+++ dmd2/statement.c	(working copy)
@@ -1202,8 +1202,6 @@
 		    VarDeclaration *v = new VarDeclaration(loc, arg->type, arg->ident, ie);
 		    if (e->isConst())
 			v->storage_class |= STCconst;
-		    else
-			v->storage_class |= STCfinal;
 		    var = v;
 		}
 	    }
@@ -1282,14 +1280,14 @@
 
 		var = new VarDeclaration(loc, arg->type, arg->ident, NULL);
 		var->storage_class |= STCforeach;
-		var->storage_class |= arg->storageClass & (STCin | STCout | STCref | STCfinal | STCconst);
+		var->storage_class |= arg->storageClass & (STCin | STCout | STCref | STCconst | STCinvariant);
 		if (dim == 2 && i == 0)
 		{   key = var;
-		    var->storage_class |= STCfinal;
+		    //var->storage_class |= STCfinal;
 		}
 		else
-		{   if (!(arg->storageClass & STCref))
-			var->storage_class |= STCfinal;
+		{   //if (!(arg->storageClass & STCref))
+			//var->storage_class |= STCfinal;
 		    value = var;
 		}
 #if 1
Index: dmd2/toobj.c
===================================================================
--- dmd2/toobj.c	(revision 209)
+++ dmd2/toobj.c	(working copy)
@@ -1214,13 +1214,16 @@
 {
     //printf("EnumDeclaration::toObjFile('%s')\n", toChars());
 
+    if (isAnonymous())
+	return;
+
     if (global.params.symdebug)
 	toDebug();
 
     type->getTypeInfo(NULL);	// generate TypeInfo
 
     TypeEnum *tc = (TypeEnum *)type;
-    if (type->isZeroInit() || !tc->sym->defaultval)
+    if (!tc->sym->defaultval || type->isZeroInit())
 	;
     else
     {
@@ -1241,8 +1244,7 @@
 #if ELFOBJ // Burton
 	sinit->Sseg = CDATA;
 #endif /* ELFOBJ */
-	dtnbytes(&sinit->Sdt, tc->size(0), (char *)&tc->sym->defaultval);
-	//sinit->Sdt = tc->sym->init->toDt();
+	tc->sym->defaultval->toDt(&sinit->Sdt);
 	outdata(sinit);
     }
 }
Index: dmd2/attrib.c
===================================================================
--- dmd2/attrib.c	(revision 209)
+++ dmd2/attrib.c	(working copy)
@@ -324,10 +324,13 @@
     if (decl)
     {	unsigned stc_save = sc->stc;
 
-	if (stc & (STCauto | STCscope | STCstatic | STCextern))
-	    sc->stc &= ~(STCauto | STCscope | STCstatic | STCextern);
-	if (stc & (STCconst | STCinvariant))
-	    sc->stc &= ~(STCconst | STCinvariant);
+	/* These sets of storage classes are mutually exclusive,
+	 * so choose the innermost or most recent one.
+	 */
+	if (stc & (STCauto | STCscope | STCstatic | STCextern | STCmanifest))
+	    sc->stc &= ~(STCauto | STCscope | STCstatic | STCextern | STCmanifest);
+	if (stc & (STCconst | STCinvariant | STCmanifest))
+	    sc->stc &= ~(STCconst | STCinvariant | STCmanifest);
 	sc->stc |= stc;
 	for (unsigned i = 0; i < decl->dim; i++)
 	{
Index: dmd2/declaration.c
===================================================================
--- dmd2/declaration.c	(revision 209)
+++ dmd2/declaration.c	(working copy)
@@ -97,11 +97,6 @@
     if (sc->incontract && isParameter())
 	error(loc, "cannot modify parameter '%s' in contract", toChars());
 
-    VarDeclaration *v = isVarDeclaration();
-    if (v && v->canassign == 0 &&
-        (isConst() || isInvariant()) && !isCtorinit())
-	error(loc, "cannot modify const/invariant variable '%s'", toChars());
-
     if (isCtorinit())
     {	// It's only modifiable if inside the right constructor
 	Dsymbol *s = sc->func;
@@ -116,6 +111,7 @@
 		fd->toParent() == toParent()
 	       )
 	    {
+		VarDeclaration *v = isVarDeclaration();
 		assert(v);
 		v->ctorinit = 1;
 		//printf("setting ctorinit\n");
@@ -136,6 +132,24 @@
 	    break;
 	}
     }
+    else
+    {
+	VarDeclaration *v = isVarDeclaration();
+	if (v && v->canassign == 0)
+	{
+	    char *p = NULL;
+	    if (isConst())
+		p = "const";
+	    else if (isInvariant())
+		p = "invariant";
+	    else if (storage_class & STCmanifest)
+		p = "manifest constant";
+	    else if (!type->isAssignable())
+		p = "struct with immutable members";
+	    if (p)
+		error(loc, "cannot modify %s", p);
+	}
+    }
 }
 
 
@@ -766,12 +780,13 @@
 	if (!type->isInvariant())
 	    type = type->constOf();
     }
+    else if (type->isConst())
+	storage_class |= STCconst;
+    else if (type->isInvariant())
+	storage_class |= STCinvariant;
 
-    if (storage_class & (STCstatic | STCextern))
+    if (isSynchronized())
     {
-    }
-    else if (isSynchronized())
-    {
 	error("variable %s cannot be synchronized", toChars());
     }
     else if (isOverride())
@@ -782,9 +797,14 @@
     {
 	error("abstract cannot be applied to variable");
     }
-    else if (storage_class & STCtemplateparameter)
+    else if (storage_class & STCfinal)
     {
+	error("final cannot be applied to variable");
     }
+
+    if (storage_class & (STCstatic | STCextern | STCmanifest | STCtemplateparameter))
+    {
+    }
     else
     {
 	AggregateDeclaration *aad = sc->anonAgg;
@@ -833,9 +853,9 @@
 
     if (type->isauto() && !noauto)
     {
-	if (storage_class & (STCfield | STCout | STCref | STCstatic) || !fd)
+	if (storage_class & (STCfield | STCout | STCref | STCstatic | STCmanifest) || !fd)
 	{
-	    error("globals, statics, fields, ref and out parameters cannot be auto");
+	    error("globals, statics, fields, manifest constants, ref and out parameters cannot be auto");
 	}
 
 	if (!(storage_class & (STCauto | STCscope)))
@@ -852,6 +872,8 @@
 
     if (init)
 	storage_class |= STCinit;     // remember we had an explicit initializer
+    else if (storage_class & STCmanifest)
+	error("manifest constants must have initializers");
 
     if (!init && !sc->inunion && !isStatic() && fd &&
 	(!(storage_class & (STCfield | STCin | STCforeach | STCparameter)) || (storage_class & STCout)) &&
@@ -920,7 +942,7 @@
 	{
 	    // If local variable, use AssignExp to handle all the various
 	    // possibilities.
-	    if (fd && !isStatic() &&
+	    if (fd && !isStatic() && !(storage_class & STCmanifest) &&
 		!init->isVoidInitializer())
 	    {
 		Expression *e1;
@@ -983,7 +1005,7 @@
 		init = init->semantic(sc, type);
 	    }
 	}
-	else if (storage_class & (STCconst | STCinvariant) ||
+	else if (storage_class & (STCconst | STCinvariant | STCmanifest) ||
 		 type->isConst() || type->isInvariant())
 	{
 	    /* Because we may need the results of a const declaration in a
@@ -1083,6 +1105,8 @@
 
 void VarDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
 {
+    if (storage_class & STCmanifest)
+	buf->writestring("manifest ");
     if (storage_class & STCstatic)
 	buf->writestring("static ");
     if (storage_class & STCconst)
@@ -1129,7 +1153,8 @@
 
 void VarDeclaration::checkNestedReference(Scope *sc, Loc loc)
 {
-    if (parent && !isDataseg() && parent != sc->parent)
+    if (parent && !isDataseg() && parent != sc->parent &&
+	!(storage_class & STCmanifest))
     {
 	// The function that this variable is in
 	FuncDeclaration *fdv = toParent()->isFuncDeclaration();
@@ -1191,7 +1216,7 @@
 
 Expression *VarDeclaration::getConstInitializer()
 {
-    if ((isConst() || isInvariant()) &&
+    if ((isConst() || isInvariant() || storage_class & STCmanifest) &&
 	storage_class & STCinit)
     {
 	ExpInitializer *ei = getExpInitializer();
@@ -1208,6 +1233,7 @@
 
 int VarDeclaration::canTakeAddressOf()
 {
+#if 0
     /* Global variables and struct/class fields of the form:
      *	const int x = 3;
      * are not stored and hence cannot have their address taken.
@@ -1221,6 +1247,10 @@
     {
 	return 0;
     }
+#else
+    if (storage_class & STCmanifest)
+	return 0;
+#endif
     return 1;
 }
 
@@ -1236,6 +1266,8 @@
     printf("%x, %p, %p\n", storage_class & (STCstatic | STCconst), parent->isModule(), parent->isTemplateInstance());
     printf("parent = '%s'\n", parent->toChars());
 #endif
+    if (storage_class & STCmanifest)
+	return 0;
     Dsymbol *parent = this->toParent();
     if (!parent && !(storage_class & STCstatic))
     {	error("forward referenced");
Index: dmd2/declaration.h
===================================================================
--- dmd2/declaration.h	(revision 209)
+++ dmd2/declaration.h	(working copy)
@@ -70,6 +70,7 @@
     STCinvariant    = 0x100000,
     STCref	    = 0x200000,
     STCinit	    = 0x400000,		// has explicit initializer
+    STCmanifest	    = 0x800000,		// manifest constant
 };
 
 struct Match
@@ -265,6 +266,7 @@
     VarDeclaration *isVarDeclaration() { return (VarDeclaration *)this; }
 };
 
+
 /**************************************************************/
 
 // This is a shell around a back end symbol
Index: dmd2/constfold.c
===================================================================
--- dmd2/constfold.c	(revision 209)
+++ dmd2/constfold.c	(working copy)
@@ -886,7 +886,45 @@
     real_t r1;
     real_t r2;
 
-    if (e1->type->isreal())
+    //printf("Cmp(e1 = %s, e2 = %s)\n", e1->toChars(), e2->toChars());
+
+    if (e1->op == TOKstring && e2->op == TOKstring)
+    {	StringExp *es1 = (StringExp *)e1;
+	StringExp *es2 = (StringExp *)e2;
+	size_t sz = es1->sz;
+	assert(sz == es2->sz);
+
+	size_t len = es1->len;
+	if (es2->len < len)
+	    len = es2->len;
+
+	int cmp = memcmp(es1->string, es2->string, sz * len);
+	if (cmp == 0)
+	    cmp = es1->len - es2->len;
+
+	switch (op)
+	{
+	    case TOKlt:	n = cmp <  0;	break;
+	    case TOKle:	n = cmp <= 0;	break;
+	    case TOKgt:	n = cmp >  0;	break;
+	    case TOKge:	n = cmp >= 0;	break;
+
+	    case TOKleg:   n = 1;		break;
+	    case TOKlg:	   n = cmp != 0;	break;
+	    case TOKunord: n = 0;		break;
+	    case TOKue:	   n = cmp == 0;	break;
+	    case TOKug:	   n = cmp >  0;	break;
+	    case TOKuge:   n = cmp >= 0;	break;
+	    case TOKul:	   n = cmp <  0;	break;
+	    case TOKule:   n = cmp <= 0;	break;
+
+	    default:
+		assert(0);
+	}
+    }
+    else if (e1->isConst() != 1 || e2->isConst() != 1)
+	return EXP_CANT_INTERPRET;
+    else if (e1->type->isreal())
     {
 	r1 = e1->toReal();
 	r2 = e2->toReal();
Index: dmd2/expression.c
===================================================================
--- dmd2/expression.c	(revision 209)
+++ dmd2/expression.c	(working copy)
@@ -746,6 +746,7 @@
 	dump(0);
 	halt();
 #endif
+	type = Type::tint32;
     }
 }
 
@@ -829,7 +830,7 @@
     //printf("Expression::modifiableLvalue() %s, type = %s\n", toChars(), type->toChars());
 
     // See if this expression is a modifiable lvalue (i.e. not const)
-    if (type && !type->isMutable())
+    if (type && (!type->isMutable() || !type->isAssignable()))
 	error("%s is not mutable", e->toChars());
 
     return toLvalue(sc, e);
@@ -1150,7 +1151,8 @@
 	    type = Type::tint32;
     }
     else
-    {	type = type->semantic(loc, sc);
+    {	if (!type->deco)
+	    type = type->semantic(loc, sc);
     }
     return this;
 }
@@ -5180,11 +5182,15 @@
 	}
     }
     else
-    {	Type *t1 = e1->type->toBasetype();
+    {
+	Type *t1 = e1->type->toBasetype();
 
 	if (!t1->isMutable() ||
 	    (t1->ty == Tpointer && !t1->nextOf()->isMutable()) ||
-	    !var->type->isMutable())
+	    !var->type->isMutable() ||
+	    !var->type->isAssignable() ||
+	    var->storage_class & STCmanifest
+	   )
 	    error("cannot modify const/invariant %s", toChars());
     }
     return this;
@@ -5747,7 +5753,7 @@
 		else
 		{
 		    if (tthis->mod != 0)
-		    {	//printf("test1: mod = %x\n", tthis->mod);
+		    {	//printf("mod = %x\n", tthis->mod);
 			error("%s can only be called on a mutable object, not %s", e1->toChars(), tthis->toChars());
 		    }
 		}
@@ -8006,7 +8012,8 @@
 	Type *tb = type->toBasetype();
 	if (tb->ty == Tsarray)
 	    type = tb->nextOf()->arrayOf();
-	if (type->ty == Tarray && tb1->nextOf()->mod != tb2->nextOf()->mod)
+	if (type->ty == Tarray && tb1->nextOf() && tb2->nextOf() &&
+	    tb1->nextOf()->mod != tb2->nextOf()->mod)
 	    type = type->nextOf()->toHeadMutable()->arrayOf();
 #if 0
 	e1->type->print();
@@ -8020,12 +8027,6 @@
 	    e = optimize(WANTvalue);
 	else if ((t1->ty == Tarray || t1->ty == Tsarray) &&
 		 (t2->ty == Tarray || t2->ty == Tsarray))
-#if 0
-	else if ((e1->type->implicitConvTo(e2->type) >= MATCHconst ||
-		  e2->type->implicitConvTo(e1->type) >= MATCHconst) &&
-		(e1->type->toBasetype()->ty == Tarray ||
-		 e1->type->toBasetype()->ty == Tsarray))
-#endif
 	{
 	    e = this;
 	}
@@ -8621,6 +8622,7 @@
 #endif
     else
 	e = this;
+    //printf("CmpExp: %s\n", e->toChars());
     return e;
 }
 
Index: dmd2/mars.c
===================================================================
--- dmd2/mars.c	(revision 209)
+++ dmd2/mars.c	(working copy)
@@ -66,7 +66,7 @@
 
     copyright = "Copyright (c) 1999-2007 by Digital Mars";
     written = "written by Walter Bright";
-    version = "v2.008";
+    version = "v2.009";
     global.structalign = 8;
 
     memset(&params, 0, sizeof(Param));
Index: dmd2/func.c
===================================================================
--- dmd2/func.c	(revision 209)
+++ dmd2/func.c	(working copy)
@@ -1360,6 +1360,16 @@
     if (!f)
 	return FALSE;
 
+#if 0
+    /* Disable this check because:
+     *	const void foo();
+     * semantic() isn't run yet on foo(), so the const hasn't been
+     * applied yet.
+     */
+    if (type)
+    {   printf("type = %s\n", type->toChars());
+	printf("f->type = %s\n", f->type->toChars());
+    }
     if (type && f->type &&	// can be NULL for overloaded constructors
 	f->type->covariant(type) &&
 	f->type->mod == type->mod &&
@@ -1368,6 +1378,7 @@
 	//printf("\tfalse: conflict %s\n", kind());
 	return FALSE;
     }
+#endif
 
     if (overnext)
 	return overnext->overloadInsert(f);
Index: dmd2/enum.c
===================================================================
--- dmd2/enum.c	(revision 209)
+++ dmd2/enum.c	(working copy)
@@ -1,5 +1,5 @@
 
-// Copyright (c) 1999-2006 by Digital Mars
+// Copyright (c) 1999-2007 by Digital Mars
 // All Rights Reserved
 // written by Walter Bright
 // http://www.digitalmars.com
@@ -20,6 +20,9 @@
 #include "enum.h"
 #include "mtype.h"
 #include "scope.h"
+#include "id.h"
+#include "expression.h"
+#include "module.h"
 
 /********************************* EnumDeclaration ****************************/
 
@@ -29,10 +32,11 @@
     this->loc = loc;
     type = new TypeEnum(this);
     this->memtype = memtype;
-    maxval = 0;
-    minval = 0;
-    defaultval = 0;
+    maxval = NULL;
+    minval = NULL;
+    defaultval = NULL;
     sinit = NULL;
+    scope = NULL;
     attributes = NULL;
 }
 
@@ -54,50 +58,84 @@
 }
 
 void EnumDeclaration::semantic(Scope *sc)
-{   int i;
-    uinteger_t number;
+{
     Type *t;
     Scope *sce;
 
-    //printf("EnumDeclaration::semantic(sd = %p, '%s')\n", sc->scopesym, sc->scopesym->toChars());
-    if (symtab)			// if already done
+    //printf("EnumDeclaration::semantic(sd = %p, '%s') %s\n", sc->scopesym, sc->scopesym->toChars(), toChars());
+    //printf("EnumDeclaration::semantic() %s\n", toChars());
+    if (!members)		// enum ident;
 	return;
-    if (!memtype)
-	memtype = Type::tint32;
-    parent = sc->scopesym;
     if (attributes)
 	attributes->append(sc->attributes);
     else
 	attributes = sc->attributes;
-    memtype = memtype->semantic(loc, sc);
 
-    /* Check to see if memtype is forward referenced
+    if (!memtype && !isAnonymous())
+    {	// Set memtype if we can to reduce fwd reference errors
+	memtype = Type::tint32;	// case 1)  enum ident { ... }
+    }
+
+    if (symtab)			// if already done
+    {	if (!scope)
+	    return;		// semantic() already completed
+    }
+    else
+	symtab = new DsymbolTable();
+
+    Scope *scx = NULL;
+    if (scope)
+    {   sc = scope;
+        scx = scope;            // save so we don't make redundant copies
+        scope = NULL;
+    }
+
+    parent = sc->parent;
+
+    /* The separate, and distinct, cases are:
+     *  1. enum { ... }
+     *  2. enum : memtype { ... }
+     *  3. enum ident { ... }
+     *  4. enum ident : memtype { ... }
      */
-    if (memtype->ty == Tenum)
-    {	EnumDeclaration *sym = (EnumDeclaration *)memtype->toDsymbol(sc);
-	if (!sym->memtype)
-	{
-	    error("base enum %s is forward referenced", sym->toChars());
+
+    if (memtype)
+    {
+	memtype = memtype->semantic(loc, sc);
+
+	/* Check to see if memtype is forward referenced
+	 */
+	if (memtype->ty == Tenum)
+	{   EnumDeclaration *sym = (EnumDeclaration *)memtype->toDsymbol(sc);
+	    if (!sym->memtype || !sym->members || !sym->symtab || sym->scope)
+	    {	// memtype is forward referenced, so try again later
+		scope = scx ? scx : new Scope(*sc);
+		scope->setNoFree();
+		scope->module->addDeferredSemantic(this);
+		printf("\tdeferring %s\n", toChars());
+		return;
+	    }
+	}
+#if 0	// Decided to abandon this restriction for D 2.0
+	if (!memtype->isintegral())
+	{   error("base type must be of integral type, not %s", memtype->toChars());
 	    memtype = Type::tint32;
 	}
+#endif
     }
 
-    if (!memtype->isintegral())
-    {	error("base type must be of integral type, not %s", memtype->toChars());
-	memtype = Type::tint32;
+    type = type->semantic(loc, sc);
+    if (isAnonymous())
+    	sce = sc;
+    else
+    {	sce = sc->push(this);
+	sce->parent = this;
     }
-
-    t = isAnonymous() ? memtype : type;
-    symtab = new DsymbolTable();
-    sce = sc->push(this);
-    sce->parent = this;
-    number = 0;
-    if (!members)		// enum ident;
-	return;
     if (members->dim == 0)
 	error("enum %s must have at least one member", toChars());
     int first = 1;
-    for (i = 0; i < members->dim; i++)
+    Expression *elast = NULL;
+    for (int i = 0; i < members->dim; i++)
     {
 	EnumMember *em = ((Dsymbol *)members->data[i])->isEnumMember();
 	Expression *e;
@@ -108,84 +146,73 @@
 	     */
 	    continue;
 
-	//printf("Enum member '%s'\n",em->toChars());
+	//printf("  Enum member '%s'\n",em->toChars());
+	if (em->type)
+	    em->type = em->type->semantic(em->loc, sce);
 	e = em->value;
 	if (e)
 	{
 	    assert(e->dyncast() == DYNCAST_EXPRESSION);
 	    e = e->semantic(sce);
 	    e = e->optimize(WANTvalue | WANTinterpret);
-	    // Need to copy it because we're going to change the type
-	    e = e->copy();
-	    e = e->implicitCastTo(sc, memtype);
+	    if (memtype)
+	    {
+		e = e->implicitCastTo(sce, memtype);
+		e = e->optimize(WANTvalue | WANTinterpret);
+		if (!isAnonymous())
+		    e = e->castTo(sce, type);
+		t = memtype;
+	    }
+	    else if (em->type)
+	    {
+		e = e->implicitCastTo(sce, em->type);
+		e = e->optimize(WANTvalue | WANTinterpret);
+		assert(isAnonymous());
+		t = e->type;
+	    }
+	    else
+		t = e->type;
+	}
+	else if (first)
+	{
+	    if (memtype)
+		t = memtype;
+	    else if (em->type)
+		t = em->type;
+	    else
+		t = Type::tint32;
+	    e = new IntegerExp(em->loc, 0, Type::tint32);
+	    e = e->implicitCastTo(sce, t);
 	    e = e->optimize(WANTvalue | WANTinterpret);
-	    number = e->toInteger();
-	    e->type = t;
+	    if (!isAnonymous())
+		e = e->castTo(sce, type);
 	}
 	else
-	{   // Default is the previous number plus 1
+	{
+	    // Set value to (elast + 1).
+	    // But first check that (elast != t.max)
+	    assert(elast);
+	    e = new EqualExp(TOKequal, em->loc, elast, t->getProperty(0, Id::max));
+	    e = e->semantic(sce);
+	    e = e->optimize(WANTvalue | WANTinterpret);
+	    if (e->toInteger())
+		error("overflow of enum value %s", elast->toChars());
 
-	    // Check for overflow
-	    if (!first)
-	    {
-		switch (t->toBasetype()->ty)
-		{
-		    case Tbool:
-			if (number == 2)	goto Loverflow;
-			break;
-
-		    case Tint8:
-			if (number == 128) goto Loverflow;
-			break;
-
-		    case Tchar:
-		    case Tuns8:
-			if (number == 256) goto Loverflow;
-			break;
-
-		    case Tint16:
-			if (number == 0x8000) goto Loverflow;
-			break;
-
-		    case Twchar:
-		    case Tuns16:
-			if (number == 0x10000) goto Loverflow;
-			break;
-
-		    case Tint32:
-			if (number == 0x80000000) goto Loverflow;
-			break;
-
-		    case Tdchar:
-		    case Tuns32:
-			if (number == 0x100000000LL) goto Loverflow;
-			break;
-
-		    case Tint64:
-			if (number == 0x8000000000000000LL) goto Loverflow;
-			break;
-
-		    case Tuns64:
-			if (number == 0) goto Loverflow;
-			break;
-
-		    Loverflow:
-			error("overflow of enum value");
-			break;
-
-		    default:
-			assert(0);
-		}
-	    }
-	    e = new IntegerExp(em->loc, number, t);
+	    // Now set e to (elast + 1)
+	    e = new AddExp(em->loc, elast, new IntegerExp(em->loc, 1, Type::tint32));
+	    e = e->semantic(sce);
+	    e = e->castTo(sce, elast->type);
+	    e = e->optimize(WANTvalue | WANTinterpret);
 	}
+	elast = e;
 	em->value = e;
 
 	// Add to symbol table only after evaluating 'value'
 	if (isAnonymous())
 	{
-	    //sce->enclosing->insert(em);
-	    for (Scope *scx = sce->enclosing; scx; scx = scx->enclosing)
+	    /* Anonymous enum members get added to enclosing scope.
+	     */
+	    for (Scope *scx = sce; scx; scx = scx->enclosing)
 	    {
 		if (scx->scopesym)
 		{
@@ -199,32 +226,47 @@
 	else
 	    em->addMember(sc, this, 1);
 
-	if (first)
-	{   first = 0;
-	    defaultval = number;
-	    minval = number;
-	    maxval = number;
-	}
-	else if (memtype->isunsigned())
+	/* Compute .min, .max and .default values.
+	 * If enum doesn't have a name, we can never identify the enum type,
+	 * so there is no purpose for a .min, .max or .default
+	 */
+	if (!isAnonymous())
 	{
-	    if (number < minval)
-		minval = number;
-	    if (number > maxval)
-		maxval = number;
+	    if (first)
+	    {	defaultval = e;
+		minval = e;
+		maxval = e;
+	    }
+	    else
+	    {	Expression *ec;
+
+		/* In order to work successfully with UDTs,
+		 * build expressions to do the comparisons,
+		 * and let the semantic analyzer and constant
+		 * folder give us the result.
+		 */
+
+		// Compute if(e < minval)
+		ec = new CmpExp(TOKlt, em->loc, e, minval);
+		ec = ec->semantic(sce);
+		ec = ec->optimize(WANTvalue | WANTinterpret);
+		if (ec->toInteger())
+		    minval = e;
+
+		ec = new CmpExp(TOKgt, em->loc, e, maxval);
+		ec = ec->semantic(sce);
+		ec = ec->optimize(WANTvalue | WANTinterpret);
+		if (ec->toInteger())
+		    maxval = e;
+	    }
 	}
-	else
-	{
-	    if ((sinteger_t)number < (sinteger_t)minval)
-		minval = number;
-	    if ((sinteger_t)number > (sinteger_t)maxval)
-		maxval = number;
-	}
-
-	number++;
+	first = 0;
     }
     //printf("defaultval = %lld\n", defaultval);
 
-    sce->pop();
+    //if (defaultval) printf("defaultval: %s %s\n", defaultval->toChars(), defaultval->type->toChars());
+    if (sc != sce)
+	sce->pop();
     //members->print();
 }
 
@@ -281,12 +323,30 @@
     return "enum";
 }
 
+Dsymbol *EnumDeclaration::search(Loc loc, Identifier *ident, int flags)
+{
+    //printf("%s.EnumDeclaration::search('%s')\n", toChars(), ident->toChars());
+    if (scope)
+	// Try one last time to resolve this enum
+        semantic(scope);
+
+    if (!members || !symtab || scope)
+    {   error("is forward referenced when looking for '%s'", ident->toChars());
+        //*(char*)0=0;
+        return NULL;
+    }
+
+    Dsymbol *s = ScopeDsymbol::search(loc, ident, flags);
+    return s;
+}
+
 /********************************* EnumMember ****************************/
 
-EnumMember::EnumMember(Loc loc, Identifier *id, Expression *value)
+EnumMember::EnumMember(Loc loc, Identifier *id, Expression *value, Type *type)
     : Dsymbol(id)
 {
     this->value = value;
+    this->type = type;
     this->loc = loc;
 }
 
@@ -296,20 +356,28 @@
     if (value)
 	e = value->syntaxCopy();
 
+    Type *t = NULL;
+    if (type)
+	t = type->syntaxCopy();
+
     EnumMember *em;
     if (s)
     {	em = (EnumMember *)s;
 	em->loc = loc;
 	em->value = e;
+	em->type = t;
     }
     else
-	em = new EnumMember(loc, ident, e);
+	em = new EnumMember(loc, ident, e, t);
     return em;
 }
 
 void EnumMember::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
 {
-    buf->writestring(ident->toChars());
+    if (type)
+	type->toCBuffer(buf, ident, hgs);
+    else
+	buf->writestring(ident->toChars());
     if (value)
     {
 	buf->writestring(" = ");
Index: dmd2/enum.h
===================================================================
--- dmd2/enum.h	(revision 209)
+++ dmd2/enum.h	(working copy)
@@ -33,14 +33,18 @@
 
 
 struct EnumDeclaration : ScopeDsymbol
-{
+{   /* enum ident : memtype { ... }
+     */
     Type *type;			// the TypeEnum
     Type *memtype;		// type of the members
-    integer_t maxval;
-    integer_t minval;
-    integer_t defaultval;	// default initializer
     Expressions * attributes; // GCC decl/type attributes
 
+    Expression *maxval;
+    Expression *minval;
+    Expression *defaultval;	// default initializer
+
+    Scope *scope;		// !=NULL means context to use
+
     EnumDeclaration(Loc loc, Identifier *id, Type *memtype);
     Dsymbol *syntaxCopy(Dsymbol *s);
     void semantic(Scope *sc);
@@ -48,6 +52,7 @@
     void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
     Type *getType();
     char *kind();
+    Dsymbol *search(Loc, Identifier *ident, int flags);
 
     void emitComment(Scope *sc);
     void toDocBuffer(OutBuffer *buf);
@@ -66,8 +71,9 @@
 struct EnumMember : Dsymbol
 {
     Expression *value;
+    Type *type;
 
-    EnumMember(Loc loc, Identifier *id, Expression *value);
+    EnumMember(Loc loc, Identifier *id, Expression *value, Type *type);
     Dsymbol *syntaxCopy(Dsymbol *s);
     void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
     char *kind();
Index: dmd2/template.c
===================================================================
--- dmd2/template.c	(revision 209)
+++ dmd2/template.c	(working copy)
@@ -839,7 +839,8 @@
 	    printf("\tfparam->type = %s\n", fparam->type->toChars());
 #endif
 
-	    m = farg->type->toHeadMutable()->deduceType(scope, fparam->type, parameters, &dedtypes);
+	    //m = farg->type->toHeadMutable()->deduceType(scope, fparam->type, parameters, &dedtypes);
+	    m = farg->type->deduceType(scope, fparam->type, parameters, &dedtypes);
 	    //printf("\tdeduceType m = %d\n", m);
 
 	    /* If no match, see if there's a conversion to a delegate
@@ -968,7 +969,7 @@
 	assert(tvp);
 
 	VarDeclaration *v = new VarDeclaration(loc, tvp->valType, tp->ident, init);
-	v->storage_class = STCstatic | STCconst;
+	v->storage_class = STCmanifest;
 	s = v;
     }
     else if (va)
@@ -1982,8 +1983,8 @@
 	/* This is so that:
 	 *   template Foo(T), Foo!(const int), => ta == int
 	 */
-	if (!(flags & 1))
-	    ta = ta->toHeadMutable();
+//	if (!(flags & 1))
+//	    ta = ta->toHeadMutable();
 
 	if (t)
 	{   // Must match already deduced type
@@ -2439,12 +2440,12 @@
 	e = e->semantic(sc);
 	e = e->implicitCastTo(sc, valType);
 	e = e->optimize(WANTvalue | WANTinterpret);
-	e->type = e->type->toHeadMutable();
+	//e->type = e->type->toHeadMutable();
 
 	ei = ei->syntaxCopy();
 	ei = ei->semantic(sc);
 	ei = ei->optimize(WANTvalue | WANTinterpret);
-	ei->type = ei->type->toHeadMutable();
+	//ei->type = ei->type->toHeadMutable();
 	//printf("\tei: %s, %s\n", ei->toChars(), ei->type->toChars());
 	//printf("\te : %s, %s\n", e->toChars(), e->type->toChars());
 	if (!ei->equals(e))
@@ -2464,7 +2465,7 @@
     //printf("vt = %s\n", vt->toChars());
     if (ei->type)
     {
-	ei->type = ei->type->toHeadMutable();
+	//ei->type = ei->type->toHeadMutable();
 	m = (MATCH)ei->implicitConvTo(vt);
 	//printf("m: %d\n", m);
 	if (!m)
@@ -2474,7 +2475,7 @@
 
     init = new ExpInitializer(loc, ei);
     sparam = new VarDeclaration(loc, vt, ident, init);
-    sparam->storage_class = STCstatic | STCconst;
+    sparam->storage_class = STCmanifest;
     *psparam = sparam;
     return m;
 
@@ -3580,7 +3581,8 @@
 #if 1
 	    /* Use deco that matches what it would be for a function parameter
 	     */
-	    buf.writestring(ea->type->toHeadMutable()->deco);
+	    //buf.writestring(ea->type->toHeadMutable()->deco);
+	    buf.writestring(ea->type->deco);
 #else
 	    // Use type of parameter, not type of argument
 	    TemplateParameter *tp = (TemplateParameter *)tempdecl->parameters->data[i];
Index: dmd2/mangle.c
===================================================================
--- dmd2/mangle.c	(revision 209)
+++ dmd2/mangle.c	(working copy)
@@ -162,6 +162,7 @@
 	return Declaration::mangle();
     }
 
+
 char *StructDeclaration::mangle()
 {
     //printf("StructDeclaration::mangle() '%s'\n", toChars());
Index: dmd2/dsymbol.c
===================================================================
--- dmd2/dsymbol.c	(revision 209)
+++ dmd2/dsymbol.c	(working copy)
@@ -808,6 +808,7 @@
 	    s2->toPrettyChars(),
 	    s2->locToChars());
     }
+halt();
 }
 
 Dsymbol *ScopeDsymbol::nameCollision(Dsymbol *s)
Index: dmd2/typinf.c
===================================================================
--- dmd2/typinf.c	(revision 209)
+++ dmd2/typinf.c	(working copy)
@@ -310,8 +310,12 @@
      *	void[] m_init;
      */
 
-    sd->memtype->getTypeInfo(NULL);
-    dtxoff(pdt, sd->memtype->vtinfo->toSymbol(), 0, TYnptr);	// TypeInfo for enum members
+    if (sd->memtype)
+    {	sd->memtype->getTypeInfo(NULL);
+	dtxoff(pdt, sd->memtype->vtinfo->toSymbol(), 0, TYnptr);	// TypeInfo for enum members
+    }
+    else
+	dtdword(pdt, 0);
 
     char *name = sd->toPrettyChars();
     size_t namelen = strlen(name);
@@ -319,7 +323,7 @@
     dtabytes(pdt, TYnptr, 0, namelen + 1, name);
 
     // void[] init;
-    if (tinfo->isZeroInit() || !sd->defaultval)
+    if (!sd->defaultval || tinfo->isZeroInit())
     {	// 0 initializer, or the same as the base type
 	dtdword(pdt, 0);	// init.length
 	dtdword(pdt, 0);	// init.ptr
Index: dmd2/parse.c
===================================================================
--- dmd2/parse.c	(revision 209)
+++ dmd2/parse.c	(working copy)
@@ -145,8 +145,25 @@
 	switch (token.value)
 	{
 	    case TOKenum:
-		s = parseEnum();
+	    {	/* Determine if this is a manifest constant declaration,
+		 * or a conventional enum.
+		 */
+		Token *t = peek(&token);
+		if (t->value == TOKlcurly || t->value == TOKcolon)
+		    s = parseEnum();
+		else if (t->value != TOKidentifier)
+		    goto Ldeclaration;
+		else
+		{
+		    t = peek(t);
+		    if (t->value == TOKlcurly || t->value == TOKcolon ||
+			t->value == TOKsemicolon)
+			s = parseEnum();
+		    else
+			goto Ldeclaration;
+		}
 		break;
+	    }
 
 	    case TOKstruct:
 	    case TOKunion:
@@ -276,13 +293,14 @@
 	    case TOKabstract:	  stc = STCabstract;	 goto Lstc;
 	    case TOKsynchronized: stc = STCsynchronized; goto Lstc;
 	    case TOKdeprecated:   stc = STCdeprecated;	 goto Lstc;
+	    //case TOKmanifest:	  stc = STCmanifest;	 goto Lstc;
 
 	    Lstc:
 		if (storageClass & stc)
 		    error("redundant storage class %s", Token::toChars(token.value));
 		{
 		unsigned u = storageClass | stc;
-		u &= STCconst | STCinvariant | STCfinal;
+		u &= STCconst | STCinvariant | STCmanifest;
 		if (u & (u - 1))
 		    error("conflicting storage class %s", Token::toChars(token.value));
 		}
@@ -308,6 +326,7 @@
 		    case TOKabstract:	  stc = STCabstract;	 goto Lstc;
 		    case TOKsynchronized: stc = STCsynchronized; goto Lstc;
 		    case TOKdeprecated:   stc = STCdeprecated;	 goto Lstc;
+		    //case TOKmanifest:	  stc = STCmanifest;	 goto Lstc;
 		    default:
 			break;
 		}
@@ -1043,7 +1062,7 @@
 EnumDeclaration *Parser::parseEnum()
 {   EnumDeclaration *e;
     Identifier *id;
-    Type *t;
+    Type *memtype;
     Loc loc = this->loc;
 
     //printf("Parser::parseEnum()\n");
@@ -1058,12 +1077,13 @@
     if (token.value == TOKcolon)
     {
 	nextToken();
-	t = parseBasicType();
+	memtype = parseBasicType();
+	memtype = parseDeclarator(memtype, NULL, NULL);
     }
     else
-	t = NULL;
+	memtype = NULL;
 
-    e = new EnumDeclaration(loc, id, t);
+    e = new EnumDeclaration(loc, id, memtype);
     if (token.value == TOKsemicolon && id)
  	nextToken();
     else if (token.value == TOKlcurly)
@@ -1074,42 +1094,61 @@
 	unsigned char *comment = token.blockComment;
 	while (token.value != TOKrcurly)
 	{
-	    if (token.value == TOKidentifier)
-	    {	EnumMember *em;
-		Expression *value;
-		Identifier *ident;
+	    /* Can take the following forms:
+	     *	1. ident
+	     *	2. ident = value
+	     *	3. type ident = value
+	     */
 
-		loc = this->loc;
+	    loc = this->loc;
+
+	    Type *type = NULL;
+	    Identifier *ident;
+	    Token *tp = peek(&token);
+	    if (token.value == TOKidentifier &&
+		(tp->value == TOKassign || tp->value == TOKcomma || tp->value == TOKrcurly))
+	    {
 		ident = token.ident;
-		value = NULL;
+		type = NULL;
 		nextToken();
-		if (token.value == TOKassign)
-		{
-		    nextToken();
-		    value = parseAssignExp();
-		}
-		em = new EnumMember(loc, ident, value);
-		e->members->push(em);
-		if (token.value == TOKrcurly)
-		    ;
-		else
-		{   addComment(em, comment);
-		    comment = NULL;
-		    check(TOKcomma);
-		}
-		addComment(em, comment);
-		comment = token.blockComment;
 	    }
 	    else
-	    {	error("enum member expected");
+	    {
+		type = parseType(&ident, NULL);
+		if (id || memtype)
+		    error("type only allowed if anonymous enum and no enum type");
+	    }
+
+	    Expression *value;
+	    if (token.value == TOKassign)
+	    {
 		nextToken();
+		value = parseAssignExp();
 	    }
+	    else
+	    {	value = NULL;
+		if (type)
+		    error("if type, there must be an initializer");
+	    }
+
+	    EnumMember *em = new EnumMember(loc, ident, value, type);
+	    e->members->push(em);
+
+	    if (token.value == TOKrcurly)
+		;
+	    else
+	    {   addComment(em, comment);
+		comment = NULL;
+		check(TOKcomma);
+	    }
+	    addComment(em, comment);
+	    comment = token.blockComment;
 	}
 	nextToken();
     }
     else
 	error("enum declaration is invalid");
-
+    //printf("-parseEnum() %s\n", e->toChars());
     return e;
 }
 
@@ -2027,7 +2066,7 @@
     unsigned char *comment = token.blockComment;
     enum LINK link = linkage;
 
-    //printf("parseDeclarations()\n");
+    //printf("parseDeclarations() %s\n", token.toChars());
     switch (token.value)
     {
 	case TOKtypedef:
@@ -2066,10 +2105,17 @@
 	    case TOKabstract:	stc = STCabstract;	 goto L1;
 	    case TOKsynchronized: stc = STCsynchronized; goto L1;
 	    case TOKdeprecated: stc = STCdeprecated;	 goto L1;
+	    case TOKenum:	stc = STCmanifest;	 goto L1;
 	    L1:
 		if (storage_class & stc)
 		    error("redundant storage class '%s'", token.toChars());
 		storage_class = (STC) (storage_class | stc);
+		{
+		unsigned u = storage_class;
+		u &= STCconst | STCinvariant | STCmanifest;
+		if (u & (u - 1))
+		    error("conflicting storage class %s", Token::toChars(token.value));
+		}
 		nextToken();
 		continue;
 
@@ -2693,9 +2739,24 @@
 	}
 
 	case TOKenum:
-	{   Dsymbol *d;
-
-	    d = parseEnum();
+	{   /* Determine if this is a manifest constant declaration,
+	     * or a conventional enum.
+	     */
+	    Dsymbol *d;
+	    Token *t = peek(&token);
+	    if (t->value == TOKlcurly || t->value == TOKcolon)
+		d = parseEnum();
+	    else if (t->value != TOKidentifier)
+		goto Ldeclaration;
+	    else
+	    {
+		t = peek(t);
+		if (t->value == TOKlcurly || t->value == TOKcolon ||
+		    t->value == TOKsemicolon)
+		    d = parseEnum();
+		else
+		    goto Ldeclaration;
+	    }
 	    s = new DeclarationStatement(loc, d);
 	    break;
 	}
Index: dmd2/interpret.c
===================================================================
--- dmd2/interpret.c	(revision 209)
+++ dmd2/interpret.c	(working copy)
@@ -57,7 +57,7 @@
 Expression *FuncDeclaration::interpret(InterState *istate, Expressions *arguments)
 {
 #if LOG
-    printf("FuncDeclaration::interpret() %s\n", toChars());
+    printf("\n********\nFuncDeclaration::interpret(istate = %p) %s\n", istate, toChars());
     printf("cantInterpret = %d, semanticRun = %d\n", cantInterpret, semanticRun);
 #endif
     if (global.errors)
@@ -161,7 +161,15 @@
 	    else
 	    {	/* Value parameters
 		 */
-		earg = earg->interpret(&istatex);
+		Type *ta = arg->type->toBasetype();
+		if (ta->ty == Tsarray && earg->op == TOKaddress)
+		{
+		    /* Static arrays are passed by a simple pointer.
+		     * Skip past this to get at the actual arg.
+		     */
+		    earg = ((AddrExp *)earg)->e1;
+		}
+		earg = earg->interpret(istate ? istate : &istatex);
 		if (earg == EXP_CANT_INTERPRET)
 		    return NULL;
 		v->value = earg;
@@ -177,13 +185,13 @@
     Expressions valueSaves;
     if (istate)
     {
-	//printf("saving state...\n");
+	//printf("saving local variables...\n");
 	valueSaves.setDim(istate->vars.dim);
 	for (size_t i = 0; i < istate->vars.dim; i++)
 	{   VarDeclaration *v = (VarDeclaration *)istate->vars.data[i];
 	    if (v)
 	    {
-		//printf("\tsaving [%d] %s = %s\n", i, v->toChars(), v->value->toChars());
+		//printf("\tsaving [%d] %s = %s\n", i, v->toChars(), v->value ? v->value->toChars() : "");
 		valueSaves.data[i] = v->value;
 		v->value = NULL;
 	    }
@@ -230,10 +238,13 @@
     {
 	/* Restore the variable values
 	 */
+	//printf("restoring local variables...\n");
 	for (size_t i = 0; i < istate->vars.dim; i++)
 	{   VarDeclaration *v = (VarDeclaration *)istate->vars.data[i];
 	    if (v)
-		v->value = (Expression *)valueSaves.data[i];
+	    {	v->value = (Expression *)valueSaves.data[i];
+		//printf("\trestoring [%d] %s = %s\n", i, v->toChars(), v->value ? v->value->toChars() : "");
+	    }
 	}
     }
 
@@ -904,6 +915,8 @@
 {
 #if LOG
     printf("Expression::interpret() %s\n", toChars());
+    printf("type = %s\n", type->toChars());
+    dump(0);
 #endif
     return EXP_CANT_INTERPRET;
 }
@@ -949,7 +962,11 @@
     SymbolDeclaration *s = d->isSymbolDeclaration();
     if (v)
     {
+#if V2
 	if ((v->isConst() || v->isInvariant()) && v->init && !v->value)
+#else
+	if (v->isConst() && v->init)
+#endif
 	{   e = v->init->toExpression();
 	    if (e && !e->type)
 		e->type = v->type;
@@ -1001,7 +1018,11 @@
 	    else if (v->init->isVoidInitializer())
 		e = NULL;
 	}
+#if V2
 	else if (s == v && (v->isConst() || v->isInvariant()) && v->init)
+#else
+	else if (s == v && v->isConst() && v->init)
+#endif
 	{   e = v->init->toExpression();
 	    if (!e)
 		e = EXP_CANT_INTERPRET;
@@ -1416,8 +1437,16 @@
 	     */
 	    if (v->value && v->value->op == TOKvar)
 	    {
-		ve = (VarExp *)v->value;
-		v = ve->var->isVarDeclaration();
+		VarExp *ve2 = (VarExp *)v->value;
+		if (ve2->var->isSymbolDeclaration())
+		{
+		    /* This can happen if v is a struct initialized to
+		     * 0 using an __initZ SymbolDeclaration from
+		     * TypeStruct::defaultInit()
+		     */
+		}
+		else
+		    v = ve2->var->isVarDeclaration();
 		assert(v);
 	    }
 
@@ -1445,6 +1474,7 @@
 		    {
 			if (i == istate->vars.dim)
 			{   istate->vars.push(v);
+			    //printf("\tadding %s to istate\n", v->toChars());
 			    break;
 			}
 			if (v == (VarDeclaration *)istate->vars.data[i])
@@ -1832,7 +1862,7 @@
 		Expression *eresult = fd->interpret(istate, arguments);
 		if (eresult)
 		    e = eresult;
-		else if (fd->type->toBasetype()->nextOf()->ty == Tvoid)
+		else if (fd->type->toBasetype()->nextOf()->ty == Tvoid && !global.errors)
 		    e = EXP_VOID_INTERPRET;
 		else
 		    error("cannot evaluate %s at compile time", toChars());
Index: dmd2/lexer.c
===================================================================
--- dmd2/lexer.c	(revision 209)
+++ dmd2/lexer.c	(working copy)
@@ -2891,6 +2891,7 @@
     {	"invariant",	TOKinvariant	},
     {	"unittest",	TOKunittest	},
     {	"version",	TOKversion	},
+    //{	"manifest",	TOKmanifest	},
 
     // Added after 1.0
     {	"ref",		TOKref		},
Index: dmd2/lexer.h
===================================================================
--- dmd2/lexer.h	(revision 209)
+++ dmd2/lexer.h	(working copy)
@@ -131,7 +131,7 @@
 	TOKalign, TOKextern, TOKprivate, TOKprotected, TOKpublic, TOKexport,
 	TOKstatic, /*TOKvirtual,*/ TOKfinal, TOKconst, TOKabstract, TOKvolatile,
 	TOKdebug, TOKdeprecated, TOKin, TOKout, TOKinout, TOKlazy,
-	TOKauto, TOKpackage,
+	TOKauto, TOKpackage, TOKmanifest,
 
 	// Statements
 	TOKif, TOKelse, TOKwhile, TOKfor, TOKdo, TOKswitch,
Index: dmd2/cast.c
===================================================================
--- dmd2/cast.c	(revision 209)
+++ dmd2/cast.c	(working copy)
@@ -57,6 +57,7 @@
 	return e->implicitCastTo(sc, t);
 
 #if 0
+printf("ty = %d\n", type->ty);
 print();
 type->print();
 printf("to:\n");
@@ -138,13 +139,14 @@
     printf("IntegerExp::implicitConvTo(this=%s, type=%s, t=%s)\n",
 	toChars(), type->toChars(), t->toChars());
 #endif
-    if (type->equals(t))
-	return MATCHexact;
+    MATCH m = type->implicitConvTo(t);
+    if (m >= MATCHconst)
+	return m;
 
     TY ty = type->toBasetype()->ty;
     TY toty = t->toBasetype()->ty;
 
-    if (type->implicitConvTo(t) == MATCHnomatch && t->ty == Tenum)
+    if (m == MATCHnomatch && t->ty == Tenum)
 	goto Lno;
 
     switch (ty)
@@ -638,9 +640,7 @@
  */
 
 Expression *Expression::castTo(Scope *sc, Type *t)
-{   Expression *e;
-    Type *tb;
-
+{
     //printf("Expression::castTo(this=%s, t=%s)\n", toChars(), t->toChars());
 #if 0
     printf("Expression::castTo(this=%s, type=%s, t=%s)\n",
@@ -648,19 +648,19 @@
 #endif
     if (type == t)
 	return this;
-    e = this;
-    tb = t->toBasetype();
-    type = type->toBasetype();
-    if (tb != type)
+    Expression *e = this;
+    Type *tb = t->toBasetype();
+    Type *typeb = type->toBasetype();
+    if (tb != typeb)
     {
 	// Do (type *) cast of (type [dim])
 	if (tb->ty == Tpointer &&
-	    type->ty == Tsarray
+	    typeb->ty == Tsarray
 	   )
 	{
 	    //printf("Converting [dim] to *\n");
 
-	    if (type->size(loc) == 0)
+	    if (typeb->size(loc) == 0)
 		e = new NullExp(loc);
 	    else
 		e = new AddrExp(loc, e);
@@ -678,6 +678,11 @@
 	    e = new CastExp(loc, e, tb);
 	}
     }
+    else
+    {
+	e = e->copy();	// because of COW for assignment to e->type
+    }
+    assert(e != this);
     e->type = t;
     //printf("Returning: %s\n", e->toChars());
     return e;
@@ -685,40 +690,55 @@
 
 
 Expression *RealExp::castTo(Scope *sc, Type *t)
-{
-    if (type->isreal() && t->isreal())
-	type = t;
-    else if (type->isimaginary() && t->isimaginary())
-	type = t;
-    else
-	return Expression::castTo(sc, t);
-    return this;
+{   Expression *e = this;
+    if (type != t)
+    {
+	if ((type->isreal() && t->isreal()) ||
+	    (type->isimaginary() && t->isimaginary())
+	   )
+	{   e = copy();
+	    e->type = t;
+	}
+	else
+	    e = Expression::castTo(sc, t);
+    }
+    return e;
 }
 
 
 Expression *ComplexExp::castTo(Scope *sc, Type *t)
-{
-    if (type->iscomplex() && t->iscomplex())
-	type = t;
-    else
-	return Expression::castTo(sc, t);
-    return this;
+{   Expression *e = this;
+    if (type != t)
+    {
+	if (type->iscomplex() && t->iscomplex())
+	{   e = copy();
+	    e->type = t;
+	}
+	else
+	    e = Expression::castTo(sc, t);
+    }
+    return e;
 }
 
 
 Expression *NullExp::castTo(Scope *sc, Type *t)
-{   Expression *e;
+{   NullExp *e;
     Type *tb;
 
     //printf("NullExp::castTo(t = %p)\n", t);
-    committed = 1;
-    e = this;
+    if (type == t)
+    {
+	committed = 1;
+	return this;
+    }
+    e = (NullExp *)copy();
+    e->committed = 1;
     tb = t->toBasetype();
-    type = type->toBasetype();
-    if (tb != type)
+    e->type = type->toBasetype();
+    if (tb != e->type)
     {
 	// NULL implicitly converts to any pointer type or dynamic array
-	if (type->ty == Tpointer && type->nextOf()->ty == Tvoid &&
+	if (e->type->ty == Tpointer && e->type->nextOf()->ty == Tvoid &&
 	    (tb->ty == Tpointer || tb->ty == Tarray || tb->ty == Taarray ||
 	     tb->ty == Tdelegate))
 	{
@@ -738,8 +758,7 @@
 	}
 	else
 	{
-	    return Expression::castTo(sc, t);
-	    //e = new CastExp(loc, e, tb);
+	    return e->Expression::castTo(sc, t);
 	}
     }
     e->type = t;
@@ -1036,13 +1055,14 @@
 
 
 Expression *TupleExp::castTo(Scope *sc, Type *t)
-{
-    for (size_t i = 0; i < exps->dim; i++)
-    {   Expression *e = (Expression *)exps->data[i];
-	e = e->castTo(sc, t);
-	exps->data[i] = (void *)e;
+{   TupleExp *e = (TupleExp *)copy();
+    e->exps = (Expressions *)exps->copy();
+    for (size_t i = 0; i < e->exps->dim; i++)
+    {   Expression *ex = (Expression *)e->exps->data[i];
+	ex = ex->castTo(sc, t);
+	e->exps->data[i] = (void *)ex;
     }
-    return this;
+    return e;
 }
 
 
@@ -1054,6 +1074,7 @@
 #endif
     if (type == t)
 	return this;
+    ArrayLiteralExp *e = this;
     Type *typeb = type->toBasetype();
     Type *tb = t->toBasetype();
     if ((tb->ty == Tarray || tb->ty == Tsarray) &&
@@ -1066,65 +1087,73 @@
 		goto L1;
 	}
 
+	e = (ArrayLiteralExp *)copy();
+	e->elements = (Expressions *)elements->copy();
 	for (int i = 0; i < elements->dim; i++)
-	{   Expression *e = (Expression *)elements->data[i];
-	    e = e->castTo(sc, tb->nextOf());
-	    elements->data[i] = (void *)e;
+	{   Expression *ex = (Expression *)elements->data[i];
+	    ex = ex->castTo(sc, tb->nextOf());
+	    e->elements->data[i] = (void *)ex;
 	}
-	type = t;
-	return this;
+	e->type = t;
+	return e;
     }
     if (tb->ty == Tpointer && typeb->ty == Tsarray)
     {
-	type = typeb->nextOf()->pointerTo();
+	e = (ArrayLiteralExp *)copy();
+	e->type = typeb->nextOf()->pointerTo();
     }
 L1:
-    return Expression::castTo(sc, t);
+    return e->Expression::castTo(sc, t);
 }
 
 Expression *AssocArrayLiteralExp::castTo(Scope *sc, Type *t)
 {
+    if (type == t)
+	return this;
+    AssocArrayLiteralExp *e = this;
     Type *typeb = type->toBasetype();
     Type *tb = t->toBasetype();
     if (tb->ty == Taarray && typeb->ty == Taarray &&
 	tb->nextOf()->toBasetype()->ty != Tvoid)
     {
+	e = (AssocArrayLiteralExp *)copy();
+	e->keys = (Expressions *)keys->copy();
+	e->values = (Expressions *)values->copy();
 	assert(keys->dim == values->dim);
 	for (size_t i = 0; i < keys->dim; i++)
-	{   Expression *e = (Expression *)values->data[i];
-	    e = e->castTo(sc, tb->nextOf());
-	    values->data[i] = (void *)e;
+	{   Expression *ex = (Expression *)values->data[i];
+	    ex = ex->castTo(sc, tb->nextOf());
+	    e->values->data[i] = (void *)ex;
 
-	    e = (Expression *)keys->data[i];
-	    e = e->castTo(sc, ((TypeAArray *)tb)->index);
-	    keys->data[i] = (void *)e;
+	    ex = (Expression *)keys->data[i];
+	    ex = ex->castTo(sc, ((TypeAArray *)tb)->index);
+	    e->keys->data[i] = (void *)ex;
 	}
-	type = t;
-	return this;
+	e->type = t;
+	return e;
     }
 L1:
-    return Expression::castTo(sc, t);
+    return e->Expression::castTo(sc, t);
 }
 
 Expression *SymOffExp::castTo(Scope *sc, Type *t)
 {
-    Type *tb;
-
 #if 0
     printf("SymOffExp::castTo(this=%s, type=%s, t=%s)\n",
 	toChars(), type->toChars(), t->toChars());
 #endif
-    Expression *e = this;
-
-    tb = t->toBasetype();
-    type = type->toBasetype();
-    if (tb != type)
+    if (type == t && hasOverloads == 0)
+	return this;
+    Expression *e;
+    Type *tb = t->toBasetype();
+    Type *typeb = type->toBasetype();
+    if (tb != typeb)
     {
 	// Look for pointers to functions where the functions are overloaded.
 	FuncDeclaration *f;
 
 	if (hasOverloads &&
-	    type->ty == Tpointer && type->nextOf()->ty == Tfunction &&
+	    typeb->ty == Tpointer && typeb->nextOf()->ty == Tfunction &&
 	    (tb->ty == Tpointer || tb->ty == Tdelegate) && tb->nextOf()->ty == Tfunction)
 	{
 	    f = var->isFuncDeclaration();
@@ -1155,32 +1184,31 @@
 	}
 	e = Expression::castTo(sc, t);
     }
-    if (e == this && hasOverloads)
-    {	e = syntaxCopy();
+    else
+    {	e = copy();
+	e->type = t;
 	((SymOffExp *)e)->hasOverloads = 0;
     }
-    e->type = t;
     return e;
 }
 
 Expression *DelegateExp::castTo(Scope *sc, Type *t)
 {
-    Type *tb;
 #if 0
     printf("DelegateExp::castTo(this=%s, type=%s, t=%s)\n",
 	toChars(), type->toChars(), t->toChars());
 #endif
-    Expression *e = this;
     static char msg[] = "cannot form delegate due to covariant return type";
 
-    tb = t->toBasetype();
-    type = type->toBasetype();
-    if (tb != type)
+    Expression *e = this;
+    Type *tb = t->toBasetype();
+    Type *typeb = type->toBasetype();
+    if (tb != typeb)
     {
 	// Look for delegates to functions where the functions are overloaded.
 	FuncDeclaration *f;
 
-	if (type->ty == Tdelegate && type->nextOf()->ty == Tfunction &&
+	if (typeb->ty == Tdelegate && typeb->nextOf()->ty == Tfunction &&
 	    tb->ty == Tdelegate && tb->nextOf()->ty == Tfunction)
 	{
 	    if (func)
@@ -1207,8 +1235,9 @@
 	func->tookAddressOf = 1;
 	if (func->tintro && func->tintro->nextOf()->isBaseOf(func->type->nextOf(), &offset) && offset)
 	    error("%s", msg);
+	e = copy();
+	e->type = t;
     }
-    e->type = t;
     return e;
 }
 
@@ -1292,6 +1321,7 @@
     t1 = e1->type;
     t2 = e2->type;
     assert(t1);
+    t = t1;
 
     //if (t1) printf("\tt1 = %s\n", t1->toChars());
     //if (t2) printf("\tt2 = %s\n", t2->toChars());
@@ -1348,6 +1378,9 @@
 	return this;
     }
 
+    t1 = t1b;
+    t2 = t2b;
+
     if (op == TOKcat)
     {
 	if ((t1->ty == Tsarray || t1->ty == Tarray) &&
@@ -1368,12 +1401,12 @@
 		e2->type = t2;
 	    else
 		e2 = e2->castTo(sc, t2);
+	    t = t1;
 	    goto Lagain;
 	}
     }
 
 Lagain:
-    t = t1;
     if (t1 == t2)
     {
 	if ((t1->ty == Tstruct || t1->ty == Tclass) &&
@@ -1396,6 +1429,7 @@
 	{
 	    t1 = t1n->mutableOf()->constOf()->pointerTo();
 	    t2 = t2n->mutableOf()->constOf()->pointerTo();
+	    t = t1;
 	    goto Lagain;
 	}
 	else if (t1n->ty == Tclass && t2n->ty == Tclass)
@@ -1459,6 +1493,7 @@
 	    t2 = t2->nextOf()->mutableOf()->constOf()->pointerTo();
 	else
 	    t2 = t2->nextOf()->mutableOf()->constOf()->arrayOf();
+	t = t1;
 	goto Lagain;
     }
     else if (t1->ty == Tclass || t2->ty == Tclass)
@@ -1557,9 +1592,10 @@
  */
 
 Expression *Expression::integralPromotions(Scope *sc)
-{   Expression *e;
+{
+    Expression *e = this;
 
-    e = this;
+    //printf("integralPromotions %s %s\n", e->toChars(), e->type->toChars());
     switch (type->toBasetype()->ty)
     {
 	case Tvoid:
