@@ -3370,15 +3370,23 @@ bool Compiler<Emitter>::VisitCXXNewExpr(const CXXNewExpr *E) {
3370
3370
3371
3371
PrimType SizeT = classifyPrim (Stripped->getType ());
3372
3372
3373
+ // Save evaluated array size to a variable.
3374
+ unsigned ArrayLen = allocateLocalPrimitive (
3375
+ Stripped, SizeT, /* IsConst=*/ false , /* IsExtended=*/ false );
3376
+ if (!this ->visit (Stripped))
3377
+ return false ;
3378
+ if (!this ->emitSetLocal (SizeT, ArrayLen, E))
3379
+ return false ;
3380
+
3373
3381
if (PlacementDest) {
3374
3382
if (!this ->visit (PlacementDest))
3375
3383
return false ;
3376
- if (!this ->visit (Stripped ))
3384
+ if (!this ->emitGetLocal (SizeT, ArrayLen, E ))
3377
3385
return false ;
3378
3386
if (!this ->emitCheckNewTypeMismatchArray (SizeT, E, E))
3379
3387
return false ;
3380
3388
} else {
3381
- if (!this ->visit (Stripped ))
3389
+ if (!this ->emitGetLocal (SizeT, ArrayLen, E ))
3382
3390
return false ;
3383
3391
3384
3392
if (ElemT) {
@@ -3392,10 +3400,113 @@ bool Compiler<Emitter>::VisitCXXNewExpr(const CXXNewExpr *E) {
3392
3400
}
3393
3401
}
3394
3402
3395
- if (Init && !this ->visitInitializer (Init))
3396
- return false ;
3403
+ if (Init) {
3404
+ QualType InitType = Init->getType ();
3405
+ size_t StaticInitElems = 0 ;
3406
+ const Expr *DynamicInit = nullptr ;
3407
+ if (const ConstantArrayType *CAT =
3408
+ Ctx.getASTContext ().getAsConstantArrayType (InitType)) {
3409
+ StaticInitElems = CAT->getZExtSize ();
3410
+ if (!this ->visitInitializer (Init))
3411
+ return false ;
3397
3412
3398
- } else {
3413
+ if (const auto *ILE = dyn_cast<InitListExpr>(Init);
3414
+ ILE && ILE->hasArrayFiller ())
3415
+ DynamicInit = ILE->getArrayFiller ();
3416
+ }
3417
+
3418
+ // The initializer initializes a certain number of elements, S.
3419
+ // However, the complete number of elements, N, might be larger than that.
3420
+ // In this case, we need to get an initializer for the remaining elements.
3421
+ // There are to cases:
3422
+ // 1) For the form 'new Struct[n];', the initializer is a
3423
+ // CXXConstructExpr and its type is an IncompleteArrayType.
3424
+ // 2) For the form 'new Struct[n]{1,2,3}', the initializer is an
3425
+ // InitListExpr and the initializer for the remaining elements
3426
+ // is the array filler.
3427
+
3428
+ if (DynamicInit || InitType->isIncompleteArrayType ()) {
3429
+ const Function *CtorFunc = nullptr ;
3430
+ if (const auto *CE = dyn_cast<CXXConstructExpr>(Init)) {
3431
+ CtorFunc = getFunction (CE->getConstructor ());
3432
+ if (!CtorFunc)
3433
+ return false ;
3434
+ }
3435
+
3436
+ LabelTy EndLabel = this ->getLabel ();
3437
+ LabelTy StartLabel = this ->getLabel ();
3438
+
3439
+ // In the nothrow case, the alloc above might have returned nullptr.
3440
+ // Don't call any constructors that case.
3441
+ if (IsNoThrow) {
3442
+ if (!this ->emitDupPtr (E))
3443
+ return false ;
3444
+ if (!this ->emitNullPtr (0 , nullptr , E))
3445
+ return false ;
3446
+ if (!this ->emitEQPtr (E))
3447
+ return false ;
3448
+ if (!this ->jumpTrue (EndLabel))
3449
+ return false ;
3450
+ }
3451
+
3452
+ // Create loop variables.
3453
+ unsigned Iter = allocateLocalPrimitive (
3454
+ Stripped, SizeT, /* IsConst=*/ false , /* IsExtended=*/ false );
3455
+ if (!this ->emitConst (StaticInitElems, SizeT, E))
3456
+ return false ;
3457
+ if (!this ->emitSetLocal (SizeT, Iter, E))
3458
+ return false ;
3459
+
3460
+ this ->fallthrough (StartLabel);
3461
+ this ->emitLabel (StartLabel);
3462
+ // Condition. Iter < ArrayLen?
3463
+ if (!this ->emitGetLocal (SizeT, Iter, E))
3464
+ return false ;
3465
+ if (!this ->emitGetLocal (SizeT, ArrayLen, E))
3466
+ return false ;
3467
+ if (!this ->emitLT (SizeT, E))
3468
+ return false ;
3469
+ if (!this ->jumpFalse (EndLabel))
3470
+ return false ;
3471
+
3472
+ // Pointer to the allocated array is already on the stack.
3473
+ if (!this ->emitGetLocal (SizeT, Iter, E))
3474
+ return false ;
3475
+ if (!this ->emitArrayElemPtr (SizeT, E))
3476
+ return false ;
3477
+
3478
+ if (DynamicInit) {
3479
+ if (std::optional<PrimType> InitT = classify (DynamicInit)) {
3480
+ if (!this ->visit (DynamicInit))
3481
+ return false ;
3482
+ if (!this ->emitStorePop (*InitT, E))
3483
+ return false ;
3484
+ } else {
3485
+ if (!this ->visitInitializer (DynamicInit))
3486
+ return false ;
3487
+ if (!this ->emitPopPtr (E))
3488
+ return false ;
3489
+ }
3490
+ } else {
3491
+ assert (CtorFunc);
3492
+ if (!this ->emitCall (CtorFunc, 0 , E))
3493
+ return false ;
3494
+ }
3495
+
3496
+ // ++Iter;
3497
+ if (!this ->emitGetPtrLocal (Iter, E))
3498
+ return false ;
3499
+ if (!this ->emitIncPop (SizeT, E))
3500
+ return false ;
3501
+
3502
+ if (!this ->jump (StartLabel))
3503
+ return false ;
3504
+
3505
+ this ->fallthrough (EndLabel);
3506
+ this ->emitLabel (EndLabel);
3507
+ }
3508
+ }
3509
+ } else { // Non-array.
3399
3510
if (PlacementDest) {
3400
3511
if (!this ->visit (PlacementDest))
3401
3512
return false ;
0 commit comments