https://github.com/llvm-beanz updated https://github.com/llvm/llvm-project/pull/133508
>From 6234f442adfebaaf73328d2c09ee443facc848b0 Mon Sep 17 00:00:00 2001 From: Chris Bieneman <chris.biene...@me.com> Date: Thu, 27 Mar 2025 09:26:31 -0500 Subject: [PATCH 1/4] [HLSL] Handle incomplete array types This refactors the initialization list transformation code to handle incomplete array types. Fixes #132958 ../clang/test/SemaHLSL/Language/InitIncompleteArrays.hlsl --- clang/lib/Sema/SemaHLSL.cpp | 131 ++++++++++++------ .../Language/InitIncompleteArrays.hlsl | 53 +++++++ clang/test/SemaHLSL/Language/InitListAST.hlsl | 78 +++++++++++ 3 files changed, 222 insertions(+), 40 deletions(-) create mode 100644 clang/test/SemaHLSL/Language/InitIncompleteArrays.hlsl diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp index 07d03e2c58b9a..cad8aa4ed0dec 100644 --- a/clang/lib/Sema/SemaHLSL.cpp +++ b/clang/lib/Sema/SemaHLSL.cpp @@ -3249,33 +3249,42 @@ void SemaHLSL::processExplicitBindingsOnDecl(VarDecl *VD) { } } } +namespace { +class InitListTransformer { + Sema &S; + ASTContext &Ctx; + QualType InitTy; + QualType *DstIt = nullptr; + Expr **ArgIt = nullptr; + bool Wrap; -static bool CastInitializer(Sema &S, ASTContext &Ctx, Expr *E, - llvm::SmallVectorImpl<Expr *> &List, - llvm::SmallVectorImpl<QualType> &DestTypes) { - if (List.size() >= DestTypes.size()) { - List.push_back(E); - // This is odd, but it isn't technically a failure due to conversion, we - // handle mismatched counts of arguments differently. - return true; + bool castInitializer(Expr *E) { + assert(DstIt && "This should always be something!"); + if (DstIt == DestTypes.end()) { + if (!Wrap) { + ArgExprs.push_back(E); + // This is odd, but it isn't technically a failure due to conversion, we + // handle mismatched counts of arguments differently. + return true; + } + DstIt = DestTypes.begin(); } - InitializedEntity Entity = InitializedEntity::InitializeParameter( - Ctx, DestTypes[List.size()], false); + InitializedEntity Entity = + InitializedEntity::InitializeParameter(Ctx, *DstIt, true); ExprResult Res = S.PerformCopyInitialization(Entity, E->getBeginLoc(), E); if (Res.isInvalid()) return false; Expr *Init = Res.get(); - List.push_back(Init); + ArgExprs.push_back(Init); + DstIt++; return true; } -static bool BuildInitializerList(Sema &S, ASTContext &Ctx, Expr *E, - llvm::SmallVectorImpl<Expr *> &List, - llvm::SmallVectorImpl<QualType> &DestTypes) { +bool buildInitializerListImpl(Expr *E) { // If this is an initialization list, traverse the sub initializers. if (auto *Init = dyn_cast<InitListExpr>(E)) { for (auto *SubInit : Init->inits()) - if (!BuildInitializerList(S, Ctx, SubInit, List, DestTypes)) + if (!buildInitializerListImpl(SubInit)) return false; return true; } @@ -3284,7 +3293,7 @@ static bool BuildInitializerList(Sema &S, ASTContext &Ctx, Expr *E, QualType Ty = E->getType(); if (Ty->isScalarType() || (Ty->isRecordType() && !Ty->isAggregateType())) - return CastInitializer(S, Ctx, E, List, DestTypes); + return castInitializer(E); if (auto *VecTy = Ty->getAs<VectorType>()) { uint64_t Size = VecTy->getNumElements(); @@ -3299,7 +3308,7 @@ static bool BuildInitializerList(Sema &S, ASTContext &Ctx, Expr *E, E, E->getBeginLoc(), Idx, E->getEndLoc()); if (ElExpr.isInvalid()) return false; - if (!CastInitializer(S, Ctx, ElExpr.get(), List, DestTypes)) + if (!castInitializer(ElExpr.get())) return false; } return true; @@ -3316,7 +3325,7 @@ static bool BuildInitializerList(Sema &S, ASTContext &Ctx, Expr *E, E, E->getBeginLoc(), Idx, E->getEndLoc()); if (ElExpr.isInvalid()) return false; - if (!BuildInitializerList(S, Ctx, ElExpr.get(), List, DestTypes)) + if (!buildInitializerListImpl(ElExpr.get())) return false; } return true; @@ -3341,7 +3350,7 @@ static bool BuildInitializerList(Sema &S, ASTContext &Ctx, Expr *E, E, false, E->getBeginLoc(), CXXScopeSpec(), FD, Found, NameInfo); if (Res.isInvalid()) return false; - if (!BuildInitializerList(S, Ctx, Res.get(), List, DestTypes)) + if (!buildInitializerListImpl(Res.get())) return false; } } @@ -3349,11 +3358,11 @@ static bool BuildInitializerList(Sema &S, ASTContext &Ctx, Expr *E, return true; } -static Expr *GenerateInitLists(ASTContext &Ctx, QualType Ty, - llvm::SmallVectorImpl<Expr *>::iterator &It) { - if (Ty->isScalarType() || (Ty->isRecordType() && !Ty->isAggregateType())) { - return *(It++); - } +Expr *generateInitListsImpl(QualType Ty) { + assert(ArgIt != ArgExprs.end() && "Something is off in iteration!"); + if (Ty->isScalarType() || (Ty->isRecordType() && !Ty->isAggregateType())) + return *(ArgIt++); + llvm::SmallVector<Expr *> Inits; assert(!isa<MatrixType>(Ty) && "Matrix types not yet supported in HLSL"); Ty = Ty.getDesugaredType(Ctx); @@ -3369,7 +3378,7 @@ static Expr *GenerateInitLists(ASTContext &Ctx, QualType Ty, Size = VTy->getZExtSize(); } for (uint64_t I = 0; I < Size; ++I) - Inits.push_back(GenerateInitLists(Ctx, ElTy, It)); + Inits.push_back(generateInitListsImpl(ElTy)); } if (auto *RTy = Ty->getAs<RecordType>()) { llvm::SmallVector<const RecordType *> RecordTypes; @@ -3384,7 +3393,7 @@ static Expr *GenerateInitLists(ASTContext &Ctx, QualType Ty, const RecordType *RT = RecordTypes.back(); RecordTypes.pop_back(); for (auto *FD : RT->getDecl()->fields()) { - Inits.push_back(GenerateInitLists(Ctx, FD->getType(), It)); + Inits.push_back(generateInitListsImpl(FD->getType())); } } } @@ -3393,6 +3402,43 @@ static Expr *GenerateInitLists(ASTContext &Ctx, QualType Ty, NewInit->setType(Ty); return NewInit; } +public: +llvm::SmallVector<QualType, 16> DestTypes; + llvm::SmallVector<Expr *, 16> ArgExprs; + InitListTransformer(Sema &SemaRef, const InitializedEntity &Entity) + : S(SemaRef), Ctx(SemaRef.getASTContext()), + Wrap(Entity.getType()->isIncompleteArrayType()) { + InitTy = Entity.getType().getNonReferenceType(); + // When we're generating initializer lists for incomplete array types we + // need to wrap around both when building the initializers and when + // generating the final initializer lists. + if (Wrap) + InitTy = QualType(InitTy->getBaseElementTypeUnsafe(),0); + BuildFlattenedTypeList(InitTy, DestTypes); + DstIt = DestTypes.begin(); + } + + bool buildInitializerList(Expr *E) { + return buildInitializerListImpl(E); + } + + Expr *generateInitLists() { + ArgIt = ArgExprs.begin(); + if (!Wrap) + return generateInitListsImpl(InitTy); + llvm::SmallVector<Expr *> Inits; + while (ArgIt != ArgExprs.end()) + Inits.push_back(generateInitListsImpl(InitTy)); + + auto *NewInit = new (Ctx) InitListExpr(Ctx, Inits.front()->getBeginLoc(), + Inits, Inits.back()->getEndLoc()); + llvm::APInt ArySize(64, Inits.size()); + NewInit->setType(Ctx.getConstantArrayType(InitTy, ArySize, nullptr, + ArraySizeModifier::Normal, 0)); + return NewInit; + } +}; +} bool SemaHLSL::TransformInitList(const InitializedEntity &Entity, const InitializationKind &Kind, @@ -3401,14 +3447,8 @@ bool SemaHLSL::TransformInitList(const InitializedEntity &Entity, if (Init->getType()->isScalarType()) return true; ASTContext &Ctx = SemaRef.getASTContext(); - llvm::SmallVector<QualType, 16> DestTypes; - // An initializer list might be attempting to initialize a reference or - // rvalue-reference. When checking the initializer we should look through the - // reference. - QualType InitTy = Entity.getType().getNonReferenceType(); - BuildFlattenedTypeList(InitTy, DestTypes); + InitListTransformer ILT(SemaRef, Entity); - llvm::SmallVector<Expr *, 16> ArgExprs; for (unsigned I = 0; I < Init->getNumInits(); ++I) { Expr *E = Init->getInit(I); if (E->HasSideEffects(Ctx)) { @@ -3419,21 +3459,32 @@ bool SemaHLSL::TransformInitList(const InitializedEntity &Entity, E->getObjectKind(), E); Init->setInit(I, E); } - if (!BuildInitializerList(SemaRef, Ctx, E, ArgExprs, DestTypes)) + if (!ILT.buildInitializerList(E)) return false; } + size_t ExpectedSize = ILT.DestTypes.size(); + size_t ActualSize = ILT.ArgExprs.size(); + // For incomplete arrays it is completely arbitrary to choose whether we think + // the user intended fewer or more elements. This implementation assumes that + // the user intended more, and errors that there are too few initializers to + // complete the final element. + if (Entity.getType()->isIncompleteArrayType()) + ExpectedSize = ((ActualSize + ExpectedSize - 1) / ExpectedSize) * ExpectedSize; - if (DestTypes.size() != ArgExprs.size()) { - int TooManyOrFew = ArgExprs.size() > DestTypes.size() ? 1 : 0; + // An initializer list might be attempting to initialize a reference or + // rvalue-reference. When checking the initializer we should look through + // the reference. + QualType InitTy = Entity.getType().getNonReferenceType(); + if (ExpectedSize != ActualSize) { + int TooManyOrFew = ActualSize > ExpectedSize ? 1 : 0; SemaRef.Diag(Init->getBeginLoc(), diag::err_hlsl_incorrect_num_initializers) - << TooManyOrFew << InitTy << DestTypes.size() << ArgExprs.size(); + << TooManyOrFew << InitTy << ExpectedSize << ActualSize; return false; } - auto It = ArgExprs.begin(); - // GenerateInitLists will always return an InitListExpr here, because the + // generateInitListsImpl will always return an InitListExpr here, because the // scalar case is handled above. - auto *NewInit = cast<InitListExpr>(GenerateInitLists(Ctx, InitTy, It)); + auto *NewInit = cast<InitListExpr>(ILT.generateInitLists()); Init->resizeInits(Ctx, NewInit->getNumInits()); for (unsigned I = 0; I < NewInit->getNumInits(); ++I) Init->updateInit(Ctx, I, NewInit->getInit(I)); diff --git a/clang/test/SemaHLSL/Language/InitIncompleteArrays.hlsl b/clang/test/SemaHLSL/Language/InitIncompleteArrays.hlsl new file mode 100644 index 0000000000000..15a991a45a6c4 --- /dev/null +++ b/clang/test/SemaHLSL/Language/InitIncompleteArrays.hlsl @@ -0,0 +1,53 @@ +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -finclude-default-header -verify -Wdouble-promotion -Wconversion %s + +// Some helpers! +template <typename T, typename U> +struct is_same { + static const bool value = false; +}; + +template <typename T> +struct is_same<T, T> { + static const bool value = true; +}; + +struct SomeVals { + int2 X; + float2 Y; + double2 D; +}; + +static SomeVals V = {1,2,3,4,5,6}; + +static int2 SomeArr[] = {V}; // #SomeArr +// expected-warning@#SomeArr 2 {{implicit conversion turns floating-point number into integer: 'double' to 'int'}} +// expected-warning@#SomeArr 2 {{implicit conversion turns floating-point number into integer: 'float' to 'int'}} + +_Static_assert(is_same<__decltype(SomeArr), int2[3]>::value, "What is this even?"); + +static int2 VecArr[] = { + int2(0,1), + int2(2,3), + int4(4,5,6,7), + }; + +_Static_assert(is_same<__decltype(VecArr), int2[4]>::value, "One vec, two vec, three vecs, FOUR!"); + +static int4 V4Arr[] = { + int2(0,1), + int2(2,3), +}; + +_Static_assert(is_same<__decltype(V4Arr), int4[1]>::value, "One!"); + +// expected-error@+1{{too few initializers in list for type 'int4[]' (aka 'vector<int, 4>[]') (expected 4 but found 2)}} +static int4 V4ArrTooSmall[] = { + int2(0,1), +}; + +// expected-error@+1{{too few initializers in list for type 'int4[]' (aka 'vector<int, 4>[]') (expected 8 but found 7)}} +static int4 V4ArrAlsoTooSmall[] = { + int2(0,1), + int2(2,3), + int3(4,5,6), +}; diff --git a/clang/test/SemaHLSL/Language/InitListAST.hlsl b/clang/test/SemaHLSL/Language/InitListAST.hlsl index d58582f9029fe..78bf269769ae6 100644 --- a/clang/test/SemaHLSL/Language/InitListAST.hlsl +++ b/clang/test/SemaHLSL/Language/InitListAST.hlsl @@ -8,6 +8,11 @@ struct TwoInts { int Z, W; }; +struct IntAndFloat { + int A; + float B; +}; + struct Doggo { int4 LegState; int TailState; @@ -981,3 +986,76 @@ FourFloats case16() { FourFloats FF = {0, makeTwo(X), 3}; return FF; } + +// CHECK-LABEL: Dumping case17 +// CHECK: VarDecl {{.*}} col:15 used Structs 'IntAndFloat[2]' cinit +// CHECK-NEXT: InitListExpr {{.*}} 'IntAndFloat[2]' +// CHECK-NEXT: InitListExpr {{.*}} 'IntAndFloat' +// CHECK-NEXT: IntegerLiteral {{.*}} 'int' 1 +// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <IntegralToFloating> +// CHECK-NEXT: IntegerLiteral {{.*}} 'int' 2 +// CHECK-NEXT: InitListExpr {{.*}} 'IntAndFloat' +// CHECK-NEXT: IntegerLiteral {{.*}} 'int' 3 +// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <IntegralToFloating> +// CHECK-NEXT: IntegerLiteral {{.*}} 'int' 4 + + +// CHECK: VarDecl {{.*}} col:9 used Floats 'float[8]' cinit +// CHECK-NEXT: InitListExpr {{.*}} 'float[8]' +// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <IntegralToFloating> +// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' <LValueToRValue> +// CHECK-NEXT: MemberExpr {{.*}} 'int' lvalue .A {{.*}} +// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'IntAndFloat' lvalue +// CHECK-NEXT: ImplicitCastExpr {{.*}} 'IntAndFloat *' <ArrayToPointerDecay> +// CHECK-NEXT: DeclRefExpr {{.*}} 'IntAndFloat[2]' lvalue Var {{.*}} 'Structs' 'IntAndFloat[2]' +// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 0 +// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue> +// CHECK-NEXT: MemberExpr {{.*}} 'float' lvalue .B {{.*}} +// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'IntAndFloat' lvalue +// CHECK-NEXT: ImplicitCastExpr {{.*}} 'IntAndFloat *' <ArrayToPointerDecay> +// CHECK-NEXT: DeclRefExpr {{.*}} 'IntAndFloat[2]' lvalue Var {{.*}} 'Structs' 'IntAndFloat[2]' +// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 0 +// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <IntegralToFloating> +// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' <LValueToRValue> +// CHECK-NEXT: MemberExpr {{.*}} 'int' lvalue .A {{.*}} +// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'IntAndFloat' lvalue +// CHECK-NEXT: ImplicitCastExpr {{.*}} 'IntAndFloat *' <ArrayToPointerDecay> +// CHECK-NEXT: DeclRefExpr {{.*}} 'IntAndFloat[2]' lvalue Var {{.*}} 'Structs' 'IntAndFloat[2]' +// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 1 +// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue> +// CHECK-NEXT: MemberExpr {{.*}} 'float' lvalue .B {{.*}} +// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'IntAndFloat' lvalue +// CHECK-NEXT: ImplicitCastExpr {{.*}} 'IntAndFloat *' <ArrayToPointerDecay> +// CHECK-NEXT: DeclRefExpr {{.*}} 'IntAndFloat[2]' lvalue Var {{.*}} 'Structs' 'IntAndFloat[2]' +// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 1 +// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <IntegralToFloating> +// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' <LValueToRValue> +// CHECK-NEXT: MemberExpr {{.*}} 'int' lvalue .A {{.*}} +// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'IntAndFloat' lvalue +// CHECK-NEXT: ImplicitCastExpr {{.*}} 'IntAndFloat *' <ArrayToPointerDecay> +// CHECK-NEXT: DeclRefExpr {{.*}} 'IntAndFloat[2]' lvalue Var {{.*}} 'Structs' 'IntAndFloat[2]' +// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 0 +// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue> +// CHECK-NEXT: MemberExpr {{.*}} 'float' lvalue .B {{.*}} +// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'IntAndFloat' lvalue +// CHECK-NEXT: ImplicitCastExpr {{.*}} 'IntAndFloat *' <ArrayToPointerDecay> +// CHECK-NEXT: DeclRefExpr {{.*}} 'IntAndFloat[2]' lvalue Var {{.*}} 'Structs' 'IntAndFloat[2]' +// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 0 +// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <IntegralToFloating> +// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' <LValueToRValue> +// CHECK-NEXT: MemberExpr {{.*}} 'int' lvalue .A {{.*}} +// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'IntAndFloat' lvalue +// CHECK-NEXT: ImplicitCastExpr {{.*}} 'IntAndFloat *' <ArrayToPointerDecay> +// CHECK-NEXT: DeclRefExpr {{.*}} 'IntAndFloat[2]' lvalue Var {{.*}} 'Structs' 'IntAndFloat[2]' +// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 1 +// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue> +// CHECK-NEXT: MemberExpr {{.*}} 'float' lvalue .B {{.*}} +// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'IntAndFloat' lvalue +// CHECK-NEXT: ImplicitCastExpr {{.*}} 'IntAndFloat *' <ArrayToPointerDecay> +// CHECK-NEXT: DeclRefExpr {{.*}} 'IntAndFloat[2]' lvalue Var {{.*}} 'Structs' 'IntAndFloat[2]' +// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 1 +float case17() { + IntAndFloat Structs[] = {1,2,3,4}; + float Floats[] = {Structs, Structs}; + return Floats[7]; +} >From 279cb38890fa933250d0ea2cdfa04aeed6f374dc Mon Sep 17 00:00:00 2001 From: Chris Bieneman <chris.biene...@me.com> Date: Fri, 28 Mar 2025 15:23:24 -0500 Subject: [PATCH 2/4] Fix formatting --- clang/lib/Sema/SemaHLSL.cpp | 262 ++++++++++++++++++------------------ 1 file changed, 131 insertions(+), 131 deletions(-) diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp index cad8aa4ed0dec..36f1ec6dd3d50 100644 --- a/clang/lib/Sema/SemaHLSL.cpp +++ b/clang/lib/Sema/SemaHLSL.cpp @@ -3258,152 +3258,153 @@ class InitListTransformer { Expr **ArgIt = nullptr; bool Wrap; - bool castInitializer(Expr *E) { - assert(DstIt && "This should always be something!"); - if (DstIt == DestTypes.end()) { - if (!Wrap) { - ArgExprs.push_back(E); - // This is odd, but it isn't technically a failure due to conversion, we - // handle mismatched counts of arguments differently. - return true; + bool castInitializer(Expr *E) { + assert(DstIt && "This should always be something!"); + if (DstIt == DestTypes.end()) { + if (!Wrap) { + ArgExprs.push_back(E); + // This is odd, but it isn't technically a failure due to conversion, we + // handle mismatched counts of arguments differently. + return true; + } + DstIt = DestTypes.begin(); } - DstIt = DestTypes.begin(); - } - InitializedEntity Entity = - InitializedEntity::InitializeParameter(Ctx, *DstIt, true); - ExprResult Res = S.PerformCopyInitialization(Entity, E->getBeginLoc(), E); - if (Res.isInvalid()) - return false; - Expr *Init = Res.get(); - ArgExprs.push_back(Init); - DstIt++; - return true; -} - -bool buildInitializerListImpl(Expr *E) { - // If this is an initialization list, traverse the sub initializers. - if (auto *Init = dyn_cast<InitListExpr>(E)) { - for (auto *SubInit : Init->inits()) - if (!buildInitializerListImpl(SubInit)) - return false; + InitializedEntity Entity = + InitializedEntity::InitializeParameter(Ctx, *DstIt, true); + ExprResult Res = S.PerformCopyInitialization(Entity, E->getBeginLoc(), E); + if (Res.isInvalid()) + return false; + Expr *Init = Res.get(); + ArgExprs.push_back(Init); + DstIt++; return true; } - // If this is a scalar type, just enqueue the expression. - QualType Ty = E->getType(); + bool buildInitializerListImpl(Expr *E) { + // If this is an initialization list, traverse the sub initializers. + if (auto *Init = dyn_cast<InitListExpr>(E)) { + for (auto *SubInit : Init->inits()) + if (!buildInitializerListImpl(SubInit)) + return false; + return true; + } - if (Ty->isScalarType() || (Ty->isRecordType() && !Ty->isAggregateType())) - return castInitializer(E); + // If this is a scalar type, just enqueue the expression. + QualType Ty = E->getType(); - if (auto *VecTy = Ty->getAs<VectorType>()) { - uint64_t Size = VecTy->getNumElements(); + if (Ty->isScalarType() || (Ty->isRecordType() && !Ty->isAggregateType())) + return castInitializer(E); - QualType SizeTy = Ctx.getSizeType(); - uint64_t SizeTySize = Ctx.getTypeSize(SizeTy); - for (uint64_t I = 0; I < Size; ++I) { - auto *Idx = IntegerLiteral::Create(Ctx, llvm::APInt(SizeTySize, I), - SizeTy, SourceLocation()); + if (auto *VecTy = Ty->getAs<VectorType>()) { + uint64_t Size = VecTy->getNumElements(); - ExprResult ElExpr = S.CreateBuiltinArraySubscriptExpr( - E, E->getBeginLoc(), Idx, E->getEndLoc()); - if (ElExpr.isInvalid()) - return false; - if (!castInitializer(ElExpr.get())) - return false; - } - return true; - } + QualType SizeTy = Ctx.getSizeType(); + uint64_t SizeTySize = Ctx.getTypeSize(SizeTy); + for (uint64_t I = 0; I < Size; ++I) { + auto *Idx = IntegerLiteral::Create(Ctx, llvm::APInt(SizeTySize, I), + SizeTy, SourceLocation()); - if (auto *ArrTy = dyn_cast<ConstantArrayType>(Ty.getTypePtr())) { - uint64_t Size = ArrTy->getZExtSize(); - QualType SizeTy = Ctx.getSizeType(); - uint64_t SizeTySize = Ctx.getTypeSize(SizeTy); - for (uint64_t I = 0; I < Size; ++I) { - auto *Idx = IntegerLiteral::Create(Ctx, llvm::APInt(SizeTySize, I), - SizeTy, SourceLocation()); - ExprResult ElExpr = S.CreateBuiltinArraySubscriptExpr( - E, E->getBeginLoc(), Idx, E->getEndLoc()); - if (ElExpr.isInvalid()) - return false; - if (!buildInitializerListImpl(ElExpr.get())) - return false; + ExprResult ElExpr = S.CreateBuiltinArraySubscriptExpr( + E, E->getBeginLoc(), Idx, E->getEndLoc()); + if (ElExpr.isInvalid()) + return false; + if (!castInitializer(ElExpr.get())) + return false; + } + return true; } - return true; - } - if (auto *RTy = Ty->getAs<RecordType>()) { - llvm::SmallVector<const RecordType *> RecordTypes; - RecordTypes.push_back(RTy); - while (RecordTypes.back()->getAsCXXRecordDecl()->getNumBases()) { - CXXRecordDecl *D = RecordTypes.back()->getAsCXXRecordDecl(); - assert(D->getNumBases() == 1 && - "HLSL doesn't support multiple inheritance"); - RecordTypes.push_back(D->bases_begin()->getType()->getAs<RecordType>()); - } - while (!RecordTypes.empty()) { - const RecordType *RT = RecordTypes.back(); - RecordTypes.pop_back(); - for (auto *FD : RT->getDecl()->fields()) { - DeclAccessPair Found = DeclAccessPair::make(FD, FD->getAccess()); - DeclarationNameInfo NameInfo(FD->getDeclName(), E->getBeginLoc()); - ExprResult Res = S.BuildFieldReferenceExpr( - E, false, E->getBeginLoc(), CXXScopeSpec(), FD, Found, NameInfo); - if (Res.isInvalid()) + if (auto *ArrTy = dyn_cast<ConstantArrayType>(Ty.getTypePtr())) { + uint64_t Size = ArrTy->getZExtSize(); + QualType SizeTy = Ctx.getSizeType(); + uint64_t SizeTySize = Ctx.getTypeSize(SizeTy); + for (uint64_t I = 0; I < Size; ++I) { + auto *Idx = IntegerLiteral::Create(Ctx, llvm::APInt(SizeTySize, I), + SizeTy, SourceLocation()); + ExprResult ElExpr = S.CreateBuiltinArraySubscriptExpr( + E, E->getBeginLoc(), Idx, E->getEndLoc()); + if (ElExpr.isInvalid()) return false; - if (!buildInitializerListImpl(Res.get())) + if (!buildInitializerListImpl(ElExpr.get())) return false; } + return true; } + + if (auto *RTy = Ty->getAs<RecordType>()) { + llvm::SmallVector<const RecordType *> RecordTypes; + RecordTypes.push_back(RTy); + while (RecordTypes.back()->getAsCXXRecordDecl()->getNumBases()) { + CXXRecordDecl *D = RecordTypes.back()->getAsCXXRecordDecl(); + assert(D->getNumBases() == 1 && + "HLSL doesn't support multiple inheritance"); + RecordTypes.push_back(D->bases_begin()->getType()->getAs<RecordType>()); + } + while (!RecordTypes.empty()) { + const RecordType *RT = RecordTypes.back(); + RecordTypes.pop_back(); + for (auto *FD : RT->getDecl()->fields()) { + DeclAccessPair Found = DeclAccessPair::make(FD, FD->getAccess()); + DeclarationNameInfo NameInfo(FD->getDeclName(), E->getBeginLoc()); + ExprResult Res = S.BuildFieldReferenceExpr( + E, false, E->getBeginLoc(), CXXScopeSpec(), FD, Found, NameInfo); + if (Res.isInvalid()) + return false; + if (!buildInitializerListImpl(Res.get())) + return false; + } + } + } + return true; } - return true; -} -Expr *generateInitListsImpl(QualType Ty) { - assert(ArgIt != ArgExprs.end() && "Something is off in iteration!"); - if (Ty->isScalarType() || (Ty->isRecordType() && !Ty->isAggregateType())) - return *(ArgIt++); - - llvm::SmallVector<Expr *> Inits; - assert(!isa<MatrixType>(Ty) && "Matrix types not yet supported in HLSL"); - Ty = Ty.getDesugaredType(Ctx); - if (Ty->isVectorType() || Ty->isConstantArrayType()) { - QualType ElTy; - uint64_t Size = 0; - if (auto *ATy = Ty->getAs<VectorType>()) { - ElTy = ATy->getElementType(); - Size = ATy->getNumElements(); - } else { - auto *VTy = cast<ConstantArrayType>(Ty.getTypePtr()); - ElTy = VTy->getElementType(); - Size = VTy->getZExtSize(); - } - for (uint64_t I = 0; I < Size; ++I) - Inits.push_back(generateInitListsImpl(ElTy)); - } - if (auto *RTy = Ty->getAs<RecordType>()) { - llvm::SmallVector<const RecordType *> RecordTypes; - RecordTypes.push_back(RTy); - while (RecordTypes.back()->getAsCXXRecordDecl()->getNumBases()) { - CXXRecordDecl *D = RecordTypes.back()->getAsCXXRecordDecl(); - assert(D->getNumBases() == 1 && - "HLSL doesn't support multiple inheritance"); - RecordTypes.push_back(D->bases_begin()->getType()->getAs<RecordType>()); - } - while (!RecordTypes.empty()) { - const RecordType *RT = RecordTypes.back(); - RecordTypes.pop_back(); - for (auto *FD : RT->getDecl()->fields()) { - Inits.push_back(generateInitListsImpl(FD->getType())); + Expr *generateInitListsImpl(QualType Ty) { + assert(ArgIt != ArgExprs.end() && "Something is off in iteration!"); + if (Ty->isScalarType() || (Ty->isRecordType() && !Ty->isAggregateType())) + return *(ArgIt++); + + llvm::SmallVector<Expr *> Inits; + assert(!isa<MatrixType>(Ty) && "Matrix types not yet supported in HLSL"); + Ty = Ty.getDesugaredType(Ctx); + if (Ty->isVectorType() || Ty->isConstantArrayType()) { + QualType ElTy; + uint64_t Size = 0; + if (auto *ATy = Ty->getAs<VectorType>()) { + ElTy = ATy->getElementType(); + Size = ATy->getNumElements(); + } else { + auto *VTy = cast<ConstantArrayType>(Ty.getTypePtr()); + ElTy = VTy->getElementType(); + Size = VTy->getZExtSize(); + } + for (uint64_t I = 0; I < Size; ++I) + Inits.push_back(generateInitListsImpl(ElTy)); + } + if (auto *RTy = Ty->getAs<RecordType>()) { + llvm::SmallVector<const RecordType *> RecordTypes; + RecordTypes.push_back(RTy); + while (RecordTypes.back()->getAsCXXRecordDecl()->getNumBases()) { + CXXRecordDecl *D = RecordTypes.back()->getAsCXXRecordDecl(); + assert(D->getNumBases() == 1 && + "HLSL doesn't support multiple inheritance"); + RecordTypes.push_back(D->bases_begin()->getType()->getAs<RecordType>()); + } + while (!RecordTypes.empty()) { + const RecordType *RT = RecordTypes.back(); + RecordTypes.pop_back(); + for (auto *FD : RT->getDecl()->fields()) { + Inits.push_back(generateInitListsImpl(FD->getType())); + } } } + auto *NewInit = new (Ctx) InitListExpr(Ctx, Inits.front()->getBeginLoc(), + Inits, Inits.back()->getEndLoc()); + NewInit->setType(Ty); + return NewInit; } - auto *NewInit = new (Ctx) InitListExpr(Ctx, Inits.front()->getBeginLoc(), - Inits, Inits.back()->getEndLoc()); - NewInit->setType(Ty); - return NewInit; -} + public: -llvm::SmallVector<QualType, 16> DestTypes; + llvm::SmallVector<QualType, 16> DestTypes; llvm::SmallVector<Expr *, 16> ArgExprs; InitListTransformer(Sema &SemaRef, const InitializedEntity &Entity) : S(SemaRef), Ctx(SemaRef.getASTContext()), @@ -3413,14 +3414,12 @@ llvm::SmallVector<QualType, 16> DestTypes; // need to wrap around both when building the initializers and when // generating the final initializer lists. if (Wrap) - InitTy = QualType(InitTy->getBaseElementTypeUnsafe(),0); + InitTy = QualType(InitTy->getBaseElementTypeUnsafe(), 0); BuildFlattenedTypeList(InitTy, DestTypes); DstIt = DestTypes.begin(); } - bool buildInitializerList(Expr *E) { - return buildInitializerListImpl(E); - } + bool buildInitializerList(Expr *E) { return buildInitializerListImpl(E); } Expr *generateInitLists() { ArgIt = ArgExprs.begin(); @@ -3438,7 +3437,7 @@ llvm::SmallVector<QualType, 16> DestTypes; return NewInit; } }; -} +} // namespace bool SemaHLSL::TransformInitList(const InitializedEntity &Entity, const InitializationKind &Kind, @@ -3469,7 +3468,8 @@ bool SemaHLSL::TransformInitList(const InitializedEntity &Entity, // the user intended more, and errors that there are too few initializers to // complete the final element. if (Entity.getType()->isIncompleteArrayType()) - ExpectedSize = ((ActualSize + ExpectedSize - 1) / ExpectedSize) * ExpectedSize; + ExpectedSize = + ((ActualSize + ExpectedSize - 1) / ExpectedSize) * ExpectedSize; // An initializer list might be attempting to initialize a reference or // rvalue-reference. When checking the initializer we should look through >From 46afbd63761e2837dacab11f5375ab1074912b53 Mon Sep 17 00:00:00 2001 From: Chris Bieneman <chris.biene...@me.com> Date: Fri, 28 Mar 2025 16:34:07 -0500 Subject: [PATCH 3/4] Remove unused parameter to SemaHLSL::transformInitList --- clang/include/clang/Sema/SemaHLSL.h | 3 +-- clang/lib/Sema/SemaHLSL.cpp | 3 +-- clang/lib/Sema/SemaInit.cpp | 2 +- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/clang/include/clang/Sema/SemaHLSL.h b/clang/include/clang/Sema/SemaHLSL.h index f333fe30e8da0..5442b5264f18f 100644 --- a/clang/include/clang/Sema/SemaHLSL.h +++ b/clang/include/clang/Sema/SemaHLSL.h @@ -151,8 +151,7 @@ class SemaHLSL : public SemaBase { QualType getInoutParameterType(QualType Ty); - bool TransformInitList(const InitializedEntity &Entity, - const InitializationKind &Kind, InitListExpr *Init); + bool transformInitList(const InitializedEntity &Entity, InitListExpr *Init); private: // HLSL resource type attributes need to be processed all at once. diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp index 36f1ec6dd3d50..103c97e1a4855 100644 --- a/clang/lib/Sema/SemaHLSL.cpp +++ b/clang/lib/Sema/SemaHLSL.cpp @@ -3439,8 +3439,7 @@ class InitListTransformer { }; } // namespace -bool SemaHLSL::TransformInitList(const InitializedEntity &Entity, - const InitializationKind &Kind, +bool SemaHLSL::transformInitList(const InitializedEntity &Entity, InitListExpr *Init) { // If the initializer is a scalar, just return it. if (Init->getType()->isScalarType()) diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index 9814c3f456f0d..eece4f7292dde 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -4845,7 +4845,7 @@ static void TryListInitialization(Sema &S, QualType DestType = Entity.getType(); if (S.getLangOpts().HLSL && - !S.HLSL().TransformInitList(Entity, Kind, InitList)) + !S.HLSL().transformInitList(Entity, InitList)) return; // C++ doesn't allow scalar initialization with more than one argument. >From 79b270cde76958a390899bd993dae7419101a410 Mon Sep 17 00:00:00 2001 From: Chris Bieneman <chris.biene...@me.com> Date: Fri, 28 Mar 2025 18:32:35 -0500 Subject: [PATCH 4/4] clang-format --- clang/lib/Sema/SemaInit.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index eece4f7292dde..6615c4bf51aaf 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -4844,8 +4844,7 @@ static void TryListInitialization(Sema &S, bool TreatUnavailableAsInvalid) { QualType DestType = Entity.getType(); - if (S.getLangOpts().HLSL && - !S.HLSL().transformInitList(Entity, InitList)) + if (S.getLangOpts().HLSL && !S.HLSL().transformInitList(Entity, InitList)) return; // C++ doesn't allow scalar initialization with more than one argument. _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits