3131#include " clang/Sema/SemaHLSL.h"
3232#include " clang/Sema/SemaObjC.h"
3333#include " llvm/ADT/APInt.h"
34+ #include " llvm/ADT/DenseMap.h"
3435#include " llvm/ADT/FoldingSet.h"
3536#include " llvm/ADT/PointerIntPair.h"
37+ #include " llvm/ADT/SmallString.h"
3638#include " llvm/ADT/SmallVector.h"
3739#include " llvm/ADT/StringExtras.h"
3840#include " llvm/Support/ErrorHandling.h"
@@ -3092,6 +3094,60 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,
30923094 PrevField = *FI;
30933095 }
30943096
3097+ const auto GenerateDesignatedInitReorderingFixit = [&]() -> FixItHint {
3098+ struct ReorderInfo {
3099+ int Pos{};
3100+ const Expr *InitExpr{};
3101+ };
3102+
3103+ llvm::SmallDenseMap<IdentifierInfo *, int > MemberNameInx{};
3104+ llvm::SmallVector<ReorderInfo, 16 > ReorderedInitExprs{};
3105+
3106+ const auto *CxxRecord =
3107+ IList->getSemanticForm ()->getType ()->getAsCXXRecordDecl ();
3108+
3109+ for (const auto &Field : CxxRecord->fields ()) {
3110+ MemberNameInx[Field->getIdentifier ()] = Field->getFieldIndex ();
3111+ }
3112+
3113+ for (const auto *Init : IList->inits ()) {
3114+ if (const auto *DI = dyn_cast_if_present<DesignatedInitExpr>(Init)) {
3115+ // We expect only one Designator
3116+ if (DI->size () != 1 )
3117+ return {};
3118+
3119+ const auto *const FieldName = DI->getDesignator (0 )->getFieldName ();
3120+ // In case we have an unknown initializer in the source, not in the
3121+ // record
3122+ if (MemberNameInx.contains (FieldName))
3123+ ReorderedInitExprs.emplace_back (
3124+ ReorderInfo{MemberNameInx.at (FieldName), Init});
3125+ }
3126+ }
3127+
3128+ llvm::sort (ReorderedInitExprs,
3129+ [](const auto &A, const auto &B) { return A.Pos < B.Pos ; });
3130+
3131+ // generate replacement
3132+ llvm::SmallString<128 > FixedInitList{};
3133+ SourceManager &SM = SemaRef.getSourceManager ();
3134+ const LangOptions &LangOpts = SemaRef.getLangOpts ();
3135+
3136+ FixedInitList += " {" ;
3137+ for (const auto &Item : ReorderedInitExprs) {
3138+ CharSourceRange CharRange =
3139+ CharSourceRange::getTokenRange (Item.InitExpr ->getSourceRange ());
3140+ const auto InitText =
3141+ Lexer::getSourceText (CharRange, SM, LangOpts) + " , " ;
3142+ FixedInitList += InitText.str ();
3143+ }
3144+ FixedInitList.pop_back_n (2 ); // remove trailing comma
3145+ FixedInitList += " }" ;
3146+
3147+ return FixItHint::CreateReplacement (IList->getSourceRange (),
3148+ FixedInitList);
3149+ };
3150+
30953151 if (PrevField &&
30963152 PrevField->getFieldIndex () > KnownField->getFieldIndex ()) {
30973153 SemaRef.Diag (DIE->getInit ()->getBeginLoc (),
@@ -3101,9 +3157,10 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,
31013157 unsigned OldIndex = StructuredIndex - 1 ;
31023158 if (StructuredList && OldIndex <= StructuredList->getNumInits ()) {
31033159 if (Expr *PrevInit = StructuredList->getInit (OldIndex)) {
3160+ auto ReorderFixit = GenerateDesignatedInitReorderingFixit ();
31043161 SemaRef.Diag (PrevInit->getBeginLoc (),
31053162 diag::note_previous_field_init)
3106- << PrevField << PrevInit->getSourceRange ();
3163+ << PrevField << PrevInit->getSourceRange () << ReorderFixit ;
31073164 }
31083165 }
31093166 }
0 commit comments