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

Reply via email to