[svn r76] Fixed: TypeInfo for structs.

Fixed: PostExp was unable to allocate storage for parameters.
Fixed: Many types of functions and delegates were broken.
Misc cleanups.
This commit is contained in:
Tomas Lindquist Olsen
2007-10-29 03:28:12 +01:00
parent 848ecbed0d
commit 4230f2ef11
12 changed files with 367 additions and 204 deletions

View File

@@ -98,7 +98,7 @@ struct AggregateDeclaration : ScopeDsymbol
bool llvmInProgress;
llvm::Type* llvmType;
llvm::Value* llvmVtbl;
llvm::Constant* llvmVtbl;
llvm::ConstantStruct* llvmConstVtbl;
llvm::Constant* llvmInitZ;
virtual void offsetToIndex(Type* t, unsigned os, std::vector<unsigned>& result); // converts a DMD field offsets to LLVM struct index vector

View File

@@ -540,7 +540,7 @@ struct TypeStruct : Type
type *toCtype();
llvm::Value* llvmInit;
llvm::Constant* llvmInit;
};
struct TypeEnum : Type
@@ -638,7 +638,7 @@ struct TypeClass : Type
Symbol *toSymbol();
llvm::Value* llvmInit;
llvm::Constant* llvmInit;
};
struct TypeTuple : Type

View File

@@ -116,6 +116,7 @@ elem* VarExp::toElem(IRState* p)
// _arguments
if (vd->ident == Id::_arguments)
{
Logger::println("Id::_arguments");
vd->llvmValue = p->func().decl->llvmArguments;
assert(vd->llvmValue);
e->mem = vd->llvmValue;
@@ -124,6 +125,7 @@ elem* VarExp::toElem(IRState* p)
// _argptr
else if (vd->ident == Id::_argptr)
{
Logger::println("Id::_argptr");
vd->llvmValue = p->func().decl->llvmArgPtr;
assert(vd->llvmValue);
e->mem = vd->llvmValue;
@@ -132,6 +134,7 @@ elem* VarExp::toElem(IRState* p)
// _dollar
else if (vd->ident == Id::dollar)
{
Logger::println("Id::dollar");
assert(!p->arrays.empty());
llvm::Value* tmp = LLVM_DtoGEPi(p->arrays.back(),0,0,"tmp",p->scopebb());
e->val = new llvm::LoadInst(tmp,"tmp",p->scopebb());
@@ -152,6 +155,7 @@ elem* VarExp::toElem(IRState* p)
}
// nested variable
else if (vd->nestedref) {
Logger::println("nested variable");
e->mem = LLVM_DtoNestedVariable(vd);
e->type = elem::VAR;
e->vardecl = vd;
@@ -159,7 +163,11 @@ elem* VarExp::toElem(IRState* p)
// function parameter
else if (vd->isParameter()) {
Logger::println("function param");
assert(vd->llvmValue);
if (!vd->llvmValue) {
// TODO: determine this properly
// this happens when the DMD frontend generates by pointer wrappers for struct opEquals(S) and opCmp(S)
vd->llvmValue = &p->func().func->getArgumentList().back();
}
if (vd->isRef() || vd->isOut()) {
e->mem = vd->llvmValue;
e->type = elem::VAR;
@@ -1432,18 +1440,27 @@ elem* SymOffExp::toElem(IRState* p)
assert(vd->llvmValue);
Type* t = LLVM_DtoDType(type);
Type* tnext = LLVM_DtoDType(t->next);
Type* vdtype = LLVM_DtoDType(vd->type);
llvm::Value* llvalue = vd->nestedref ? LLVM_DtoNestedVariable(vd) : vd->llvmValue;
if (vdtype->ty == Tstruct && !(t->ty == Tpointer && t->next == vdtype)) {
TypeStruct* vdt = (TypeStruct*)vdtype;
assert(vdt->sym);
e = new elem;
std::vector<unsigned> dst(1,0);
vdt->sym->offsetToIndex(t->next, offset, dst);
llvm::Value* ptr = llvalue;
assert(ptr);
e->mem = LLVM_DtoGEP(ptr,dst,"tmp");
bool donormally = true;
if (offset == 0) {
const llvm::Type* llt = LLVM_DtoType(t);
e->mem = p->ir->CreateBitCast(llvalue, llt, "tmp");
}
else {
std::vector<unsigned> dst(1,0);
vdt->sym->offsetToIndex(tnext, offset, dst);
llvm::Value* ptr = llvalue;
assert(ptr);
e->mem = LLVM_DtoGEP(ptr,dst,"tmp");
}
e->type = elem::VAL;
e->field = true;
}
@@ -2118,7 +2135,8 @@ elem* PostExp::toElem(IRState* p)
else
assert(post);
//llvm::Value* tostore = l->storeVal ? l->storeVal : l->val;
if (l->mem == 0)
LLVM_DtoGiveArgumentStorage(l);
new llvm::StoreInst(post,l->mem,p->scopebb());
delete l;

View File

@@ -151,7 +151,7 @@ const llvm::Type* LLVM_DtoType(Type* t)
case Tfunction:
{
if (t->llvmType == 0) {
return LLVM_DtoFunctionType(t);
return LLVM_DtoFunctionType(t,NULL);
}
else {
return t->llvmType;
@@ -188,94 +188,13 @@ const llvm::Type* LLVM_DtoType(Type* t)
//////////////////////////////////////////////////////////////////////////////////////////
const llvm::FunctionType* LLVM_DtoFunctionType(Type* t, const llvm::Type* thisparam)
const llvm::FunctionType* LLVM_DtoFunctionType(Type* type, const llvm::Type* thistype, bool ismain)
{
TypeFunction* f = (TypeFunction*)t;
// parameter types
const llvm::Type* rettype;
std::vector<const llvm::Type*> paramvec;
if (LLVM_DtoIsPassedByRef(f->next)) {
rettype = llvm::PointerType::get(LLVM_DtoType(f->next));
paramvec.push_back(rettype);
rettype = llvm::Type::VoidTy;
}
else {
Type* rt = f->next;
if (rt)
rettype = LLVM_DtoType(rt);
else
assert(0);
}
if (thisparam) {
paramvec.push_back(thisparam);
}
size_t n = Argument::dim(f->parameters);
for (int i=0; i < n; ++i) {
Argument* arg = Argument::getNth(f->parameters, i);
// ensure scalar
Type* argT = arg->type;
assert(argT);
paramvec.push_back(LLVM_DtoType(argT));
}
Logger::cout() << "Return type: " << *rettype << '\n';
llvm::FunctionType* functype = llvm::FunctionType::get(rettype, paramvec, f->varargs);
return functype;
}
//////////////////////////////////////////////////////////////////////////////////////////
static const llvm::FunctionType* LLVM_DtoVaFunctionType(FuncDeclaration* fdecl)
{
TypeFunction* f = (TypeFunction*)fdecl->type;
TypeFunction* f = (TypeFunction*)type;
assert(f != 0);
const llvm::PointerType* i8pty = llvm::PointerType::get(llvm::Type::Int8Ty);
std::vector<const llvm::Type*> args;
if (fdecl->llvmInternal == LLVMva_start) {
args.push_back(i8pty);
}
else if (fdecl->llvmInternal == LLVMva_intrinsic) {
size_t n = Argument::dim(f->parameters);
for (size_t i=0; i<n; ++i) {
args.push_back(i8pty);
}
}
else
assert(0);
const llvm::FunctionType* fty = llvm::FunctionType::get(llvm::Type::VoidTy, args, false);
f->llvmType = fty;
return fty;
}
//////////////////////////////////////////////////////////////////////////////////////////
const llvm::FunctionType* LLVM_DtoFunctionType(FuncDeclaration* fdecl)
{
if ((fdecl->llvmInternal == LLVMva_start) || (fdecl->llvmInternal == LLVMva_intrinsic)) {
return LLVM_DtoVaFunctionType(fdecl);
}
TypeFunction* f = (TypeFunction*)fdecl->type;
assert(f != 0);
// type has already been resolved
if (f->llvmType != 0) {
return llvm::cast<llvm::FunctionType>(f->llvmType);
}
bool typesafeVararg = false;
if (f->linkage == LINKd && f->varargs == 1) {
assert(fdecl->v_arguments);
Logger::println("v_arguments = %s", fdecl->v_arguments->toChars());
assert(fdecl->v_arguments->isParameter());
typesafeVararg = true;
}
@@ -286,11 +205,12 @@ const llvm::FunctionType* LLVM_DtoFunctionType(FuncDeclaration* fdecl)
bool retinptr = false;
bool usesthis = false;
if (fdecl->isMain()) {
if (ismain) {
rettype = llvm::Type::Int32Ty;
actualRettype = rettype;
}
else if (rt) {
else {
assert(rt);
if (LLVM_DtoIsPassedByRef(rt)) {
rettype = llvm::PointerType::get(LLVM_DtoType(rt));
actualRettype = llvm::Type::VoidTy;
@@ -301,9 +221,6 @@ const llvm::FunctionType* LLVM_DtoFunctionType(FuncDeclaration* fdecl)
actualRettype = rettype;
}
}
else {
assert(0);
}
// parameter types
std::vector<const llvm::Type*> paramvec;
@@ -313,21 +230,8 @@ const llvm::FunctionType* LLVM_DtoFunctionType(FuncDeclaration* fdecl)
paramvec.push_back(rettype);
}
if (fdecl->needThis()) {
if (AggregateDeclaration* ad = fdecl->isMember()) {
Logger::print("isMember = this is: %s\n", ad->type->toChars());
const llvm::Type* thisty = LLVM_DtoType(ad->type);
Logger::cout() << "this llvm type: " << *thisty << '\n';
if (llvm::isa<llvm::StructType>(thisty) || thisty == gIR->topstruct().recty.get())
thisty = llvm::PointerType::get(thisty);
paramvec.push_back(thisty);
usesthis = true;
}
else
assert(0);
}
else if (fdecl->isNested()) {
paramvec.push_back(llvm::PointerType::get(llvm::Type::Int8Ty));
if (thistype) {
paramvec.push_back(thistype);
usesthis = true;
}
@@ -396,7 +300,6 @@ const llvm::FunctionType* LLVM_DtoFunctionType(FuncDeclaration* fdecl)
bool isvararg = !typesafeVararg && f->varargs;
llvm::FunctionType* functype = llvm::FunctionType::get(actualRettype, paramvec, isvararg);
f->llvmType = functype;
f->llvmRetInPtr = retinptr;
f->llvmUsesThis = usesthis;
return functype;
@@ -404,6 +307,67 @@ const llvm::FunctionType* LLVM_DtoFunctionType(FuncDeclaration* fdecl)
//////////////////////////////////////////////////////////////////////////////////////////
static const llvm::FunctionType* LLVM_DtoVaFunctionType(FuncDeclaration* fdecl)
{
TypeFunction* f = (TypeFunction*)fdecl->type;
assert(f != 0);
const llvm::PointerType* i8pty = llvm::PointerType::get(llvm::Type::Int8Ty);
std::vector<const llvm::Type*> args;
if (fdecl->llvmInternal == LLVMva_start) {
args.push_back(i8pty);
}
else if (fdecl->llvmInternal == LLVMva_intrinsic) {
size_t n = Argument::dim(f->parameters);
for (size_t i=0; i<n; ++i) {
args.push_back(i8pty);
}
}
else
assert(0);
const llvm::FunctionType* fty = llvm::FunctionType::get(llvm::Type::VoidTy, args, false);
f->llvmType = fty;
return fty;
}
//////////////////////////////////////////////////////////////////////////////////////////
const llvm::FunctionType* LLVM_DtoFunctionType(FuncDeclaration* fdecl)
{
if ((fdecl->llvmInternal == LLVMva_start) || (fdecl->llvmInternal == LLVMva_intrinsic)) {
return LLVM_DtoVaFunctionType(fdecl);
}
// type has already been resolved
if (fdecl->type->llvmType != 0) {
return llvm::cast<llvm::FunctionType>(fdecl->type->llvmType);
}
const llvm::Type* thisty = NULL;
if (fdecl->needThis()) {
if (AggregateDeclaration* ad = fdecl->isMember()) {
Logger::print("isMember = this is: %s\n", ad->type->toChars());
thisty = LLVM_DtoType(ad->type);
Logger::cout() << "this llvm type: " << *thisty << '\n';
if (llvm::isa<llvm::StructType>(thisty) || thisty == gIR->topstruct().recty.get())
thisty = llvm::PointerType::get(thisty);
}
else
assert(0);
}
else if (fdecl->isNested()) {
thisty = llvm::PointerType::get(llvm::Type::Int8Ty);
}
const llvm::FunctionType* functype = LLVM_DtoFunctionType(fdecl->type, thisty, fdecl->isMain());
fdecl->type->llvmType = functype;
return functype;
}
//////////////////////////////////////////////////////////////////////////////////////////
const llvm::StructType* LLVM_DtoDelegateType(Type* t)
{
const llvm::Type* i8ptr = llvm::PointerType::get(llvm::Type::Int8Ty);

View File

@@ -11,7 +11,7 @@ llvm::Value* LLVM_DtoStructZeroInit(llvm::Value* v);
llvm::Value* LLVM_DtoStructCopy(llvm::Value* dst, llvm::Value* src);
llvm::Constant* LLVM_DtoConstStructInitializer(StructInitializer* si);
const llvm::FunctionType* LLVM_DtoFunctionType(Type* t, const llvm::Type* thisparam = 0);
const llvm::FunctionType* LLVM_DtoFunctionType(Type* t, const llvm::Type* thistype, bool ismain = false);
const llvm::FunctionType* LLVM_DtoFunctionType(FuncDeclaration* fdecl);
llvm::Function* LLVM_DtoDeclareFunction(FuncDeclaration* fdecl);

View File

@@ -296,7 +296,8 @@ void StructDeclaration::toObjFile()
gIR->structs.pop_back();
// generate typeinfo
//type->getTypeInfo(NULL);
if (getModule() == gIR->dmodule)
type->getTypeInfo(NULL);
}
/* ================================================================== */
@@ -624,8 +625,7 @@ void TypedefDeclaration::toObjFile()
LOG_SCOPE;
// generate typeinfo
if (!type->builtinTypeInfo())
type->getTypeInfo(NULL);
type->getTypeInfo(NULL);
}
/* ================================================================== */

View File

@@ -263,12 +263,6 @@ void TypeInfoDeclaration::toObjFile()
void TypeInfoDeclaration::toDt(dt_t **pdt)
{
assert(0 && "TypeInfoDeclaration");
/*
//printf("TypeInfoDeclaration::toDt() %s\n", toChars());
dtxoff(pdt, Type::typeinfo->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfo
dtdword(pdt, 0); // monitor
*/
}
/* ========================================================================= */
@@ -316,7 +310,6 @@ void TypeInfoTypedefDeclaration::toDt(dt_t **pdt)
if (tinfo->isZeroInit() || !sd->init) // 0 initializer, or the same as the base type
{
sinits.push_back(LLVM_DtoConstSlice(LLVM_DtoConstSize_t(0), llvm::ConstantPointerNull::get(initpt)));
//sinits.push_back(initZ->getOperand(3));
}
else
{
@@ -334,43 +327,6 @@ void TypeInfoTypedefDeclaration::toDt(dt_t **pdt)
llvm::GlobalVariable* gvar = new llvm::GlobalVariable(stype,true,llvm::GlobalValue::InternalLinkage,tiInit,toChars(),gIR->module);
llvmValue = gvar;
/*
dtxoff(pdt, Type::typeinfotypedef->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfo_Typedef
dtdword(pdt, 0); // monitor
assert(tinfo->ty == Ttypedef);
TypeTypedef *tc = (TypeTypedef *)tinfo;
TypedefDeclaration *sd = tc->sym;
//printf("basetype = %s\n", sd->basetype->toChars());
// Put out:
// TypeInfo base;
// char[] name;
// void[] m_init;
sd->basetype = sd->basetype->merge();
sd->basetype->getTypeInfo(NULL); // generate vtinfo
assert(sd->basetype->vtinfo);
dtxoff(pdt, sd->basetype->vtinfo->toSymbol(), 0, TYnptr); // TypeInfo for basetype
char *name = sd->toPrettyChars();
size_t namelen = strlen(name);
dtdword(pdt, namelen);
dtabytes(pdt, TYnptr, 0, namelen + 1, name);
// void[] init;
if (tinfo->isZeroInit() || !sd->init)
{ // 0 initializer, or the same as the base type
dtdword(pdt, 0); // init.length
dtdword(pdt, 0); // init.ptr
}
else
{
dtdword(pdt, sd->type->size()); // init.length
dtxoff(pdt, sd->toInitializer(), 0, TYnptr); // init.ptr
*/
}
/* ========================================================================= */
@@ -418,7 +374,6 @@ void TypeInfoEnumDeclaration::toDt(dt_t **pdt)
if (tinfo->isZeroInit() || !sd->defaultval) // 0 initializer, or the same as the base type
{
sinits.push_back(LLVM_DtoConstSlice(LLVM_DtoConstSize_t(0), llvm::ConstantPointerNull::get(initpt)));
//sinits.push_back(initZ->getOperand(3));
}
else
{
@@ -437,44 +392,6 @@ void TypeInfoEnumDeclaration::toDt(dt_t **pdt)
llvm::GlobalVariable* gvar = new llvm::GlobalVariable(stype,true,llvm::GlobalValue::InternalLinkage,tiInit,toChars(),gIR->module);
llvmValue = gvar;
/*
//printf("TypeInfoEnumDeclaration::toDt()\n");
dtxoff(pdt, Type::typeinfoenum->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfo_Enum
dtdword(pdt, 0); // monitor
assert(tinfo->ty == Tenum);
TypeEnum *tc = (TypeEnum *)tinfo;
EnumDeclaration *sd = tc->sym;
// Put out:
// TypeInfo base;
// char[] name;
// void[] m_init;
sd->memtype->getTypeInfo(NULL);
dtxoff(pdt, sd->memtype->vtinfo->toSymbol(), 0, TYnptr); // TypeInfo for enum members
char *name = sd->toPrettyChars();
size_t namelen = strlen(name);
dtdword(pdt, namelen);
dtabytes(pdt, TYnptr, 0, namelen + 1, name);
// void[] init;
if (tinfo->isZeroInit() || !sd->defaultval)
{ // 0 initializer, or the same as the base type
dtdword(pdt, 0); // init.length
dtdword(pdt, 0); // init.ptr
}
else
{
dtdword(pdt, sd->type->size()); // init.length
dtxoff(pdt, sd->toInitializer(), 0, TYnptr); // init.ptr
}
*/
}
/* ========================================================================= */
@@ -610,7 +527,166 @@ void TypeInfoDelegateDeclaration::toDt(dt_t **pdt)
void TypeInfoStructDeclaration::toDt(dt_t **pdt)
{
assert(0 && "TypeInfoStructDeclaration");
Logger::println("TypeInfoStructDeclaration::toDt() %s", toChars());
LOG_SCOPE;
assert(tinfo->ty == Tstruct);
TypeStruct *tc = (TypeStruct *)tinfo;
StructDeclaration *sd = tc->sym;
ClassDeclaration* base = Type::typeinfostruct;
base->toObjFile();
const llvm::StructType* stype = llvm::cast<llvm::StructType>(base->llvmType);
std::vector<llvm::Constant*> sinits;
sinits.push_back(base->llvmVtbl);
// char[] name
char *name = sd->toPrettyChars();
sinits.push_back(LLVM_DtoConstString(name));
assert(sinits.back()->getType() == stype->getElementType(1));
// void[] init
const llvm::PointerType* initpt = llvm::PointerType::get(llvm::Type::Int8Ty);
if (sd->zeroInit) // 0 initializer, or the same as the base type
{
sinits.push_back(LLVM_DtoConstSlice(LLVM_DtoConstSize_t(0), llvm::ConstantPointerNull::get(initpt)));
}
else
{
assert(sd->llvmInitZ);
size_t cisize = gTargetData->getTypeSize(tc->llvmType);
llvm::Constant* cicast = llvm::ConstantExpr::getBitCast(tc->llvmInit, initpt);
sinits.push_back(LLVM_DtoConstSlice(LLVM_DtoConstSize_t(cisize), cicast));
}
// toX functions ground work
FuncDeclaration *fd;
FuncDeclaration *fdx;
TypeFunction *tf;
Type *ta;
Dsymbol *s;
static TypeFunction *tftohash;
static TypeFunction *tftostring;
if (!tftohash)
{
Scope sc;
tftohash = new TypeFunction(NULL, Type::thash_t, 0, LINKd);
tftohash = (TypeFunction *)tftohash->semantic(0, &sc);
tftostring = new TypeFunction(NULL, Type::tchar->arrayOf(), 0, LINKd);
tftostring = (TypeFunction *)tftostring->semantic(0, &sc);
}
TypeFunction *tfeqptr;
{
Scope sc;
Arguments *arguments = new Arguments;
Argument *arg = new Argument(STCin, tc->pointerTo(), NULL, NULL);
arguments->push(arg);
tfeqptr = new TypeFunction(arguments, Type::tint32, 0, LINKd);
tfeqptr = (TypeFunction *)tfeqptr->semantic(0, &sc);
}
#if 0
TypeFunction *tfeq;
{
Scope sc;
Array *arguments = new Array;
Argument *arg = new Argument(In, tc, NULL, NULL);
arguments->push(arg);
tfeq = new TypeFunction(arguments, Type::tint32, 0, LINKd);
tfeq = (TypeFunction *)tfeq->semantic(0, &sc);
}
#endif
const llvm::PointerType* ptty = llvm::cast<llvm::PointerType>(stype->getElementType(3));
s = search_function(sd, Id::tohash);
fdx = s ? s->isFuncDeclaration() : NULL;
if (fdx)
{
fd = fdx->overloadExactMatch(tftohash);
if (fd) {
assert(fd->llvmValue != 0);
llvm::Constant* c = llvm::cast_or_null<llvm::Constant>(fd->llvmValue);
assert(c);
c = llvm::ConstantExpr::getBitCast(c, ptty);
sinits.push_back(c);
}
else {
//fdx->error("must be declared as extern (D) uint toHash()");
sinits.push_back(llvm::ConstantPointerNull::get(ptty));
}
}
else {
sinits.push_back(llvm::ConstantPointerNull::get(ptty));
}
s = search_function(sd, Id::eq);
fdx = s ? s->isFuncDeclaration() : NULL;
for (int i = 0; i < 2; i++)
{
ptty = llvm::cast<llvm::PointerType>(stype->getElementType(4+i));
if (fdx)
{
fd = fdx->overloadExactMatch(tfeqptr);
if (fd) {
assert(fd->llvmValue != 0);
llvm::Constant* c = llvm::cast_or_null<llvm::Constant>(fd->llvmValue);
assert(c);
c = llvm::ConstantExpr::getBitCast(c, ptty);
sinits.push_back(c);
}
else {
//fdx->error("must be declared as extern (D) int %s(%s*)", fdx->toChars(), sd->toChars());
sinits.push_back(llvm::ConstantPointerNull::get(ptty));
}
}
else {
sinits.push_back(llvm::ConstantPointerNull::get(ptty));
}
s = search_function(sd, Id::cmp);
fdx = s ? s->isFuncDeclaration() : NULL;
}
ptty = llvm::cast<llvm::PointerType>(stype->getElementType(6));
s = search_function(sd, Id::tostring);
fdx = s ? s->isFuncDeclaration() : NULL;
if (fdx)
{
fd = fdx->overloadExactMatch(tftostring);
if (fd) {
assert(fd->llvmValue != 0);
llvm::Constant* c = llvm::cast_or_null<llvm::Constant>(fd->llvmValue);
assert(c);
c = llvm::ConstantExpr::getBitCast(c, ptty);
sinits.push_back(c);
}
else {
//fdx->error("must be declared as extern (D) char[] toString()");
sinits.push_back(llvm::ConstantPointerNull::get(ptty));
}
}
else {
sinits.push_back(llvm::ConstantPointerNull::get(ptty));
}
// uint m_flags;
sinits.push_back(LLVM_DtoConstUint(tc->hasPointers()));
// create the symbol
llvm::Constant* tiInit = llvm::ConstantStruct::get(stype, sinits);
llvm::GlobalVariable* gvar = new llvm::GlobalVariable(stype,true,llvm::GlobalValue::InternalLinkage,tiInit,toChars(),gIR->module);
llvmValue = gvar;
/*
//printf("TypeInfoStructDeclaration::toDt() '%s'\n", toChars());

View File

@@ -937,6 +937,8 @@ class TypeInfo_Interface : TypeInfo
ClassInfo info;
}
+/
class TypeInfo_Struct : TypeInfo
{
char[] toString() { return name; }
@@ -987,7 +989,7 @@ class TypeInfo_Struct : TypeInfo
return c;
}
int compare(void *p2, void *p1)
int compare(void *p1, void *p2)
{
int c = 0;
@@ -1029,6 +1031,8 @@ class TypeInfo_Struct : TypeInfo
uint m_flags;
}
/+
class TypeInfo_Tuple : TypeInfo
{
TypeInfo[] elements;

12
test/bug38.d Normal file
View File

@@ -0,0 +1,12 @@
module bug38;
void func(int* p)
{
p++;
}
void main()
{
int i;
func(&i);
}

13
test/bug39.d Normal file
View File

@@ -0,0 +1,13 @@
module bug39;
struct S
{
long l;
}
void main()
{
S s;
s.l = 23;
void* p = &s;
}

12
test/bug40.d Normal file
View File

@@ -0,0 +1,12 @@
module bug40;
char[] func(void* p)
{
return null;
}
void main()
{
char[] function(void*) fp = &func;
assert(fp(null) is null);
}

64
test/typeinfo10.d Normal file
View File

@@ -0,0 +1,64 @@
module typeinfo10;
struct S
{
long l;
float f;
void* vp;
hash_t toHash()
{
return l + cast(size_t)f;
}
int opEquals(S s)
{
return (s.l == l) && (s.f == f);
}
int opCmp(S a)
{
if (l == a.l) {
return (f < a.f) ? -1 : (f > a.f) ? 1 : 0;
}
return (l < a.l) ? -1 : 1;
}
char[] toString()
{
return "S instance";
}
}
void main()
{
S s=S(-1, 0);
S t=S(-1, 1);
S u=S(11,-1);
S v=S(12,13);
{
assert(s == s);
assert(s != t);
assert(s != v);
assert(s < t);
assert(u > s);
assert(v > u);
}
{
auto ti = typeid(S);
assert(ti.getHash(&s) == s.toHash());
assert(ti.equals(&s,&s));
assert(!ti.equals(&s,&t));
assert(!ti.equals(&s,&v));
assert(ti.compare(&s,&s) == 0);
assert(ti.compare(&s,&t) < 0);
assert(ti.compare(&u,&s) > 0);
assert(ti.compare(&v,&u) > 0);
{
auto tis = cast(TypeInfo_Struct)ti;
assert(tis.xtoString(&s) == s.toString());
}
}
}