Index: src/declaration.c
===================================================================
--- src/declaration.c    (revision 780)
+++ src/declaration.c    (working copy)
@@ -91,7 +91,7 @@ void Declaration::checkModify(Loc loc, Scope *sc, Type *t)
     if (sc->incontract && isResult())
         error(loc, "cannot modify result '%s' in contract", toChars());
 
-    if (isCtorinit() && !t->isMutable())
+    if (isCtorinit() && !t->head()->isMutable())
     {   // It's only modifiable if inside the right constructor
         Dsymbol *s = sc->func;
         while (1)
@@ -887,16 +887,17 @@ Lagain:
 
     /* Adjust storage class to reflect type
      */
-    if (type->isConst())
+    Type *thead = type->head();
+    if (thead->isConst())
     {   storage_class |= STCconst;
-        if (type->isShared())
+        if (thead->isShared())
             storage_class |= STCshared;
     }
-    else if (type->isImmutable())
+    else if (thead->isImmutable())
         storage_class |= STCimmutable;
-    else if (type->isShared())
+    else if (thead->isShared())
         storage_class |= STCshared;
-    else if (type->isWild())
+    else if (thead->isWild())
         storage_class |= STCwild;
 
     if (isSynchronized())
Index: src/expression.c
===================================================================
--- src/expression.c    (revision 780)
+++ src/expression.c    (working copy)
@@ -1095,7 +1095,7 @@ Expression *Expression::modifiableLvalue(Scope *sc, Expression *e)
 
     // See if this expression is a modifiable lvalue (i.e. not const)
 #if DMDV2
-    if (type && (!type->isMutable() || !type->isAssignable()))
+    if (type && (!type->head()->isMutable() || !type->isAssignable()))
         error("%s is not mutable", e->toChars());
 #endif
     return toLvalue(sc, e);
@@ -6217,9 +6217,9 @@ Expression *DotVarExp::modifiableLvalue(Scope *sc, Expression *e)
 
     Type *t1 = e1->type->toBasetype();
 
-    if (!t1->isMutable() ||
-        (t1->ty == Tpointer && !t1->nextOf()->isMutable()) ||
-        !var->type->isMutable() ||
+    if (!t1->head()->isMutable() ||
+        (t1->ty == Tpointer && !t1->nextOf()->head()->isMutable()) ||
+        !var->type->head()->isMutable() ||
         !var->type->isAssignable() ||
         var->storage_class & STCmanifest
        )
@@ -8674,7 +8674,7 @@ Expression *IndexExp::modifiableLvalue(Scope *sc, Expression *e)
     modifiable = 1;
     if (e1->op == TOKstring)
         error("string literals are immutable");
-    if (type && !type->isMutable())
+    if (type && !type->head()->isMutable())
         error("%s isn't mutable", e->toChars());
     Type *t1 = e1->type->toBasetype();
     if (t1->ty == Taarray)
@@ -9081,7 +9081,7 @@ Expression *AssignExp::semantic(Scope *sc)
     else if (e1->op == TOKslice)
     {
         Type *tn = e1->type->nextOf();
-        if (tn && !tn->isMutable() && op != TOKconstruct)
+        if (tn && !tn->head()->isMutable() && op != TOKconstruct)
         {   error("slice %s is not mutable", e1->toChars());
             return new ErrorExp();
         }
Index: src/func.c
===================================================================
--- src/func.c    (revision 780)
+++ src/func.c    (working copy)
@@ -1275,7 +1275,7 @@ void FuncDeclaration::semantic3(Scope *sc)
                     for (int i = 0; i < cd->fields.dim; i++)
                     {   VarDeclaration *v = (VarDeclaration *)cd->fields.data[i];
 
-                        if (v->ctorinit == 0 && v->isCtorinit() && !v->type->isMutable())
+                        if (v->ctorinit == 0 && v->isCtorinit() && !v->type->head()->isMutable())
                             error("missing initializer for final field %s", v->toChars());
                     }
                 }
Index: src/mtype.c
===================================================================
--- src/mtype.c    (revision 780)
+++ src/mtype.c    (working copy)
@@ -122,6 +122,7 @@ Type::Type(TY ty)
     this->ty = ty;
     this->mod = 0;
     this->deco = NULL;
+    this->thead = NULL;
 #if DMDV2
     this->cto = NULL;
     this->ito = NULL;
@@ -199,6 +200,7 @@ void Type::init()
     mangleChar[Taarray] = 'H';
     mangleChar[Tpointer] = 'P';
     mangleChar[Treference] = 'R';
+    mangleChar[Trefsuffix] = 'X';
     mangleChar[Tfunction] = 'F';
     mangleChar[Tident] = 'I';
     mangleChar[Tclass] = 'C';
@@ -347,7 +349,7 @@ MATCH Type::constConv(Type *to)
 {
     if (equals(to))
         return MATCHexact;
-    if (ty == to->ty && MODimplicitConv(mod, to->mod))
+    if (ty == to->ty && MODimplicitConv(head()->mod, to->head()->mod))
         return MATCHconst;
     return MATCHnomatch;
 }
@@ -359,10 +361,10 @@ MATCH Type::constConv(Type *to)
 Type *Type::constOf()
 {
     //printf("Type::constOf() %p %s\n", this, toChars());
-    if (mod == MODconst)
+    if (head()->mod == MODconst)
         return this;
     if (cto)
-    {   assert(cto->mod == MODconst);
+    {   assert(cto->head()->mod == MODconst);
         return cto;
     }
     Type *t = makeConst();
@@ -379,13 +381,13 @@ Type *Type::constOf()
 Type *Type::invariantOf()
 {
     //printf("Type::invariantOf() %p %s\n", this, toChars());
-    if (isImmutable())
+    if (head()->isImmutable())
     {
         return this;
     }
     if (ito)
     {
-        assert(ito->isImmutable());
+        assert(ito->head()->isImmutable());
         return ito;
     }
     Type *t = makeInvariant();
@@ -403,24 +405,24 @@ Type *Type::mutableOf()
 {
     //printf("Type::mutableOf() %p, %s\n", this, toChars());
     Type *t = this;
-    if (isConst())
-    {   if (isShared())
+    if (head()->isConst())
+    {   if (head()->isShared())
             t = sto;            // shared const => shared
         else
             t = cto;            // const => naked
-        assert(!t || t->isMutable());
+        assert(!t || t->head()->isMutable());
     }
-    else if (isImmutable())
+    else if (head()->isImmutable())
     {   t = ito;                // immutable => naked
-        assert(!t || (t->isMutable() && !t->isShared()));
+        assert(!t || (t->head()->isMutable() && !t->head()->isShared()));
     }
-    else if (isWild())
+    else if (head()->isWild())
     {
-        if (isShared())
+        if (head()->isShared())
             t = sto;            // shared wild => shared
         else
             t = wto;            // wild => naked
-        assert(!t || t->isMutable());
+        assert(!t || t->head()->isMutable());
     }
     if (!t)
     {
@@ -428,20 +430,20 @@ Type *Type::mutableOf()
         t = t->merge();
         t->fixTo(this);
     }
-    assert(t->isMutable());
+    assert(t->head()->isMutable());
     return t;
 }
 
 Type *Type::sharedOf()
 {
     //printf("Type::sharedOf() %p, %s\n", this, toChars());
-    if (mod == MODshared)
+    if (head()->mod == MODshared)
     {
         return this;
     }
     if (sto)
     {
-        assert(sto->isShared());
+        assert(sto->head()->isShared());
         return sto;
     }
     Type *t = makeShared();
@@ -454,13 +456,13 @@ Type *Type::sharedOf()
 Type *Type::sharedConstOf()
 {
     //printf("Type::sharedConstOf() %p, %s\n", this, toChars());
-    if (mod == (MODshared | MODconst))
+    if (head()->mod == (MODshared | MODconst))
     {
         return this;
     }
     if (scto)
     {
-        assert(scto->mod == (MODshared | MODconst));
+        assert(scto->head()->mod == (MODshared | MODconst));
         return scto;
     }
     Type *t = makeSharedConst();
@@ -487,39 +489,25 @@ Type *Type::unSharedOf()
     //printf("Type::unSharedOf() %p, %s\n", this, toChars());
     Type *t = this;
 
-    if (isShared())
+    if (head()->isShared())
     {
-        if (isConst())
+        if (head()->isConst())
             t = cto;    // shared const => const
-        else if (isWild())
+        else if (head()->isWild())
             t = wto;    // shared wild => wild
         else
             t = sto;
-        assert(!t || !t->isShared());
+        assert(!t || !t->head()->isShared());
     }
 
     if (!t)
     {
-        unsigned sz = sizeTy[ty];
-        t = (Type *)mem.malloc(sz);
-        memcpy(t, this, sz);
-        t->mod = mod & ~MODshared;
-        t->deco = NULL;
-        t->arrayof = NULL;
-        t->pto = NULL;
-        t->rto = NULL;
-        t->cto = NULL;
-        t->ito = NULL;
-        t->sto = NULL;
-        t->scto = NULL;
-        t->wto = NULL;
-        t->swto = NULL;
-        t->vtinfo = NULL;
+        t = makeUnShared();
         t = t->merge();
 
         t->fixTo(this);
     }
-    assert(!t->isShared());
+    assert(!t->head()->isShared());
     return t;
 }
 
@@ -530,13 +518,13 @@ Type *Type::unSharedOf()
 Type *Type::wildOf()
 {
     //printf("Type::wildOf() %p %s\n", this, toChars());
-    if (mod == MODwild)
+    if (head()->mod == MODwild)
     {
         return this;
     }
     if (wto)
     {
-        assert(wto->isWild());
+        assert(wto->head()->isWild());
         return wto;
     }
     Type *t = makeWild();
@@ -549,13 +537,13 @@ Type *Type::wildOf()
 Type *Type::sharedWildOf()
 {
     //printf("Type::sharedWildOf() %p, %s\n", this, toChars());
-    if (mod == (MODshared | MODwild))
+    if (head()->mod == (MODshared | MODwild))
     {
         return this;
     }
     if (swto)
     {
-        assert(swto->mod == (MODshared | MODwild));
+        assert(swto->head()->mod == (MODshared | MODwild));
         return swto;
     }
     Type *t = makeSharedWild();
@@ -583,9 +571,9 @@ void Type::fixTo(Type *t)
     scto = t->scto;
 #endif
 
-    assert(mod != t->mod);
+    assert(head()->mod != t->head()->mod);
 #define X(m, n) (((m) << 4) | (n))
-    switch (X(mod, t->mod))
+    switch (X(head()->mod, t->head()->mod))
     {
         case X(0, MODconst):
             cto = t;
@@ -795,69 +783,69 @@ void Type::fixTo(Type *t)
 
 void Type::check()
 {
-    switch (mod)
+    switch (head()->mod)
     {
         case 0:
-            if (cto) assert(cto->mod == MODconst);
-            if (ito) assert(ito->mod == MODimmutable);
-            if (sto) assert(sto->mod == MODshared);
-            if (scto) assert(scto->mod == (MODshared | MODconst));
-            if (wto) assert(wto->mod == MODwild);
-            if (swto) assert(swto->mod == (MODshared | MODwild));
+            if (cto) assert(cto->head()->mod == MODconst);
+            if (ito) assert(ito->head()->mod == MODimmutable);
+            if (sto) assert(sto->head()->mod == MODshared);
+            if (scto) assert(scto->head()->mod == (MODshared | MODconst));
+            if (wto) assert(wto->head()->mod == MODwild);
+            if (swto) assert(swto->head()->mod == (MODshared | MODwild));
             break;
 
         case MODconst:
-            if (cto) assert(cto->mod == 0);
-            if (ito) assert(ito->mod == MODimmutable);
-            if (sto) assert(sto->mod == MODshared);
-            if (scto) assert(scto->mod == (MODshared | MODconst));
-            if (wto) assert(wto->mod == MODwild);
-            if (swto) assert(swto->mod == (MODshared | MODwild));
+            if (cto) assert(cto->head()->mod == 0);
+            if (ito) assert(ito->head()->mod == MODimmutable);
+            if (sto) assert(sto->head()->mod == MODshared);
+            if (scto) assert(scto->head()->mod == (MODshared | MODconst));
+            if (wto) assert(wto->head()->mod == MODwild);
+            if (swto) assert(swto->head()->mod == (MODshared | MODwild));
             break;
 
         case MODimmutable:
-            if (cto) assert(cto->mod == MODconst);
-            if (ito) assert(ito->mod == 0);
-            if (sto) assert(sto->mod == MODshared);
-            if (scto) assert(scto->mod == (MODshared | MODconst));
-            if (wto) assert(wto->mod == MODwild);
-            if (swto) assert(swto->mod == (MODshared | MODwild));
+            if (cto) assert(cto->head()->mod == MODconst);
+            if (ito) assert(ito->head()->mod == 0);
+            if (sto) assert(sto->head()->mod == MODshared);
+            if (scto) assert(scto->head()->mod == (MODshared | MODconst));
+            if (wto) assert(wto->head()->mod == MODwild);
+            if (swto) assert(swto->head()->mod == (MODshared | MODwild));
             break;
 
         case MODshared:
-            if (cto) assert(cto->mod == MODconst);
-            if (ito) assert(ito->mod == MODimmutable);
-            if (sto) assert(sto->mod == 0);
-            if (scto) assert(scto->mod == (MODshared | MODconst));
-            if (wto) assert(wto->mod == MODwild);
-            if (swto) assert(swto->mod == (MODshared | MODwild));
+            if (cto) assert(cto->head()->mod == MODconst);
+            if (ito) assert(ito->head()->mod == MODimmutable);
+            if (sto) assert(sto->head()->mod == 0);
+            if (scto) assert(scto->head()->mod == (MODshared | MODconst));
+            if (wto) assert(wto->head()->mod == MODwild);
+            if (swto) assert(swto->head()->mod == (MODshared | MODwild));
             break;
 
         case MODshared | MODconst:
-            if (cto) assert(cto->mod == MODconst);
-            if (ito) assert(ito->mod == MODimmutable);
-            if (sto) assert(sto->mod == MODshared);
-            if (scto) assert(scto->mod == 0);
-            if (wto) assert(wto->mod == MODwild);
-            if (swto) assert(swto->mod == (MODshared | MODwild));
+            if (cto) assert(cto->head()->mod == MODconst);
+            if (ito) assert(ito->head()->mod == MODimmutable);
+            if (sto) assert(sto->head()->mod == MODshared);
+            if (scto) assert(scto->head()->mod == 0);
+            if (wto) assert(wto->head()->mod == MODwild);
+            if (swto) assert(swto->head()->mod == (MODshared | MODwild));
             break;
 
         case MODwild:
-            if (cto) assert(cto->mod == MODconst);
-            if (ito) assert(ito->mod == MODimmutable);
-            if (sto) assert(sto->mod == MODshared);
-            if (scto) assert(scto->mod == (MODshared | MODconst));
-            if (wto) assert(wto->mod == 0);
-            if (swto) assert(swto->mod == (MODshared | MODwild));
+            if (cto) assert(cto->head()->mod == MODconst);
+            if (ito) assert(ito->head()->mod == MODimmutable);
+            if (sto) assert(sto->head()->mod == MODshared);
+            if (scto) assert(scto->head()->mod == (MODshared | MODconst));
+            if (wto) assert(wto->head()->mod == 0);
+            if (swto) assert(swto->head()->mod == (MODshared | MODwild));
             break;
 
         case MODshared | MODwild:
-            if (cto) assert(cto->mod == MODconst);
-            if (ito) assert(ito->mod == MODimmutable);
-            if (sto) assert(sto->mod == MODshared);
-            if (scto) assert(scto->mod == (MODshared | MODconst));
-            if (wto) assert(wto->mod == MODwild);
-            if (swto) assert(swto->mod == 0);
+            if (cto) assert(cto->head()->mod == MODconst);
+            if (ito) assert(ito->head()->mod == MODimmutable);
+            if (sto) assert(sto->head()->mod == MODshared);
+            if (scto) assert(scto->head()->mod == (MODshared | MODconst));
+            if (wto) assert(wto->head()->mod == MODwild);
+            if (swto) assert(swto->head()->mod == 0);
             break;
 
         default:
@@ -993,6 +981,26 @@ Type *Type::makeSharedConst()
     return t;
 }
 
+Type *Type::makeUnShared()
+{
+    unsigned sz = sizeTy[ty];
+    Type *t = (Type *)mem.malloc(sz);
+    memcpy(t, this, sz);
+    t->mod = mod & ~MODshared;
+    t->deco = NULL;
+    t->arrayof = NULL;
+    t->pto = NULL;
+    t->rto = NULL;
+    t->cto = NULL;
+    t->ito = NULL;
+    t->sto = NULL;
+    t->scto = NULL;
+    t->wto = NULL;
+    t->swto = NULL;
+    t->vtinfo = NULL;
+    return t;
+}
+
 Type *Type::makeWild()
 {
     if (wto)
@@ -1111,7 +1119,7 @@ Type *Type::addMod(unsigned mod)
 
     /* Add anything to immutable, and it remains immutable
      */
-    if (!t->isImmutable())
+    if (!t->head()->isImmutable())
     {
         //printf("addMod(%x) %s\n", mod, toChars());
         switch (mod)
@@ -1120,7 +1128,7 @@ Type *Type::addMod(unsigned mod)
                 break;
 
             case MODconst:
-                if (isShared())
+                if (head()->isShared())
                     t = sharedConstOf();
                 else
                     t = constOf();
@@ -1131,9 +1139,9 @@ Type *Type::addMod(unsigned mod)
                 break;
 
             case MODshared:
-                if (isConst())
+                if (head()->isConst())
                     t = sharedConstOf();
-                else if (isWild())
+                else if (head()->isWild())
                     t = sharedWildOf();
                 else
                     t = sharedOf();
@@ -1144,9 +1152,9 @@ Type *Type::addMod(unsigned mod)
                 break;
 
             case MODwild:
-                if (isConst())
+                if (head()->isConst())
                     ;
-                else if (isShared())
+                else if (head()->isShared())
                     t = sharedWildOf();
                 else
                     t = wildOf();
@@ -4416,6 +4424,66 @@ int TypeReference::isZeroInit(Loc loc)
 }
 
 
+
+/***************************** TypeRefSuffix *****************************/
+
+TypeRefSuffix::TypeRefSuffix(Type *t)
+    : TypeNext(Trefsuffix, t)
+{
+    // BUG: what about references to static arrays?
+}
+
+Type *TypeRefSuffix::syntaxCopy()
+{
+    Type *t = next->syntaxCopy();
+    if (t == next)
+        t = this;
+    else
+    {   t = new TypeRefSuffix(t);
+        t->mod = mod;
+    }
+    return t;
+}
+
+Type *TypeRefSuffix::semantic(Loc loc, Scope *sc)
+{
+    //printf("TypeReference::semantic()\n");
+    Type *n = next->semantic(loc, sc);
+    if (n->ty != Tclass || next->ty != Tident /* block double ref */)
+    {   error(loc, "ref suffix is only valid for class types");
+        return n;
+    }
+    next = n;
+    transitive();
+    if (next->mod != mod)
+    {   /* apply ref suffix modifiers.
+         */
+        return next->castMod(mod);
+    }
+    return next;
+}
+
+void TypeRefSuffix::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
+{
+    if (mod != this->mod)
+    {   toCBuffer3(buf, hgs, mod);
+        return;
+    }
+    next->toCBuffer2(buf, hgs, this->mod);
+    buf->writestring("ref");
+}
+
+Expression *TypeRefSuffix::dotExp(Scope *sc, Expression *e, Identifier *ident)
+{
+#if LOGDOTEXP
+    printf("TypeRefSuffix::dotExp(e = '%s', ident = '%s')\n", e->toChars(), ident->toChars());
+#endif
+
+    // References just forward things along
+    return next->dotExp(sc, e, ident);
+}
+
+
 /***************************** TypeFunction *****************************/
 
 TypeFunction::TypeFunction(Parameters *parameters, Type *treturn, int varargs, enum LINK linkage, StorageClass stc)
@@ -7194,6 +7262,27 @@ TypeClass::TypeClass(ClassDeclaration *sym)
     this->sym = sym;
 }
 
+TypeClass::TypeClass(TypeClass* tc, unsigned char headmod)
+        : Type(Tclass)
+{
+    this->sym = tc->sym;
+    this->mod = tc->mod;
+    
+    // Fix class modifiers
+    if (headmod & MODimmutable)
+        this->mod = MODimmutable;
+    else if (!isImmutable())
+        this->mod |= headmod;
+    
+    if (headmod != this->mod)
+    {
+        thead = new TypeRefSuffix(this);
+        thead->mod = headmod;
+        ((TypeRefSuffix *)thead)->next = this;
+        thead->check();
+    }
+}
+
 char *TypeClass::toChars()
 {
     if (mod)
@@ -7227,6 +7316,17 @@ Dsymbol *TypeClass::toDsymbol(Scope *sc)
 
 void TypeClass::toDecoBuffer(OutBuffer *buf, int flag)
 {
+    if (thead && thead->mod != this->mod)
+    {   /* Only print thead's deco if thead->mod differs from this->mod.
+         * Avoiding infinite recurtion by temporarily detatching ref member.
+         */
+        assert(thead->ty == Trefsuffix && ((TypeRefSuffix *)thead)->next == this);
+        Type *savedhead = thead;
+        thead = NULL;
+        savedhead->toDecoBuffer(buf, flag);
+        thead = savedhead;
+        return;
+    }
     const char *name = sym->mangle();
     //printf("TypeClass::toDecoBuffer('%s' flag=%d mod=%x) = '%s'\n", toChars(), flag, mod, name);
     Type::toDecoBuffer(buf, flag);
@@ -7235,6 +7335,17 @@ void TypeClass::toDecoBuffer(OutBuffer *buf, int flag)
 
 void TypeClass::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
 {
+    if (thead && thead->mod != this->mod)
+    {   /* Only print 'ref' marker if thead->mod differs from this->mod.
+         * Avoiding infinite recurtion by temporarily detatching ref member.
+         */
+        assert(thead->ty == Trefsuffix && ((TypeRefSuffix *)thead)->next == this);
+        Type *savedhead = thead;
+        thead = NULL;
+        savedhead->toCBuffer2(buf, hgs, mod);
+        thead = savedhead;
+        return;
+    }
     if (mod != this->mod)
     {   toCBuffer3(buf, hgs, mod);
         return;
@@ -7602,11 +7713,53 @@ MATCH TypeClass::constConv(Type *to)
     return MATCHnomatch;
 }
 
+Type *TypeClass::makeConst()
+{
+    return new TypeClass(this, MODconst);
+}
+
+Type *TypeClass::makeInvariant()
+{ 
+    return new TypeClass(this, MODimmutable);
+}
+
+Type *TypeClass::makeShared()
+{
+    return new TypeClass(this, MODshared);
+}
+
+Type *TypeClass::makeSharedConst()
+{
+    return new TypeClass(this, MODshared | MODconst);
+}
+Type *TypeClass::makeWild()
+{
+    return new TypeClass(this, MODwild);
+}
+
+Type *TypeClass::makeSharedWild()
+{
+    return new TypeClass(this, MODshared | MODwild);
+}
+
+Type *TypeClass::makeUnShared()
+{
+    return new TypeClass(this, head()->mod & ~MODshared);
+}
+
+Type *TypeClass::makeMutable()
+{
+    return new TypeClass(this, head()->mod & MODshared);
+}
+
 Type *TypeClass::toHeadMutable()
 {
-    return this;
+    if (!head()->mod)
+        return this;
+    return mutableOf();
 }
 
+
 Expression *TypeClass::defaultInit(Loc loc)
 {
 #if LOGDEFAULTINIT
@@ -7630,6 +7783,7 @@ int TypeClass::hasPointers()
     return TRUE;
 }
 
+
 /***************************** TypeTuple *****************************/
 
 TypeTuple::TypeTuple(Parameters *arguments)
Index: src/mtype.h
===================================================================
--- src/mtype.h    (revision 780)
+++ src/mtype.h    (working copy)
@@ -58,6 +58,7 @@ enum ENUMTY
     Taarray,            // associative array, aka T[type]
     Tpointer,
     Treference,
+    Trefsuffix,         // explicit ref suffix, aka Object ref
     Tfunction,
     Tident,
     Tclass,
@@ -121,6 +122,11 @@ struct Type : Object
         #define MODwild      8  // type is wild
         #define MODmutable   0x10       // type is mutable (only used in wildcard matching)
     char *deco;
+    
+    /* Head type which holds reference modifiers for class type.
+     * Points to 'this' for other types.
+     */
+    Type *thead;
 
     /* These are cached values that are lazily evaluated by constOf(), invariantOf(), etc.
      * They should not be referenced by anybody but mtype.c.
@@ -221,6 +227,7 @@ struct Type : Object
     virtual Type *syntaxCopy();
     int equals(Object *o);
     int dyncast() { return DYNCAST_TYPE; } // kludge for template.isType()
+    Type *head() { return thead ? thead : this; }
     int covariant(Type *t);
     char *toChars();
     static char needThisPrefix();
@@ -280,6 +287,7 @@ struct Type : Object
     virtual Type *makeInvariant();
     virtual Type *makeShared();
     virtual Type *makeSharedConst();
+    virtual Type *makeUnShared();
     virtual Type *makeWild();
     virtual Type *makeSharedWild();
     virtual Type *makeMutable();
@@ -538,6 +546,15 @@ struct TypeReference : TypeNext
 #endif
 };
 
+struct TypeRefSuffix : TypeNext
+{
+    TypeRefSuffix(Type *t);
+    Type *syntaxCopy();
+    Type *semantic(Loc loc, Scope *sc);
+    void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
+    Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
+};
+
 enum RET
 {
     RETregs     = 1,    // returned in registers
@@ -821,10 +838,19 @@ struct TypeClass : Type
     ClassDeclaration *sym;
 
     TypeClass(ClassDeclaration *sym);
+    TypeClass(TypeClass* tc, unsigned char headmod);
     d_uns64 size(Loc loc);
     char *toChars();
     Type *syntaxCopy();
     Type *semantic(Loc loc, Scope *sc);
+    Type *makeConst();
+    Type *makeInvariant();
+    Type *makeShared();
+    Type *makeSharedConst();
+    Type *makeUnShared();
+    Type *makeWild();
+    Type *makeSharedWild();
+    Type *makeMutable();
     Dsymbol *toDsymbol(Scope *sc);
     void toDecoBuffer(OutBuffer *buf, int flag);
     void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
Index: src/osx.mak
===================================================================
--- src/osx.mak    (revision 780)
+++ src/osx.mak    (working copy)
@@ -20,8 +20,8 @@ CC=g++ -m32 -isysroot $(SDK)
 
 WARNINGS=-Wno-deprecated -Wstrict-aliasing
 
-#GFLAGS = $(WARNINGS) -D__near= -D__pascal= -fno-exceptions -g -DDEBUG=1 -DUNITTEST $(COV)
-GFLAGS = $(WARNINGS) -D__near= -D__pascal= -fno-exceptions -O2
+GFLAGS = $(WARNINGS) -D__near= -D__pascal= -fno-exceptions -g -DDEBUG=1 -DUNITTEST $(COV)
+#GFLAGS = $(WARNINGS) -D__near= -D__pascal= -fno-exceptions -O2
 
 CFLAGS = $(GFLAGS) -I$(ROOT) -D__I86__=1 -DMARS=1 -DTARGET_OSX=1 -D_DH
 MFLAGS = $(GFLAGS) -I$C -I$(TK) -D__I86__=1 -DMARS=1 -DTARGET_OSX=1 -D_DH
Index: src/parse.c
===================================================================
--- src/parse.c    (revision 780)
+++ src/parse.c    (working copy)
@@ -2386,6 +2386,7 @@ Type *Parser::parseBasicType()
  *      t [expression .. expression]
  *      t function
  *      t delegate
+ *      t ref
  */
 
 Type *Parser::parseBasicType2(Type *t)
@@ -2399,6 +2400,14 @@ Type *Parser::parseBasicType2(Type *t)
                 t = new TypePointer(t);
                 nextToken();
                 continue;
+            
+            case TOKref:
+                // handle explicit reference marker for class:
+                //      Object ref
+                //      const(Object)ref
+                t = new TypeRefSuffix(t);
+                nextToken();
+                continue;
 
             case TOKlbracket:
                 // Handle []. Make sure things like
@@ -4463,6 +4472,10 @@ int Parser::isDeclarator(Token **pt, int *haveId, enum TOK endtok)
             //case TOKand:
                 t = peek(t);
                 continue;
+                
+            case TOKref:
+                t = peek(t);
+                continue;
 
             case TOKlbracket:
                 t = peek(t);
Index: src/statement.c
===================================================================
--- src/statement.c    (revision 780)
+++ src/statement.c    (working copy)
@@ -1536,7 +1536,7 @@ Lagain:
                     value = var;
                     /* Reference to immutable data should be marked as const
                      */
-                    if (var->storage_class & STCref && !tn->isMutable())
+                    if (var->storage_class & STCref && !tn->head()->isMutable())
                     {
                         var->storage_class |= STCconst;
                     }
@@ -3534,7 +3534,7 @@ Statement *ReturnStatement::semantic(Scope *sc)
 
         if (((TypeFunction *)fd->type)->isref && !fd->isCtorDeclaration())
         {   // Function returns a reference
-            if (tbret->isMutable())
+            if (tbret->head()->isMutable())
                 exp = exp->modifiableLvalue(sc, exp);
             else
                 exp = exp->toLvalue(sc, exp);
Index: src/typinf.c
===================================================================
--- src/typinf.c    (revision 780)
+++ src/typinf.c    (working copy)
@@ -239,8 +239,13 @@ void TypeInfoConstDeclaration::toDt(dt_t **pdt)
     //printf("TypeInfoConstDeclaration::toDt() %s\n", toChars());
     dtxoff(pdt, Type::typeinfoconst->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfo_Const
     dtsize_t(pdt, 0);                        // monitor
-    Type *tm = tinfo->mutableOf();
-    tm = tm->merge();
+    Type *tm;
+    if (tinfo->ty == Tclass)
+        tm = ((TypeClass *)tinfo)->sym->type;
+    else
+    {   tm = tinfo->mutableOf();
+        tm = tm->merge();
+    }
     tm->getTypeInfo(NULL);
     dtxoff(pdt, tm->vtinfo->toSymbol(), 0, TYnptr);
 }
@@ -250,8 +255,13 @@ void TypeInfoInvariantDeclaration::toDt(dt_t **pdt)
     //printf("TypeInfoInvariantDeclaration::toDt() %s\n", toChars());
     dtxoff(pdt, Type::typeinfoinvariant->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfo_Invariant
     dtsize_t(pdt, 0);                        // monitor
-    Type *tm = tinfo->mutableOf();
-    tm = tm->merge();
+    Type *tm;
+    if (tinfo->ty == Tclass)
+        tm = ((TypeClass *)tinfo)->sym->type;
+    else
+    {   tm = tinfo->mutableOf();
+        tm = tm->merge();
+    }
     tm->getTypeInfo(NULL);
     dtxoff(pdt, tm->vtinfo->toSymbol(), 0, TYnptr);
 }
@@ -261,8 +271,16 @@ void TypeInfoSharedDeclaration::toDt(dt_t **pdt)
     //printf("TypeInfoSharedDeclaration::toDt() %s\n", toChars());
     dtxoff(pdt, Type::typeinfoshared->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfo_Shared
     dtsize_t(pdt, 0);                        // monitor
-    Type *tm = tinfo->unSharedOf();
-    tm = tm->merge();
+    Type *tm;
+    if (tinfo->ty == Tclass)
+    {   tm = ((TypeClass *)tinfo)->sym->type;
+        if (tinfo->mod != MODshared) // other modifiers
+            tm = tm->addMod(tinfo->mod & ~MODshared);
+    }
+    else
+    {   tm = tinfo->unSharedOf();
+        tm = tm->merge();
+    }
     tm->getTypeInfo(NULL);
     dtxoff(pdt, tm->vtinfo->toSymbol(), 0, TYnptr);
 }
@@ -272,8 +290,13 @@ void TypeInfoWildDeclaration::toDt(dt_t **pdt)
     //printf("TypeInfoWildDeclaration::toDt() %s\n", toChars());
     dtxoff(pdt, Type::typeinfowild->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfo_Wild
     dtsize_t(pdt, 0);                        // monitor
-    Type *tm = tinfo->mutableOf();
-    tm = tm->merge();
+    Type *tm;
+    if (tinfo->ty == Tclass)
+        tm = ((TypeClass *)tinfo)->sym->type;
+    else
+    {   tm = tinfo->mutableOf();
+        tm = tm->merge();
+    }
     tm->getTypeInfo(NULL);
     dtxoff(pdt, tm->vtinfo->toSymbol(), 0, TYnptr);
 }
Index: test/compilable/objconst1.d
new file mode 100644
===================================================================
--- /dev/null    (revision 780)
+++ test/compilable/objconst1.d    (working copy)
@@ -0,0 +1,7 @@
+
+void main()
+{
+	const(Object)ref copy = new const(Object)ref;
+	const(Object) value = new const(Object)ref;
+	copy = value;
+}
\ No newline at end of file
Index: test/compilable/objconst2.d
new file mode 100644
===================================================================
--- /dev/null    (revision 780)
+++ test/compilable/objconst2.d    (working copy)
@@ -0,0 +1,7 @@
+
+void main()
+{
+	const(Object)ref[] copy = new const(Object)ref[12];
+	const(Object)[] value = new const(Object)ref[12];
+	copy[] = value[];
+}
\ No newline at end of file
Index: test/compilable/objconst3.d
new file mode 100644
===================================================================
--- /dev/null    (revision 780)
+++ test/compilable/objconst3.d    (working copy)
@@ -0,0 +1,10 @@
+
+void main()
+{
+	const(Object)ref[] objects = new const(Object)ref[12];
+	foreach (ref object; objects)
+	{
+		static assert(is(typeof(object) == const(Object)ref));
+		object = new Object;
+	}
+}
\ No newline at end of file
Index: test/compilable/objconst4.d
new file mode 100644
===================================================================
--- /dev/null    (revision 780)
+++ test/compilable/objconst4.d    (working copy)
@@ -0,0 +1,11 @@
+
+struct S
+{
+	const(Object)ref o;
+}
+
+void main()
+{
+	S s;
+	s.o = new Object;
+}
\ No newline at end of file
Index: test/compilable/objconst5.d
new file mode 100644
===================================================================
--- /dev/null    (revision 780)
+++ test/compilable/objconst5.d    (working copy)
@@ -0,0 +1,6 @@
+
+void main()
+{
+	auto o = cast(const(Object)ref)(new const(Object));
+	static assert(is(typeof(o) == const(Object)ref));
+}
\ No newline at end of file
Index: test/fail_compilation/objconst1fail.d
new file mode 100644
===================================================================
--- /dev/null    (revision 780)
+++ test/fail_compilation/objconst1fail.d    (working copy)
@@ -0,0 +1,7 @@
+
+void main()
+{
+	const(Object) copy;
+	const(Object) value;
+	copy = value;
+}
\ No newline at end of file
Index: test/fail_compilation/objconst2fail.d
new file mode 100644
===================================================================
--- /dev/null    (revision 780)
+++ test/fail_compilation/objconst2fail.d    (working copy)
@@ -0,0 +1,7 @@
+
+void main()
+{
+	const(Object)[] copy = new const(Object)ref[12];
+	const(Object)[] value = new const(Object)ref[12];
+	copy[] = value[];
+}
\ No newline at end of file
Index: test/runnable/objconst1unqual.d
new file mode 100644
===================================================================
--- /dev/null    (revision 780)
+++ test/runnable/objconst1unqual.d    (working copy)
@@ -0,0 +1,66 @@
+template Unqual(T)
+{
+    version (none) // Error: recursive alias declaration @@@BUG1308@@@
+    {
+             static if (is(T U ==     const U)) alias Unqual!U Unqual;
+        else static if (is(T U == immutable U)) alias Unqual!U Unqual;
+        else static if (is(T U ==    shared U)) alias Unqual!U Unqual;
+        else                                    alias        T Unqual;
+    }
+    else // workaround
+    {
+             static if (is(T U == shared(const U))) alias U Unqual;
+        else static if (is(T U ==        const U )) alias U Unqual;
+        else static if (is(T U ==    immutable U )) alias U Unqual;
+        else static if (is(T U ==       shared U )) alias U Unqual;
+        else                                        alias T Unqual;
+    }
+}
+
+//unittest
+//{
+//    static assert(is(Unqual!(int) == int));
+//    static assert(is(Unqual!(const int) == int));
+//    static assert(is(Unqual!(immutable int) == int));
+//    static assert(is(Unqual!(shared int) == int));
+//    static assert(is(Unqual!(shared(const int)) == int));
+//    alias immutable(int[]) ImmIntArr;
+//    static assert(is(Unqual!(ImmIntArr) == immutable(int)[]));
+	
+    static assert(is(Unqual!(const(Object)) == const(Object)ref));
+    static assert(is(Unqual!(const(Object ref)) == const(Object)ref));
+    static assert(is(Unqual!(const(immutable(Object)ref)) == immutable(Object)ref));
+    static assert(!is(Unqual!(const(Object)) == const(Object)));
+    static assert(!is(Unqual!(const(Object)) == Object));
+//}
+
+import std.stdio;
+
+alias const(Object)ref OO;
+
+void test(const(OO)ref o) {}
+
+int main()
+{
+	writeln((&test).mangleof);
+
+	writeln((const(Object)ref).stringof);
+	writeln((immutable(Object)ref).stringof);
+	writeln((shared(Object)ref).stringof);
+	writeln((const(Object)ref).mangleof);
+	writeln((immutable(Object)ref).mangleof);
+	writeln((shared(Object)ref).mangleof);
+	writeln(Object.mangleof);
+	assert((const(Object)ref).stringof == "const(Object)ref");
+	assert((immutable(Object)ref).stringof == "immutable(Object)ref");
+	assert((shared(Object)ref).stringof == "shared(Object)ref");
+	assert((const(Object)).stringof == "const(Object)");
+	assert((immutable(Object)).stringof == "immutable(Object)");
+	assert((shared(Object)).stringof == "shared(Object)");
+//	writeln((immutable(Object)ref).mangleof ~ " hello");
+	//writeln((shared(const(Object)ref)).stringof);
+	//writeln((shared(const(Object)ref[])*).stringof);
+	//assert((shared(const(Object)ref)).stringof == "shared(const(Object)ref)");
+	//assert((shared(const(Object)ref[])*).stringof == "shared(const(Object)ref[])*");
+	return 0;
+}
Index: test/runnable/objconst2typeinfo.d
new file mode 100644
===================================================================
--- /dev/null    (revision 780)
+++ test/runnable/objconst2typeinfo.d    (working copy)
@@ -0,0 +1,14 @@
+
+void main()
+{
+	// This tests wehther typeinfo was generated correctly.
+	typeid(const(Object)ref).toString();
+	typeid(immutable(Object)ref).toString();
+	typeid(shared(Object)ref).toString();
+	typeid(shared(const(Object))ref).toString();
+	typeid(inout(Object)ref).toString();
+	typeid(inout(shared(Object))ref).toString();
+	typeid(inout(shared(Object)ref)).toString();
+	typeid(const(shared(Object)ref)).toString();
+	typeid(shared(immutable(Object)ref)).toString();
+}
\ No newline at end of file
