symbol *returnLabel; /* function return label */
symbol *entryLabel; /* function entry label */
+
+#if defined(__BORLANDC__) || defined(_MSC_VER)
+#define LONG_LONG __int64
+#else
+#define LONG_LONG long long
+#endif
+
/*-----------------------------------------------------------------*/
/* forward definition of some functions */
operand *geniCodeDivision (operand *, operand *);
{ARRAYINIT, "arrayInit", picGenericOne, NULL},
};
+/*-----------------------------------------------------------------*/
+/* checkConstantRange: check a constant against the type */
+/*-----------------------------------------------------------------*/
+
+/* pedantic=0: allmost anything is allowed as long as the absolute
+ value is within the bit range of the type, and -1 is treated as
+ 0xf..f for unsigned types (e.g. in assign)
+ pedantic=1: -1==-1, not allowed for unsigned types (e.g. in compare)
+ pedantic>1: "char c=200" is not allowed (evaluates to -56)
+*/
+
+void checkConstantRange(sym_link *ltype, value *val, char *msg, int pedantic) {
+ LONG_LONG max = (LONG_LONG) 1 << bitsForType(ltype);
+ char message[132]="";
+ int warnings=0;
+ int negative=0;
+ long v=SPEC_CVAL(val->type).v_long;
+
+#if 0
+ // this could be a good idea
+ if (options.pedantic)
+ pedantic=2;
+#endif
+
+ if (SPEC_NOUN(ltype)==FLOAT) {
+ // anything will do
+ return;
+ }
+
+ if (!SPEC_USIGN(val->type) && v<0) {
+ negative=1;
+ if (SPEC_USIGN(ltype) && (pedantic>1)) {
+ warnings++;
+ }
+ v=-v;
+ }
+
+ // if very pedantic: "char c=200" is not allowed
+ if (pedantic>1 && !SPEC_USIGN(ltype)) {
+ max = max/2 + negative;
+ }
+
+ if (v >= max) {
+ warnings++;
+ }
+
+ if (warnings) {
+ sprintf (message, "for %s %s in %s",
+ SPEC_USIGN(ltype) ? "unsigned" : "signed",
+ nounName(ltype), msg);
+ werror (W_CONST_RANGE, message);
+
+ if (pedantic>1)
+ fatalError++;
+ }
+}
/*-----------------------------------------------------------------*/
/* operandName - returns the name of the operand */
sym_link *optype;
sym_link *opetype = getSpec (optype = operandType (op));
sym_link *restype;
+ int errors=0;
/* one of them has size zero then error */
if (IS_VOID (optype))
return operandFromValue (valCastLiteral (type,
operandLitValue (op)));
- /* if casting to some pointer type &&
- the destination is not a generic pointer
- then give a warning : (only for implicit casts) */
- if (IS_PTR (optype) && implicit &&
- (DCL_TYPE (optype) != DCL_TYPE (type)) &&
- !IS_GENPTR (type))
- {
- werror (E_INCOMPAT_CAST);
- fprintf (stderr, "from type '");
- printTypeChain (optype, stderr);
- fprintf (stderr, "' to type '");
- printTypeChain (type, stderr);
- fprintf (stderr, "'\n");
+ /* if casting to/from pointers, do some checking */
+ if (IS_PTR(type)) { // to a pointer
+ if (!IS_PTR(optype) && !IS_FUNC(optype)) { // from a non pointer
+ if (IS_INTEGRAL(optype)) {
+ // maybe this is NULL, than it's ok.
+ if (!(IS_LITERAL(optype) && (SPEC_CVAL(optype).v_ulong ==0))) {
+ if (!TARGET_IS_Z80 && !TARGET_IS_GBZ80 && IS_GENPTR(type)) {
+ // no way to set the storage
+ if (IS_LITERAL(optype)) {
+ werror(E_LITERAL_GENERIC);
+ errors++;
+ } else {
+ werror(E_NONPTR2_GENPTR);
+ errors++;
+ }
+ } else if (implicit) {
+ werror(W_INTEGRAL2PTR_NOCAST);
+ errors++;
+ }
+ }
+ } else {
+ // shouldn't do that with float, array or structure unless to void
+ if (!IS_VOID(getSpec(type)) &&
+ !(IS_CODEPTR(type) && IS_FUNC(type->next) && IS_FUNC(optype))) {
+ werror(E_INCOMPAT_TYPES);
+ errors++;
+ }
+ }
+ } else { // from a pointer to a pointer
+ if (!TARGET_IS_Z80 && !TARGET_IS_GBZ80) {
+ // if not a pointer to a function
+ if (!(IS_CODEPTR(type) && IS_FUNC(type->next) && IS_FUNC(optype))) {
+ if (implicit) { // if not to generic, they have to match
+ if ((!IS_GENPTR(type) && (DCL_TYPE(optype) != DCL_TYPE(type)))) {
+ werror(E_INCOMPAT_PTYPES);
+ errors++;
+ }
+ }
+ }
+ }
+ }
+ } else { // to a non pointer
+ if (IS_PTR(optype)) { // from a pointer
+ if (implicit) { // sneaky
+ if (IS_INTEGRAL(type)) {
+ werror(W_PTR2INTEGRAL_NOCAST);
+ errors++;
+ } else { // shouldn't do that with float, array or structure
+ werror(E_INCOMPAT_TYPES);
+ errors++;
+ }
+ }
}
+ }
+ if (errors) {
+ /* fprintf (stderr, "%s%s %d: ", op->operand.symOperand->name,
+ implicit?"(implicit)":"", errors); */
+ fprintf (stderr, "from type '");
+ printTypeChain (optype, stderr);
+ fprintf (stderr, "' to type '");
+ printTypeChain (type, stderr);
+ fprintf (stderr, "'\n");
+ }
/* if they are the same size create an assignment */
if (getSize (type) == getSize (optype) &&
return IC_RESULT (ic);
}
-#if defined(__BORLANDC__) || defined(_MSC_VER)
-#define LONG_LONG __int64
-#else
-#define LONG_LONG long long
-#endif
-
/*-----------------------------------------------------------------*/
/* geniCodeLogic- logic code */
/*-----------------------------------------------------------------*/
/* left is integral type and right is literal then
check if the literal value is within bounds */
- if (IS_INTEGRAL (ltype) && IS_LITERAL (rtype))
+ if (IS_INTEGRAL (ltype) && IS_VALOP (right) && IS_LITERAL (rtype))
{
- int nbits = bitsForType (ltype);
- long v = (long) operandLitValue (right);
-
- if (v >= ((LONG_LONG) 1 << nbits) && v > 0)
- werror (W_CONST_RANGE, " compare operation ");
+ checkConstantRange(ltype,
+ OP_VALUE(right), "compare operation", 1);
}
ctype = usualBinaryConversions (&left, &right);
check if the literal value is within bounds */
if (IS_INTEGRAL (ltype) && right->type == VALUE && IS_LITERAL (rtype))
{
- int nbits = bitsForType (ltype);
- long v = (long) operandLitValue (right);
-
- if (v >= ((LONG_LONG) 1 << nbits) && v > 0)
- werror (W_CONST_RANGE, " = operation");
+ checkConstantRange(ltype,
+ OP_VALUE(right), "= operation", 0);
}
/* if the left & right type don't exactly match */
case '[': /* array operation */
{
- sym_link *ltype = operandType (left);
- left = geniCodeRValue (left, IS_PTR (ltype->next) ? TRUE : FALSE);
+ //sym_link *ltype = operandType (left);
+ //left = geniCodeRValue (left, IS_PTR (ltype->next) ? TRUE : FALSE);
+ left = geniCodeRValue (left, FALSE);
right = geniCodeRValue (right, TRUE);
}