When doing << or >> operators, don't convert the return type to the type of the shift amount.
Fixes issue #73. Previously, if we had e.g. an int16 type that was being shifted left by 1, then the constant integer 1 would come in as an int32, we'd convert the int16 to an int32, and then we'd do the shift. Now, for shifts, the type of the expression is always the same as the type of the value being shifted.
This commit is contained in:
37
expr.cpp
37
expr.cpp
@@ -119,13 +119,14 @@ lMaybeIssuePrecisionWarning(const AtomicType *toAtomicType,
|
|||||||
errorMsgBase);
|
errorMsgBase);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
FATAL("logic error in lMaybeIssuePrecisionWarning");
|
FATAL("logic error in lMaybeIssuePrecisionWarning()");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Expr *
|
Expr *
|
||||||
Expr::TypeConv(const Type *toType, const char *errorMsgBase, bool failureOk) {
|
Expr::TypeConv(const Type *toType, const char *errorMsgBase, bool failureOk,
|
||||||
|
bool issuePrecisionWarnings) {
|
||||||
/* This function is way too long and complex. Is type conversion stuff
|
/* This function is way too long and complex. Is type conversion stuff
|
||||||
always this messy, or can this be cleaned up somehow? */
|
always this messy, or can this be cleaned up somehow? */
|
||||||
assert(failureOk || errorMsgBase != NULL);
|
assert(failureOk || errorMsgBase != NULL);
|
||||||
@@ -313,7 +314,7 @@ Expr::TypeConv(const Type *toType, const char *errorMsgBase, bool failureOk) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!failureOk)
|
if (!failureOk && issuePrecisionWarnings)
|
||||||
lMaybeIssuePrecisionWarning(toAtomicType, fromAtomicType, pos,
|
lMaybeIssuePrecisionWarning(toAtomicType, fromAtomicType, pos,
|
||||||
errorMsgBase);
|
errorMsgBase);
|
||||||
|
|
||||||
@@ -1010,6 +1011,7 @@ BinaryExpr::GetType() const {
|
|||||||
return lMatchingBoolType(promotedType);
|
return lMatchingBoolType(promotedType);
|
||||||
case Shl:
|
case Shl:
|
||||||
case Shr:
|
case Shr:
|
||||||
|
return type1->IsVaryingType() ? type0->GetAsVaryingType() : type0;
|
||||||
case BitAnd:
|
case BitAnd:
|
||||||
case BitXor:
|
case BitXor:
|
||||||
case BitOr:
|
case BitOr:
|
||||||
@@ -1309,15 +1311,28 @@ BinaryExpr::TypeCheck() {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Type *promotedType = Type::MoreGeneralType(type0, type1, arg0->pos,
|
if (op == Shl || op == Shr) {
|
||||||
"binary bit op");
|
bool isVarying = (type0->IsVaryingType() ||
|
||||||
if (promotedType == NULL)
|
type1->IsVaryingType());
|
||||||
return NULL;
|
if (isVarying) {
|
||||||
|
arg0 = arg0->TypeConv(type0->GetAsVaryingType(), "shift operator");
|
||||||
|
type0 = arg0->GetType();
|
||||||
|
}
|
||||||
|
arg1 = arg1->TypeConv(type0, "shift operator", false, false);
|
||||||
|
if (arg1 == NULL)
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const Type *promotedType = Type::MoreGeneralType(type0, type1, arg0->pos,
|
||||||
|
"binary bit op");
|
||||||
|
if (promotedType == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
arg0 = arg0->TypeConv(promotedType, "binary bit op");
|
arg0 = arg0->TypeConv(promotedType, "binary bit op");
|
||||||
arg1 = arg1->TypeConv(promotedType, "binary bit op");
|
arg1 = arg1->TypeConv(promotedType, "binary bit op");
|
||||||
if (arg0 == NULL || arg1 == NULL)
|
if (arg0 == NULL || arg1 == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
case Add:
|
case Add:
|
||||||
|
|||||||
2
expr.h
2
expr.h
@@ -97,7 +97,7 @@ public:
|
|||||||
that incorporates the given error message string. In either
|
that incorporates the given error message string. In either
|
||||||
failure case, NULL is returned. */
|
failure case, NULL is returned. */
|
||||||
Expr *TypeConv(const Type *type, const char *errorMsgBase = NULL,
|
Expr *TypeConv(const Type *type, const char *errorMsgBase = NULL,
|
||||||
bool failureOk = false);
|
bool failureOk = false, bool issuePrecisionWarnings = true);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user