diff --git a/lib/Differentiator/ReverseModeVisitor.cpp b/lib/Differentiator/ReverseModeVisitor.cpp index db2c7e6b1..b2b1c5238 100644 --- a/lib/Differentiator/ReverseModeVisitor.cpp +++ b/lib/Differentiator/ReverseModeVisitor.cpp @@ -734,11 +734,12 @@ Expr* ReverseModeVisitor::getStdInitListSizeExpr(const Expr* E) { initDiff.getExpr(), baseTSI, {placementArg}); } else if (CI->isDelegatingInitializer()) { - auto* thisDRE = cast(thisExpr); - auto* thisVD = cast(thisDRE->getDecl()); - Expr* newInit = utils::BuildCXXNewExpr(m_Sema, baseTy, nullptr, - initDiff.getExpr(), baseTSI); - SetDeclInit(thisVD, newInit); + // Placement-new into the malloc'd `_this` (paired with free(_this)), + // as the base-initializer path above does. An allocating + // `new ClassTy(args)` here would be freed with free() -- a mismatch. + initCall = + utils::BuildCXXNewExpr(m_Sema, baseTy, /*arraySize=*/nullptr, + initDiff.getExpr(), baseTSI, {thisExpr}); } } CompoundStmt* block = endBlock(direction::reverse); diff --git a/test/Gradient/Constructors.C b/test/Gradient/Constructors.C index fa4fcc9b2..d685885e5 100644 --- a/test/Gradient/Constructors.C +++ b/test/Gradient/Constructors.C @@ -2,8 +2,6 @@ // RUN: ./Constructors.out | %filecheck_exec %s // RUN: %cladclang -Xclang -plugin-arg-clad -Xclang -disable-tbr -Xclang -plugin-arg-clad -Xclang -enable-va %s -I%S/../../include -oConstructors.out // RUN: ./Constructors.out | %filecheck_exec %s -// FIXME: real new/free mismatch for delegating constructors; drop when fixed. -// XFAIL: valgrind #include "clad/Differentiator/Differentiator.h" #include "clad/Differentiator/STLBuiltins.h" @@ -368,15 +366,17 @@ double fn6(double x, double y) { } // x^2 * y // CHECK: static clad::ValueAndAdjoint constructor_reverse_forw(clad::Tag, double v, double u, double _d_v, double _d_u) { -// CHECK-NEXT: argByValWrapper *_this = new argByValWrapper(v); +// CHECK-NEXT: argByValWrapper *_this = (argByValWrapper *)malloc(sizeof(argByValWrapper)); // CHECK-NEXT: argByValWrapper *_d_this = (argByValWrapper *)malloc(sizeof(argByValWrapper)); // CHECK-NEXT: memset(_d_this, 0, sizeof(argByValWrapper)); +// CHECK-NEXT: new (_this) argByValWrapper(v); // CHECK-NEXT: _this->z = _this->y * u; // CHECK-NEXT: return {*_this, *_d_this}; // CHECK-NEXT: } // CHECK: static void constructor_pullback(double v, double u, argByValWrapper *_d_this, double *_d_v, double *_d_u) { -// CHECK-NEXT: argByValWrapper *_this = new argByValWrapper(v); +// CHECK-NEXT: argByValWrapper *_this = (argByValWrapper *)malloc(sizeof(argByValWrapper)); +// CHECK-NEXT: new (_this) argByValWrapper(v); // CHECK-NEXT: _this->z = _this->y * u; // CHECK-NEXT: { // CHECK-NEXT: double _r_d0 = _d_this->z;