Since [bugs:#69] (r2464) TNullableDate.AssignVariant with ehRaiseException builds the message for its EConvertError with TryVar2Str, and falls back to DumpVariant if that fails or raises. The comment there says "DumpVariant never raises", which holds only for its body: its parameter is a by-value OleVariant, so the Variant is converted at the call site, outside DumpVariant's try. The second DumpVariant(_v) call, in the except branch, is not protected by anything.
That conversion (_OleVarFromVar) raises for a custom variant type that cannot be cast to varOleStr, an unregistered custom type, and varAny without a CORBA handler.
Measured on Delphi 2007 and 12 with a registered custom variant type whose CastTo always calls RaiseCastError:
| Call | Result |
|---|---|
TryVar2Str(v, s, ehNoException) |
False |
o := v (o: OleVariant) |
EVariantTypeCastError |
AssignVariant(v, ehRaiseException) |
EVariantTypeCastError, documented is EConvertError |
AssignVariant(v, ehNoException) |
False, correct |
Expected: EConvertError, as documented. Where neither TryVar2Str nor DumpVariant can describe the value, the message could name only its variant type, VarType needs no conversion.
Only u_dzNullableDate builds its message this way; the other nullable types do not call DumpVariant.
Found by a code review.