https://github.com/MythreyaK updated https://github.com/llvm/llvm-project/pull/172959
>From bcdb0fd408b055baaf1a1dc3cde1d87daf5cde44 Mon Sep 17 00:00:00 2001 From: Mythreya <[email protected]> Date: Thu, 18 Dec 2025 23:21:50 -0800 Subject: [PATCH 1/2] [clang] Add FixItHint for designated init order --- clang/lib/Sema/SemaInit.cpp | 59 ++++++++++++++++++++++++++++++++++++- 1 file changed, 58 insertions(+), 1 deletion(-) diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index cc6ddf568d346..3eb648506e758 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -31,8 +31,10 @@ #include "clang/Sema/SemaHLSL.h" #include "clang/Sema/SemaObjC.h" #include "llvm/ADT/APInt.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/PointerIntPair.h" +#include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/ErrorHandling.h" @@ -3092,6 +3094,60 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity, PrevField = *FI; } + const auto GenerateDesignatedInitReorderingFixit = [&]() -> FixItHint { + struct ReorderInfo { + int Pos{}; + const Expr *InitExpr{}; + }; + + llvm::SmallDenseMap<IdentifierInfo *, int> MemberNameInx{}; + llvm::SmallVector<ReorderInfo, 16> ReorderedInitExprs{}; + + const auto *CxxRecord = + IList->getSemanticForm()->getType()->getAsCXXRecordDecl(); + + for (const auto &Field : CxxRecord->fields()) { + MemberNameInx[Field->getIdentifier()] = Field->getFieldIndex(); + } + + for (const auto *Init : IList->inits()) { + if (const auto *DI = dyn_cast_if_present<DesignatedInitExpr>(Init)) { + // We expect only one Designator + if (DI->size() != 1) + return {}; + + const auto *const FieldName = DI->getDesignator(0)->getFieldName(); + // In case we have an unknown initializer in the source, not in the + // record + if (MemberNameInx.contains(FieldName)) + ReorderedInitExprs.emplace_back( + ReorderInfo{MemberNameInx.at(FieldName), Init}); + } + } + + llvm::sort(ReorderedInitExprs, + [](const auto &A, const auto &B) { return A.Pos < B.Pos; }); + + // generate replacement + llvm::SmallString<128> FixedInitList{}; + SourceManager &SM = SemaRef.getSourceManager(); + const LangOptions &LangOpts = SemaRef.getLangOpts(); + + FixedInitList += "{"; + for (const auto &Item : ReorderedInitExprs) { + CharSourceRange CharRange = + CharSourceRange::getTokenRange(Item.InitExpr->getSourceRange()); + const auto InitText = + Lexer::getSourceText(CharRange, SM, LangOpts) + ", "; + FixedInitList += InitText.str(); + } + FixedInitList.pop_back_n(2); // remove trailing comma + FixedInitList += "}"; + + return FixItHint::CreateReplacement(IList->getSourceRange(), + FixedInitList); + }; + if (PrevField && PrevField->getFieldIndex() > KnownField->getFieldIndex()) { SemaRef.Diag(DIE->getInit()->getBeginLoc(), @@ -3101,9 +3157,10 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity, unsigned OldIndex = StructuredIndex - 1; if (StructuredList && OldIndex <= StructuredList->getNumInits()) { if (Expr *PrevInit = StructuredList->getInit(OldIndex)) { + auto ReorderFixit = GenerateDesignatedInitReorderingFixit(); SemaRef.Diag(PrevInit->getBeginLoc(), diag::note_previous_field_init) - << PrevField << PrevInit->getSourceRange(); + << PrevField << PrevInit->getSourceRange() << ReorderFixit; } } } >From 322f1de4358039a495b3663a1fc79b2f1774d697 Mon Sep 17 00:00:00 2001 From: Mythreya <[email protected]> Date: Thu, 18 Dec 2025 23:32:09 -0800 Subject: [PATCH 2/2] Replace exprs instead of regenerating everything --- clang/lib/Sema/SemaInit.cpp | 103 ++++++++++++++++++------------------ 1 file changed, 52 insertions(+), 51 deletions(-) diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index 3eb648506e758..46ca85bfa37a5 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -3094,59 +3094,60 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity, PrevField = *FI; } - const auto GenerateDesignatedInitReorderingFixit = [&]() -> FixItHint { - struct ReorderInfo { - int Pos{}; - const Expr *InitExpr{}; - }; + const auto GenerateDesignatedInitReorderingFixit = + [&](SemaBase::SemaDiagnosticBuilder &Diags) { + struct ReorderInfo { + int Pos{}; + const Expr *InitExpr{}; + }; - llvm::SmallDenseMap<IdentifierInfo *, int> MemberNameInx{}; - llvm::SmallVector<ReorderInfo, 16> ReorderedInitExprs{}; + llvm::SmallDenseMap<IdentifierInfo *, int> MemberNameInx{}; + llvm::SmallVector<ReorderInfo, 16> ReorderedInitExprs{}; - const auto *CxxRecord = - IList->getSemanticForm()->getType()->getAsCXXRecordDecl(); + const auto *CxxRecord = + IList->getSemanticForm()->getType()->getAsCXXRecordDecl(); - for (const auto &Field : CxxRecord->fields()) { - MemberNameInx[Field->getIdentifier()] = Field->getFieldIndex(); - } + for (const auto &Field : CxxRecord->fields()) { + MemberNameInx[Field->getIdentifier()] = Field->getFieldIndex(); + } - for (const auto *Init : IList->inits()) { - if (const auto *DI = dyn_cast_if_present<DesignatedInitExpr>(Init)) { - // We expect only one Designator - if (DI->size() != 1) - return {}; - - const auto *const FieldName = DI->getDesignator(0)->getFieldName(); - // In case we have an unknown initializer in the source, not in the - // record - if (MemberNameInx.contains(FieldName)) - ReorderedInitExprs.emplace_back( - ReorderInfo{MemberNameInx.at(FieldName), Init}); - } - } + for (const auto *Init : IList->inits()) { + if (const auto *DI = + dyn_cast_if_present<DesignatedInitExpr>(Init)) { + // We expect only one Designator + if (DI->size() != 1) + return; + + const auto *const FieldName = + DI->getDesignator(0)->getFieldName(); + // In case we have an unknown initializer in the source, not in + // the record + if (MemberNameInx.contains(FieldName)) + ReorderedInitExprs.emplace_back( + ReorderInfo{MemberNameInx.at(FieldName), Init}); + } + } - llvm::sort(ReorderedInitExprs, - [](const auto &A, const auto &B) { return A.Pos < B.Pos; }); - - // generate replacement - llvm::SmallString<128> FixedInitList{}; - SourceManager &SM = SemaRef.getSourceManager(); - const LangOptions &LangOpts = SemaRef.getLangOpts(); - - FixedInitList += "{"; - for (const auto &Item : ReorderedInitExprs) { - CharSourceRange CharRange = - CharSourceRange::getTokenRange(Item.InitExpr->getSourceRange()); - const auto InitText = - Lexer::getSourceText(CharRange, SM, LangOpts) + ", "; - FixedInitList += InitText.str(); - } - FixedInitList.pop_back_n(2); // remove trailing comma - FixedInitList += "}"; + llvm::sort(ReorderedInitExprs, [](const auto &A, const auto &B) { + return A.Pos < B.Pos; + }); + + llvm::SmallString<128> FixedInitList{}; + SourceManager &SM = SemaRef.getSourceManager(); + const LangOptions &LangOpts = SemaRef.getLangOpts(); - return FixItHint::CreateReplacement(IList->getSourceRange(), - FixedInitList); - }; + // loop over each existing expression and apply replacement + for (const auto &[OrigExpr, Repl] : + llvm::zip(IList->inits(), ReorderedInitExprs)) { + CharSourceRange CharRange = CharSourceRange::getTokenRange( + Repl.InitExpr->getSourceRange()); + const auto InitText = + Lexer::getSourceText(CharRange, SM, LangOpts); + + Diags << FixItHint::CreateReplacement(OrigExpr->getSourceRange(), + InitText.str()); + } + }; if (PrevField && PrevField->getFieldIndex() > KnownField->getFieldIndex()) { @@ -3157,10 +3158,10 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity, unsigned OldIndex = StructuredIndex - 1; if (StructuredList && OldIndex <= StructuredList->getNumInits()) { if (Expr *PrevInit = StructuredList->getInit(OldIndex)) { - auto ReorderFixit = GenerateDesignatedInitReorderingFixit(); - SemaRef.Diag(PrevInit->getBeginLoc(), - diag::note_previous_field_init) - << PrevField << PrevInit->getSourceRange() << ReorderFixit; + auto Diags = SemaRef.Diag(PrevInit->getBeginLoc(), + diag::note_previous_field_init) + << PrevField << PrevInit->getSourceRange(); + GenerateDesignatedInitReorderingFixit(Diags); } } } _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
