| 279 | static bool AreCompatibleFnPtrTypes(PPrototype *to, PPrototype *from); |
| 280 | |
| 281 | bool AreCompatiblePointerTypes(PType *dest, PType *source, bool forcompare) |
| 282 | { |
| 283 | if (dest->isPointer() && source->isPointer()) |
| 284 | { |
| 285 | auto fromtype = source->toPointer(); |
| 286 | auto totype = dest->toPointer(); |
| 287 | // null pointers can be assigned to everything, everything can be assigned to void pointers. |
| 288 | if (fromtype == nullptr || totype == TypeVoidPtr) return true; |
| 289 | // when comparing const-ness does not matter. |
| 290 | // If not comparing, then we should not allow const to be cast away. |
| 291 | if (!forcompare && fromtype->IsConst && !totype->IsConst) return false; |
| 292 | // A type is always compatible to itself. |
| 293 | if (fromtype == totype) return true; |
| 294 | if (source->isObjectPointer() && dest->isObjectPointer()) |
| 295 | { // Pointers to different types are only compatible if both point to an object and the source type is a child of the destination type. |
| 296 | auto fromcls = static_cast<PObjectPointer*>(source)->PointedClass(); |
| 297 | auto tocls = static_cast<PObjectPointer*>(dest)->PointedClass(); |
| 298 | if (forcompare && tocls->IsDescendantOf(fromcls)) return true; |
| 299 | return (fromcls->IsDescendantOf(tocls)); |
| 300 | } |
| 301 | else if (source->isClassPointer() && dest->isClassPointer()) |
| 302 | { // The same rules apply to class pointers. A child type can be assigned to a variable of a parent type. |
| 303 | auto fromcls = static_cast<PClassPointer*>(source)->ClassRestriction; |
| 304 | auto tocls = static_cast<PClassPointer*>(dest)->ClassRestriction; |
| 305 | if (forcompare && tocls->IsDescendantOf(fromcls)) return true; |
| 306 | return (fromcls->IsDescendantOf(tocls)); |
| 307 | } |
| 308 | else if(source->isFunctionPointer() && dest->isFunctionPointer()) |
| 309 | { |
| 310 | auto from = static_cast<PFunctionPointer*>(source); |
| 311 | auto to = static_cast<PFunctionPointer*>(dest); |
| 312 | if(from->PointedType == TypeVoid) return false; |
| 313 | |
| 314 | return to->PointedType == TypeVoid || (AreCompatibleFnPtrTypes((PPrototype *)to->PointedType, (PPrototype *)from->PointedType) && from->ArgFlags == to->ArgFlags && FScopeBarrier::CheckSidesForFunctionPointer(from->Scope, to->Scope)); |
| 315 | } |
| 316 | else if(source->isRealPointer() && dest->isRealPointer()) |
| 317 | { |
| 318 | return fromtype->PointedType == totype->PointedType; |
| 319 | } |
| 320 | } |
| 321 | return false; |
| 322 | } |
| 323 | |
| 324 | |
| 325 | //========================================================================== |
no test coverage detected