https://github.com/MythreyaK created 
https://github.com/llvm/llvm-project/pull/172959

None

>From e74519649a148d01b04f0934638df4dec8372423 Mon Sep 17 00:00:00 2001
From: Mythreya <[email protected]>
Date: Tue, 16 Dec 2025 02:44:10 -0800
Subject: [PATCH] [clang] Add FixItHint for designated init order

---
 clang/lib/Sema/SemaInit.cpp | 89 ++++++++++++++++++++++++++++++++++++-
 1 file changed, 88 insertions(+), 1 deletion(-)

diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index cc6ddf568d346..2eb8ecfc05b25 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -31,13 +31,45 @@
 #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"
 #include "llvm/Support/raw_ostream.h"
 
+#include <iostream>
+#define DUMP_ARG1(X)                                                           
\
+  {                                                                            
\
+    if (X) {                                                                   
\
+      fprintf(stderr, "----- %s ----- (%s:%d)\n", #X, __FILE__, __LINE__);     
\
+      (X)->dumpColor();                                                        
\
+      fprintf(stderr, "--------------------------------\n\n");                 
\
+      fflush(stdout);                                                          
\
+      std::flush(std::cout);                                                   
\
+    } else                                                                     
\
+      fprintf(stderr, "Arg '" #X "' was empty\n");                             
\
+  }                                                                            
\
+  do {                                                                         
\
+  } while (0)
+
+#define DUMP_ARG2(PREFIX, X)                                                   
\
+  {                                                                            
\
+    if (X) {                                                                   
\
+      fprintf(stderr, "%s: %s ----- (%s:%d)\n", PREFIX, #X, __FILE__,          
\
+              __LINE__);                                                       
\
+      (X)->dumpColor();                                                        
\
+      fprintf(stderr, "--------------------------------\n\n");                 
\
+      fflush(stdout);                                                          
\
+      std::flush(std::cout);                                                   
\
+    } else                                                                     
\
+      fprintf(stderr, "Arg '" #X "' was empty\n");                             
\
+  }                                                                            
\
+  do {                                                                         
\
+  } while (0)
+
 using namespace clang;
 
 
//===----------------------------------------------------------------------===//
@@ -3092,6 +3124,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 +3187,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;
           }
         }
       }

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to