Correct behavior: If false is returned when IsInstanceOfInterface() called as part of a castclass then the usual InvalidCastException
will be thrown unless an alternate exception is assigned to the castError output parameter.
This parameter is ignored on successful casts or during the evaluation of an isinst (which returns null rather than throwing on error).
Object * pObj = OpStackGet<Object*>(idx);
if (pObj != NULL)
{
- if (!ObjIsInstanceOf(pObj, TypeHandle(cls)))
+ if (!ObjIsInstanceOf(pObj, TypeHandle(cls), TRUE))
{
- OBJECTREF oref = ObjectToOBJECTREF(OpStackGet<Object*>(idx));
- COMPlusThrowInvalidCastException(&oref, TypeHandle(cls));
+ UNREACHABLE(); //ObjIsInstanceOf will throw if cast can't be done
}
}
if ((boxTypeAttribs & CORINFO_FLG_VALUECLASS) == 0)
{
Object* obj = OpStackGet<Object*>(tos);
- if (obj != NULL && !ObjIsInstanceOf(obj, TypeHandle(boxTypeClsHnd)))
- COMPlusThrowInvalidCastException(&ObjectToOBJECTREF(obj), TypeHandle(boxTypeClsHnd));
+ if (obj != NULL && !ObjIsInstanceOf(obj, TypeHandle(boxTypeClsHnd), TRUE))
+ {
+ UNREACHABLE(); //ObjIsInstanceOf will throw if cast can't be done
+ }
}
else
{
return pMT->CanCastToClassOrInterfaceNoGC(toTypeHnd.AsMethodTable());
}
-BOOL ObjIsInstanceOf(Object *pObject, TypeHandle toTypeHnd)
+BOOL ObjIsInstanceOf(Object *pObject, TypeHandle toTypeHnd, BOOL throwCastException)
{
CONTRACTL {
THROWS;
CALL_MANAGED_METHOD(fCast, BOOL, args);
INDEBUG(managedType = NULL); // managedType isn't protected during the call
- if (exception != NULL)
+ if (!fCast && throwCastException && exception != NULL)
{
RealCOMPlusThrow(exception);
}
}
#endif // FEATURE_ICASTABLE
- GCPROTECT_END();
+ if (!fCast && throwCastException)
+ {
+ COMPlusThrowInvalidCastException(&obj, toTypeHnd);
+ }
+
+ GCPROTECT_END(); // obj
return(fCast);
}
TypeHandle clsHnd(type);
HELPER_METHOD_FRAME_BEGIN_RET_1(oref);
- if (!ObjIsInstanceOf(OBJECTREFToObject(oref), clsHnd))
- COMPlusThrowInvalidCastException(&oref, clsHnd);
+ if (!ObjIsInstanceOf(OBJECTREFToObject(oref), clsHnd, TRUE))
+ {
+ UNREACHABLE(); //ObjIsInstanceOf will throw if cast can't be done
+ }
HELPER_METHOD_FRAME_END();
return OBJECTREFToObject(oref);
EXTERN_C FCDECL0(VOID, JIT_PollGC_Nop);
#endif
-BOOL ObjIsInstanceOf(Object *pObject, TypeHandle toTypeHnd);
+BOOL ObjIsInstanceOf(Object *pObject, TypeHandle toTypeHnd, BOOL throwCastException = FALSE);
EXTERN_C TypeHandle::CastResult STDCALL ObjIsInstanceOfNoGC(Object *pObject, TypeHandle toTypeHnd);
#ifdef _WIN64
{
case ENCODE_ISINSTANCEOF_HELPER:
case ENCODE_CHKCAST_HELPER:
- if (*(Object **)pArgument == NULL || ObjIsInstanceOf(*(Object **)pArgument, th))
{
- result = (SIZE_T)(*(Object **)pArgument);
- }
- else
- {
- if (kind == ENCODE_CHKCAST_HELPER)
+ BOOL throwInvalidCast = (kind == ENCODE_CHKCAST_HELPER);
+ if (*(Object **)pArgument == NULL || ObjIsInstanceOf(*(Object **)pArgument, th, throwInvalidCast))
{
- OBJECTREF obj = ObjectToOBJECTREF(*(Object **)pArgument);
- GCPROTECT_BEGIN(obj);
- COMPlusThrowInvalidCastException(&obj, th);
- GCPROTECT_END();
+ result = (SIZE_T)(*(Object **)pArgument);
+ }
+ else
+ {
+ _ASSERTE (!throwInvalidCast);
+ result = NULL;
}
-
- result = NULL;
}
break;
case ENCODE_STATIC_BASE_NONGC_HELPER:
}
catch (CastableException) {}
+ Assert(!(nullCastable is IRetThis), "null castable shouldn't be allowed to be casted to anything");
+
+ var shouldBeNull = nullCastable as IRetThis;
+ Assert(shouldBeNull == null, "shouldBeNull should be assigned null");
+
object badCastable = new BadCastable();
try
{