static void check_dereference(expression result, type dereferenced, const char *errorstring) { if (type_pointer(dereferenced)) { type t = type_points_to(dereferenced); result->type = t; #if 0 if (TYPE_SIZE (t) == 0 && TREE_CODE (t) != ARRAY_TYPE) { error ("dereferencing pointer to incomplete type"); return error_mark_node; } #endif if (type_void(t) && unevaluated_expression == 0) warning("dereferencing `void *' pointer"); result->side_effects |= type_volatile(t) || flag_volatile; } else { result->type = error_type; if (dereferenced != error_type) error("invalid type argument of `%s'", errorstring); } result->lvalue = TRUE; }
type *TypeClass::toCtype() { //printf("TypeClass::toCtype() %s\n", toChars()); if (ctype) return ctype; type *t = type_struct_class(sym->toPrettyChars(), sym->alignsize, sym->structsize, NULL, NULL, false, true, true); ctype = type_pointer(t); /* Add in fields of the class * (after setting ctype to avoid infinite recursion) */ if (global.params.symdebug) for (size_t i = 0; i < sym->fields.dim; i++) { VarDeclaration *v = sym->fields[i]; symbol_struct_addField(t->Ttag, v->ident->toChars(), v->type->toCtype(), v->offset); } if (0 && global.params.symdebug) sym->toDebug(); return ctype; }
type *TypePointer::toCtype() { //printf("TypePointer::toCtype() %s\n", toChars()); if (!ctype) ctype = type_pointer(next->toCtype()); if (!ctype->Tnext) ctype->Tnext = next->toCtype(); // assume recursion checked elsewhere return ctype; }
static bool pointerint_conditional(type t1, type t2, expression e2) { if (type_pointer(t1) && type_integer(t2)) { if (!definite_zero(e2)) pedwarn("pointer/integer type mismatch in conditional expression"); return TRUE; } return FALSE; }
STATIC void cpp_this_type(type *tfunc,Classsym *stag) { type *t; type_debug(tfunc); symbol_debug(stag); #if MARS t = type_pointer(stag->Stype); #else t = cpp_thistype(tfunc,stag); #endif //cpp_data_indirect_type(t); cpp_ecsu_data_indirect_type(t); type_free(t); }
expression build_function_call(region r, location loc, expression fn, expression arglist) { expression result = CAST(expression, new_function_call(r, loc, fn, arglist, NULL, normal_call)); type fntype = type_default_conversion(fn->type), rettype; if (type_pointer(fntype)) /* All function types come this way because default_conversion makes them into pointers to functions... */ fntype = type_points_to(fntype); rettype = type_function_return_type(fntype); result->type = rettype; result->cst = fold_function_call(result, 0); return result; }
static void dump_type(type t) { if (type_complex(t)) { printf("C"); t = make_base_type(t); } if (type_network_base_type(t)) printf("N%s", type_networkdef(t)->name); /* Enums treated as ints for now */ else if (type_integer(t)) if (type_unsigned(t)) printf("U"); else printf("I"); else if (type_float(t)) printf("F"); else if (type_double(t)) printf("D"); else if (type_long_double(t)) printf("LD"); else if (type_union(t)) if (type_network(t)) printf("ANU"); else printf("AU"); else if (type_struct(t)) if (type_network(t)) printf("ANS"); else printf("AS"); else if (type_pointer(t)) printf("U"); else assert(0); }
void visit(TypeClass *t) { //printf("TypeClass::toCtype() %s\n", toChars()); type *tc = type_struct_class(t->sym->toPrettyChars(true), t->sym->alignsize, t->sym->structsize, NULL, NULL, false, true, true); t->ctype = type_pointer(tc); /* Add in fields of the class * (after setting ctype to avoid infinite recursion) */ if (global.params.symdebug) { for (size_t i = 0; i < t->sym->fields.dim; i++) { VarDeclaration *v = t->sym->fields[i]; symbol_struct_addField(tc->Ttag, v->ident->toChars(), Type_toCtype(v->type), v->offset); } } }
/**************************************** * Return type index for a darray of type E[] * Input: * t darray type * etypidx type index for E */ idx_t cv8_darray(type *t, idx_t etypidx) { //printf("cv8_darray(etypidx = %x)\n", etypidx); /* Put out a struct: * struct dArray { * size_t length; * E* ptr; * } */ #if 0 d = debtyp_alloc(18); TOWORD(d->data, 0x100F); TOWORD(d->data + 2, OEM); TOWORD(d->data + 4, 1); // 1 = dynamic array TOLONG(d->data + 6, 2); // count of type indices to follow TOLONG(d->data + 10, 0x23); // index type, T_UQUAD TOLONG(d->data + 14, next); // element type return cv_debtyp(d); #endif type *tp = type_pointer(t->Tnext); idx_t ptridx = cv4_typidx(tp); type_free(tp); static const unsigned char fl[] = { 0x03, 0x12, // LF_FIELDLIST_V2 0x0d, 0x15, // LF_MEMBER_V3 0x03, 0x00, // attribute 0x23, 0x00, 0x00, 0x00, // size_t 0x00, 0x00, // offset 'l', 'e', 'n', 'g', 't', 'h', 0x00, 0xf3, 0xf2, 0xf1, // align to 4-byte including length word before data 0x0d, 0x15, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, // etypidx 0x08, 0x00, 'p', 't', 'r', 0x00, 0xf2, 0xf1, }; debtyp_t *f = debtyp_alloc(sizeof(fl)); memcpy(f->data,fl,sizeof(fl)); TOLONG(f->data + 6, I64 ? 0x23 : 0x22); // size_t TOLONG(f->data + 26, ptridx); TOWORD(f->data + 30, NPTRSIZE); idx_t fieldlist = cv_debtyp(f); const char *id; switch (t->Tnext->Tty) { case mTYimmutable | TYchar: id = "string"; break; case mTYimmutable | TYwchar_t: id = "wstring"; break; case mTYimmutable | TYdchar: id = "dstring"; break; default: id = t->Tident ? t->Tident : "dArray"; break; } int idlen = strlen(id); if (idlen > CV8_MAX_SYMBOL_LENGTH) idlen = CV8_MAX_SYMBOL_LENGTH; debtyp_t *d = debtyp_alloc(20 + idlen + 1); TOWORD(d->data, LF_STRUCTURE_V3); TOWORD(d->data + 2, 2); // count TOWORD(d->data + 4, 0); // property TOLONG(d->data + 6, fieldlist); TOLONG(d->data + 10, 0); // dList TOLONG(d->data + 14, 0); // vtshape TOWORD(d->data + 18, 2 * NPTRSIZE); // size cv_namestring(d->data + 20, id, idlen); d->data[20 + idlen] = 0; idx_t top = cv_numdebtypes(); idx_t debidx = cv_debtyp(d); if(top != cv_numdebtypes()) cv8_udt(id, debidx); return debidx; }
/**************************************** * Return type index for a delegate * Input: * t delegate type * functypidx type index for pointer to function */ idx_t cv8_ddelegate(type *t, idx_t functypidx) { //printf("cv8_ddelegate(functypidx = %x)\n", functypidx); /* Put out a struct: * struct dDelegate { * void* ptr; * function* funcptr; * } */ type *tv = type_fake(TYnptr); tv->Tcount++; idx_t pvidx = cv4_typidx(tv); type_free(tv); type *tp = type_pointer(t->Tnext); idx_t ptridx = cv4_typidx(tp); type_free(tp); #if 0 debtyp_t *d = debtyp_alloc(18); TOWORD(d->data, 0x100F); TOWORD(d->data + 2, OEM); TOWORD(d->data + 4, 3); // 3 = delegate TOLONG(d->data + 6, 2); // count of type indices to follow TOLONG(d->data + 10, key); // void* type TOLONG(d->data + 14, functypidx); // function type #else static const unsigned char fl[] = { 0x03, 0x12, // LF_FIELDLIST_V2 0x0d, 0x15, // LF_MEMBER_V3 0x03, 0x00, // attribute 0x00, 0x00, 0x00, 0x00, // void* 0x00, 0x00, // offset 'p','t','r',0, // "ptr" 0xf2, 0xf1, // align to 4-byte including length word before data 0x0d, 0x15, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, // ptrtypidx 0x08, 0x00, 'f', 'u','n','c','p','t','r', 0, // "funcptr" 0xf2, 0xf1, }; debtyp_t *f = debtyp_alloc(sizeof(fl)); memcpy(f->data,fl,sizeof(fl)); TOLONG(f->data + 6, pvidx); TOLONG(f->data + 22, ptridx); TOWORD(f->data + 26, NPTRSIZE); idx_t fieldlist = cv_debtyp(f); const char *id = "dDelegate"; int idlen = strlen(id); if (idlen > CV8_MAX_SYMBOL_LENGTH) idlen = CV8_MAX_SYMBOL_LENGTH; debtyp_t *d = debtyp_alloc(20 + idlen + 1); TOWORD(d->data, LF_STRUCTURE_V3); TOWORD(d->data + 2, 2); // count TOWORD(d->data + 4, 0); // property TOLONG(d->data + 6, fieldlist); TOLONG(d->data + 10, 0); // dList TOLONG(d->data + 14, 0); // vtshape TOWORD(d->data + 18, 2 * NPTRSIZE); // size memcpy(d->data + 20, id, idlen); d->data[20 + idlen] = 0; #endif return cv_debtyp(d); }
/* Return TRUE if no error and lhstype and rhstype are not error_type */ bool check_assignment(type lhstype, type rhstype, expression rhs, const char *context, data_declaration fundecl, const char *funname, int parmnum) { bool zerorhs = rhs && definite_zero(rhs); if (lhstype == error_type || rhstype == error_type) return FALSE; if (type_void(rhstype)) { error("void value not ignored as it ought to be"); return FALSE; } if (type_equal_unqualified(lhstype, rhstype)) return TRUE; if (type_arithmetic(lhstype) && type_arithmetic(rhstype)) { if (rhs) constant_overflow_warning(rhs->cst); return check_conversion(lhstype, rhstype); } if (parmnum && (type_qualifiers(lhstype) & transparent_qualifier)) { /* See if we can match any field of lhstype */ tag_declaration tag = type_tag(lhstype); field_declaration fields, marginal_field = NULL; /* I blame gcc for this horrible mess (and it's minor inconsistencies with the regular rules) */ /* pedantic warnings are skipped in here because we're already issuing a warning for the use of this construct */ for (fields = tag->fieldlist; fields; fields = fields->next) { type ft = fields->type; if (type_compatible(ft, rhstype)) break; if (!type_pointer(ft)) continue; if (type_pointer(rhstype)) { type ttl = type_points_to(ft), ttr = type_points_to(rhstype); bool goodmatch = assignable_pointer_targets(ttl, ttr, FALSE); /* Any non-function converts to a [const][volatile] void * and vice versa; otherwise, targets must be the same. Meanwhile, the lhs target must have all the qualifiers of the rhs. */ if (goodmatch) { /* If this type won't generate any warnings, use it. */ if ((type_function(ttr) && type_function(ttl)) ? (((!type_const(ttl)) | type_const(ttr)) & ((!type_volatile(ttl)) | type_volatile(ttr))) : (((type_const(ttl)) | (!type_const(ttr))) & (type_volatile(ttl) | (!type_volatile(ttr))))) break; /* Keep looking for a better type, but remember this one. */ if (!marginal_field) marginal_field = fields; } } /* Can convert integer zero to any pointer type. */ /* Note that this allows passing *any* null pointer (gcc bug?) */ if (zerorhs) break; } if (fields || marginal_field) { if (!fields) { /* We have only a marginally acceptable member type; it needs a warning. */ type ttl = type_points_to(marginal_field->type), ttr = type_points_to(rhstype); ptrconversion_warnings(ttl, ttr, rhs, context, funname, parmnum, FALSE); } if (pedantic && !(fundecl && fundecl->in_system_header)) pedwarn("ANSI C prohibits argument conversion to union type"); return TRUE; } } if (type_pointer(lhstype) && type_pointer(rhstype)) { type ttl = type_points_to(lhstype), ttr = type_points_to(rhstype); bool goodmatch = assignable_pointer_targets(ttl, ttr, pedantic); /* Any non-function converts to a [const][volatile] void * and vice versa; otherwise, targets must be the same. Meanwhile, the lhs target must have all the qualifiers of the rhs. */ if (goodmatch || (type_equal_unqualified(make_unsigned_type(ttl), make_unsigned_type(ttr)))) ptrconversion_warnings(ttl, ttr, rhs, context, funname, parmnum, pedantic); else warn_for_assignment("%s from incompatible pointer type", context, funname, parmnum); return check_conversion(lhstype, rhstype); } /* enum = ptr and ptr = enum counts as an error, so use type_integral */ else if (type_pointer(lhstype) && type_integral(rhstype)) { if (!zerorhs) warn_for_assignment("%s makes pointer from integer without a cast", context, funname, parmnum); return check_conversion(lhstype, rhstype); } else if (type_integral(lhstype) && type_pointer(rhstype)) { warn_for_assignment("%s makes integer from pointer without a cast", context, funname, parmnum); return check_conversion(lhstype, rhstype); } if (!context) if (funname) error("incompatible type for argument %d of `%s'", parmnum, funname); else error("incompatible type for argument %d of indirect function call", parmnum); else error("incompatible types in %s", context); return FALSE; }
Symbol *VarDeclaration::toSymbol() { //printf("VarDeclaration::toSymbol(%s)\n", toChars()); //if (needThis()) *(char*)0=0; assert(!needThis()); if (!csym) { TYPE *t; const char *id; if (isDataseg()) id = mangle(); else id = ident->toChars(); Symbol *s = symbol_calloc(id); s->Salignment = alignment; if (storage_class & (STCout | STCref)) { // should be TYref, but problems in back end t = type_pointer(type->toCtype()); } else if (storage_class & STClazy) { if (config.exe == EX_WIN64 && isParameter()) t = type_fake(TYnptr); else t = type_fake(TYdelegate); // Tdelegate as C type t->Tcount++; } else if (isParameter()) { if (config.exe == EX_WIN64 && type->size(Loc()) > REGSIZE) { // should be TYref, but problems in back end t = type_pointer(type->toCtype()); } else { t = type->toCParamtype(); t->Tcount++; } } else { t = type->toCtype(); t->Tcount++; } if (isDataseg()) { if (isThreadlocal()) { /* Thread local storage */ TYPE *ts = t; ts->Tcount++; // make sure a different t is allocated type_setty(&t, t->Tty | mTYthread); ts->Tcount--; if (global.params.vtls) { char *p = loc.toChars(); fprintf(stderr, "%s: %s is thread local\n", p ? p : "", toChars()); if (p) mem.free(p); } } s->Sclass = SCextern; s->Sfl = FLextern; slist_add(s); /* if it's global or static, then it needs to have a qualified but unmangled name. * This gives some explanation of the separation in treating name mangling. * It applies to PDB format, but should apply to CV as PDB derives from CV. * http://msdn.microsoft.com/en-us/library/ff553493(VS.85).aspx */ s->prettyIdent = toPrettyChars(); } else { s->Sclass = SCauto; s->Sfl = FLauto; if (nestedrefs.dim) { /* Symbol is accessed by a nested function. Make sure * it is not put in a register, and that the optimizer * assumes it is modified across function calls and pointer * dereferences. */ //printf("\tnested ref, not register\n"); type_setcv(&t, t->Tty | mTYvolatile); } } if (ident == Id::va_argsave) /* __va_argsave is set outside of the realm of the optimizer, * so we tell the optimizer to leave it alone */ type_setcv(&t, t->Tty | mTYvolatile); mangle_t m = 0; switch (linkage) { case LINKwindows: m = mTYman_std; break; case LINKpascal: m = mTYman_pas; break; case LINKc: m = mTYman_c; break; case LINKd: m = mTYman_d; break; case LINKcpp: { m = mTYman_cpp; s->Sflags = SFLpublic; Dsymbol *parent = toParent(); ClassDeclaration *cd = parent->isClassDeclaration(); if (cd) { ::type *tc = cd->type->toCtype(); s->Sscope = tc->Tnext->Ttag; } StructDeclaration *sd = parent->isStructDeclaration(); if (sd) { ::type *ts = sd->type->toCtype(); s->Sscope = ts->Ttag; } break; } default: printf("linkage = %d\n", linkage); assert(0); } type_setmangle(&t, m); s->Stype = t; csym = s; } return csym; }
/************************************* * 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. */ void buildClosure(FuncDeclaration *fd, IRState *irs) { if (fd->needsClosure()) { // Generate closure on the heap // BUG: doesn't capture variadic arguments passed to this function /* BUG: doesn't handle destructors for the local variables. * The way to do it is to make the closure variables the fields * of a class object: * class Closure { * vtbl[] * monitor * ptr to destructor * sthis * ... closure variables ... * ~this() { call destructor } * } */ //printf("FuncDeclaration::buildClosure() %s\n", toChars()); /* Generate type name for closure struct */ const char *name1 = "CLOSURE."; const char *name2 = fd->toPrettyChars(); size_t namesize = strlen(name1)+strlen(name2)+1; char *closname = (char *) calloc(namesize, sizeof(char)); strcat(strcat(closname, name1), name2); /* Build type for closure */ type *Closstru = type_struct_class(closname, Target::ptrsize, 0, NULL, NULL, false, false, true); symbol_struct_addField(Closstru->Ttag, "__chain", Type_toCtype(Type::tvoidptr), 0); Symbol *sclosure; sclosure = symbol_name("__closptr", SCauto, type_pointer(Closstru)); sclosure->Sflags |= SFLtrue | SFLfree; symbol_add(sclosure); irs->sclosure = sclosure; unsigned offset = Target::ptrsize; // leave room for previous sthis for (size_t i = 0; i < fd->closureVars.dim; i++) { VarDeclaration *v = fd->closureVars[i]; //printf("closure var %s\n", v->toChars()); assert(v->isVarDeclaration()); if (v->needsAutoDtor()) { /* Because the value needs to survive the end of the scope! */ v->error("has scoped destruction, cannot build closure"); } if (v->isargptr) { /* See Bugzilla 2479 * This is actually a bug, but better to produce a nice * message at compile time rather than memory corruption at runtime */ v->error("cannot reference variadic arguments from closure"); } /* Align and allocate space for v in the closure * just like AggregateDeclaration::addField() does. */ unsigned memsize; unsigned memalignsize; structalign_t xalign; if (v->storage_class & STClazy) { /* Lazy variables are really delegates, * so give same answers that TypeDelegate would */ memsize = Target::ptrsize * 2; memalignsize = memsize; xalign = STRUCTALIGN_DEFAULT; } else if (ISWIN64REF(v)) { memsize = v->type->size(); memalignsize = v->type->alignsize(); xalign = v->alignment; } else if (ISREF(v, NULL)) { // reference parameters are just pointers memsize = Target::ptrsize; memalignsize = memsize; xalign = STRUCTALIGN_DEFAULT; } else { memsize = v->type->size(); memalignsize = v->type->alignsize(); xalign = v->alignment; } AggregateDeclaration::alignmember(xalign, memalignsize, &offset); v->offset = offset; offset += memsize; /* Set Sscope to closure */ Symbol *vsym = toSymbol(v); assert(vsym->Sscope == NULL); vsym->Sscope = sclosure; /* Add variable as closure type member */ symbol_struct_addField(Closstru->Ttag, vsym->Sident, vsym->Stype, v->offset); //printf("closure field %s: memalignsize: %i, offset: %i\n", vsym->Sident, memalignsize, v->offset); /* Can't do nrvo if the variable is put in a closure, since * what the shidden points to may no longer exist. */ if (fd->nrvo_can && fd->nrvo_var == v) { fd->nrvo_can = 0; } } // offset is now the size of the closure Closstru->Ttag->Sstruct->Sstructsize = offset; // Allocate memory for the closure elem *e = el_long(TYsize_t, offset); e = el_bin(OPcall, TYnptr, el_var(getRtlsym(RTLSYM_ALLOCMEMORY)), e); toTraceGC(irs, e, &fd->loc); // 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 (size_t i = 0; i < fd->closureVars.dim; i++) { VarDeclaration *v = fd->closureVars[i]; if (!v->isParameter()) continue; tym_t tym = totym(v->type); bool win64ref = ISWIN64REF(v); if (win64ref) { if (v->storage_class & STClazy) tym = TYdelegate; } else if (ISREF(v, NULL)) tym = TYnptr; // reference parameters are just pointers else if (v->storage_class & STClazy) tym = TYdelegate; ex = el_bin(OPadd, TYnptr, el_var(sclosure), el_long(TYsize_t, v->offset)); ex = el_una(OPind, tym, ex); elem *ev = el_var(toSymbol(v)); if (win64ref) { ev->Ety = TYnptr; ev = el_una(OPind, tym, ev); if (tybasic(ev->Ety) == TYstruct || tybasic(ev->Ety) == TYarray) ev->ET = Type_toCtype(v->type); } if (tybasic(ex->Ety) == TYstruct || tybasic(ex->Ety) == TYarray) { ::type *t = Type_toCtype(v->type); ex->ET = t; ex = el_bin(OPstreq, tym, ex, ev); ex->ET = t; } else ex = el_bin(OPeq, tym, ex, ev); e = el_combine(e, ex); } block_appendexp(irs->blx->curblock, e); } }
expression make_cast(location loc, asttype t, expression e) { expression result = CAST(expression, new_cast(parse_region, loc, e, t)); type castto = t->type; if (castto == error_type || type_void(castto)) ; /* Do nothing */ else if (type_array(castto)) { error("cast specifies array type"); castto = error_type; } else if (type_function(castto)) { error("cast specifies function type"); castto = error_type; } else if (type_equal_unqualified(castto, e->type)) { if (pedantic && type_aggregate(castto)) pedwarn("ANSI C forbids casting nonscalar to the same type"); } else { type etype = e->type; /* Convert functions and arrays to pointers, but don't convert any other types. */ if (type_function(etype) || type_array(etype)) etype = default_conversion(e); if (type_union(castto)) { tag_declaration utag = type_tag(castto); field_declaration ufield; /* Look for etype as a field of the union */ for (ufield = utag->fieldlist; ufield; ufield = ufield->next) if (ufield->name && type_equal_unqualified(ufield->type, etype)) { if (pedantic) pedwarn("ANSI C forbids casts to union type"); break; } if (!ufield) error("cast to union type from type not present in union"); } else { /* Optionally warn about potentially worrisome casts. */ if (warn_cast_qual && type_pointer(etype) && type_pointer(castto)) { type ep = type_points_to(etype), cp = type_points_to(castto); if (type_volatile(ep) && !type_volatile(cp)) pedwarn("cast discards `volatile' from pointer target type"); if (type_const(ep) && !type_const(cp)) pedwarn("cast discards `const' from pointer target type"); } /* This warning is weird */ if (warn_bad_function_cast && is_function_call(e) && !type_equal_unqualified(castto, etype)) warning ("cast does not match function type"); #if 0 /* Warn about possible alignment problems. */ if (STRICT_ALIGNMENT && warn_cast_align && TREE_CODE (type) == POINTER_TYPE && TREE_CODE (otype) == POINTER_TYPE && TREE_CODE (TREE_TYPE (otype)) != VOID_TYPE && TREE_CODE (TREE_TYPE (otype)) != FUNCTION_TYPE /* Don't warn about opaque types, where the actual alignment restriction is unknown. */ && !((TREE_CODE (TREE_TYPE (otype)) == UNION_TYPE || TREE_CODE (TREE_TYPE (otype)) == RECORD_TYPE) && TYPE_MODE (TREE_TYPE (otype)) == VOIDmode) && TYPE_ALIGN (TREE_TYPE (type)) > TYPE_ALIGN (TREE_TYPE (otype))) warning ("cast increases required alignment of target type"); if (TREE_CODE (type) == INTEGER_TYPE && TREE_CODE (otype) == POINTER_TYPE && TYPE_PRECISION (type) != TYPE_PRECISION (otype) && !TREE_CONSTANT (value)) warning ("cast from pointer to integer of different size"); if (TREE_CODE (type) == POINTER_TYPE && TREE_CODE (otype) == INTEGER_TYPE && TYPE_PRECISION (type) != TYPE_PRECISION (otype) #if 0 /* Don't warn about converting 0 to pointer, provided the 0 was explicit--not cast or made by folding. */ && !(TREE_CODE (value) == INTEGER_CST && integer_zerop (value)) #endif /* Don't warn about converting any constant. */ && !TREE_CONSTANT (value)) warning ("cast to pointer from integer of different size"); #endif check_conversion(castto, etype); } } result->lvalue = !pedantic && e->lvalue; result->isregister = e->isregister; result->bitfield = e->bitfield; result->static_address = e->static_address; result->type = castto; result->cst = fold_cast(result); return result; }
type check_binary(int binop, expression e1, expression e2) { type t1 = default_conversion(e1), t2 = default_conversion(e2); type rtype = NULL; bool common = FALSE; /* XXX: Misc warnings (see build_binary_op) */ if (t1 == error_type || t2 == error_type) rtype = error_type; else switch(binop) { case kind_plus: if (type_pointer(t1) && type_integer(t2)) rtype = pointer_int_sum(t1, t2); else if (type_pointer(t2) && type_integer(t1)) rtype = pointer_int_sum(t2, t1); else common = TRUE; break; case kind_minus: if (type_pointer(t1) && type_integer(t2)) rtype = pointer_int_sum(t1, t2); else if (type_pointer(t1) && type_pointer(t2) && compatible_pointer_types(t1, t2)) rtype = ptrdiff_t_type; else common = TRUE; break; case kind_plus_assign: case kind_minus_assign: if (type_pointer(t1) && type_integer(t2)) rtype = pointer_int_sum(t1, t2); else common = TRUE; break; case kind_times: case kind_divide: case kind_times_assign: case kind_divide_assign: common = TRUE; break; case kind_modulo: case kind_bitand: case kind_bitor: case kind_bitxor: case kind_lshift: case kind_rshift: case kind_modulo_assign: case kind_bitand_assign: case kind_bitor_assign: case kind_bitxor_assign: case kind_lshift_assign: case kind_rshift_assign: if (type_integer(t1) && type_integer(t2)) rtype = common_type(t1, t2); break; case kind_leq: case kind_geq: case kind_lt: case kind_gt: rtype = int_type; /* Default to assuming success */ if (type_real(t1) && type_real(t2)) ; else if (type_pointer(t1) && type_pointer(t2)) { if (compatible_pointer_types(t1, t2)) { /* XXX: how can this happen ? */ if (type_incomplete(t1) != type_incomplete(t2)) pedwarn("comparison of complete and incomplete pointers"); else if (pedantic && type_function(type_points_to(t1))) pedwarn("ANSI C forbids ordered comparisons of pointers to functions"); } else pedwarn("comparison of distinct pointer types lacks a cast"); } /* XXX: Use of definite_zero may lead to extra warnings when !extra_warnings */ else if ((type_pointer(t1) && definite_zero(e2)) || (type_pointer(t2) && definite_zero(e1))) { if (pedantic || extra_warnings) pedwarn("ordered comparison of pointer with integer zero"); } else if ((type_pointer(t1) && type_integer(t2)) || (type_pointer(t2) && type_integer(t1))) { if (!flag_traditional) pedwarn("comparison between pointer and integer"); } else rtype = NULL; /* Force error */ break; case kind_eq: case kind_ne: rtype = int_type; /* Default to assuming success */ if (type_arithmetic(t1) && type_arithmetic(t2)) ; else if (type_pointer(t1) && type_pointer(t2)) { if (!compatible_pointer_types(t1, t2) && !valid_compare(t1, t2, e1) && !valid_compare(t2, t1, e2)) pedwarn("comparison of distinct pointer types lacks a cast"); } else if ((type_pointer(t1) && definite_null(e2)) || (type_pointer(t2) && definite_null(e1))) ; else if ((type_pointer(t1) && type_integer(t2)) || (type_pointer(t2) && type_integer(t1))) { if (!flag_traditional) pedwarn("comparison between pointer and integer"); } else rtype = NULL; /* Force error */ break; case kind_andand: case kind_oror: if (type_scalar(t1) && type_scalar(t2)) rtype = int_type; break; default: assert(0); break; } if (common && type_arithmetic(t1) && type_arithmetic(t2)) rtype = common_type(t1, t2); if (!rtype) { error("invalid operands to binary %s", binary_op_name(binop)); rtype = error_type; } return rtype; }
void visit(TypePointer *t) { //printf("TypePointer::toCtype() %s\n", t->toChars()); t->ctype = type_pointer(Type_toCtype(t->next)); }
bool check_conversion(type to, type from) { if (type_equal_unqualified(to, from)) return TRUE; if (to == error_type || from == error_type) return FALSE; if (type_void(from)) { error("void value not ignored as it ought to be"); return FALSE; } if (type_void(to)) return TRUE; if (type_integer(to)) { if (!type_scalar(from)) { error("aggregate value used where an integer was expected"); return FALSE; } } else if (type_pointer(to)) { if (!(type_integer(from) || type_pointer(from))) { error("cannot convert to a pointer type"); return FALSE; } } else if (type_floating(to)) { if (type_pointer(from)) { error("pointer value used where a floating point value was expected"); return FALSE; } else if (!type_arithmetic(from)) { error("aggregate value used where a float was expected"); return FALSE; } } else if (type_complex(to)) { if (type_pointer(from)) { error("pointer value used where a complex was expected"); return FALSE; } else if (!type_arithmetic(from)) { error("aggregate value used where a complex was expected"); return FALSE; } } else { error("conversion to non-scalar type requested"); return FALSE; } return TRUE; }