@@ -3097,12 +3097,11 @@ bool Compiler<Emitter>::VisitCXXNewExpr(const CXXNewExpr *E) {
30973097 QualType ElementType = E->getAllocatedType ();
30983098 std::optional<PrimType> ElemT = classify (ElementType);
30993099 unsigned PlacementArgs = E->getNumPlacementArgs ();
3100+ const FunctionDecl *OperatorNew = E->getOperatorNew ();
3101+ const Expr *PlacementDest = nullptr ;
31003102 bool IsNoThrow = false ;
31013103
3102- // FIXME: Better diagnostic. diag::note_constexpr_new_placement
31033104 if (PlacementArgs != 0 ) {
3104- // The only new-placement list we support is of the form (std::nothrow).
3105- //
31063105 // FIXME: There is no restriction on this, but it's not clear that any
31073106 // other form makes any sense. We get here for cases such as:
31083107 //
@@ -3111,27 +3110,43 @@ bool Compiler<Emitter>::VisitCXXNewExpr(const CXXNewExpr *E) {
31113110 // (which should presumably be valid only if N is a multiple of
31123111 // alignof(int), and in any case can't be deallocated unless N is
31133112 // alignof(X) and X has new-extended alignment).
3114- if (PlacementArgs != 1 || !E->getPlacementArg (0 )->getType ()->isNothrowT ())
3115- return this ->emitInvalid (E);
3113+ if (PlacementArgs == 1 ) {
3114+ const Expr *Arg1 = E->getPlacementArg (0 );
3115+ if (Arg1->getType ()->isNothrowT ()) {
3116+ if (!this ->discard (Arg1))
3117+ return false ;
3118+ IsNoThrow = true ;
3119+ } else if (Ctx.getLangOpts ().CPlusPlus26 &&
3120+ OperatorNew->isReservedGlobalPlacementOperator ()) {
3121+ // If we have a placement-new destination, we'll later use that instead
3122+ // of allocating.
3123+ PlacementDest = Arg1;
3124+ } else {
3125+ return this ->emitInvalidNewDeleteExpr (E, E);
3126+ }
31163127
3117- if (!this ->discard (E->getPlacementArg (0 )))
3118- return false ;
3119- IsNoThrow = true ;
3128+ } else {
3129+ return this ->emitInvalid (E);
3130+ }
3131+ } else if (!OperatorNew->isReplaceableGlobalAllocationFunction ()) {
3132+ return this ->emitInvalidNewDeleteExpr (E, E);
31203133 }
31213134
31223135 const Descriptor *Desc;
3123- if (ElemT) {
3124- if (E->isArray ())
3125- Desc = nullptr ; // We're not going to use it in this case.
3126- else
3127- Desc = P.createDescriptor (E, *ElemT, Descriptor::InlineDescMD,
3128- /* IsConst=*/ false , /* IsTemporary=*/ false ,
3129- /* IsMutable=*/ false );
3130- } else {
3131- Desc = P.createDescriptor (
3132- E, ElementType.getTypePtr (),
3133- E->isArray () ? std::nullopt : Descriptor::InlineDescMD,
3134- /* IsConst=*/ false , /* IsTemporary=*/ false , /* IsMutable=*/ false , Init);
3136+ if (!PlacementDest) {
3137+ if (ElemT) {
3138+ if (E->isArray ())
3139+ Desc = nullptr ; // We're not going to use it in this case.
3140+ else
3141+ Desc = P.createDescriptor (E, *ElemT, Descriptor::InlineDescMD,
3142+ /* IsConst=*/ false , /* IsTemporary=*/ false ,
3143+ /* IsMutable=*/ false );
3144+ } else {
3145+ Desc = P.createDescriptor (
3146+ E, ElementType.getTypePtr (),
3147+ E->isArray () ? std::nullopt : Descriptor::InlineDescMD,
3148+ /* IsConst=*/ false , /* IsTemporary=*/ false , /* IsMutable=*/ false , Init);
3149+ }
31353150 }
31363151
31373152 if (E->isArray ()) {
@@ -3148,26 +3163,42 @@ bool Compiler<Emitter>::VisitCXXNewExpr(const CXXNewExpr *E) {
31483163
31493164 PrimType SizeT = classifyPrim (Stripped->getType ());
31503165
3151- if (! this -> visit (Stripped))
3152- return false ;
3153-
3154- if (ElemT) {
3155- // N primitive elements.
3156- if (!this ->emitAllocN (SizeT, *ElemT, E, IsNoThrow , E))
3166+ if (PlacementDest) {
3167+ if (! this -> visit (PlacementDest))
3168+ return false ;
3169+ if (! this -> visit (Stripped))
3170+ return false ;
3171+ if (!this ->emitCheckNewTypeMismatchArray (SizeT, E , E))
31573172 return false ;
31583173 } else {
3159- // N Composite elements.
3160- if (!this ->emitAllocCN (SizeT, Desc, IsNoThrow, E))
3174+ if (!this ->visit (Stripped))
31613175 return false ;
3176+
3177+ if (ElemT) {
3178+ // N primitive elements.
3179+ if (!this ->emitAllocN (SizeT, *ElemT, E, IsNoThrow, E))
3180+ return false ;
3181+ } else {
3182+ // N Composite elements.
3183+ if (!this ->emitAllocCN (SizeT, Desc, IsNoThrow, E))
3184+ return false ;
3185+ }
31623186 }
31633187
31643188 if (Init && !this ->visitInitializer (Init))
31653189 return false ;
31663190
31673191 } else {
3168- // Allocate just one element.
3169- if (!this ->emitAlloc (Desc, E))
3170- return false ;
3192+ if (PlacementDest) {
3193+ if (!this ->visit (PlacementDest))
3194+ return false ;
3195+ if (!this ->emitCheckNewTypeMismatch (E, E))
3196+ return false ;
3197+ } else {
3198+ // Allocate just one element.
3199+ if (!this ->emitAlloc (Desc, E))
3200+ return false ;
3201+ }
31713202
31723203 if (Init) {
31733204 if (ElemT) {
@@ -3194,6 +3225,11 @@ template <class Emitter>
31943225bool Compiler<Emitter>::VisitCXXDeleteExpr(const CXXDeleteExpr *E) {
31953226 const Expr *Arg = E->getArgument ();
31963227
3228+ const FunctionDecl *OperatorDelete = E->getOperatorDelete ();
3229+
3230+ if (!OperatorDelete->isReplaceableGlobalAllocationFunction ())
3231+ return this ->emitInvalidNewDeleteExpr (E, E);
3232+
31973233 // Arg must be an lvalue.
31983234 if (!this ->visit (Arg))
31993235 return false ;
0 commit comments