Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is the compiler allowed to optimize out dynamic_cast of a volatile pointer when the compiler doesn't see a possible type which can fulfill the cast?

Look at this little snippet:

struct A {
    virtual ~A() { }
};

struct B { };

bool fn() {
    A *volatile a = new A;
    return dynamic_cast<B *>(a); 
}

Is the compiler allowed to remove the dynamic_cast altogether, and transform dynamic_cast to a simple nullptr;?

The reason of this question is this answer.

Notes:

  • Assume that volatile means that the compiler cannot assume anything about a, because it's volatile. Here's a question why.

  • The fact that dynamic_cast may not be allowed to be removed is that there could be a type somewhere in the program, which derives from both A and B.

like image 779
geza Avatar asked Sep 27 '18 21:09

geza


People also ask

What does dynamic_cast return if fails?

If the dynamic_cast operator succeeds, it returns a pointer that points to the object denoted by arg . If dynamic_cast fails, it returns 0 . You may perform downcasts with the dynamic_cast operator only on polymorphic classes.

Can dynamic_cast throw exception?

dynamic_cast will no longer throw an exception when type-id is an interior pointer to a value type, with the cast failing at runtime. The cast will now return the 0 pointer value instead of throwing.

Is Static_cast faster than dynamic_cast?

While typeid + static_cast is faster than dynamic_cast , not having to switch on the runtime type of the object is faster than any of them. Save this answer.

Is dynamic_cast fast?

dynamic_cast runs at about 14.4953 nanoseconds. Checking a virtual method and static_cast ing runs at about twice the speed, 6.55936 nanoseconds.


2 Answers

Yes. dynamic_cast has no observable behavior beyond its return value.

The compiler is aware of the static type pointed to by a.

So under the as-if rule, the compiler is free to evaluate the dynamic cast at compile time.

In fact:

struct A { virtual ~A() {} };
struct B:A {};

bool foo() {
  A* a = new A;
  return dynamic_cast<B*>(a);
}

the above dynamic cast statement can also be optimized to return false; The new cannot be omitted without whole program optimization as someone could overload the global operator new; once it is proven that no global operator new is overloaded, it could even optimize out the call to new A, as neither allocating memory by the default operator new, nor creating an A nor destroying one has any observable side effects.

like image 50
Yakk - Adam Nevraumont Avatar answered Sep 22 '22 13:09

Yakk - Adam Nevraumont


Yes, a compiler can omit the call to dynamic_cast as per as-if rule 1) if and only if it can prove that the only valid result of the call is false. That's simple.

The tricky part is to prove that the only valid result of dynamic_cast is false. You can prove that iff there is no class in your whole program that inherits both from A and B.

Now I am not very versed in this part, but I think you can do that when you create the binary and have all the types in your program only if it's an executable (not a library) and only if the program doesn't dynamically link to other libraries.


1) the dynamic_cast on pointers doesn't have side effect, it doesn't throw

like image 29
bolov Avatar answered Sep 21 '22 13:09

bolov