UB when deleting storage-providing char array from free store?

JMC*_*JMC 8 c++ placement-new undefined-behavior language-lawyer

The following example of usage of placement-new was provided by an earlier version of the cppreference page:

char* ptr = new char[sizeof(T)]; // allocate memory
T* tptr = new(ptr) T;            // construct in allocated storage ("place")
tptr->~T();                      // destruct
delete[] ptr;                    // deallocate memory
Run Code Online (Sandbox Code Playgroud)

Inspired by this comment on an older SO thread I have come to the conclusion that this might be UB. However, in the talk page of that cppreference article there is a small discussion as to whether this is actually the case.

The comment was based on this standard excerpt which might suggest that it could be UB:

[expr.delete] 3 In an array delete expression, if the dynamic type of the object to be deleted differs from its static type, the behavior is undefined.

Does this apply even if the T's lifetime has ended? EDIT: As pointed out by Language Lawyer in the comments: the dynamic type of ptr remains unchanged, so this doesn't apply.

On the other hand [basic.life] says that: (bold part addded by me)

[...] after the lifetime of an object has ended and before the storage which the object occupied is reused or released, any pointer that represents the address of the storage location where the object will be or was located may be used but only in limited ways. [...] such a pointer refers to allocated storage ([basic.stc.dynamic.allocation]), and using the pointer as if the pointer were of type void* is well-defined. (Please note: [exp.delete] notes that "an object cannot be deleted using a pointer of type void*") Indirection through such a pointer is permitted but the resulting lvalue may only be used in limited ways, as described below. The program has undefined behavior if:

-the object will be or was of a class type with a non-trivial destructor and the pointer is used as the operand of a delete-expression,

...

As the char[] is not a class type with a non-trivial destructor, this doesn't apply and neither do the other elements of the list of explicitly undefined behaviours of that paragraph. However, does that imply that it is otherwise well-defined? That specific bullet point seems to suggest that is is the possible destructor mismatch that would present a problem, which doesn't apply here.

Also, the wording is "before the storage which the object occupied is reused", but technically it has been reused, it's just that the object that reused it also doesn't live anymore. It could be possible that only a pointer to the object with the most recent life time in that storage is allowed to be used here.

In conclusion: is it UB to delete a dynamically allocated char array after it has provided storage for another object that has since been destructed? If yes, is there a legal way to deallocate it at all, or should it be completely replaced with an explicit operator new / operator delete combination like how the standard allocator does it?