Esempio n. 1
0
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;
}
Esempio n. 2
0
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;
}
Esempio n. 3
0
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;
}
Esempio n. 4
0
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;
}
Esempio n. 5
0
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);
}
Esempio n. 6
0
File: edit.c Progetto: albedium/nesc
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;
}
Esempio n. 7
0
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);
}
Esempio n. 8
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);
            }
        }
    }
Esempio n. 9
0
File: cv8.c Progetto: jasonwhite/dmd
/****************************************
 * 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;
}
Esempio n. 10
0
File: cv8.c Progetto: jasonwhite/dmd
/****************************************
 * 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);
}
Esempio n. 11
0
/* 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;
}
Esempio n. 12
0
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;
}
Esempio n. 13
0
/*************************************
 * 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);
    }
}
Esempio n. 14
0
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;
}
Esempio n. 15
0
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;
}
Esempio n. 16
0
 void visit(TypePointer *t)
 {
     //printf("TypePointer::toCtype() %s\n", t->toChars());
     t->ctype = type_pointer(Type_toCtype(t->next));
 }
Esempio n. 17
0
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;
}