rsmith added inline comments.
================ Comment at: lib/CodeGen/CGExprCXX.cpp:1867-1868 - if (Dtor->isVirtual()) { + if (Dtor->isVirtual() && + !(Dtor->hasAttr<FinalAttr>() || RD->hasAttr<FinalAttr>())) { CGF.CGM.getCXXABI().emitVirtualObjectDelete(CGF, DE, Ptr, ElementType, ---------------- yamauchi wrote: > rsmith wrote: > > Can we use `getDevirtualizedMethod` here instead? That catches a few other > > cases that just checking for `final` will miss, and disables this for cases > > where it will currently do the wrong thing (eg, `-fapple-kext`). See > > `EmitCXXMemberOrOperatorMemberCallExpr` for where we do this for other > > virtual calls. > > > > As a particularly terrible example: > > > > ``` > > struct A { virtual ~A() final = 0; }; > > void evil(A *p) { delete p; } > > ``` > > > > is (amazingly) valid, and must not be devirtualized because there is no > > requirement that the destructor of `A` have a definition in this program. > > (It would, however, be correct to optimize out the entire `delete` > > expression in this case, on the basis that `p` must always be `nullptr` > > whenever it's reached. But that doesn't really seem worthwhile.) > Updated. Hopefully this does the right thing. Please can you add that test to your testcases too (eg, with a `CHECK-NOT` to ensure we don't reference the destructor of `A`)? It's subtle enough that I could imagine us getting that wrong in the future. ================ Comment at: lib/CodeGen/CGExprCXX.cpp:1887 + Dtor = DevirtualizedDtor; + Ptr = CGF.EmitPointerWithAlignment(Inner); + } else { ---------------- In this case we'll emit the inner expression (including its side-effects) twice. The simplest thing to do would be to just drop this `else if` case for now and add a FIXME. Repository: rC Clang CHANGES SINCE LAST ACTION https://reviews.llvm.org/D63161/new/ https://reviews.llvm.org/D63161 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits