If by “illegal” you mean ill-formed, then it is illegal if the base class is inaccessible or ambiguous.
-
It is inaccessible when, for example, the base class is private.
class A {}; class B : A {}; ... B b; A *pa = &b; // ERROR: base class is inaccessible
Note that even in C++11 a C-style cast can “break through” access protection and perform a formally correct upcast
A *pa = (A *) &b; // OK, not a `reinterpret_cast`, but a valid upcast
This usage should be avoided, of course.
-
It is ambiguous if your source type contains multiple base subobjects of the target type (through multiple inheritance).
class A {}; class B : public A {}; class C : public A {}; class D : public B, public C {}; D d; A *pa = &d; // ERROR: base class is ambiguous
In such cases the upcast can be performed by explicitly “walking” the desired upcast path with intermediate upcasts to the point where the base is no longer ambiguous
B* pb = &d; A* pa = pb; // OK: points to 'D::B::A' subobject