https://github.com/AnonMiraj created https://github.com/llvm/llvm-project/pull/225573
Every field designator rescans the record's field list to recover the field's index. `FieldDecl::getFieldIndex()` already caches that index in the AST, so using it instead fixes the issue. When `KnownField` is not a field of `RD` the behavior is kept as before. | N | before | after | | ----- | ------ | ----- | | 10000 | 0.41s | 0.02s | | 20000 | 1.90s | 0.03s | | 40000 | 8.87s | 0.07s | fixes #136568 >From ab07603afbfac0f24f48e64bfcf66ff2324a31ed Mon Sep 17 00:00:00 2001 From: Anonmiraj <[email protected]> Date: Tue, 22 Sep 2026 02:36:26 +0300 Subject: [PATCH] [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 8f685feac4beba..bdb2b3fedb6421 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 = _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
