[clang] [HLSL] Handle incomplete array types (PR #133508)
Sarah Spall via cfe-commits
cfe-commits at lists.llvm.org
Tue Apr 8 14:25:04 PDT 2025
================
@@ -3249,166 +3249,204 @@ void SemaHLSL::processExplicitBindingsOnDecl(VarDecl *VD) {
}
}
}
-
-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.
+namespace {
+class InitListTransformer {
+ Sema &S;
+ ASTContext &Ctx;
+ QualType InitTy;
+ QualType *DstIt = nullptr;
+ 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;
+ }
+ 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;
}
- InitializedEntity Entity = InitializedEntity::InitializeParameter(
- Ctx, DestTypes[List.size()], false);
- ExprResult Res = S.PerformCopyInitialization(Entity, E->getBeginLoc(), E);
- if (Res.isInvalid())
- return false;
- Expr *Init = Res.get();
- List.push_back(Init);
- return true;
-}
-static bool BuildInitializerList(Sema &S, ASTContext &Ctx, Expr *E,
- llvm::SmallVectorImpl<Expr *> &List,
- llvm::SmallVectorImpl<QualType> &DestTypes) {
- // 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))
- return false;
- 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;
+ return true;
+ }
- // If this is a scalar type, just enqueue the expression.
- QualType Ty = E->getType();
+ // If this is a scalar type, just enqueue the expression.
+ QualType Ty = E->getType();
- if (Ty->isScalarType() || (Ty->isRecordType() && !Ty->isAggregateType()))
- return CastInitializer(S, Ctx, E, List, DestTypes);
+ if (Ty->isScalarType() || (Ty->isRecordType() && !Ty->isAggregateType()))
+ return castInitializer(E);
- if (auto *VecTy = Ty->getAs<VectorType>()) {
- uint64_t Size = VecTy->getNumElements();
+ if (auto *VecTy = Ty->getAs<VectorType>()) {
+ uint64_t Size = VecTy->getNumElements();
- 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());
+ 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 (!CastInitializer(S, Ctx, ElExpr.get(), List, DestTypes))
- 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 *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 (!BuildInitializerList(S, Ctx, ElExpr.get(), List, DestTypes))
- 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())
+ 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 (!BuildInitializerList(S, Ctx, Res.get(), List, DestTypes))
+ 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;
-}
-static Expr *GenerateInitLists(ASTContext &Ctx, QualType Ty,
- llvm::SmallVectorImpl<Expr *>::iterator &It) {
- if (Ty->isScalarType() || (Ty->isRecordType() && !Ty->isAggregateType())) {
- return *(It++);
- }
- 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(GenerateInitLists(Ctx, ElTy, It));
- }
- 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(GenerateInitLists(Ctx, FD->getType(), 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);
+ 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;
-}
-bool SemaHLSL::TransformInitList(const InitializedEntity &Entity,
- const InitializationKind &Kind,
+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);
----------------
spall wrote:
The implementation of 'getBaseElementTypeUnsafe' looks like it would get the 'int2' type? Or am I misunderstanding this.
https://clang.llvm.org/doxygen/classclang_1_1Type.html#a866ff611f24817f77eb80393de8cb126
https://github.com/llvm/llvm-project/pull/133508
More information about the cfe-commits
mailing list