All pastes #932579 Raw Edit

Untitled

public text v1 · immutable
·published 2008-03-07 20:56 UTC
rendered paste body
Index: d/phobos/std/loader.d
===================================================================
--- d/phobos/std/loader.d	(Revision 199)
+++ d/phobos/std/loader.d	(Arbeitskopie)
@@ -858,8 +858,16 @@
 
     this(uint errcode)
     {
+      version (linux)
+      {
+	char[80] buf = void;
+	super(std.string.toString(strerror_r(errcode, buf.ptr, buf.length)).dup);
+      }
+      else
+      {
 	super(std.string.toString(strerror(errcode)).dup);
     }
+    }
 }
 
 /// This class represents an executable image
Index: d/phobos/std/process.d
===================================================================
--- d/phobos/std/process.d	(Revision 199)
+++ d/phobos/std/process.d	(Arbeitskopie)
@@ -146,7 +146,11 @@
 
 Lerror:
     retval = getErrno;
-    throw new Exception("Cannot spawn " ~ toString(pathname) ~ "; " ~ toString(strerror(retval)) ~ " [errno " ~ toString(retval) ~ "]");
+    char[80] buf = void;
+    throw new Exception(
+        "Cannot spawn " ~ toString(pathname) ~ "; "
+                      ~ toString(strerror_r(retval, buf.ptr, buf.length))
+                      ~ " [errno " ~ toString(retval) ~ "]");
 }   // _spawnvp
 private
 {
Index: d/phobos/std/stdio.d
===================================================================
--- d/phobos/std/stdio.d	(Revision 199)
+++ d/phobos/std/stdio.d	(Arbeitskopie)
@@ -104,7 +104,15 @@
     }
 
     this(uint errno)
-    {	char* s = 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).dup);
     }
 
Index: d/phobos/std/system.d
===================================================================
--- d/phobos/std/system.d	(Revision 199)
+++ d/phobos/std/system.d	(Arbeitskopie)
@@ -1,3 +1,4 @@
+// Written in the D programming language
 
 /**
  * Information about the target operating system, environment, and CPU
@@ -63,7 +64,7 @@
 	RedHatLinux,
     }
 
-    /// Byte order endiannes
+    /// Byte order endianness
 
     enum Endian
     {
@@ -73,7 +74,7 @@
 
     version(LittleEndian)
     {
-	/// Native system endiannes
+	/// Native system endianness
         Endian endian = Endian.LittleEndian;
     }
     else
Index: d/phobos/std/math.d
===================================================================
--- d/phobos/std/math.d	(Revision 199)
+++ d/phobos/std/math.d	(Arbeitskopie)
@@ -83,7 +83,7 @@
 {
     this(string msg)
     {
-	super(msg ~ "not implemented");
+	super(msg ~ " not implemented");
     }
 }
 
@@ -372,18 +372,18 @@
 
 /***************
  * Calculates the arc tangent of y / x,
- * returning a value ranging from -$(PI)/2 to $(PI)/2.
+ * returning a value ranging from -$(PI) to $(PI).
  *
  *      $(TABLE_SV
  *      $(TR $(TH y)                 $(TH x)            $(TH atan(y, x)))
  *      $(TR $(TD $(NAN))            $(TD anything)     $(TD $(NAN)) )
  *      $(TR $(TD anything)          $(TD $(NAN))       $(TD $(NAN)) )
  *      $(TR $(TD $(PLUSMN)0.0)      $(TD $(GT)0.0)     $(TD $(PLUSMN)0.0) )
- *      $(TR $(TD $(PLUSMN)0.0)      $(TD $(PLUSMN)0.0) $(TD $(PLUSMN)0.0) )
+ *      $(TR $(TD $(PLUSMN)0.0)      $(TD +0.0)         $(TD $(PLUSMN)0.0) )
  *      $(TR $(TD $(PLUSMN)0.0)      $(TD $(LT)0.0)     $(TD $(PLUSMN)$(PI)))
  *      $(TR $(TD $(PLUSMN)0.0)      $(TD -0.0)         $(TD $(PLUSMN)$(PI)))
  *      $(TR $(TD $(GT)0.0)          $(TD $(PLUSMN)0.0) $(TD $(PI)/2) )
- *      $(TR $(TD $(LT)0.0)          $(TD $(PLUSMN)0.0) $(TD $(PI)/2))
+ *      $(TR $(TD $(LT)0.0)          $(TD $(PLUSMN)0.0) $(TD -$(PI)/2) )
  *      $(TR $(TD $(GT)0.0)          $(TD $(INFIN))     $(TD $(PLUSMN)0.0) )
  *      $(TR $(TD $(PLUSMN)$(INFIN)) $(TD anything)     $(TD $(PLUSMN)$(PI)/2))
  *      $(TR $(TD $(GT)0.0)          $(TD -$(INFIN))    $(TD $(PLUSMN)$(PI)) )
@@ -906,6 +906,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)
 {
@@ -1181,6 +1183,8 @@
 /***************************************
  * Rounds x to the nearest integer value, using the current rounding
  * mode.
+ *
+ * Note: Not supported on windows
  */
 long lrint(real x)
 {
@@ -1234,6 +1238,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)
 {
@@ -1287,6 +1293,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); }
 
@@ -1498,6 +1506,8 @@
  * 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)
 {
Index: d/phobos/std/stream.d
===================================================================
--- d/phobos/std/stream.d	(Revision 199)
+++ d/phobos/std/stream.d	(Arbeitskopie)
@@ -2130,7 +2130,7 @@
   }
 
   /// creates file in requested mode
-  void create(char[] filename, FileMode mode = FileMode.Out) {
+  void create(char[] filename, FileMode mode = FileMode.OutNew) {
     File sf = cast(File)s;
     sf.create(filename,mode);
     resetSource();
Index: d/phobos/std/c/string.d
===================================================================
--- d/phobos/std/c/string.d	(Revision 199)
+++ d/phobos/std/c/string.d	(Arbeitskopie)
@@ -68,3 +68,9 @@
 {
     int memicmp(char* s1, char* s2, size_t n);	///
 }
+
+version (linux)
+{
+    char* strerror_r(int errnum, char* buf, size_t buflen);	///
+}
+
Index: d/phobos/std/c/windows/winsock.d
===================================================================
--- d/phobos/std/c/windows/winsock.d	(Revision 199)
+++ d/phobos/std/c/windows/winsock.d	(Arbeitskopie)
@@ -381,6 +381,7 @@
 	MSG_OOB =        0x1,
 	MSG_PEEK =       0x2,
 	MSG_DONTROUTE =  0x4,
+        MSG_NOSIGNAL =   0x0, /// not supported on win32, would be 0x4000 if it was
 }
 
 
Index: d/phobos/std/c/windows/windows.d
===================================================================
--- d/phobos/std/c/windows/windows.d	(Revision 199)
+++ d/phobos/std/c/windows/windows.d	(Arbeitskopie)
@@ -250,8 +250,11 @@
     FILE_VOLUME_IS_COMPRESSED       = 0x00008000,  
 }
 
-const DWORD MAILSLOT_NO_MESSAGE = cast(DWORD)-1;
-const DWORD MAILSLOT_WAIT_FOREVER = cast(DWORD)-1; 
+enum
+{
+    MAILSLOT_NO_MESSAGE = cast(DWORD)-1,
+    MAILSLOT_WAIT_FOREVER = cast(DWORD)-1, 
+}
 
 enum : uint
 {
@@ -275,9 +278,13 @@
 }
 
 const 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 : DWORD
+{
+    INVALID_SET_FILE_POINTER = cast(DWORD)-1,
+    INVALID_FILE_SIZE = cast(DWORD)0xFFFFFFFF,
+}
+
 struct OVERLAPPED {
     DWORD   Internal;
     DWORD   InternalHigh;
@@ -326,6 +333,13 @@
     wchar  cAlternateFileName[ 14 ];
 }
 
+enum
+{
+	STD_INPUT_HANDLE =    cast(DWORD)-10,
+	STD_OUTPUT_HANDLE =   cast(DWORD)-11,
+	STD_ERROR_HANDLE =    cast(DWORD)-12,
+}
+
 export
 {
 BOOL SetCurrentDirectoryA(LPCSTR lpPathName);
@@ -428,8 +442,11 @@
 // Key creation/open disposition
 //
 
-const int REG_CREATED_NEW_KEY =         0x00000001;   // New Registry Key created
-const int REG_OPENED_EXISTING_KEY =     0x00000002;   // Existing Key opened
+enum : int
+{
+	REG_CREATED_NEW_KEY =         0x00000001,   // New Registry Key created
+	REG_OPENED_EXISTING_KEY =     0x00000002,   // Existing Key opened
+}
 
 
 //
@@ -1102,6 +1119,7 @@
 export HANDLE GetCurrentThread();
 export BOOL GetProcessTimes(HANDLE hProcess, LPFILETIME lpCreationTime, LPFILETIME lpExitTime, LPFILETIME lpKernelTime, LPFILETIME lpUserTime);
 export HANDLE GetCurrentProcess();
+export DWORD GetCurrentProcessId();
 export BOOL DuplicateHandle (HANDLE sourceProcess, HANDLE sourceThread,
         HANDLE targetProcessHandle, HANDLE *targetHandle, DWORD access, 
         BOOL inheritHandle, DWORD options);
@@ -2083,11 +2101,15 @@
 	COLOR_BTNHILIGHT =        COLOR_BTNHIGHLIGHT,
 }
 
-const int CW_USEDEFAULT = cast(int)0x80000000;
+enum : int
+{
+	CW_USEDEFAULT = cast(int)0x80000000
+}
+
 /*
  * Special value for CreateWindow, et al.
  */
-const HWND HWND_DESKTOP = (cast(HWND)0);
+const HWND HWND_DESKTOP = cast(HWND)0;
 
 
 export ATOM RegisterClassA(WNDCLASSA *lpWndClass);
@@ -2713,10 +2735,328 @@
 export int wsprintfA(LPSTR, LPCSTR, ...);
 export int wsprintfW(LPWSTR, LPCWSTR, ...);
 
-const uint INFINITE = uint.max;
-const uint WAIT_OBJECT_0 = 0;
+enum : uint
+{
+	INFINITE = uint.max,
+	WAIT_OBJECT_0 = 0,
+}
 
 export HANDLE CreateSemaphoreA(LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, LONG lInitialCount, LONG lMaximumCount, LPCTSTR lpName);
 export HANDLE OpenSemaphoreA(DWORD dwDesiredAccess, BOOL bInheritHandle, LPCTSTR lpName);
 export BOOL ReleaseSemaphore(HANDLE hSemaphore, LONG lReleaseCount, LPLONG lpPreviousCount);
+
+struct COORD {
+    SHORT X;
+    SHORT Y;
 }
+alias COORD *PCOORD;
+
+struct SMALL_RECT {
+    SHORT Left;
+    SHORT Top;
+    SHORT Right;
+    SHORT Bottom;
+}
+alias SMALL_RECT *PSMALL_RECT;
+
+struct KEY_EVENT_RECORD {
+    BOOL bKeyDown;
+    WORD wRepeatCount;
+    WORD wVirtualKeyCode;
+    WORD wVirtualScanCode;
+    union {
+        WCHAR UnicodeChar;
+        CHAR   AsciiChar;
+    }
+    DWORD dwControlKeyState;
+}
+alias KEY_EVENT_RECORD *PKEY_EVENT_RECORD;
+
+//
+// ControlKeyState flags
+//
+
+enum
+{
+	RIGHT_ALT_PRESSED =     0x0001, // the right alt key is pressed.
+	LEFT_ALT_PRESSED =      0x0002, // the left alt key is pressed.
+	RIGHT_CTRL_PRESSED =    0x0004, // the right ctrl key is pressed.
+	LEFT_CTRL_PRESSED =     0x0008, // the left ctrl key is pressed.
+	SHIFT_PRESSED =         0x0010, // the shift key is pressed.
+	NUMLOCK_ON =            0x0020, // the numlock light is on.
+	SCROLLLOCK_ON =         0x0040, // the scrolllock light is on.
+	CAPSLOCK_ON =           0x0080, // the capslock light is on.
+	ENHANCED_KEY =          0x0100, // the key is enhanced.
+}
+
+struct MOUSE_EVENT_RECORD {
+    COORD dwMousePosition;
+    DWORD dwButtonState;
+    DWORD dwControlKeyState;
+    DWORD dwEventFlags;
+}
+alias MOUSE_EVENT_RECORD *PMOUSE_EVENT_RECORD;
+
+//
+// ButtonState flags
+//
+enum
+{
+	FROM_LEFT_1ST_BUTTON_PRESSED =    0x0001,
+	RIGHTMOST_BUTTON_PRESSED =        0x0002,
+	FROM_LEFT_2ND_BUTTON_PRESSED =    0x0004,
+	FROM_LEFT_3RD_BUTTON_PRESSED =    0x0008,
+	FROM_LEFT_4TH_BUTTON_PRESSED =    0x0010,
+}
+
+//
+// EventFlags
+//
+
+enum
+{
+	MOUSE_MOVED =   0x0001,
+	DOUBLE_CLICK =  0x0002,
+}
+
+struct WINDOW_BUFFER_SIZE_RECORD {
+    COORD dwSize;
+}
+alias WINDOW_BUFFER_SIZE_RECORD *PWINDOW_BUFFER_SIZE_RECORD;
+
+struct MENU_EVENT_RECORD {
+    UINT dwCommandId;
+}
+alias MENU_EVENT_RECORD *PMENU_EVENT_RECORD;
+
+struct FOCUS_EVENT_RECORD {
+    BOOL bSetFocus;
+}
+alias FOCUS_EVENT_RECORD *PFOCUS_EVENT_RECORD;
+
+struct INPUT_RECORD {
+    WORD EventType;
+    union {
+        KEY_EVENT_RECORD KeyEvent;
+        MOUSE_EVENT_RECORD MouseEvent;
+        WINDOW_BUFFER_SIZE_RECORD WindowBufferSizeEvent;
+        MENU_EVENT_RECORD MenuEvent;
+        FOCUS_EVENT_RECORD FocusEvent;
+    }
+}
+alias INPUT_RECORD *PINPUT_RECORD;
+
+//
+//  EventType flags:
+//
+
+enum
+{
+	KEY_EVENT =         0x0001, // Event contains key event record
+	MOUSE_EVENT =       0x0002, // Event contains mouse event record
+	WINDOW_BUFFER_SIZE_EVENT = 0x0004, // Event contains window change event record
+	MENU_EVENT = 0x0008, // Event contains menu event record
+	FOCUS_EVENT = 0x0010, // event contains focus change
+}
+
+struct CHAR_INFO {
+    union {
+        WCHAR UnicodeChar;
+        CHAR   AsciiChar;
+    }
+    WORD Attributes;
+}
+alias CHAR_INFO *PCHAR_INFO;
+
+//
+// Attributes flags:
+//
+
+enum
+{
+	FOREGROUND_BLUE =      0x0001, // text color contains blue.
+	FOREGROUND_GREEN =     0x0002, // text color contains green.
+	FOREGROUND_RED =       0x0004, // text color contains red.
+	FOREGROUND_INTENSITY = 0x0008, // text color is intensified.
+	BACKGROUND_BLUE =      0x0010, // background color contains blue.
+	BACKGROUND_GREEN =     0x0020, // background color contains green.
+	BACKGROUND_RED =       0x0040, // background color contains red.
+	BACKGROUND_INTENSITY = 0x0080, // background color is intensified.
+}
+
+struct CONSOLE_SCREEN_BUFFER_INFO {
+    COORD dwSize;
+    COORD dwCursorPosition;
+    WORD  wAttributes;
+    SMALL_RECT srWindow;
+    COORD dwMaximumWindowSize;
+}
+alias CONSOLE_SCREEN_BUFFER_INFO *PCONSOLE_SCREEN_BUFFER_INFO;
+
+struct CONSOLE_CURSOR_INFO {
+    DWORD  dwSize;
+    BOOL   bVisible;
+}
+alias CONSOLE_CURSOR_INFO *PCONSOLE_CURSOR_INFO;
+
+enum
+{
+	ENABLE_PROCESSED_INPUT = 0x0001,
+	ENABLE_LINE_INPUT =      0x0002,
+	ENABLE_ECHO_INPUT =      0x0004,
+	ENABLE_WINDOW_INPUT =    0x0008,
+	ENABLE_MOUSE_INPUT =     0x0010,
+}
+
+enum
+{
+	ENABLE_PROCESSED_OUTPUT =    0x0001,
+	ENABLE_WRAP_AT_EOL_OUTPUT =  0x0002,
+}
+
+BOOL PeekConsoleInputA(HANDLE hConsoleInput, PINPUT_RECORD lpBuffer, DWORD nLength, LPDWORD lpNumberOfEventsRead);
+BOOL PeekConsoleInputW(HANDLE hConsoleInput, PINPUT_RECORD lpBuffer, DWORD nLength, LPDWORD lpNumberOfEventsRead);
+BOOL ReadConsoleInputA(HANDLE hConsoleInput, PINPUT_RECORD lpBuffer, DWORD nLength, LPDWORD lpNumberOfEventsRead);
+BOOL ReadConsoleInputW(HANDLE hConsoleInput, PINPUT_RECORD lpBuffer, DWORD nLength, LPDWORD lpNumberOfEventsRead);
+BOOL WriteConsoleInputA(HANDLE hConsoleInput, INPUT_RECORD *lpBuffer, DWORD nLength, LPDWORD lpNumberOfEventsWritten);
+BOOL WriteConsoleInputW(HANDLE hConsoleInput, INPUT_RECORD *lpBuffer, DWORD nLength, LPDWORD lpNumberOfEventsWritten);
+BOOL ReadConsoleOutputA(HANDLE hConsoleOutput, PCHAR_INFO lpBuffer, COORD dwBufferSize, COORD dwBufferCoord, PSMALL_RECT lpReadRegion);
+BOOL ReadConsoleOutputW(HANDLE hConsoleOutput, PCHAR_INFO lpBuffer, COORD dwBufferSize, COORD dwBufferCoord, PSMALL_RECT lpReadRegion);
+BOOL WriteConsoleOutputA(HANDLE hConsoleOutput, CHAR_INFO *lpBuffer, COORD dwBufferSize, COORD dwBufferCoord, PSMALL_RECT lpWriteRegion);
+BOOL WriteConsoleOutputW(HANDLE hConsoleOutput, CHAR_INFO *lpBuffer, COORD dwBufferSize, COORD dwBufferCoord, PSMALL_RECT lpWriteRegion);
+BOOL ReadConsoleOutputCharacterA(HANDLE hConsoleOutput, LPSTR lpCharacter, DWORD nLength, COORD dwReadCoord, LPDWORD lpNumberOfCharsRead);
+BOOL ReadConsoleOutputCharacterW(HANDLE hConsoleOutput, LPWSTR lpCharacter, DWORD nLength, COORD dwReadCoord, LPDWORD lpNumberOfCharsRead);
+BOOL ReadConsoleOutputAttribute(HANDLE hConsoleOutput, LPWORD lpAttribute, DWORD nLength, COORD dwReadCoord, LPDWORD lpNumberOfAttrsRead);
+BOOL WriteConsoleOutputCharacterA(HANDLE hConsoleOutput, LPCSTR lpCharacter, DWORD nLength, COORD dwWriteCoord, LPDWORD lpNumberOfCharsWritten);
+BOOL WriteConsoleOutputCharacterW(HANDLE hConsoleOutput, LPCWSTR lpCharacter, DWORD nLength, COORD dwWriteCoord, LPDWORD lpNumberOfCharsWritten);
+BOOL WriteConsoleOutputAttribute(HANDLE hConsoleOutput, WORD *lpAttribute, DWORD nLength, COORD dwWriteCoord, LPDWORD lpNumberOfAttrsWritten);
+BOOL FillConsoleOutputCharacterA(HANDLE hConsoleOutput, CHAR cCharacter, DWORD  nLength, COORD  dwWriteCoord, LPDWORD lpNumberOfCharsWritten);
+BOOL FillConsoleOutputCharacterW(HANDLE hConsoleOutput, WCHAR cCharacter, DWORD  nLength, COORD  dwWriteCoord, LPDWORD lpNumberOfCharsWritten);
+BOOL FillConsoleOutputAttribute(HANDLE hConsoleOutput, WORD   wAttribute, DWORD  nLength, COORD  dwWriteCoord, LPDWORD lpNumberOfAttrsWritten);
+BOOL GetConsoleMode(HANDLE hConsoleHandle, LPDWORD lpMode);
+BOOL GetNumberOfConsoleInputEvents(HANDLE hConsoleInput, LPDWORD lpNumberOfEvents);
+BOOL GetConsoleScreenBufferInfo(HANDLE hConsoleOutput, PCONSOLE_SCREEN_BUFFER_INFO lpConsoleScreenBufferInfo);
+COORD GetLargestConsoleWindowSize( HANDLE hConsoleOutput);
+BOOL GetConsoleCursorInfo(HANDLE hConsoleOutput, PCONSOLE_CURSOR_INFO lpConsoleCursorInfo);
+BOOL GetNumberOfConsoleMouseButtons( LPDWORD lpNumberOfMouseButtons);
+BOOL SetConsoleMode(HANDLE hConsoleHandle, DWORD dwMode);
+BOOL SetConsoleActiveScreenBuffer(HANDLE hConsoleOutput);
+BOOL FlushConsoleInputBuffer(HANDLE hConsoleInput);
+BOOL SetConsoleScreenBufferSize(HANDLE hConsoleOutput, COORD dwSize);
+BOOL SetConsoleCursorPosition(HANDLE hConsoleOutput, COORD dwCursorPosition);
+BOOL SetConsoleCursorInfo(HANDLE hConsoleOutput, CONSOLE_CURSOR_INFO *lpConsoleCursorInfo);
+BOOL ScrollConsoleScreenBufferA(HANDLE hConsoleOutput, SMALL_RECT *lpScrollRectangle, SMALL_RECT *lpClipRectangle, COORD dwDestinationOrigin, CHAR_INFO *lpFill);
+BOOL ScrollConsoleScreenBufferW(HANDLE hConsoleOutput, SMALL_RECT *lpScrollRectangle, SMALL_RECT *lpClipRectangle, COORD dwDestinationOrigin, CHAR_INFO *lpFill);
+BOOL SetConsoleWindowInfo(HANDLE hConsoleOutput, BOOL bAbsolute, SMALL_RECT *lpConsoleWindow);
+BOOL SetConsoleTextAttribute(HANDLE hConsoleOutput, WORD wAttributes);
+alias BOOL(*PHANDLER_ROUTINE)(DWORD CtrlType);
+BOOL SetConsoleCtrlHandler(PHANDLER_ROUTINE HandlerRoutine, BOOL Add);
+BOOL GenerateConsoleCtrlEvent( DWORD dwCtrlEvent, DWORD dwProcessGroupId);
+BOOL AllocConsole();
+BOOL FreeConsole();
+DWORD GetConsoleTitleA(LPSTR lpConsoleTitle, DWORD nSize);
+DWORD GetConsoleTitleW(LPWSTR lpConsoleTitle, DWORD nSize);
+BOOL SetConsoleTitleA(LPCSTR lpConsoleTitle);
+BOOL SetConsoleTitleW(LPCWSTR lpConsoleTitle);
+BOOL ReadConsoleA(HANDLE hConsoleInput, LPVOID lpBuffer, DWORD nNumberOfCharsToRead, LPDWORD lpNumberOfCharsRead, LPVOID lpReserved);
+BOOL ReadConsoleW(HANDLE hConsoleInput, LPVOID lpBuffer, DWORD nNumberOfCharsToRead, LPDWORD lpNumberOfCharsRead, LPVOID lpReserved);
+BOOL WriteConsoleA(HANDLE hConsoleOutput,  void *lpBuffer, DWORD nNumberOfCharsToWrite, LPDWORD lpNumberOfCharsWritten, LPVOID lpReserved);
+BOOL WriteConsoleW(HANDLE hConsoleOutput,  void *lpBuffer, DWORD nNumberOfCharsToWrite, LPDWORD lpNumberOfCharsWritten, LPVOID lpReserved);
+HANDLE CreateConsoleScreenBuffer(DWORD dwDesiredAccess, DWORD dwShareMode, SECURITY_ATTRIBUTES *lpSecurityAttributes, DWORD dwFlags, LPVOID lpScreenBufferData);
+UINT GetConsoleCP();
+BOOL SetConsoleCP( UINT wCodePageID);
+UINT GetConsoleOutputCP();
+BOOL SetConsoleOutputCP(UINT wCodePageID);
+
+enum : int
+{
+	CONSOLE_TEXTMODE_BUFFER = 1,
+}
+
+enum
+{
+	SM_CXSCREEN =             0,
+	SM_CYSCREEN =             1,
+	SM_CXVSCROLL =            2,
+	SM_CYHSCROLL =            3,
+	SM_CYCAPTION =            4,
+	SM_CXBORDER =             5,
+	SM_CYBORDER =             6,
+	SM_CXDLGFRAME =           7,
+	SM_CYDLGFRAME =           8,
+	SM_CYVTHUMB =             9,
+	SM_CXHTHUMB =             10,
+	SM_CXICON =               11,
+	SM_CYICON =               12,
+	SM_CXCURSOR =             13,
+	SM_CYCURSOR =             14,
+	SM_CYMENU =               15,
+	SM_CXFULLSCREEN =         16,
+	SM_CYFULLSCREEN =         17,
+	SM_CYKANJIWINDOW =        18,
+	SM_MOUSEPRESENT =         19,
+	SM_CYVSCROLL =            20,
+	SM_CXHSCROLL =            21,
+	SM_DEBUG =                22,
+	SM_SWAPBUTTON =           23,
+	SM_RESERVED1 =            24,
+	SM_RESERVED2 =            25,
+	SM_RESERVED3 =            26,
+	SM_RESERVED4 =            27,
+	SM_CXMIN =                28,
+	SM_CYMIN =                29,
+	SM_CXSIZE =               30,
+	SM_CYSIZE =               31,
+	SM_CXFRAME =              32,
+	SM_CYFRAME =              33,
+	SM_CXMINTRACK =           34,
+	SM_CYMINTRACK =           35,
+	SM_CXDOUBLECLK =          36,
+	SM_CYDOUBLECLK =          37,
+	SM_CXICONSPACING =        38,
+	SM_CYICONSPACING =        39,
+	SM_MENUDROPALIGNMENT =    40,
+	SM_PENWINDOWS =           41,
+	SM_DBCSENABLED =          42,
+	SM_CMOUSEBUTTONS =        43,
+
+
+	SM_CXFIXEDFRAME =         SM_CXDLGFRAME,
+	SM_CYFIXEDFRAME =         SM_CYDLGFRAME,
+	SM_CXSIZEFRAME =          SM_CXFRAME,
+	SM_CYSIZEFRAME =          SM_CYFRAME,
+
+	SM_SECURE =               44,
+	SM_CXEDGE =               45,
+	SM_CYEDGE =               46,
+	SM_CXMINSPACING =         47,
+	SM_CYMINSPACING =         48,
+	SM_CXSMICON =             49,
+	SM_CYSMICON =             50,
+	SM_CYSMCAPTION =          51,
+	SM_CXSMSIZE =             52,
+	SM_CYSMSIZE =             53,
+	SM_CXMENUSIZE =           54,
+	SM_CYMENUSIZE =           55,
+	SM_ARRANGE =              56,
+	SM_CXMINIMIZED =          57,
+	SM_CYMINIMIZED =          58,
+	SM_CXMAXTRACK =           59,
+	SM_CYMAXTRACK =           60,
+	SM_CXMAXIMIZED =          61,
+	SM_CYMAXIMIZED =          62,
+	SM_NETWORK =              63,
+	SM_CLEANBOOT =            67,
+	SM_CXDRAG =               68,
+	SM_CYDRAG =               69,
+	SM_SHOWSOUNDS =           70,
+	SM_CXMENUCHECK =          71,
+	SM_CYMENUCHECK =          72,
+	SM_SLOWMACHINE =          73,
+	SM_MIDEASTENABLED =       74,
+	SM_CMETRICS =             75,
+}
+
+int GetSystemMetrics(int nIndex);
+
+}
Index: d/phobos/std/c/linux/socket.d
===================================================================
--- d/phobos/std/c/linux/socket.d	(Revision 199)
+++ d/phobos/std/c/linux/socket.d	(Arbeitskopie)
@@ -235,6 +235,7 @@
 	MSG_OOB =        0x1,
 	MSG_PEEK =       0x2,
 	MSG_DONTROUTE =  0x4,
+        MSG_NOSIGNAL =   0x4000,
 }
 
 
Index: d/phobos/std/c/stdlib.d
===================================================================
--- d/phobos/std/c/stdlib.d	(Revision 199)
+++ d/phobos/std/c/stdlib.d	(Arbeitskopie)
@@ -1,6 +1,7 @@
 /**
  * C's <stdlib.h>
- * Authors: Walter Bright, Digital Mars, www.digitalmars.com
+ * D Programming Language runtime library
+ * Authors: Walter Bright, Digital Mars, http://www.digitalmars.com
  * License: Public Domain
  * Macros:
  *	WIKI=Phobos/StdCStdlib
Index: d/phobos/std/zlib.d
===================================================================
--- d/phobos/std/zlib.d	(Revision 199)
+++ d/phobos/std/zlib.d	(Arbeitskopie)
@@ -20,7 +20,7 @@
 
 //debug=zlib;		// uncomment to turn on debugging printf's
 
-private import etc.c.zlib, std.stdint, std.gc;
+private import etc.c.zlib, std.stdint;
 
 // Values for 'mode'
 
@@ -117,13 +117,13 @@
 body
 {
     int err;
-    void[] destbuf;
+    ubyte[] destbuf;
     Culong_t destlen;
 
     destlen = srcbuf.length + ((srcbuf.length + 1023) / 1024) + 12;
-    destbuf = new void[destlen];
+    destbuf = new ubyte[destlen];
     std.gc.hasNoPointers(destbuf.ptr);
-    err = etc.c.zlib.compress2(cast(ubyte *)destbuf, &destlen, cast(ubyte *)srcbuf, srcbuf.length, level);
+    err = etc.c.zlib.compress2(destbuf.ptr, &destlen, cast(ubyte *)srcbuf, srcbuf.length, level);
     if (err)
     {	delete destbuf;
 	throw new ZlibException(err);
@@ -153,7 +153,7 @@
 void[] uncompress(void[] srcbuf, size_t destlen = 0u, int winbits = 15)
 {
     int err;
-    void[] destbuf;
+    ubyte[] destbuf;
 
     if (!destlen)
 	destlen = srcbuf.length * 2 + 1;
@@ -162,13 +162,12 @@
     {
 	etc.c.zlib.z_stream zs;
 
-	destbuf = new void[destlen];
-	std.gc.hasNoPointers(destbuf.ptr);
+	destbuf = new ubyte[destlen];
 
 	zs.next_in = cast(ubyte*) srcbuf;
 	zs.avail_in = srcbuf.length;
 
-	zs.next_out = cast(ubyte*)destbuf;
+	zs.next_out = destbuf.ptr;
 	zs.avail_out = destlen;
 
 	err = etc.c.zlib.inflateInit2(&zs, winbits);
@@ -291,7 +290,7 @@
      */
     void[] compress(void[] buf)
     {	int err;
-	void[] destbuf;
+	ubyte[] destbuf;
 
 	if (buf.length == 0)
 	    return null;
@@ -304,9 +303,8 @@
 	    inited = 1;
 	}
 
-	destbuf = new void[zs.avail_in + buf.length];
-	std.gc.hasNoPointers(destbuf.ptr);
-	zs.next_out = cast(ubyte*) destbuf.ptr;
+	destbuf = new ubyte[zs.avail_in + buf.length];
+	zs.next_out = destbuf.ptr;
 	zs.avail_out = destbuf.length;
 
 	if (zs.avail_in)
@@ -455,7 +453,7 @@
     }
     body
     {	int err;
-	void[] destbuf;
+	ubyte[] destbuf;
 
 	if (buf.length == 0)
 	    return null;
@@ -470,9 +468,8 @@
 
 	if (!destbufsize)
 	    destbufsize = buf.length * 2;
-	destbuf = new void[zs.avail_in * 2 + destbufsize];
-	std.gc.hasNoPointers(destbuf.ptr);
-	zs.next_out = cast(ubyte*) destbuf;
+	destbuf = new ubyte[zs.avail_in * 2 + destbufsize];
+	zs.next_out = destbuf.ptr;
 	zs.avail_out = destbuf.length;
 
 	if (zs.avail_in)
@@ -506,8 +503,8 @@
     }
     body
     {
-	void[] extra;
-	void[] destbuf;
+	ubyte[] extra;
+	ubyte[] destbuf;
 	int err;
 
 	done = 1;
@@ -515,9 +512,8 @@
 	    return null;
 
       L1:
-	destbuf = new void[zs.avail_in * 2 + 100];
-	std.gc.hasNoPointers(destbuf.ptr);
-	zs.next_out = cast(ubyte*) destbuf;
+	destbuf = new ubyte[zs.avail_in * 2 + 100];
+	zs.next_out = destbuf.ptr;
 	zs.avail_out = destbuf.length;
 
 	err = etc.c.zlib.inflate(&zs, Z_NO_FLUSH);
@@ -533,7 +529,7 @@
 		err = Z_BUF_ERROR;
 	    error(err);
 	}
-	destbuf = cast(void[])((cast(ubyte*)destbuf)[0 .. zs.next_out - cast(ubyte*)destbuf]);
+	destbuf = destbuf.ptr[0 .. zs.next_out - destbuf.ptr];
 	err = etc.c.zlib.inflateEnd(&zs);
 	inited = 0;
 	if (err)
Index: d/phobos/std/conv.d
===================================================================
--- d/phobos/std/conv.d	(Revision 199)
+++ d/phobos/std/conv.d	(Arbeitskopie)
@@ -1,4 +1,3 @@
-
 // Written in the D programming language.
 
 /*
@@ -944,6 +943,11 @@
     // nan
     f = toFloat("nan");
     assert(toString(f) == toString(float.nan));
+    
+    bool ok = false;
+    try toFloat("\x00");
+    catch (ConvError e) ok = true;
+    assert(ok);
 }
 
 /*******************************************************
@@ -1013,6 +1017,11 @@
     d = toDouble("nan");
     assert(toString(d) == toString(double.nan));
     //assert(cast(real)d == cast(real)double.nan);
+    
+    bool ok = false;
+    try toDouble("\x00");
+    catch (ConvError e) ok = true;
+    assert(ok);
 }
 
 /*******************************************************
@@ -1086,6 +1095,11 @@
     r = toReal(toString(real.nan));
     assert(toString(r) == toString(real.nan));
     //assert(r == real.nan);
+
+    bool ok = false;
+    try toReal("\x00");
+    catch (ConvError e) ok = true;
+    assert(ok);
 }
 
 version (none)
Index: d/phobos/std/thread.d
===================================================================
--- d/phobos/std/thread.d	(Revision 199)
+++ d/phobos/std/thread.d	(Arbeitskopie)
@@ -1,5 +1,5 @@
 /*
- *  Copyright (C) 2002-2006 by Digital Mars, www.digitalmars.com
+ *  Copyright (C) 2002-2007 by Digital Mars, www.digitalmars.com
  *  Written by Walter Bright
  *
  *  This software is provided 'as-is', without any express or implied
@@ -40,6 +40,8 @@
 
 module std.thread;
 
+import std.c.stdio;
+
 //debug=thread;
 
 /* ================================ Win32 ================================= */
@@ -56,6 +58,8 @@
 	stdfp start_addr, void* arglist, uint initflag,
 	thread_id* thrdaddr);
 
+private const uint  WAIT_TIMEOUT = 258;
+
 /**
  * The type of the thread handle used by the operating system.
  * For Windows, it is equivalent to a HANDLE from windows.d.
@@ -69,7 +73,7 @@
  */
 class ThreadError : Error
 {
-    this(char[] s)
+    this(string s)
     {
 	super("Thread error: " ~ s);
     }
@@ -110,6 +114,17 @@
     }
 
     /**
+     * Destructor
+     *
+     * If the thread hasn't been joined yet, detach it.
+     */
+    ~this()
+    {
+	if (state != TS.FINISHED)
+	    CloseHandle(hdl);
+    }
+
+    /**
      * The handle to this thread assigned by the operating system. This is set
      * to thread_id.init if the thread hasn't been started yet.
      */
@@ -123,11 +138,11 @@
      */
     void start()
     {
+	synchronized (Thread.classinfo)
+	{
 	if (state != TS.INITIAL)
 	    error("already started");
 
-	synchronized (threadLock)
-	{
 	    for (int i = 0; 1; i++)
 	    {
 		if (i == allThreads.length)
@@ -141,17 +156,19 @@
 		}
 	    }
 	    nthreads++;
-	}
 
 	state = TS.RUNNING;
 	hdl = _beginthreadex(null, cast(uint)stacksize, &threadstart, cast(void*)this, 0, &id);
 	if (hdl == cast(thread_hdl)0)
-	{   state = TS.TERMINATED;
+	{
 	    allThreads[idx] = null;
+	    nthreads--;
+	    state = TS.FINISHED;
 	    idx = -1;
 	    error("failed to start");
 	}
     }
+    }
 
     /**
      * Entry point for a thread. If not overridden, it calls the function
@@ -176,12 +193,15 @@
      */
     void wait()
     {
-	if (this is getThis())
+	if (isSelf)
 	    error("wait on self");
-	if (state == TS.RUNNING)
+	if (state != TS.FINISHED)
 	{   DWORD dw;
 
 	    dw = WaitForSingleObject(hdl, 0xFFFFFFFF);
+	    state = TS.FINISHED;
+	    CloseHandle(hdl);
+	    hdl = null;
 	}
     }
 
@@ -193,12 +213,18 @@
      */
     void wait(uint milliseconds)
     {
-	if (this is getThis())
+	if (isSelf)
 	    error("wait on self");
-	if (state == TS.RUNNING)
+	if (state != TS.FINISHED)
 	{   DWORD dw;
 
 	    dw = WaitForSingleObject(hdl, milliseconds);
+	    if (dw != WAIT_TIMEOUT)
+	    {
+		state = TS.FINISHED;
+		CloseHandle(hdl);
+		hdl = null;
+	    }
 	}
     }
 
@@ -209,7 +235,8 @@
     {
 	INITIAL,	/// The thread hasn't been started yet.
 	RUNNING,	/// The thread is running or paused.
-	TERMINATED	/// The thread has ended.
+	TERMINATED,	/// The thread has ended.
+	FINISHED	/// The thread has been cleaned up
     }
 
     /**
@@ -228,7 +255,8 @@
 	INCREASE,	/// Increase thread priority
 	DECREASE,	/// Decrease thread priority
 	IDLE,		/// Assign thread low priority
-	CRITICAL	/// Assign thread high priority
+	CRITICAL,	/// Assign thread high priority
+	NORMAL
     }
 
     /**
@@ -253,6 +281,9 @@
 	    case PRIORITY.CRITICAL:
 		nPriority = THREAD_PRIORITY_TIME_CRITICAL;
 		break;
+	    case PRIORITY.NORMAL:
+		nPriority = THREAD_PRIORITY_NORMAL;
+		break;
 	    default:
 		assert(0);
 	}
@@ -276,13 +307,8 @@
      */
     static Thread getThis()
     {
-	thread_id id;
-	Thread result;
-
 	//printf("getThis(), allThreadsDim = %d\n", allThreadsDim);
-	synchronized (threadLock)
-	{
-	    id = GetCurrentThreadId();
+	    thread_id id = GetCurrentThreadId();
 	    for (int i = 0; i < allThreadsDim; i++)
 	    {
 		Thread t = allThreads[i];
@@ -291,10 +317,8 @@
 		    return t;
 		}
 	    }
-	}
 	printf("didn't find it\n");
-	assert(result);
-	return result;
+	assert(0);
     }
 
     /**
@@ -302,7 +326,7 @@
      */
     static Thread[] getAll()
     {
-	return allThreads[0 .. allThreadsDim];
+	synchronized (Thread.classinfo) return allThreads[0 .. allThreadsDim];
     }
 
     /**
@@ -328,38 +352,42 @@
      */
     static void pauseAll()
     {
+	synchronized (Thread.classinfo)
+	{
 	if (nthreads > 1)
 	{
-	    Thread tthis = getThis();
+	    thread_id thisid = GetCurrentThreadId();
 
 	    for (int i = 0; i < allThreadsDim; i++)
-	    {   Thread t;
-
-		t = allThreads[i];
-		if (t && t !is tthis && t.state == TS.RUNNING)
+	    { 
+		Thread t = allThreads[i];
+		if (t && t.id != thisid && t.state == TS.RUNNING)
 		    t.pause();
 	    }
 	}
     }
+    }
 
     /**
      * Resume execution of all paused threads.
      */
     static void resumeAll()
     {
+	synchronized (Thread.classinfo)
+	{
 	if (nthreads > 1)
 	{
-	    Thread tthis = getThis();
+	    thread_id thisid = GetCurrentThreadId();
 
 	    for (int i = 0; i < allThreadsDim; i++)
-	    {   Thread t;
-
-		t = allThreads[i];
-		if (t && t !is tthis && t.state == TS.RUNNING)
+	    { 
+		Thread t = allThreads[i];
+		if (t && t.id != thisid && t.state == TS.RUNNING)
 		    t.resume();
 	    }
 	}
     }
+    }
 
     /**
      * Give up the remainder of this thread's time slice.
@@ -377,7 +405,6 @@
   private:
 
     static uint allThreadsDim;
-    static Object threadLock;
     static Thread[0x400] allThreads;	// length matches value in C runtime
 
     TS state;
@@ -390,7 +417,7 @@
 
     int delegate() dg;
 
-    void error(char[] msg)
+    void error(string msg)
     {
 	throw new ThreadError(msg);
     }
@@ -413,16 +440,18 @@
 	}
 	catch (Object o)
 	{
-	    printf("Error: ");
-	    o.print();
+	    fprintf(stderr, "Error: %.*s\n", o.toString());
 	    result = 1;
 	}
 
 	debug (thread) printf("Ending thread %d\n", t.idx);
+	synchronized (Thread.classinfo)
+	{
+	allThreads[t.idx] = null;
+	nthreads--;
 	t.state = TS.TERMINATED;
-	allThreads[t.idx] = null;
 	t.idx = -1;
-	nthreads--;
+	}
 	return result;
     }
 
@@ -433,8 +462,6 @@
 
     public static void thread_init()
     {
-	threadLock = new Object();
-
 	Thread t = new Thread();
 
 	t.state = TS.RUNNING;
@@ -536,7 +563,7 @@
 
 class ThreadError : Error
 {
-    this(char[] s)
+    this(string s)
     {
 	super("Thread error: " ~ s);
     }
@@ -568,6 +595,8 @@
     {
 	pthread_cond_destroy(&waitCond);
 	pthread_mutex_destroy(&waitMtx);
+	if (state != TS.FINISHED)
+	    pthread_detach(id);
     }
 
     pthread_t id;
@@ -579,7 +608,7 @@
 	if (state != TS.INITIAL)
 	    error("already started");
 
-	synchronized (threadLock)
+	synchronized (Thread.classinfo)
 	{
 	    for (int i = 0; 1; i++)
 	    {
@@ -596,14 +625,13 @@
 	    nthreads++;
 
 	    state = TS.RUNNING;
-	    int result;
 	    //printf("creating thread x%x\n", this);
 	    //result = pthread_create(&id, null, &threadstart, this);
 	    // Create with thread attributes to allow non-default stack size - Dave Fladebo
-	    result = pthread_create(&id, &threadAttrs, &threadstart, cast(void*)this);
+	    int result = pthread_create(&id, &threadAttrs, &threadstart, cast(void*)this);
 	    if (result)
-	    {   state = TS.TERMINATED;
-		allThreads[idx] = null;
+	    {   state = TS.FINISHED;
+		synchronized (Thread.classinfo) allThreads[idx] = null;
 		idx = -1;
 		error("failed to start");	// BUG: should report errno
 	    }
@@ -622,25 +650,15 @@
 
     void wait()
     {
-	if (this is getThis())
+	if (isSelf)
 	    error("wait on self");
 
-	/* Sean Kelly writes:
-	 * Change to:
-	 *   if (state != TS.INITIAL)
-	 * Because it is not only legal to call pthread_join on a thread that
-	 * has run and finished, but calling pthread_join or pthread_detach is
-	 * required for the thread resources to be released.  However, it is
-	 * illegal to call pthread_join more than once, and I believe it is also
-	 * illegal to detach a thread that has already been joined, so 'id'
-	 * should probably be cleared after join/detach is called, and this
-	 * value tested along with 'state' before performing thread ops.
-	 */
-	if (state == TS.RUNNING)
-	{   int result;
+	if (state != TS.FINISHED)
+	{
 	    void *value;
 
-	    result = pthread_join(id, &value);
+	    int result = pthread_join(id, &value);
+	    state = TS.FINISHED;
 	    if (result)
 		error("failed to wait");
 	}
@@ -649,9 +667,9 @@
     void wait(uint milliseconds)
     {
 	// Implemented for POSIX systems by Dave Fladebo
-	if (this is getThis())
+	if (isSelf)
 	    error("wait on self");
-	if (state == TS.RUNNING)
+	if (state != TS.FINISHED)
 	{
 	    timespec ts; 
 	    timeval  tv;
@@ -683,9 +701,12 @@
 		pthread_setcanceltype(oldtype, null);
 
 		state = TS.TERMINATED;
+		synchronized (Thread.classinfo)
+		{
 		allThreads[idx] = null;
 		idx = -1;
 		nthreads--;
+		}
 
 		pthread_mutex_unlock(&waitMtx);
 	    }
@@ -699,9 +720,10 @@
 
     enum TS
     {
-	INITIAL,
-	RUNNING,
-	TERMINATED
+	INITIAL,	// created
+	RUNNING,	// running
+	TERMINATED,	// execution finished
+	FINISHED	// pthread_join()'ed
     }
 
     TS getState()
@@ -751,13 +773,8 @@
 
     static Thread getThis()
     {
-	pthread_t id;
-	Thread result;
-
 	//printf("getThis(), allThreadsDim = %d\n", allThreadsDim);
-	//synchronized (threadLock)
-	{
-	    id = pthread_self();
+	    pthread_t id = pthread_self();
 	    //printf("id = %d\n", id);
 	    for (int i = 0; i < allThreadsDim; i++)
 	    {
@@ -768,15 +785,13 @@
 		    return t;
 		}
 	    }
-	}
 	printf("didn't find it\n");
-	assert(result);
-	return result;
+	assert(null);
     }
 
     static Thread[] getAll()
     {
-	return allThreads[0 .. allThreadsDim];
+	synchronized (Thread.classinfo) return allThreads[0 .. allThreadsDim];
     }
 
     void pause()
@@ -789,10 +804,9 @@
 		    error("cannot pause");
 	    }
 	    else
-	    {   int result;
+	    {
 
-		result = pthread_kill(id, SIGUSR1);
-		if (result)
+		if (pthread_kill(id, SIGUSR1))
 		    error("cannot pause");
 		else
 		    flagSuspend.wait();	// wait for acknowledgement
@@ -812,10 +826,8 @@
 		    error("cannot pause");
 	    }
 	    else
-	    {   int result;
-
-		result = pthread_kill(id, SIGUSR2);
-		if (result)
+	    {
+		if (pthread_kill(id, SIGUSR2))
 		    error("cannot resume");
 	    }
 	}
@@ -825,24 +837,21 @@
 
     static void pauseAll()
     {
+	synchronized(Thread.classinfo)
+	{
 	version (GNU_pthread_suspend)
 	{
 	    if (nthreads > 1)
 	    {
-		Thread tthis = getThis();
-
-		synchronized (threadLock)
-		{
+		pthread_t thisid = pthread_self();
 		    
 		for (int i = 0; i < allThreadsDim; i++)
-		{   Thread t;
+		{
 
-		    t = allThreads[i];
-		    if (t && t !is tthis && t.state == TS.RUNNING)
+		    Thread t = allThreads[i];
+		    if (t && !pthread_equal(thisid, t.id) && t.state == TS.RUNNING)
 			t.pause();
 		}
-
-		}
 	    }
 	}
 	else
@@ -850,54 +859,50 @@
 	
 	if (nthreads > 1)
 	{
-	    Thread tthis = getThis();
+	    pthread_t thisid = pthread_self();
 	    int npause = 0;
 
-	    synchronized (threadLock)
+	    for (int i = 0; i < allThreadsDim; i++)
 	    {
-		
-	    for (int i = 0; i < allThreadsDim; i++)
-	    {   Thread t;
 
-		t = allThreads[i];
-		if (t && t !is tthis && t.state == TS.RUNNING)
-		{   int result;
-
-		    result = pthread_kill(t.id, SIGUSR1);
-		    if (result)
+		Thread t = allThreads[i];
+		if (t && !pthread_equal(thisid, t.id) && t.state == TS.RUNNING)
+		{
+		    if (pthread_kill(t.id, SIGUSR1))
 			getThis().error("cannot pause");
 		    else
 			npause++;	// count of paused threads
 		}
 	    }
 
-	    }
-	    
 	    // Wait for each paused thread to acknowledge
 	    while (npause--)
 	    {
 		flagSuspend.wait();
 	    }
 	}
-
 	}
+	}
     }
 
     static void resumeAll()
     {
+	synchronized (Thread.classinfo)
+	{
 	if (nthreads > 1)
 	{
-	    Thread tthis = getThis();
+	    pthread_t thisid = pthread_self();
 
 	    for (int i = 0; i < allThreadsDim; i++)
-	    {   Thread t;
+	    {
 
-		t = allThreads[i];
-		if (t && t !is tthis && t.state == TS.RUNNING)
+		Thread t = allThreads[i];
+		if (t && t.id != thisid && t.state == TS.RUNNING)
 		    t.resume();
 	    }
 	}
     }
+    }
 
     static void yield()
     {
@@ -909,7 +914,6 @@
   private:
 
     static uint allThreadsDim;
-    static Object threadLock;
  
     // Set max to Windows equivalent for compatibility.
     // pthread_create will fail gracefully if stack limit
@@ -938,7 +942,7 @@
 
     int delegate() dg;
 
-    void error(char[] msg)
+    void error(string msg)
     {
 	throw new ThreadError(msg);
     }
@@ -978,7 +982,7 @@
 	t.id = pthread_self();
 
 	version(skyos)
-	    installSignalHandlers();
+	    installSignalHandlers(t);
 
 	t.stackBottom = getESP();
 	try
@@ -989,15 +993,14 @@
 	}
 	catch (Object o)
 	{
-	    printf("Error: ");
-	    o.print();
+	    fprintf(stderr, "Error: %.*s\n", o.toString());
 	    result = 1;
 	}
 
 	debug (thread) printf("Ending thread %d\n", t.idx);
-	synchronized (threadLock)
+	    t.state = TS.TERMINATED;
+	synchronized (Thread.classinfo)
 	{
-	    t.state = TS.TERMINATED;
 	    allThreads[t.idx] = null;
 	    t.idx = -1;
 	    nthreads--;
@@ -1012,8 +1015,6 @@
 
     public static void thread_init()
     {
-	threadLock = new Object();
-
 	Thread t = new Thread();
 
 	t.state = TS.RUNNING;
@@ -1033,7 +1034,7 @@
 	{
 	    /* Install signal handlers so we can suspend/resume threads
 	     */
-	    installSignalHandlers();
+	    installSignalHandlers(t);
 	}
 
 	return;
@@ -1047,7 +1048,7 @@
     else
     {
     
-	private static void installSignalHandlers()
+	private static void installSignalHandlers(Thread t)
 	{
 	    int result;
 	    sigaction_t sigact;
@@ -1068,7 +1069,7 @@
 
 	    return;
 	    Lfail:
-	    getThis().error("cannot initialize threads");
+	    t.error("cannot initialize threads");
 	}
 
 	
Index: d/phobos/std/moduleinit.d
===================================================================
--- d/phobos/std/moduleinit.d	(Revision 199)
+++ d/phobos/std/moduleinit.d	(Arbeitskopie)
@@ -1,3 +1,4 @@
+// Written in the D programming language
 
 /* NOTE: This file has been patched from the original DMD distribution to
    work with the GDC compiler.
@@ -23,6 +24,7 @@
     MIctordone = 2,	// finished construction
     MIstandalone = 4,	// module ctor does not depend on other module
 			// ctors being done first
+    MIhasictor = 8,	// has ictor member
 }
 
 /***********************
@@ -36,10 +38,14 @@
 
     uint flags;		// initialization state
 
-    void (*ctor)();
-    void (*dtor)();
-    void (*unitTest)();
+    void (*ctor)();	// module static constructor (order dependent)
+    void (*dtor)();	// module static destructor
+    void (*unitTest)();	// module unit tests
 
+    void* xgetMembers;	// module getMembers() function
+
+    void (*ictor)();	// module static constructor (order independent)
+
     /******************
      * Return collection of all modules in the program.
      */
@@ -53,7 +59,8 @@
 {
     this(ModuleInfo m)
     {
-	super("circular initialization dependency with module " ~ m.name);
+	super(cast(string) ("circular initialization dependency with module "
+                            ~ m.name));
     }
 }
 
@@ -119,6 +126,7 @@
 
     _moduleinfo_dtors = new ModuleInfo[_moduleinfo_array.length];
     debug printf("_moduleinfo_dtors = x%x\n", cast(void *)_moduleinfo_dtors);
+    _moduleIndependentCtors();
     _moduleCtor2(_moduleinfo_array, 0);
 
     version (none)
@@ -227,3 +235,20 @@
     }
 }
 
+/**********************************
+ * Run unit tests.
+ */
+
+extern (C) void _moduleIndependentCtors()
+{
+    debug printf("_moduleIndependentCtors()\n");
+    foreach (m; _moduleinfo_array)
+    {
+	if (m && m.flags & MIhasictor && m.ictor)
+	{
+	    (*m.ictor)();
+	}
+    }
+}
+
+
Index: d/phobos/std/mmfile.d
===================================================================
--- d/phobos/std/mmfile.d	(Revision 199)
+++ d/phobos/std/mmfile.d	(Arbeitskopie)
@@ -1,4 +1,6 @@
-/* Copyright 2004-2005 by Digital Mars
+// Written in the D programming language
+
+/* Copyright 2004-2008 by Digital Mars
  * Written by Walter Bright and Matthew Wilson
  *
  * This software is provided 'as-is', without any express or implied
@@ -105,7 +107,7 @@
      * Throws:
      *	std.file.FileException
      */
-    this(char[] filename)
+    this(string filename)
     {
 		this(filename, Mode.Read, 0, null);
     }
@@ -128,7 +130,7 @@
      * Throws:
      *	std.file.FileException
      */
-    this(char[] filename, Mode mode, ulong size, void* address,
+    this(string filename, Mode mode, ulong size, void* address,
 			size_t window = 0)
     {
 		this.filename = filename;
@@ -194,9 +196,11 @@
 				assert(0);
 			}
 		
+			if (filename)
+			{
 			if (useWfuncs)
 			{
-				wchar* namez = std.utf.toUTF16z(filename);
+					auto namez = std.utf.toUTF16z(filename);
 				hFile = CreateFileW(namez,
 						dwDesiredAccess2,
 						dwShareMode,
@@ -207,7 +211,7 @@
 			}
 			else
 			{
-				char* namez = std.file.toMBSz(filename);
+					auto namez = std.file.toMBSz(filename);
 				hFile = CreateFileA(namez,
 						dwDesiredAccess2,
 						dwShareMode,
@@ -218,6 +222,9 @@
 			}
 			if (hFile == INVALID_HANDLE_VALUE)
 				goto err1;
+			}
+			else
+				hFile = null;
 		
 			int hi = cast(int)(size>>32);
 			hFileMap = CreateFileMappingA(hFile, null, flProtect, hi, cast(uint)size, null);
@@ -360,7 +367,7 @@
 				errNo();
 			hFileMap = null;
 
-			if (hFile != INVALID_HANDLE_VALUE && CloseHandle(hFile) != TRUE)
+			if (hFile && hFile != INVALID_HANDLE_VALUE && CloseHandle(hFile) != TRUE)
 				errNo();
 			hFile = INVALID_HANDLE_VALUE;
 		}
@@ -552,7 +559,7 @@
 	}
 
 	private:
-	char[] filename;
+	string filename;
 	void[] data;
 	ulong  start;
 	size_t window;
@@ -634,5 +641,8 @@
 	assert( data2[length-1] == 'b' );
 	delete mf;
 	std.file.remove("testing.txt");
+	
+	// Create anonymous mapping
+	auto test = new MmFile(null, MmFile.Mode.ReadWriteNew, 1024*1024, null);
     }
 }
Index: d/phobos/std/file.d
===================================================================
--- d/phobos/std/file.d	(Revision 199)
+++ d/phobos/std/file.d	(Arbeitskopie)
@@ -852,11 +852,10 @@
 
 private import std.c.unix.unix;
 private import std.date;
+private import std.c.string;
 
 alias std.c.unix.unix unix;
 
-extern (C) char* strerror(int);
-
 /***********************************
  */
 
@@ -876,7 +875,8 @@
     }
 
     this(char[] name, uint errno)
-    {	char* s = strerror(errno);
+    {	char[80] buf = void;
+	auto s = strerror_r(errno, buf.ptr, buf.length);
 	this(name, std.string.toString(s).dup);
 	this.errno = errno;
     }
Index: d/phobos/std/socket.d
===================================================================
--- d/phobos/std/socket.d	(Revision 199)
+++ d/phobos/std/socket.d	(Arbeitskopie)
@@ -108,12 +108,10 @@
 		{
 			if(errorCode > 0)
 			{
-				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')
@@ -484,7 +482,8 @@
 	 */	
 	bool getHostByName(string name)
 	{
-		hostent* he = gethostbyname(toStringz(name));
+		hostent* he;
+                synchronized(this.classinfo) he = gethostbyname(toStringz(name));
 		if(!he)
 			return false;
 		validHostent(he);
@@ -499,7 +498,8 @@
 	bool getHostByAddr(uint addr)
 	{
 		uint x = htonl(addr);
-		hostent* he = gethostbyaddr(&x, 4, cast(int)AddressFamily.INET);
+		hostent* he;
+                synchronized(this.classinfo) he = gethostbyaddr(&x, 4, cast(int)AddressFamily.INET);
 		if(!he)
 			return false;
 		validHostent(he);
@@ -516,7 +516,8 @@
 	bool getHostByAddr(string addr)
 	{
 		uint x = inet_addr(std.string.toStringz(addr));
-		hostent* he = gethostbyaddr(&x, 4, cast(int)AddressFamily.INET);
+		hostent* he;
+                synchronized(this.classinfo) he = gethostbyaddr(&x, 4, cast(int)AddressFamily.INET);
 		if(!he)
 			return false;
 		validHostent(he);
@@ -764,6 +765,7 @@
 	OOB =        MSG_OOB,	/// out-of-band stream data
 	PEEK =       MSG_PEEK,	/// peek at incoming data without removing it from the queue, only for receiving
 	DONTROUTE =  MSG_DONTROUTE, /// data should not be subject to routing; this flag may be ignored. Only for sending
+        NOSIGNAL =   MSG_NOSIGNAL,  /// don't send SIGPIPE signal on socket write error and instead return EPIPE
 }
 
 
@@ -1325,6 +1327,7 @@
 	//returns number of bytes actually sent, or -1 on error
 	int send(void[] buf, SocketFlags flags)
 	{
+                flags |= SocketFlags.NOSIGNAL;
 		int sent = .send(sock, buf.ptr, buf.length, cast(int)flags);
 		return sent;
 	}
@@ -1332,7 +1335,7 @@
 	/// ditto
 	int send(void[] buf)
 	{
-		return send(buf, SocketFlags.NONE);
+		return send(buf, SocketFlags.NOSIGNAL);
 	}
 	
 	/**
@@ -1340,6 +1343,7 @@
 	 */
 	int sendTo(void[] buf, SocketFlags flags, Address to)
 	{
+                flags |= SocketFlags.NOSIGNAL;
 		int sent = .sendto(sock, buf.ptr, buf.length, cast(int)flags, to.name(), to.nameLen());
 		return sent;
 	}
@@ -1355,6 +1359,7 @@
 	/// ditto
 	int sendTo(void[] buf, SocketFlags flags)
 	{
+                flags |= SocketFlags.NOSIGNAL;
 		int sent = .sendto(sock, buf.ptr, buf.length, cast(int)flags, null, 0);
 		return sent;
 	}
Index: d/phobos/unittest.d
===================================================================
--- d/phobos/unittest.d	(Revision 199)
+++ d/phobos/unittest.d	(Arbeitskopie)
@@ -52,6 +52,7 @@
 import std.file;
 import std.signals;
 import std.cpuid;
+import std.socket;
 
 int main(char[][] args)
 {
Index: d/phobos/std.ddoc
===================================================================
--- d/phobos/std.ddoc	(Revision 199)
+++ d/phobos/std.ddoc	(Arbeitskopie)
@@ -3,7 +3,7 @@
 <html>
 
 <!--
-	Copyright (c) 1999-2006 by Digital Mars
+	Copyright (c) 1999-2008 by Digital Mars
 	All Rights Reserved
 	Written by Walter Bright
 	www.digitalmars.com
@@ -62,7 +62,7 @@
 
 <div id="copyright">
 $(COPYRIGHT) |
-Page generated by $(LINK2 http://www.digitalmars.com/d/ddoc.html, Ddoc).
+Page generated by $(LINK2 http://www.digitalmars.com/d/1.0/ddoc.html, Ddoc).
 </div>
 
 </body>
@@ -89,7 +89,7 @@
 <div id="searchbox">
 <input id="q" name="q" size="10" value="RTL Search" onFocus='if(this.value == "RTL Search"){this.value="";}'>
 <input type="hidden" id="domains" name="domains" value="www.digitalmars.com">
-<input type="hidden" id="sitesearch" name="sitesearch" value="www.digitalmars.com/d/phobos">
+<input type="hidden" id="sitesearch" name="sitesearch" value="www.digitalmars.com/d/1.0/phobos">
 <input type="hidden" id="sourceid" name="sourceid" value="google-search">
 <input type="submit" id="submit" name="submit" value="Go">
 </div>
Index: d/phobos/linux.mak
===================================================================
--- d/phobos/linux.mak	(Revision 199)
+++ d/phobos/linux.mak	(Arbeitskopie)
@@ -198,17 +198,17 @@
 
 
 #$(LIB) : $(OBJS) internal/gc/dmgc.a linux.mak
-$(LIB) : $(OBJS) internal/gc/dmgc.a $(ZLIB_OBJS) linux.mak
+$(LIB) : $(OBJS) $(GC_OBJS) $(ZLIB_OBJS) linux.mak
 	rm -f $(LIB)
 	ar -r $@ $(OBJS) $(ZLIB_OBJS) $(GC_OBJS)
 
 ###########################################################
 
-internal/gc/dmgc.a:
+$(GC_OBJS):
 #	cd internal/gc
 #	make -f linux.mak dmgc.a
 #	cd ../..
-	make -C ./internal/gc -f linux.mak dmgc.a
+	make -C ./internal/gc -f linux.mak
 
 $(ZLIB_OBJS):
 #	cd etc/c/zlib
@@ -594,3 +594,6 @@
 
 clean:
 	$(RM) $(LIB) $(OBJS) unittest unittest.o
+	make -C ./internal/gc -f linux.mak clean
+	make -C ./etc/c/zlib -f linux.mak clean
+
Index: d/phobos/etc/c/zlib/linux.mak
===================================================================
--- d/phobos/etc/c/zlib/linux.mak	(Revision 199)
+++ d/phobos/etc/c/zlib/linux.mak	(Arbeitskopie)
@@ -74,4 +74,5 @@
 	echo hello world | minigzip | minigzip -d 
 
 clean:
-	$(RM) $(OBJS) zlib.a example minigzip minigzip.o test foo.gz
+	$(RM) $(OBJS) zlib.a example.o example minigzip minigzip.o test foo.gz
+
Index: d/phobos/internal/arraycat.d
===================================================================
--- d/phobos/internal/arraycat.d	(Revision 199)
+++ d/phobos/internal/arraycat.d	(Arbeitskopie)
@@ -3,26 +3,9 @@
  */
 
 /*
- *  Copyright (C) 2004-2007 by Digital Mars, www.digitalmars.com
+ *  http://www.digitalmars.com
  *  Written by Walter Bright
- *
- *  This software is provided 'as-is', without any express or implied
- *  warranty. In no event will the authors be held liable for any damages
- *  arising from the use of this software.
- *
- *  Permission is granted to anyone to use this software for any purpose,
- *  including commercial applications, and to alter it and redistribute it
- *  freely, in both source and binary form, subject to the following
- *  restrictions:
- *
- *  o  The origin of this software must not be misrepresented; you must not
- *     claim that you wrote the original software. If you use this software
- *     in a product, an acknowledgment in the product documentation would be
- *     appreciated but is not required.
- *  o  Altered source versions must be plainly marked as such, and must not
- *     be misrepresented as being the original software.
- *  o  This notice may not be removed or altered from any source
- *     distribution.
+ *  Placed in the Public Domain
  */
 
 /* NOTE: This file has been patched from the original DMD distribution to
@@ -36,28 +19,28 @@
 import object;
 import std.string;
 import std.c.string;
-import std.c.stdio;
-import std.c.stdarg;
 
 extern (C)
-byte[] _d_arraycopy(size_t size, byte[] from, byte[] to)
+void[] _d_arraycopy(uint size, void[] from, void[] to)
 {
-    //printf("f = %p,%d, t = %p,%d, size = %d\n", (void*)from, from.length, (void*)to, to.length, size);
+    //printf("f = %p,%d, t = %p,%d, size = %d\n", from.ptr, from.length, to.ptr, to.length, size);
 
     if (to.length != from.length)
     {
 	//throw new Error(std.string.format("lengths don't match for array copy, %s = %s", to.length, from.length));
-	throw new Error("lengths don't match for array copy," ~
-		toString(to.length) ~ " = " ~ toString(from.length));
+	throw new Error(cast(string) ("lengths don't match for array copy," ~
+                                      toString(to.length) ~ " = "
+                                      ~ toString(from.length)));
     }
-    else if (cast(byte *)to + to.length * size <= cast(byte *)from ||
-	cast(byte *)from + from.length * size <= cast(byte *)to)
+    else if (to.ptr + to.length * size <= from.ptr ||
+	from.ptr + from.length * size <= to.ptr)
     {
-	memcpy(cast(byte *)to, cast(byte *)from, to.length * size);
+	memcpy(to.ptr, from.ptr, to.length * size);
     }
     else
     {
 	throw new Error("overlapping array copy");
+	//memmove(to.ptr, from.ptr, to.length * size);
     }
     return to;
 }
Index: d/phobos/internal/object.d
===================================================================
--- d/phobos/internal/object.d	(Revision 199)
+++ d/phobos/internal/object.d	(Arbeitskopie)
@@ -312,6 +312,9 @@
 
     /********************
      * Create instance of Object represented by 'this'.
+     * Returns:
+     *	the object created, or null if the Object does
+     *	does not have a default constructor
      */
     Object create()
     {
Index: d/phobos/internal/gc/gcx.d
===================================================================
--- d/phobos/internal/gc/gcx.d	(Revision 199)
+++ d/phobos/internal/gc/gcx.d	(Arbeitskopie)
@@ -1,8 +1,28 @@
-//
-// Copyright (C) 2001-2006 by Digital Mars
-// All Rights Reserved
-// Written by Walter Bright
-// www.digitalmars.com
+/**
+ * This module contains the garbage collector implementation.
+ *
+ * Copyright: Copyright (C) 2001-2007 Digital Mars, www.digitalmars.com.
+ *            All rights reserved.
+ * License:
+ *  This software is provided 'as-is', without any express or implied
+ *  warranty. In no event will the authors be held liable for any damages
+ *  arising from the use of this software.
+ *
+ *  Permission is granted to anyone to use this software for any purpose,
+ *  including commercial applications, and to alter it and redistribute it
+ *  freely, in both source and binary form, subject to the following
+ *  restrictions:
+ *
+ *  o  The origin of this software must not be misrepresented; you must not
+ *     claim that you wrote the original software. If you use this software
+ *     in a product, an acknowledgment in the product documentation would be
+ *     appreciated but is not required.
+ *  o  Altered source versions must be plainly marked as such, and must not
+ *     be misrepresented as being the original software.
+ *  o  This notice may not be removed or altered from any source
+ *     distribution.
+ * Authors:   Walter Bright, David Friedman, Sean Kelly
+ */
 
 /* NOTE: This file has been patched from the original DMD distribution to
    work with the GDC compiler.
@@ -32,16 +52,16 @@
 
 /***************************************************/
 
+private import gcbits;
+private import gcstats;
 
-debug (PRINTF) import std.c.stdio;
+private import cstdlib = std.c.stdlib : calloc, free, malloc, realloc;
+private import cstring = std.c.string : memcpy, memmove, memset;
 
-import std.c.stdio;
-import std.c.stdlib;
-import std.c.string;
-import gcbits;
+debug private import std.c.stdio;
+
 import std.outofmemory;
 import std.gc;
-import gcstats;
 
 version (GNU)
 {
@@ -72,7 +92,32 @@
     import std.thread;
 }
 
-//alias GC* gc_t;
+private void onOutOfMemoryError()
+{
+    _d_OutOfMemory();
+}
+
+private void* rt_stackBottom()
+{
+    version (Win32)
+    {
+	return win32.os_query_stackBottom();
+    }
+    version (GNU)
+    {
+	return gcgcc.os_query_stackBottom();
+    }
+    else version (linux)
+    {
+	return gclinux.os_query_stackBottom();
+    }
+}
+
+private bool thread_needLock()
+{
+    return std.thread.Thread.nthreads != 1;
+}
+
 alias GC gc_t;
 
 version (X86) version (D_InlineAsm) { version = Asm86; }
@@ -83,11 +128,11 @@
 {
     struct Log
     {
-	void *p;
+	void* p;
 	size_t size;
 	uint line;
-	char *file;
-	void *parent;
+	char* file;
+	void* parent;
 
 	void print()
 	{
@@ -103,14 +148,13 @@
 
     struct LogArray
     {
-	size_t dim;
-	size_t allocdim;
+	size_t dim, allocdim;
 	Log *data;
 
 	void Dtor()
 	{
 	    if (data)
-		std.c.stdlib.free(data);
+		cstdlib.free(data);
 	    data = null;
 	}
 
@@ -123,18 +167,18 @@
 		assert(dim + nentries <= allocdim);
 		if (!data)
 		{
-		    data = cast(Log *)std.c.stdlib.malloc(allocdim * Log.sizeof);
+		    data = cast(Log *)cstdlib.malloc(allocdim * Log.sizeof);
 		    if (!data && allocdim)
-			_d_OutOfMemory();
+			onOutOfMemoryError();
 		}
 		else
 		{   Log *newdata;
 
-		    newdata = cast(Log *)std.c.stdlib.malloc(allocdim * Log.sizeof);
+		    newdata = cast(Log *)cstdlib.malloc(allocdim * Log.sizeof);
 		    if (!newdata && allocdim)
-			_d_OutOfMemory();
-		    memcpy(newdata, data, dim * Log.sizeof);
-		    std.c.stdlib.free(data);
+			onOutOfMemoryError();
+		    cstring.memcpy(newdata, data, dim * Log.sizeof);
+		    cstdlib.free(data);
 		    data = newdata;
 		}
 	    }
@@ -148,7 +192,7 @@
 
 	void remove(size_t i)
 	{
-	    memmove(data + i, data + i + 1, (dim - i) * Log.sizeof);
+	    cstring.memmove(data + i, data + i + 1, (dim - i) * Log.sizeof);
 	    dim--;
 	}
 
@@ -176,10 +220,8 @@
 
 /* ============================ GC =============================== */
 
+alias void (*GC_FINALIZER)(void *p, bool dummy);
 
-//alias int size_t;
-alias void (*GC_FINALIZER)(void *p, void *dummy);
-
 class GCLock { }		// just a dummy so we can get a global lock
 
 const uint GCVERSION = 1;	// increment every time we change interface
@@ -188,7 +230,7 @@
 class GC
 {
     // For passing to debug code
-    static uint line;
+    static size_t line;
     static char *file;
 
     uint gcversion = GCVERSION;
@@ -199,22 +241,11 @@
     void initialize()
     {
 	gcLock = GCLock.classinfo;
-	gcx = cast(Gcx *)std.c.stdlib.calloc(1, Gcx.sizeof);
+	gcx = cast(Gcx *)cstdlib.calloc(1, Gcx.sizeof);
 	if (!gcx)
-	    _d_OutOfMemory();
+	    onOutOfMemoryError();
 	gcx.initialize();
-	version (Win32)
-	{
-	    setStackBottom(win32.os_query_stackBottom());
-	}
-	else version (GNU)
-	{
-	    setStackBottom(gcgcc.os_query_stackBottom());
-	}
-	else version (linux)
-	{
-	    setStackBottom(gclinux.os_query_stackBottom());
-	}
+	setStackBottom(rt_stackBottom());
     }
 
 
@@ -229,45 +260,90 @@
 	if (gcx)
 	{
 	    gcx.Dtor();
-	    std.c.stdlib.free(gcx);
+	    cstdlib.free(gcx);
 	    gcx = null;
 	}
     }
 
-    invariant
+
+    invariant()
     {
 	if (gcx)
+        {
 	    gcx.thread_Invariant();
     }
+    }
 
+
+    /**
+     *
+     */
+    void enable()
+	{
+        if (!thread_needLock())
+        {
+	    assert(gcx.disabled > 0);
+	    gcx.disabled--;
+        }
+        else synchronized (gcLock)
+	{
+	    assert(gcx.disabled > 0);
+	    gcx.disabled--;
+	}
+    }
+
+
+    /**
+     *
+	     */
+    void disable()
+    {
+        if (!thread_needLock())
+        {
+	    gcx.disabled++;
+        }
+        else synchronized (gcLock)
+	{
+	    gcx.disabled++;
+	}
+    }
+
+
+    /**
+     *
+     */
     void *malloc(size_t size)
-    {	void *p;
+    {
+        if (!size)
+        {
+            return null;
+        }
 
-	if (std.thread.Thread.nthreads == 1)
+	if (!thread_needLock())
 	{
-	    /* Single-threaded no-sync - Dave Fladebo.
-	     * The reason this works is because none of the gc code
-	     * can start up a new thread from within mallocNoSync().
-	     * Skip the sync for speed reasons.
-	     */
 	    return mallocNoSync(size);
 	}
 	else synchronized (gcLock)
 	{
-	    p = mallocNoSync(size);
+	    return mallocNoSync(size);
 	}
-	return p;
     }
 
-    void *mallocNoSync(size_t size)
-    {   void *p = null;
+
+    //
+    //
+    //
+    private void *mallocNoSync(size_t size)
+    {
+        assert(size != 0);
+
+        void *p = null;
 	Bins bin;
 
 	//debug(PRINTF) printf("GC::malloc(size = %d, gcx = %p)\n", size, gcx);
 	assert(gcx);
 	//debug(PRINTF) printf("gcx.self = %x, pthread_self() = %x\n", gcx.self, pthread_self());
-	if (size)
-	{
+
 	    size += SENTINEL_EXTRA;
 
 	    // Compute size bin
@@ -290,7 +366,7 @@
 		{
 		    if (!gcx.allocPage(bin) && !gcx.disabled)	// try to find a new page
 		    {
-			if (std.thread.Thread.nthreads == 1)
+                    if (!thread_needLock())
 			{
 			    /* Then we haven't locked it yet. Be sure
 			     * and lock for a collection, since a finalizer
@@ -319,13 +395,8 @@
 
 		// Return next item from free list
 		gcx.bucket[bin] = (cast(List *)p).next;
-		version(GNU)
-		    memset(p + size, 0, binsize[bin] - size);
-		else
-		    // 'inline' memset - Dave Fladebo.
-		//foreach(inout byte b; cast(byte[])(p + size)[0..binsize[bin] - size]) { b = 0; }
-		//debug(PRINTF) printf("\tmalloc => %x\n", p);
-		debug (MEMSTOMP) memset(p, 0xF0, size);
+		cstring.memset(p + size, 0, binsize[bin] - size);
+		debug (MEMSTOMP) cstring.memset(p, 0xF0, size);
 	    }
 	    else
 	    {
@@ -337,38 +408,49 @@
 	    p = sentinel_add(p);
 	    sentinel_init(p, size);
 	    gcx.log_malloc(p, size);
-	}
 	return p;
     }
 
-
+    /**
+     *
+     */
     void *calloc(size_t size, size_t n)
     {
-	size_t len;
-	void *p;
+	size_t len = size * n;
+	if (!len) return null;
+	if (!thread_needLock()) return callocNoSync(len);
+	else synchronized (gcLock) return callocNoSync(len);
+    }
 
-	len = size * n;
-	p = malloc(len);
+    private void *callocNoSync(size_t size) {
+	assert(size != 0);
+	void *p = mallocNoSync(size);
 	if (p)
 	{   //debug(PRINTF) printf("calloc: %x len %d\n", p, len);
-	    memset(p, 0, len);
+	    cstring.memset(p, 0, size);
 	}
 	return p;
     }
 
-
+    /**
+     *
+     */
     void *realloc(void *p, size_t size)
     {
-	gcx.p_cache = null;
+	if (!thread_needLock()) return reallocNoSync(p, size);
+	else synchronized (gcLock) return reallocNoSync(p, size);
+    }
+    private void *reallocNoSync(void *p, size_t size)
+    {
 	if (!size)
 	{   if (p)
-	    {   free(p);
+	    {   freeNoSync(p);
 		p = null;
 	    }
 	}
 	else if (!p)
 	{
-	    p = malloc(size);
+	    p = mallocNoSync(size);
 	}
 	else
 	{   void *p2;
@@ -381,11 +463,11 @@
 		psize = *sentinel_size(p);
 		if (psize != size)
 		{
-		    p2 = malloc(size);
+		    p2 = mallocNoSync(size);
 		    if (psize < size)
 			size = psize;
 		    //debug(PRINTF) printf("\tcopying %d bytes\n",size);
-		    memcpy(p2, p, size);
+		    cstring.memcpy(p2, p, size);
 		    p = p2;
 		}
 	    }
@@ -404,49 +486,42 @@
 
 		    if (newsz < psz)
 		    {	// Shrink in place
-			synchronized (gcLock)
-			{
-			    debug (MEMSTOMP) memset(p + size, 0xF2, psize - size);
-			    pool.freePages(pagenum + newsz, psz - newsz);
-			}
+			debug (MEMSTOMP) cstring.memset(p + size, 0xF2, psize - size);
+			pool.freePages(pagenum + newsz, psz - newsz);
 			return p;
 		    }
 		    else if (pagenum + newsz <= pool.npages)
 		    {
 			// Attempt to expand in place
-			synchronized (gcLock)
+			for (size_t i = pagenum + psz; 1;)
 			{
-			    for (size_t i = pagenum + psz; 1;)
+			    if (i == pagenum + newsz)
 			    {
-				if (i == pagenum + newsz)
-				{
-				    debug (MEMSTOMP) memset(p + psize, 0xF0, size - psize);
-				    memset(&pool.pagetable[pagenum + psz], B_PAGEPLUS, newsz - psz);
-				    return p;
-				}
-				if (i == pool.ncommitted)
-				{
-				    auto u = pool.extendPages(pagenum + newsz - pool.ncommitted);
-				    if (u == ~0u)
-					break;
-				    i = pagenum + newsz;
-				    continue;
-				}
-				if (pool.pagetable[i] != B_FREE)
+				debug (MEMSTOMP) cstring.memset(p + psize, 0xF0, size - psize);
+				cstring.memset(&pool.pagetable[pagenum + psz], B_PAGEPLUS, newsz - psz);
+				return p;
+			    }
+			    if (i == pool.ncommitted)
+			    {
+				auto u = pool.extendPages(pagenum + newsz - pool.ncommitted);
+				if (u == ~0u)
 				    break;
-				i++;
+				i = pagenum + newsz;
+				continue;
 			    }
+			    if (pool.pagetable[i] != B_FREE) break;
+			    i++;
 			}
 		    }
 		}
 		if (psize < size ||		// if new size is bigger
 		    psize > size * 2)		// or less than half
 		{
-		    p2 = malloc(size);
+		    p2 = mallocNoSync(size);
 		    if (psize < size)
 			size = psize;
 		    //debug(PRINTF) printf("\tcopying %d bytes\n",size);
-		    memcpy(p2, p, size);
+		    cstring.memcpy(p2, p, size);
 		    p = p2;
 		}
 	    }
@@ -454,17 +529,39 @@
 	return p;
     }
 
+
     /**
-     * Attempt to in-place enlarge the memory block pointed to by p
-     * by at least minbytes beyond its current capacity,
-     * up to a maximum of maxbytes.
-     * This does not attempt to move the memory block (like realloc() does).
+     * Attempt to in-place enlarge the memory block pointed to by p by at least
+     * minbytes beyond its current capacity, up to a maximum of maxsize.  This
+     * does not attempt to move the memory block (like realloc() does).
+     *
      * Returns:
      *	0 if could not extend p,
      *	total size of entire memory block if successful.
      */
     size_t extend(void* p, size_t minsize, size_t maxsize)
     {
+        if (!thread_needLock())
+        {
+            return extendNoSync(p, minsize, maxsize);
+        }
+        else synchronized (gcLock)
+        {
+            return extendNoSync(p, minsize, maxsize);
+        }
+    }
+
+
+    //
+    //
+    //
+    private size_t extendNoSync(void* p, size_t minsize, size_t maxsize)
+    in
+    {
+        assert( minsize <= maxsize );
+    }
+    body
+    {
 	//debug(PRINTF) printf("GC::extend(p = %x, minsize = %u, maxsize = %u)\n", p, minsize, maxsize);
 	version (SENTINEL)
 	{
@@ -481,8 +578,6 @@
 	auto pool = gcx.findPool(p);
 	auto pagenum = (p - pool.baseAddr) / PAGESIZE;
 
-	synchronized (gcLock)
-	{
 	    size_t sz;
 	    for (sz = 0; sz < maxsz; sz++)
 	    {
@@ -507,24 +602,47 @@
 	    }
 	    else
 		return 0;
-	    debug (MEMSTOMP) memset(p + psize, 0xF0, (psz + sz) * PAGESIZE - psize);
-	    memset(pool.pagetable + pagenum + psz, B_PAGEPLUS, sz);
+        debug (MEMSTOMP) cstring.memset(p + psize, 0xF0, (psz + sz) * PAGESIZE - psize);
+        cstring.memset(pool.pagetable + pagenum + psz, B_PAGEPLUS, sz);
 	    gcx.p_cache = null;
 	    gcx.size_cache = 0;
 	    return (psz + sz) * PAGESIZE;
 	}
-    }
 
+
+    /**
+     *
+     */
     void free(void *p)
     {
+	if (!p)
+        {
+	    return;
+        }
+
+        if (!thread_needLock())
+        {
+            return freeNoSync(p);
+        }
+        else synchronized (gcLock)
+        {
+            return freeNoSync(p);
+        }
+    }
+
+
+    //
+    //
+    //
+    private void freeNoSync(void *p)
+    {
+        assert (p);
+
 	Pool *pool;
 	uint pagenum;
 	Bins bin;
 	uint biti;
 
-	if (!p)
-	    return;
-
 	// Find which page it is in
 	pool = gcx.findPool(p);
 	if (!pool)				// if not one of ours
@@ -532,18 +650,10 @@
 	sentinel_Invariant(p);
 	p = sentinel_sub(p);
 	pagenum = (p - pool.baseAddr) / PAGESIZE;
-
-	synchronized (gcLock)
-	{
 	biti = cast(uint)(p - pool.baseAddr) / 16;
-	pool.noptrs.clear(biti);
-	if (pool.finals.nbits && gcx.finalizer)
-	{
-	    if (pool.finals.testClear(biti))
-	    {
-		(*gcx.finalizer)(sentinel_add(p), null);
-	    }
-	}
+	pool.noscan.clear(biti);
+	if (pool.finals.nbits && pool.finals.testClear(biti))
+	    gcx.rt_finalize(sentinel_add(p), false);
 
 	gcx.p_cache = null;
 	bin = cast(Bins)pool.pagetable[pagenum];
@@ -556,31 +666,51 @@
 	    n = pagenum;
 	    while (++n < pool.ncommitted && pool.pagetable[n] == B_PAGEPLUS)
 		npages++;
-	    debug (MEMSTOMP) memset(p, 0xF2, npages * PAGESIZE);
+	    debug (MEMSTOMP) cstring.memset(p, 0xF2, npages * PAGESIZE);
 	    pool.freePages(pagenum, npages);
 	}
 	else
 	{   // Add to free list
 	    List *list = cast(List *)p;
 
-	    debug (MEMSTOMP) memset(p, 0xF2, binsize[bin]);
+	    debug (MEMSTOMP) cstring.memset(p, 0xF2, binsize[bin]);
 
 	    list.next = gcx.bucket[bin];
 	    gcx.bucket[bin] = list;
 	}
-	}
 	gcx.log_free(sentinel_add(p));
     }
 
 
-    /****************************************
-     * Determine the allocated size of pointer p.
-     * If p is an interior pointer or not a gc allocated pointer,
-     * return 0.
+    /**
+     * Determine the allocated size of pointer p.  If p is an interior pointer
+     * or not a gc allocated pointer, return 0.
      */
-
     size_t capacity(void *p)
     {
+        if (!p)
+        {
+            return 0;
+        }
+
+        if (!thread_needLock())
+        {
+            return sizeOfNoSync(p);
+        }
+        else synchronized (gcLock)
+        {
+            return sizeOfNoSync(p);
+        }
+    }
+
+
+    //
+    //
+    //
+    private size_t sizeOfNoSync(void *p)
+    {
+        assert (p);
+
 	version (SENTINEL)
 	{
 	    p = sentinel_sub(p);
@@ -618,7 +748,7 @@
     }
 
 
-    /****************************************
+    /**
      * Verify that pointer p:
      *	1) belongs to this memory pool
      *	2) points to the start of an allocated piece of memory
@@ -627,10 +757,17 @@
 
     void check(void *p)
     {
-	if (p)
-	{
-	  synchronized (gcLock)
+	if (!p) return;
+	if (!thread_needLock())
+	    checkNoSync(p);
+	else synchronized (gcLock)
+	    checkNoSync(p);
+    }
+    
+    private void checkNoSync(void *p)
 	  {
+	assert(p);
+
 	    sentinel_Invariant(p);
 	    debug (PTRCHECK)
 	    {
@@ -663,11 +800,12 @@
 		}
 	    }
 	  }
-	}
-    }
 
 
-    void setStackBottom(void *p)
+    //
+    //
+    //
+    private void setStackBottom(void *p)
     {
 	version (STACKGROWSDOWN)
 	{
@@ -689,6 +827,7 @@
 	}
     }
 
+
     static void scanStaticData(gc_t g)
     {
 	void *pbot;
@@ -724,44 +863,104 @@
     }
 
 
-    void addRoot(void *p)	// add p to list of roots
+    /**
+     * add p to list of roots
+     */
+    void addRoot(void *p)
     {
-	synchronized (gcLock)
+        if (!p)
+        {
+            return;
+        }
+
+        if (!thread_needLock())
+        {
+	    gcx.addRoot(p);
+        }
+        else synchronized (gcLock)
 	{
 	    gcx.addRoot(p);
 	}
     }
 
-    void removeRoot(void *p)	// remove p from list of roots
+
+    /**
+     * remove p from list of roots
+     */
+    void removeRoot(void *p)
     {
-	synchronized (gcLock)
+        if (!p)
+        {
+            return;
+        }
+
+        if (!thread_needLock())
+        {
+	    gcx.removeRoot(p);
+        }
+        else synchronized (gcLock)
 	{
 	    gcx.removeRoot(p);
 	}
     }
 
-    void addRange(void *pbot, void *ptop)	// add range to scan for roots
+
+    /**
+     * add range to scan for roots
+     */
+    void addRange(void *pbot, void *ptop)
     {
+        if (!pbot || !ptop)
+    {
+            return;
+        }
+
 	//debug(PRINTF) printf("+GC.addRange(pbot = x%x, ptop = x%x)\n", pbot, ptop);
-	synchronized (gcLock)
+        if (!thread_needLock())
+        {
+	    gcx.addRange(pbot, ptop);
+        }
+        else synchronized (gcLock)
 	{
 	    gcx.addRange(pbot, ptop);
 	}
 	//debug(PRINTF) printf("-GC.addRange()\n");
     }
 
-    void removeRange(void *pbot)		// remove range
+
+    /**
+     * remove range
+     */
+    void removeRange(void *p)
     {
-	synchronized (gcLock)
+        if (!p)
 	{
-	    gcx.removeRange(pbot);
+            return;
+        }
+
+        if (!thread_needLock())
+        {
+	    gcx.removeRange(p);
+        }
+        else synchronized (gcLock)
+	{
+	    gcx.removeRange(p);
 	}
     }
 
-    void fullCollect()		// do full garbage collection
+
+    /**
+     * do full garbage collection
+     */
+    void fullCollect()
     {
 	debug(PRINTF) printf("GC.fullCollect()\n");
-	synchronized (gcLock)
+
+        if (!thread_needLock())
+        {
+	    gcx.fullcollectshell();
+        }
+        else synchronized (gcLock)
 	{
 	    gcx.fullcollectshell();
 	}
@@ -778,14 +977,31 @@
 	gcx.log_collect();
     }
 
-    void fullCollectNoStack()		// do full garbage collection
+
+    /**
+     * do full garbage collection ignoring roots
+     */
+    void fullCollectNoStack()
     {
+        if (!thread_needLock())
+    {
 	gcx.noStack++;
-	fullCollect();
+            gcx.fullcollectshell();
 	gcx.noStack--;
     }
+        else synchronized (gcLock)
+        {
+            gcx.noStack++;
+            gcx.fullcollectshell();
+            gcx.noStack--;
+        }
+    }
 
-    void genCollect()	// do generational garbage collection
+
+    /**
+     * do generational garbage collection
+     */
+    void genCollect()
     {
 	synchronized (gcLock)
 	{
@@ -807,6 +1023,7 @@
 	}
     }
 
+
     void hasPointers(void *p)
     {
 	synchronized (gcLock)
@@ -815,6 +1032,7 @@
 	}
     }
 
+
     void hasNoPointers(void *p)
     {
 	if (!gcx.conservative)
@@ -830,23 +1048,6 @@
 	gcx.conservative = 1;
     }
 
-    void enable()
-    {
-	synchronized (gcLock)
-	{
-	    assert(gcx.disabled > 0);
-	    gcx.disabled--;
-	}
-    }
-
-    void disable()
-    {
-	synchronized (gcLock)
-	{
-	    gcx.disabled++;
-	}
-    }
-
     /*****************************************
      * Retrieve statistics about garbage collection.
      * Useful for debugging and tuning.
@@ -854,6 +1055,11 @@
 
     void getStats(out GCStats stats)
     {
+	if (!thread_needLock()) getStatsNoSync(stats);
+	else synchronized (gcLock) getStatsNoSync(stats);
+    }
+    private void getStatsNoSync(out GCStats stats)
+    {
 	size_t psize = 0;
 	size_t usize = 0;
 	size_t flsize = 0;
@@ -864,24 +1070,20 @@
 	//debug(PRINTF) printf("getStats()\n");
 	memset(&stats, 0, GCStats.sizeof);
 
-	synchronized (gcLock)
-	{
-	    for (n = 0; n < gcx.npools; n++)
-	    {   Pool *pool = gcx.pooltable[n];
+	for (n = 0; n < gcx.npools; n++)
+	{   Pool *pool = gcx.pooltable[n];
 
-		psize += pool.ncommitted * PAGESIZE;
-		for (uint j = 0; j < pool.ncommitted; j++)
-		{
-		    Bins bin = cast(Bins)pool.pagetable[j];
-		    if (bin == B_FREE)
-			stats.freeblocks++;
-		    else if (bin == B_PAGE)
-			stats.pageblocks++;
-		    else if (bin < B_PAGE)
-			bsize += PAGESIZE;
-		}
+	    psize += pool.ncommitted * PAGESIZE;
+	    for (uint j = 0; j < pool.ncommitted; j++)
+	    {
+		Bins bin = cast(Bins)pool.pagetable[j];
+		if (bin == B_FREE)
+		    stats.freeblocks++;
+		else if (bin == B_PAGE)
+		    stats.pageblocks++;
+		else if (bin < B_PAGE)
+		    bsize += PAGESIZE;
 	    }
-
 	    for (n = 0; n < B_PAGE; n++)
 	    {
 		//debug(PRINTF) printf("bin %d\n", n);
@@ -902,16 +1104,15 @@
 }
 
 
-
-
 /* ============================ Gcx =============================== */
 
 enum
 {   PAGESIZE =	  4096,
     COMMITSIZE = (4096*16),
-    POOLSIZE =   (4096*256),
+    POOLSIZE =   (4096*256)
 }
 
+
 enum
 {
     B_16,
@@ -929,26 +1130,30 @@
     B_MAX
 }
 
+
 alias ubyte Bins;
 
+
 struct List
 {
     List *next;
 }
 
+
 struct Range
 {
     void *pbot;
     void *ptop;
 }
 
+
 const uint binsize[B_MAX] = [ 16,32,64,128,256,512,1024,2048,4096 ];
 const uint notbinsize[B_MAX] = [ ~(16u-1),~(32u-1),~(64u-1),~(128u-1),~(256u-1),
 				~(512u-1),~(1024u-1),~(2048u-1),~(4096u-1) ];
 
-
 /* ============================ Gcx =============================== */
 
+
 struct Gcx
 {
     debug (THREADINVARIANT)
@@ -995,6 +1200,13 @@
 
     GC_FINALIZER finalizer;	// finalizer function (one per GC)
 
+    private void rt_finalize( void* p, bool dummy )
+    {
+        if (finalizer)
+            (*finalizer)(p, dummy);
+    }
+
+
     void initialize()
     {   int dummy;
 
@@ -1007,6 +1219,7 @@
 	inited = 1;
     }
 
+
     void Dtor()
     {
 	inited = 0;
@@ -1015,21 +1228,23 @@
 	{   Pool *pool = pooltable[i];
 
 	    pool.Dtor();
-	    std.c.stdlib.free(pool);
+	    cstdlib.free(pool);
 	}
 	if (pooltable)
-	    std.c.stdlib.free(pooltable);
+	    cstdlib.free(pooltable);
 
 	if (roots)
-	    std.c.stdlib.free(roots);
+	    cstdlib.free(roots);
 
 	if (ranges)
-	    std.c.stdlib.free(ranges);
+	    cstdlib.free(ranges);
     }
 
+
     void Invariant() { }
 
-    invariant
+
+    invariant()
     {
 	if (inited)
 	{
@@ -1086,7 +1301,8 @@
     }
 
 
-    /***************************************
+    /**
+     *
      */
 
     void addRoot(void *p)
@@ -1096,12 +1312,12 @@
 	    size_t newdim = rootdim * 2 + 16;
 	    void **newroots;
 
-	    newroots = cast(void **)std.c.stdlib.malloc(newdim * newroots[0].sizeof);
+	    newroots = cast(void **)cstdlib.malloc(newdim * newroots[0].sizeof);
 	    if (!newroots)
-		_d_OutOfMemory();
+		onOutOfMemoryError();
 	    if (roots)
-	    {   memcpy(newroots, roots, nroots * newroots[0].sizeof);
-		std.c.stdlib.free(roots);
+	    {   cstring.memcpy(newroots, roots, nroots * newroots[0].sizeof);
+		cstdlib.free(roots);
 	    }
 	    roots = newroots;
 	    rootdim = newdim;
@@ -1113,20 +1329,20 @@
 
     void removeRoot(void *p)
     {
-	size_t i;
-	for (i = nroots; i--;)
+	for (size_t i = nroots; i--;)
 	{
 	    if (roots[i] == p)
 	    {
 		nroots--;
-		memmove(roots + i, roots + i + 1, (nroots - i) * roots[0].sizeof);
+		cstring.memmove(roots + i, roots + i + 1, (nroots - i) * roots[0].sizeof);
 		return;
 	    }
 	}
 	assert(0);
     }
 
-    /***************************************
+    /**
+     *
      */
 
     void addRange(void *pbot, void *ptop)
@@ -1138,12 +1354,12 @@
 	    size_t newdim = rangedim * 2 + 16;
 	    Range *newranges;
 
-	    newranges = cast(Range *)std.c.stdlib.malloc(newdim * newranges[0].sizeof);
+	    newranges = cast(Range *)cstdlib.malloc(newdim * newranges[0].sizeof);
 	    if (!newranges)
-		_d_OutOfMemory();
+		onOutOfMemoryError();
 	    if (ranges)
-	    {   memcpy(newranges, ranges, nranges * newranges[0].sizeof);
-		std.c.stdlib.free(ranges);
+	    {   cstring.memcpy(newranges, ranges, nranges * newranges[0].sizeof);
+		cstdlib.free(ranges);
 	    }
 	    ranges = newranges;
 	    rangedim = newdim;
@@ -1153,7 +1369,9 @@
 	nranges++;
     }
 
-
+    /**
+     *
+     */
     void removeRange(void *pbot)
     {
 	debug(THREADINVARIANT) { debug(PRINTF) printf("Thread %x ", pthread_self()); }
@@ -1163,7 +1381,7 @@
 	    if (ranges[i].pbot == pbot)
 	    {
 		nranges--;
-		memmove(ranges + i, ranges + i + 1, (nranges - i) * ranges[0].sizeof);
+		cstring.memmove(ranges + i, ranges + i + 1, (nranges - i) * ranges[0].sizeof);
 		return;
 	    }
 	}
@@ -1175,12 +1393,12 @@
 	//assert(zero);
     }
 
-    /*******************************
+
+    /**
      * Find Pool that pointer is in.
      * Return null if not in a Pool.
      * Assume pooltable[] is sorted.
      */
-
     Pool *findPool(void *p)
     {
 	if (p >= minAddr && p < maxAddr)
@@ -1205,7 +1423,7 @@
     }
 
 
-    /*******************************
+    /**
      * Find size of pointer p.
      * Returns 0 if not a gc'd pointer
      */
@@ -1242,7 +1460,7 @@
     }
 
 
-    /*******************************
+    /**
      * Compute bin for size.
      */
 
@@ -1288,7 +1506,7 @@
 	return bin;
     }
 
-    /****************************************
+    /**
      * Allocate a chunk of memory that is larger than a page.
      * Return null if out of memory.
      */
@@ -1359,25 +1577,24 @@
       L1:
 	pool.pagetable[pn] = B_PAGE;
 	if (npages > 1)
-	    memset(&pool.pagetable[pn + 1], B_PAGEPLUS, npages - 1);
+	    cstring.memset(&pool.pagetable[pn + 1], B_PAGEPLUS, npages - 1);
 	p = pool.baseAddr + pn * PAGESIZE;
-	memset(cast(char *)p + size, 0, npages * PAGESIZE - size);
-	debug (MEMSTOMP) memset(p, 0xF1, size);
+	cstring.memset(cast(char *)p + size, 0, npages * PAGESIZE - size);
+	debug (MEMSTOMP) cstring.memset(p, 0xF1, size);
 	//debug(PRINTF) printf("\tp = %x\n", p);
 	return p;
 
       Lnomemory:
-	_d_OutOfMemory();
+	onOutOfMemoryError();
 	return null;
     }
 
 
-    /***********************************
+    /**
      * Allocate a new pool with at least npages in it.
      * Sort it into pooltable[].
      * Return null if failed.
      */
-
     Pool *newPool(uint npages)
     {
 	Pool *pool;
@@ -1412,7 +1629,7 @@
 		npages = n;
 	}
 
-	pool = cast(Pool *)std.c.stdlib.calloc(1, Pool.sizeof);
+	pool = cast(Pool *)cstdlib.calloc(1, Pool.sizeof);
 	if (pool)
 	{
 	    pool.initialize(npages);
@@ -1420,7 +1637,7 @@
 		goto Lerr;
 
 	    newnpools = npools + 1;
-	    newpooltable = cast(Pool **)std.c.stdlib.realloc(pooltable, newnpools * (Pool *).sizeof);
+	    newpooltable = cast(Pool **)cstdlib.realloc(pooltable, newnpools * (Pool *).sizeof);
 	    if (!newpooltable)
 		goto Lerr;
 
@@ -1430,7 +1647,7 @@
 		if (pool.opCmp(newpooltable[i]) < 0)
 		     break;
 	    }
-	    memmove(newpooltable + i + 1, newpooltable + i, (npools - i) * (Pool *).sizeof);
+	    cstring.memmove(newpooltable + i + 1, newpooltable + i, (npools - i) * (Pool *).sizeof);
 	    newpooltable[i] = pool;
 
 	    pooltable = newpooltable;
@@ -1443,17 +1660,16 @@
 
       Lerr:
 	pool.Dtor();
-	std.c.stdlib.free(pool);
+	cstdlib.free(pool);
 	return null;
     }
 
 
-    /*******************************
+    /**
      * Allocate a page of bin's.
      * Returns:
      *	0	failed
      */
-
     int allocPage(Bins bin)
     {
 	Pool *pool;
@@ -1490,17 +1706,16 @@
     }
 
 
-    /************************************
+    /**
      * Search a range of memory values and mark any pointers into the GC pool.
      */
-
     void mark(void *pbot, void *ptop)
     {
 	void **p1 = cast(void **)pbot;
 	void **p2 = cast(void **)ptop;
 	uint changes = 0;
 
-	//if (log) debug(PRINTF) printf("Gcx::mark(%x .. %x)\n", pbot, ptop);
+        //printf("marking range: %p -> %p\n", pbot, ptop);
 	for (; p1 < p2; p1++)
 	{
 	    Pool *pool;
@@ -1543,8 +1758,9 @@
 		    {
 			//if (log) debug(PRINTF) printf("\t\tmarking %x\n", p);
 			pool.mark.set(biti);
-			if (!pool.noptrs.test(biti))
-			{   pool.scan.set(biti);
+			if (!pool.noscan.test(biti))
+			{
+                            pool.scan.set(biti);
 			    changes = 1;
 			}
 			log_parent(sentinel_add(pool.baseAddr + biti * 16), sentinel_add(pbot));
@@ -1555,7 +1771,7 @@
 	anychanges |= changes;
     }
 
-    /*********************************
+    /**
      * Return number of full pages free'd.
      */
 
@@ -1594,6 +1810,9 @@
 	return result;
     }
 
+    /**
+     *
+     */
     size_t fullcollect(void *stackTop)
     {
 	uint n;
@@ -1812,17 +2031,14 @@
 		    {
 			for (; p < ptop; p += size, biti += bitstride)
 			{
-			    if (finalizer && pool.finals.nbits &&
-				pool.finals.testClear(biti))
-			    {
-				(*finalizer)(cast(List *)sentinel_add(p), null);
-			    }
+			    if (pool.finals.nbits && pool.finals.testClear(biti))
+				rt_finalize(cast(List *)sentinel_add(p), false);
 
 			    List *list = cast(List *)p;
 			    //debug(PRINTF) printf("\tcollecting %x\n", list);
 			    log_free(sentinel_add(list));
 
-			    debug (MEMSTOMP) memset(p, 0xF3, size);
+			    debug (MEMSTOMP) cstring.memset(p, 0xF3, size);
 			}
 			pool.pagetable[pn] = B_FREE;
 			freed += PAGESIZE;
@@ -1837,18 +2053,15 @@
 			    sentinel_Invariant(sentinel_add(p));
 
 			    pool.freebits.set(biti);
-			    pool.noptrs.clear(biti);
-			    if (finalizer && pool.finals.nbits &&
-				pool.finals.testClear(biti))
-			    {
-				(*finalizer)(cast(List *)sentinel_add(p), null);
-			    }
+			    pool.noscan.clear(biti);
+			    if (pool.finals.nbits && pool.finals.testClear(biti))
+				rt_finalize(cast(List *)sentinel_add(p), false);
 
 			    List *list = cast(List *)p;
 			    debug(PRINTF) printf("\tcollecting %x\n", list);
 			    log_free(sentinel_add(list));
 
-			    debug (MEMSTOMP) memset(p, 0xF3, size);
+			    debug (MEMSTOMP) cstring.memset(p, 0xF3, size);
 
 			    freed += size;
 			}
@@ -1861,18 +2074,15 @@
 		    {   byte *p = pool.baseAddr + pn * PAGESIZE;
 
 			sentinel_Invariant(sentinel_add(p));
-			pool.noptrs.clear(biti);
-			if (finalizer && pool.finals.nbits &&
-			    pool.finals.testClear(biti))
-			{
-			    (*finalizer)(sentinel_add(p), null);
-			}
+			pool.noscan.clear(biti);
+			if (pool.finals.nbits && pool.finals.testClear(biti))
+			    rt_finalize(sentinel_add(p), false);
 
 			debug(COLLECT_PRINTF) printf("\tcollecting big %x\n", p);
 			log_free(sentinel_add(p));
 			pool.pagetable[pn] = B_FREE;
 			freedpages++;
-			debug (MEMSTOMP) memset(p, 0xF3, PAGESIZE);
+			debug (MEMSTOMP) cstring.memset(p, 0xF3, PAGESIZE);
 			while (pn + 1 < ncommitted && pool.pagetable[pn + 1] == B_PAGEPLUS)
 			{
 			    pn++;
@@ -1881,7 +2091,7 @@
 
 			    debug (MEMSTOMP)
 			    {   p += PAGESIZE;
-				memset(p, 0xF3, PAGESIZE);
+				cstring.memset(p, 0xF3, PAGESIZE);
 			    }
 			}
 		    }
@@ -1950,10 +2160,9 @@
     }
 
 
-    /*********************************
+    /**
      * Run finalizer on p when it is free'd.
      */
-
     void doFinalize(void *p)
     {
 	Pool *pool = findPool(p);
@@ -1967,7 +2176,7 @@
     }
 
 
-    /*********************************
+    /**
      * Indicate that block pointed to by p has possible pointers
      * to GC allocated memory in it.
      */
@@ -1977,31 +2186,33 @@
 	Pool *pool = findPool(p);
 	assert(pool);
 
-	pool.noptrs.clear((p - pool.baseAddr) / 16);
+	pool.noscan.clear((p - pool.baseAddr) / 16);
     }
 
 
-    /*********************************
+    /**
      * Indicate that block pointed to by p has no possible pointers
      * to GC allocated memory in it.
      */
-
     void HasNoPointers(void *p)
     {
 	//printf("HasNoPointers(%p)\n", p);
 	Pool *pool = findPool(p);
 	assert(pool);
 
-	pool.noptrs.set((p - pool.baseAddr) / 16);
+	pool.noscan.set((p - pool.baseAddr) / 16);
     }
 
 
     /***** Leak Detector ******/
+
+
     debug (LOGGING)
     {
 	LogArray current;
 	LogArray prev;
 
+
 	void log_init()
 	{
 	    //debug(PRINTF) printf("+log_init()\n");
@@ -2130,9 +2341,9 @@
     byte* topAddr;
     GCBits mark;	// entries already scanned, or should not be scanned
     GCBits scan;	// entries that need to be scanned
-    GCBits finals;	// entries that need finalizer run on them
     GCBits freebits;	// entries that are on the free list
-    GCBits noptrs;	// entries that do not contain pointers
+    GCBits finals;      // entries that need finalizer run on them
+    GCBits noscan;      // entries that should not be scanned
 
     uint npages;
     uint ncommitted;	// ncommitted <= npages
@@ -2164,17 +2375,18 @@
 	mark.alloc(poolsize / 16);
 	scan.alloc(poolsize / 16);
 	freebits.alloc(poolsize / 16);
-	noptrs.alloc(poolsize / 16);
+	noscan.alloc(poolsize / 16);
 
-	pagetable = cast(ubyte*)std.c.stdlib.malloc(npages);
+	pagetable = cast(ubyte*)cstdlib.malloc(npages);
 	if (!pagetable)
-	    _d_OutOfMemory();
-	memset(pagetable, B_UNCOMMITTED, npages);
+	    onOutOfMemoryError();
+	cstring.memset(pagetable, B_UNCOMMITTED, npages);
 
 	this.npages = npages;
 	ncommitted = 0;
     }
 
+
     void Dtor()
     {
 	if (baseAddr)
@@ -2199,22 +2411,26 @@
 	    topAddr = null;
 	}
 	if (pagetable)
-	    std.c.stdlib.free(pagetable);
+	    cstdlib.free(pagetable);
 
 	mark.Dtor();
 	scan.Dtor();
+	freebits.Dtor();
 	finals.Dtor();
-	freebits.Dtor();
+        noscan.Dtor();
     }
 
+
     void Invariant() { }
 
-    invariant
+
+    invariant()
     {
 	//mark.Invariant();
 	//scan.Invariant();
+	//freebits.Invariant();
 	//finals.Invariant();
-	//freebits.Invariant();
+	//noscan.Invariant();
 
 	if (baseAddr)
 	{
@@ -2231,11 +2447,11 @@
 	}
     }
 
-    /**************************************
+
+    /**
      * Allocate n pages from Pool.
      * Returns ~0u on failure.
      */
-
     uint allocPages(uint n)
     {
 	uint i;
@@ -2258,11 +2474,10 @@
 	return extendPages(n);
     }
 
-    /**************************************
+    /**
      * Extend Pool by n pages.
      * Returns ~0u on failure.
      */
-
     uint extendPages(uint n)
     {
 	//debug(PRINTF) printf("Pool::extendPages(n = %d)\n", n);
@@ -2277,7 +2492,7 @@
 	    //fflush(stdout);
 	    if (os_mem_commit(baseAddr, ncommitted * PAGESIZE, tocommit * PAGESIZE) == 0)
 	    {
-		memset(pagetable + ncommitted, B_FREE, tocommit);
+		cstring.memset(pagetable + ncommitted, B_FREE, tocommit);
 		auto i = ncommitted;
 		ncommitted += tocommit;
 
@@ -2292,19 +2507,19 @@
 	return ~0u;
     }
 
-    /**********************************
+
+    /**
      * Free npages pages starting with pagenum.
      */
-
     void freePages(uint pagenum, uint npages)
     {
-	memset(&pagetable[pagenum], B_FREE, npages);
+	cstring.memset(&pagetable[pagenum], B_FREE, npages);
     }
 
-    /***************************
+
+    /**
      * Used for sorting pooltable[]
      */
-
     int opCmp(Pool *p2)
     {
 	if (baseAddr < p2.baseAddr)
Index: d/phobos/internal/gc/testgc.d
===================================================================
--- d/phobos/internal/gc/testgc.d	(Revision 199)
+++ d/phobos/internal/gc/testgc.d	(Arbeitskopie)
@@ -128,7 +128,7 @@
 
 /* ---------------------------- */
 
-void finalizer(void *p, void *dummy)
+void finalizer(void *p, bool dummy)
 {
 }
 
Index: d/phobos/internal/gc/gc.d
===================================================================
--- d/phobos/internal/gc/gc.d	(Revision 199)
+++ d/phobos/internal/gc/gc.d	(Arbeitskopie)
@@ -3,7 +3,7 @@
  */
 
 /*
- *  Copyright (C) 2004-2007 by Digital Mars, www.digitalmars.com
+ *  Copyright (C) 2004-2008 by Digital Mars, www.digitalmars.com
  *  Written by Walter Bright
  *
  *  This software is provided 'as-is', without any express or implied
@@ -464,13 +464,25 @@
 
 }
 
-void new_finalizer(void *p, void *dummy)
+void new_finalizer(void *p, bool dummy)
 {
     //printf("new_finalizer(p = %p)\n", p);
     _d_callfinalizer(p);
 }
 
 extern (C)
+void _d_callinterfacefinalizer(void *p)
+{
+    //printf("_d_callinterfacefinalizer(p = %p)\n", p);
+    if (p)
+    {
+	Interface *pi = **cast(Interface ***)p;
+	Object o = cast(Object)(p - pi.offset);
+	_d_callfinalizer(cast(void*)o);
+    }
+}
+
+extern (C)
 void _d_callfinalizer(void *p)
 {
     //printf("_d_callfinalizer(p = %p)\n", p);
Index: d/phobos/internal/minit.asm
===================================================================
--- d/phobos/internal/minit.asm	(Revision 199)
+++ d/phobos/internal/minit.asm	(Arbeitskopie)
@@ -1,11 +1,9 @@
 ;_ minit.asm
-; Copyright (C) 2001 by Digital Mars
-; All rights reserved
-; www.digitalmars.com
+; Written by Walter Bright
+; Digital Mars
+; http://www.digitalmars.com/d/
+; Placed into the Public Domain
 
-; Converts array of ModuleInfo pointers to a D dynamic array of them,
-; so they can be accessed via D.
-
 include macros.asm
 
 ifdef _WIN32
@@ -14,11 +12,30 @@
   DATAGRP      EQU     DGROUP
 endif
 
+; Provide a default resolution for weak extern records, no way in C
+; to define an omf symbol with a specific value
 public __nullext
 __nullext	equ 0
 
 	extrn	__moduleinfo_array:near
 
+; This bit of assembler is needed because, from C or D, one cannot
+; specify the names of data segments. Why does this matter?
+; All the ModuleInfo pointers are placed into a segment named 'FM'.
+; The order in which they are placed in 'FM' is arbitrarily up to the linker.
+; In order to walk all the pointers, we need to be able to find the
+; beginning and the end of the 'FM' segment.
+; This is done by bracketing the 'FM' segment with two other, empty,
+; segments named 'FMB' and 'FME'. Since this module is the only one that
+; ever refers to 'FMB' and 'FME', we get to control the order in which
+; these segments appear relative to 'FM' by using a GROUP statement.
+; So, we have in memory:
+;	FMB	empty segment
+;	FM	contains all the pointers
+;	FME	empty segment
+; and finding the limits of FM is as easy as taking the address of FMB
+; and the address of FME.
+
 ; These segments bracket FM, which contains the list of ModuleInfo pointers
 FMB     segment dword use32 public 'DATA'
 FMB     ends
@@ -40,6 +57,12 @@
 
 	begcode minit
 
+; extern (C) void _minit();
+; Converts array of ModuleInfo pointers to a D dynamic array of them,
+; so they can be accessed via D.
+; Result is written to:
+; extern (C) ModuleInfo[] _moduleinfo_array;
+
 	public	__minit
 __minit	proc	near
 	mov	EDX,offset DATAGRP:FMB
Index: d/Make-lang.in
===================================================================
--- d/Make-lang.in	(Revision 199)
+++ d/Make-lang.in	(Arbeitskopie)
@@ -167,7 +167,7 @@
 	cp $(D_DRIVER_NAME)$(exeext) $(D_DRIVER_NAME)-cross$(exeext)
 
 D_DMD_OBJS = \
-    d/access.dmd.o d/array.dmd.o d/attrib.dmd.o d/cast.dmd.o d/class.dmd.o d/cond.dmd.o d/constfold.dmd.o d/dchar.dmd.o d/declaration.dmd.o d/delegatize.dmd.o d/doc.dmd.o \
+    d/access.dmd.o d/array.dmd.o d/attrib.dmd.o d/cast.dmd.o d/class.dmd.o d/clone.dmd.o d/cond.dmd.o d/constfold.dmd.o d/dchar.dmd.o d/declaration.dmd.o d/delegatize.dmd.o d/doc.dmd.o \
     d/dsymbol.dmd.o d/dump.dmd.o d/entity.dmd.o d/enum.dmd.o d/expression.dmd.o d/func.dmd.o d/gnuc.dmd.o d/hdrgen.dmd.o d/html.dmd.o d/identifier.dmd.o d/import.dmd.o \
     d/init.dmd.o d/inline.dmd.o d/interpret.dmd.o d/lexer.dmd.o d/lstring.dmd.o d/macro.dmd.o d/mangle.dmd.o d/mars.dmd.o d/mem.dmd.o d/mtype.dmd.o d/module.dmd.o d/opover.dmd.o d/optimize.dmd.o d/parse.dmd.o \
     d/root.dmd.o d/scope.dmd.o d/statement.dmd.o d/staticassert.dmd.o d/stringtable.dmd.o d/struct.dmd.o d/template.dmd.o  \
Index: d/dmd/mtype.c
===================================================================
--- d/dmd/mtype.c	(Revision 199)
+++ d/dmd/mtype.c	(Arbeitskopie)
@@ -1,6 +1,6 @@
 
 // Compiler implementation of the D programming language
-// Copyright (c) 1999-2007 by Digital Mars
+// Copyright (c) 1999-2008 by Digital Mars
 // All Rights Reserved
 // written by Walter Bright
 // http://www.digitalmars.com
@@ -136,8 +136,13 @@
 Type::Type(TY ty, Type *next)
 {
     this->ty = ty;
+    this->mod = 0;
     this->next = next;
     this->deco = NULL;
+#if V2
+    this->cto = NULL;
+    this->ito = NULL;
+#endif
     this->pto = NULL;
     this->rto = NULL;
     this->arrayof = NULL;
@@ -361,16 +366,6 @@
 }
 
 /********************************
- * Name mangling.
- */
-
-void Type::toTypeInfoBuffer(OutBuffer *buf)
-{
-    assert(0);
-    buf->writeByte(mangleChar[ty]);
-}
-
-/********************************
  * For pretty-printing a type.
  */
 
@@ -379,27 +374,54 @@
     HdrGenState hgs;
 
     buf = new OutBuffer();
-    toCBuffer2(buf, NULL, &hgs);
+    toCBuffer(buf, NULL, &hgs);
     return buf->toChars();
 }
 
 void Type::toCBuffer(OutBuffer *buf, Identifier *ident, HdrGenState *hgs)
 {
-    OutBuffer tbuf;
+    toCBuffer2(buf, hgs, 0);
+    if (ident)
+    {	buf->writeByte(' ');
+	buf->writestring(ident->toChars());
+    }
+}
 
-    toCBuffer2(&tbuf, ident, hgs);
-    buf->write(&tbuf);
+void Type::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
+{
+    if (mod != this->mod)
+    {	toCBuffer3(buf, hgs, mod);
+	return;
+    }
+    buf->writestring(toChars());
 }
 
-void Type::toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs)
+void Type::toCBuffer3(OutBuffer *buf, HdrGenState *hgs, int mod)
 {
-    buf->prependstring(toChars());
-    if (ident)
-    {	buf->writeByte(' ');
-	buf->writestring(ident->toChars());
+    if (mod != this->mod)
+    {	char *p;
+
+	switch (this->mod)
+	{
+	    case 0:
+		toCBuffer2(buf, hgs, this->mod);
+		break;
+	    case MODconst:
+		p = "const(";
+		goto L1;
+	    case MODinvariant:
+		p = "invariant(";
+	    L1:	buf->writestring(p);
+		toCBuffer2(buf, hgs, this->mod);
+		buf->writeByte(')');
+		break;
+	    default:
+		assert(0);
+	}
     }
 }
 
+
 /************************************
  */
 
@@ -511,7 +533,7 @@
 }
 
 
-Expression *Type::defaultInit()
+Expression *Type::defaultInit(Loc loc)
 {
 #if LOGDEFAULTINIT
     printf("Type::defaultInit() '%s'\n", toChars());
@@ -578,8 +600,7 @@
     {
 	if (ty == Tvoid)
 	    error(loc, "void does not have an initializer");
-	e = defaultInit();
-	e->loc = loc;
+	e = defaultInit(loc);
     }
     else if (ident == Id::mangleof)
     {
@@ -656,7 +677,7 @@
 			    e->isBool(0) &&
 			    v->type->toBasetype()->ty == Tstruct)
 			{
-			    e = v->type->defaultInit();
+			    e = v->type->defaultInit(loc);
 			}
 		    }
 		    e = e->optimize(WANTvalue | WANTinterpret);
@@ -666,8 +687,7 @@
 		return e;
 	    }
 #endif
-	    Expression *ex = defaultInit();
-	    ex->loc = e->loc;
+	    Expression *ex = defaultInit(e->loc);
 	    return ex;
 	}
     }
@@ -931,13 +951,14 @@
     return dstring;
 }
 
-void TypeBasic::toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs)
+void TypeBasic::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
 {
-    buf->prependstring(cstring);
-    if (ident)
-    {	buf->writeByte(' ');
-	buf->writestring(ident->toChars());
+    //printf("TypeBasic::toCBuffer2(mod = %d, this->mod = %d)\n", mod, this->mod);
+    if (mod != this->mod)
+    {	toCBuffer3(buf, hgs, mod);
+	return;
     }
+    buf->writestring(dstring);
 }
 
 d_uns64 TypeBasic::size(Loc loc)
@@ -1381,7 +1402,7 @@
     return e;
 }
 
-Expression *TypeBasic::defaultInit()
+Expression *TypeBasic::defaultInit(Loc loc)
 {   integer_t value = 0;
 
 #if LOGDEFAULTINIT
@@ -1407,9 +1428,9 @@
 	case Tcomplex32:
 	case Tcomplex64:
 	case Tcomplex80:
-	    return getProperty(0, Id::nan);
+	    return getProperty(loc, Id::nan);
     }
-    return new IntegerExp(0, value, this);
+    return new IntegerExp(loc, value, this);
 }
 
 int TypeBasic::isZeroInit()
@@ -1649,59 +1670,7 @@
     return e;
 }
 
-void TypeArray::toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs)
-{
-#if 1
-    OutBuffer buf2;
-    toPrettyBracket(&buf2, hgs);
-    buf->prependstring(buf2.toChars());
-    if (ident)
-    {
-	buf->writeByte(' ');
-	buf->writestring(ident->toChars());
-    }
-    next->toCBuffer2(buf, NULL, hgs);
-#elif 1
-    // The D way
-    Type *t;
-    OutBuffer buf2;
-    for (t = this; 1; t = t->next)
-    {	TypeArray *ta;
 
-	ta = dynamic_cast<TypeArray *>(t);
-	if (!ta)
-	    break;
-	ta->toPrettyBracket(&buf2, hgs);
-    }
-    buf->prependstring(buf2.toChars());
-    if (ident)
-    {
-	buf2.writestring(ident->toChars());
-    }
-    t->toCBuffer2(buf, NULL, hgs);
-#else
-    // The C way
-    if (buf->offset)
-    {	buf->bracket('(', ')');
-	assert(!ident);
-    }
-    else if (ident)
-	buf->writestring(ident->toChars());
-    Type *t = this;
-    do
-    {	Expression *dim;
-	buf->writeByte('[');
-	dim = ((TypeSArray *)t)->dim;
-	if (dim)
-	    buf->printf("%lld", dim->toInteger());
-	buf->writeByte(']');
-	t = t->next;
-    } while (t->ty == Tsarray);
-    t->toCBuffer2(buf, NULL, hgs);
-#endif
-}
-
-
 /***************************** TypeSArray *****************************/
 
 TypeSArray::TypeSArray(Type *t, Expression *dim)
@@ -1886,6 +1855,14 @@
 	dim = semanticLength(sc, tbn, dim);
 
 	dim = dim->optimize(WANTvalue | WANTinterpret);
+	if (sc->parameterSpecialization && dim->op == TOKvar &&
+	    ((VarExp *)dim)->var->storage_class & STCtemplateparameter)
+	{
+	    /* It could be a template parameter N which has no value yet:
+	     *   template Foo(T : T[N], size_t N);
+	     */
+	    return this;
+	}
 	integer_t d1 = dim->toInteger();
 	dim = dim->castTo(sc, tsize_t);
 	dim = dim->optimize(WANTvalue);
@@ -1954,15 +1931,13 @@
 	next->toDecoBuffer(buf);
 }
 
-void TypeSArray::toTypeInfoBuffer(OutBuffer *buf)
+void TypeSArray::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
 {
-    buf->writeByte(mangleChar[Tarray]);
-    if (next)
-	next->toTypeInfoBuffer(buf);
-}
-
-void TypeSArray::toPrettyBracket(OutBuffer *buf, HdrGenState *hgs)
-{
+    if (mod != this->mod)
+    {	toCBuffer3(buf, hgs, mod);
+	return;
+    }
+    next->toCBuffer2(buf, hgs, this->mod);
     buf->printf("[%s]", dim->toChars());
 }
 
@@ -2030,12 +2005,12 @@
     return Type::implicitConvTo(to);
 }
 
-Expression *TypeSArray::defaultInit()
+Expression *TypeSArray::defaultInit(Loc loc)
 {
 #if LOGDEFAULTINIT
     printf("TypeSArray::defaultInit() '%s'\n", toChars());
 #endif
-    return next->defaultInit();
+    return next->defaultInit(loc);
 }
 
 int TypeSArray::isZeroInit()
@@ -2120,15 +2095,13 @@
 	next->toDecoBuffer(buf);
 }
 
-void TypeDArray::toTypeInfoBuffer(OutBuffer *buf)
+void TypeDArray::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
 {
-    buf->writeByte(mangleChar[ty]);
-    if (next)
-	next->toTypeInfoBuffer(buf);
-}
-
-void TypeDArray::toPrettyBracket(OutBuffer *buf, HdrGenState *hgs)
-{
+    if (mod != this->mod)
+    {	toCBuffer3(buf, hgs, mod);
+	return;
+    }
+    next->toCBuffer2(buf, hgs, this->mod);
     buf->writestring("[]");
 }
 
@@ -2188,13 +2161,13 @@
     return Type::implicitConvTo(to);
 }
 
-Expression *TypeDArray::defaultInit()
+Expression *TypeDArray::defaultInit(Loc loc)
 {
 #if LOGDEFAULTINIT
     printf("TypeDArray::defaultInit() '%s'\n", toChars());
 #endif
     Expression *e;
-    e = new NullExp(0);
+    e = new NullExp(loc);
     e->type = this;
     return e;
 }
@@ -2393,24 +2366,25 @@
     next->toDecoBuffer(buf);
 }
 
-void TypeAArray::toPrettyBracket(OutBuffer *buf, HdrGenState *hgs)
+void TypeAArray::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
 {
+    if (mod != this->mod)
+    {	toCBuffer3(buf, hgs, mod);
+	return;
+    }
+    next->toCBuffer2(buf, hgs, this->mod);
     buf->writeByte('[');
-    {	OutBuffer ibuf;
-
-	index->toCBuffer2(&ibuf, NULL, hgs);
-	buf->write(&ibuf);
-    }
+    index->toCBuffer2(buf, hgs, 0);
     buf->writeByte(']');
 }
 
-Expression *TypeAArray::defaultInit()
+Expression *TypeAArray::defaultInit(Loc loc)
 {
 #if LOGDEFAULTINIT
     printf("TypeAArray::defaultInit() '%s'\n", toChars());
 #endif
     Expression *e;
-    e = new NullExp(0);
+    e = new NullExp(loc);
     e->type = this;
     return e;
 }
@@ -2465,16 +2439,16 @@
     return PTRSIZE;
 }
 
-void TypePointer::toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs)
+void TypePointer::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
 {
     //printf("TypePointer::toCBuffer2() next = %d\n", next->ty);
-    buf->prependstring("*");
-    if (ident)
-    {
-	buf->writeByte(' ');
-	buf->writestring(ident->toChars());
+    if (mod != this->mod)
+    {	toCBuffer3(buf, hgs, mod);
+	return;
     }
-    next->toCBuffer2(buf, NULL, hgs);
+    next->toCBuffer2(buf, hgs, this->mod);
+    if (next->ty != Tfunction)
+	buf->writeByte('*');
 }
 
 MATCH TypePointer::implicitConvTo(Type *to)
@@ -2512,13 +2486,13 @@
     return TRUE;
 }
 
-Expression *TypePointer::defaultInit()
+Expression *TypePointer::defaultInit(Loc loc)
 {
 #if LOGDEFAULTINIT
     printf("TypePointer::defaultInit() '%s'\n", toChars());
 #endif
     Expression *e;
-    e = new NullExp(0);
+    e = new NullExp(loc);
     e->type = this;
     return e;
 }
@@ -2559,14 +2533,14 @@
     return PTRSIZE;
 }
 
-void TypeReference::toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs)
+void TypeReference::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
 {
-    buf->prependstring("&");
-    if (ident)
-    {
-	buf->writestring(ident->toChars());
+    if (mod != this->mod)
+    {	toCBuffer3(buf, hgs, mod);
+	return;
     }
-    next->toCBuffer2(buf, NULL, hgs);
+    next->toCBuffer2(buf, hgs, this->mod);
+    buf->writeByte('&');
 }
 
 Expression *TypeReference::dotExp(Scope *sc, Expression *e, Identifier *ident)
@@ -2579,13 +2553,13 @@
     return next->dotExp(sc, e, ident);
 }
 
-Expression *TypeReference::defaultInit()
+Expression *TypeReference::defaultInit(Loc loc)
 {
 #if LOGDEFAULTINIT
     printf("TypeReference::defaultInit() '%s'\n", toChars());
 #endif
     Expression *e;
-    e = new NullExp(0);
+    e = new NullExp(loc);
     e->type = this;
     return e;
 }
@@ -2735,7 +2709,7 @@
     inuse--;
 }
 
-void TypeFunction::toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs)
+void TypeFunction::toCBuffer(OutBuffer *buf, Identifier *ident, HdrGenState *hgs)
 {
     char *p = NULL;
 
@@ -2744,6 +2718,8 @@
 	return;
     }
     inuse++;
+    if (next && (!ident || ident->toHChars2() == ident->toChars()))
+	next->toCBuffer2(buf, hgs, 0);
     if (hgs->ddoc != 1)
     {
 	switch (linkage)
@@ -2758,25 +2734,45 @@
 	}
     }
 
-    if (buf->offset)
-    {
 	if (!hgs->hdrgen && p)
-	    buf->prependstring(p);
-	buf->bracket('(', ')');
-	assert(!ident);
-    }
-    else
-    {
-	if (!hgs->hdrgen && p)
 	    buf->writestring(p);
 	if (ident)
 	{   buf->writeByte(' ');
 	    buf->writestring(ident->toHChars2());
 	}
+    Argument::argsToCBuffer(buf, hgs, parameters, varargs);
+    inuse--;
+}
+
+void TypeFunction::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
+{
+    char *p = NULL;
+
+    if (inuse)
+    {	inuse = 2;		// flag error to caller
+	return;
     }
+    inuse++;
+    if (next)
+	next->toCBuffer2(buf, hgs, 0);
+    if (hgs->ddoc != 1)
+    {
+	switch (linkage)
+	{
+	    case LINKd:		p = NULL;	break;
+	    case LINKc:		p = "C ";	break;
+	    case LINKwindows:	p = "Windows ";	break;
+	    case LINKpascal:	p = "Pascal ";	break;
+	    case LINKcpp:	p = "C++ ";	break;
+	    default:
+		assert(0);
+	}
+    }
+
+    if (!hgs->hdrgen && p)
+	buf->writestring(p);
+    buf->writestring(" function");
     Argument::argsToCBuffer(buf, hgs, parameters, varargs);
-    if (next && (!ident || ident->toHChars2() == ident->toChars()))
-	next->toCBuffer2(buf, NULL, hgs);
     inuse--;
 }
 
@@ -2789,38 +2785,50 @@
     }
     //printf("TypeFunction::semantic() this = %p\n", this);
 
-    linkage = sc->linkage;
-    if (!next)
+    TypeFunction *tf = (TypeFunction *)mem.malloc(sizeof(TypeFunction));
+    memcpy(tf, this, sizeof(TypeFunction));
+    if (parameters)
+    {	tf->parameters = (Arguments *)parameters->copy();
+	for (size_t i = 0; i < parameters->dim; i++)
+	{   Argument *arg = (Argument *)parameters->data[i];
+	    Argument *cpy = (Argument *)mem.malloc(sizeof(Argument));
+	    memcpy(cpy, arg, sizeof(Argument));
+	    tf->parameters->data[i] = (void *)cpy;
+	}
+    }
+
+    tf->linkage = sc->linkage;
+    if (!tf->next)
     {
 	assert(global.errors);
-	next = tvoid;
+	tf->next = tvoid;
     }
-    next = next->semantic(loc,sc);
-    if (next->toBasetype()->ty == Tsarray)
-    {	error(loc, "functions cannot return static array %s", next->toChars());
-	next = Type::terror;
+    tf->next = tf->next->semantic(loc,sc);
+    if (tf->next->toBasetype()->ty == Tsarray)
+    {	error(loc, "functions cannot return static array %s", tf->next->toChars());
+	tf->next = Type::terror;
     }
-    if (next->toBasetype()->ty == Tfunction)
+    if (tf->next->toBasetype()->ty == Tfunction)
     {	error(loc, "functions cannot return a function");
-	next = Type::terror;
+	tf->next = Type::terror;
     }
-    if (next->toBasetype()->ty == Ttuple)
+    if (tf->next->toBasetype()->ty == Ttuple)
     {	error(loc, "functions cannot return a tuple");
-	next = Type::terror;
+	tf->next = Type::terror;
     }
-    if (next->isauto() && !(sc->flags & SCOPEctor))
-	error(loc, "functions cannot return auto %s", next->toChars());
+    if (tf->next->isauto() && !(sc->flags & SCOPEctor))
+	error(loc, "functions cannot return auto %s", tf->next->toChars());
 
-    if (parameters)
-    {	size_t dim = Argument::dim(parameters);
+    if (tf->parameters)
+    {	size_t dim = Argument::dim(tf->parameters);
 
 	for (size_t i = 0; i < dim; i++)
-	{   Argument *arg = Argument::getNth(parameters, i);
+	{   Argument *arg = Argument::getNth(tf->parameters, i);
 	    Type *t;
 
-	    inuse++;
+	    tf->inuse++;
 	    arg->type = arg->type->semantic(loc,sc);
-	    if (inuse == 1) inuse--;
+	    if (tf->inuse == 1) tf->inuse--;
 	    t = arg->type->toBasetype();
 
 	    if (arg->storageClass & (STCout | STCref | STClazy))
@@ -2842,27 +2850,27 @@
 	     * change.
 	     */
 	    if (t->ty == Ttuple)
-	    {	dim = Argument::dim(parameters);
+	    {	dim = Argument::dim(tf->parameters);
 		i--;
 	    }
 	}
     }
-    deco = merge()->deco;
+    tf->deco = tf->merge()->deco;
 
-    if (inuse)
+    if (tf->inuse)
     {	error(loc, "recursive type");
-	inuse = 0;
+	tf->inuse = 0;
 	return terror;
     }
 
-    if (varargs == 1 && linkage != LINKd && Argument::dim(parameters) == 0)
+    if (tf->varargs == 1 && tf->linkage != LINKd && Argument::dim(tf->parameters) == 0)
 	error(loc, "variadic functions with non-D linkage must have at least one parameter");
 
     /* Don't return merge(), because arg identifiers and default args
      * can be different
      * even though the types match
      */
-    return this;
+    return tf;
 }
 
 /********************************
@@ -3035,37 +3043,26 @@
     return PTRSIZE * 2;
 }
 
-void TypeDelegate::toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs)
+void TypeDelegate::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
 {
-#if 1
-    OutBuffer args;
+    if (mod != this->mod)
+    {	toCBuffer3(buf, hgs, mod);
+	return;
+    }
     TypeFunction *tf = (TypeFunction *)next;
 
-    Argument::argsToCBuffer(&args, hgs, tf->parameters, tf->varargs);
-    buf->prependstring(args.toChars());
-    buf->prependstring(" delegate");
-    if (ident)
-    {
-	buf->writeByte(' ');
-	buf->writestring(ident->toChars());
-    }
-    next->next->toCBuffer2(buf, NULL, hgs);
-#else
-    next->toCBuffer2(buf, Id::delegate, hgs);
-    if (ident)
-    {
-	buf->writestring(ident->toChars());
-    }
-#endif
+    tf->next->toCBuffer2(buf, hgs, 0);
+    buf->writestring(" delegate");
+    Argument::argsToCBuffer(buf, hgs, tf->parameters, tf->varargs);
 }
 
-Expression *TypeDelegate::defaultInit()
+Expression *TypeDelegate::defaultInit(Loc loc)
 {
 #if LOGDEFAULTINIT
     printf("TypeDelegate::defaultInit() '%s'\n", toChars());
 #endif
     Expression *e;
-    e = new NullExp(0);
+    e = new NullExp(loc);
     e->type = this;
     return e;
 }
@@ -3158,7 +3155,7 @@
     idents.push(ident);
 }
 
-void TypeQualified::toCBuffer2Helper(OutBuffer *buf, Identifier *ident, HdrGenState *hgs)
+void TypeQualified::toCBuffer2Helper(OutBuffer *buf, HdrGenState *hgs)
 {
     int i;
 
@@ -3388,17 +3385,14 @@
     //buf->printf("%c%s", mangleChar[ty], name);
 }
 
-void TypeIdentifier::toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs)
+void TypeIdentifier::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
 {
-    OutBuffer tmp;
-
-    tmp.writestring(this->ident->toChars());
-    toCBuffer2Helper(&tmp, NULL, hgs);
-    buf->prependstring(tmp.toChars());
-    if (ident)
-    {	buf->writeByte(' ');
-	buf->writestring(ident->toChars());
+    if (mod != this->mod)
+    {	toCBuffer3(buf, hgs, mod);
+	return;
     }
+    buf->writestring(this->ident->toChars());
+    toCBuffer2Helper(buf, hgs);
 }
 
 /*************************************
@@ -3520,17 +3514,14 @@
 }
 
 
-void TypeInstance::toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs)
+void TypeInstance::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
 {
-    OutBuffer tmp;
-
-    tempinst->toCBuffer(&tmp, hgs);
-    toCBuffer2Helper(&tmp, NULL, hgs);
-    buf->prependstring(tmp.toChars());
-    if (ident)
-    {	buf->writeByte(' ');
-	buf->writestring(ident->toChars());
+    if (mod != this->mod)
+    {	toCBuffer3(buf, hgs, mod);
+	return;
     }
+    tempinst->toCBuffer(buf, hgs);
+    toCBuffer2Helper(buf, hgs);
 }
 
 void TypeInstance::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps)
@@ -3623,19 +3614,16 @@
     return t->toDsymbol(sc);
 }
 
-void TypeTypeof::toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs)
+void TypeTypeof::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
 {
-    OutBuffer tmp;
-
-    tmp.writestring("typeof(");
-    exp->toCBuffer(&tmp, hgs);
-    tmp.writeByte(')');
-    toCBuffer2Helper(&tmp, NULL, hgs);
-    buf->prependstring(tmp.toChars());
-    if (ident)
-    {	buf->writeByte(' ');
-	buf->writestring(ident->toChars());
+    if (mod != this->mod)
+    {	toCBuffer3(buf, hgs, mod);
+	return;
     }
+    buf->writestring("typeof(");
+    exp->toCBuffer(buf, hgs);
+    buf->writeByte(')');
+    toCBuffer2Helper(buf, hgs);
 }
 
 Type *TypeTypeof::semantic(Loc loc, Scope *sc)
@@ -3812,18 +3800,13 @@
     buf->printf("%c%s", mangleChar[ty], name);
 }
 
-void TypeEnum::toTypeInfoBuffer(OutBuffer *buf)
+void TypeEnum::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
 {
-    toBasetype()->toTypeInfoBuffer(buf);
-}
-
-void TypeEnum::toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs)
-{
-    buf->prependstring(sym->toChars());
-    if (ident)
-    {	buf->writeByte(' ');
-	buf->writestring(ident->toChars());
+    if (mod != this->mod)
+    {	toCBuffer3(buf, hgs, mod);
+	return;
     }
+    buf->writestring(sym->toChars());
 }
 
 Expression *TypeEnum::dotExp(Scope *sc, Expression *e, Identifier *ident)
@@ -3871,7 +3854,7 @@
     {
 	if (!sym->symtab)
 	    goto Lfwd;
-	e = defaultInit();
+	e = defaultInit(loc);
     }
     else
     {
@@ -3920,14 +3903,14 @@
     return m;
 }
 
-Expression *TypeEnum::defaultInit()
+Expression *TypeEnum::defaultInit(Loc loc)
 {
 #if LOGDEFAULTINIT
     printf("TypeEnum::defaultInit() '%s'\n", toChars());
 #endif
     // Initialize to first member of enum
     Expression *e;
-    e = new IntegerExp(0, sym->defaultval, this);
+    e = new IntegerExp(loc, sym->defaultval, this);
     return e;
 }
 
@@ -3993,19 +3976,14 @@
     buf->printf("%c%s", mangleChar[ty], name);
 }
 
-void TypeTypedef::toTypeInfoBuffer(OutBuffer *buf)
+void TypeTypedef::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
 {
-    sym->basetype->toTypeInfoBuffer(buf);
-}
-
-void TypeTypedef::toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs)
-{
     //printf("TypeTypedef::toCBuffer2() '%s'\n", sym->toChars());
-    buf->prependstring(sym->toChars());
-    if (ident)
-    {	buf->writeByte(' ');
-	buf->writestring(ident->toChars());
+    if (mod != this->mod)
+    {	toCBuffer3(buf, hgs, mod);
+	return;
     }
+    buf->writestring(sym->toChars());
 }
 
 Expression *TypeTypedef::dotExp(Scope *sc, Expression *e, Identifier *ident)
@@ -4020,6 +3998,15 @@
     return sym->basetype->dotExp(sc, e, ident);
 }
 
+Expression *TypeTypedef::getProperty(Loc loc, Identifier *ident)
+{
+    if (ident == Id::init)
+    {
+	return Type::getProperty(loc, ident);
+    }
+    return sym->basetype->getProperty(loc, ident);
+}
+
 int TypeTypedef::isbit()
 {
     return sym->basetype->isbit();
@@ -4095,7 +4082,7 @@
     return m;
 }
 
-Expression *TypeTypedef::defaultInit()
+Expression *TypeTypedef::defaultInit(Loc loc)
 {   Expression *e;
     Type *bt;
 
@@ -4108,7 +4095,7 @@
 	return sym->init->toExpression();
     }
     bt = sym->basetype;
-    e = bt->defaultInit();
+    e = bt->defaultInit(loc);
     e->type = this;
     while (bt->ty == Tsarray)
     {
@@ -4212,20 +4199,19 @@
     buf->printf("%c%s", mangleChar[ty], name);
 }
 
-void TypeStruct::toTypeInfoBuffer(OutBuffer *buf)
+void TypeStruct::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
 {
-    toDecoBuffer(buf);
+    if (mod != this->mod)
+    {	toCBuffer3(buf, hgs, mod);
+	return;
+    }
+    TemplateInstance *ti = sym->parent->isTemplateInstance();
+    if (ti && ti->toAlias() == sym)
+	buf->writestring(ti->toChars());
+    else
+	buf->writestring(sym->toChars());
 }
 
-
-void TypeStruct::toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs)
-{
-    buf->prependbyte(' ');
-    buf->prependstring(toChars());
-    if (ident)
-	buf->writestring(ident->toChars());
-}
-
 Expression *TypeStruct::dotExp(Scope *sc, Expression *e, Identifier *ident)
 {   unsigned offset;
 
@@ -4323,6 +4309,18 @@
 	return e;
     }
 
+    TemplateInstance *ti = s->isTemplateInstance();
+    if (ti)
+    {	if (!ti->semanticdone)
+	    ti->semantic(sc);
+	s = ti->inst->toAlias();
+	if (!s->isTemplateInstance())
+	    goto L1;
+	Expression *de = new DotExp(e->loc, e, new ScopeExp(e->loc, ti));
+	de->type = e->type;
+	return de;
+    }
+
     d = s->isDeclaration();
 #ifdef DEBUG
     if (!d)
@@ -4386,7 +4384,7 @@
     return sym->structalign;
 }
 
-Expression *TypeStruct::defaultInit()
+Expression *TypeStruct::defaultInit(Loc loc)
 {   Symbol *s;
     Declaration *d;
 
@@ -4477,13 +4475,13 @@
     buf->printf("%c%s", mangleChar[ty], name);
 }
 
-void TypeClass::toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs)
+void TypeClass::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
 {
-    buf->prependstring(sym->toChars());
-    if (ident)
-    {	buf->writeByte(' ');
-	buf->writestring(ident->toChars());
+    if (mod != this->mod)
+    {	toCBuffer3(buf, hgs, mod);
+	return;
     }
+    buf->writestring(sym->toChars());
 }
 
 Expression *TypeClass::dotExp(Scope *sc, Expression *e, Identifier *ident)
@@ -4648,6 +4646,18 @@
 	return e;
     }
 
+    TemplateInstance *ti = s->isTemplateInstance();
+    if (ti)
+    {	if (!ti->semanticdone)
+	    ti->semantic(sc);
+	s = ti->inst->toAlias();
+	if (!s->isTemplateInstance())
+	    goto L1;
+	Expression *de = new DotExp(e->loc, e, new ScopeExp(e->loc, ti));
+	de->type = e->type;
+	return de;
+    }
+
     d = s->isDeclaration();
     if (!d)
     {
@@ -4770,13 +4780,13 @@
     return MATCHnomatch;
 }
 
-Expression *TypeClass::defaultInit()
+Expression *TypeClass::defaultInit(Loc loc)
 {
 #if LOGDEFAULTINIT
     printf("TypeClass::defaultInit() '%s'\n", toChars());
 #endif
     Expression *e;
-    e = new NullExp(0);
+    e = new NullExp(loc);
     e->type = this;
     return e;
 }
@@ -4899,15 +4909,9 @@
     return NULL;
 }
 
-void TypeTuple::toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs)
+void TypeTuple::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
 {
-    OutBuffer buf2;
-    Argument::argsToCBuffer(&buf2, hgs, arguments, 0);
-    buf->prependstring(buf2.toChars());
-    if (ident)
-    {	buf->writeByte(' ');
-	buf->writestring(ident->toChars());
-    }
+    Argument::argsToCBuffer(buf, hgs, arguments, 0);
 }
 
 void TypeTuple::toDecoBuffer(OutBuffer *buf)
@@ -5061,20 +5065,16 @@
     }
 }
 
-void TypeSlice::toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs)
+void TypeSlice::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
 {
-    OutBuffer buf2;
+    if (mod != this->mod)
+    {	toCBuffer3(buf, hgs, mod);
+	return;
+    }
+    next->toCBuffer2(buf, hgs, this->mod);
 
-    buf2.printf("[%s .. ", lwr->toChars());
-    buf2.printf("%s]", upr->toChars());
-
-    buf->prependstring(buf2.toChars());
-    if (ident)
-    {
-	buf->writeByte(' ');
-	buf->writestring(ident->toChars());
-    }
-    next->toCBuffer2(buf, NULL, hgs);
+    buf->printf("[%s .. ", lwr->toChars());
+    buf->printf("%s]", upr->toChars());
 }
 
 /***************************** Argument *****************************/
@@ -5131,7 +5131,7 @@
 		buf->writeByte(',');
 	    arg = (Argument *)args->data[i];
 	    argbuf.reset();
-	    arg->type->toCBuffer2(&argbuf, NULL, &hgs);
+	    arg->type->toCBuffer2(&argbuf, &hgs, 0);
 	    buf->write(&argbuf);
 	}
 	if (varargs)
@@ -5167,7 +5167,7 @@
 	    else if (arg->storageClass & STClazy)
 		buf->writestring("lazy ");
 	    argbuf.reset();
-	    arg->type->toCBuffer2(&argbuf, arg->ident, hgs);
+	    arg->type->toCBuffer(&argbuf, arg->ident, hgs);
 	    if (arg->defaultArg)
 	    {
 		argbuf.writestring(" = ");
Index: d/dmd/optimize.c
===================================================================
--- d/dmd/optimize.c	(Revision 199)
+++ d/dmd/optimize.c	(Arbeitskopie)
@@ -295,7 +295,7 @@
 	if (fd)
 	{
 	    Expression *eresult = fd->interpret(NULL, arguments);
-	    if (eresult)
+	    if (eresult && eresult != EXP_VOID_INTERPRET)
 		e = eresult;
 	    else if (result & WANTinterpret)
 		error("cannot evaluate %s at compile time", toChars());
Index: d/dmd/init.c
===================================================================
--- d/dmd/init.c	(Revision 199)
+++ d/dmd/init.c	(Arbeitskopie)
@@ -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;
 		}
 
Index: d/dmd/mtype.h
===================================================================
--- d/dmd/mtype.h	(Revision 199)
+++ d/dmd/mtype.h	(Arbeitskopie)
@@ -118,6 +118,9 @@
 struct Type : Object
 {
     TY ty;
+    unsigned char mod;	// modifiers (MODconst, MODinvariant)
+	#define MODconst     1	// type is const
+	#define MODinvariant 2	// type is invariant
     Type *next;
     char *deco;
     Type *pto;		// merged pointer to this type
@@ -206,10 +209,10 @@
     virtual unsigned alignsize();
     virtual Type *semantic(Loc loc, Scope *sc);
     virtual void toDecoBuffer(OutBuffer *buf);
-    virtual void toTypeInfoBuffer(OutBuffer *buf);
     Type *merge();
-    void toCBuffer(OutBuffer *buf, Identifier *ident, HdrGenState *hgs);
-    virtual void toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs);
+    virtual void toCBuffer(OutBuffer *buf, Identifier *ident, HdrGenState *hgs);
+    virtual void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
+    void toCBuffer3(OutBuffer *buf, HdrGenState *hgs, int mod);
     virtual int isbit();
     virtual int isintegral();
     virtual int isfloating();	// real, imaginary, or complex
@@ -233,7 +236,7 @@
     virtual Expression *getProperty(Loc loc, Identifier *ident);
     virtual Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
     virtual unsigned memalign(unsigned salign);
-    virtual Expression *defaultInit();
+    virtual Expression *defaultInit(Loc loc = 0);
     virtual int isZeroInit();		// if initializer is 0
     virtual dt_t **toDt(dt_t **pdt);
     Identifier *getTypeInfoIdent(int internal);
@@ -273,7 +276,7 @@
     Expression *getProperty(Loc loc, Identifier *ident);
     Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
     char *toChars();
-    void toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs);
+    void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
     int isintegral();
     int isbit();
     int isfloating();
@@ -283,7 +286,7 @@
     int isscalar();
     int isunsigned();
     MATCH implicitConvTo(Type *to);
-    Expression *defaultInit();
+    Expression *defaultInit(Loc loc);
     int isZeroInit();
     int builtinTypeInfo();
 
@@ -294,8 +297,6 @@
 struct TypeArray : Type
 {
     TypeArray(TY ty, Type *next);
-    virtual void toPrettyBracket(OutBuffer *buf, HdrGenState *hgs) = 0;
-    void toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs);
     Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
 };
 
@@ -311,14 +312,13 @@
     Type *semantic(Loc loc, Scope *sc);
     void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps);
     void toDecoBuffer(OutBuffer *buf);
-    void toTypeInfoBuffer(OutBuffer *buf);
-    void toPrettyBracket(OutBuffer *buf, HdrGenState *hgs);
+    void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
     Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
     int isString();
     int isZeroInit();
     unsigned memalign(unsigned salign);
     MATCH implicitConvTo(Type *to);
-    Expression *defaultInit();
+    Expression *defaultInit(Loc loc);
     dt_t **toDt(dt_t **pdt);
     dt_t **toDtElem(dt_t **pdt, Expression *e);
     MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes);
@@ -339,14 +339,13 @@
     unsigned alignsize();
     Type *semantic(Loc loc, Scope *sc);
     void toDecoBuffer(OutBuffer *buf);
-    void toTypeInfoBuffer(OutBuffer *buf);
-    void toPrettyBracket(OutBuffer *buf, HdrGenState *hgs);
+    void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
     Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
     int isString();
     int isZeroInit();
     int checkBoolean();
     MATCH implicitConvTo(Type *to);
-    Expression *defaultInit();
+    Expression *defaultInit(Loc loc);
     int builtinTypeInfo();
     TypeInfoDeclaration *getTypeInfoDeclaration();
     int hasPointers();
@@ -364,9 +363,9 @@
     d_uns64 size(Loc loc);
     Type *semantic(Loc loc, Scope *sc);
     void toDecoBuffer(OutBuffer *buf);
-    void toPrettyBracket(OutBuffer *buf, HdrGenState *hgs);
+    void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
     Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
-    Expression *defaultInit();
+    Expression *defaultInit(Loc loc);
     MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes);
     int checkBoolean();
     TypeInfoDeclaration *getTypeInfoDeclaration();
@@ -384,10 +383,10 @@
     Type *syntaxCopy();
     Type *semantic(Loc loc, Scope *sc);
     d_uns64 size(Loc loc);
-    void toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs);
+    void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
     MATCH implicitConvTo(Type *to);
     int isscalar();
-    Expression *defaultInit();
+    Expression *defaultInit(Loc loc);
     int isZeroInit();
     TypeInfoDeclaration *getTypeInfoDeclaration();
     int hasPointers();
@@ -400,9 +399,9 @@
     TypeReference(Type *t);
     Type *syntaxCopy();
     d_uns64 size(Loc loc);
-    void toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs);
+    void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
     Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
-    Expression *defaultInit();
+    Expression *defaultInit(Loc loc);
     int isZeroInit();
 };
 
@@ -425,7 +424,8 @@
     Type *syntaxCopy();
     Type *semantic(Loc loc, Scope *sc);
     void toDecoBuffer(OutBuffer *buf);
-    void toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs);
+    void toCBuffer(OutBuffer *buf, Identifier *ident, HdrGenState *hgs);
+    void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
     MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes);
     TypeInfoDeclaration *getTypeInfoDeclaration();
     Type *reliesOnTident();
@@ -443,8 +443,8 @@
     Type *syntaxCopy();
     Type *semantic(Loc loc, Scope *sc);
     d_uns64 size(Loc loc);
-    void toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs);
-    Expression *defaultInit();
+    void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
+    Expression *defaultInit(Loc loc);
     int isZeroInit();
     int checkBoolean();
     TypeInfoDeclaration *getTypeInfoDeclaration();
@@ -462,7 +462,7 @@
     TypeQualified(TY ty, Loc loc);
     void syntaxCopyHelper(TypeQualified *t);
     void addIdent(Identifier *ident);
-    void toCBuffer2Helper(OutBuffer *buf, Identifier *ident, HdrGenState *hgs);
+    void toCBuffer2Helper(OutBuffer *buf, HdrGenState *hgs);
     d_uns64 size(Loc loc);
     void resolveHelper(Loc loc, Scope *sc, Dsymbol *s, Dsymbol *scopesym,
 	Expression **pe, Type **pt, Dsymbol **ps);
@@ -476,7 +476,7 @@
     Type *syntaxCopy();
     //char *toChars();
     void toDecoBuffer(OutBuffer *buf);
-    void toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs);
+    void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
     void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps);
     Dsymbol *toDsymbol(Scope *sc);
     Type *semantic(Loc loc, Scope *sc);
@@ -495,7 +495,7 @@
     Type *syntaxCopy();
     //char *toChars();
     //void toDecoBuffer(OutBuffer *buf);
-    void toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs);
+    void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
     void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps);
     Type *semantic(Loc loc, Scope *sc);
     MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes);
@@ -508,7 +508,7 @@
     TypeTypeof(Loc loc, Expression *exp);
     Type *syntaxCopy();
     Dsymbol *toDsymbol(Scope *sc);
-    void toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs);
+    void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
     Type *semantic(Loc loc, Scope *sc);
     d_uns64 size(Loc loc);
 };
@@ -525,11 +525,10 @@
     Type *semantic(Loc loc, Scope *sc);
     Dsymbol *toDsymbol(Scope *sc);
     void toDecoBuffer(OutBuffer *buf);
-    void toTypeInfoBuffer(OutBuffer *buf);
-    void toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs);
+    void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
     Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
     unsigned memalign(unsigned salign);
-    Expression *defaultInit();
+    Expression *defaultInit(Loc loc);
     int isZeroInit();
     int checkBoolean();
     dt_t **toDt(dt_t **pdt);
@@ -551,8 +550,7 @@
     Type *semantic(Loc loc, Scope *sc);
     Dsymbol *toDsymbol(Scope *sc);
     void toDecoBuffer(OutBuffer *buf);
-    void toTypeInfoBuffer(OutBuffer *buf);
-    void toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs);
+    void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
     Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
     Expression *getProperty(Loc loc, Identifier *ident);
     int isintegral();
@@ -561,7 +559,7 @@
     int isunsigned();
     MATCH implicitConvTo(Type *to);
     Type *toBasetype();
-    Expression *defaultInit();
+    Expression *defaultInit(Loc loc);
     int isZeroInit();
     MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes);
     TypeInfoDeclaration *getTypeInfoDeclaration();
@@ -582,9 +580,9 @@
     Type *semantic(Loc loc, Scope *sc);
     Dsymbol *toDsymbol(Scope *sc);
     void toDecoBuffer(OutBuffer *buf);
-    void toTypeInfoBuffer(OutBuffer *buf);
-    void toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs);
+    void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
     Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
+    Expression *getProperty(Loc loc, Identifier *ident);
     int isbit();
     int isintegral();
     int isfloating();
@@ -596,7 +594,7 @@
     int checkBoolean();
     Type *toBasetype();
     MATCH implicitConvTo(Type *to);
-    Expression *defaultInit();
+    Expression *defaultInit(Loc loc);
     int isZeroInit();
     dt_t **toDt(dt_t **pdt);
     MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes);
@@ -618,12 +616,12 @@
     Type *semantic(Loc loc, Scope *sc);
     Dsymbol *toDsymbol(Scope *sc);
     void toDecoBuffer(OutBuffer *buf);
-    void toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs);
+    void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
     Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
     ClassDeclaration *isClassHandle();
     int isBaseOf(Type *t, target_ptrdiff_t *poffset);
     MATCH implicitConvTo(Type *to);
-    Expression *defaultInit();
+    Expression *defaultInit(Loc loc);
     int isZeroInit();
     MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes);
     int isauto();
@@ -646,7 +644,7 @@
     Type *semantic(Loc loc, Scope *sc);
     int equals(Object *o);
     Type *reliesOnTident();
-    void toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs);
+    void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
     void toDecoBuffer(OutBuffer *buf);
     Expression *getProperty(Loc loc, Identifier *ident);
     TypeInfoDeclaration *getTypeInfoDeclaration();
@@ -661,7 +659,7 @@
     Type *syntaxCopy();
     Type *semantic(Loc loc, Scope *sc);
     void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps);
-    void toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs);
+    void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
 };
 
 /**************************************************************/
Index: d/dmd/statement.c
===================================================================
--- d/dmd/statement.c	(Revision 199)
+++ d/dmd/statement.c	(Arbeitskopie)
@@ -528,7 +528,7 @@
 int CompoundStatement::fallOffEnd()
 {   int falloff = TRUE;
 
-    //printf("CompoundStatement::fallOffEnd()\n");
+    //printf("CompoundStatement::fallOffEnd() %s\n", toChars());
     for (int i = 0; i < statements->dim; i++)
     {	Statement *s = (Statement *)statements->data[i];
 
@@ -648,25 +648,18 @@
 }
 
 int UnrolledLoopStatement::fallOffEnd()
-{   int falloff = TRUE;
-
+{
     //printf("UnrolledLoopStatement::fallOffEnd()\n");
     for (size_t i = 0; i < statements->dim; i++)
     {	Statement *s = (Statement *)statements->data[i];
 
-	if (!s)
-	    continue;
-
-	if (!falloff && global.params.warnings && !s->comeFrom())
-	{
-	    fprintf(stdmsg, "warning - ");
-	    s->error("statement is not reachable");
-	}
-	falloff = s->fallOffEnd();
+	if (s)
+	    s->fallOffEnd();
     }
-    return falloff;
+    return TRUE;
 }
 
+
 int UnrolledLoopStatement::comeFrom()
 {   int comefrom = FALSE;
 
@@ -1998,6 +1991,7 @@
     {	condition = condition->integralPromotions(sc);
 	condition->checkIntegral();
     }
+    condition = condition->optimize(WANTvalue);
 
     sc = sc->push();
     sc->sbreak = this;
@@ -3222,7 +3216,7 @@
 int TryFinallyStatement::fallOffEnd()
 {   int result;
 
-    result = body->fallOffEnd();
+    result = body ? body->fallOffEnd() : TRUE;
 //    if (finalbody)
 //	result = finalbody->fallOffEnd();
     return result;
Index: d/dmd/class.c
===================================================================
--- d/dmd/class.c	(Revision 199)
+++ d/dmd/class.c	(Arbeitskopie)
@@ -1,6 +1,6 @@
 
 // Compiler implementation of the D programming language
-// Copyright (c) 1999-2007 by Digital Mars
+// Copyright (c) 1999-2008 by Digital Mars
 // All Rights Reserved
 // written by Walter Bright
 // http://www.digitalmars.com
@@ -652,6 +652,7 @@
     sizeok = 1;
     Module::dprogress++;
 
+    dtor = buildDtor(sc);
 
     sc->pop();
 
Index: d/dmd/toobj.c
===================================================================
--- d/dmd/toobj.c	(Revision 199)
+++ d/dmd/toobj.c	(Arbeitskopie)
@@ -100,7 +100,7 @@
 {
     Symbol *msym = toSymbol();
     unsigned offset;
-    unsigned sizeof_ModuleInfo = 12 * PTRSIZE;
+    unsigned sizeof_ModuleInfo = 14 * PTRSIZE;
 
     //////////////////////////////////////////////
 
@@ -118,6 +118,8 @@
 	    void *ctor;
 	    void *dtor;
 	    void *unitTest;
+	    const(MemberInfo[]) function(string) xgetMembers;	// module getMembers() function
+	    void *ictor;
        }
      */
     dt_t *dt = NULL;
@@ -180,9 +182,9 @@
 	dtdword(&dt, 0);
 
     if (needmoduleinfo)
-	dti32(&dt, 0, true);		// flags (4 means MIstandalone)
+	dti32(&dt, 8|0, true);		// flags (4 means MIstandalone)
     else
-	dti32(&dt, 4, true);		// flags (4 means MIstandalone)
+	dti32(&dt, 8|4, true);		// flags (4 means MIstandalone)
 
     if (sctor)
 	dtxoff(&dt, sctor, 0, TYnptr);
@@ -199,6 +201,13 @@
     else
 	dtdword(&dt, 0);
 
+    dtdword(&dt, 0);			// xgetMembers
+
+    if (sictor)
+	dtxoff(&dt, sictor, 0, TYnptr);
+    else
+	dtdword(&dt, 0);
+
     //////////////////////////////////////////////
 
 #ifdef IN_GCC
@@ -283,7 +292,6 @@
 {   unsigned i;
     unsigned offset;
     Symbol *sinit;
-    Symbol *sdtor;
     enum_SC scclass;
 
     //printf("ClassDeclaration::toObjFile('%s')\n", toChars());
@@ -309,8 +317,9 @@
 	member = (Dsymbol *)members->data[i];
 	member->toObjFile();
     }
-
     // Build destructor by aggregating dtors[]
+#if 0
+    Symbol *sdtor;
 #ifndef IN_GCC
     switch (dtors.dim)
     {	case 0:
@@ -371,7 +380,7 @@
 #else
     sdtor = d_gcc_aggregate_dtors(this);
 #endif
-
+#endif
     // Generate C symbols
     toSymbol();
     toVtblSymbol();
@@ -458,8 +467,8 @@
 	dtdword(&dt, 0);
 
     // destructor
-    if (sdtor)
-	dtxoff(&dt, sdtor, 0, TYnptr);
+    if (dtor)
+	dtxoff(&dt, dtor->toSymbol(), 0, TYnptr);
     else
 	dtdword(&dt, 0);
 
Index: d/dmd/declaration.c
===================================================================
--- d/dmd/declaration.c	(Revision 199)
+++ d/dmd/declaration.c	(Arbeitskopie)
@@ -35,6 +35,7 @@
     : Dsymbol(id)
 {
     type = NULL;
+    originalType = NULL;
     storage_class = STCundefined;
     protection = PROTundefined;
     linkage = LINKdefault;
@@ -627,9 +628,13 @@
 	 * declarations.
 	 */
 	storage_class &= ~STCauto;
+	originalType = type;
     }
     else
+    {	if (!originalType)
+	    originalType = type;
 	type = type->semantic(loc, sc);
+    }
 
     type->checkDeprecated(loc, sc);
     linkage = sc->linkage;
@@ -674,6 +679,7 @@
 	size_t nelems = Argument::dim(tt->arguments);
 	Objects *exps = new Objects();
 	exps->setDim(nelems);
+	Expression *ie = init ? init->toExpression() : NULL;
 
 	for (size_t i = 0; i < nelems; i++)
 	{   Argument *arg = Argument::getNth(tt->arguments, i);
@@ -684,7 +690,16 @@
 	    char *name = (char *)buf.extractData();
 	    Identifier *id = new Identifier(name, TOKidentifier);
 
-	    VarDeclaration *v = new VarDeclaration(loc, arg->type, id, NULL);
+	    Expression *einit = ie;
+	    if (ie && ie->op == TOKtuple)
+	    {	einit = (Expression *)((TupleExp *)ie)->exps->data[i];
+	    }
+	    Initializer *ti = init;
+	    if (einit)
+	    {	ti = new ExpInitializer(einit->loc, einit);
+	    }
+
+	    VarDeclaration *v = new VarDeclaration(loc, arg->type, id, ti);
 	    //printf("declaring field %s of type %s\n", v->toChars(), v->type->toChars());
 	    v->semantic(sc);
 
@@ -780,7 +795,8 @@
     }
 
     if (!init && !sc->inunion && !isStatic() && !isConst() && fd &&
-	!(storage_class & (STCfield | STCin | STCforeach)))
+	!(storage_class & (STCfield | STCin | STCforeach)) &&
+	type->size() != 0)
     {
 	// Provide a default initializer
 	//printf("Providing default initializer for '%s'\n", toChars());
@@ -873,19 +889,19 @@
 		t = type->toBasetype();
 		if (t->ty == Tsarray)
 		{
+		    ei->exp = ei->exp->semantic(sc);
+		    if (!ei->exp->implicitConvTo(type))
+		    {
 		    dim = ((TypeSArray *)t)->dim->toInteger();
 		    // If multidimensional static array, treat as one large array
 		    while (1)
 		    {
-			t = t->next->toBasetype();
+			    t = t->nextOf()->toBasetype();
 			if (t->ty != Tsarray)
 			    break;
-			if (t->next->toBasetype()->ty == Tbit)
-			    // t->size() gives size in bytes, convert to bits
-			    dim *= t->size() * 8;
-			else
 			    dim *= ((TypeSArray *)t)->dim->toInteger();
-			e1->type = new TypeSArray(t->next, new IntegerExp(0, dim, Type::tindex));
+			    e1->type = new TypeSArray(t->nextOf(), new IntegerExp(0, dim, Type::tindex));
+			}
 		    }
 		    e1 = new SliceExp(loc, e1, NULL, NULL);
 		}
@@ -1052,7 +1068,7 @@
 
 void VarDeclaration::checkNestedReference(Scope *sc, Loc loc)
 {
-    if (!isDataseg() && parent != sc->parent && parent)
+    if (parent && !isDataseg() && parent != sc->parent)
     {
 	FuncDeclaration *fdv = toParent()->isFuncDeclaration();
 	FuncDeclaration *fdthis = sc->parent->isFuncDeclaration();
@@ -1103,6 +1119,7 @@
 Expression *VarDeclaration::callAutoDtor()
 {   Expression *e = NULL;
 
+    //printf("VarDeclaration::callAutoDtor() %s\n", toChars());
     if (storage_class & (STCauto | STCscope) && !noauto)
     {
 	for (ClassDeclaration *cd = type->isClassHandle();
@@ -1113,6 +1130,8 @@
 	     * classes to determine if there's no way the monitor
 	     * could be set.
 	     */
+	    //if (cd->isInterfaceDeclaration())
+		//error("interface %s cannot be scope", cd->toChars());
 	    if (1 || onstack || cd->dtors.dim)	// if any destructors
 	    {
 		// delete this;
@@ -1189,6 +1208,24 @@
     assert(linkage == LINKc);
 }
 
+/***************************** TypeInfoConstDeclaration **********************/
+
+#if V2
+TypeInfoConstDeclaration::TypeInfoConstDeclaration(Type *tinfo)
+    : TypeInfoDeclaration(tinfo, 0)
+{
+}
+#endif
+
+/***************************** TypeInfoInvariantDeclaration **********************/
+
+#if V2
+TypeInfoInvariantDeclaration::TypeInfoInvariantDeclaration(Type *tinfo)
+    : TypeInfoDeclaration(tinfo, 0)
+{
+}
+#endif
+
 /***************************** TypeInfoStructDeclaration **********************/
 
 TypeInfoStructDeclaration::TypeInfoStructDeclaration(Type *tinfo)
Index: d/dmd/declaration.h
===================================================================
--- d/dmd/declaration.h	(Revision 199)
+++ d/dmd/declaration.h	(Arbeitskopie)
@@ -89,6 +89,7 @@
 struct Declaration : Dsymbol
 {
     Type *type;
+    Type *originalType;		// before semantic analysis
     unsigned storage_class;
     enum PROT protection;
     enum LINK linkage;
@@ -113,6 +114,7 @@
     int isFinal()        { return storage_class & STCfinal; }
     int isAbstract()     { return storage_class & STCabstract; }
     int isConst()        { return storage_class & STCconst; }
+    int isInvariant()    { return 0; }
     int isAuto()         { return storage_class & STCauto; }
     int isScope()        { return storage_class & (STCscope | STCauto); }
     int isSynchronized() { return storage_class & STCsynchronized; }
@@ -413,6 +415,23 @@
 
 /**************************************************************/
 
+#if V2
+
+enum BUILTIN
+{
+    BUILTINunknown = -1,	// not known if this is a builtin
+    BUILTINnot,			// this is not a builtin
+    BUILTINsin,			// std.math.sin
+    BUILTINcos,			// std.math.cos
+    BUILTINtan,			// std.math.tan
+    BUILTINsqrt,		// std.math.sqrt
+    BUILTINfabs,		// std.math.fabs
+};
+
+Expression *eval_builtin(enum BUILTIN builtin, Expressions *arguments);
+
+#endif
+
 struct FuncDeclaration : Declaration
 {
     Array *fthrows;			// Array of Type's of exceptions (not used)
@@ -443,7 +462,6 @@
     int inlineNest;			// !=0 if nested inline
     int cantInterpret;			// !=0 if cannot interpret function
     int semanticRun;			// !=0 if semantic3() had been run
-    int nestedFrameRef;			// !=0 if nested variables referenced frame ptr
     ForeachStatement *fes;		// if foreach body, this is the foreach
     int introducing;			// !=0 if 'introducing' function
     Type *tintro;			// if !=NULL, then this is the type
@@ -463,6 +481,20 @@
     VarDeclaration *nrvo_var;		// variable to replace with shidden
     Symbol *shidden;			// hidden pointer passed to function
 
+#if V2
+    enum BUILTIN builtin;		// set if this is a known, builtin
+					// function we can evaluate at compile
+					// time
+
+    int tookAddressOf;			// set if someone took the address of
+					// this function
+    Dsymbols closureVars;		// local variables in this function
+					// which are referenced by nested
+					// functions
+#else
+    int nestedFrameRef;			// !=0 if nested variables referenced
+#endif
+
     FuncDeclaration(Loc loc, Loc endloc, Identifier *id, enum STC storage_class, Type *type);
     Dsymbol *syntaxCopy(Dsymbol *);
     void semantic(Scope *sc);
@@ -559,6 +591,7 @@
 struct DtorDeclaration : FuncDeclaration
 {
     DtorDeclaration(Loc loc, Loc endloc);
+    DtorDeclaration(Loc loc, Loc endloc, Identifier *id);
     Dsymbol *syntaxCopy(Dsymbol *);
     void semantic(Scope *sc);
     void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
Index: d/dmd/expression.c
===================================================================
--- d/dmd/expression.c	(Revision 199)
+++ d/dmd/expression.c	(Arbeitskopie)
@@ -1,6 +1,6 @@
 
 // Compiler implementation of the D programming language
-// Copyright (c) 1999-2007 by Digital Mars
+// Copyright (c) 1999-2008 by Digital Mars
 // All Rights Reserved
 // written by Walter Bright
 // http://www.digitalmars.com
@@ -92,6 +92,7 @@
 
 void initPrecedence()
 {
+    precedence[TOKdotvar] = PREC_primary;
     precedence[TOKimport] = PREC_primary;
     precedence[TOKidentifier] = PREC_primary;
     precedence[TOKthis] = PREC_primary;
@@ -173,6 +174,8 @@
     precedence[TOKquestion] = PREC_cond;
 
     precedence[TOKassign] = PREC_assign;
+    precedence[TOKconstruct] = PREC_assign;
+    precedence[TOKblit] = PREC_assign;
     precedence[TOKaddass] = PREC_assign;
     precedence[TOKminass] = PREC_assign;
     precedence[TOKcatass] = PREC_assign;
@@ -521,7 +524,7 @@
 	    {
 		// BUG: should check that argument to ref is type 'invariant'
 		// BUG: assignments to ref should also be type 'invariant'
-		arg = arg->modifiableLvalue(sc, NULL);
+		arg = arg->modifiableLvalue(sc, arg);
 
 		//if (arg->op == TOKslice)
 		    //arg->error("cannot modify slice %s", arg->toChars());
@@ -646,7 +649,7 @@
 	    if (i)
 		buf->writeByte(',');
 	    argbuf.reset();
-	    arg->type->toCBuffer2(&argbuf, NULL, hgs);
+	    arg->type->toCBuffer2(&argbuf, hgs, 0);
 	    buf->write(&argbuf);
 	}
     }
@@ -853,10 +856,13 @@
     return this;
 }
 
-void Expression::checkArithmetic()
+Expression *Expression::checkArithmetic()
 {
     if (!type->isintegral() && !type->isfloating())
-	error("'%s' is not an arithmetic type", toChars());
+    {	error("'%s' is not of arithmetic type, it is a %s", toChars(), type->toChars());
+	return new IntegerExp(0);
+    }
+    return this;
 }
 
 void Expression::checkDeprecated(Scope *sc, Dsymbol *s)
@@ -1268,7 +1274,7 @@
 
 char *RealExp::toChars()
 {
-    static char buffer[sizeof(value) * 3 + 8 + 1 + 1];
+    char buffer[sizeof(value) * 3 + 8 + 1 + 1];
 
 #ifdef IN_GCC
     value.format(buffer, sizeof(buffer));
@@ -1278,7 +1284,7 @@
     sprintf(buffer, type->isimaginary() ? "%Lgi" : "%Lg", value);
 #endif
     assert(strlen(buffer) < sizeof(buffer));
-    return buffer;
+    return mem.strdup(buffer);
 }
 
 integer_t RealExp::toInteger()
@@ -1513,7 +1519,7 @@
 
 char *ComplexExp::toChars()
 {
-    static char buffer[sizeof(value) * 3 + 8 + 1];
+    char buffer[sizeof(value) * 3 + 8 + 1];
 
 #ifdef IN_GCC
     char buf1[sizeof(value) * 3 + 8 + 1];
@@ -1525,7 +1531,7 @@
     sprintf(buffer, "(%Lg+%Lgi)", creall(value), cimagl(value));
     assert(strlen(buffer) < sizeof(buffer));
 #endif
-    return buffer;
+    return mem.strdup(buffer);
 }
 
 integer_t ComplexExp::toInteger()
@@ -1794,7 +1800,7 @@
     em = s->isEnumMember();
     if (em)
     {
-	e = em->value;
+	e = em->value->copy();
 	e = e->semantic(sc);
 	return e;
     }
@@ -2530,6 +2536,8 @@
 #if LOGSEMANTIC
     printf("ArrayLiteralExp::semantic('%s')\n", toChars());
 #endif
+    if (type)
+	return this;
 
     // Run semantic() on each element
     for (int i = 0; i < elements->dim; i++)
@@ -3174,7 +3182,13 @@
 	if (cd->isInterfaceDeclaration())
 	    error("cannot create instance of interface %s", cd->toChars());
 	else if (cd->isAbstract())
-	    error("cannot create instance of abstract class %s", cd->toChars());
+	{   error("cannot create instance of abstract class %s", cd->toChars());
+	    for (int i = 0; i < cd->vtbl.dim; i++)
+	    {	FuncDeclaration *fd = ((Dsymbol *)cd->vtbl.data[i])->isFuncDeclaration();
+		if (fd && fd->isAbstract())
+		    error("function %s is abstract", fd->toChars());
+	    }
+	}
 	checkDeprecated(sc, cd);
 	if (cd->isNested())
 	{   /* We need a 'this' pointer for the nested class.
@@ -3798,6 +3812,25 @@
     }
 }
 
+elem *TupleExp::toElem(IRState *irs)
+{   //elem *e = NULL;
+
+    printf("TupleExp::toElem() %s\n", toChars());
+    printf("EXPER: Uneducated guesswork ensues. Beware.");
+    Expression *res;
+    for (size_t i = 0; i < exps->dim; i++)
+      res = Expression::combine(res, (Expression *)exps->data[i]);
+    return res->toElem(irs);
+    /*
+    for (size_t i = 0; i < exps->dim; i++)
+    {	Expression *el = (Expression *)exps->data[i];
+	elem *ep = el->toElem(irs);
+
+	e = el_combine(e, ep);
+    }
+    return e;*/
+}
+
 /******************************** FuncExp *********************************/
 
 FuncExp::FuncExp(Loc loc, FuncLiteralDeclaration *fd)
@@ -4381,7 +4414,7 @@
 	if (e)
 	    return e;
 
-	e1 = e1->modifiableLvalue(sc, NULL);
+	e1 = e1->modifiableLvalue(sc, e1);
 	e1->checkScalar();
 	type = e1->type;
 	if (type->toBasetype()->ty == Tbool)
@@ -4412,7 +4445,7 @@
 	if (e)
 	    return e;
 
-	e1 = e1->modifiableLvalue(sc, NULL);
+	e1 = e1->modifiableLvalue(sc, e1);
 	e1->checkScalar();
 	type = e1->type;
 	if (type->toBasetype()->ty == Tbool)
@@ -4432,6 +4465,8 @@
     if (op == TOKplusplus ||
 	   op == TOKminusminus ||
 	   op == TOKassign ||
+	   op == TOKconstruct ||
+	   op == TOKblit ||
 	   op == TOKaddass ||
 	   op == TOKminass ||
 	   op == TOKcatass ||
@@ -5558,9 +5593,9 @@
 	    TemplateDeclaration *td = dte->td;
 	    assert(td);
 	    if (!arguments)
-		// Should fix deduce() so it works on NULL argument
+		// Should fix deduceFunctionTemplate() so it works on NULL argument
 		arguments = new Expressions();
-	    f = td->deduce(sc, loc, NULL, arguments);
+	    f = td->deduceFunctionTemplate(sc, loc, NULL, arguments);
 	    if (!f)
 	    {	type = Type::terror;
 		return this;
@@ -5735,7 +5770,7 @@
 	else if (e1->op == TOKtemplate)
 	{
 	    TemplateExp *te = (TemplateExp *)e1;
-	    f = te->td->deduce(sc, loc, NULL, arguments);
+	    f = te->td->deduceFunctionTemplate(sc, loc, NULL, arguments);
 	    if (!f)
 	    {	type = Type::terror;
 		return this;
@@ -6154,13 +6189,10 @@
 
 		if (f)
 		{
-		    Expression *e;
-		    Expression *ec;
 		    Type *tpv = Type::tvoid->pointerTo();
 
-		    e = e1;
-		    e->type = tpv;
-		    ec = new VarExp(loc, f);
+		    Expression *e = e1->castTo(sc, tpv);
+		    Expression *ec = new VarExp(loc, f);
 		    e = new CallExp(loc, ec, e);
 		    return e->semantic(sc);
 		}
@@ -6252,7 +6284,10 @@
 	}
 
 	Type *tob = to->toBasetype();
-	if (tob->ty == Tstruct && !tob->equals(e1->type->toBasetype()))
+	if (tob->ty == Tstruct &&
+	    !tob->equals(e1->type->toBasetype()) &&
+	    ((TypeStruct *)to)->sym->search(0, Id::call, 0)
+	   )
 	{
 	    /* Look to replace:
 	     *	cast(S)t
@@ -6893,7 +6928,7 @@
 	    return e;
 
 	e = this;
-	e1 = e1->modifiableLvalue(sc, NULL);
+	e1 = e1->modifiableLvalue(sc, e1);
 	e1->checkScalar();
 	e1->checkNoBool();
 	if (e1->type->ty == Tpointer)
@@ -7023,6 +7058,31 @@
     e2 = resolveProperties(sc, e2);
     assert(e1->type);
 
+    /* Rewrite tuple assignment as a tuple of assignments.
+     */
+    if (e1->op == TOKtuple && e2->op == TOKtuple)
+    {	TupleExp *tup1 = (TupleExp *)e1;
+	TupleExp *tup2 = (TupleExp *)e2;
+	size_t dim = tup1->exps->dim;
+	if (dim != tup2->exps->dim)
+	{
+	    error("mismatched tuple lengths, %d and %d", (int)dim, (int)tup2->exps->dim);
+	}
+	else
+	{   Expressions *exps = new Expressions;
+	    exps->setDim(dim);
+
+	    for (int i = 0; i < dim; i++)
+	    {	Expression *ex1 = (Expression *)tup1->exps->data[i];
+		Expression *ex2 = (Expression *)tup2->exps->data[i];
+		exps->data[i] = (void *) new AssignExp(loc, ex1, ex2);
+	    }
+	    Expression *e = new TupleExp(loc, exps);
+	    e = e->semantic(sc);
+	    return e;
+	}
+    }
+
     t1 = e1->type->toBasetype();
 
     if (t1->ty == Tfunction)
@@ -7054,7 +7114,7 @@
 	// e1 is not an lvalue, but we let code generator handle it
 	ArrayLengthExp *ale = (ArrayLengthExp *)e1;
 
-	ale->e1 = ale->e1->modifiableLvalue(sc, NULL);
+	ale->e1 = ale->e1->modifiableLvalue(sc, e1);
     }
     else if (e1->op == TOKslice)
 	;
@@ -7065,21 +7125,14 @@
     }
 
     if (e1->op == TOKslice &&
-	t1->next &&
-	!(t1->next->equals(e2->type->next) /*||
-	  (t1->next->ty == Tchar && e2->op == TOKstring)*/)
+	t1->nextOf() &&
+	e2->implicitConvTo(t1->nextOf())
+//	!(t1->nextOf()->equals(e2->type->nextOf()))
        )
     {	// memset
+	ismemset = 1;	// make it easy for back end to tell what this is
 	e2 = e2->implicitCastTo(sc, t1->next);
     }
-#if 0
-    else if (e1->op == TOKslice &&
-	     e2->op == TOKstring &&
-	     ((StringExp *)e2)->len == 1)
-    {	// memset
-	e2 = e2->implicitCastTo(sc, e1->type->next);
-    }
-#endif
     else if (t1->ty == Tsarray)
     {
 	error("cannot assign to static array %s", e1->toChars());
@@ -7123,7 +7176,7 @@
     if (e)
 	return e;
 
-    e1 = e1->modifiableLvalue(sc, NULL);
+    e1 = e1->modifiableLvalue(sc, e1);
 
     Type *tb1 = e1->type->toBasetype();
     Type *tb2 = e2->type->toBasetype();
@@ -7223,17 +7276,17 @@
     if (e)
 	return e;
 
-    e1 = e1->modifiableLvalue(sc, NULL);
+    e1 = e1->modifiableLvalue(sc, e1);
     e1->checkScalar();
     e1->checkNoBool();
     if (e1->type->ty == Tpointer && e2->type->isintegral())
 	e = scaleFactor(sc);
     else
     {
+	e1 = e1->checkArithmetic();
+	e2 = e2->checkArithmetic();
 	type = e1->type;
 	typeCombine(sc);
-	e1->checkArithmetic();
-	e2->checkArithmetic();
 	if (type->isreal() || type->isimaginary())
 	{
 	    assert(e2->type->isfloating());
@@ -7268,11 +7321,13 @@
 	    error("cannot append to static array %s", se->e1->type->toChars());
     }
 
-    e1 = e1->modifiableLvalue(sc, NULL);
+    e1 = e1->modifiableLvalue(sc, e1);
 
     Type *tb1 = e1->type->toBasetype();
     Type *tb2 = e2->type->toBasetype();
 
+    e2->rvalue();
+
     if ((tb1->ty == Tarray) &&
 	(tb2->ty == Tarray || tb2->ty == Tsarray) &&
 	e2->implicitConvTo(e1->type)
@@ -7317,7 +7372,7 @@
     if (e)
 	return e;
 
-    e1 = e1->modifiableLvalue(sc, NULL);
+    e1 = e1->modifiableLvalue(sc, e1);
     e1->checkScalar();
     e1->checkNoBool();
     type = e1->type;
@@ -7373,7 +7428,7 @@
     if (e)
 	return e;
 
-    e1 = e1->modifiableLvalue(sc, NULL);
+    e1 = e1->modifiableLvalue(sc, e1);
     e1->checkScalar();
     e1->checkNoBool();
     type = e1->type;
@@ -7444,7 +7499,7 @@
     if (e)
 	return e;
 
-    e1 = e1->modifiableLvalue(sc, NULL);
+    e1 = e1->modifiableLvalue(sc, e1);
     e1->checkScalar();
     e1->checkNoBool();
     type = e1->type;
@@ -7472,7 +7527,7 @@
     if (e)
 	return e;
 
-    e1 = e1->modifiableLvalue(sc, NULL);
+    e1 = e1->modifiableLvalue(sc, e1);
     e1->checkScalar();
     e1->checkNoBool();
     type = e1->type;
@@ -7500,7 +7555,7 @@
     if (e)
 	return e;
 
-    e1 = e1->modifiableLvalue(sc, NULL);
+    e1 = e1->modifiableLvalue(sc, e1);
     e1->checkScalar();
     e1->checkNoBool();
     type = e1->type;
@@ -8333,6 +8388,13 @@
 	return this;
 
     BinExp::semanticp(sc);
+
+    if (e1->type->toBasetype()->ty == Tclass && e2->op == TOKnull ||
+	e2->type->toBasetype()->ty == Tclass && e1->op == TOKnull)
+    {
+	error("do not use null when comparing class types");
+    }
+
     e = op_overload(sc);
     if (e)
     {
@@ -8386,6 +8448,7 @@
 EqualExp::EqualExp(enum TOK op, Loc loc, Expression *e1, Expression *e2)
 	: BinExp(loc, op, sizeof(EqualExp), e1, e2)
 {
+    assert(op == TOKequal || op == TOKnotequal);
 }
 
 Expression *EqualExp::semantic(Scope *sc)
@@ -8420,6 +8483,14 @@
 	}
     }
 
+    if (e1->type->toBasetype()->ty == Tclass && e2->op == TOKnull ||
+	e2->type->toBasetype()->ty == Tclass && e1->op == TOKnull)
+    {
+	error("use '%s' instead of '%s' when comparing with null",
+		Token::toChars(op == TOKequal ? TOKidentity : TOKnotidentity),
+		Token::toChars(op));
+    }
+
     //if (e2->op != TOKnull)
     {
 	e = op_overload(sc);
Index: d/dmd/clone.c
===================================================================
--- d/dmd/clone.c	(Revision 0)
+++ d/dmd/clone.c	(Revision 0)
@@ -0,0 +1,175 @@
+
+// Compiler implementation of the D programming language
+// Copyright (c) 1999-2008 by Digital Mars
+// All Rights Reserved
+// written by Walter Bright
+// http://www.digitalmars.com
+// License for redistribution is by either the Artistic License
+// in artistic.txt, or the GNU General Public License in gnu.txt.
+// See the included readme.txt for details.
+
+#include <stdio.h>
+#include <assert.h>
+
+#include "root.h"
+#include "aggregate.h"
+#include "scope.h"
+#include "mtype.h"
+#include "declaration.h"
+#include "module.h"
+#include "id.h"
+#include "expression.h"
+#include "statement.h"
+
+
+/*********************************
+ * Generate expression that calls opClone()
+ * for each member of the struct
+ * (can be NULL for members that don't need one)
+ */
+
+#if V2
+Expression *StructDeclaration::cloneMembers()
+{
+    Expression *e = NULL;
+
+    for (size_t i = 0; i < fields.dim; i++)
+    {
+	Dsymbol *s = (Dsymbol *)fields.data[i];
+	VarDeclaration *v = s->isVarDeclaration();
+	assert(v && v->storage_class & STCfield);
+	Type *tv = v->type->toBasetype();
+	size_t dim = 1;
+	while (tv->ty == Tsarray)
+	{   TypeSArray *ta = (TypeSArray *)tv;
+	    dim *= ((TypeSArray *)tv)->dim->toInteger();
+	    tv = tv->nextOf()->toBasetype();
+	}
+	if (tv->ty == Tstruct)
+	{   TypeStruct *ts = (TypeStruct *)tv;
+	    StructDeclaration *sd = ts->sym;
+	    if (sd->opclone)
+	    {	Expression *ex;
+
+		// this.v
+		ex = new ThisExp(0);
+		ex = new DotVarExp(0, ex, v, 0);
+
+		if (dim == 1)
+		{   // this.v.opClone()
+		    ex = new DotVarExp(0, ex, sd->opclone, 0);
+		    ex = new CallExp(0, ex);
+		}
+		else
+		{
+		    // _callOpClones(&this.v, opclone, dim)
+		    Expressions *args = new Expressions();
+		    args->push(new AddrExp(0, ex));
+		    args->push(new SymOffExp(0, sd->opclone, 0));
+		    args->push(new IntegerExp(dim));
+		    FuncDeclaration *ec = FuncDeclaration::genCfunc(Type::tvoid, "_callOpClones");
+		    ex = new CallExp(0, new VarExp(0, ec), args);
+		}
+		e = Expression::combine(e, ex);
+	    }
+	}
+    }
+    return e;
+}
+#endif
+
+/*****************************************
+ * Create inclusive destructor for struct by aggregating
+ * all the destructors in dtors[] with the destructors for
+ * all the members.
+ */
+
+FuncDeclaration *AggregateDeclaration::buildDtor(Scope *sc)
+{
+    //printf("StructDeclaration::buildDtor() %s\n", toChars());
+    Expression *e = NULL;
+
+#if V2
+    for (size_t i = 0; i < fields.dim; i++)
+    {
+	Dsymbol *s = (Dsymbol *)fields.data[i];
+	VarDeclaration *v = s->isVarDeclaration();
+	assert(v && v->storage_class & STCfield);
+	Type *tv = v->type->toBasetype();
+	size_t dim = 1;
+	while (tv->ty == Tsarray)
+	{   TypeSArray *ta = (TypeSArray *)tv;
+	    dim *= ((TypeSArray *)tv)->dim->toInteger();
+	    tv = tv->nextOf()->toBasetype();
+	}
+	if (tv->ty == Tstruct)
+	{   TypeStruct *ts = (TypeStruct *)tv;
+	    StructDeclaration *sd = ts->sym;
+	    if (sd->dtor)
+	    {	Expression *ex;
+
+		// this.v
+		ex = new ThisExp(0);
+		ex = new DotVarExp(0, ex, v, 0);
+
+		if (dim == 1)
+		{   // this.v.dtor()
+		    ex = new DotVarExp(0, ex, sd->dtor, 0);
+		    ex = new CallExp(0, ex);
+		}
+		else
+		{
+		    // Typeinfo.destroy(cast(void*)&this.v);
+		    Expression *ea = new AddrExp(0, ex);
+		    ea = new CastExp(0, ea, Type::tvoid->pointerTo());
+		    Expressions *args = new Expressions();
+		    args->push(ea);
+
+		    Expression *et = v->type->getTypeInfo(sc);
+		    et = new DotIdExp(0, et, Id::destroy);
+
+		    ex = new CallExp(0, et, args);
+		}
+		e = Expression::combine(ex, e);	// combine in reverse order
+	    }
+	}
+    }
+
+    /* Build our own "destructor" which executes e
+     */
+    if (e)
+    {	//printf("Building __fieldDtor()\n");
+	DtorDeclaration *dd = new DtorDeclaration(0, 0, Lexer::idPool("__fieldDtor"));
+	dd->fbody = new ExpStatement(0, e);
+	dtors.shift(dd);
+	members->push(dd);
+	dd->semantic(sc);
+    }
+#endif
+
+    switch (dtors.dim)
+    {
+	case 0:
+	    return NULL;
+
+	case 1:
+	    return (FuncDeclaration *)dtors.data[0];
+
+	default:
+	    e = NULL;
+	    for (size_t i = 0; i < dtors.dim; i++)
+	    {	FuncDeclaration *fd = (FuncDeclaration *)dtors.data[i];
+		Expression *ex = new ThisExp(0);
+		ex = new DotVarExp(0, ex, fd);
+		ex = new CallExp(0, ex);
+		e = Expression::combine(ex, e);
+	    }
+	    DtorDeclaration *dd = new DtorDeclaration(0, 0, Lexer::idPool("__aggrDtor"));
+	    dd->fbody = new ExpStatement(0, e);
+	    members->push(dd);
+	    dd->semantic(sc);
+	    return dd;
+    }
+}
+
+
Index: d/dmd/mars.c
===================================================================
--- d/dmd/mars.c	(Revision 199)
+++ d/dmd/mars.c	(Arbeitskopie)
@@ -1,6 +1,6 @@
 
 // Compiler implementation of the D programming language
-// Copyright (c) 1999-2007 by Digital Mars
+// Copyright (c) 1999-2008 by Digital Mars
 // All Rights Reserved
 // written by Walter Bright
 // http://www.digitalmars.com
@@ -64,9 +64,9 @@
     obj_ext = "o";
 #endif
 
-    copyright = "Copyright (c) 1999-2007 by Digital Mars";
+    copyright = "Copyright (c) 1999-2008 by Digital Mars";
     written = "written by Walter Bright";
-    version = "v1.022";
+    version = "v1.028";
     global.structalign = 8;
 
     memset(&params, 0, sizeof(Param));
@@ -254,6 +254,7 @@
     global.params.useInline = 0;
     global.params.obj = 1;
     global.params.Dversion = 2;
+    global.params.quiet = 1;
 
     global.params.linkswitches = new Array();
     global.params.libfiles = new Array();
Index: d/dmd/expression.h
===================================================================
--- d/dmd/expression.h	(Revision 199)
+++ d/dmd/expression.h	(Arbeitskopie)
@@ -113,7 +113,7 @@
     void checkScalar();
     void checkNoBool();
     Expression *checkIntegral();
-    void checkArithmetic();
+    Expression *checkArithmetic();
     void checkDeprecated(Scope *sc, Dsymbol *s);
     virtual Expression *checkToBoolean();
     Expression *checkToPointer();
@@ -347,6 +347,7 @@
     Expression *optimize(int result);
     Expression *interpret(InterState *istate);
     Expression *castTo(Scope *sc, Type *t);
+    elem *toElem(IRState *irs);
 
     int inlineCost(InlineCostState *ics);
     Expression *doInline(InlineDoState *ids);
Index: d/dmd/inline.c
===================================================================
--- d/dmd/inline.c	(Revision 199)
+++ d/dmd/inline.c	(Arbeitskopie)
@@ -546,8 +546,6 @@
 	    ;
 	else
 	{
-	    ExpInitializer *ie;
-	    ExpInitializer *ieto;
 	    VarDeclaration *vto;
 
 	    vto = new VarDeclaration(vd->loc, vd->type, vd->ident, vd->init);
@@ -559,16 +557,18 @@
 	    ids->from.push(vd);
 	    ids->to.push(vto);
 
+	    if (vd->init)
+	    {
 	    if (vd->init->isVoidInitializer())
 	    {
 		vto->init = new VoidInitializer(vd->init->loc);
 	    }
 	    else
 	    {
-		ie = vd->init->isExpInitializer();
+		    ExpInitializer *ie = vd->init->isExpInitializer();
 		assert(ie);
-		ieto = new ExpInitializer(ie->loc, ie->exp->doInline(ids));
-		vto->init = ieto;
+		    vto->init = new ExpInitializer(ie->loc, ie->exp->doInline(ids));
+		}
 	    }
 	    de->declaration = (Dsymbol *) (void *)vto;
 	}
@@ -854,6 +854,7 @@
 Statement *ForeachStatement::inlineScan(InlineScanState *iss)
 {
     aggr = aggr->inlineScan(iss);
+    if (body)
     body = body->inlineScan(iss);
     return this;
 }
@@ -864,6 +865,7 @@
 {
     lwr = lwr->inlineScan(iss);
     upr = upr->inlineScan(iss);
+    if (body)
     body = body->inlineScan(iss);
     return this;
 }
@@ -1288,7 +1290,11 @@
 #endif
 	isSynchronized() ||
 	isImportedSymbol() ||
+#if V2
+	closureVars.dim ||	// no nested references to this frame
+#else
 	nestedFrameRef ||	// no nested references to this frame
+#endif
 	(isVirtual() && !isFinal())
        ))
     {
Index: d/dmd/module.c
===================================================================
--- d/dmd/module.c	(Revision 199)
+++ d/dmd/module.c	(Arbeitskopie)
@@ -85,6 +85,7 @@
     vmoduleinfo = NULL;
     massert = NULL;
     marray = NULL;
+    sictor = NULL;
     sctor = NULL;
     sdtor = NULL;
     stest = NULL;
Index: d/dmd/module.h
===================================================================
--- d/dmd/module.h	(Revision 199)
+++ d/dmd/module.h	(Arbeitskopie)
@@ -139,6 +139,7 @@
     Symbol *cov;		// private uint[] __coverage;
     unsigned *covb;		// bit array of valid code line numbers
 
+    Symbol *sictor;		// module order independent constructor
     Symbol *sctor;		// module constructor
     Symbol *sdtor;		// module destructor
     Symbol *stest;		// module unit test
Index: d/dmd/func.c
===================================================================
--- d/dmd/func.c	(Revision 199)
+++ d/dmd/func.c	(Arbeitskopie)
@@ -1,6 +1,6 @@
 
 // Compiler implementation of the D programming language
-// Copyright (c) 1999-2007 by Digital Mars
+// Copyright (c) 1999-2008 by Digital Mars
 // All Rights Reserved
 // written by Walter Bright
 // http://www.digitalmars.com
@@ -147,6 +147,9 @@
 
     if (isAbstract() && !isVirtual())
 	error("non-virtual functions cannot be abstract");
+
+    if (isAbstract() && isFinal())
+	error("cannot be both final and abstract");
 #if 0
     if (isAbstract() && fbody)
 	error("abstract functions cannot have bodies");
@@ -561,6 +564,8 @@
 
     if (!parent)
     {
+	if (global.errors)
+	    return;
 	printf("FuncDeclaration::semantic3(%s '%s', sc = %p)\n", kind(), toChars(), sc);
 	assert(0);
     }
@@ -612,7 +617,7 @@
 	sc2->sw = NULL;
 	sc2->fes = fes;
 	sc2->linkage = LINKd;
-	sc2->stc &= ~(STCauto | STCscope | STCstatic | STCabstract | STCdeprecated);
+	sc2->stc &= ~(STCauto | STCscope | STCstatic | STCabstract | STCdeprecated | STCfinal);
 	sc2->attributes = NULL;
 	sc2->protection = PROTpublic;
 	sc2->explicitProtection = 0;
@@ -2066,6 +2071,8 @@
     Type *tret;
 
     //printf("CtorDeclaration::semantic()\n");
+    if (type)
+	return;
 
     sc = sc->push();
     sc->stc &= ~STCstatic;		// not a static constructor
@@ -2147,12 +2154,15 @@
 {
 }
 
+DtorDeclaration::DtorDeclaration(Loc loc, Loc endloc, Identifier *id)
+    : FuncDeclaration(loc, endloc, id, STCundefined, NULL)
+{
+}
+
 Dsymbol *DtorDeclaration::syntaxCopy(Dsymbol *s)
 {
-    DtorDeclaration *dd;
-
     assert(!s);
-    dd = new DtorDeclaration(loc, endloc);
+    DtorDeclaration *dd = new DtorDeclaration(loc, endloc, ident);
     return FuncDeclaration::syntaxCopy(dd);
 }
 
Index: d/dmd/aggregate.h
===================================================================
--- d/dmd/aggregate.h	(Revision 199)
+++ d/dmd/aggregate.h	(Arbeitskopie)
@@ -1,6 +1,6 @@
 
 // Compiler implementation of the D programming language
-// Copyright (c) 1999-2006 by Digital Mars
+// Copyright (c) 1999-2008 by Digital Mars
 // All Rights Reserved
 // written by Walter Bright
 // http://www.digitalmars.com
@@ -57,6 +57,8 @@
 				// 2: cannot determine size; fwd referenced
     int isdeprecated;		// !=0 if deprecated
     Scope *scope;		// !=NULL means context to use
+    FuncDeclarations dtors;	// Array of destructors
+    FuncDeclaration *dtor;	// aggregate destructor
 
     // Special member functions
     InvariantDeclaration *inv;		// invariant
@@ -77,6 +79,7 @@
     Type *getType();
     void addField(Scope *sc, VarDeclaration *v);
     int isDeprecated();		// is aggregate deprecated?
+    FuncDeclaration *buildDtor(Scope *sc);
 
     void emitComment(Scope *sc);
     void toDocBuffer(OutBuffer *buf);
@@ -117,6 +120,7 @@
     void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
     char *mangle();
     char *kind();
+    Expression *cloneMembers();
     void toDocBuffer(OutBuffer *buf);
 
     PROT getAccess(Dsymbol *smember);	// determine access to smember
@@ -168,7 +172,6 @@
     ClassDeclaration *baseClass;	// NULL only if this is Object
     CtorDeclaration *ctor;
     CtorDeclaration *defaultCtor;	// default constructor
-    FuncDeclarations dtors;		// Array of destructors
     FuncDeclaration *staticCtor;
     FuncDeclaration *staticDtor;
     Array vtbl;				// Array of FuncDeclaration's making up the vtbl[]
@@ -185,7 +188,8 @@
 					// their own vtbl[]
 
     ClassInfoDeclaration *vclassinfo;	// the ClassInfo object for this ClassDeclaration
-    int com;				// !=0 if this is a COM class
+    int com;				// !=0 if this is a COM class (meaning
+					// it derives from IUnknown)
     int isauto;				// !=0 if this is an auto class
     int isabstract;			// !=0 if abstract class
 
@@ -202,11 +206,17 @@
     virtual int isBaseOf(ClassDeclaration *cd, target_ptrdiff_t *poffset);
 
     Dsymbol *search(Loc, Identifier *ident, int flags);
+#if V2
+    int isFuncHidden(FuncDeclaration *fd);
+#endif
     FuncDeclaration *findFunc(Identifier *ident, TypeFunction *tf);
     void interfaceSemantic(Scope *sc);
     int isNested();
     int isCOMclass();
     virtual int isCOMinterface();
+#if V2
+    virtual int isCPPinterface();
+#endif
     int isAbstract();
     virtual int vtblOffset();
     char *kind();
@@ -233,6 +243,9 @@
 
 struct InterfaceDeclaration : ClassDeclaration
 {
+#if V2
+    int cpp;				// !=0 if this is a C++ interface
+#endif
     InterfaceDeclaration(Loc loc, Identifier *id, BaseClasses *baseclasses);
     Dsymbol *syntaxCopy(Dsymbol *s);
     void semantic(Scope *sc);
@@ -240,6 +253,9 @@
     int isBaseOf(BaseClass *bc, target_ptrdiff_t *poffset);
     char *kind();
     int vtblOffset();
+#if V2
+    int isCPPinterface();
+#endif
     virtual int isCOMinterface();
 
     void toObjFile();			// compile to .obj file
Index: d/dmd/e2ir.c
===================================================================
--- d/dmd/e2ir.c	(Revision 0)
+++ d/dmd/e2ir.c	(Revision 0)
@@ -0,0 +1,4189 @@
+
+// Compiler implementation of the D programming language
+// Copyright (c) 1999-2008 by Digital Mars
+// All Rights Reserved
+// written by Walter Bright
+// http://www.digitalmars.com
+
+#include	<stdio.h>
+#include	<string.h>
+#include	<time.h>
+#include	<complex.h>
+
+#include	"lexer.h"
+#include	"expression.h"
+#include	"mtype.h"
+#include	"dsymbol.h"
+#include	"declaration.h"
+#include	"enum.h"
+#include	"aggregate.h"
+#include	"attrib.h"
+#include	"module.h"
+#include	"init.h"
+#include	"template.h"
+
+#if _WIN32
+#include	"..\tk\mem.h"	// for mem_malloc
+#elif linux
+#include	"../tk/mem.h"	// for mem_malloc
+#endif
+
+#include	"cc.h"
+#include	"el.h"
+#include	"oper.h"
+#include	"global.h"
+#include	"code.h"
+#include	"type.h"
+#include	"dt.h"
+#include	"irstate.h"
+#include	"id.h"
+#include	"type.h"
+#include	"toir.h"
+
+static char __file__[] = __FILE__;	/* for tassert.h		*/
+#include	"tassert.h"
+
+
+elem *addressElem(elem *e, Type *t);
+elem *array_toPtr(Type *t, elem *e);
+elem *bit_assign(enum OPER op, elem *eb, elem *ei, elem *ev, int result);
+elem *bit_read(elem *eb, elem *ei, int result);
+elem *exp2_copytotemp(elem *e);
+
+#define el_setLoc(e,loc)	((e)->Esrcpos.Sfilename = (loc).filename, \
+				 (e)->Esrcpos.Slinnum = (loc).linnum)
+
+/************************************
+ * Call a function.
+ */
+
+elem *callfunc(Loc loc,
+	IRState *irs,
+	int directcall,		// 1: don't do virtual call
+	Type *tret,		// return type
+	elem *ec,		// evaluates to function address
+	Type *ectype,		// original type of ec
+	FuncDeclaration *fd,	// if !=NULL, this is the function being called
+	Type *t,		// TypeDelegate or TypeFunction for this function
+	elem *ehidden,		// if !=NULL, this is the 'hidden' argument
+	Array *arguments)
+{
+    elem *ep;
+    elem *e;
+    elem *ethis = NULL;
+    elem *eside = NULL;
+    int i;
+    tym_t ty;
+    tym_t tyret;
+    enum RET retmethod;
+    int reverse;
+    TypeFunction *tf;
+    int op;
+
+#if 0
+    printf("callfunc(directcall = %d, tret = '%s', ec = %p, fd = %p)\n",
+	directcall, tret->toChars(), ec, fd);
+    printf("ec: "); elem_print(ec);
+    if (fd)
+	printf("fd = '%s'\n", fd->toChars());
+#endif
+
+    t = t->toBasetype();
+    if (t->ty == Tdelegate)
+    {
+	// A delegate consists of:
+	//	{ Object *this; Function *funcptr; }
+	assert(!fd);
+	assert(t->nextOf()->ty == Tfunction);
+	tf = (TypeFunction *)(t->nextOf());
+	ethis = ec;
+	ec = el_same(&ethis);
+	ethis = el_una(OP64_32, TYnptr, ethis);	// get this
+	ec = array_toPtr(t, ec);		// get funcptr
+	ec = el_una(OPind, tf->totym(), ec);
+    }
+    else
+    {	assert(t->ty == Tfunction);
+	tf = (TypeFunction *)(t);
+    }
+    retmethod = tf->retStyle();
+    ty = ec->Ety;
+    if (fd)
+	ty = fd->toSymbol()->Stype->Tty;
+    reverse = tyrevfunc(ty);
+    ep = NULL;
+    if (arguments)
+    {
+	// j=1 if _arguments[] is first argument
+	int j = (tf->linkage == LINKd && tf->varargs == 1);
+
+	for (i = 0; i < arguments->dim ; i++)
+	{   Expression *arg;
+	    elem *ea;
+
+	    arg = (Expression *)arguments->data[i];
+	    //printf("\targ: %s\n", arg->toChars());
+
+	    size_t nparams = Argument::dim(tf->parameters);
+	    if (i - j < nparams && i >= j)
+	    {
+		Argument *p = Argument::getNth(tf->parameters, i - j);
+
+		if (p->storageClass & (STCout | STCref))
+		{
+		    // Convert argument to a pointer,
+		    // use AddrExp::toElem()
+		    Expression *ae = arg->addressOf(NULL);
+		    ea = ae->toElem(irs);
+		    goto L1;
+		}
+	    }
+	    ea = arg->toElem(irs);
+	L1:
+	    if (ea->Ety == TYstruct)
+	    {
+		ea = el_una(OPstrpar, TYstruct, ea);
+		ea->Enumbytes = ea->E1->Enumbytes;
+		assert(ea->Enumbytes);
+	    }
+	    if (reverse)
+		ep = el_param(ep,ea);
+	    else
+		ep = el_param(ea,ep);
+	}
+    }
+
+    if (retmethod == RETstack)
+    {
+	if (!ehidden)
+	{   // Don't have one, so create one
+	    type *t;
+
+	    if (tf->next->toBasetype()->ty == Tstruct)
+		t = tf->next->toCtype();
+	    else
+		t = type_fake(tf->next->totym());
+	    Symbol *stmp = symbol_genauto(t);
+	    ehidden = el_ptr(stmp);
+	}
+	if (ep)
+	{
+#if 0 // BUG: implement
+	    if (reverse && type_mangle(tfunc) == mTYman_cpp)
+		ep = el_param(ehidden,ep);
+	    else
+#endif
+		ep = el_param(ep,ehidden);
+	}
+	else
+	    ep = ehidden;
+	ehidden = NULL;
+    }
+    assert(ehidden == NULL);
+
+    if (fd && fd->isMember2())
+    {
+	InterfaceDeclaration *intd;
+	Symbol *sfunc;
+	AggregateDeclaration *ad;
+
+	ad = fd->isThis();
+	if (ad)
+	{
+	    ethis = ec;
+	    if (ad->handle->ty == Tpointer && tybasic(ec->Ety) != TYnptr)
+	    {
+		ethis = addressElem(ec, ectype);
+	    }
+	}
+	else
+	{
+	    // Evaluate ec for side effects
+	    eside = ec;
+	}
+	sfunc = fd->toSymbol();
+
+	if (!fd->isVirtual() ||
+	    directcall ||		// BUG: fix
+	    fd->isFinal()
+	   )
+	{
+	    // make static call
+	    ec = el_var(sfunc);
+	}
+	else
+	{
+	    // make virtual call
+	    elem *ev;
+	    unsigned vindex;
+
+	    assert(ethis);
+	    ev = el_same(&ethis);
+	    ev = el_una(OPind, TYnptr, ev);
+	    vindex = fd->vtblIndex;
+
+	    // Build *(ev + vindex * 4)
+	    ec = el_bin(OPadd,TYnptr,ev,el_long(TYint, vindex * 4));
+	    ec = el_una(OPind,TYnptr,ec);
+	    ec = el_una(OPind,tybasic(sfunc->Stype->Tty),ec);
+	}
+    }
+    else if (fd && fd->isNested())
+    {
+	assert(!ethis);
+	ethis = getEthis(0, irs, fd);
+
+    }
+
+    ep = el_param(ep, ethis);
+
+    tyret = tret->totym();
+
+    // Look for intrinsic functions
+    if (ec->Eoper == OPvar && (op = intrinsic_op(ec->EV.sp.Vsym->Sident)) != -1)
+    {
+	el_free(ec);
+	if (OTbinary(op))
+	{
+	    ep->Eoper = op;
+	    ep->Ety = tyret;
+	    e = ep;
+	    if (op == OPscale)
+	    {	elem *et;
+
+		et = e->E1;
+		e->E1 = el_una(OPs32_d, TYdouble, e->E2);
+		e->E1 = el_una(OPd_ld, TYldouble, e->E1);
+		e->E2 = et;
+		e->Ety = tyret;
+	    }
+	}
+	else
+	    e = el_una(op,tyret,ep);
+    }
+    else if (ep)
+	e = el_bin(OPcall,tyret,ec,ep);
+    else
+	e = el_una(OPucall,tyret,ec);
+
+    if (retmethod == RETstack)
+    {
+	e->Ety = TYnptr;
+	e = el_una(OPind, tyret, e);
+    }
+    if (tybasic(tyret) == TYstruct)
+    {
+	e->Enumbytes = tret->size();
+    }
+    e = el_combine(eside, e);
+    return e;
+}
+
+/*******************************************
+ * Take address of an elem.
+ */
+
+elem *addressElem(elem *e, Type *t)
+{
+    elem **pe;
+
+    //printf("addressElem()\n");
+
+    for (pe = &e; (*pe)->Eoper == OPcomma; pe = &(*pe)->E2)
+	;
+    if ((*pe)->Eoper != OPvar && (*pe)->Eoper != OPind)
+    {	Symbol *stmp;
+	elem *eeq;
+	elem *e = *pe;
+	type *tx;
+
+	// Convert to ((tmp=e),tmp)
+	TY ty;
+	if (t && ((ty = t->toBasetype()->ty) == Tstruct || ty == Tsarray))
+	    tx = t->toCtype();
+	else
+	    tx = type_fake(e->Ety);
+	stmp = symbol_genauto(tx);
+	eeq = el_bin(OPeq,e->Ety,el_var(stmp),e);
+	if (e->Ety == TYstruct)
+	{
+	    eeq->Eoper = OPstreq;
+	    eeq->Enumbytes = e->Enumbytes;
+	}
+	else if (e->Ety == TYarray)
+	{
+	    eeq->Eoper = OPstreq;
+	    eeq->Ejty = eeq->Ety = TYstruct;
+	    eeq->Enumbytes = t->size();
+	}
+	*pe = el_bin(OPcomma,e->Ety,eeq,el_var(stmp));
+    }
+    e = el_una(OPaddr,TYnptr,e);
+    return e;
+}
+
+/*****************************************
+ * Convert array to a pointer to the data.
+ */
+
+elem *array_toPtr(Type *t, elem *e)
+{
+    //printf("array_toPtr()\n");
+    //elem_print(e);
+    t = t->toBasetype();
+    switch (t->ty)
+    {
+	case Tpointer:
+	    break;
+
+	case Tarray:
+	case Tdelegate:
+	    if (e->Eoper == OPcomma)
+	    {
+		e->Ety = TYnptr;
+		e->E2 = array_toPtr(t, e->E2);
+	    }
+	    else if (e->Eoper == OPpair)
+	    {
+		e->Eoper = OPcomma;
+		e->Ety = TYnptr;
+	    }
+	    else
+	    {
+#if 1
+		e = el_una(OPmsw, TYnptr, e);
+#else
+		e = el_una(OPaddr, TYnptr, e);
+		e = el_bin(OPadd, TYnptr, e, el_long(TYint, 4));
+		e = el_una(OPind, TYnptr, e);
+#endif
+	    }
+	    break;
+
+	case Tsarray:
+	    e = el_una(OPaddr, TYnptr, e);
+	    break;
+
+	default:
+	    t->print();
+	    assert(0);
+    }
+    return e;
+}
+
+/*****************************************
+ * Convert array to a dynamic array.
+ */
+
+elem *array_toDarray(Type *t, elem *e)
+{
+    unsigned dim;
+    elem *ef = NULL;
+    elem *ex;
+
+    //printf("array_toDarray(t = %s)\n", t->toChars());
+    //elem_print(e);
+    t = t->toBasetype();
+    switch (t->ty)
+    {
+	case Tarray:
+	    break;
+
+	case Tsarray:
+	    e = el_una(OPaddr, TYnptr, e);
+	    dim = ((TypeSArray *)t)->dim->toInteger();
+	    e = el_pair(TYullong, el_long(TYint, dim), e);
+	    break;
+
+	default:
+	L1:
+	    switch (e->Eoper)
+	    {
+		case OPconst:
+		{
+		    size_t len = tysize[tybasic(e->Ety)];
+		    elem *es = el_calloc();
+		    es->Eoper = OPstring;
+
+		    // Match MEM_PH_FREE for OPstring in ztc\el.c
+		    es->EV.ss.Vstring = (char *)mem_malloc(len);
+		    memcpy(es->EV.ss.Vstring, &e->EV, len);
+
+		    es->EV.ss.Vstrlen = len;
+		    es->Ety = TYnptr;
+		    e = es;
+		    break;
+		}
+
+		case OPvar:
+		    e = el_una(OPaddr, TYnptr, e);
+		    break;
+
+		case OPcomma:
+		    ef = el_combine(ef, e->E1);
+		    ex = e;
+		    e = e->E2;
+		    ex->E1 = NULL;
+		    ex->E2 = NULL;
+		    el_free(ex);
+		    goto L1;
+
+		case OPind:
+		    ex = e;
+		    e = e->E1;
+		    ex->E1 = NULL;
+		    ex->E2 = NULL;
+		    el_free(ex);
+		    break;
+
+		default:
+		{
+		    // Copy expression to a variable and take the
+		    // address of that variable.
+		    Symbol *stmp;
+		    tym_t ty = tybasic(e->Ety);
+
+		    if (ty == TYstruct)
+		    {
+			if (e->Enumbytes == 4)
+			    ty = TYint;
+			else if (e->Enumbytes == 8)
+			    ty = TYllong;
+		    }
+		    e->Ety = ty;
+		    stmp = symbol_genauto(type_fake(ty));
+		    e = el_bin(OPeq, e->Ety, el_var(stmp), e);
+		    e = el_bin(OPcomma, TYnptr, e, el_una(OPaddr, TYnptr, el_var(stmp)));
+		    break;
+		}
+	    }
+	    dim = 1;
+	    e = el_pair(TYullong, el_long(TYint, dim), e);
+	    break;
+    }
+    return el_combine(ef, e);
+}
+
+/*****************************************
+ * Evaluate elem and convert to dynamic array.
+ */
+
+elem *eval_Darray(IRState *irs, Expression *e)
+{
+    elem *ex;
+
+    ex = e->toElem(irs);
+    return array_toDarray(e->type, ex);
+}
+
+/************************************
+ */
+
+elem *sarray_toDarray(Type *tfrom, Type *tto, elem *e)
+{
+    //printf("sarray_toDarray()\n");
+    //elem_print(e);
+
+    elem *elen;
+    unsigned dim = ((TypeSArray *)tfrom)->dim->toInteger();
+
+    if (tto)
+    {
+	unsigned fsize = tfrom->nextOf()->size();
+	unsigned tsize = tto->nextOf()->size();
+
+	if ((dim * fsize) % tsize != 0)
+	{
+	  Lerr:
+	    error((Loc)0, "cannot cast %s to %s since sizes don't line up", tfrom->toChars(), tto->toChars());
+	}
+	dim = (dim * fsize) / tsize;
+    }
+  L1:
+    elen = el_long(TYint, dim);
+    e = el_una(OPaddr, TYnptr, e);
+    e = el_pair(TYullong, elen, e);
+    return e;
+}
+
+/*******************************************
+ * Set an array pointed to by eptr to evalue:
+ *	eptr[0..edim] = evalue;
+ * Input:
+ *	eptr	where to write the data to
+ *	evalue	value to write
+ *	edim	number of times to write evalue to eptr[]
+ *	tb	type of evalue
+ */
+
+elem *setArray(elem *eptr, elem *edim, Type *tb, elem *evalue)
+{   int r;
+    elem *e;
+    int sz = tb->size();
+
+    if (tb->ty == Tfloat80 || tb->ty == Timaginary80)
+	r = RTLSYM_MEMSET80;
+    else if (tb->ty == Tcomplex80)
+	r = RTLSYM_MEMSET160;
+    else if (tb->ty == Tcomplex64)
+	r = RTLSYM_MEMSET128;
+    else
+    {
+	switch (sz)
+	{
+	    case 1:	 r = RTLSYM_MEMSET8;	break;
+	    case 2:	 r = RTLSYM_MEMSET16;	break;
+	    case 4:	 r = RTLSYM_MEMSET32;	break;
+	    case 8:	 r = RTLSYM_MEMSET64;	break;
+
+	    default:
+		r = RTLSYM_MEMSETN;
+		evalue = el_una(OPaddr, TYnptr, evalue);
+		elem *esz = el_long(TYint, sz);
+		e = el_params(esz, edim, evalue, eptr, NULL);
+		e = el_bin(OPcall,TYnptr,el_var(rtlsym[r]),e);
+		return e;
+	}
+    }
+    if (sz > 1 && sz <= 8 &&
+	evalue->Eoper == OPconst && el_allbits(evalue, 0))
+    {
+	r = RTLSYM_MEMSET8;
+	edim = el_bin(OPmul, TYuint, edim, el_long(TYuint, sz));
+    }
+
+    if (evalue->Ety == TYstruct)
+    {
+	evalue = el_una(OPstrpar, TYstruct, evalue);
+	evalue->Enumbytes = evalue->E1->Enumbytes;
+	assert(evalue->Enumbytes);
+    }
+
+    // Be careful about parameter side effect ordering
+    if (r == RTLSYM_MEMSET8)
+    {
+	e = el_param(edim, evalue);
+	e = el_bin(OPmemset,TYnptr,eptr,e);
+    }
+    else
+    {
+	e = el_params(edim, evalue, eptr, NULL);
+	e = el_bin(OPcall,TYnptr,el_var(rtlsym[r]),e);
+    }
+    return e;
+}
+
+/***************************************
+ */
+
+elem *Expression::toElem(IRState *irs)
+{
+    print();
+    assert(0);
+    return NULL;
+}
+
+/***************************************
+ */
+
+elem *VarExp::toElem(IRState *irs)
+{   Symbol *s;
+    elem *e;
+    tym_t tym;
+    Type *tb = type->toBasetype();
+    FuncDeclaration *fd;
+
+    //printf("VarExp::toElem('%s') %p\n", toChars(), this);
+    //printf("\tparent = '%s'\n", var->parent ? var->parent->toChars() : "null");
+    if (var->needThis())
+    {
+	error("need 'this' to access member %s", toChars());
+	return el_long(TYint, 0);
+    }
+    s = var->toSymbol();
+    fd = NULL;
+    if (var->toParent2())
+	fd = var->toParent2()->isFuncDeclaration();
+
+    int nrvo = 0;
+    if (fd && fd->nrvo_can && fd->nrvo_var == var)
+    {
+	s = fd->shidden;
+	nrvo = 1;
+    }
+
+    if (s->Sclass == SCauto || s->Sclass == SCparameter)
+    {
+	if (fd && fd != irs->getFunc())
+	{   // 'var' is a variable in an enclosing function.
+	    elem *ethis;
+	    int offset;
+
+	    ethis = getEthis(loc, irs, fd);
+	    ethis = el_una(OPaddr, TYnptr, ethis);
+
+	    offset = s->Soffset;
+
+	    /* If fd is a non-static member function of a class or struct,
+	     * then ethis isn't the frame pointer.
+	     * ethis is the 'this' pointer to the class/struct instance.
+	     * We must offset it.
+	     */
+	    if (fd->vthis)
+	    {
+		offset -= fd->vthis->toSymbol()->Soffset;
+	    }
+	    //printf("\tSoffset = x%x, sthis->Soffset = x%x\n", s->Soffset, irs->sthis->Soffset);
+
+	    ethis = el_bin(OPadd, TYnptr, ethis, el_long(TYnptr, offset));
+	    e = el_una(OPind, 0, ethis);
+	    if ((var->isParameter() && tb->ty == Tsarray) || var->isOut() || var->isRef())
+		goto L2;
+	    goto L1;
+	}
+    }
+
+    if (s->Sclass == SCauto && s->Ssymnum == -1)
+    {
+	//printf("\tadding symbol\n");
+	symbol_add(s);
+    }
+    if (var->isImportedSymbol())
+    {
+	e = el_var(var->toImport());
+	e = el_una(OPind,s->ty(),e);
+    }
+    else if ((var->isParameter() && tb->ty == Tsarray) || var->isOut() || var->isRef())
+    {	// Static arrays are really passed as pointers to the array
+	// Out parameters are really references
+	e = el_var(s);
+L2:
+	e->Ety = TYnptr;
+	e = el_una(OPind, s->ty(), e);
+    }
+    else
+	e = el_var(s);
+L1:
+    if (nrvo)
+    {
+	e->Ety = TYnptr;
+	e = el_una(OPind, 0, e);
+    }
+    if (tb->ty == Tfunction)
+    {
+	tym = s->Stype->Tty;
+    }
+    else
+	tym = type->totym();
+    e->Ejty = e->Ety = tym;
+    if (tybasic(tym) == TYstruct)
+    {
+	e->Enumbytes = type->size();
+    }
+    else if (tybasic(tym) == TYarray)
+    {
+	e->Ejty = e->Ety = TYstruct;
+	e->Enumbytes = type->size();
+    }
+    el_setLoc(e,loc);
+    return e;
+}
+
+/*****************************************
+ */
+
+elem *FuncExp::toElem(IRState *irs)
+{
+    elem *e;
+    Symbol *s;
+
+    //printf("FuncExp::toElem() %s\n", toChars());
+    s = fd->toSymbol();
+    e = el_ptr(s);
+    if (fd->isNested())
+    {
+	elem *ethis = getEthis(loc, irs, fd);
+	e = el_pair(TYullong, ethis, e);
+    }
+
+    irs->deferToObj->push(fd);
+    el_setLoc(e,loc);
+    return e;
+}
+
+/**************************************
+ */
+
+elem *Dsymbol_toElem(Dsymbol *s, IRState *irs)
+{
+    elem *e = NULL;
+    Symbol *sp;
+    AttribDeclaration *ad;
+    VarDeclaration *vd;
+    ClassDeclaration *cd;
+    StructDeclaration *sd;
+    FuncDeclaration *fd;
+    TemplateMixin *tm;
+    TupleDeclaration *td;
+    TypedefDeclaration *tyd;
+
+    //printf("Dsymbol_toElem() %s\n", s->toChars());
+    ad = s->isAttribDeclaration();
+    if (ad)
+    {
+	Array *decl = ad->include(NULL, NULL);
+	if (decl && decl->dim)
+	{
+	    for (size_t i = 0; i < decl->dim; i++)
+	    {
+		s = (Dsymbol *)decl->data[i];
+		e = el_combine(e, Dsymbol_toElem(s, irs));
+	    }
+	}
+    }
+    else if ((vd = s->isVarDeclaration()) != NULL)
+    {
+	s = s->toAlias();
+	if (s != vd)
+	    return Dsymbol_toElem(s, irs);
+	if (vd->isStatic() || vd->isConst() || vd->storage_class & STCextern)
+	    vd->toObjFile();
+	else
+	{
+	    sp = s->toSymbol();
+	    symbol_add(sp);
+	    //printf("\tadding symbol '%s'\n", sp->Sident);
+	    if (vd->init)
+	    {
+		ExpInitializer *ie;
+
+		ie = vd->init->isExpInitializer();
+		if (ie)
+		    e = ie->exp->toElem(irs);
+	    }
+	}
+    }
+    else if ((cd = s->isClassDeclaration()) != NULL)
+    {
+	irs->deferToObj->push(s);
+	//sd->toObjFile();
+    }
+    else if ((sd = s->isStructDeclaration()) != NULL)
+    {
+	irs->deferToObj->push(sd);
+	//sd->toObjFile();
+    }
+    else if ((fd = s->isFuncDeclaration()) != NULL)
+    {
+	//printf("function %s\n", fd->toChars());
+	irs->deferToObj->push(fd);
+	//fd->toObjFile();
+    }
+    else if ((tm = s->isTemplateMixin()) != NULL)
+    {
+	//printf("%s\n", tm->toChars());
+	if (tm->members)
+	{
+	    for (size_t i = 0; i < tm->members->dim; i++)
+	    {
+		Dsymbol *sm = (Dsymbol *)tm->members->data[i];
+		e = el_combine(e, Dsymbol_toElem(sm, irs));
+	    }
+	}
+    }
+    else if ((td = s->isTupleDeclaration()) != NULL)
+    {
+	for (size_t i = 0; i < td->objects->dim; i++)
+	{   Object *o = (Object *)td->objects->data[i];
+	    if (o->dyncast() == DYNCAST_EXPRESSION)
+	    {	Expression *eo = (Expression *)o;
+		if (eo->op == TOKdsymbol)
+		{   DsymbolExp *se = (DsymbolExp *)eo;
+		    e = el_combine(e, Dsymbol_toElem(se->s, irs));
+		}
+	    }
+	}
+    }
+    else if ((tyd = s->isTypedefDeclaration()) != NULL)
+    {
+	irs->deferToObj->push(tyd);
+    }
+    return e;
+}
+
+elem *DeclarationExp::toElem(IRState *irs)
+{   elem *e;
+
+    //printf("DeclarationExp::toElem() %s\n", toChars());
+    e = Dsymbol_toElem(declaration, irs);
+    return e;
+}
+
+/***************************************
+ */
+
+elem *ThisExp::toElem(IRState *irs)
+{   elem *ethis;
+    FuncDeclaration *fd;
+
+    //printf("ThisExp::toElem()\n");
+    assert(irs->sthis);
+
+    if (var)
+    {
+	assert(var->parent);
+	fd = var->toParent2()->isFuncDeclaration();
+	assert(fd);
+	ethis = getEthis(loc, irs, fd);
+    }
+    else
+	ethis = el_var(irs->sthis);
+
+    el_setLoc(ethis,loc);
+    return ethis;
+}
+
+/***************************************
+ */
+
+elem *IntegerExp::toElem(IRState *irs)
+{   elem *e;
+
+    e = el_long(type->totym(), value);
+    el_setLoc(e,loc);
+    return e;
+}
+
+/***************************************
+ */
+
+elem *RealExp::toElem(IRState *irs)
+{   union eve c;
+    tym_t ty;
+
+    //printf("RealExp::toElem(%p)\n", this);
+    memset(&c, 0, sizeof(c));
+    ty = type->toBasetype()->totym();
+    switch (ty)
+    {
+	case TYfloat:
+	case TYifloat:
+	    c.Vfloat = value;
+	    break;
+
+	case TYdouble:
+	case TYidouble:
+	    c.Vdouble = value;
+	    break;
+
+	case TYldouble:
+	case TYildouble:
+	    c.Vldouble = value;
+	    break;
+
+	default:
+	    print();
+	    type->print();
+	    type->toBasetype()->print();
+	    printf("ty = %d, tym = %x\n", type->ty, ty);
+	    assert(0);
+    }
+    return el_const(ty, &c);
+}
+
+
+/***************************************
+ */
+
+elem *ComplexExp::toElem(IRState *irs)
+{   union eve c;
+    tym_t ty;
+    real_t re;
+    real_t im;
+
+    re = creall(value);
+    im = cimagl(value);
+
+    memset(&c, 0, sizeof(c));
+    ty = type->totym();
+    switch (ty)
+    {
+	case TYcfloat:
+	    c.Vcfloat.re = (float) re;
+	    c.Vcfloat.im = (float) im;
+	    break;
+
+	case TYcdouble:
+	    c.Vcdouble.re = (double) re;
+	    c.Vcdouble.im = (double) im;
+	    break;
+
+	case TYcldouble:
+	    c.Vcldouble.re = re;
+	    c.Vcldouble.im = im;
+	    break;
+
+	default:
+	    assert(0);
+    }
+    return el_const(ty, &c);
+}
+
+/***************************************
+ */
+
+elem *NullExp::toElem(IRState *irs)
+{
+    return el_long(type->totym(), 0);
+}
+
+/***************************************
+ */
+
+struct StringTab
+{
+    Module *m;		// module we're generating code for
+    Symbol *si;
+    void *string;
+    size_t sz;
+    size_t len;
+};
+
+#define STSIZE 16
+StringTab stringTab[STSIZE];
+size_t stidx;
+
+static Symbol *assertexp_sfilename = NULL;
+static char *assertexp_name = NULL;
+static Module *assertexp_mn = NULL;
+
+void clearStringTab()
+{
+    //printf("clearStringTab()\n");
+    memset(stringTab, 0, sizeof(stringTab));
+    stidx = 0;
+
+    assertexp_sfilename = NULL;
+    assertexp_name = NULL;
+    assertexp_mn = NULL;
+}
+
+elem *StringExp::toElem(IRState *irs)
+{
+    elem *e;
+    Type *tb= type->toBasetype();
+
+
+#if 0
+    printf("StringExp::toElem() %s, type = %s\n", toChars(), type->toChars());
+#endif
+
+    if (tb->ty == Tarray)
+    {
+	Symbol *si;
+	dt_t *dt;
+	StringTab *st;
+
+#if 0
+	printf("irs->m = %p\n", irs->m);
+	printf(" m   = %s\n", irs->m->toChars());
+	printf(" len = %d\n", len);
+	printf(" sz  = %d\n", sz);
+#endif
+	for (size_t i = 0; i < STSIZE; i++)
+	{
+	    st = &stringTab[(stidx + i) % STSIZE];
+	    //if (!st->m) continue;
+	    //printf(" st.m   = %s\n", st->m->toChars());
+	    //printf(" st.len = %d\n", st->len);
+	    //printf(" st.sz  = %d\n", st->sz);
+	    if (st->m == irs->m &&
+		st->si &&
+		st->len == len &&
+		st->sz == sz &&
+		memcmp(st->string, string, sz * len) == 0)
+	    {
+		//printf("use cached value\n");
+		si = st->si;	// use cached value
+		goto L1;
+	    }
+	}
+
+	stidx = (stidx + 1) % STSIZE;
+	st = &stringTab[stidx];
+
+	dt = NULL;
+	toDt(&dt);
+
+	si = symbol_generate(SCstatic,type_fake(TYdarray));
+	si->Sdt = dt;
+	si->Sfl = FLdata;
+#if ELFOBJ // Burton
+	si->Sseg = CDATA;
+#endif
+	outdata(si);
+
+	st->m = irs->m;
+	st->si = si;
+	st->string = string;
+	st->len = len;
+	st->sz = sz;
+    L1:
+	e = el_var(si);
+    }
+    else if (tb->ty == Tsarray)
+    {
+	Symbol *si;
+	dt_t *dt = NULL;
+
+	toDt(&dt);
+	dtnzeros(&dt, sz);		// leave terminating 0
+
+	si = symbol_generate(SCstatic,type_allocn(TYarray, tschar));
+	si->Sdt = dt;
+	si->Sfl = FLdata;
+
+#if ELFOBJ // Burton
+	si->Sseg = CDATA;
+#endif
+	outdata(si);
+
+	e = el_var(si);
+    }
+    else if (tb->ty == Tpointer)
+    {
+	e = el_calloc();
+	e->Eoper = OPstring;
+#if 1
+	// Match MEM_PH_FREE for OPstring in ztc\el.c
+	e->EV.ss.Vstring = (char *)mem_malloc((len + 1) * sz);
+	memcpy(e->EV.ss.Vstring, string, (len + 1) * sz);
+#else
+	e->EV.ss.Vstring = (char *)string;
+#endif
+	e->EV.ss.Vstrlen = (len + 1) * sz;
+	e->Ety = TYnptr;
+    }
+    else
+    {
+	printf("type is %s\n", type->toChars());
+	assert(0);
+    }
+    el_setLoc(e,loc);
+    return e;
+}
+
+elem *NewExp::toElem(IRState *irs)
+{   elem *e;
+    Type *t;
+    Type *ectype;
+
+    //printf("NewExp::toElem() %s\n", toChars());
+    t = type->toBasetype();
+    //printf("\ttype = %s\n", t->toChars());
+    if (t->ty == Tclass)
+    {
+	Symbol *csym;
+
+	t = newtype->toBasetype();
+	assert(t->ty == Tclass);
+	TypeClass *tclass = (TypeClass *)(t);
+	ClassDeclaration *cd = tclass->sym;
+
+	/* Things to do:
+	 * 1) ex: call allocator
+	 * 2) ey: set vthis for nested classes
+	 * 3) ez: call constructor
+	 */
+
+	elem *ex = NULL;
+	elem *ey = NULL;
+	elem *ez = NULL;
+
+	if (allocator || onstack)
+	{   elem *ei;
+	    Symbol *si;
+
+	    if (onstack)
+	    {
+		/* Create an instance of the class on the stack,
+		 * and call it stmp.
+		 * Set ex to be the &stmp.
+		 */
+		Symbol *s = symbol_calloc(tclass->sym->toChars());
+		s->Sclass = SCstruct;
+		s->Sstruct = struct_calloc();
+		s->Sstruct->Sflags |= 0;
+		s->Sstruct->Salignsize = tclass->sym->alignsize;
+		s->Sstruct->Sstructalign = tclass->sym->structalign;
+		s->Sstruct->Sstructsize = tclass->sym->structsize;
+
+		::type *tc = type_alloc(TYstruct);
+		tc->Ttag = (Classsym *)s;                // structure tag name
+		tc->Tcount++;
+		s->Stype = tc;
+
+		Symbol *stmp = symbol_genauto(tc);
+		ex = el_ptr(stmp);
+	    }
+	    else
+	    {
+		ex = el_var(allocator->toSymbol());
+		ex = callfunc(loc, irs, 1, type, ex, allocator->type,
+			allocator, allocator->type, NULL, newargs);
+	    }
+
+	    si = tclass->sym->toInitializer();
+	    ei = el_var(si);
+
+	    if (cd->isNested())
+	    {
+		ey = el_same(&ex);
+		ez = el_copytree(ey);
+	    }
+	    else if (member)
+		ez = el_same(&ex);
+
+	    ex = el_una(OPind, TYstruct, ex);
+	    ex = el_bin(OPstreq, TYnptr, ex, ei);
+	    ex->Enumbytes = cd->size(loc);
+	    ex = el_una(OPaddr, TYnptr, ex);
+	    ectype = tclass;
+	}
+	else
+	{
+	    csym = cd->toSymbol();
+	    ex = el_bin(OPcall,TYnptr,el_var(rtlsym[RTLSYM_NEWCLASS]),el_ptr(csym));
+	    ectype = NULL;
+
+	    if (cd->isNested())
+	    {
+		ey = el_same(&ex);
+		ez = el_copytree(ey);
+	    }
+	    else if (member)
+		ez = el_same(&ex);
+//elem_print(ex);
+//elem_print(ey);
+//elem_print(ez);
+	}
+
+	if (thisexp)
+	{   ClassDeclaration *cdthis = thisexp->type->isClassHandle();
+	    assert(cdthis);
+	    //printf("cd = %s\n", cd->toChars());
+	    //printf("cdthis = %s\n", cdthis->toChars());
+	    assert(cd->isNested());
+	    int offset = 0;
+	    Dsymbol *cdp = cd->toParent2();	// class we're nested in
+	    elem *ethis;
+
+//printf("member = %p\n", member);
+//printf("cdp = %s\n", cdp->toChars());
+//printf("cdthis = %s\n", cdthis->toChars());
+	    if (cdp != cdthis)
+	    {	int i = cdp->isClassDeclaration()->isBaseOf(cdthis, &offset);
+		assert(i);
+	    }
+	    ethis = thisexp->toElem(irs);
+	    if (offset)
+		ethis = el_bin(OPadd, TYnptr, ethis, el_long(TYint, offset));
+
+	    ey = el_bin(OPadd, TYnptr, ey, el_long(TYint, cd->vthis->offset));
+	    ey = el_una(OPind, TYnptr, ey);
+	    ey = el_bin(OPeq, TYnptr, ey, ethis);
+
+//printf("ex: "); elem_print(ex);
+//printf("ey: "); elem_print(ey);
+//printf("ez: "); elem_print(ez);
+	}
+	else if (cd->isNested())
+	{   /* Initialize cd->vthis:
+	     *	*(ey + cd.vthis.offset) = this;
+	     */
+	    elem *ethis;
+	    FuncDeclaration *thisfd = irs->getFunc();
+	    int offset = 0;
+	    Dsymbol *cdp = cd->toParent2();	// class/func we're nested in
+
+	    if (cdp == thisfd)
+	    {	/* Class we're new'ing is a local class in this function:
+		 *	void thisfd() { class cd { } }
+		 */
+		if (irs->sthis)
+		{
+#if V2
+		    if (thisfd->closureVars.dim)
+#else
+		    if (thisfd->nestedFrameRef)
+#endif
+			ethis = el_ptr(irs->sthis);
+		    else
+			ethis = el_var(irs->sthis);
+		}
+		else
+		{
+		    ethis = el_long(TYnptr, 0);
+#if V2
+		    if (thisfd->closureVars.dim)
+#else
+		    if (thisfd->nestedFrameRef)
+#endif
+			ethis->Eoper = OPframeptr;
+		}
+	    }
+	    else if (thisfd->vthis &&
+		  (cdp == thisfd->toParent2() ||
+		   (cdp->isClassDeclaration() &&
+		    cdp->isClassDeclaration()->isBaseOf(thisfd->toParent2()->isClassDeclaration(), &offset)
+		   )
+		  )
+		)
+	    {	/* Class we're new'ing is at the same level as thisfd
+		 */
+		assert(offset == 0);	// BUG: should handle this case
+		ethis = el_var(irs->sthis);
+	    }
+	    else
+	    {
+		ethis = getEthis(loc, irs, cd->toParent2());
+		ethis = el_una(OPaddr, TYnptr, ethis);
+	    }
+
+	    ey = el_bin(OPadd, TYnptr, ey, el_long(TYint, cd->vthis->offset));
+	    ey = el_una(OPind, TYnptr, ey);
+	    ey = el_bin(OPeq, TYnptr, ey, ethis);
+
+	}
+
+	if (member)
+	    // Call constructor
+	    ez = callfunc(loc, irs, 1, type, ez, ectype, member, member->type, NULL, arguments);
+
+	e = el_combine(ex, ey);
+	e = el_combine(e, ez);
+    }
+    else if (t->ty == Tarray)
+    {
+	TypeDArray *tda = (TypeDArray *)(t);
+
+	assert(arguments && arguments->dim >= 1);
+	if (arguments->dim == 1)
+	{   // Single dimension array allocations
+	    Expression *arg = (Expression *)arguments->data[0];	// gives array length
+	    e = arg->toElem(irs);
+	    d_uns64 elemsize = tda->next->size();
+
+	    // call _d_newT(ti, arg)
+	    e = el_param(e, type->getTypeInfo(NULL)->toElem(irs));
+	    int rtl = t->next->isZeroInit() ? RTLSYM_NEWARRAYT : RTLSYM_NEWARRAYIT;
+	    e = el_bin(OPcall,TYdarray,el_var(rtlsym[rtl]),e);
+	}
+	else
+	{   // Multidimensional array allocations
+	    e = el_long(TYint, arguments->dim);
+	    for (size_t i = 0; i < arguments->dim; i++)
+	    {
+		Expression *arg = (Expression *)arguments->data[i];	// gives array length
+		e = el_param(arg->toElem(irs), e);
+		assert(t->ty == Tarray);
+		t = t->nextOf();
+		assert(t);
+	    }
+
+	    e = el_param(e, type->getTypeInfo(NULL)->toElem(irs));
+
+	    int rtl = t->isZeroInit() ? RTLSYM_NEWARRAYMT : RTLSYM_NEWARRAYMIT;
+	    e = el_bin(OPcall,TYdarray,el_var(rtlsym[rtl]),e);
+	}
+    }
+    else if (t->ty == Tpointer)
+    {
+	d_uns64 elemsize = t->next->size();
+	Expression *di = t->next->defaultInit();
+	d_uns64 disize = di->type->size();
+
+	// call _d_newarrayT(ti, 1)
+	e = el_long(TYsize_t, 1);
+	e = el_param(e, type->getTypeInfo(NULL)->toElem(irs));
+
+	int rtl = t->next->isZeroInit() ? RTLSYM_NEWARRAYT : RTLSYM_NEWARRAYIT;
+	e = el_bin(OPcall,TYdarray,el_var(rtlsym[rtl]),e);
+
+	// The new functions return an array, so convert to a pointer
+	// e -> (unsigned)(e >> 32)
+	e = el_bin(OPshr, TYdarray, e, el_long(TYint, 32));
+	e = el_una(OP64_32, t->totym(), e);
+    }
+    else
+    {
+	assert(0);
+    }
+
+    el_setLoc(e,loc);
+    return e;
+}
+
+elem *SymOffExp::toElem(IRState *irs)
+{   Symbol *s;
+    elem *e;
+    Type *tb = var->type->toBasetype();
+    FuncDeclaration *fd = NULL;
+    if (var->toParent2())
+	fd = var->toParent2()->isFuncDeclaration();
+
+    //printf("SymOffExp::toElem(): %s\n", toChars());
+    s = var->toSymbol();
+
+    int nrvo = 0;
+    if (fd && fd->nrvo_can && fd->nrvo_var == var)
+    { 	s = fd->shidden;
+	nrvo = 1;
+    }
+
+    if (s->Sclass == SCauto && s->Ssymnum == -1)
+	symbol_add(s);
+    assert(!var->isImportedSymbol());
+
+    // This code closely parallels that in VarExp::toElem()
+    if (s->Sclass == SCauto || s->Sclass == SCparameter)
+    {
+	if (fd && fd != irs->getFunc())
+	{   // 'var' is a variable in an enclosing function.
+	    elem *ethis;
+	    int soffset;
+
+	    ethis = getEthis(loc, irs, fd);
+	    ethis = el_una(OPaddr, TYnptr, ethis);
+
+	    soffset = s->Soffset;
+
+	    // If fd is a non-static member function, then ethis isn't the
+	    // frame pointer. We must offset it.
+	    if (fd->vthis)
+	    {
+		soffset -= fd->vthis->toSymbol()->Soffset;
+	    }
+
+	    if (!nrvo)
+		soffset += offset;
+	    e = el_bin(OPadd, TYnptr, ethis, el_long(TYnptr, soffset));
+	    if ((var->isParameter() && tb->ty == Tsarray) || var->isOut() || var->isRef())
+		e = el_una(OPind, s->ty(), e);
+	    else if (nrvo)
+	    {	e = el_una(OPind, TYnptr, e);
+		e = el_bin(OPadd, e->Ety, e, el_long(TYint, offset));
+	    }
+	    goto L1;
+	}
+    }
+    if ((var->isParameter() && tb->ty == Tsarray) || var->isOut() || var->isRef())
+    {   // Static arrays are really passed as pointers to the array
+        // Out parameters are really references
+        e = el_var(s);
+        e->Ety = TYnptr;
+	if (offset)
+	    e = el_bin(OPadd, TYnptr, e, el_long(TYint, offset));
+    }
+    else
+    {	e = nrvo ? el_var(s) : el_ptr(s);
+	e = el_bin(OPadd, e->Ety, e, el_long(TYint, offset));
+    }
+
+L1:
+    el_setLoc(e,loc);
+    return e;
+}
+
+//////////////////////////// Unary ///////////////////////////////
+
+/***************************************
+ */
+
+elem *NegExp::toElem(IRState *irs)
+{
+    elem *e = el_una(OPneg, type->totym(), e1->toElem(irs));
+    el_setLoc(e,loc);
+    return e;
+}
+
+/***************************************
+ */
+
+elem *ComExp::toElem(IRState *irs)
+{   elem *e;
+
+    elem *e1 = this->e1->toElem(irs);
+    tym_t ty = type->totym();
+    if (this->e1->type->toBasetype()->ty == Tbool)
+	e = el_bin(OPxor, ty, e1, el_long(ty, 1));
+    else
+	e = el_una(OPcom,ty,e1);
+    el_setLoc(e,loc);
+    return e;
+}
+
+/***************************************
+ */
+
+elem *NotExp::toElem(IRState *irs)
+{
+    elem *e = el_una(OPnot, type->totym(), e1->toElem(irs));
+    el_setLoc(e,loc);
+    return e;
+}
+
+
+/***************************************
+ */
+
+elem *HaltExp::toElem(IRState *irs)
+{   elem *e;
+
+    e = el_calloc();
+    e->Ety = TYvoid;
+    e->Eoper = OPhalt;
+    el_setLoc(e,loc);
+    return e;
+}
+
+/********************************************
+ */
+
+elem *AssertExp::toElem(IRState *irs)
+{   elem *e;
+    elem *ea;
+    Type *t1 = e1->type->toBasetype();
+
+    //printf("AssertExp::toElem() %s\n", toChars());
+    if (global.params.useAssert)
+    {
+	e = e1->toElem(irs);
+
+	InvariantDeclaration *inv = (InvariantDeclaration *)(void *)1;
+
+	// If e1 is a class object, call the class invariant on it
+	if (global.params.useInvariants && t1->ty == Tclass &&
+	    !((TypeClass *)t1)->sym->isInterfaceDeclaration())
+	{
+#if TARGET_LINUX
+	    e = el_bin(OPcall, TYvoid, el_var(rtlsym[RTLSYM__DINVARIANT]), e);
+#else
+	    e = el_bin(OPcall, TYvoid, el_var(rtlsym[RTLSYM_DINVARIANT]), e);
+#endif
+	}
+	// If e1 is a struct object, call the struct invariant on it
+	else if (global.params.useInvariants &&
+	    t1->ty == Tpointer &&
+	    t1->nextOf()->ty == Tstruct &&
+	    (inv = ((TypeStruct *)t1->nextOf())->sym->inv) != NULL)
+	{
+	    e = callfunc(loc, irs, 1, inv->type->nextOf(), e, e1->type, inv, inv->type, NULL, NULL);
+	}
+	else
+	{
+	    // Construct: (e1 || ModuleAssert(line))
+	    Symbol *sassert;
+	    Module *m = irs->blx->module;
+	    char *mname = m->srcfile->toChars();
+
+	    //printf("filename = '%s'\n", loc.filename);
+	    //printf("module = '%s'\n", m->srcfile->toChars());
+
+	    /* If the source file name has changed, probably due
+	     * to a #line directive.
+	     */
+	    if (loc.filename && (msg || strcmp(loc.filename, mname) != 0))
+	    {	elem *efilename;
+
+		/* Cache values.
+		 */
+		//static Symbol *assertexp_sfilename = NULL;
+		//static char *assertexp_name = NULL;
+		//static Module *assertexp_mn = NULL;
+
+		if (!assertexp_sfilename || strcmp(loc.filename, assertexp_name) != 0 || assertexp_mn != m)
+		{
+		    dt_t *dt = NULL;
+		    char *id;
+		    int len;
+
+		    id = loc.filename;
+		    len = strlen(id);
+		    dtdword(&dt, len);
+		    dtabytes(&dt,TYnptr, 0, len + 1, id);
+
+		    assertexp_sfilename = symbol_generate(SCstatic,type_fake(TYdarray));
+		    assertexp_sfilename->Sdt = dt;
+		    assertexp_sfilename->Sfl = FLdata;
+#if ELFOBJ
+		    assertexp_sfilename->Sseg = CDATA;
+#endif
+		    outdata(assertexp_sfilename);
+
+		    assertexp_mn = m;
+		    assertexp_name = id;
+		}
+
+		efilename = el_var(assertexp_sfilename);
+
+		if (msg)
+		{   elem *emsg = msg->toElem(irs);
+		    ea = el_var(rtlsym[RTLSYM_DASSERT_MSG]);
+		    ea = el_bin(OPcall, TYvoid, ea, el_params(el_long(TYint, loc.linnum), efilename, emsg, NULL));
+		}
+		else
+		{
+		    ea = el_var(rtlsym[RTLSYM_DASSERT]);
+		    ea = el_bin(OPcall, TYvoid, ea, el_param(el_long(TYint, loc.linnum), efilename));
+		}
+	    }
+	    else
+	    {
+		sassert = m->toModuleAssert();
+		ea = el_bin(OPcall,TYvoid,el_var(sassert),
+		    el_long(TYint, loc.linnum));
+	    }
+	    e = el_bin(OPoror,TYvoid,e,ea);
+	}
+    }
+    else
+    {	// BUG: should replace assert(0); with a HLT instruction
+	e = el_long(TYint, 0);
+    }
+    el_setLoc(e,loc);
+    return e;
+}
+
+elem *PostExp::toElem(IRState *irs)
+{   elem *e;
+    elem *einc;
+
+    e = e1->toElem(irs);
+    einc = e2->toElem(irs);
+    e = el_bin((op == TOKplusplus) ? OPpostinc : OPpostdec,
+		e->Ety,e,einc);
+    el_setLoc(e,loc);
+    return e;
+}
+
+//////////////////////////// Binary ///////////////////////////////
+
+/********************************************
+ */
+
+elem *BinExp::toElemBin(IRState *irs,int op)
+{
+    //printf("toElemBin() '%s'\n", toChars());
+
+    tym_t tym = type->totym();
+
+    elem *el = e1->toElem(irs);
+    elem *er = e2->toElem(irs);
+    elem *e = el_bin(op,tym,el,er);
+    el_setLoc(e,loc);
+    return e;
+}
+
+/****************************************
+ */
+
+elem *CommaExp::toElem(IRState *irs)
+{
+    assert(e1 && e2);
+    elem *eleft  = e1->toElem(irs);
+    elem *eright = e2->toElem(irs);
+    elem *e = el_combine(eleft, eright);
+    if (e)
+	el_setLoc(e, loc);
+    return e;
+}
+
+
+/***************************************
+ */
+
+elem *CondExp::toElem(IRState *irs)
+{   elem *eleft;
+    elem *eright;
+
+    elem *ec = econd->toElem(irs);
+
+    eleft = e1->toElem(irs);
+    tym_t ty = eleft->Ety;
+    if (global.params.cov && e1->loc.linnum)
+	eleft = el_combine(incUsageElem(irs, e1->loc), eleft);
+
+    eright = e2->toElem(irs);
+    if (global.params.cov && e2->loc.linnum)
+	eright = el_combine(incUsageElem(irs, e2->loc), eright);
+
+    elem *e = el_bin(OPcond, ty, ec, el_bin(OPcolon, ty, eleft, eright));
+    if (tybasic(ty) == TYstruct)
+	e->Enumbytes = e1->type->size();
+    el_setLoc(e, loc);
+    return e;
+}
+
+/***************************************
+ */
+
+elem *AddExp::toElem(IRState *irs)
+{   elem *e;
+    Type *tb1 = e1->type->toBasetype();
+    Type *tb2 = e2->type->toBasetype();
+
+    if ((tb1->ty == Tarray || tb1->ty == Tsarray) &&
+	(tb2->ty == Tarray || tb2->ty == Tsarray)
+       )
+    {
+	error("Array operations not implemented");
+    }
+    else
+	e = toElemBin(irs,OPadd);
+    return e;
+}
+
+/***************************************
+ */
+
+elem *MinExp::toElem(IRState *irs)
+{
+    return toElemBin(irs,OPmin);
+}
+
+/***************************************
+ */
+
+elem *CatExp::toElem(IRState *irs)
+{   elem *e;
+
+#if 0
+    printf("CatExp::toElem()\n");
+    print();
+#endif
+
+    Type *tb1 = e1->type->toBasetype();
+    Type *tb2 = e2->type->toBasetype();
+    Type *tn;
+
+#if 0
+    if ((tb1->ty == Tarray || tb1->ty == Tsarray) &&
+	(tb2->ty == Tarray || tb2->ty == Tsarray)
+       )
+#endif
+
+    Type *ta = tb1->nextOf() ? e1->type : e2->type;
+    tn = tb1->nextOf() ? tb1->nextOf() : tb2->nextOf();
+    {
+	if (e1->op == TOKcat)
+	{
+	    elem *ep;
+	    CatExp *ce = this;
+	    int n = 2;
+
+	    ep = eval_Darray(irs, ce->e2);
+	    do
+	    {
+		n++;
+		ce = (CatExp *)ce->e1;
+		ep = el_param(ep, eval_Darray(irs, ce->e2));
+	    } while (ce->e1->op == TOKcat);
+	    ep = el_param(ep, eval_Darray(irs, ce->e1));
+#if 1
+	    ep = el_params(
+			   ep,
+			   el_long(TYint, n),
+			   ta->getTypeInfo(NULL)->toElem(irs),
+			   NULL);
+	    e = el_bin(OPcall, TYdarray, el_var(rtlsym[RTLSYM_ARRAYCATNT]), ep);
+#else
+	    ep = el_params(
+			   ep,
+			   el_long(TYint, n),
+			   el_long(TYint, tn->size()),
+			   NULL);
+	    e = el_bin(OPcall, TYdarray, el_var(rtlsym[RTLSYM_ARRAYCATN]), ep);
+#endif
+	}
+	else
+	{
+	    elem *e1;
+	    elem *e2;
+	    elem *ep;
+
+	    e1 = eval_Darray(irs, this->e1);
+	    e2 = eval_Darray(irs, this->e2);
+#if 1
+	    ep = el_params(e2, e1, ta->getTypeInfo(NULL)->toElem(irs), NULL);
+	    e = el_bin(OPcall, TYdarray, el_var(rtlsym[RTLSYM_ARRAYCATT]), ep);
+#else
+	    ep = el_params(el_long(TYint, tn->size()), e2, e1, NULL);
+	    e = el_bin(OPcall, TYdarray, el_var(rtlsym[RTLSYM_ARRAYCAT]), ep);
+#endif
+	}
+	el_setLoc(e,loc);
+    }
+#if 0
+    else if ((tb1->ty == Tarray || tb1->ty == Tsarray) &&
+	     e2->type->equals(tb1->next))
+    {
+	error("array cat with element not implemented");
+	e = el_long(TYint, 0);
+    }
+    else
+	assert(0);
+#endif
+    return e;
+}
+
+/***************************************
+ */
+
+elem *MulExp::toElem(IRState *irs)
+{
+    return toElemBin(irs,OPmul);
+}
+
+/************************************
+ */
+
+elem *DivExp::toElem(IRState *irs)
+{
+    return toElemBin(irs,OPdiv);
+}
+
+/***************************************
+ */
+
+elem *ModExp::toElem(IRState *irs)
+{
+    elem *e;
+    elem *e1;
+    elem *e2;
+    tym_t tym;
+
+    tym = type->totym();
+
+    e1 = this->e1->toElem(irs);
+    e2 = this->e2->toElem(irs);
+
+#if 0 // Now inlined
+    if (this->e1->type->isfloating())
+    {	elem *ep;
+
+	switch (this->e1->type->ty)
+	{
+	    case Tfloat32:
+	    case Timaginary32:
+		e1 = el_una(OPf_d, TYdouble, e1);
+		e2 = el_una(OPf_d, TYdouble, e2);
+	    case Tfloat64:
+	    case Timaginary64:
+		e1 = el_una(OPd_ld, TYldouble, e1);
+		e2 = el_una(OPd_ld, TYldouble, e2);
+		break;
+	    case Tfloat80:
+	    case Timaginary80:
+		break;
+	    default:
+		assert(0);
+		break;
+	}
+	ep = el_param(e2,e1);
+	e = el_bin(OPcall,tym,el_var(rtlsym[RTLSYM_MODULO]),ep);
+    }
+    else
+#endif
+	e = el_bin(OPmod,tym,e1,e2);
+    el_setLoc(e,loc);
+    return e;
+}
+
+/***************************************
+ */
+
+elem *CmpExp::toElem(IRState *irs)
+{
+    elem *e;
+    enum OPER eop;
+    Type *t1 = e1->type->toBasetype();
+    Type *t2 = e2->type->toBasetype();
+
+    switch (op)
+    {
+	case TOKlt:	eop = OPlt;	break;
+	case TOKgt:	eop = OPgt;	break;
+	case TOKle:	eop = OPle;	break;
+	case TOKge:	eop = OPge;	break;
+	case TOKequal:	eop = OPeqeq;	break;
+	case TOKnotequal: eop = OPne;	break;
+
+	// NCEG floating point compares
+	case TOKunord:	eop = OPunord;	break;
+	case TOKlg:	eop = OPlg;	break;
+	case TOKleg:	eop = OPleg;	break;
+	case TOKule:	eop = OPule;	break;
+	case TOKul:	eop = OPul;	break;
+	case TOKuge:	eop = OPuge;	break;
+	case TOKug:	eop = OPug;	break;
+	case TOKue:	eop = OPue;	break;
+	default:
+	    dump(0);
+	    assert(0);
+    }
+    if (!t1->isfloating())
+    {
+	// Convert from floating point compare to equivalent
+	// integral compare
+	eop = (enum OPER)rel_integral(eop);
+    }
+    if ((int)eop > 1 && t1->ty == Tclass && t2->ty == Tclass)
+    {
+#if 1
+	assert(0);
+#else
+	elem *ec1;
+	elem *ec2;
+
+	ec1 = e1->toElem(irs);
+	ec2 = e2->toElem(irs);
+	e = el_bin(OPcall,TYint,el_var(rtlsym[RTLSYM_OBJ_CMP]),el_param(ec1, ec2));
+	e = el_bin(eop, TYint, e, el_long(TYint, 0));
+#endif
+    }
+    else if ((int)eop > 1 &&
+	     (t1->ty == Tarray || t1->ty == Tsarray) &&
+	     (t2->ty == Tarray || t2->ty == Tsarray))
+    {
+	elem *ea1;
+	elem *ea2;
+	elem *ep;
+	Type *telement = t1->nextOf()->toBasetype();
+	int rtlfunc;
+
+	ea1 = e1->toElem(irs);
+	ea1 = array_toDarray(t1, ea1);
+	ea2 = e2->toElem(irs);
+	ea2 = array_toDarray(t2, ea2);
+
+	ep = el_params(telement->getInternalTypeInfo(NULL)->toElem(irs), ea2, ea1, NULL);
+	rtlfunc = RTLSYM_ARRAYCMP;
+	e = el_bin(OPcall, TYint, el_var(rtlsym[rtlfunc]), ep);
+	e = el_bin(eop, TYint, e, el_long(TYint, 0));
+	el_setLoc(e,loc);
+    }
+    else
+    {
+	if ((int)eop <= 1)
+	{
+	    /* The result is determinate, create:
+	     *   (e1 , e2) , eop
+	     */
+	    e = toElemBin(irs,OPcomma);
+	    e = el_bin(OPcomma,e->Ety,e,el_long(e->Ety,(int)eop));
+	}
+	else
+	    e = toElemBin(irs,eop);
+    }
+    return e;
+}
+
+elem *EqualExp::toElem(IRState *irs)
+{
+    //printf("EqualExp::toElem() %s\n", toChars());
+
+    elem *e;
+    enum OPER eop;
+    Type *t1 = e1->type->toBasetype();
+    Type *t2 = e2->type->toBasetype();
+
+    switch (op)
+    {
+	case TOKequal:		eop = OPeqeq;	break;
+	case TOKnotequal:	eop = OPne;	break;
+	default:
+	    dump(0);
+	    assert(0);
+    }
+
+    //printf("EqualExp::toElem()\n");
+    if (t1->ty == Tstruct)
+    {	// Do bit compare of struct's
+	elem *es1;
+	elem *es2;
+	elem *ecount;
+
+	es1 = e1->toElem(irs);
+	es2 = e2->toElem(irs);
+#if 1
+	es1 = addressElem(es1, t1);
+	es2 = addressElem(es2, t2);
+#else
+	es1 = el_una(OPaddr, TYnptr, es1);
+	es2 = el_una(OPaddr, TYnptr, es2);
+#endif
+	e = el_param(es1, es2);
+	ecount = el_long(TYint, t1->size());
+	e = el_bin(OPmemcmp, TYint, e, ecount);
+	e = el_bin(eop, TYint, e, el_long(TYint, 0));
+	el_setLoc(e,loc);
+    }
+#if 0
+    else if (t1->ty == Tclass && t2->ty == Tclass)
+    {
+	elem *ec1;
+	elem *ec2;
+
+	ec1 = e1->toElem(irs);
+	ec2 = e2->toElem(irs);
+	e = el_bin(OPcall,TYint,el_var(rtlsym[RTLSYM_OBJ_EQ]),el_param(ec1, ec2));
+    }
+#endif
+    else if ((t1->ty == Tarray || t1->ty == Tsarray) &&
+	     (t2->ty == Tarray || t2->ty == Tsarray))
+    {
+	elem *ea1;
+	elem *ea2;
+	elem *ep;
+	Type *telement = t1->nextOf()->toBasetype();
+	int rtlfunc;
+
+	ea1 = e1->toElem(irs);
+	ea1 = array_toDarray(t1, ea1);
+	ea2 = e2->toElem(irs);
+	ea2 = array_toDarray(t2, ea2);
+
+	ep = el_params(telement->getInternalTypeInfo(NULL)->toElem(irs), ea2, ea1, NULL);
+	rtlfunc = RTLSYM_ARRAYEQ;
+	e = el_bin(OPcall, TYint, el_var(rtlsym[rtlfunc]), ep);
+	if (op == TOKnotequal)
+	    e = el_bin(OPxor, TYint, e, el_long(TYint, 1));
+	el_setLoc(e,loc);
+    }
+    else
+	e = toElemBin(irs, eop);
+    return e;
+}
+
+elem *IdentityExp::toElem(IRState *irs)
+{
+    elem *e;
+    enum OPER eop;
+    Type *t1 = e1->type->toBasetype();
+    Type *t2 = e2->type->toBasetype();
+
+    switch (op)
+    {
+	case TOKidentity:	eop = OPeqeq;	break;
+	case TOKnotidentity:	eop = OPne;	break;
+	default:
+	    dump(0);
+	    assert(0);
+    }
+
+    //printf("IdentityExp::toElem() %s\n", toChars());
+
+    if (t1->ty == Tstruct)
+    {	// Do bit compare of struct's
+	elem *es1;
+	elem *es2;
+	elem *ecount;
+
+	es1 = e1->toElem(irs);
+	es1 = addressElem(es1, e1->type);
+	//es1 = el_una(OPaddr, TYnptr, es1);
+	es2 = e2->toElem(irs);
+	es2 = addressElem(es2, e2->type);
+	//es2 = el_una(OPaddr, TYnptr, es2);
+	e = el_param(es1, es2);
+	ecount = el_long(TYint, t1->size());
+	e = el_bin(OPmemcmp, TYint, e, ecount);
+	e = el_bin(eop, TYint, e, el_long(TYint, 0));
+	el_setLoc(e,loc);
+    }
+    else if ((t1->ty == Tarray || t1->ty == Tsarray) &&
+	     (t2->ty == Tarray || t2->ty == Tsarray))
+    {
+	elem *ea1;
+	elem *ea2;
+
+	ea1 = e1->toElem(irs);
+	ea1 = array_toDarray(t1, ea1);
+	ea2 = e2->toElem(irs);
+	ea2 = array_toDarray(t2, ea2);
+
+	e = el_bin(eop, type->totym(), ea1, ea2);
+	el_setLoc(e,loc);
+    }
+    else
+	e = toElemBin(irs, eop);
+
+    return e;
+}
+
+
+/***************************************
+ */
+
+elem *InExp::toElem(IRState *irs)
+{   elem *e;
+    elem *key = e1->toElem(irs);
+    elem *aa = e2->toElem(irs);
+    elem *ep;
+    elem *keyti;
+    TypeAArray *taa = (TypeAArray *)e2->type->toBasetype();
+    
+
+    // set to:
+    //	aaIn(aa, keyti, key);
+
+    if (key->Ety == TYstruct)
+    {
+	key = el_una(OPstrpar, TYstruct, key);
+	key->Enumbytes = key->E1->Enumbytes;
+	assert(key->Enumbytes);
+    }
+
+    Symbol *s = taa->aaGetSymbol("In", 0);
+    keyti = taa->key->getInternalTypeInfo(NULL)->toElem(irs);
+    ep = el_params(key, keyti, aa, NULL);
+    e = el_bin(OPcall, type->totym(), el_var(s), ep);
+
+    el_setLoc(e,loc);
+    return e;
+}
+
+/***************************************
+ */
+
+elem *RemoveExp::toElem(IRState *irs)
+{   elem *e;
+    Type *tb = e1->type->toBasetype();
+    assert(tb->ty == Taarray);
+    TypeAArray *taa = (TypeAArray *)tb;
+    elem *ea = e1->toElem(irs);
+    elem *ekey = e2->toElem(irs);
+    elem *ep;
+    elem *keyti;
+
+    if (ekey->Ety == TYstruct)
+    {
+	ekey = el_una(OPstrpar, TYstruct, ekey);
+	ekey->Enumbytes = ekey->E1->Enumbytes;
+	assert(ekey->Enumbytes);
+    }
+
+    Symbol *s = taa->aaGetSymbol("Del", 0);
+    keyti = taa->key->getInternalTypeInfo(NULL)->toElem(irs);
+    ep = el_params(ekey, keyti, ea, NULL);
+    e = el_bin(OPcall, TYnptr, el_var(s), ep);
+
+    el_setLoc(e,loc);
+    return e;
+}
+
+/***************************************
+ */
+
+elem *AssignExp::toElem(IRState *irs)
+{   elem *e;
+    IndexExp *ae;
+    int r;
+    Type *t1b;
+
+    //printf("AssignExp::toElem('%s')\n", toChars());
+    t1b = e1->type->toBasetype();
+
+    // Look for array.length = n
+    if (e1->op == TOKarraylength)
+    {
+	// Generate:
+	//	_d_arraysetlength(e2, sizeelem, &ale->e1);
+
+	ArrayLengthExp *ale = (ArrayLengthExp *)e1;
+	elem *p1;
+	elem *p2;
+	elem *p3;
+	elem *ep;
+	Type *t1;
+
+	p1 = e2->toElem(irs);
+	p3 = ale->e1->toElem(irs);
+	p3 = addressElem(p3, NULL);
+	t1 = ale->e1->type->toBasetype();
+
+#if 1
+	// call _d_arraysetlengthT(ti, e2, &ale->e1);
+	p2 = t1->getTypeInfo(NULL)->toElem(irs);
+	ep = el_params(p3, p1, p2, NULL);	// c function
+	r = t1->nextOf()->isZeroInit() ? RTLSYM_ARRAYSETLENGTHT : RTLSYM_ARRAYSETLENGTHIT;
+#else
+	if (t1->next->isZeroInit())
+	{   p2 = t1->getTypeInfo(NULL)->toElem(irs);
+	    ep = el_params(p3, p1, p2, NULL);	// c function
+	    r = RTLSYM_ARRAYSETLENGTHT;
+	}
+	else
+	{
+	    p2 = el_long(TYint, t1->next->size());
+	    ep = el_params(p3, p2, p1, NULL);	// c function
+	    Expression *init = t1->next->defaultInit();
+	    ep = el_param(el_long(TYint, init->type->size()), ep);
+	    elem *ei = init->toElem(irs);
+	    ep = el_param(ei, ep);
+	    r = RTLSYM_ARRAYSETLENGTH3;
+	}
+#endif
+
+	e = el_bin(OPcall, type->totym(), el_var(rtlsym[r]), ep);
+	el_setLoc(e, loc);
+	return e;
+    }
+
+    // Look for array[]=n
+    if (e1->op == TOKslice)
+    {
+	SliceExp *are = (SliceExp *)(e1);
+	Type *t1 = t1b;
+	Type *t2 = e2->type->toBasetype();
+
+	// which we do if the 'next' types match
+	if (ismemset)
+	{   // Do a memset for array[]=n
+//printf("Lpair %s\n", toChars());
+	    SliceExp *are = (SliceExp *)e1;
+	    elem *elwr;
+	    elem *eupr;
+	    elem *n1;
+	    elem *evalue;
+	    elem *enbytes;
+	    elem *elength;
+	    elem *einit;
+	    integer_t value;
+	    Type *ta = are->e1->type->toBasetype();
+	    Type *tb = ta->nextOf()->toBasetype();
+	    int sz = tb->size();
+	    tym_t tym = type->totym();
+
+	    n1 = are->e1->toElem(irs);
+	    elwr = are->lwr ? are->lwr->toElem(irs) : NULL;
+	    eupr = are->upr ? are->upr->toElem(irs) : NULL;
+
+	    elem *n1x = n1;
+
+	    // Look for array[]=n
+	    if (ta->ty == Tsarray)
+	    {
+		TypeSArray *ts;
+
+		ts = (TypeSArray *) ta;
+		n1 = array_toPtr(ta, n1);
+		enbytes = ts->dim->toElem(irs);
+		n1x = n1;
+		n1 = el_same(&n1x);
+		einit = resolveLengthVar(are->lengthVar, &n1, ta);
+	    }
+	    else if (ta->ty == Tarray)
+	    {
+		n1 = el_same(&n1x);
+		einit = resolveLengthVar(are->lengthVar, &n1, ta);
+		enbytes = el_copytree(n1);
+		n1 = array_toPtr(ta, n1);
+		enbytes = el_una(OP64_32, TYint, enbytes);
+	    }
+	    else if (ta->ty == Tpointer)
+	    {
+		n1 = el_same(&n1x);
+		enbytes = el_long(TYint, -1);	// largest possible index
+		einit = NULL;
+	    }
+
+	    // Enforce order of evaluation of n1[elwr..eupr] as n1,elwr,eupr
+	    elem *elwrx = elwr;
+	    if (elwr) elwr = el_same(&elwrx);
+	    elem *euprx = eupr;
+	    if (eupr) eupr = el_same(&euprx);
+
+#if 0
+	    printf("sz = %d\n", sz);
+	    printf("n1x\n");
+	    elem_print(n1x);
+	    printf("einit\n");
+	    elem_print(einit);
+	    printf("elwrx\n");
+	    elem_print(elwrx);
+	    printf("euprx\n");
+	    elem_print(euprx);
+	    printf("n1\n");
+	    elem_print(n1);
+	    printf("elwr\n");
+	    elem_print(elwr);
+	    printf("eupr\n");
+	    elem_print(eupr);
+	    printf("enbytes\n");
+	    elem_print(enbytes);
+#endif
+	    einit = el_combine(n1x, einit);
+	    einit = el_combine(einit, elwrx);
+	    einit = el_combine(einit, euprx);
+
+	    evalue = this->e2->toElem(irs);
+
+#if 0
+	    printf("n1\n");
+	    elem_print(n1);
+	    printf("enbytes\n");
+	    elem_print(enbytes);
+#endif
+
+	    if (global.params.useArrayBounds && eupr && ta->ty != Tpointer)
+	    {
+		elem *c1;
+		elem *c2;
+		elem *ea;
+		elem *eb;
+		elem *enbytesx;
+
+		assert(elwr);
+		enbytesx = enbytes;
+		enbytes = el_same(&enbytesx);
+		c1 = el_bin(OPle, TYint, el_copytree(eupr), enbytesx);
+		c2 = el_bin(OPle, TYint, el_copytree(elwr), el_copytree(eupr));
+		c1 = el_bin(OPandand, TYint, c1, c2);
+
+		// Construct: (c1 || ModuleArray(line))
+		Symbol *sassert;
+
+		sassert = irs->blx->module->toModuleArray();
+		ea = el_bin(OPcall,TYvoid,el_var(sassert), el_long(TYint, loc.linnum));
+		eb = el_bin(OPoror,TYvoid,c1,ea);
+		einit = el_combine(einit, eb);
+	    }
+
+	    if (elwr)
+	    {   elem *elwr2;
+
+		el_free(enbytes);
+		elwr2 = el_copytree(elwr);
+		elwr2 = el_bin(OPmul, TYint, elwr2, el_long(TYint, sz));
+		n1 = el_bin(OPadd, TYnptr, n1, elwr2);
+		enbytes = el_bin(OPmin, TYint, eupr, elwr);
+		elength = el_copytree(enbytes);
+	    }
+	    else
+		elength = el_copytree(enbytes);
+	    e = setArray(n1, enbytes, tb, evalue);
+	Lpair:
+	    e = el_pair(TYullong, elength, e);
+	Lret2:
+	    e = el_combine(einit, e);
+	    //elem_print(e);
+	    goto Lret;
+	}
+	else
+	{
+	    /* It's array1[]=array2[]
+	     * which is a memcpy
+	     */
+	    elem *eto;
+	    elem *efrom;
+	    elem *esize;
+	    elem *ep;
+
+	    eto = e1->toElem(irs);
+	    efrom = e2->toElem(irs);
+
+	    unsigned size;
+
+	    size = t1->nextOf()->size();
+	    esize = el_long(TYint, size);
+
+	    if (e2->type->ty == Tpointer || !global.params.useArrayBounds)
+	    {	elem *epto;
+		elem *epfr;
+		elem *elen;
+		elem *ex;
+
+		ex = el_same(&eto);
+
+		// Determine if elen is a constant
+		if (eto->Eoper == OPpair &&
+		    eto->E1->Eoper == OPconst)
+		{
+		    elen = el_copytree(eto->E1);
+		}
+		else
+		{
+		    // It's not a constant, so pull it from the dynamic array
+		    elen = el_una(OP64_32, TYint, el_copytree(ex));
+		}
+
+		esize = el_bin(OPmul, TYint, elen, esize);
+		epto = array_toPtr(e1->type, ex);
+		epfr = array_toPtr(e2->type, efrom);
+		e = el_bin(OPmemcpy, TYnptr, epto, el_param(epfr, esize));
+		e = el_pair(eto->Ety, el_copytree(elen), e);
+		e = el_combine(eto, e);
+	    }
+	    else
+	    {
+		// Generate:
+		//	_d_arraycopy(eto, efrom, esize)
+
+		// If eto is a static array, need to convert it to
+		// a dynamic array.
+		//if (are->e1->type->ty == Tsarray)
+		//    eto = sarray_toDarray(are->e1->type, eto);
+
+		ep = el_params(eto, efrom, esize, NULL);
+		e = el_bin(OPcall, type->totym(), el_var(rtlsym[RTLSYM_ARRAYCOPY]), ep);
+	    }
+	    el_setLoc(e, loc);
+	    return e;
+	}
+    }
+
+    if (e1->op == TOKindex)
+    {
+	elem *eb;
+	elem *ei;
+	elem *ev;
+	TY ty;
+	Type *ta;
+
+	ae = (IndexExp *)(e1);
+	ta = ae->e1->type->toBasetype();
+	ty = ta->ty;
+    }
+#if 1
+    /* This will work if we can distinguish an assignment from
+     * an initialization of the lvalue. It'll work if the latter.
+     * If the former, because of aliasing of the return value with
+     * function arguments, it'll fail.
+     */
+    if (op == TOKconstruct && e2->op == TOKcall)
+    {	CallExp *ce = (CallExp *)e2;
+
+	TypeFunction *tf = (TypeFunction *)ce->e1->type->toBasetype();
+	if (tf->ty == Tfunction && tf->retStyle() == RETstack)
+	{
+	    elem *ehidden = e1->toElem(irs);
+	    ehidden = el_una(OPaddr, TYnptr, ehidden);
+	    assert(!irs->ehidden);
+	    irs->ehidden = ehidden;
+	    e = e2->toElem(irs);
+	    goto Lret;
+	}
+    }
+#endif
+    if (t1b->ty == Tstruct)
+    {
+	if (e2->op == TOKint64)
+	{   /* Implement:
+	     *	(struct = 0)
+	     * with:
+	     *	memset(&struct, 0, struct.sizeof)
+	     */
+	    elem *el = e1->toElem(irs);
+	    elem *enbytes = el_long(TYint, e1->type->size());
+	    elem *evalue = el_long(TYint, 0);
+
+	    el = el_una(OPaddr, TYnptr, el);
+	    e = el_param(enbytes, evalue);
+	    e = el_bin(OPmemset,TYnptr,el,e);
+	    el_setLoc(e, loc);
+	    //e = el_una(OPind, TYstruct, e);
+	}
+	else
+	{
+	    elem *e1;
+	    elem *e2;
+	    tym_t tym;
+
+	    //printf("toElemBin() '%s'\n", toChars());
+
+	    tym = type->totym();
+
+	    e1 = this->e1->toElem(irs);
+	    elem *ex = e1;
+	    if (e1->Eoper == OPind)
+		ex = e1->E1;
+	    if (this->e2->op == TOKstructliteral &&
+		ex->Eoper == OPvar && ex->EV.sp.Voffset == 0)
+	    {	StructLiteralExp *se = (StructLiteralExp *)this->e2;
+
+		Symbol *symSave = se->sym;
+		size_t soffsetSave = se->soffset;
+		int fillHolesSave = se->fillHoles;
+
+		se->sym = ex->EV.sp.Vsym;
+		se->soffset = 0;
+		se->fillHoles = (op == TOKconstruct) ? 1 : 0;
+
+		el_free(e1);
+		e = this->e2->toElem(irs);
+
+		se->sym = symSave;
+		se->soffset = soffsetSave;
+		se->fillHoles = fillHolesSave;
+	    }
+	    else
+	    {
+		e2 = this->e2->toElem(irs);
+		e = el_bin(OPstreq,tym,e1,e2);
+		e->Enumbytes = this->e1->type->size();
+	    }
+	    goto Lret;
+	}
+    }
+    else
+	e = toElemBin(irs,OPeq);
+    return e;
+
+  Lret:
+    el_setLoc(e,loc);
+    return e;
+}
+
+/***************************************
+ */
+
+elem *AddAssignExp::toElem(IRState *irs)
+{
+    //printf("AddAssignExp::toElem() %s\n", toChars());
+    elem *e;
+    Type *tb1 = e1->type->toBasetype();
+    Type *tb2 = e2->type->toBasetype();
+
+    if ((tb1->ty == Tarray || tb1->ty == Tsarray) &&
+	(tb2->ty == Tarray || tb2->ty == Tsarray)
+       )
+    {
+	error("Array operations not implemented");
+    }
+    else
+	e = toElemBin(irs,OPaddass);
+    return e;
+}
+
+
+/***************************************
+ */
+
+elem *MinAssignExp::toElem(IRState *irs)
+{
+    return toElemBin(irs,OPminass);
+}
+
+/***************************************
+ */
+
+elem *CatAssignExp::toElem(IRState *irs)
+{
+    //printf("CatAssignExp::toElem('%s')\n", toChars());
+    elem *e;
+    Type *tb1 = e1->type->toBasetype();
+    Type *tb2 = e2->type->toBasetype();
+
+    if (tb1->ty == Tarray || tb2->ty == Tsarray)
+    {   elem *e1;
+	elem *e2;
+	elem *ep;
+
+	e1 = this->e1->toElem(irs);
+	e1 = el_una(OPaddr, TYnptr, e1);
+
+	e2 = this->e2->toElem(irs);
+	if (e2->Ety == TYstruct)
+	{
+	    e2 = el_una(OPstrpar, TYstruct, e2);
+	    e2->Enumbytes = e2->E1->Enumbytes;
+	    assert(e2->Enumbytes);
+	}
+
+	Type *tb1n = tb1->nextOf()->toBasetype();
+	if ((tb2->ty == Tarray || tb2->ty == Tsarray) &&
+	    tb1n->equals(tb2->nextOf()->toBasetype()))
+	{   // Append array
+#if 1
+	    ep = el_params(e2, e1, this->e1->type->getTypeInfo(NULL)->toElem(irs), NULL);
+	    e = el_bin(OPcall, TYdarray, el_var(rtlsym[RTLSYM_ARRAYAPPENDT]), ep);
+#else
+	    ep = el_params(el_long(TYint, tb1n->size()), e2, e1, NULL);
+	    e = el_bin(OPcall, TYdarray, el_var(rtlsym[RTLSYM_ARRAYAPPEND]), ep);
+#endif
+	}
+	else
+	{   // Append element
+#if 1
+	    ep = el_params(e2, e1, this->e1->type->getTypeInfo(NULL)->toElem(irs), NULL);
+	    e = el_bin(OPcall, TYdarray, el_var(rtlsym[RTLSYM_ARRAYAPPENDCT]), ep);
+#else
+	    ep = el_params(e2, el_long(TYint, tb1n->size()), e1, NULL);
+	    e = el_bin(OPcall, TYdarray, el_var(rtlsym[RTLSYM_ARRAYAPPENDC]), ep);
+#endif
+	}
+	el_setLoc(e,loc);
+    }
+    else
+	assert(0);
+    return e;
+}
+
+
+/***************************************
+ */
+
+elem *DivAssignExp::toElem(IRState *irs)
+{
+    return toElemBin(irs,OPdivass);
+}
+
+
+/***************************************
+ */
+
+elem *ModAssignExp::toElem(IRState *irs)
+{
+    return toElemBin(irs,OPmodass);
+}
+
+
+/***************************************
+ */
+
+elem *MulAssignExp::toElem(IRState *irs)
+{
+    return toElemBin(irs,OPmulass);
+}
+
+
+/***************************************
+ */
+
+elem *ShlAssignExp::toElem(IRState *irs)
+{   elem *e;
+
+    e = toElemBin(irs,OPshlass);
+    return e;
+}
+
+
+/***************************************
+ */
+
+elem *ShrAssignExp::toElem(IRState *irs)
+{
+    return toElemBin(irs,OPshrass);
+}
+
+
+/***************************************
+ */
+
+elem *UshrAssignExp::toElem(IRState *irs)
+{
+    elem *eleft  = e1->toElem(irs);
+    eleft->Ety = touns(eleft->Ety);
+    elem *eright = e2->toElem(irs);
+    elem *e = el_bin(OPshrass, type->totym(), eleft, eright);
+    el_setLoc(e, loc);
+    return e;
+}
+
+
+/***************************************
+ */
+
+elem *AndAssignExp::toElem(IRState *irs)
+{
+    return toElemBin(irs,OPandass);
+}
+
+
+/***************************************
+ */
+
+elem *OrAssignExp::toElem(IRState *irs)
+{
+    return toElemBin(irs,OPorass);
+}
+
+
+/***************************************
+ */
+
+elem *XorAssignExp::toElem(IRState *irs)
+{
+    return toElemBin(irs,OPxorass);
+}
+
+
+/***************************************
+ */
+
+elem *AndAndExp::toElem(IRState *irs)
+{
+    elem *e = toElemBin(irs,OPandand);
+    if (global.params.cov && e2->loc.linnum)
+	e->E2 = el_combine(incUsageElem(irs, e2->loc), e->E2);
+    return e;
+}
+
+
+/***************************************
+ */
+
+elem *OrOrExp::toElem(IRState *irs)
+{
+    elem *e = toElemBin(irs,OPoror);
+    if (global.params.cov && e2->loc.linnum)
+	e->E2 = el_combine(incUsageElem(irs, e2->loc), e->E2);
+    return e;
+}
+
+
+/***************************************
+ */
+
+elem *XorExp::toElem(IRState *irs)
+{
+    return toElemBin(irs,OPxor);
+}
+
+
+/***************************************
+ */
+
+elem *AndExp::toElem(IRState *irs)
+{
+    return toElemBin(irs,OPand);
+}
+
+
+/***************************************
+ */
+
+elem *OrExp::toElem(IRState *irs)
+{
+    return toElemBin(irs,OPor);
+}
+
+
+/***************************************
+ */
+
+elem *ShlExp::toElem(IRState *irs)
+{
+    return toElemBin(irs, OPshl);
+}
+
+
+/***************************************
+ */
+
+elem *ShrExp::toElem(IRState *irs)
+{
+    return toElemBin(irs,OPshr);
+}
+
+
+/***************************************
+ */
+
+elem *UshrExp::toElem(IRState *irs)
+{
+    elem *eleft  = e1->toElem(irs);
+    eleft->Ety = touns(eleft->Ety);
+    elem *eright = e2->toElem(irs);
+    elem *e = el_bin(OPshr, type->totym(), eleft, eright);
+    el_setLoc(e, loc);
+    return e;
+}
+
+elem *TypeDotIdExp::toElem(IRState *irs)
+{
+    print();
+    assert(0);
+    return NULL;
+}
+
+elem *TypeExp::toElem(IRState *irs)
+{
+#ifdef DEBUG
+    printf("TypeExp::toElem()\n");
+#endif
+    error("type %s is not an expression", toChars());
+    return el_long(TYint, 0);
+}
+
+elem *ScopeExp::toElem(IRState *irs)
+{
+    error("%s is not an expression", sds->toChars());
+    return el_long(TYint, 0);
+}
+
+elem *DotVarExp::toElem(IRState *irs)
+{
+    // *(&e + offset)
+
+    //printf("DotVarExp::toElem('%s')\n", toChars());
+
+    VarDeclaration *v = var->isVarDeclaration();
+    if (!v)
+    {
+	error("%s is not a field", var->toChars());
+    }
+
+    elem *e = e1->toElem(irs);
+    Type *tb1 = e1->type->toBasetype();
+    if (tb1->ty != Tclass && tb1->ty != Tpointer)
+	e = el_una(OPaddr, TYnptr, e);
+    e = el_bin(OPadd, TYnptr, e, el_long(TYint, v ? v->offset : 0));
+    e = el_una(OPind, type->totym(), e);
+    if (tybasic(e->Ety) == TYstruct)
+    {
+	e->Enumbytes = type->size();
+    }
+    el_setLoc(e,loc);
+    return e;
+}
+
+elem *DelegateExp::toElem(IRState *irs)
+{
+    elem *e;
+    elem *ethis;
+    elem *ep;
+    Symbol *sfunc;
+    int directcall = 0;
+
+    //printf("DelegateExp::toElem() '%s'\n", toChars());
+    sfunc = func->toSymbol();
+    if (func->isNested())
+    {
+	ep = el_ptr(sfunc);
+	ethis = getEthis(loc, irs, func);
+    }
+    else
+    {
+	ethis = e1->toElem(irs);
+	if (e1->type->ty != Tclass && e1->type->ty != Tpointer)
+	    ethis = el_una(OPaddr, TYnptr, ethis);
+
+	if (e1->op == TOKsuper)
+	    directcall = 1;
+
+	if (!func->isThis())
+	    error("delegates are only for non-static functions");
+
+	if (!func->isVirtual() ||
+	    directcall ||
+	    func->isFinal())
+	{
+	    ep = el_ptr(sfunc);
+	}
+	else
+	{
+	    // Get pointer to function out of virtual table
+	    unsigned vindex;
+
+	    assert(ethis);
+	    ep = el_same(&ethis);
+	    ep = el_una(OPind, TYnptr, ep);
+	    vindex = func->vtblIndex;
+
+	    // Build *(ep + vindex * 4)
+	    ep = el_bin(OPadd,TYnptr,ep,el_long(TYint, vindex * 4));
+	    ep = el_una(OPind,TYnptr,ep);
+	}
+
+//	if (func->tintro)
+//	    func->error(loc, "cannot form delegate due to covariant return type");
+    }
+    if (ethis->Eoper == OPcomma)
+    {
+	ethis->E2 = el_pair(TYullong, ethis->E2, ep);
+	ethis->Ety = TYullong;
+	e = ethis;
+    }
+    else
+	e = el_pair(TYullong, ethis, ep);
+    el_setLoc(e,loc);
+    return e;
+}
+
+elem *DotTypeExp::toElem(IRState *irs)
+{
+    // Just a pass-thru to e1
+    elem *e;
+
+    //printf("DotTypeExp::toElem() %s\n", toChars());
+    e = e1->toElem(irs);
+    el_setLoc(e,loc);
+    return e;
+}
+
+elem *CallExp::toElem(IRState *irs)
+{
+    //printf("CallExp::toElem('%s')\n", toChars());
+    assert(e1->type);
+    elem *ec;
+    int directcall;
+    FuncDeclaration *fd;
+    Type *t1 = e1->type->toBasetype();
+    Type *ectype = t1;
+
+    elem *ehidden = irs->ehidden;
+    irs->ehidden = NULL;
+
+    directcall = 0;
+    fd = NULL;
+    if (e1->op == TOKdotvar && t1->ty != Tdelegate)
+    {	DotVarExp *dve = (DotVarExp *)e1;
+
+	fd = dve->var->isFuncDeclaration();
+	Expression *ex = dve->e1;
+	while (1)
+	{
+	    switch (ex->op)
+	    {
+		case TOKsuper:		// super.member() calls directly
+		case TOKdottype:	// type.member() calls directly
+		    directcall = 1;
+		    break;
+
+		case TOKcast:
+		    ex = ((CastExp *)ex)->e1;
+		    continue;
+
+		default:
+		    //ex->dump(0);
+		    break;
+	    }
+	    break;
+	}
+	ec = dve->e1->toElem(irs);
+	ectype = dve->e1->type->toBasetype();
+    }
+    else if (e1->op == TOKvar)
+    {
+	fd = ((VarExp *)e1)->var->isFuncDeclaration();
+
+	if (fd && fd->ident == Id::alloca &&
+	    !fd->fbody && fd->linkage == LINKc &&
+	    arguments && arguments->dim == 1)
+	{   Expression *arg = (Expression *)arguments->data[0];
+	    arg = arg->optimize(WANTvalue);
+	    if (arg->isConst() && arg->type->isintegral())
+	    {	integer_t sz = arg->toInteger();
+		if (sz > 0 && sz < 0x40000)
+		{
+		    // It's an alloca(sz) of a fixed amount.
+		    // Replace with an array allocated on the stack
+		    // of the same size: char[sz] tmp;
+
+		    Symbol *stmp;
+		    ::type *t;
+
+		    assert(!ehidden);
+		    t = type_allocn(TYarray, tschar);
+		    t->Tdim = sz;
+		    stmp = symbol_genauto(t);
+		    ec = el_ptr(stmp);
+		    el_setLoc(ec,loc);
+		    return ec;
+		}
+	    }
+	}
+
+	ec = e1->toElem(irs);
+    }
+    else
+    {
+	ec = e1->toElem(irs);
+    }
+    ec = callfunc(loc, irs, directcall, type, ec, ectype, fd, t1, ehidden, arguments);
+    el_setLoc(ec,loc);
+    return ec;
+}
+
+elem *AddrExp::toElem(IRState *irs)
+{   elem *e;
+    elem **pe;
+
+    //printf("AddrExp::toElem('%s')\n", toChars());
+
+    e = e1->toElem(irs);
+    e = addressElem(e, e1->type);
+L2:
+    e->Ety = type->totym();
+    el_setLoc(e,loc);
+    return e;
+}
+
+elem *PtrExp::toElem(IRState *irs)
+{   elem *e;
+
+    //printf("PtrExp::toElem() %s\n", toChars());
+    e = e1->toElem(irs);
+    e = el_una(OPind,type->totym(),e);
+    if (tybasic(e->Ety) == TYstruct)
+    {
+	e->Enumbytes = type->size();
+    }
+    el_setLoc(e,loc);
+    return e;
+}
+
+elem *BoolExp::toElem(IRState *irs)
+{   elem *e1;
+
+    e1 = this->e1->toElem(irs);
+    return el_una(OPbool,type->totym(),e1);
+}
+
+elem *DeleteExp::toElem(IRState *irs)
+{   elem *e;
+    int rtl;
+    Type *tb;
+
+    //printf("DeleteExp::toElem()\n");
+    if (e1->op == TOKindex)
+    {
+	IndexExp *ae = (IndexExp *)(e1);
+	tb = ae->e1->type->toBasetype();
+	if (tb->ty == Taarray)
+	{
+	    TypeAArray *taa = (TypeAArray *)tb;
+	    elem *ea = ae->e1->toElem(irs);
+	    elem *ekey = ae->e2->toElem(irs);
+	    elem *ep;
+	    elem *keyti;
+
+	    if (ekey->Ety == TYstruct)
+	    {
+		ekey = el_una(OPstrpar, TYstruct, ekey);
+		ekey->Enumbytes = ekey->E1->Enumbytes;
+		assert(ekey->Enumbytes);
+	    }
+
+	    Symbol *s = taa->aaGetSymbol("Del", 0);
+	    keyti = taa->key->getInternalTypeInfo(NULL)->toElem(irs);
+	    ep = el_params(ekey, keyti, ea, NULL);
+	    e = el_bin(OPcall, TYnptr, el_var(s), ep);
+	    goto Lret;
+	}
+    }
+    //e1->type->print();
+    e = e1->toElem(irs);
+    rtl = RTLSYM_DELCLASS;
+    tb = e1->type->toBasetype();
+    switch (tb->ty)
+    {
+	case Tarray:
+	    e = addressElem(e, e1->type);
+	    rtl = RTLSYM_DELARRAY;
+	    break;
+
+	case Tclass:
+	    if (e1->op == TOKvar)
+	    {	VarExp *ve = (VarExp *)e1;
+		if (ve->var->isVarDeclaration() &&
+		    ve->var->isVarDeclaration()->onstack)
+		{
+		    rtl = RTLSYM_CALLFINALIZER;
+		    if (tb->isClassHandle()->isInterfaceDeclaration())
+			rtl = RTLSYM_CALLINTERFACEFINALIZER;
+		    break;
+		}
+	    }
+	    e = addressElem(e, e1->type);
+	    rtl = RTLSYM_DELCLASS;
+	    if (tb->isClassHandle()->isInterfaceDeclaration())
+		rtl = RTLSYM_DELINTERFACE;
+	    break;
+
+	case Tpointer:
+	    e = addressElem(e, e1->type);
+	    rtl = RTLSYM_DELMEMORY;
+	    break;
+
+	default:
+	    assert(0);
+	    break;
+    }
+    e = el_bin(OPcall, TYvoid, el_var(rtlsym[rtl]), e);
+
+  Lret:
+    el_setLoc(e,loc);
+    return e;
+}
+
+elem *CastExp::toElem(IRState *irs)
+{   elem *e;
+    TY fty;
+    TY tty;
+    tym_t ftym;
+    tym_t ttym;
+    enum OPER eop;
+    Type *t;
+    Type *tfrom;
+
+#if 0
+    printf("CastExp::toElem()\n");
+    print();
+    printf("\tfrom: %s\n", e1->type->toChars());
+    printf("\tto  : %s\n", to->toChars());
+#endif
+
+    e = e1->toElem(irs);
+    tfrom = e1->type->toBasetype();
+    t = to->toBasetype();		// skip over typedef's
+    if (t->equals(tfrom))
+	goto Lret;
+
+    fty = tfrom->ty;
+    //printf("fty = %d\n", fty);
+    tty = t->ty;
+
+    if (tty == Tpointer && fty == Tarray
+#if 0
+	&& (t->next->ty == Tvoid || t->next->equals(e1->type->next))
+#endif
+       )
+    {
+	if (e->Eoper == OPvar)
+	{
+	    // e1 -> *(&e1 + 4)
+	    e = el_una(OPaddr, TYnptr, e);
+	    e = el_bin(OPadd, TYnptr, e, el_long(TYint, 4));
+	    e = el_una(OPind,t->totym(),e);
+	}
+	else
+	{
+	    // e1 -> (unsigned)(e1 >> 32)
+	    e = el_bin(OPshr, TYullong, e, el_long(TYint, 32));
+	    e = el_una(OP64_32, t->totym(), e);
+	}
+	goto Lret;
+    }
+
+    if (tty == Tpointer && fty == Tsarray
+#if 0
+	&& (t->next->ty == Tvoid || t->next->equals(e1->type->next))
+#endif
+	)
+    {
+	// e1 -> &e1
+	e = el_una(OPaddr, TYnptr, e);
+	goto Lret;
+    }
+
+    // Convert from static array to dynamic array
+    if (tty == Tarray && fty == Tsarray)
+    {
+	e = sarray_toDarray(tfrom, t, e);
+	goto Lret;
+    }
+
+    // Convert from dynamic array to dynamic array
+    if (tty == Tarray && fty == Tarray)
+    {
+	unsigned fsize = tfrom->nextOf()->size();
+	unsigned tsize = t->nextOf()->size();
+
+	if (fsize != tsize)
+	{
+	    elem *ep;
+
+	    ep = el_params(e, el_long(TYint, fsize), el_long(TYint, tsize), NULL);
+	    e = el_bin(OPcall, type->totym(), el_var(rtlsym[RTLSYM_ARRAYCAST]), ep);
+	}
+	goto Lret;
+    }
+
+    // Casting from base class to derived class requires a runtime check
+    if (fty == Tclass && tty == Tclass)
+    {
+	// Casting from derived class to base class is a no-op
+	ClassDeclaration *cdfrom;
+	ClassDeclaration *cdto;
+	int offset;
+	int rtl = RTLSYM_DYNAMIC_CAST;
+
+	cdfrom = e1->type->isClassHandle();
+	cdto   = t->isClassHandle();
+	if (cdfrom->isInterfaceDeclaration())
+	{
+	    rtl = RTLSYM_INTERFACE_CAST;
+	    if (cdfrom->isCOMinterface())
+	    {
+		if (cdto->isCOMinterface())
+		{
+		    /* Casting from a com interface to a com interface
+		     * is always a 'paint' operation
+		     */
+		    goto Lret;			// no-op
+		}
+
+		/* Casting from a COM interface to a class
+		 * always results in null because there is no runtime
+		 * information available to do it.
+		 *
+		 * Casting from a COM interface to a non-COM interface
+		 * always results in null because there's no way one
+		 * can be derived from the other.
+		 */
+		e = el_bin(OPcomma, TYnptr, e, el_long(TYnptr, 0));
+		goto Lret;
+	    }
+	}
+	if (cdto->isBaseOf(cdfrom, &offset) && offset != OFFSET_RUNTIME)
+	{
+	    /* The offset from cdfrom=>cdto is known at compile time.
+	     */
+	
+	    //printf("offset = %d\n", offset);
+	    if (offset)
+	    {	/* Rewrite cast as (e ? e + offset : null)
+		 */
+		elem *etmp;
+		elem *ex;
+
+		if (e1->op == TOKthis)
+		{   // Assume 'this' is never null, so skip null check
+		    e = el_bin(OPadd, TYnptr, e, el_long(TYint, offset));
+		}
+		else
+		{
+		    etmp = el_same(&e);
+		    ex = el_bin(OPadd, TYnptr, etmp, el_long(TYint, offset));
+		    ex = el_bin(OPcolon, TYnptr, ex, el_long(TYnptr, 0));
+		    e = el_bin(OPcond, TYnptr, e, ex);
+		}
+	    }
+	    goto Lret;			// no-op
+	}
+
+	/* The offset from cdfrom=>cdto can only be determined at runtime.
+	 */
+	elem *ep;
+
+	ep = el_param(el_ptr(cdto->toSymbol()), e);
+	e = el_bin(OPcall, TYnptr, el_var(rtlsym[rtl]), ep);
+	goto Lret;
+    }
+
+    ftym = e->Ety;
+    ttym = t->totym();
+    if (ftym == ttym)
+	goto Lret;
+
+    switch (tty)
+    {
+	case Tpointer:
+	    if (fty == Tdelegate)
+		goto Lpaint;
+	    tty = Tuns32;
+	    break;
+
+	case Tchar:	tty = Tuns8;	break;
+	case Twchar:	tty = Tuns16;	break;
+	case Tdchar:	tty = Tuns32;	break;
+	case Tvoid:	goto Lpaint;
+
+	case Tbool:
+	{
+	    // Construct e?true:false
+	    elem *eq;
+
+	    e = el_una(OPbool, ttym, e);
+	    goto Lret;
+	}
+    }
+
+    switch (fty)
+    {
+	case Tpointer:	fty = Tuns32;	break;
+	case Tchar:	fty = Tuns8;	break;
+	case Twchar:	fty = Tuns16;	break;
+	case Tdchar:	fty = Tuns32;	break;
+    }
+
+    #define X(fty, tty) ((fty) * TMAX + (tty))
+Lagain:
+    switch (X(fty,tty))
+    {
+#if 0
+	case X(Tbit,Tint8):
+	case X(Tbit,Tuns8):
+				goto Lpaint;
+	case X(Tbit,Tint16):
+	case X(Tbit,Tuns16):
+	case X(Tbit,Tint32):
+	case X(Tbit,Tuns32):	eop = OPu8_16;	goto Leop;
+	case X(Tbit,Tint64):
+	case X(Tbit,Tuns64):
+	case X(Tbit,Tfloat32):
+	case X(Tbit,Tfloat64):
+	case X(Tbit,Tfloat80):
+	case X(Tbit,Tcomplex32):
+	case X(Tbit,Tcomplex64):
+	case X(Tbit,Tcomplex80):
+				e = el_una(OPu8_16, TYuint, e);
+				fty = Tuns32;
+				goto Lagain;
+	case X(Tbit,Timaginary32):
+	case X(Tbit,Timaginary64):
+	case X(Tbit,Timaginary80): goto Lzero;
+#endif
+	/* ============================= */
+
+	case X(Tbool,Tint8):
+	case X(Tbool,Tuns8):
+				goto Lpaint;
+	case X(Tbool,Tint16):
+	case X(Tbool,Tuns16):
+	case X(Tbool,Tint32):
+	case X(Tbool,Tuns32):	eop = OPu8_16;	goto Leop;
+	case X(Tbool,Tint64):
+	case X(Tbool,Tuns64):
+	case X(Tbool,Tfloat32):
+	case X(Tbool,Tfloat64):
+	case X(Tbool,Tfloat80):
+	case X(Tbool,Tcomplex32):
+	case X(Tbool,Tcomplex64):
+	case X(Tbool,Tcomplex80):
+				e = el_una(OPu8_16, TYuint, e);
+				fty = Tuns32;
+				goto Lagain;
+	case X(Tbool,Timaginary32):
+	case X(Tbool,Timaginary64):
+	case X(Tbool,Timaginary80): goto Lzero;
+
+	/* ============================= */
+
+	case X(Tint8,Tuns8):	goto Lpaint;
+	case X(Tint8,Tint16):
+	case X(Tint8,Tuns16):
+	case X(Tint8,Tint32):
+	case X(Tint8,Tuns32):	eop = OPs8_16;	goto Leop;
+	case X(Tint8,Tint64):
+	case X(Tint8,Tuns64):
+	case X(Tint8,Tfloat32):
+	case X(Tint8,Tfloat64):
+	case X(Tint8,Tfloat80):
+	case X(Tint8,Tcomplex32):
+	case X(Tint8,Tcomplex64):
+	case X(Tint8,Tcomplex80):
+				e = el_una(OPs8_16, TYint, e);
+				fty = Tint32;
+				goto Lagain;
+	case X(Tint8,Timaginary32):
+	case X(Tint8,Timaginary64):
+	case X(Tint8,Timaginary80): goto Lzero;
+
+	/* ============================= */
+
+	case X(Tuns8,Tint8):	goto Lpaint;
+	case X(Tuns8,Tint16):
+	case X(Tuns8,Tuns16):
+	case X(Tuns8,Tint32):
+	case X(Tuns8,Tuns32):	eop = OPu8_16;	goto Leop;
+	case X(Tuns8,Tint64):
+	case X(Tuns8,Tuns64):
+	case X(Tuns8,Tfloat32):
+	case X(Tuns8,Tfloat64):
+	case X(Tuns8,Tfloat80):
+	case X(Tuns8,Tcomplex32):
+	case X(Tuns8,Tcomplex64):
+	case X(Tuns8,Tcomplex80):
+				e = el_una(OPu8_16, TYuint, e);
+				fty = Tuns32;
+				goto Lagain;
+	case X(Tuns8,Timaginary32):
+	case X(Tuns8,Timaginary64):
+	case X(Tuns8,Timaginary80): goto Lzero;
+
+	/* ============================= */
+
+	case X(Tint16,Tint8):
+	case X(Tint16,Tuns8):	eop = OP16_8;	goto Leop;
+	case X(Tint16,Tuns16):	goto Lpaint;
+	case X(Tint16,Tint32):
+	case X(Tint16,Tuns32):	eop = OPs16_32;	goto Leop;
+	case X(Tint16,Tint64):
+	case X(Tint16,Tuns64):	e = el_una(OPs16_32, TYint, e);
+				fty = Tint32;
+				goto Lagain;
+	case X(Tint16,Tfloat32):
+	case X(Tint16,Tfloat64):
+	case X(Tint16,Tfloat80):
+	case X(Tint16,Tcomplex32):
+	case X(Tint16,Tcomplex64):
+	case X(Tint16,Tcomplex80):
+				e = el_una(OPs16_d, TYdouble, e);
+				fty = Tfloat64;
+				goto Lagain;
+	case X(Tint16,Timaginary32):
+	case X(Tint16,Timaginary64):
+	case X(Tint16,Timaginary80): goto Lzero;
+
+	/* ============================= */
+
+	case X(Tuns16,Tint8):
+	case X(Tuns16,Tuns8):	eop = OP16_8;	goto Leop;
+	case X(Tuns16,Tint16):	goto Lpaint;
+	case X(Tuns16,Tint32):
+	case X(Tuns16,Tuns32):	eop = OPu16_32;	goto Leop;
+	case X(Tuns16,Tint64):
+	case X(Tuns16,Tuns64):
+	case X(Tuns16,Tfloat64):
+	case X(Tuns16,Tfloat32):
+	case X(Tuns16,Tfloat80):
+	case X(Tuns16,Tcomplex32):
+	case X(Tuns16,Tcomplex64):
+	case X(Tuns16,Tcomplex80):
+				e = el_una(OPu16_32, TYuint, e);
+				fty = Tuns32;
+				goto Lagain;
+	case X(Tuns16,Timaginary32):
+	case X(Tuns16,Timaginary64):
+	case X(Tuns16,Timaginary80): goto Lzero;
+
+	/* ============================= */
+
+	case X(Tint32,Tint8):
+	case X(Tint32,Tuns8):	e = el_una(OP32_16, TYshort, e);
+				fty = Tint16;
+				goto Lagain;
+	case X(Tint32,Tint16):
+	case X(Tint32,Tuns16):	eop = OP32_16;	goto Leop;
+	case X(Tint32,Tuns32):	goto Lpaint;
+	case X(Tint32,Tint64):
+	case X(Tint32,Tuns64):	eop = OPs32_64;	goto Leop;
+	case X(Tint32,Tfloat32):
+	case X(Tint32,Tfloat64):
+	case X(Tint32,Tfloat80):
+	case X(Tint32,Tcomplex32):
+	case X(Tint32,Tcomplex64):
+	case X(Tint32,Tcomplex80):
+				e = el_una(OPs32_d, TYdouble, e);
+				fty = Tfloat64;
+				goto Lagain;
+	case X(Tint32,Timaginary32):
+	case X(Tint32,Timaginary64):
+	case X(Tint32,Timaginary80): goto Lzero;
+
+	/* ============================= */
+
+	case X(Tuns32,Tint8):
+	case X(Tuns32,Tuns8):	e = el_una(OP32_16, TYshort, e);
+				fty = Tuns16;
+				goto Lagain;
+	case X(Tuns32,Tint16):
+	case X(Tuns32,Tuns16):	eop = OP32_16;	goto Leop;
+	case X(Tuns32,Tint32):	goto Lpaint;
+	case X(Tuns32,Tint64):
+	case X(Tuns32,Tuns64):	eop = OPu32_64;	goto Leop;
+	case X(Tuns32,Tfloat32):
+	case X(Tuns32,Tfloat64):
+	case X(Tuns32,Tfloat80):
+	case X(Tuns32,Tcomplex32):
+	case X(Tuns32,Tcomplex64):
+	case X(Tuns32,Tcomplex80):
+				e = el_una(OPu32_d, TYdouble, e);
+				fty = Tfloat64;
+				goto Lagain;
+	case X(Tuns32,Timaginary32):
+	case X(Tuns32,Timaginary64):
+	case X(Tuns32,Timaginary80): goto Lzero;
+
+	/* ============================= */
+
+	case X(Tint64,Tint8):
+	case X(Tint64,Tuns8):
+	case X(Tint64,Tint16):
+	case X(Tint64,Tuns16):	e = el_una(OP64_32, TYint, e);
+				fty = Tint32;
+				goto Lagain;
+	case X(Tint64,Tint32):
+	case X(Tint64,Tuns32):	eop = OP64_32; goto Leop;
+	case X(Tint64,Tuns64):	goto Lpaint;
+	case X(Tint64,Tfloat32):
+	case X(Tint64,Tfloat64):
+	case X(Tint64,Tfloat80):
+	case X(Tint64,Tcomplex32):
+	case X(Tint64,Tcomplex64):
+	case X(Tint64,Tcomplex80):
+				e = el_una(OPs64_d, TYdouble, e);
+				fty = Tfloat64;
+				goto Lagain;
+	case X(Tint64,Timaginary32):
+	case X(Tint64,Timaginary64):
+	case X(Tint64,Timaginary80): goto Lzero;
+
+	/* ============================= */
+
+	case X(Tuns64,Tint8):
+	case X(Tuns64,Tuns8):
+	case X(Tuns64,Tint16):
+	case X(Tuns64,Tuns16):	e = el_una(OP64_32, TYint, e);
+				fty = Tint32;
+				goto Lagain;
+	case X(Tuns64,Tint32):
+	case X(Tuns64,Tuns32):	eop = OP64_32;	goto Leop;
+	case X(Tuns64,Tint64):	goto Lpaint;
+	case X(Tuns64,Tfloat32):
+	case X(Tuns64,Tfloat64):
+	case X(Tuns64,Tfloat80):
+	case X(Tuns64,Tcomplex32):
+	case X(Tuns64,Tcomplex64):
+	case X(Tuns64,Tcomplex80):
+				 e = el_una(OPu64_d, TYdouble, e);
+				 fty = Tfloat64;
+				 goto Lagain;
+	case X(Tuns64,Timaginary32):
+	case X(Tuns64,Timaginary64):
+	case X(Tuns64,Timaginary80): goto Lzero;
+
+	/* ============================= */
+
+	case X(Tfloat32,Tint8):
+	case X(Tfloat32,Tuns8):
+	case X(Tfloat32,Tint16):
+	case X(Tfloat32,Tuns16):
+	case X(Tfloat32,Tint32):
+	case X(Tfloat32,Tuns32):
+	case X(Tfloat32,Tint64):
+	case X(Tfloat32,Tuns64):
+	case X(Tfloat32,Tfloat80): e = el_una(OPf_d, TYdouble, e);
+				   fty = Tfloat64;
+				   goto Lagain;
+	case X(Tfloat32,Tfloat64): eop = OPf_d;	goto Leop;
+	case X(Tfloat32,Timaginary32): goto Lzero;
+	case X(Tfloat32,Timaginary64): goto Lzero;
+	case X(Tfloat32,Timaginary80): goto Lzero;
+	case X(Tfloat32,Tcomplex32):
+	case X(Tfloat32,Tcomplex64):
+	case X(Tfloat32,Tcomplex80):
+	    e = el_bin(OPadd,TYcfloat,el_long(TYifloat,0),e);
+	    fty = Tcomplex32;
+	    goto Lagain;
+
+	/* ============================= */
+
+	case X(Tfloat64,Tint8):
+	case X(Tfloat64,Tuns8):    e = el_una(OPd_s16, TYshort, e);
+				   fty = Tint16;
+				   goto Lagain;
+	case X(Tfloat64,Tint16):   eop = OPd_s16; goto Leop;
+	case X(Tfloat64,Tuns16):   eop = OPd_u16; goto Leop;
+	case X(Tfloat64,Tint32):   eop = OPd_s32; goto Leop;
+	case X(Tfloat64,Tuns32):   eop = OPd_u32; goto Leop;
+	case X(Tfloat64,Tint64):   eop = OPd_s64; goto Leop;
+	case X(Tfloat64,Tuns64):   eop = OPd_u64; goto Leop;
+	case X(Tfloat64,Tfloat32): eop = OPd_f;   goto Leop;
+	case X(Tfloat64,Tfloat80): eop = OPd_ld;  goto Leop;
+	case X(Tfloat64,Timaginary32):	goto Lzero;
+	case X(Tfloat64,Timaginary64):	goto Lzero;
+	case X(Tfloat64,Timaginary80):	goto Lzero;
+	case X(Tfloat64,Tcomplex32):
+	case X(Tfloat64,Tcomplex64):
+	case X(Tfloat64,Tcomplex80):
+	    e = el_bin(OPadd,TYcfloat,el_long(TYidouble,0),e);
+	    fty = Tcomplex64;
+	    goto Lagain;
+
+	/* ============================= */
+
+	case X(Tfloat80,Tint8):
+	case X(Tfloat80,Tuns8):
+	case X(Tfloat80,Tint16):
+	case X(Tfloat80,Tuns16):
+	case X(Tfloat80,Tint32):
+	case X(Tfloat80,Tuns32):
+	case X(Tfloat80,Tint64):
+	case X(Tfloat80,Tuns64):
+	case X(Tfloat80,Tfloat32): e = el_una(OPld_d, TYdouble, e);
+				   fty = Tfloat64;
+				   goto Lagain;
+	case X(Tfloat80,Tfloat64): eop = OPld_d; goto Leop;
+	case X(Tfloat80,Timaginary32): goto Lzero;
+	case X(Tfloat80,Timaginary64): goto Lzero;
+	case X(Tfloat80,Timaginary80): goto Lzero;
+	case X(Tfloat80,Tcomplex32):
+	case X(Tfloat80,Tcomplex64):
+	case X(Tfloat80,Tcomplex80):
+	    e = el_bin(OPadd,TYcldouble,e,el_long(TYildouble,0));
+	    fty = Tcomplex80;
+	    goto Lagain;
+
+	/* ============================= */
+
+	case X(Timaginary32,Tint8):
+	case X(Timaginary32,Tuns8):
+	case X(Timaginary32,Tint16):
+	case X(Timaginary32,Tuns16):
+	case X(Timaginary32,Tint32):
+	case X(Timaginary32,Tuns32):
+	case X(Timaginary32,Tint64):
+	case X(Timaginary32,Tuns64):
+	case X(Timaginary32,Tfloat32):
+	case X(Timaginary32,Tfloat64):
+	case X(Timaginary32,Tfloat80):	goto Lzero;
+	case X(Timaginary32,Timaginary64): eop = OPf_d;	goto Leop;
+	case X(Timaginary32,Timaginary80):
+				   e = el_una(OPf_d, TYidouble, e);
+				   fty = Timaginary64;
+				   goto Lagain;
+	case X(Timaginary32,Tcomplex32):
+	case X(Timaginary32,Tcomplex64):
+	case X(Timaginary32,Tcomplex80):
+	    e = el_bin(OPadd,TYcfloat,el_long(TYfloat,0),e);
+	    fty = Tcomplex32;
+	    goto Lagain;
+
+	/* ============================= */
+
+	case X(Timaginary64,Tint8):
+	case X(Timaginary64,Tuns8):
+	case X(Timaginary64,Tint16):
+	case X(Timaginary64,Tuns16):
+	case X(Timaginary64,Tint32):
+	case X(Timaginary64,Tuns32):
+	case X(Timaginary64,Tint64):
+	case X(Timaginary64,Tuns64):
+	case X(Timaginary64,Tfloat32):
+	case X(Timaginary64,Tfloat64):
+	case X(Timaginary64,Tfloat80):	goto Lzero;
+	case X(Timaginary64,Timaginary32): eop = OPd_f;   goto Leop;
+	case X(Timaginary64,Timaginary80): eop = OPd_ld;  goto Leop;
+	case X(Timaginary64,Tcomplex32):
+	case X(Timaginary64,Tcomplex64):
+	case X(Timaginary64,Tcomplex80):
+	    e = el_bin(OPadd,TYcdouble,el_long(TYdouble,0),e);
+	    fty = Tcomplex64;
+	    goto Lagain;
+
+	/* ============================= */
+
+	case X(Timaginary80,Tint8):
+	case X(Timaginary80,Tuns8):
+	case X(Timaginary80,Tint16):
+	case X(Timaginary80,Tuns16):
+	case X(Timaginary80,Tint32):
+	case X(Timaginary80,Tuns32):
+	case X(Timaginary80,Tint64):
+	case X(Timaginary80,Tuns64):
+	case X(Timaginary80,Tfloat32):
+	case X(Timaginary80,Tfloat64):
+	case X(Timaginary80,Tfloat80):	goto Lzero;
+	case X(Timaginary80,Timaginary32): e = el_una(OPf_d, TYidouble, e);
+				   fty = Timaginary64;
+				   goto Lagain;
+	case X(Timaginary80,Timaginary64): eop = OPld_d; goto Leop;
+	case X(Timaginary80,Tcomplex32):
+	case X(Timaginary80,Tcomplex64):
+	case X(Timaginary80,Tcomplex80):
+	    e = el_bin(OPadd,TYcldouble,el_long(TYldouble,0),e);
+	    fty = Tcomplex80;
+	    goto Lagain;
+
+	/* ============================= */
+
+	case X(Tcomplex32,Tint8):
+	case X(Tcomplex32,Tuns8):
+	case X(Tcomplex32,Tint16):
+	case X(Tcomplex32,Tuns16):
+	case X(Tcomplex32,Tint32):
+	case X(Tcomplex32,Tuns32):
+	case X(Tcomplex32,Tint64):
+	case X(Tcomplex32,Tuns64):
+	case X(Tcomplex32,Tfloat32):
+	case X(Tcomplex32,Tfloat64):
+	case X(Tcomplex32,Tfloat80):
+		e = el_una(OPc_r, TYfloat, e);
+		fty = Tfloat32;
+		goto Lagain;
+	case X(Tcomplex32,Timaginary32):
+	case X(Tcomplex32,Timaginary64):
+	case X(Tcomplex32,Timaginary80):
+		e = el_una(OPc_i, TYifloat, e);
+		fty = Timaginary32;
+		goto Lagain;
+	case X(Tcomplex32,Tcomplex64):
+	case X(Tcomplex32,Tcomplex80):
+		e = el_una(OPf_d, TYcdouble, e);
+		fty = Tcomplex64;
+		goto Lagain;
+
+	/* ============================= */
+
+	case X(Tcomplex64,Tint8):
+	case X(Tcomplex64,Tuns8):
+	case X(Tcomplex64,Tint16):
+	case X(Tcomplex64,Tuns16):
+	case X(Tcomplex64,Tint32):
+	case X(Tcomplex64,Tuns32):
+	case X(Tcomplex64,Tint64):
+	case X(Tcomplex64,Tuns64):
+	case X(Tcomplex64,Tfloat32):
+	case X(Tcomplex64,Tfloat64):
+	case X(Tcomplex64,Tfloat80):
+		e = el_una(OPc_r, TYdouble, e);
+		fty = Tfloat64;
+		goto Lagain;
+	case X(Tcomplex64,Timaginary32):
+	case X(Tcomplex64,Timaginary64):
+	case X(Tcomplex64,Timaginary80):
+		e = el_una(OPc_i, TYidouble, e);
+		fty = Timaginary64;
+		goto Lagain;
+	case X(Tcomplex64,Tcomplex32):	 eop = OPd_f;	goto Leop;
+	case X(Tcomplex64,Tcomplex80):	 eop = OPd_ld;	goto Leop;
+
+	/* ============================= */
+
+	case X(Tcomplex80,Tint8):
+	case X(Tcomplex80,Tuns8):
+	case X(Tcomplex80,Tint16):
+	case X(Tcomplex80,Tuns16):
+	case X(Tcomplex80,Tint32):
+	case X(Tcomplex80,Tuns32):
+	case X(Tcomplex80,Tint64):
+	case X(Tcomplex80,Tuns64):
+	case X(Tcomplex80,Tfloat32):
+	case X(Tcomplex80,Tfloat64):
+	case X(Tcomplex80,Tfloat80):
+		e = el_una(OPc_r, TYldouble, e);
+		fty = Tfloat80;
+		goto Lagain;
+	case X(Tcomplex80,Timaginary32):
+	case X(Tcomplex80,Timaginary64):
+	case X(Tcomplex80,Timaginary80):
+		e = el_una(OPc_i, TYildouble, e);
+		fty = Timaginary80;
+		goto Lagain;
+	case X(Tcomplex80,Tcomplex32):
+	case X(Tcomplex80,Tcomplex64):
+		e = el_una(OPld_d, TYcdouble, e);
+		fty = Tcomplex64;
+		goto Lagain;
+
+	/* ============================= */
+
+	default:
+	    if (fty == tty)
+		goto Lpaint;
+	    //dump(0);
+	    //printf("fty = %d, tty = %d\n", fty, tty);
+	    error("e2ir: cannot cast from %s to %s", e1->type->toChars(), t->toChars());
+	    goto Lzero;
+
+	Lzero:
+	    e = el_long(ttym, 0);
+	    break;
+
+	Lpaint:
+	    e->Ety = ttym;
+	    break;
+
+	Leop:
+	    e = el_una(eop, ttym, e);
+	    break;
+    }
+Lret:
+    // Adjust for any type paints
+    t = type->toBasetype();
+    e->Ety = t->totym();
+
+    el_setLoc(e,loc);
+    return e;
+}
+
+elem *ArrayLengthExp::toElem(IRState *irs)
+{
+    elem *e = e1->toElem(irs);
+    e = el_una(OP64_32, type->totym(), e);
+    el_setLoc(e,loc);
+    return e;
+}
+
+elem *SliceExp::toElem(IRState *irs)
+{   elem *e;
+    Type *t1;
+
+    //printf("SliceExp::toElem()\n");
+    t1 = e1->type->toBasetype();
+    e = e1->toElem(irs);
+    if (lwr)
+    {	elem *elwr;
+	elem *elwr2;
+	elem *eupr;
+	elem *eptr;
+	elem *einit;
+	int sz;
+
+	einit = resolveLengthVar(lengthVar, &e, t1);
+
+	sz = t1->nextOf()->size();
+
+	elwr = lwr->toElem(irs);
+	eupr = upr->toElem(irs);
+
+	elwr2 = el_same(&elwr);
+
+	// Create an array reference where:
+	// length is (upr - lwr)
+	// pointer is (ptr + lwr*sz)
+	// Combine as (length pair ptr)
+
+	if (global.params.useArrayBounds)
+	{
+	    // Checks (unsigned compares):
+	    //	upr <= array.length
+	    //	lwr <= upr
+
+	    elem *c1;
+	    elem *c2;
+	    elem *ea;
+	    elem *eb;
+	    elem *eupr2;
+	    elem *elength;
+
+	    if (t1->ty == Tpointer)
+	    {
+		// Just do lwr <= upr check
+
+		eupr2 = el_same(&eupr);
+		eupr2->Ety = TYuint;			// make sure unsigned comparison
+		c1 = el_bin(OPle, TYint, elwr2, eupr2);
+		c1 = el_combine(eupr, c1);
+		goto L2;
+	    }
+	    else if (t1->ty == Tsarray)
+	    {	TypeSArray *tsa = (TypeSArray *)t1;
+		integer_t length = tsa->dim->toInteger();
+
+		elength = el_long(TYuint, length);
+		goto L1;
+	    }
+	    else if (t1->ty == Tarray)
+	    {
+		if (lengthVar)
+		    elength = el_var(lengthVar->toSymbol());
+		else
+		{
+		    elength = e;
+		    e = el_same(&elength);
+		    elength = el_una(OP64_32, TYuint, elength);
+		}
+	    L1:
+		eupr2 = el_same(&eupr);
+		c1 = el_bin(OPle, TYint, eupr, elength);
+		eupr2->Ety = TYuint;			// make sure unsigned comparison
+		c2 = el_bin(OPle, TYint, elwr2, eupr2);
+		c1 = el_bin(OPandand, TYint, c1, c2);	// (c1 && c2)
+
+	    L2:
+		// Construct: (c1 || ModuleArray(line))
+		Symbol *sassert;
+
+		sassert = irs->blx->module->toModuleArray();
+		ea = el_bin(OPcall,TYvoid,el_var(sassert), el_long(TYint, loc.linnum));
+		eb = el_bin(OPoror,TYvoid,c1,ea);
+		elwr = el_combine(elwr, eb);
+
+		elwr2 = el_copytree(elwr2);
+		eupr = el_copytree(eupr2);
+	    }
+	}
+
+	eptr = array_toPtr(e1->type, e);
+
+	elem *elength = el_bin(OPmin, TYint, eupr, elwr2);
+	eptr = el_bin(OPadd, TYnptr, eptr, el_bin(OPmul, TYint, el_copytree(elwr2), el_long(TYint, sz)));
+
+	e = el_pair(TYullong, elength, eptr);
+	e = el_combine(elwr, e);
+	e = el_combine(einit, e);
+    }
+    else if (t1->ty == Tsarray)
+    {
+	e = sarray_toDarray(t1, NULL, e);
+    }
+    el_setLoc(e,loc);
+    return e;
+}
+
+elem *IndexExp::toElem(IRState *irs)
+{   elem *e;
+    elem *n1 = e1->toElem(irs);
+    elem *n2;
+    elem *eb = NULL;
+    Type *t1;
+
+    //printf("IndexExp::toElem() %s\n", toChars());
+    t1 = e1->type->toBasetype();
+    if (t1->ty == Taarray)
+    {
+	// set to:
+	//	*aaGet(aa, keyti, valuesize, value);
+
+	TypeAArray *taa = (TypeAArray *)t1;
+	elem *keyti;
+	elem *ep;
+	int vsize = taa->next->size();
+	elem *valuesize;
+	Symbol *s;
+
+	n2 = e2->toElem(irs);
+	if (n2->Ety == TYstruct)
+	{
+	    n2 = el_una(OPstrpar, TYstruct, n2);
+	    n2->Enumbytes = n2->E1->Enumbytes;
+	    assert(n2->Enumbytes);
+	}
+	valuesize = el_long(TYuint, vsize);	// BUG: should be TYsize_t
+	if (modifiable)
+	{
+	    n1 = el_una(OPaddr, TYnptr, n1);
+	    s = taa->aaGetSymbol("Get", 1);
+	}
+	else
+	{
+	    s = taa->aaGetSymbol("GetRvalue", 1);
+	}
+	//printf("taa->key = %s\n", taa->key->toChars());
+	keyti = taa->key->getInternalTypeInfo(NULL)->toElem(irs);
+	//printf("keyti:\n");
+	//elem_print(keyti);
+	ep = el_params(n2, valuesize, keyti, n1, NULL);
+	e = el_bin(OPcall, TYnptr, el_var(s), ep);
+	if (global.params.useArrayBounds)
+	{
+	    elem *n;
+	    elem *ea;
+
+	    n = el_same(&e);
+
+	    // Construct: ((e || ModuleAssert(line)),n)
+	    Symbol *sassert;
+
+	    sassert = irs->blx->module->toModuleArray();
+	    ea = el_bin(OPcall,TYvoid,el_var(sassert),
+		el_long(TYint, loc.linnum));
+	    e = el_bin(OPoror,TYvoid,e,ea);
+	    e = el_bin(OPcomma, TYnptr, e, n);
+	}
+	e = el_una(OPind, type->totym(), e);
+	if (tybasic(e->Ety) == TYstruct)
+	    e->Enumbytes = type->size();
+    }
+    else
+    {	elem *einit;
+
+	einit = resolveLengthVar(lengthVar, &n1, t1);
+	n2 = e2->toElem(irs);
+
+	if (global.params.useArrayBounds)
+	{
+	    elem *elength;
+	    elem *n2x;
+	    elem *ea;
+
+	    if (t1->ty == Tsarray)
+	    {	TypeSArray *tsa = (TypeSArray *)t1;
+		integer_t length = tsa->dim->toInteger();
+
+		elength = el_long(TYuint, length);
+		goto L1;
+	    }
+	    else if (t1->ty == Tarray)
+	    {
+		elength = n1;
+		n1 = el_same(&elength);
+		elength = el_una(OP64_32, TYuint, elength);
+	    L1:
+		n2x = n2;
+		n2 = el_same(&n2x);
+		n2x = el_bin(OPlt, TYint, n2x, elength);
+
+		// Construct: (n2x || ModuleAssert(line))
+		Symbol *sassert;
+
+		sassert = irs->blx->module->toModuleArray();
+		ea = el_bin(OPcall,TYvoid,el_var(sassert),
+		    el_long(TYint, loc.linnum));
+		eb = el_bin(OPoror,TYvoid,n2x,ea);
+	    }
+	}
+
+	n1 = array_toPtr(t1, n1);
+
+	{   elem *escale;
+
+	    escale = el_long(TYint, t1->nextOf()->size());
+	    n2 = el_bin(OPmul, TYint, n2, escale);
+	    e = el_bin(OPadd, TYnptr, n1, n2);
+	    e = el_una(OPind, type->totym(), e);
+	    if (tybasic(e->Ety) == TYstruct || tybasic(e->Ety) == TYarray)
+	    {	e->Ety = TYstruct;
+		e->Enumbytes = type->size();
+	    }
+	}
+
+	eb = el_combine(einit, eb);
+	e = el_combine(eb, e);
+    }
+    el_setLoc(e,loc);
+    return e;
+}
+
+
+elem *TupleExp::toElem(IRState *irs)
+{   elem *e = NULL;
+
+    //printf("TupleExp::toElem() %s\n", toChars());
+    for (size_t i = 0; i < exps->dim; i++)
+    {	Expression *el = (Expression *)exps->data[i];
+	elem *ep = el->toElem(irs);
+
+	e = el_combine(e, ep);
+    }
+    return e;
+}
+
+
+elem *ArrayLiteralExp::toElem(IRState *irs)
+{   elem *e;
+    size_t dim;
+
+    //printf("ArrayLiteralExp::toElem() %s\n", toChars());
+    if (elements)
+    {
+	dim = elements->dim;
+	e = el_long(TYint, dim);
+	for (size_t i = 0; i < dim; i++)
+	{   Expression *el = (Expression *)elements->data[i];
+	    elem *ep = el->toElem(irs);
+
+	    if (tybasic(ep->Ety) == TYstruct || tybasic(ep->Ety) == TYarray)
+	    {
+		ep = el_una(OPstrpar, TYstruct, ep);
+		ep->Enumbytes = el->type->size();
+	    }
+	    e = el_param(ep, e);
+	}
+    }
+    else
+    {	dim = 0;
+	e = el_long(TYint, 0);
+    }
+    Type *tb = type->toBasetype();
+#if 1
+    e = el_param(e, type->getTypeInfo(NULL)->toElem(irs));
+
+    // call _d_arrayliteralT(ti, dim, ...)
+    e = el_bin(OPcall,TYnptr,el_var(rtlsym[RTLSYM_ARRAYLITERALT]),e);
+#else
+    e = el_param(e, el_long(TYint, tb->next->size()));
+
+    // call _d_arrayliteral(size, dim, ...)
+    e = el_bin(OPcall,TYnptr,el_var(rtlsym[RTLSYM_ARRAYLITERAL]),e);
+#endif
+    if (tb->ty == Tarray)
+    {
+	e = el_pair(TYullong, el_long(TYint, dim), e);
+    }
+    else if (tb->ty == Tpointer)
+    {
+    }
+    else
+    {
+	e = el_una(OPind,TYstruct,e);
+	e->Enumbytes = type->size();
+    }
+
+    el_setLoc(e,loc);
+    return e;
+}
+
+
+elem *AssocArrayLiteralExp::toElem(IRState *irs)
+{   elem *e;
+    size_t dim;
+
+    //printf("AssocArrayLiteralExp::toElem() %s\n", toChars());
+    dim = keys->dim;
+    e = el_long(TYint, dim);
+    for (size_t i = 0; i < dim; i++)
+    {   Expression *el = (Expression *)keys->data[i];
+
+	for (int j = 0; j < 2; j++)
+	{
+	    elem *ep = el->toElem(irs);
+
+	    if (tybasic(ep->Ety) == TYstruct || tybasic(ep->Ety) == TYarray)
+	    {
+		ep = el_una(OPstrpar, TYstruct, ep);
+		ep->Enumbytes = el->type->size();
+	    }
+//printf("[%d] %s\n", i, el->toChars());
+//elem_print(ep);
+	    e = el_param(ep, e);
+	    el = (Expression *)values->data[i];
+	}
+    }
+    e = el_param(e, type->getTypeInfo(NULL)->toElem(irs));
+
+    // call _d_assocarrayliteralT(ti, dim, ...)
+    e = el_bin(OPcall,TYnptr,el_var(rtlsym[RTLSYM_ASSOCARRAYLITERALT]),e);
+
+    el_setLoc(e,loc);
+    return e;
+}
+
+
+/*******************************************
+ * Generate elem to zero fill contents of Symbol stmp
+ * from *poffset..offset2.
+ * May store anywhere from 0..maxoff, as this function
+ * tries to use aligned int stores whereever possible.
+ * Update *poffset to end of initialized hole; *poffset will be >= offset2.
+ */
+
+elem *fillHole(Symbol *stmp, size_t *poffset, size_t offset2, size_t maxoff)
+{   elem *e = NULL;
+    int basealign = 1;
+
+    while (*poffset < offset2)
+    {   tym_t ty;
+	elem *e1;
+
+	if (tybasic(stmp->Stype->Tty) == TYnptr)
+	    e1 = el_var(stmp);
+	else
+	    e1 = el_ptr(stmp);
+	if (basealign)
+	    *poffset &= ~3;
+	basealign = 1;
+	size_t sz = maxoff - *poffset;
+	switch (sz)
+	{   case 1: ty = TYchar;	break;
+	    case 2: ty = TYshort;	break;
+	    case 3:
+		ty = TYshort;
+		basealign = 0;
+		break;
+	    default:
+		ty = TYlong;
+		break;
+	}
+	e1 = el_bin(OPadd, TYnptr, e1, el_long(TYsize_t, *poffset));
+	e1 = el_una(OPind, ty, e1);
+	e1 = el_bin(OPeq, ty, e1, el_long(ty, 0));
+	e = el_combine(e, e1);
+	*poffset += tysize[ty];
+    }
+    return e;
+}
+
+elem *StructLiteralExp::toElem(IRState *irs)
+{   elem *e;
+    size_t dim;
+
+    //printf("StructLiteralExp::toElem() %s\n", toChars());
+
+    // struct symbol to initialize with the literal
+    Symbol *stmp = sym ? sym : symbol_genauto(sd->type->toCtype());
+
+    e = NULL;
+
+    if (fillHoles)
+    {
+	/* Initialize all alignment 'holes' to zero.
+	 * Do before initializing fields, as the hole filling process
+	 * can spill over into the fields.
+	 */
+	size_t offset = 0;
+	for (size_t i = 0; i < sd->fields.dim; i++)
+	{
+	    Dsymbol *s = (Dsymbol *)sd->fields.data[i];
+	    VarDeclaration *v = s->isVarDeclaration();
+	    assert(v);
+
+	    e = el_combine(e, fillHole(stmp, &offset, v->offset, sd->structsize));
+	    size_t vend = v->offset + v->type->size();
+	    if (offset < vend)
+		offset = vend;
+	}
+	e = el_combine(e, fillHole(stmp, &offset, sd->structsize, sd->structsize));
+    }
+
+    if (elements)
+    {
+	dim = elements->dim;
+	assert(dim <= sd->fields.dim);
+	for (size_t i = 0; i < dim; i++)
+	{   Expression *el = (Expression *)elements->data[i];
+	    if (!el)
+		continue;
+
+	    Dsymbol *s = (Dsymbol *)sd->fields.data[i];
+	    VarDeclaration *v = s->isVarDeclaration();
+	    assert(v);
+
+	    elem *e1;
+	    if (tybasic(stmp->Stype->Tty) == TYnptr)
+	    {	e1 = el_var(stmp);
+		e1->EV.sp.Voffset = soffset;
+	    }
+	    else
+	    {	e1 = el_ptr(stmp);
+		if (soffset)
+		    e1 = el_bin(OPadd, TYnptr, e1, el_long(TYsize_t, soffset));
+	    }
+	    e1 = el_bin(OPadd, TYnptr, e1, el_long(TYsize_t, v->offset));
+
+	    elem *ep = el->toElem(irs);
+
+	    Type *t1b = v->type->toBasetype();
+	    Type *t2b = el->type->toBasetype();
+	    if (t1b->ty == Tsarray)
+	    {
+		if (t2b->implicitConvTo(t1b))
+		{   elem *esize = el_long(TYsize_t, t1b->size());
+		    ep = array_toPtr(el->type, ep);
+		    e1 = el_bin(OPmemcpy, TYnptr, e1, el_param(ep, esize));
+		}
+		else
+		{
+		    elem *edim = el_long(TYsize_t, t1b->size() / t2b->size());
+		    e1 = setArray(e1, edim, t2b, ep);
+		}
+	    }
+	    else
+	    {
+		tym_t ty = v->type->totym();
+		e1 = el_una(OPind, ty, e1);
+		if (ty == TYstruct)
+		    e1->Enumbytes = v->type->size();
+		e1 = el_bin(OPeq, ty, e1, ep);
+		if (ty == TYstruct)
+		{   e1->Eoper = OPstreq;
+		    e1->Enumbytes = v->type->size();
+		}
+	    }
+	    e = el_combine(e, e1);
+	}
+    }
+
+    elem *ev = el_var(stmp);
+    ev->Enumbytes = sd->structsize;
+    e = el_combine(e, ev);
+    el_setLoc(e,loc);
+    return e;
+}
Index: d/dmd/scope.c
===================================================================
--- d/dmd/scope.c	(Revision 199)
+++ d/dmd/scope.c	(Arbeitskopie)
@@ -75,6 +75,7 @@
     this->incontract = 0;
     this->nofree = 0;
     this->noctor = 0;
+    this->noaccesscheck = 0;
     this->intypeof = 0;
     this->parameterSpecialization = 0;
     this->callSuper = 0;
@@ -121,6 +122,7 @@
     this->incontract = enclosing->incontract;
     this->nofree = 0;
     this->noctor = enclosing->noctor;
+    this->noaccesscheck = enclosing->noaccesscheck;
     this->intypeof = enclosing->intypeof;
     this->parameterSpecialization = enclosing->parameterSpecialization;
     this->callSuper = enclosing->callSuper;
Index: d/dmd/opover.c
===================================================================
--- d/dmd/opover.c	(Revision 199)
+++ d/dmd/opover.c	(Arbeitskopie)
@@ -739,7 +739,7 @@
     FuncDeclaration *fd;
 
     assert(td);
-    fd = td->deduce(sc, loc, targsi, arguments);
+    fd = td->deduceFunctionTemplate(sc, loc, targsi, arguments);
     if (!fd)
 	return;
     m->anyf = fd;
Index: d/dmd/template.c
===================================================================
--- d/dmd/template.c	(Revision 199)
+++ d/dmd/template.c	(Arbeitskopie)
@@ -1,6 +1,6 @@
 
 // Compiler implementation of the D programming language
-// Copyright (c) 1999-2007 by Digital Mars
+// Copyright (c) 1999-2008 by Digital Mars
 // All Rights Reserved
 // written by Walter Bright
 // http://www.digitalmars.com
@@ -81,6 +81,7 @@
     return (Tuple *)o;
 }
 
+
 /***********************
  * Try to get arg as a type.
  */
@@ -135,6 +136,7 @@
     Dsymbol *s2 = isDsymbol(o2);
     Tuple *v1 = isTuple(o1);
     Tuple *v2 = isTuple(o2);
+    //printf("\t match t1 %p t2 %p, e1 %p e2 %p, s1 %p s2 %p, v1 %p v2 %p\n", t1,t2,e1,e2,s1,s2,v1,v2);
 
     /* A proper implementation of the various equals() overrides
      * should make it possible to just do o1->equals(o2), but
@@ -163,7 +165,7 @@
 	}
 
 	if (!t2 || !t1->equals(t2))
-	    goto L1;
+	    goto Lnomatch;
     }
     else if (e1)
     {
@@ -173,33 +175,39 @@
 	    printf("match %d\n", e1->equals(e2));
 	    e1->print();
 	    e2->print();
+	    e1->type->print();
+	    e2->type->print();
 	}
 #endif
-	if (!e2 || !e1->equals(e2))
-	    goto L1;
+	if (!e2)
+	    goto Lnomatch;
+	if (!e1->equals(e2))
+	    goto Lnomatch;
     }
     else if (s1)
     {
 	//printf("%p %s, %p %s\n", s1, s1->toChars(), s2, s2->toChars());
 	if (!s2 || !s1->equals(s2) || s1->parent != s2->parent)
-	    goto L1;
+	{
+	    goto Lnomatch;
+	}
     }
     else if (v1)
     {
 	if (!v2)
-	    goto L1;
+	    goto Lnomatch;
 	if (v1->objects.dim != v2->objects.dim)
-	    goto L1;
+	    goto Lnomatch;
 	for (size_t i = 0; i < v1->objects.dim; i++)
 	{
 	    if (!match((Object *)v1->objects.data[i],
 		       (Object *)v2->objects.data[i],
 		       tempdecl, sc))
-		goto L1;
+		goto Lnomatch;
 	}
     }
     return 1;	// match
-L1:
+Lnomatch:
     return 0;	// nomatch;
 }
 
@@ -208,12 +216,15 @@
 
 void ObjectToCBuffer(OutBuffer *buf, HdrGenState *hgs, Object *oarg)
 {
+    //printf("ObjectToCBuffer()\n");
     Type *t = isType(oarg);
     Expression *e = isExpression(oarg);
     Dsymbol *s = isDsymbol(oarg);
     Tuple *v = isTuple(oarg);
     if (t)
+    {	//printf("\tt: %s ty = %d\n", t->toChars(), t->ty);
 	t->toCBuffer(buf, NULL, hgs);
+    }
     else if (e)
 	e->toCBuffer(buf, hgs);
     else if (s)
@@ -270,6 +281,7 @@
 #endif
     this->loc = loc;
     this->parameters = parameters;
+    this->origParameters = parameters;
     this->members = decldefs;
     this->overnext = NULL;
     this->overroot = NULL;
@@ -338,6 +350,17 @@
     Scope *paramscope = sc->push(paramsym);
     paramscope->parameterSpecialization = 1;
 
+    if (global.params.doDocComments)
+    {
+	origParameters = new TemplateParameters();
+	origParameters->setDim(parameters->dim);
+	for (int i = 0; i < parameters->dim; i++)
+	{
+	    TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
+	    origParameters->data[i] = (void *)tp->syntaxCopy();
+	}
+    }
+
     for (int i = 0; i < parameters->dim; i++)
     {
 	TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
@@ -350,6 +373,8 @@
 	TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
 
 	tp->semantic(paramscope);
+	if (i + 1 != parameters->dim && tp->isTemplateTupleParameter())
+	    error("template tuple parameter must be last one");
     }
 
     paramscope->pop();
@@ -439,6 +464,7 @@
  * those deduced types in dedtypes[].
  * Input:
  *	flag	1: don't do semantic() because of dummy types
+ *		2: don't change types in matchArg()
  * Output:
  *	dedtypes	deduced arguments
  * Return match level.
@@ -449,8 +475,9 @@
 {   MATCH m;
     int dedtypes_dim = dedtypes->dim;
 
-#if LOG
-    printf("+TemplateDeclaration::matchWithInstance(this = %p, ti = %p, flag = %d)\n", this, ti, flag);
+#define LOGM 0
+#if LOGM
+    printf("\n+TemplateDeclaration::matchWithInstance(this = %s, ti = %s, flag = %d)\n", toChars(), ti->toChars(), flag);
 #endif
 
 #if 0
@@ -468,7 +495,7 @@
     // If more arguments than parameters, no match
     if (ti->tiargs->dim > parameters_dim && !variadic)
     {
-#if LOG
+#if LOGM
 	printf(" no match: more arguments than parameters\n");
 #endif
 	return MATCHnomatch;
@@ -491,14 +518,15 @@
 	Declaration *sparam;
 
 	//printf("\targument [%d]\n", i);
-#if 0
-	printf("\targument [%d] is %s\n", i, oarg ? oarg->toChars() : "null");
+#if LOGM
+	//printf("\targument [%d] is %s\n", i, oarg ? oarg->toChars() : "null");
 	TemplateTypeParameter *ttp = tp->isTemplateTypeParameter();
 	if (ttp)
 	    printf("\tparameter[%d] is %s : %s\n", i, tp->ident->toChars(), ttp->specType ? ttp->specType->toChars() : "");
 #endif
 
 	m2 = tp->matchArg(paramscope, ti->tiargs, i, parameters, dedtypes, &sparam);
+	//printf("\tm2 = %d\n", m2);
 
 	if (m2 == MATCHnomatch)
 	{
@@ -529,7 +557,7 @@
 	}
     }
 
-#if 0
+#if LOGM
     // Print out the results
     printf("--------------------------\n");
     printf("template %s\n", toChars());
@@ -554,20 +582,20 @@
 	goto Lnomatch;
 #endif
 
-#if LOG
+#if LOGM
     printf(" match = %d\n", m);
 #endif
     goto Lret;
 
 Lnomatch:
-#if LOG
+#if LOGM
     printf(" no match\n");
 #endif
     m = MATCHnomatch;
 
 Lret:
     paramscope->pop();
-#if LOG
+#if LOGM
     printf("-TemplateDeclaration::matchWithInstance(this = %p, ti = %p) = %d\n", this, ti, m);
 #endif
     return m;
@@ -646,16 +674,19 @@
  *	fargs		arguments to function
  * Output:
  *	dedargs		Expression/Type deduced template arguments
+ * Returns:
+ *	match level
  */
 
-MATCH TemplateDeclaration::deduceMatch(Objects *targsi, Expressions *fargs,
+MATCH TemplateDeclaration::deduceFunctionTemplateMatch(Objects *targsi, Expressions *fargs,
 	Objects *dedargs)
 {
     size_t i;
     size_t nfparams;
-    size_t nfparams2;
     size_t nfargs;
     size_t nargsi;
+    int fptupindex = -1;
+    int tuple_dim = 0;
     MATCH match = MATCHexact;
     FuncDeclaration *fd = onemember->toAlias()->isFuncDeclaration();
     TypeFunction *fdtype;
@@ -663,7 +694,7 @@
     Objects dedtypes;	// for T:T*, the dedargs is the T*, dedtypes is the T
 
 #if 0
-    printf("\nTemplateDeclaration::deduceMatch() %s\n", toChars());
+    printf("\nTemplateDeclaration::deduceFunctionTemplateMatch() %s\n", toChars());
     for (i = 0; i < fargs->dim; i++)
     {	Expression *e = (Expression *)fargs->data[i];
 	printf("\tfarg[%d] is %s, type is %s\n", i, e->toChars(), e->type->toChars());
@@ -683,13 +714,19 @@
     paramsym->parent = scope->parent;
     Scope *paramscope = scope->push(paramsym);
 
+    tp = isVariadic();
+
     nargsi = 0;
     if (targsi)
     {	// Set initial template arguments
 
 	nargsi = targsi->dim;
 	if (nargsi > parameters->dim)
+	{   if (!tp)
 	    goto Lnomatch;
+	    dedargs->setDim(nargsi);
+	    dedargs->zero();
+	}
 
 	memcpy(dedargs->data, targsi->data, nargsi * sizeof(*dedargs->data));
 
@@ -699,6 +736,7 @@
 	    Declaration *sparam;
 
 	    m = tp->matchArg(paramscope, dedargs, i, parameters, &dedtypes, &sparam);
+	    //printf("\tdeduceType m = %d\n", m);
 	    if (m == MATCHnomatch)
 		goto Lnomatch;
 	    if (m < match)
@@ -714,7 +752,6 @@
     fdtype = (TypeFunction *)fd->type;
 
     nfparams = Argument::dim(fdtype->parameters); // number of function parameters
-    nfparams2 = nfparams;
     nfargs = fargs->dim;		// number of function arguments
 
     /* Check for match of function arguments with variadic template
@@ -737,34 +774,39 @@
 	    goto L1;
 	else
 	{
-	    /* See if 'A' of the template parameter matches 'A'
-	     * of the type of the last function parameter.
+	    /* Figure out which of the function parameters matches
+	     * the tuple template parameter. Do this by matching
+	     * type identifiers.
+	     * Set the index of this function parameter to fptupindex.
 	     */
-	    Argument *fparam = (Argument *)fdtype->parameters->data[nfparams - 1];
+	    for (fptupindex = 0; fptupindex < nfparams; fptupindex++)
+	    {
+		Argument *fparam = (Argument *)fdtype->parameters->data[fptupindex];
 	    if (fparam->type->ty != Tident)
-		goto L1;
+		    continue;
 	    TypeIdentifier *tid = (TypeIdentifier *)fparam->type;
 	    if (!tp->ident->equals(tid->ident) || tid->idents.dim)
-		goto L1;
+		    continue;
 
 	    if (fdtype->varargs)	// variadic function doesn't
 		goto Lnomatch;		// go with variadic template
 
-	    /* The types of the function arguments [nfparams - 1 .. nfargs]
+		/* The types of the function arguments
 	     * now form the tuple argument.
 	     */
 	    Tuple *t = new Tuple();
 	    dedargs->data[parameters->dim - 1] = (void *)t;
 
-	    int tuple_dim = nfargs - (nfparams - 1);
+		tuple_dim = nfargs - (nfparams - 1);
 	    t->objects.setDim(tuple_dim);
 	    for (i = 0; i < tuple_dim; i++)
-	    {	Expression *farg = (Expression *)fargs->data[nfparams - 1 + i];
+		{   Expression *farg = (Expression *)fargs->data[fptupindex + i];
 		t->objects.data[i] = (void *)farg->type;
 	    }
-	    nfparams2--;	// don't consider the last parameter for type deduction
 	    goto L2;
 	}
+	    fptupindex = -1;
+	}
     }
 
 L1:
@@ -779,8 +821,18 @@
 
 L2:
     // Loop through the function parameters
-    for (i = 0; i < nfparams2; i++)
+    for (i = 0; i < nfparams; i++)
     {
+	/* Skip over function parameters which wound up
+	 * as part of a template tuple parameter.
+	 */
+	if (i == fptupindex)
+	{   if (fptupindex == nfparams - 1)
+		break;
+	    i += tuple_dim - 1;
+	    continue;
+	}
+
 	Argument *fparam = Argument::getNth(fdtype->parameters, i);
 	Expression *farg;
 	MATCH m;
@@ -809,12 +861,12 @@
 	    if (!m && fparam->type->toBasetype()->ty == Tdelegate)
 	    {
 		TypeDelegate *td = (TypeDelegate *)fparam->type->toBasetype();
-		TypeFunction *tf = (TypeFunction *)td->nextOf();
+		TypeFunction *tf = (TypeFunction *)td->next;
 
 		if (!tf->varargs && Argument::dim(tf->parameters) == 0)
 		{
-		    m = farg->type->deduceType(scope, tf->nextOf(), parameters, &dedtypes);
-		    if (!m && tf->nextOf()->toBasetype()->ty == Tvoid)
+		    m = farg->type->deduceType(scope, tf->next, parameters, &dedtypes);
+		    if (!m && tf->next->toBasetype()->ty == Tvoid)
 			m = MATCHconvert;
 		}
 		//printf("\tm2 = %d\n", m);
@@ -968,6 +1020,15 @@
     return ::isVariadic(parameters);
 }
 
+/***********************************
+ * We can overload templates.
+ */
+
+int TemplateDeclaration::isOverloadable()
+{
+    return 1;
+}
+
 /*************************************************
  * Given function arguments, figure out which template function
  * to expand, and return that function.
@@ -977,7 +1038,7 @@
  *	fargs		arguments to function
  */
 
-FuncDeclaration *TemplateDeclaration::deduce(Scope *sc, Loc loc,
+FuncDeclaration *TemplateDeclaration::deduceFunctionTemplate(Scope *sc, Loc loc,
 	Objects *targsi, Expressions *fargs)
 {
     MATCH m_best = MATCHnomatch;
@@ -988,7 +1049,7 @@
     FuncDeclaration *fd;
 
 #if 0
-    printf("TemplateDeclaration::deduce() %s\n", toChars());
+    printf("TemplateDeclaration::deduceFunctionTemplate() %s\n", toChars());
     printf("    targsi:\n");
     if (targsi)
     {	for (int i = 0; i < targsi->dim; i++)
@@ -1020,8 +1081,8 @@
 	MATCH m;
 	Objects dedargs;
 
-	m = td->deduceMatch(targsi, fargs, &dedargs);
-	//printf("deduceMatch = %d\n", m);
+	m = td->deduceFunctionTemplateMatch(targsi, fargs, &dedargs);
+	//printf("deduceFunctionTemplateMatch = %d\n", m);
 	if (!m)			// if no match
 	    continue;
 
@@ -1036,9 +1097,9 @@
 	int c2 = td_best->leastAsSpecialized(td);
 	//printf("c1 = %d, c2 = %d\n", c1, c2);
 
-	if (c1 && !c2)
+	if (c1 > c2)
 	    goto Ltd;
-	else if (!c1 && c2)
+	else if (c1 < c2)
 	    goto Ltd_best;
 	else
 	    goto Lambig;
@@ -1108,6 +1169,8 @@
     for (int i = 0; i < parameters->dim; i++)
     {
 	TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
+	if (hgs->ddoc)
+	    tp = (TemplateParameter *)origParameters->data[i];
 	if (i)
 	    buf->writeByte(',');
 	tp->toCBuffer(buf, hgs);
@@ -1158,6 +1221,17 @@
  * Return -1 if not found.
  */
 
+int templateIdentifierLookup(Identifier *id, TemplateParameters *parameters)
+{
+	for (size_t i = 0; i < parameters->dim; i++)
+	{   TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
+
+	    if (tp->ident->equals(id))
+		return i;
+	}
+    return -1;
+}
+
 int templateParameterLookup(Type *tparam, TemplateParameters *parameters)
 {
     assert(tparam->ty == Tident);
@@ -1165,14 +1239,7 @@
     //printf("\ttident = '%s'\n", tident->toChars());
     if (tident->idents.dim == 0)
     {
-	Identifier *id = tident->ident;
-
-	for (size_t i = 0; i < parameters->dim; i++)
-	{   TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
-
-	    if (tp->ident->equals(id))
-		return i;
-	}
+	return templateIdentifierLookup(tident->ident, parameters);
     }
     return -1;
 }
@@ -1274,7 +1341,32 @@
 	if (tparam->ty == Tsarray)
 	{
 	    TypeSArray *tp = (TypeSArray *)tparam;
-	    if (dim->toInteger() != tp->dim->toInteger())
+
+	    if (tp->dim->op == TOKvar &&
+		((VarExp *)tp->dim)->var->storage_class & STCtemplateparameter)
+	    {	int i = templateIdentifierLookup(((VarExp *)tp->dim)->var->ident, parameters);
+		// This code matches code in TypeInstance::deduceType()
+		if (i == -1)
+		    goto Lnomatch;
+		TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
+		TemplateValueParameter *tvp = tp->isTemplateValueParameter();
+		if (!tvp)
+		    goto Lnomatch;
+		Expression *e = (Expression *)dedtypes->data[i];
+		if (e)
+		{
+		    if (!dim->equals(e))
+			goto Lnomatch;
+		}
+		else
+		{   Type *vt = tvp->valType->semantic(0, sc);
+		    MATCH m = (MATCH)dim->implicitConvTo(vt);
+		    if (!m)
+			goto Lnomatch;
+		    dedtypes->data[i] = dim;
+		}
+	    }
+	    else if (dim->toInteger() != tp->dim->toInteger())
 		return MATCHnomatch;
 	}
 	else if (tparam->ty == Taarray)
@@ -1327,9 +1419,11 @@
 
 MATCH TypeAArray::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes)
 {
-    //printf("TypeAArray::deduceType()\n");
-    //printf("\tthis   = %d, ", ty); print();
-    //printf("\ttparam = %d, ", tparam->ty); tparam->print();
+#if 0
+    printf("TypeAArray::deduceType()\n");
+    printf("\tthis   = %d, ", ty); print();
+    printf("\ttparam = %d, ", tparam->ty); tparam->print();
+#endif
 
     // Extra check that index type must match
     if (tparam && tparam->ty == Taarray)
@@ -1469,15 +1563,58 @@
 	//printf("tempinst->tempdecl = %p\n", tempinst->tempdecl);
 	//printf("tp->tempinst->tempdecl = %p\n", tp->tempinst->tempdecl);
 	if (!tp->tempinst->tempdecl)
-	{   if (!tp->tempinst->name->equals(tempinst->name))
+	{   //printf("tp->tempinst->name = '%s'\n", tp->tempinst->name->toChars());
+	    if (!tp->tempinst->name->equals(tempinst->name))
+	    {
+		/* Handle case of:
+		 *  template Foo(T : sa!(T), alias sa)
+		 */
+		int i = templateIdentifierLookup(tp->tempinst->name, parameters);
+		if (i == -1)
+		{   /* Didn't find it as a parameter identifier. Try looking
+		     * it up and seeing if is an alias. See Bugzilla 1454
+		     */
+		    Dsymbol *s = tempinst->tempdecl->scope->search(0, tp->tempinst->name, NULL);
+		    if (s)
+		    {
+			s = s->toAlias();
+			TemplateDeclaration *td = s->isTemplateDeclaration();
+			if (td && td == tempinst->tempdecl)
+			    goto L2;
+		    }
 		goto Lnomatch;
 	}
+		TemplateParameter *tpx = (TemplateParameter *)parameters->data[i];
+		// This logic duplicates tpx->matchArg()
+		TemplateAliasParameter *ta = tpx->isTemplateAliasParameter();
+		if (!ta)
+		    goto Lnomatch;
+		Dsymbol *sa = tempinst->tempdecl;
+		if (!sa)
+		    goto Lnomatch;
+		if (ta->specAlias && sa != ta->specAlias)
+		    goto Lnomatch;
+		if (dedtypes->data[i])
+		{   // Must match already deduced symbol
+		    Dsymbol *s = (Dsymbol *)dedtypes->data[i];
+
+		    if (s != sa)
+			goto Lnomatch;
+		}
+		dedtypes->data[i] = sa;
+	    }
+	}
 	else if (tempinst->tempdecl != tp->tempinst->tempdecl)
 	    goto Lnomatch;
 
+      L2:
+	if (tempinst->tiargs->dim != tp->tempinst->tiargs->dim)
+	    goto Lnomatch;
+
 	for (int i = 0; i < tempinst->tiargs->dim; i++)
 	{
-	    //printf("test: [%d]\n", i);
+	    //printf("\ttest: tempinst->tiargs[%d]\n", i);
+	    int j;
 	    Object *o1 = (Object *)tempinst->tiargs->data[i];
 	    Object *o2 = (Object *)tp->tempinst->tiargs->data[i];
 
@@ -1502,18 +1639,29 @@
 	    else if (e1 && e2)
 	    {
 		if (!e1->equals(e2))
+		{   if (e2->op == TOKvar)
+		    {
+			/*
+			 * (T:Number!(e2), int e2)
+			 */
+			j = templateIdentifierLookup(((VarExp *)e2)->var->ident, parameters);
+			goto L1;
+		    }
 		    goto Lnomatch;
 	    }
+	    }
 	    else if (e1 && t2 && t2->ty == Tident)
-	    {	int i = templateParameterLookup(t2, parameters);
-		if (i == -1)
+	    {
+		j = templateParameterLookup(t2, parameters);
+	    L1:
+		if (j == -1)
 		    goto Lnomatch;
-		TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
+		TemplateParameter *tp = (TemplateParameter *)parameters->data[j];
 		// BUG: use tp->matchArg() instead of the following
 		TemplateValueParameter *tv = tp->isTemplateValueParameter();
 		if (!tv)
 		    goto Lnomatch;
-		Expression *e = (Expression *)dedtypes->data[i];
+		Expression *e = (Expression *)dedtypes->data[j];
 		if (e)
 		{
 		    if (!e1->equals(e))
@@ -1524,7 +1672,7 @@
 		    MATCH m = (MATCH)e1->implicitConvTo(vt);
 		    if (!m)
 			goto Lnomatch;
-		    dedtypes->data[i] = e1;
+		    dedtypes->data[j] = e1;
 		}
 	    }
 	    // BUG: Need to handle alias and tuple parameters
@@ -1836,6 +1984,7 @@
 	if (t)
 	{   // Must match already deduced type
 
+	    m = MATCHexact;
 	    if (!t->equals(ta))
 		goto Lnomatch;
 	}
@@ -2282,6 +2431,7 @@
     return m;
 
 Lnomatch:
+    //printf("\tno match\n");
     *psparam = NULL;
     return MATCHnomatch;
 }
@@ -2769,7 +2919,7 @@
 	    objFileModule = m;
 #endif
 	}
-	for (i = 0; 1; i++)
+	for (int i = 0; 1; i++)
 	{
 	    if (i == a->dim)
 	    {
@@ -2946,7 +3096,7 @@
 	Expression *ea = isExpression(o);
 	Dsymbol *sa = isDsymbol(o);
 
-	//printf("1: tiargs->data[%d] = %p, %p, %p\n", j, o, isDsymbol(o), isTuple(o));
+	//printf("1: tiargs->data[%d] = %p, %p, %p, ea=%p, ta=%p\n", j, o, isDsymbol(o), isTuple(o), ea, ta);
 	if (ta)
 	{
 	    //printf("type %s\n", ta->toChars());
@@ -3004,6 +3154,8 @@
 	    ea = ea->semantic(sc);
 	    ea = ea->optimize(WANTvalue | WANTinterpret);
 	    tiargs->data[j] = ea;
+	    if (ea->op == TOKtype)
+		tiargs->data[j] = ea->type;
 	}
 	else if (sa)
 	{
@@ -3055,6 +3207,7 @@
 	}
 #if LOG
 	printf("It's an instance of '%s' kind '%s'\n", s->toChars(), s->kind());
+	if (s->parent)
 	printf("s->parent = '%s'\n", s->parent->toChars());
 #endif
 	withsym = scopesym->isWithScopeSymbol();
@@ -3160,12 +3313,14 @@
 	}
 
 	dedtypes.setDim(td->parameters->dim);
+	dedtypes.zero();
 	if (!td->scope)
 	{
 	    error("forward reference to template declaration %s", td->toChars());
 	    return NULL;
 	}
 	m = td->matchWithInstance(this, &dedtypes, 0);
+	//printf("m = %d\n", m);
 	if (!m)			// no match at all
 	    continue;
 
@@ -3184,9 +3339,9 @@
 	int c2 = td_best->leastAsSpecialized(td);
 	//printf("c1 = %d, c2 = %d\n", c1, c2);
 
-	if (c1 && !c2)
+	if (c1 > c2)
 	    goto Ltd;
-	else if (!c1 && c2)
+	else if (c1 < c2)
 	    goto Ltd_best;
 	else
 	    goto Lambig;
@@ -3285,15 +3440,38 @@
 	  Lsa:
 	    Declaration *d = sa->isDeclaration();
 	    if (d && !d->isDataseg() &&
+#if V2
+		!(d->storage_class & STCmanifest) &&
+#endif
 		(!d->isFuncDeclaration() || d->isFuncDeclaration()->isNested()) &&
 		!isTemplateMixin())
 	    {
 		// if module level template
 		if (tempdecl->toParent()->isModule())
+		{   Dsymbol *dparent = d->toParent();
+		    if (!isnested)
+			isnested = dparent;
+		    else if (isnested != dparent)
 		{
-		    if (isnested && isnested != d->toParent())
-			error("inconsistent nesting levels %s and %s", isnested->toChars(), d->toParent()->toChars());
-		    isnested = d->toParent();
+			/* Select the more deeply nested of the two.
+			 * Error if one is not nested inside the other.
+			 */
+			for (Dsymbol *p = isnested; p; p = p->parent)
+			{
+			    if (p == dparent)
+				goto L1;	// isnested is most nested
+			}
+			for (Dsymbol *p = dparent; 1; p = p->parent)
+			{
+			    if (p == isnested)
+			    {	isnested = dparent;
+				goto L1;	// dparent is most nested
+			    }
+			}
+			error("is nested in both %s and %s", isnested->toChars(), dparent->toChars());
+		    }
+		  L1:
+		    //printf("\tnested inside %s\n", isnested->toChars());
 		    nested |= 1;
 		}
 		else
@@ -3825,6 +4003,8 @@
     argsym->parent = scy->parent;
     Scope *scope = scy->push(argsym);
 
+    unsigned errorsave = global.errors;
+
     // Declare each template parameter as an alias for the argument type
     declareParameters(scope);
 
@@ -3866,6 +4046,12 @@
 	semantic3(sc2);
     }
 
+    // Give additional context info if error occurred during instantiation
+    if (global.errors != errorsave)
+    {
+	error("error instantiating");
+    }
+
     sc2->pop();
 
     scope->pop();
Index: d/dmd/scope.h
===================================================================
--- d/dmd/scope.h	(Revision 199)
+++ d/dmd/scope.h	(Arbeitskopie)
@@ -61,6 +61,7 @@
     int noctor;			// set if constructor calls aren't allowed
     int intypeof;		// in typeof(exp)
     int parameterSpecialization; // if in template parameter specialization
+    int noaccesscheck;		// don't do access checks
 
     unsigned callSuper;		// primitive flow analysis for constructors
 #define	CSXthis_ctor	1	// called this()
Index: d/dmd/template.h
===================================================================
--- d/dmd/template.h	(Revision 199)
+++ d/dmd/template.h	(Arbeitskopie)
@@ -48,6 +48,9 @@
 struct TemplateDeclaration : ScopeDsymbol
 {
     TemplateParameters *parameters;	// array of TemplateParameter's
+
+    TemplateParameters *origParameters;	// originals for Ddoc
+
     Array instances;		// array of TemplateInstance's
 
     TemplateDeclaration *overnext;	// next overloaded TemplateDeclaration
@@ -70,13 +73,14 @@
     MATCH matchWithInstance(TemplateInstance *ti, Objects *atypes, int flag);
     int leastAsSpecialized(TemplateDeclaration *td2);
 
-    MATCH deduceMatch(Objects *targsi, Expressions *fargs, Objects *dedargs);
-    FuncDeclaration *deduce(Scope *sc, Loc loc, Objects *targsi, Expressions *fargs);
+    MATCH deduceFunctionTemplateMatch(Objects *targsi, Expressions *fargs, Objects *dedargs);
+    FuncDeclaration *deduceFunctionTemplate(Scope *sc, Loc loc, Objects *targsi, Expressions *fargs);
     void declareParameter(Scope *sc, TemplateParameter *tp, Object *o);
 
     TemplateDeclaration *isTemplateDeclaration() { return this; }
 
     TemplateTupleParameter *isVariadic();
+    int isOverloadable();
 };
 
 struct TemplateParameter
Index: d/dmd/mangle.c
===================================================================
--- d/dmd/mangle.c	(Revision 199)
+++ d/dmd/mangle.c	(Arbeitskopie)
@@ -147,6 +147,9 @@
 	if (isMain())
 	    return "_Dmain";
 
+	if (isWinMain() || isDllMain())
+	    return ident->toChars();
+
 	assert(this);
 	return Declaration::mangle();
     }
Index: d/dmd/doc.c
===================================================================
--- d/dmd/doc.c	(Revision 199)
+++ d/dmd/doc.c	(Arbeitskopie)
@@ -1,6 +1,6 @@
 
 // Compiler implementation of the D programming language
-// Copyright (c) 1999-2006 by Digital Mars
+// Copyright (c) 1999-2008 by Digital Mars
 // All Rights Reserved
 // written by Walter Bright
 // http://www.digitalmars.com
@@ -102,6 +102,7 @@
 unsigned char *skipwhitespace(unsigned char *p);
 unsigned skiptoident(OutBuffer *buf, unsigned i);
 unsigned skippastident(OutBuffer *buf, unsigned i);
+unsigned skippastURL(OutBuffer *buf, unsigned i);
 void highlightText(Scope *sc, Dsymbol *s, OutBuffer *buf, unsigned offset);
 void highlightCode(Scope *sc, Dsymbol *s, OutBuffer *buf, unsigned offset);
 void highlightCode2(Scope *sc, Dsymbol *s, OutBuffer *buf, unsigned offset);
@@ -114,7 +115,7 @@
 	</head><body>\n\
 	<h1>$(TITLE)</h1>\n\
 	$(BODY)\n\
-	<hr>$(SMALL Page generated by $(LINK2 http://www.digitalmars.com/d/ddoc.html, Ddoc). $(COPYRIGHT))\n\
+	<hr>$(SMALL Page generated by $(LINK2 http://www.digitalmars.com/d/1.0/ddoc.html, Ddoc). $(COPYRIGHT))\n\
 	</body></html>\n\
 \n\
 B =	<b>$0</b>\n\
@@ -269,7 +270,6 @@
     }
 
     buf.printf("$(DDOC_COMMENT Generated by Ddoc from %s)\n", srcfile->toChars());
-
     if (isDocFile)
     {
 	size_t commentlen = strlen((char *)comment);
@@ -283,7 +283,6 @@
     }
     else
     {
-
 	dc->writeSections(sc, this, sc->docbuf);
 	emitMemberComments(sc);
     }
@@ -373,6 +372,7 @@
 
 void Dsymbol::emitDitto(Scope *sc)
 {
+    //printf("Dsymbol::emitDitto() %s %s\n", kind(), toChars());
     OutBuffer *buf = sc->docbuf;
     unsigned o;
     OutBuffer b;
@@ -380,6 +380,17 @@
     b.writestring("$(DDOC_DITTO ");
     o = b.offset;
     toDocBuffer(&b);
+	//printf("b: '%.*s'\n", b.offset, b.data);
+	/* If 'this' is a function template, then highlightCode() was
+	 * already run by FuncDeclaration::toDocbuffer().
+	 */
+	TemplateDeclaration *td;
+	if (parent &&
+	    (td = parent->isTemplateDeclaration()) != NULL &&
+	    td->onemember == this)
+	{
+	}
+	else
     highlightCode(sc, this, &b, o);
     b.writeByte(')');
     buf->spread(sc->lastoffset, b.offset);
@@ -437,6 +448,7 @@
 
 void Dsymbol::emitComment(Scope *sc)		   { }
 void InvariantDeclaration::emitComment(Scope *sc)  { }
+//void PostBlitDeclaration::emitComment(Scope *sc)   { }
 void DtorDeclaration::emitComment(Scope *sc)	   { }
 void StaticCtorDeclaration::emitComment(Scope *sc) { }
 void StaticDtorDeclaration::emitComment(Scope *sc) { }
@@ -637,6 +649,7 @@
     //printf("Dsymbol::toDocbuffer() %s\n", toChars());
     HdrGenState hgs;
 
+    hgs.ddoc = 1;
     toCBuffer(buf, &hgs);
 }
 
@@ -654,6 +667,10 @@
 	    buf->writestring("static ");
 	if (d->isConst())
 	    buf->writestring("const ");
+#if V2
+	if (d->isInvariant())
+	    buf->writestring("invariant ");
+#endif
 	if (d->isFinal())
 	    buf->writestring("final ");
 	if (d->isSynchronized())
@@ -663,7 +680,7 @@
 
 void Declaration::toDocBuffer(OutBuffer *buf)
 {
-    //printf("Declaration::toDocbuffer() %s\n", toChars());
+    //printf("Declaration::toDocbuffer() %s, originalType = %p\n", toChars(), originalType);
     if (ident)
     {
 	prefix(buf, this);
@@ -671,6 +688,11 @@
 	if (type)
 	{   HdrGenState hgs;
 	    hgs.ddoc = 1;
+	    if (originalType)
+	    {	//originalType->print();
+		originalType->toCBuffer(buf, ident, &hgs);
+	    }
+	    else
 	    type->toCBuffer(buf, ident, &hgs);
 	}
 	else
@@ -723,22 +745,22 @@
 	    td->onemember == this)
 	{   HdrGenState hgs;
 	    unsigned o = buf->offset;
+	    TypeFunction *tf = (TypeFunction *)type;
 
 	    hgs.ddoc = 1;
 	    prefix(buf, td);
-	    type->next->toCBuffer(buf, NULL, &hgs);
+	    tf->next->toCBuffer(buf, NULL, &hgs);
 	    buf->writeByte(' ');
 	    buf->writestring(ident->toChars());
 	    buf->writeByte('(');
-	    for (int i = 0; i < td->parameters->dim; i++)
+	    for (int i = 0; i < td->origParameters->dim; i++)
 	    {
-		TemplateParameter *tp = (TemplateParameter *)td->parameters->data[i];
+		TemplateParameter *tp = (TemplateParameter *)td->origParameters->data[i];
 		if (i)
 		    buf->writeByte(',');
 		tp->toCBuffer(buf, &hgs);
 	    }
 	    buf->writeByte(')');
-	    TypeFunction *tf = (TypeFunction *)type;
 	    Argument::argsToCBuffer(buf, &hgs, tf->parameters, tf->varargs);
 	    buf->writestring(";\n");
 
@@ -1484,6 +1506,55 @@
 }
 
 
+/************************************************
+ * Scan forward past URL starting at i.
+ * We don't want to highlight parts of a URL.
+ * Returns:
+ *	i if not a URL
+ *	index just past it if it is a URL
+ */
+
+unsigned skippastURL(OutBuffer *buf, unsigned i)
+{   unsigned length = buf->offset - i;
+    unsigned char *p = &buf->data[i];
+    unsigned j;
+    unsigned sawdot = 0;
+
+    if (length > 7 && memicmp((char *)p, "http://", 7) == 0)
+    {
+	j = 7;
+    }
+    else if (length > 8 && memicmp((char *)p, "https://", 8) == 0)
+    {
+	j = 8;
+    }
+    else
+	goto Lno;
+
+    for (; j < length; j++)
+    {	unsigned char c = p[j];
+	if (isalnum(c))
+	    continue;
+        if (c == '-' || c == '_' || c == '?' ||
+            c == '=' || c == '%' || c == '&' ||
+            c == '/' || c == '+' || c == '#' ||
+            c == '~')
+            continue;
+        if (c == '.')
+        {
+            sawdot = 1;
+            continue;
+        }
+        break;
+    }
+    if (sawdot)
+	return i + j;
+
+Lno:
+    return i;
+}
+
+
 /****************************************************
  */
 
@@ -1728,6 +1799,12 @@
 		    j = skippastident(buf, i);
 		    if (j > i)
 		    {
+			unsigned k = skippastURL(buf, i);
+			if (k > i)
+			{   i = k - 1;
+			    break;
+			}
+
 			if (buf->data[i] == '_')	// leading '_' means no highlight
 			{
 			    buf->remove(i, 1);
Index: d/dmd/parse.c
===================================================================
--- d/dmd/parse.c	(Revision 199)
+++ d/dmd/parse.c	(Arbeitskopie)
@@ -650,6 +650,14 @@
 	    id = token.ident;
 	else if (token.value == TOKint32v)
 	    level = (unsigned)token.uns64value;
+#if V2
+	/* Allow:
+	 *    version (unittest)
+	 * even though unittest is a keyword
+	 */
+	else if (token.value == TOKunittest)
+	    id = Lexer::idPool(Token::toChars(TOKunittest));
+#endif
 	else
 	    error("identifier or integer expected, not %s", token.toChars());
 	nextToken();
@@ -1232,13 +1240,12 @@
 
 TemplateParameters *Parser::parseTemplateParameterList()
 {
-    TemplateParameters *tpl;
+    TemplateParameters *tpl = new TemplateParameters();
 
     if (token.value != TOKlparen)
     {   error("parenthesized TemplateParameterList expected following TemplateIdentifier");
 	goto Lerr;
     }
-    tpl = new TemplateParameters();
     nextToken();
 
     // Get array of TemplateParameters
@@ -1322,7 +1329,7 @@
 		if (!tp_ident)
 		{
 		    error("no identifier for template value parameter");
-		    goto Lerr;
+		    tp_ident = new Identifier("error", TOKidentifier);
 		}
 		if (token.value == TOKcolon)	// : CondExpression
 		{
@@ -1343,10 +1350,8 @@
 	}
     }
     check(TOKrparen);
+Lerr:
     return tpl;
-
-Lerr:
-    return NULL;
 }
 
 /******************************************
@@ -2261,6 +2266,9 @@
 			    break;
 			continue;
 
+		    case TOKeof:
+			break;
+
 		    default:
 			continue;
 		}
@@ -2301,6 +2309,10 @@
 			nextToken();
 			break;
 
+		    case TOKeof:
+			error("found EOF instead of initializer");
+			break;
+
 		    default:
 			value = parseInitializer();
 			is->addInit(NULL, value);
Index: d/dmd/interpret.c
===================================================================
--- d/dmd/interpret.c	(Revision 199)
+++ d/dmd/interpret.c	(Arbeitskopie)
@@ -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() : "");
+	    }
 	}
     }
 
@@ -591,10 +602,13 @@
 	    if (e && e != EXP_CONTINUE_INTERPRET)
 		break;
 	Lcontinue:
+	    if (increment)
+	    {
 	    e = increment->interpret(istate);
 	    if (e == EXP_CANT_INTERPRET)
 		break;
 	}
+	}
 	else if (e->isBool(FALSE))
 	{   e = NULL;
 	    break;
@@ -904,6 +918,8 @@
 {
 #if LOG
     printf("Expression::interpret() %s\n", toChars());
+    printf("type = %s\n", type->toChars());
+    dump(0);
 #endif
     return EXP_CANT_INTERPRET;
 }
@@ -949,7 +965,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 +1021,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 +1440,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 +1477,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])
@@ -1797,7 +1830,27 @@
     {
 	FuncDeclaration *fd = ((VarExp *)e1)->var->isFuncDeclaration();
 	if (fd)
-	{   // Inline .dup
+	{
+#if V2
+	    enum BUILTIN b = fd->isBuiltin();
+	    if (b)
+	    {	Expressions args;
+		args.setDim(arguments->dim);
+		for (size_t i = 0; i < args.dim; i++)
+		{
+		    Expression *earg = (Expression *)arguments->data[i];
+		    earg = earg->interpret(istate);
+		    if (earg == EXP_CANT_INTERPRET)
+			return earg;
+		    args.data[i] = (void *)earg;
+		}
+		e = eval_builtin(b, &args);
+		if (!e)
+		    e = EXP_CANT_INTERPRET;
+	    }
+	    else
+#endif
+	    // Inline .dup
 	    if (fd->ident == Id::adDup && arguments && arguments->dim == 2)
 	    {
 		e = (Expression *)arguments->data[1];
@@ -1812,7 +1865,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: d/dmd/toir.c
===================================================================
--- d/dmd/toir.c	(Revision 199)
+++ d/dmd/toir.c	(Arbeitskopie)
@@ -1,6 +1,6 @@
 
 // Compiler implementation of the D programming language
-// Copyright (c) 1999-2007 by Digital Mars
+// Copyright (c) 1999-2008 by Digital Mars
 // All Rights Reserved
 // written by Walter Bright
 // http://www.digitalmars.com
@@ -102,6 +102,11 @@
     {	/* Going down one nesting level, i.e. we're calling
 	 * a nested function from its enclosing function.
 	 */
+#if V2
+	if (irs->sclosure)
+	    ethis = el_var(irs->sclosure);
+	else
+#endif
 	if (irs->sthis)
 	{   // We have a 'this' pointer for the current function
 	    ethis = el_var(irs->sthis);
@@ -111,7 +116,11 @@
 	     * adding this frame into the linked list of stack
 	     * frames.
 	     */
+#if V2
+	    if (thisfd->closureVars.dim)
+#else
 	    if (thisfd->nestedFrameRef)
+#endif
 	    {	/* Local variables are referenced, can't skip.
 		 * Address of 'this' gives the 'this' for the nested
 		 * function
@@ -124,7 +133,11 @@
 	     * use NULL if no references to the current function's frame
 	     */
 	    ethis = el_long(TYnptr, 0);
+#if V2
+	    if (thisfd->closureVars.dim)
+#else
 	    if (thisfd->nestedFrameRef)
+#endif
 	    {	/* OPframeptr is an operator that gets the frame pointer
 		 * for the current function, i.e. for the x86 it gets
 		 * the value of EBP
@@ -160,7 +173,11 @@
 		    if (thisfd->isNested())
 		    {
 			FuncDeclaration *p = s->toParent2()->isFuncDeclaration();
+#if V2
+			if (!p || p->closureVars.dim)
+#else
 			if (!p || p->nestedFrameRef)
+#endif
 			    ethis = el_una(OPind, TYnptr, ethis);
 		    }
 		    else if (thisfd->vthis)
@@ -174,13 +191,15 @@
 		     * function must be a member function of that class.
 		     */
 		    ClassDeclaration *cd = s->isClassDeclaration();
-		    assert(cd);
+		    if (!cd)
+			goto Lnoframe;
 		    if (//cd->baseClass == fd ||
 			fd->isClassDeclaration() &&
 			fd->isClassDeclaration()->isBaseOf(cd, NULL))
 			break;
 		    if (!cd->isNested() || !cd->vthis)
 		    {
+		      Lnoframe:
 			irs->getFunc()->error(loc, "cannot get frame pointer to %s", fd->toChars());
 			return el_long(TYnptr, 0);	// error recovery
 		    }
@@ -194,7 +213,11 @@
 			 * nested references are skipped in the linked list
 			 * of frames.
 			 */
+#if V2
+			if (s->toParent2()->isFuncDeclaration()->closureVars.dim)
+#else
 			if (s->toParent2()->isFuncDeclaration()->nestedFrameRef)
+#endif
 			    ethis = el_una(OPind, TYnptr, ethis);
 			break;
 		    }
@@ -204,7 +227,11 @@
 			 * nested references are skipped in the linked list
 			 * of frames.
 			 */
+#if V2
+			if (s->toParent2()->isFuncDeclaration()->closureVars.dim)
+#else
 			if (s->toParent2()->isFuncDeclaration()->nestedFrameRef)
+#endif
 			    ethis = el_una(OPind, TYnptr, ethis);
 		    }
 		}
@@ -351,4 +378,110 @@
     return einit;
 }
 
+/*************************************
+ * Closures are implemented by taking the local variables that
+ * need to survive the scope of the function, and copying them
+ * into a gc allocated chuck of memory. That chunk, called the
+ * closure here, is inserted into the linked list of stack
+ * frames instead of the usual stack frame.
+ *
+ * buildClosure() inserts code just after the function prolog
+ * is complete. It allocates memory for the closure, allocates
+ * a local variable (sclosure) to point to it, inserts into it
+ * the link to the enclosing frame, and copies into it the parameters
+ * that are referred to in nested functions.
+ * In VarExp::toElem and SymOffExp::toElem, when referring to a
+ * variable that is in a closure, takes the offset from sclosure rather
+ * than from the frame pointer.
+ *
+ * getEthis() and NewExp::toElem need to use sclosure, if set, rather
+ * than the current frame pointer.
+ */
 
+#if V2
+
+void FuncDeclaration::buildClosure(IRState *irs)
+{
+    if (needsClosure())
+    {   // Generate closure on the heap
+	// BUG: doesn't capture variadic arguments passed to this function
+
+	Symbol *sclosure;
+	sclosure = symbol_name("__closptr",SCauto,Type::tvoidptr->toCtype());
+	sclosure->Sflags |= SFLtrue | SFLfree;
+	symbol_add(sclosure);
+	irs->sclosure = sclosure;
+
+	unsigned offset = PTRSIZE;	// leave room for previous sthis
+	for (int i = 0; i < closureVars.dim; i++)
+	{   VarDeclaration *v = (VarDeclaration *)closureVars.data[i];
+	    assert(v->isVarDeclaration());
+
+	    /* Align and allocate space for v in the closure
+	     * just like AggregateDeclaration::addField() does.
+	     */
+	    unsigned memsize = v->type->size();
+	    unsigned memalignsize = v->type->alignsize();
+	    unsigned xalign = v->type->memalign(global.structalign);
+	    AggregateDeclaration::alignmember(xalign, memalignsize, &offset);
+	    v->offset = offset;
+	    offset += memsize;
+
+	    /* Can't do nrvo if the variable is put in a closure, since
+	     * what the shidden points to may no longer exist.
+	     */
+	    if (nrvo_can && nrvo_var == v)
+	    {
+		nrvo_can = 0;
+	    }
+	}
+	// offset is now the size of the closure
+
+	// Allocate memory for the closure
+	elem *e;
+	e = el_long(TYint, offset);
+	e = el_bin(OPcall, TYnptr, el_var(rtlsym[RTLSYM_ALLOCMEMORY]), e);
+
+	// Assign block of memory to sclosure
+	//    sclosure = allocmemory(sz);
+	e = el_bin(OPeq, TYvoid, el_var(sclosure), e);
+
+	// Set the first element to sthis
+	//    *(sclosure + 0) = sthis;
+	elem *ethis;
+	if (irs->sthis)
+	    ethis = el_var(irs->sthis);
+	else
+	    ethis = el_long(TYnptr, 0);
+	elem *ex = el_una(OPind, TYnptr, el_var(sclosure));
+	ex = el_bin(OPeq, TYnptr, ex, ethis);
+	e = el_combine(e, ex);
+
+	// Copy function parameters into closure
+	for (int i = 0; i < closureVars.dim; i++)
+	{   VarDeclaration *v = (VarDeclaration *)closureVars.data[i];
+
+	    if (!v->isParameter())
+		continue;
+	    tym_t tym = v->type->totym();
+	    if (v->type->toBasetype()->ty == Tsarray || v->isOut() || v->isRef())
+		tym = TYnptr;	// reference parameters are just pointers
+	    ex = el_bin(OPadd, TYnptr, el_var(sclosure), el_long(TYint, v->offset));
+	    ex = el_una(OPind, tym, ex);
+	    if (ex->Ety == TYstruct)
+	    {   ex->Enumbytes = v->type->size();
+		ex = el_bin(OPstreq, tym, ex, el_var(v->toSymbol()));
+		ex->Enumbytes = v->type->size();
+	    }
+	    else
+		ex = el_bin(OPeq, tym, ex, el_var(v->toSymbol()));
+
+	    e = el_combine(e, ex);
+	}
+
+	block_appendexp(irs->blx->curblock, e);
+    }
+}
+
+#endif
+
Index: d/dmd/lexer.c
===================================================================
--- d/dmd/lexer.c	(Revision 199)
+++ d/dmd/lexer.c	(Arbeitskopie)
@@ -1,6 +1,6 @@
 
 // Compiler implementation of the D programming language
-// Copyright (c) 1999-2007 by Digital Mars
+// Copyright (c) 1999-2008 by Digital Mars
 // All Rights Reserved
 // written by Walter Bright
 // http://www.digitalmars.com
@@ -602,8 +602,20 @@
 		do
 		{
 		    p++;
+		    switch (*p)
+		    {
+			case 'u':
+			case 'U':
+			case '&':
 		    c = escapeSequence();
 		    stringbuffer.writeUTF8(c);
+			    break;
+
+			default:
+			    c = escapeSequence();
+			    stringbuffer.writeByte(c);
+			    break;
+		    }
 		} while (*p == '\\');
 		t->len = stringbuffer.offset;
 		stringbuffer.writeByte(0);
@@ -727,6 +739,15 @@
 			t->value = TOKint64v;
 			t->uns64value = major * 1000 + minor;
 		    }
+#if V2
+		    else if (id == Id::EOFX)
+		    {
+			t->value = TOKeof;
+			// Advance scanner to end of file
+			while (!(*p == 0 || *p == 0x1A))
+			    p++;
+		    }
+#endif
 		}
 		//printf("t->value = %d\n",t->value);
 		return;
@@ -1299,7 +1320,7 @@
 
 	default:
 		if (isoctal(c))
-		{   unsigned char v;
+		{   unsigned v;
 
 		    n = 0;
 		    v = 0;
@@ -1309,6 +1330,8 @@
 			c = *++p;
 		    } while (++n < 3 && isoctal(c));
 		    c = v;
+		    if (c > 0xFF)
+			error("0%03o is larger than a byte", c);
 		}
 		else
 		    error("undefined escape sequence \\%c\n",c);
@@ -1496,7 +1519,6 @@
 	{
 	    case '\n':
 	    Lnextline:
-printf("Lnextline\n");
 		loc.linnum++;
 		startline = 1;
 		if (blankrol)
@@ -1553,7 +1575,7 @@
 		}
 		else
 		{   hereid = t.ident;
-printf("hereid = '%s'\n", hereid->toChars());
+		    //printf("hereid = '%s'\n", hereid->toChars());
 		    blankrol = 1;
 		}
 		nest = 0;
@@ -1587,11 +1609,10 @@
 		unsigned char *psave = p;
 		p--;
 		scan(&t);		// read in possible heredoc identifier
-printf("endid = '%s'\n", t.ident->toChars());
+		//printf("endid = '%s'\n", t.ident->toChars());
 		if (t.value == TOKidentifier && t.ident->equals(hereid))
 		{   /* should check that rest of line is blank
 		     */
-printf("done\n");
 		    goto Ldone;
 		}
 		p = psave;
@@ -2171,7 +2192,7 @@
 		break;
 	    if (d >= r)
 		break;
-	    if (n * r + d < n)
+	    if (n && n * r + d <= n)
 	    {
 		error ("integer overflow");
 		break;
@@ -2751,13 +2772,10 @@
  */
 
 Identifier *Lexer::idPool(const char *s)
-{   unsigned len;
-    Identifier *id;
-    StringValue *sv;
-
-    len = strlen(s);
-    sv = stringtable.update(s, len);
-    id = (Identifier *) sv->ptrvalue;
+{
+    size_t len = strlen(s);
+    StringValue *sv = stringtable.update(s, len);
+    Identifier *id = (Identifier *) sv->ptrvalue;
     if (!id)
     {
 	id = new Identifier(sv->lstring.string, TOKidentifier);
@@ -2766,6 +2784,25 @@
     return id;
 }
 
+/*********************************************
+ * Create a unique identifier using the prefix s.
+ */
+
+Identifier *Lexer::uniqueId(const char *s, int num)
+{   char buffer[32];
+    size_t slen = strlen(s);
+
+    assert(slen + sizeof(num) * 3 + 1 <= sizeof(buffer));
+    sprintf(buffer, "%s%d", s, num);
+    return idPool(buffer);
+}
+
+Identifier *Lexer::uniqueId(const char *s)
+{
+    static int num;
+    return uniqueId(s, ++num);
+}
+
 /****************************************
  */
 
@@ -2884,12 +2921,16 @@
     {	"invariant",	TOKinvariant	},
     {	"unittest",	TOKunittest	},
     {	"version",	TOKversion	},
+    //{	"manifest",	TOKmanifest	},
 
     // Added after 1.0
     {	"ref",		TOKref		},
     {	"macro",	TOKmacro	},
 #if V2
+    {	"pure",		TOKpure		},
+    {	"nothrow",	TOKnothrow	},
     {	"__traits",	TOKtraits	},
+    {	"__overloadset", TOKoverloadset	},
 #endif
 };
 
@@ -2942,6 +2983,9 @@
     Token::tochars[TOKxorass]		= "^=";
     Token::tochars[TOKassign]		= "=";
     Token::tochars[TOKconstruct]	= "=";
+#if V2
+    Token::tochars[TOKblit]		= "=";
+#endif
     Token::tochars[TOKlt]		= "<";
     Token::tochars[TOKgt]		= ">";
     Token::tochars[TOKle]		= "<=";
@@ -3025,4 +3069,5 @@
     Token::tochars[TOKtuple]		= "tuple";
     Token::tochars[TOKdeclaration]	= "declaration";
     Token::tochars[TOKdottd]		= "dottd";
+    Token::tochars[TOKon_scope_exit]	= "scope(exit)";
 }
Index: d/dmd/lexer.h
===================================================================
--- d/dmd/lexer.h	(Revision 199)
+++ d/dmd/lexer.h	(Arbeitskopie)
@@ -1,6 +1,6 @@
 
 // Compiler implementation of the D programming language
-// Copyright (c) 1999-2007 by Digital Mars
+// Copyright (c) 1999-2008 by Digital Mars
 // All Rights Reserved
 // written by Walter Bright
 // http://www.digitalmars.com
@@ -92,11 +92,11 @@
 	TOKand,		TOKor,		TOKxor,
 	TOKandass,	TOKorass,	TOKxorass,
 	TOKassign,	TOKnot,		TOKtilde,
-	TOKplusplus,	TOKminusminus,	TOKconstruct,
+	TOKplusplus,	TOKminusminus,	TOKconstruct,	TOKblit,
 	TOKdot,		TOKarrow,	TOKcomma,
 	TOKquestion,	TOKandand,	TOKoror,
 
-// 103
+// 104
 	// Numeric literals
 	TOKint32v, TOKuns32v,
 	TOKint64v, TOKuns64v,
@@ -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,
@@ -152,6 +152,8 @@
 	TOKmacro,
 #if V2
 	TOKtraits,
+	TOKoverloadset,
+	TOKpure,
 #endif
 
 	TOKMAX
@@ -261,6 +263,8 @@
 
     static void initKeywords();
     static Identifier *idPool(const char *s);
+    static Identifier *uniqueId(const char *s);
+    static Identifier *uniqueId(const char *s, int num);
 
     TOK nextToken();
     void scan(Token *t);
Index: d/dmd/cast.c
===================================================================
--- d/dmd/cast.c	(Revision 199)
+++ d/dmd/cast.c	(Arbeitskopie)
@@ -578,30 +578,27 @@
  */
 
 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",
 	toChars(), type->toChars(), t->toChars());
 #endif
-    e = this;
-    tb = t->toBasetype();
-    type = type->toBasetype();
-    if (tb != type)
+    if (type == t)
+	return this;
+    Expression *e = this;
+    Type *tb = t->toBasetype();
+    Type *typeb = type->toBasetype();
+    if (tb != typeb)
     {
-	if (tb->ty == Tbit && isBit())
-	    ;
-
 	// Do (type *) cast of (type [dim])
-	else if (tb->ty == Tpointer &&
-	    type->ty == Tsarray
+	if (tb->ty == Tpointer &&
+	    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);
@@ -610,8 +607,8 @@
 	else if (tb->ty == Tdelegate && type->ty != Tdelegate)
 	{
 	    TypeDelegate *td = (TypeDelegate *)tb;
-	    TypeFunction *tf = (TypeFunction *)td->next;
-	    return toDelegate(sc, tf->next);
+	    TypeFunction *tf = (TypeFunction *)td->nextOf();
+	    return toDelegate(sc, tf->nextOf());
 	}
 #endif
 	else
@@ -619,6 +616,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;
@@ -626,47 +628,62 @@
 
 
 Expression *RealExp::castTo(Scope *sc, Type *t)
-{
-    if (type->isreal() && t->isreal())
-	type = t;
-    else if (type->isimaginary() && t->isimaginary())
-	type = t;
+{   Expression *e = this;
+    if (type != t)
+    {
+	if ((type->isreal() && t->isreal()) ||
+	    (type->isimaginary() && t->isimaginary())
+	   )
+	{   e = copy();
+	    e->type = t;
+	}
     else
-	return Expression::castTo(sc, t);
-    return this;
+	    e = Expression::castTo(sc, t);
+    }
+    return e;
 }
 
 
 Expression *ComplexExp::castTo(Scope *sc, Type *t)
-{
+{   Expression *e = this;
+    if (type != t)
+    {
     if (type->iscomplex() && t->iscomplex())
-	type = t;
+	{   e = copy();
+	    e->type = t;
+	}
     else
-	return Expression::castTo(sc, t);
-    return this;
+	    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);
+    if (type == t)
+    {
     committed = 1;
-    e = this;
+	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->next->ty == Tvoid &&
+	if (e->type->ty == Tpointer && e->type->nextOf()->ty == Tvoid &&
 	    (tb->ty == Tpointer || tb->ty == Tarray || tb->ty == Taarray ||
 	     tb->ty == Tdelegate))
 	{
 #if 0
 	    if (tb->ty == Tdelegate)
 	    {   TypeDelegate *td = (TypeDelegate *)tb;
-		TypeFunction *tf = (TypeFunction *)td->next;
+		TypeFunction *tf = (TypeFunction *)td->nextOf();
 
 		if (!tf->varargs &&
 		    !(tf->arguments && tf->arguments->dim)
@@ -679,8 +696,7 @@
 	}
 	else
 	{
-	    return Expression::castTo(sc, t);
-	    //e = new CastExp(loc, e, tb);
+	    return e->Expression::castTo(sc, t);
 	}
     }
     e->type = t;
@@ -950,23 +966,31 @@
 
 
 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;
 }
 
 
 Expression *ArrayLiteralExp::castTo(Scope *sc, Type *t)
 {
+#if 0
+    printf("ArrayLiteralExp::castTo(this=%s, type=%s, t=%s)\n",
+	toChars(), type->toChars(), t->toChars());
+#endif
+    if (type == t)
+	return this;
+    ArrayLiteralExp *e = this;
     Type *typeb = type->toBasetype();
     Type *tb = t->toBasetype();
     if ((tb->ty == Tarray || tb->ty == Tsarray) &&
 	(typeb->ty == Tarray || typeb->ty == Tsarray) &&
-	tb->next->toBasetype()->ty != Tvoid)
+	tb->nextOf()->toBasetype()->ty != Tvoid)
     {
 	if (tb->ty == Tsarray)
 	{   TypeSArray *tsa = (TypeSArray *)tb;
@@ -974,46 +998,56 @@
 		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->next);
-	    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->next->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->next->toBasetype()->ty != Tvoid)
+	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->next);
-	    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)->key);
-	    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;
Index: d/dmd/link.c
===================================================================
--- d/dmd/link.c	(Revision 199)
+++ d/dmd/link.c	(Arbeitskopie)
@@ -255,7 +255,7 @@
     argv.push((void *)"-lpthread");
     argv.push((void *)"-lm");
 
-    if (!global.params.quiet)
+    if (!global.params.quiet || global.params.verbose)
     {
 	// Print it
 	for (i = 0; i < argv.dim; i++)