@@ -3294,164 +3294,210 @@ void SemaHLSL::processExplicitBindingsOnDecl(VarDecl *VD) {
32943294 if (!HasBinding && isResourceRecordTypeOrArrayOf (VD))
32953295 SemaRef.Diag (VD->getLocation (), diag::warn_hlsl_implicit_binding);
32963296}
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++;
33053328 return true ;
33063329 }
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- }
33163330
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+ }
33273339
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 ();
33303342
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 );
33333345
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 ();
33363348
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 ());
33423354
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 ;
33493363 }
3350- return true ;
3351- }
33523364
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 ())
33873375 return false ;
3388- if (!BuildInitializerList (S, Ctx, Res .get (), List, DestTypes ))
3376+ if (!buildInitializerListImpl (ElExpr .get ()))
33893377 return false ;
33903378 }
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+ }
33913404 }
3405+ return true ;
33923406 }
3393- return true ;
3394- }
33953407
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+ }
34313444 }
34323445 }
3446+ auto *NewInit = new (Ctx) InitListExpr (Ctx, Inits.front ()->getBeginLoc (),
3447+ Inits, Inits.back ()->getEndLoc ());
3448+ NewInit->setType (Ty);
3449+ return NewInit;
34333450 }
3434- auto *NewInit = new (Ctx) InitListExpr (Ctx, Inits.front ()->getBeginLoc (),
3435- Inits, Inits.back ()->getEndLoc ());
3436- NewInit->setType (Ty);
3437- return NewInit;
3438- }
34393451
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,
34423494 InitListExpr *Init) {
34433495 // If the initializer is a scalar, just return it.
34443496 if (Init->getType ()->isScalarType ())
34453497 return true ;
34463498 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);
34533500
3454- llvm::SmallVector<Expr *, 16 > ArgExprs;
34553501 for (unsigned I = 0 ; I < Init->getNumInits (); ++I) {
34563502 Expr *E = Init->getInit (I);
34573503 if (E->HasSideEffects (Ctx)) {
@@ -3462,21 +3508,35 @@ bool SemaHLSL::TransformInitList(const InitializedEntity &Entity,
34623508 E->getObjectKind (), E);
34633509 Init->setInit (I, E);
34643510 }
3465- if (!BuildInitializerList (SemaRef, Ctx, E, ArgExprs, DestTypes ))
3511+ if (!ILT. buildInitializerList (E ))
34663512 return false ;
34673513 }
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;
34683523
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 ;
34713532 SemaRef.Diag (Init->getBeginLoc (), diag::err_hlsl_incorrect_num_initializers)
3472- << TooManyOrFew << InitTy << DestTypes. size () << ArgExprs. size () ;
3533+ << TooManyOrFew << InitTy << ExpectedSize << ActualSize ;
34733534 return false ;
34743535 }
34753536
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
34783538 // scalar case is handled above.
3479- auto *NewInit = cast<InitListExpr>(GenerateInitLists (Ctx, InitTy, It ));
3539+ auto *NewInit = cast<InitListExpr>(ILT. generateInitLists ( ));
34803540 Init->resizeInits (Ctx, NewInit->getNumInits ());
34813541 for (unsigned I = 0 ; I < NewInit->getNumInits (); ++I)
34823542 Init->updateInit (Ctx, I, NewInit->getInit (I));
0 commit comments