Not true. Arrays have bounds and those are checked. However, you can do arithmetic with the type ptrdiff_t of the package Interfaces.C.Pointers. You can also do an Ada.Unchecked_Conversion on a pointer that you get from a C function. Obviously that's unsafe.
> * Dynamic allocation is straight unsafe and unchecked
If allocation on the heap fails, it will raise a Storage_Error, but you can catch it. Also, the language has a lot of restrictions on when you may copy and store a pointer.
> * Accessing uninitialised variables is not forbidden.
True, but there are pragmas like Normalize_Scalars (to initialize them to invalid values) or Initialize_Scalars.
> * You can dereference null pointers
True, but dereferencing will raise an exception. Also you can define non-null pointers like this:
type Foo_Ptr is not null access Foo;
or add a "not null" constraint to a nullable pointer type: procedure Bar (Value : not null Foo_Access);