changeset 6:35d93ce68cf4 trunk

[svn r10] Updated for LLVM rev. 20070913 Applied fixes from wilsonk on the forum Some tweaks to work with gc 7.0 Fixed aggregate members of aggregates Fixed cyclic/recursive class declarations Other minor tweaks
author lindquist
date Wed, 26 Sep 2007 19:05:18 +0200
parents 3d60e549b0c2
children 7a155ba88c53
files dmd/mem.c gen/arrays.c gen/irstate.c gen/irstate.h gen/toir.c gen/tollvm.c gen/tollvm.h gen/toobj.c test/classes5.d test/typeinfo.d
diffstat 10 files changed, 118 insertions(+), 54 deletions(-) [+]
line wrap: on
line diff
--- a/dmd/mem.c	Wed Sep 05 07:16:31 2007 +0200
+++ b/dmd/mem.c	Wed Sep 26 19:05:18 2007 +0200
@@ -6,7 +6,8 @@
 #include <stdlib.h>
 #include <string.h>
 
-#include "gc.h"
+// I needed to perfix the dir after upgrading to gc 7.0
+#include "gc/gc.h"
 
 #include "mem.h"
 
@@ -14,10 +15,12 @@
  */
 
 Mem mem;
+static bool gc_was_init = false;
 
 void Mem::init()
 {
     GC_init();
+    gc_was_init = true;
 }
 
 char *Mem::strdup(const char *s)
@@ -127,7 +130,11 @@
 /* =================================================== */
 
 void * operator new(size_t m_size)
-{   
+{
+    // without this we segfault with gc 7.0
+    if (!gc_was_init) {
+        mem.init();
+    }
     void *p = GC_malloc(m_size);
     if (p)
 	return p;
--- a/gen/arrays.c	Wed Sep 05 07:16:31 2007 +0200
+++ b/gen/arrays.c	Wed Sep 26 19:05:18 2007 +0200
@@ -133,11 +133,11 @@
         llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
         llvm::Value* one = llvm::ConstantInt::get(llvm::Type::Int32Ty, 1, false);
 
-        llvm::Value* dstlen = new llvm::GetElementPtrInst(dst,zero,zero,"tmp",gIR->scopebb());
+        llvm::Value* dstlen = LLVM_DtoGEP(dst,zero,zero,"tmp",gIR->scopebb());
         llvm::Value* srclen = llvm::ConstantInt::get(LLVM_DtoSize_t(), arrty->getNumElements(), false);
         new llvm::StoreInst(srclen, dstlen, gIR->scopebb());
 
-        llvm::Value* dstptr = new llvm::GetElementPtrInst(dst,zero,one,"tmp",gIR->scopebb());
+        llvm::Value* dstptr = LLVM_DtoGEP(dst,zero,one,"tmp",gIR->scopebb());
         llvm::Value* srcptr = new llvm::BitCastInst(src,dstty,"tmp",gIR->scopebb());
         new llvm::StoreInst(srcptr, dstptr, gIR->scopebb());
     }
@@ -155,7 +155,7 @@
 
         std::vector<llvm::Value*> args;
         args.resize(3);
-        args[0] = new llvm::GetElementPtrInst(l,zero,zero,"tmp",gIR->scopebb());
+        args[0] = LLVM_DtoGEP(l,zero,zero,"tmp",gIR->scopebb());
         args[1] = llvm::ConstantInt::get(LLVM_DtoSize_t(), arrty->getNumElements(), false);
         args[2] = r;
         
@@ -225,10 +225,10 @@
     llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
     llvm::Value* one = llvm::ConstantInt::get(llvm::Type::Int32Ty, 1, false);
 
-    llvm::Value* arrdim = new llvm::GetElementPtrInst(arr,zero,zero,"tmp",gIR->scopebb());
+    llvm::Value* arrdim = LLVM_DtoGEP(arr,zero,zero,"tmp",gIR->scopebb());
     new llvm::StoreInst(dim, arrdim, gIR->scopebb());
     
-    llvm::Value* arrptr = new llvm::GetElementPtrInst(arr,zero,one,"tmp",gIR->scopebb());
+    llvm::Value* arrptr = LLVM_DtoGEP(arr,zero,one,"tmp",gIR->scopebb());
     new llvm::StoreInst(ptr, arrptr, gIR->scopebb());
 }
 
--- a/gen/irstate.c	Wed Sep 05 07:16:31 2007 +0200
+++ b/gen/irstate.c	Wed Sep 26 19:05:18 2007 +0200
@@ -99,7 +99,7 @@
     type = 0;
 }
 
-IRStruct::IRStruct(TypeStruct* t)
+IRStruct::IRStruct(Type* t)
  : recty(llvm::OpaqueType::get())
 {
     type = t;
--- a/gen/irstate.h	Wed Sep 05 07:16:31 2007 +0200
+++ b/gen/irstate.h	Wed Sep 26 19:05:18 2007 +0200
@@ -36,7 +36,7 @@
     IRScope(llvm::BasicBlock* b, llvm::BasicBlock* e);
 };
 
-// represents a struct
+// represents a struct or class
 struct IRStruct : Object
 {
     typedef std::vector<const llvm::Type*> TypeVector;
@@ -45,21 +45,15 @@
 
 public:
     IRStruct();
-    IRStruct(TypeStruct*);
+    IRStruct(Type*);
     virtual ~IRStruct();
 
-    TypeStruct* type;
+    Type* type;
     TypeVector fields;
     ConstantVector inits;
     llvm::PATypeHolder recty;
 };
 
-// represents a clas
-struct IRClass : Object
-{
-    // TODO
-};
-
 // represents the module
 struct IRState : Object
 {
--- a/gen/toir.c	Wed Sep 05 07:16:31 2007 +0200
+++ b/gen/toir.c	Wed Sep 26 19:05:18 2007 +0200
@@ -101,7 +101,8 @@
             if (!p->arrays.empty())
             {
                 llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
-                llvm::Value* tmp = new llvm::GetElementPtrInst(p->arrays.back(),zero,zero,"tmp",p->scopebb());
+                //llvm::Value* tmp = new llvm::GetElementPtrInst(p->arrays.back(),zero,zero,"tmp",p->scopebb());
+                llvm::Value* tmp = LLVM_DtoGEP(p->arrays.back(),zero,zero,"tmp",p->scopebb());
                 e->val = new llvm::LoadInst(tmp,"tmp",p->scopebb());
                 e->type = elem::VAL;
             }
@@ -205,7 +206,13 @@
     Logger::print("RealExp::toElem: %s | %s\n", toChars(), type->toChars());
     LOG_SCOPE;
     elem* e = new elem;
-    e->val = llvm::ConstantFP::get(LLVM_DtoType(type),value);
+    const llvm::Type* fty = LLVM_DtoType(type);
+    if (type->ty == Tfloat32)
+        e->val = llvm::ConstantFP::get(fty,float(value));
+    else if (type->ty == Tfloat64 || type->ty == Tfloat80)
+        e->val = llvm::ConstantFP::get(fty,double(value));
+    else
+    assert(0);
     e->type = elem::CONST;
     return e;
 }
@@ -251,7 +258,7 @@
     llvm::GlobalVariable* gvar = new llvm::GlobalVariable(at,true,_linkage,_init,"stringliteral",gIR->module);
 
     llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
-    llvm::Value* arrptr = new llvm::GetElementPtrInst(gvar,zero,zero,"tmp",p->scopebb());
+    llvm::Value* arrptr = LLVM_DtoGEP(gvar,zero,zero,"tmp",p->scopebb());
 
     elem* e = new elem;
 
@@ -435,7 +442,7 @@
             TypeStruct* ts = (TypeStruct*)e1->type->next;
             llvm::Value* offset = llvm::ConstantInt::get(llvm::Type::Int32Ty, ts->sym->offsetToIndex(cofs->getZExtValue()), false);
 
-            e->mem = new llvm::GetElementPtrInst(l->getValue(), zero, offset, "tmp", p->scopebb());
+            e->mem = LLVM_DtoGEP(l->getValue(), zero, offset, "tmp", p->scopebb());
             e->type = elem::VAR;
             e->field = true;
         }
@@ -806,7 +813,7 @@
         }
         // struct pointer - delegate
         else if (llvm::isa<llvm::StructType>(funcval->getType()->getContainedType(0))) {
-            funcval = new llvm::GetElementPtrInst(funcval,zero,one,"tmp",p->scopebb());
+            funcval = LLVM_DtoGEP(funcval,zero,one,"tmp",p->scopebb());
             funcval = new llvm::LoadInst(funcval,"tmp",p->scopebb());
             const llvm::Type* ty = funcval->getType()->getContainedType(0);
             llfnty = llvm::cast<llvm::FunctionType>(ty);
@@ -865,7 +872,7 @@
     // delegate context parameter
     else if (delegateCall) {
         Logger::println("Delegate Call");
-        llvm::Value* contextptr = new llvm::GetElementPtrInst(fn->mem,zero,zero,"tmp",p->scopebb());
+        llvm::Value* contextptr = LLVM_DtoGEP(fn->mem,zero,zero,"tmp",p->scopebb());
         llargs[j] = new llvm::LoadInst(contextptr,"tmp",p->scopebb());
         ++j;
         ++argiter;
@@ -1039,7 +1046,7 @@
             assert(from->next == to->next);
             llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
             llvm::Value* one = llvm::ConstantInt::get(llvm::Type::Int32Ty, 1, false);
-            llvm::Value* ptr = new llvm::GetElementPtrInst(u->getValue(),zero,one,"tmp",p->scopebb());
+            llvm::Value* ptr = LLVM_DtoGEP(u->getValue(),zero,one,"tmp",p->scopebb());
             e->val = new llvm::LoadInst(ptr, "tmp", p->scopebb());
             e->type = elem::VAL;
         }
@@ -1067,10 +1074,10 @@
                 else {
                     llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
                     llvm::Value* one = llvm::ConstantInt::get(llvm::Type::Int32Ty, 1, false);
-                    e->arg = new llvm::GetElementPtrInst(uval,zero,zero,"tmp",p->scopebb());
+                    e->arg = LLVM_DtoGEP(uval,zero,zero,"tmp",p->scopebb());
                     e->arg = new llvm::LoadInst(e->arg, "tmp", p->scopebb());
 
-                    e->mem = new llvm::GetElementPtrInst(uval,zero,one,"tmp",p->scopebb());
+                    e->mem = LLVM_DtoGEP(uval,zero,one,"tmp",p->scopebb());
                     e->mem = new llvm::LoadInst(e->mem, "tmp", p->scopebb());
                     //Logger::cout() << *e->mem->getType() << '|' << *ptrty << '\n';
                     e->mem = new llvm::BitCastInst(e->mem, ptrty, "tmp", p->scopebb());
@@ -1124,7 +1131,7 @@
             //const llvm::Type* _typ = llvm::GetElementPtrInst::getIndexedType(LLVM_DtoType(type), idx1);
             llvm::Value* ptr = vd->llvmValue;
             assert(ptr);
-            e->mem = new llvm::GetElementPtrInst(ptr,idx0,idx1,"tmp",p->scopebb());
+            e->mem = LLVM_DtoGEP(ptr,idx0,idx1,"tmp",p->scopebb());
             e->type = elem::VAL;
             e->field = true;
         }
@@ -1135,7 +1142,7 @@
             e = new elem;
             llvm::Value* idx0 = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
             //llvm::Value* idx1 = llvm::ConstantInt::get(llvm::Type::Int32Ty, 1, false);
-            e->mem = new llvm::GetElementPtrInst(vd->llvmValue,idx0,idx0,"tmp",p->scopebb());
+            e->mem = LLVM_DtoGEP(vd->llvmValue,idx0,idx0,"tmp",p->scopebb());
             e->type = elem::VAL;
         }
         else if (offset == 0) {
@@ -1222,7 +1229,7 @@
         assert(src != 0);
         llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
         llvm::Value* offset = llvm::ConstantInt::get(llvm::Type::Int32Ty, vdoffset, false);
-        llvm::Value* arrptr = new llvm::GetElementPtrInst(src,zero,offset,"tmp",p->scopebb());
+        llvm::Value* arrptr = LLVM_DtoGEP(src,zero,offset,"tmp",p->scopebb());
         e->mem = arrptr;
         Logger::cout() << "mem: " << *e->mem << '\n';
         e->type = elem::VAR;
@@ -1246,10 +1253,10 @@
 
             llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
             llvm::Value* vtblidx = llvm::ConstantInt::get(llvm::Type::Int32Ty, (size_t)fdecl->vtblIndex, false);
-            funcval = new llvm::GetElementPtrInst(e->arg, zero, zero, "tmp", p->scopebb());
+            funcval = LLVM_DtoGEP(e->arg, zero, zero, "tmp", p->scopebb());
             funcval = new llvm::LoadInst(funcval,"tmp",p->scopebb());
             funcval = new llvm::BitCastInst(funcval, vtbltype, "tmp", p->scopebb());
-            funcval = new llvm::GetElementPtrInst(funcval, zero, vtblidx, "tmp", p->scopebb());
+            funcval = LLVM_DtoGEP(funcval, zero, vtblidx, "tmp", p->scopebb());
             funcval = new llvm::LoadInst(funcval,"tmp",p->scopebb());
             funcval = new llvm::BitCastInst(funcval, fdecl->llvmValue->getType(), "tmp", p->scopebb());
         }
@@ -1337,7 +1344,7 @@
         for (unsigned i=0; i<n; ++i)
         {
             llvm::Value* offset = llvm::ConstantInt::get(llvm::Type::Int32Ty, i, false);
-            llvm::Value* arrptr = new llvm::GetElementPtrInst(sptr,zero,offset,"tmp",p->scopebb());
+            llvm::Value* arrptr = LLVM_DtoGEP(sptr,zero,offset,"tmp",p->scopebb());
 
             Expression* vx = (Expression*)elements->data[i];
             if (vx != 0) {
@@ -1380,10 +1387,10 @@
         arrptr = new llvm::GetElementPtrInst(l->getValue(),r->getValue(),"tmp",p->scopebb());
     }
     else if (e1->type->ty == Tsarray) {
-        arrptr = new llvm::GetElementPtrInst(l->mem, zero, r->getValue(),"tmp",p->scopebb());
+        arrptr = LLVM_DtoGEP(l->mem, zero, r->getValue(),"tmp",p->scopebb());
     }
     else if (e1->type->ty == Tarray) {
-        arrptr = new llvm::GetElementPtrInst(l->mem,zero,one,"tmp",p->scopebb());
+        arrptr = LLVM_DtoGEP(l->mem,zero,one,"tmp",p->scopebb());
         arrptr = new llvm::LoadInst(arrptr,"tmp",p->scopebb());
         arrptr = new llvm::GetElementPtrInst(arrptr,r->getValue(),"tmp",p->scopebb());
     }
@@ -1431,7 +1438,7 @@
                 e->mem = v->getValue();
             }
             else if (e1->type->ty == Tarray) {
-                llvm::Value* tmp = new llvm::GetElementPtrInst(v->mem,zero,one,"tmp",p->scopebb());
+                llvm::Value* tmp = LLVM_DtoGEP(v->mem,zero,one,"tmp",p->scopebb());
                 e->mem = new llvm::LoadInst(tmp,"tmp",p->scopebb());
             }
             else
@@ -1444,7 +1451,7 @@
         }
         else
         {
-            llvm::Value* tmp = new llvm::GetElementPtrInst(v->mem,zero,one,"tmp",p->scopebb());
+            llvm::Value* tmp = LLVM_DtoGEP(v->mem,zero,one,"tmp",p->scopebb());
             tmp = new llvm::LoadInst(tmp,"tmp",p->scopebb());
             e->mem = new llvm::GetElementPtrInst(tmp,lo->getValue(),"tmp",p->scopebb());
         }
@@ -1834,7 +1841,7 @@
         llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
         llvm::Value* one = llvm::ConstantInt::get(llvm::Type::Int32Ty, 1, false);
         
-        llvm::Value* ptr = new llvm::GetElementPtrInst(ldval,zero,one,"tmp",p->scopebb());
+        llvm::Value* ptr = LLVM_DtoGEP(ldval,zero,one,"tmp",p->scopebb());
         ptr = new llvm::LoadInst(ptr,"tmp",p->scopebb());
         new llvm::FreeInst(ptr, p->scopebb());
         LLVM_DtoNullArray(val);
@@ -1860,7 +1867,7 @@
     elem* u = e1->toElem(p);
 
     llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
-    llvm::Value* ptr = new llvm::GetElementPtrInst(u->mem,zero,zero,"tmp",p->scopebb());
+    llvm::Value* ptr = LLVM_DtoGEP(u->mem,zero,zero,"tmp",p->scopebb());
     e->val = new llvm::LoadInst(ptr, "tmp", p->scopebb());
     e->type = elem::VAL;
 
@@ -2086,11 +2093,11 @@
 
     llvm::Value* lval = p->toplval();
 
-    llvm::Value* context = new llvm::GetElementPtrInst(lval,zero,zero,"tmp",p->scopebb());
+    llvm::Value* context = LLVM_DtoGEP(lval,zero,zero,"tmp",p->scopebb());
     llvm::Value* castcontext = new llvm::BitCastInst(u->getValue(),int8ptrty,"tmp",p->scopebb());
     new llvm::StoreInst(castcontext, context, p->scopebb());
     
-    llvm::Value* fptr = new llvm::GetElementPtrInst(lval,zero,one,"tmp",p->scopebb());
+    llvm::Value* fptr = LLVM_DtoGEP(lval,zero,one,"tmp",p->scopebb());
     
     assert(func->llvmValue);
     llvm::Value* castfptr = new llvm::BitCastInst(func->llvmValue,fptr->getType()->getContainedType(0),"tmp",p->scopebb());
--- a/gen/tollvm.c	Wed Sep 05 07:16:31 2007 +0200
+++ b/gen/tollvm.c	Wed Sep 26 19:05:18 2007 +0200
@@ -99,15 +99,23 @@
     case Tclass:    {
         if (t->llvmType == 0)
         {
+            // recursive or cyclic declaration
+            if (!gIR->structs.empty())
+            {
+                IRStruct* found = 0;
+                for (IRState::StructVector::iterator i=gIR->structs.begin(); i!=gIR->structs.end(); ++i)
+                {
+                    if (t == i->type)
+                    {
+                        return llvm::PointerType::get(i->recty.get());
+                    }
+                }
+            }
+
+            // forward declaration
             TypeClass* tc = (TypeClass*)t;
             assert(tc->sym);
-            if (!tc->sym->llvmInProgress) {
-                tc->sym->toObjFile();
-            }
-            else {
-                //assert(0 && "circular class referencing");
-                return llvm::OpaqueType::get();
-            }
+            tc->sym->toObjFile();
         }
         return llvm::PointerType::get(t->llvmType);
     }
@@ -122,7 +130,7 @@
             return t->llvmType;
         }
     }
-    
+
     // delegates
     case Tdelegate:
     {
@@ -803,3 +811,11 @@
     }
     return _init;
 }
+
+llvm::Value* LLVM_DtoGEP(llvm::Value* ptr, llvm::Value* i0, llvm::Value* i1, const std::string& var, llvm::BasicBlock* bb)
+{
+    std::vector<llvm::Value*> v(2);
+    v[0] = i0;
+    v[1] = i1;
+    return new llvm::GetElementPtrInst(ptr, v.begin(), v.end(), var, bb);
+}
--- a/gen/tollvm.h	Wed Sep 05 07:16:31 2007 +0200
+++ b/gen/tollvm.h	Wed Sep 26 19:05:18 2007 +0200
@@ -36,4 +36,6 @@
 llvm::Function* LLVM_DeclareMemCpy32();
 llvm::Function* LLVM_DeclareMemCpy64();
 
+llvm::Value* LLVM_DtoGEP(llvm::Value* ptr, llvm::Value* i0, llvm::Value* i1, const std::string& var, llvm::BasicBlock* bb);
+
 #include "enums.h"
--- a/gen/toobj.c	Wed Sep 05 07:16:31 2007 +0200
+++ b/gen/toobj.c	Wed Sep 26 19:05:18 2007 +0200
@@ -48,18 +48,21 @@
     Logger::cout() << "Generating module: " << (md ? md->toChars() : toChars()) << '\n';
     LOG_SCOPE;
 
+    // start by deleting the old object file
     deleteObjFile();
 
+    // creaet a new ir state
     IRState ir;
     gIR = &ir;
-
     ir.dmodule = this;
 
+    // name the module
     std::string mname(toChars());
     if (md != 0)
         mname = md->toChars();
     ir.module = new llvm::Module(mname);
 
+    // set target stuff
     std::string target_triple(global.params.tt_arch);
     target_triple.append(global.params.tt_os);
     ir.module->setTargetTriple(target_triple);
@@ -67,6 +70,7 @@
 
     gTargetData = new llvm::TargetData(ir.module);
 
+    // process module members
     for (int k=0; k < members->dim; k++) {
         Dsymbol* dsym = (Dsymbol*)(members->data[k]);
         assert(dsym);
@@ -76,6 +80,7 @@
     delete gTargetData;
     gTargetData = 0;
 
+    // verify the llvm
     std::string verifyErr;
     if (llvm::verifyModule(*ir.module,llvm::ReturnStatusAction,&verifyErr))
     {
@@ -83,6 +88,7 @@
         fatal();
     }
 
+    // emit the llvm main function if necessary
     if (ir.emitMain) {
         LLVM_DtoMain();
     }
@@ -97,6 +103,7 @@
         ir.module->print(os);
     }*/
 
+    // write bytecode
     //if (global.params.llvmBC) {
         Logger::println("Writing LLVM bitcode\n");
         std::ofstream os(bcfile->name->toChars(), std::ios::binary);
@@ -131,6 +138,7 @@
 
 /* ================================================================== */
 
+/// Returns the LLVM style index from a DMD style offset
 unsigned AggregateDeclaration::offsetToIndex(unsigned os)
 {
     for (unsigned i=0; i<fields.dim; ++i) {
@@ -165,6 +173,8 @@
     return (unsigned)-1;
 }
 
+/// Returns the LLVM style index from a DMD style offset
+/// Handles class inheritance
 unsigned ClassDeclaration::offsetToIndex(unsigned os)
 {
     unsigned idx = 0;
@@ -308,7 +318,7 @@
     Logger::print("ClassDeclaration::toObjFile(%d): %s\n", fdi++, toChars());
     LOG_SCOPE;
 
-    gIR->structs.push_back(IRStruct());
+    gIR->structs.push_back(IRStruct(ts));
     gIR->classes.push_back(this);
     gIR->classmethods.push_back(IRState::FuncDeclVec());
     gIR->queueClassMethods.push_back(true);
@@ -328,6 +338,14 @@
     }
 
     llvm::StructType* structtype = llvm::StructType::get(gIR->topstruct().fields);
+    // refine abstract types for stuff like: class C {C next;}
+    if (gIR->topstruct().recty != 0)
+    {
+        llvm::PATypeHolder& pa = gIR->topstruct().recty;
+        llvm::cast<llvm::OpaqueType>(pa.get())->refineAbstractTypeTo(structtype);
+        structtype = llvm::cast<llvm::StructType>(pa.get());
+    }
+
     ts->llvmType = structtype;
     llvmType = structtype;
 
@@ -527,6 +545,12 @@
                 std::vector<llvm::Constant*> vals(n,_init);
                 _init = llvm::ConstantArray::get(arrty, vals);
             }
+            else if (llvm::isa<llvm::StructType>(_type)) {
+                const llvm::StructType* structty = llvm::cast<llvm::StructType>(_type);
+                TypeStruct* ts = (TypeStruct*)type;
+                assert(ts->sym->llvmInitZ);
+                _init = ts->sym->llvmInitZ;
+            }
             else
             assert(0);
         }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/classes5.d	Wed Sep 26 19:05:18 2007 +0200
@@ -0,0 +1,17 @@
+module classes5;
+
+struct S
+{
+    long l;
+}
+
+class C
+{
+    C c;
+    S s;
+}
+
+void main()
+{
+    //C c = new C;
+}
--- a/test/typeinfo.d	Wed Sep 05 07:16:31 2007 +0200
+++ b/test/typeinfo.d	Wed Sep 26 19:05:18 2007 +0200
@@ -1,9 +1,6 @@
 module typeinfo;
 
-typedef int int_t;
-
 void main()
 {
-    int_t i;
-    i += 3;
+    auto ti = typeid(int);
 }