@@ -3294,164 +3294,210 @@ void SemaHLSL::processExplicitBindingsOnDecl(VarDecl *VD) {
3294
3294
if (!HasBinding && isResourceRecordTypeOrArrayOf (VD))
3295
3295
SemaRef.Diag (VD->getLocation (), diag::warn_hlsl_implicit_binding);
3296
3296
}
3297
-
3298
- static bool CastInitializer (Sema &S, ASTContext &Ctx, Expr *E,
3299
- llvm::SmallVectorImpl<Expr *> &List,
3300
- llvm::SmallVectorImpl<QualType> &DestTypes) {
3301
- if (List.size () >= DestTypes.size ()) {
3302
- List.push_back (E);
3303
- // This is odd, but it isn't technically a failure due to conversion, we
3304
- // handle mismatched counts of arguments differently.
3297
+ namespace {
3298
+ class InitListTransformer {
3299
+ Sema &S;
3300
+ ASTContext &Ctx;
3301
+ QualType InitTy;
3302
+ QualType *DstIt = nullptr ;
3303
+ Expr **ArgIt = nullptr ;
3304
+ // Is wrapping the destination type iterator required? This is only used for
3305
+ // incomplete array types where we loop over the destination type since we
3306
+ // don't know the full number of elements from the declaration.
3307
+ bool Wrap;
3308
+
3309
+ bool castInitializer (Expr *E) {
3310
+ assert (DstIt && " This should always be something!" );
3311
+ if (DstIt == DestTypes.end ()) {
3312
+ if (!Wrap) {
3313
+ ArgExprs.push_back (E);
3314
+ // This is odd, but it isn't technically a failure due to conversion, we
3315
+ // handle mismatched counts of arguments differently.
3316
+ return true ;
3317
+ }
3318
+ DstIt = DestTypes.begin ();
3319
+ }
3320
+ InitializedEntity Entity = InitializedEntity::InitializeParameter (
3321
+ Ctx, *DstIt, /* Consumed (ObjC) */ false );
3322
+ ExprResult Res = S.PerformCopyInitialization (Entity, E->getBeginLoc (), E);
3323
+ if (Res.isInvalid ())
3324
+ return false ;
3325
+ Expr *Init = Res.get ();
3326
+ ArgExprs.push_back (Init);
3327
+ DstIt++;
3305
3328
return true ;
3306
3329
}
3307
- InitializedEntity Entity = InitializedEntity::InitializeParameter (
3308
- Ctx, DestTypes[List.size ()], false );
3309
- ExprResult Res = S.PerformCopyInitialization (Entity, E->getBeginLoc (), E);
3310
- if (Res.isInvalid ())
3311
- return false ;
3312
- Expr *Init = Res.get ();
3313
- List.push_back (Init);
3314
- return true ;
3315
- }
3316
3330
3317
- static bool BuildInitializerList (Sema &S, ASTContext &Ctx, Expr *E,
3318
- llvm::SmallVectorImpl<Expr *> &List,
3319
- llvm::SmallVectorImpl<QualType> &DestTypes) {
3320
- // If this is an initialization list, traverse the sub initializers.
3321
- if (auto *Init = dyn_cast<InitListExpr>(E)) {
3322
- for (auto *SubInit : Init->inits ())
3323
- if (!BuildInitializerList (S, Ctx, SubInit, List, DestTypes))
3324
- return false ;
3325
- return true ;
3326
- }
3331
+ bool buildInitializerListImpl (Expr *E) {
3332
+ // If this is an initialization list, traverse the sub initializers.
3333
+ if (auto *Init = dyn_cast<InitListExpr>(E)) {
3334
+ for (auto *SubInit : Init->inits ())
3335
+ if (!buildInitializerListImpl (SubInit))
3336
+ return false ;
3337
+ return true ;
3338
+ }
3327
3339
3328
- // If this is a scalar type, just enqueue the expression.
3329
- QualType Ty = E->getType ();
3340
+ // If this is a scalar type, just enqueue the expression.
3341
+ QualType Ty = E->getType ();
3330
3342
3331
- if (Ty->isScalarType () || (Ty->isRecordType () && !Ty->isAggregateType ()))
3332
- return CastInitializer (S, Ctx, E, List, DestTypes );
3343
+ if (Ty->isScalarType () || (Ty->isRecordType () && !Ty->isAggregateType ()))
3344
+ return castInitializer (E );
3333
3345
3334
- if (auto *VecTy = Ty->getAs <VectorType>()) {
3335
- uint64_t Size = VecTy->getNumElements ();
3346
+ if (auto *VecTy = Ty->getAs <VectorType>()) {
3347
+ uint64_t Size = VecTy->getNumElements ();
3336
3348
3337
- QualType SizeTy = Ctx.getSizeType ();
3338
- uint64_t SizeTySize = Ctx.getTypeSize (SizeTy);
3339
- for (uint64_t I = 0 ; I < Size ; ++I) {
3340
- auto *Idx = IntegerLiteral::Create (Ctx, llvm::APInt (SizeTySize, I),
3341
- SizeTy, SourceLocation ());
3349
+ QualType SizeTy = Ctx.getSizeType ();
3350
+ uint64_t SizeTySize = Ctx.getTypeSize (SizeTy);
3351
+ for (uint64_t I = 0 ; I < Size ; ++I) {
3352
+ auto *Idx = IntegerLiteral::Create (Ctx, llvm::APInt (SizeTySize, I),
3353
+ SizeTy, SourceLocation ());
3342
3354
3343
- ExprResult ElExpr = S.CreateBuiltinArraySubscriptExpr (
3344
- E, E->getBeginLoc (), Idx, E->getEndLoc ());
3345
- if (ElExpr.isInvalid ())
3346
- return false ;
3347
- if (!CastInitializer (S, Ctx, ElExpr.get (), List, DestTypes))
3348
- return false ;
3355
+ ExprResult ElExpr = S.CreateBuiltinArraySubscriptExpr (
3356
+ E, E->getBeginLoc (), Idx, E->getEndLoc ());
3357
+ if (ElExpr.isInvalid ())
3358
+ return false ;
3359
+ if (!castInitializer (ElExpr.get ()))
3360
+ return false ;
3361
+ }
3362
+ return true ;
3349
3363
}
3350
- return true ;
3351
- }
3352
3364
3353
- if (auto *ArrTy = dyn_cast<ConstantArrayType>(Ty.getTypePtr ())) {
3354
- uint64_t Size = ArrTy->getZExtSize ();
3355
- QualType SizeTy = Ctx.getSizeType ();
3356
- uint64_t SizeTySize = Ctx.getTypeSize (SizeTy);
3357
- for (uint64_t I = 0 ; I < Size ; ++I) {
3358
- auto *Idx = IntegerLiteral::Create (Ctx, llvm::APInt (SizeTySize, I),
3359
- SizeTy, SourceLocation ());
3360
- ExprResult ElExpr = S.CreateBuiltinArraySubscriptExpr (
3361
- E, E->getBeginLoc (), Idx, E->getEndLoc ());
3362
- if (ElExpr.isInvalid ())
3363
- return false ;
3364
- if (!BuildInitializerList (S, Ctx, ElExpr.get (), List, DestTypes))
3365
- return false ;
3366
- }
3367
- return true ;
3368
- }
3369
-
3370
- if (auto *RTy = Ty->getAs <RecordType>()) {
3371
- llvm::SmallVector<const RecordType *> RecordTypes;
3372
- RecordTypes.push_back (RTy);
3373
- while (RecordTypes.back ()->getAsCXXRecordDecl ()->getNumBases ()) {
3374
- CXXRecordDecl *D = RecordTypes.back ()->getAsCXXRecordDecl ();
3375
- assert (D->getNumBases () == 1 &&
3376
- " HLSL doesn't support multiple inheritance" );
3377
- RecordTypes.push_back (D->bases_begin ()->getType ()->getAs <RecordType>());
3378
- }
3379
- while (!RecordTypes.empty ()) {
3380
- const RecordType *RT = RecordTypes.pop_back_val ();
3381
- for (auto *FD : RT->getDecl ()->fields ()) {
3382
- DeclAccessPair Found = DeclAccessPair::make (FD, FD->getAccess ());
3383
- DeclarationNameInfo NameInfo (FD->getDeclName (), E->getBeginLoc ());
3384
- ExprResult Res = S.BuildFieldReferenceExpr (
3385
- E, false , E->getBeginLoc (), CXXScopeSpec (), FD, Found, NameInfo);
3386
- if (Res.isInvalid ())
3365
+ if (auto *ArrTy = dyn_cast<ConstantArrayType>(Ty.getTypePtr ())) {
3366
+ uint64_t Size = ArrTy->getZExtSize ();
3367
+ QualType SizeTy = Ctx.getSizeType ();
3368
+ uint64_t SizeTySize = Ctx.getTypeSize (SizeTy);
3369
+ for (uint64_t I = 0 ; I < Size ; ++I) {
3370
+ auto *Idx = IntegerLiteral::Create (Ctx, llvm::APInt (SizeTySize, I),
3371
+ SizeTy, SourceLocation ());
3372
+ ExprResult ElExpr = S.CreateBuiltinArraySubscriptExpr (
3373
+ E, E->getBeginLoc (), Idx, E->getEndLoc ());
3374
+ if (ElExpr.isInvalid ())
3387
3375
return false ;
3388
- if (!BuildInitializerList (S, Ctx, Res .get (), List, DestTypes ))
3376
+ if (!buildInitializerListImpl (ElExpr .get ()))
3389
3377
return false ;
3390
3378
}
3379
+ return true ;
3380
+ }
3381
+
3382
+ if (auto *RTy = Ty->getAs <RecordType>()) {
3383
+ llvm::SmallVector<const RecordType *> RecordTypes;
3384
+ RecordTypes.push_back (RTy);
3385
+ while (RecordTypes.back ()->getAsCXXRecordDecl ()->getNumBases ()) {
3386
+ CXXRecordDecl *D = RecordTypes.back ()->getAsCXXRecordDecl ();
3387
+ assert (D->getNumBases () == 1 &&
3388
+ " HLSL doesn't support multiple inheritance" );
3389
+ RecordTypes.push_back (D->bases_begin ()->getType ()->getAs <RecordType>());
3390
+ }
3391
+ while (!RecordTypes.empty ()) {
3392
+ const RecordType *RT = RecordTypes.pop_back_val ();
3393
+ for (auto *FD : RT->getDecl ()->fields ()) {
3394
+ DeclAccessPair Found = DeclAccessPair::make (FD, FD->getAccess ());
3395
+ DeclarationNameInfo NameInfo (FD->getDeclName (), E->getBeginLoc ());
3396
+ ExprResult Res = S.BuildFieldReferenceExpr (
3397
+ E, false , E->getBeginLoc (), CXXScopeSpec (), FD, Found, NameInfo);
3398
+ if (Res.isInvalid ())
3399
+ return false ;
3400
+ if (!buildInitializerListImpl (Res.get ()))
3401
+ return false ;
3402
+ }
3403
+ }
3391
3404
}
3405
+ return true ;
3392
3406
}
3393
- return true ;
3394
- }
3395
3407
3396
- static Expr *GenerateInitLists (ASTContext &Ctx, QualType Ty,
3397
- llvm::SmallVectorImpl<Expr *>::iterator &It) {
3398
- if (Ty->isScalarType () || (Ty->isRecordType () && !Ty->isAggregateType ())) {
3399
- return *(It++);
3400
- }
3401
- llvm::SmallVector<Expr *> Inits;
3402
- assert (!isa<MatrixType>(Ty) && " Matrix types not yet supported in HLSL" );
3403
- Ty = Ty.getDesugaredType (Ctx);
3404
- if (Ty->isVectorType () || Ty->isConstantArrayType ()) {
3405
- QualType ElTy;
3406
- uint64_t Size = 0 ;
3407
- if (auto *ATy = Ty->getAs <VectorType>()) {
3408
- ElTy = ATy->getElementType ();
3409
- Size = ATy->getNumElements ();
3410
- } else {
3411
- auto *VTy = cast<ConstantArrayType>(Ty.getTypePtr ());
3412
- ElTy = VTy->getElementType ();
3413
- Size = VTy->getZExtSize ();
3414
- }
3415
- for (uint64_t I = 0 ; I < Size ; ++I)
3416
- Inits.push_back (GenerateInitLists (Ctx, ElTy, It));
3417
- }
3418
- if (auto *RTy = Ty->getAs <RecordType>()) {
3419
- llvm::SmallVector<const RecordType *> RecordTypes;
3420
- RecordTypes.push_back (RTy);
3421
- while (RecordTypes.back ()->getAsCXXRecordDecl ()->getNumBases ()) {
3422
- CXXRecordDecl *D = RecordTypes.back ()->getAsCXXRecordDecl ();
3423
- assert (D->getNumBases () == 1 &&
3424
- " HLSL doesn't support multiple inheritance" );
3425
- RecordTypes.push_back (D->bases_begin ()->getType ()->getAs <RecordType>());
3426
- }
3427
- while (!RecordTypes.empty ()) {
3428
- const RecordType *RT = RecordTypes.pop_back_val ();
3429
- for (auto *FD : RT->getDecl ()->fields ()) {
3430
- Inits.push_back (GenerateInitLists (Ctx, FD->getType (), It));
3408
+ Expr *generateInitListsImpl (QualType Ty) {
3409
+ assert (ArgIt != ArgExprs.end () && " Something is off in iteration!" );
3410
+ if (Ty->isScalarType () || (Ty->isRecordType () && !Ty->isAggregateType ()))
3411
+ return *(ArgIt++);
3412
+
3413
+ llvm::SmallVector<Expr *> Inits;
3414
+ assert (!isa<MatrixType>(Ty) && " Matrix types not yet supported in HLSL" );
3415
+ Ty = Ty.getDesugaredType (Ctx);
3416
+ if (Ty->isVectorType () || Ty->isConstantArrayType ()) {
3417
+ QualType ElTy;
3418
+ uint64_t Size = 0 ;
3419
+ if (auto *ATy = Ty->getAs <VectorType>()) {
3420
+ ElTy = ATy->getElementType ();
3421
+ Size = ATy->getNumElements ();
3422
+ } else {
3423
+ auto *VTy = cast<ConstantArrayType>(Ty.getTypePtr ());
3424
+ ElTy = VTy->getElementType ();
3425
+ Size = VTy->getZExtSize ();
3426
+ }
3427
+ for (uint64_t I = 0 ; I < Size ; ++I)
3428
+ Inits.push_back (generateInitListsImpl (ElTy));
3429
+ }
3430
+ if (auto *RTy = Ty->getAs <RecordType>()) {
3431
+ llvm::SmallVector<const RecordType *> RecordTypes;
3432
+ RecordTypes.push_back (RTy);
3433
+ while (RecordTypes.back ()->getAsCXXRecordDecl ()->getNumBases ()) {
3434
+ CXXRecordDecl *D = RecordTypes.back ()->getAsCXXRecordDecl ();
3435
+ assert (D->getNumBases () == 1 &&
3436
+ " HLSL doesn't support multiple inheritance" );
3437
+ RecordTypes.push_back (D->bases_begin ()->getType ()->getAs <RecordType>());
3438
+ }
3439
+ while (!RecordTypes.empty ()) {
3440
+ const RecordType *RT = RecordTypes.pop_back_val ();
3441
+ for (auto *FD : RT->getDecl ()->fields ()) {
3442
+ Inits.push_back (generateInitListsImpl (FD->getType ()));
3443
+ }
3431
3444
}
3432
3445
}
3446
+ auto *NewInit = new (Ctx) InitListExpr (Ctx, Inits.front ()->getBeginLoc (),
3447
+ Inits, Inits.back ()->getEndLoc ());
3448
+ NewInit->setType (Ty);
3449
+ return NewInit;
3433
3450
}
3434
- auto *NewInit = new (Ctx) InitListExpr (Ctx, Inits.front ()->getBeginLoc (),
3435
- Inits, Inits.back ()->getEndLoc ());
3436
- NewInit->setType (Ty);
3437
- return NewInit;
3438
- }
3439
3451
3440
- bool SemaHLSL::TransformInitList (const InitializedEntity &Entity,
3441
- const InitializationKind &Kind,
3452
+ public:
3453
+ llvm::SmallVector<QualType, 16 > DestTypes;
3454
+ llvm::SmallVector<Expr *, 16 > ArgExprs;
3455
+ InitListTransformer (Sema &SemaRef, const InitializedEntity &Entity)
3456
+ : S(SemaRef), Ctx(SemaRef.getASTContext()),
3457
+ Wrap (Entity.getType()->isIncompleteArrayType()) {
3458
+ InitTy = Entity.getType ().getNonReferenceType ();
3459
+ // When we're generating initializer lists for incomplete array types we
3460
+ // need to wrap around both when building the initializers and when
3461
+ // generating the final initializer lists.
3462
+ if (Wrap) {
3463
+ assert (InitTy->isIncompleteArrayType ());
3464
+ const IncompleteArrayType *IAT = Ctx.getAsIncompleteArrayType (InitTy);
3465
+ InitTy = IAT->getElementType ();
3466
+ }
3467
+ BuildFlattenedTypeList (InitTy, DestTypes);
3468
+ DstIt = DestTypes.begin ();
3469
+ }
3470
+
3471
+ bool buildInitializerList (Expr *E) { return buildInitializerListImpl (E); }
3472
+
3473
+ Expr *generateInitLists () {
3474
+ assert (!ArgExprs.empty () &&
3475
+ " Call buildInitializerList to generate argument expressions." );
3476
+ ArgIt = ArgExprs.begin ();
3477
+ if (!Wrap)
3478
+ return generateInitListsImpl (InitTy);
3479
+ llvm::SmallVector<Expr *> Inits;
3480
+ while (ArgIt != ArgExprs.end ())
3481
+ Inits.push_back (generateInitListsImpl (InitTy));
3482
+
3483
+ auto *NewInit = new (Ctx) InitListExpr (Ctx, Inits.front ()->getBeginLoc (),
3484
+ Inits, Inits.back ()->getEndLoc ());
3485
+ llvm::APInt ArySize (64 , Inits.size ());
3486
+ NewInit->setType (Ctx.getConstantArrayType (InitTy, ArySize, nullptr ,
3487
+ ArraySizeModifier::Normal, 0 ));
3488
+ return NewInit;
3489
+ }
3490
+ };
3491
+ } // namespace
3492
+
3493
+ bool SemaHLSL::transformInitList (const InitializedEntity &Entity,
3442
3494
InitListExpr *Init) {
3443
3495
// If the initializer is a scalar, just return it.
3444
3496
if (Init->getType ()->isScalarType ())
3445
3497
return true ;
3446
3498
ASTContext &Ctx = SemaRef.getASTContext ();
3447
- llvm::SmallVector<QualType, 16 > DestTypes;
3448
- // An initializer list might be attempting to initialize a reference or
3449
- // rvalue-reference. When checking the initializer we should look through the
3450
- // reference.
3451
- QualType InitTy = Entity.getType ().getNonReferenceType ();
3452
- BuildFlattenedTypeList (InitTy, DestTypes);
3499
+ InitListTransformer ILT (SemaRef, Entity);
3453
3500
3454
- llvm::SmallVector<Expr *, 16 > ArgExprs;
3455
3501
for (unsigned I = 0 ; I < Init->getNumInits (); ++I) {
3456
3502
Expr *E = Init->getInit (I);
3457
3503
if (E->HasSideEffects (Ctx)) {
@@ -3462,21 +3508,35 @@ bool SemaHLSL::TransformInitList(const InitializedEntity &Entity,
3462
3508
E->getObjectKind (), E);
3463
3509
Init->setInit (I, E);
3464
3510
}
3465
- if (!BuildInitializerList (SemaRef, Ctx, E, ArgExprs, DestTypes ))
3511
+ if (!ILT. buildInitializerList (E ))
3466
3512
return false ;
3467
3513
}
3514
+ size_t ExpectedSize = ILT.DestTypes .size ();
3515
+ size_t ActualSize = ILT.ArgExprs .size ();
3516
+ // For incomplete arrays it is completely arbitrary to choose whether we think
3517
+ // the user intended fewer or more elements. This implementation assumes that
3518
+ // the user intended more, and errors that there are too few initializers to
3519
+ // complete the final element.
3520
+ if (Entity.getType ()->isIncompleteArrayType ())
3521
+ ExpectedSize =
3522
+ ((ActualSize + ExpectedSize - 1 ) / ExpectedSize) * ExpectedSize;
3468
3523
3469
- if (DestTypes.size () != ArgExprs.size ()) {
3470
- int TooManyOrFew = ArgExprs.size () > DestTypes.size () ? 1 : 0 ;
3524
+ // An initializer list might be attempting to initialize a reference or
3525
+ // rvalue-reference. When checking the initializer we should look through
3526
+ // the reference.
3527
+ QualType InitTy = Entity.getType ().getNonReferenceType ();
3528
+ if (InitTy.hasAddressSpace ())
3529
+ InitTy = SemaRef.getASTContext ().removeAddrSpaceQualType (InitTy);
3530
+ if (ExpectedSize != ActualSize) {
3531
+ int TooManyOrFew = ActualSize > ExpectedSize ? 1 : 0 ;
3471
3532
SemaRef.Diag (Init->getBeginLoc (), diag::err_hlsl_incorrect_num_initializers)
3472
- << TooManyOrFew << InitTy << DestTypes. size () << ArgExprs. size () ;
3533
+ << TooManyOrFew << InitTy << ExpectedSize << ActualSize ;
3473
3534
return false ;
3474
3535
}
3475
3536
3476
- auto It = ArgExprs.begin ();
3477
- // GenerateInitLists will always return an InitListExpr here, because the
3537
+ // generateInitListsImpl will always return an InitListExpr here, because the
3478
3538
// scalar case is handled above.
3479
- auto *NewInit = cast<InitListExpr>(GenerateInitLists (Ctx, InitTy, It ));
3539
+ auto *NewInit = cast<InitListExpr>(ILT. generateInitLists ( ));
3480
3540
Init->resizeInits (Ctx, NewInit->getNumInits ());
3481
3541
for (unsigned I = 0 ; I < NewInit->getNumInits (); ++I)
3482
3542
Init->updateInit (Ctx, I, NewInit->getInit (I));
0 commit comments