https://github.com/AnonMiraj updated https://github.com/llvm/llvm-project/pull/225573
>From ab07603afbfac0f24f48e64bfcf66ff2324a31ed Mon Sep 17 00:00:00 2001 From: Anonmiraj <[email protected]> Date: Tue, 22 Sep 2026 02:36:26 +0300 Subject: [PATCH 1/2] [Clang] Fix quadratic designated-initializer checking --- clang/lib/Sema/SemaInit.cpp | 32 +++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index 8f685feac4beb..bdb2b3fedb642 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -363,6 +363,10 @@ class InitListChecker { SmallVectorImpl<QualType> *AggrDeductionCandidateParamTypes = nullptr; EmbedExpr *CurEmbed = nullptr; // Save current embed we're processing. unsigned CurEmbedIndex = 0; + /// Indices of a record's unnamed bitfields, in increasing order. Usually + /// empty. getFieldIndex() counts them, designators don't. + llvm::SmallDenseMap<const RecordDecl *, SmallVector<unsigned, 0>, 2> + UnnamedBitFieldIndices; NoInitExpr *getDummyInit() { if (!DummyExpr) @@ -3012,14 +3016,28 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity, unsigned FieldIndex = NumBases; - for (auto *FI : RD->fields()) { - if (FI->isUnnamedBitField()) - continue; - if (declaresSameEntity(KnownField, FI)) { - KnownField = FI; - break; + // Avoid a quadratic per-designator scan; the AST caches each field's + // index. + if (KnownField->getParent() == RD) { + auto [It, Inserted] = UnnamedBitFieldIndices.try_emplace(RD); + if (Inserted) + for (const FieldDecl *FI : RD->fields()) + if (FI->isUnnamedBitField()) + It->second.push_back(FI->getFieldIndex()); + unsigned Index = KnownField->getFieldIndex(); + FieldIndex += + Index - (llvm::lower_bound(It->second, Index) - It->second.begin()); + } else { + // A field of another record: its cached index isn't RD's numbering. + for (auto *FI : RD->fields()) { + if (FI->isUnnamedBitField()) + continue; + if (declaresSameEntity(KnownField, FI)) { + KnownField = FI; + break; + } + ++FieldIndex; } - ++FieldIndex; } RecordDecl::field_iterator Field = >From c59a6da4552f848a360541cd5875b60f56439071 Mon Sep 17 00:00:00 2001 From: Anonmiraj <[email protected]> Date: Fri, 25 Sep 2026 02:29:18 +0300 Subject: [PATCH 2/2] Move the designator field index lookup to ASTContext --- clang/include/clang/AST/ASTContext.h | 9 +++++++++ clang/lib/AST/ASTContext.cpp | 15 +++++++++++++++ clang/lib/Sema/SemaInit.cpp | 16 +++------------- 3 files changed, 27 insertions(+), 13 deletions(-) diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index a4ed852d36442..5ccf885b8a6e7 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -330,6 +330,10 @@ class ASTContext : public RefCountedBase<ASTContext> { /// This is lazily created. This is intentionally not serialized. mutable llvm::DenseMap<const RecordDecl*, const ASTRecordLayout*> ASTRecordLayouts; + /// Indices of a record's unnamed bitfields, in increasing order. Usually + /// empty. getFieldIndex() counts them, designators don't. + mutable llvm::DenseMap<const RecordDecl *, llvm::SmallVector<unsigned, 0>> + UnnamedBitFieldIndices; mutable llvm::DenseMap<const ObjCInterfaceDecl *, const ASTRecordLayout *> ObjCLayouts; @@ -2875,6 +2879,11 @@ class ASTContext : public RefCountedBase<ASTContext> { /// position information. const ASTRecordLayout &getASTRecordLayout(const RecordDecl *D) const; + /// Returns the index of Field among RD's named fields, the numbering + /// designators use. + std::optional<unsigned> getFieldIndex(const RecordDecl *RD, + const FieldDecl *Field) const; + /// Get or compute information about the layout of the specified /// Objective-C interface. const ASTRecordLayout &getASTObjCInterfaceLayout(const ObjCInterfaceDecl *D) diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index abf0cd5e18c2b..8b6233ebdc8cd 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -3236,6 +3236,21 @@ ASTContext::getASTObjCInterfaceLayout(const ObjCInterfaceDecl *D) const { return getObjCLayout(D); } +std::optional<unsigned> +ASTContext::getFieldIndex(const RecordDecl *RD, const FieldDecl *Field) const { + if (Field->getParent() != RD) + return std::nullopt; + + // Designators skip unnamed bitfields; subtract the ones before Field. + auto [It, Inserted] = UnnamedBitFieldIndices.try_emplace(RD); + if (Inserted) + for (const FieldDecl *FI : RD->fields()) + if (FI->isUnnamedBitField()) + It->second.push_back(FI->getFieldIndex()); + unsigned Index = Field->getFieldIndex(); + return Index - (llvm::lower_bound(It->second, Index) - It->second.begin()); +} + static auto getCanonicalTemplateArguments(const ASTContext &C, ArrayRef<TemplateArgument> Args, bool &AnyNonCanonArgs) { diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index bdb2b3fedb642..6e1ddcb6a7cab 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -363,10 +363,6 @@ class InitListChecker { SmallVectorImpl<QualType> *AggrDeductionCandidateParamTypes = nullptr; EmbedExpr *CurEmbed = nullptr; // Save current embed we're processing. unsigned CurEmbedIndex = 0; - /// Indices of a record's unnamed bitfields, in increasing order. Usually - /// empty. getFieldIndex() counts them, designators don't. - llvm::SmallDenseMap<const RecordDecl *, SmallVector<unsigned, 0>, 2> - UnnamedBitFieldIndices; NoInitExpr *getDummyInit() { if (!DummyExpr) @@ -3018,15 +3014,9 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity, // Avoid a quadratic per-designator scan; the AST caches each field's // index. - if (KnownField->getParent() == RD) { - auto [It, Inserted] = UnnamedBitFieldIndices.try_emplace(RD); - if (Inserted) - for (const FieldDecl *FI : RD->fields()) - if (FI->isUnnamedBitField()) - It->second.push_back(FI->getFieldIndex()); - unsigned Index = KnownField->getFieldIndex(); - FieldIndex += - Index - (llvm::lower_bound(It->second, Index) - It->second.begin()); + if (std::optional<unsigned> SelfIndex = + SemaRef.Context.getFieldIndex(RD, KnownField)) { + FieldIndex += *SelfIndex; } else { // A field of another record: its cached index isn't RD's numbering. for (auto *FI : RD->fields()) { _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
