Skip to content

Commit e745196

Browse files
committed
[clang] Add FixItHint for designated init order
1 parent 5a581ac commit e745196

File tree

1 file changed

+88
-1
lines changed

1 file changed

+88
-1
lines changed

clang/lib/Sema/SemaInit.cpp

Lines changed: 88 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,45 @@
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"
3941
#include "llvm/Support/raw_ostream.h"
4042

43+
#include <iostream>
44+
#define DUMP_ARG1(X) \
45+
{ \
46+
if (X) { \
47+
fprintf(stderr, "----- %s ----- (%s:%d)\n", #X, __FILE__, __LINE__); \
48+
(X)->dumpColor(); \
49+
fprintf(stderr, "--------------------------------\n\n"); \
50+
fflush(stdout); \
51+
std::flush(std::cout); \
52+
} else \
53+
fprintf(stderr, "Arg '" #X "' was empty\n"); \
54+
} \
55+
do { \
56+
} while (0)
57+
58+
#define DUMP_ARG2(PREFIX, X) \
59+
{ \
60+
if (X) { \
61+
fprintf(stderr, "%s: %s ----- (%s:%d)\n", PREFIX, #X, __FILE__, \
62+
__LINE__); \
63+
(X)->dumpColor(); \
64+
fprintf(stderr, "--------------------------------\n\n"); \
65+
fflush(stdout); \
66+
std::flush(std::cout); \
67+
} else \
68+
fprintf(stderr, "Arg '" #X "' was empty\n"); \
69+
} \
70+
do { \
71+
} while (0)
72+
4173
using namespace clang;
4274

4375
//===----------------------------------------------------------------------===//
@@ -3092,6 +3124,60 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,
30923124
PrevField = *FI;
30933125
}
30943126

3127+
const auto GenerateDesignatedInitReorderingFixit = [&]() -> FixItHint {
3128+
struct ReorderInfo {
3129+
int Pos{};
3130+
const Expr *InitExpr{};
3131+
};
3132+
3133+
llvm::SmallDenseMap<IdentifierInfo *, int> MemberNameInx{};
3134+
llvm::SmallVector<ReorderInfo, 16> ReorderedInitExprs{};
3135+
3136+
const auto *CxxRecord =
3137+
IList->getSemanticForm()->getType()->getAsCXXRecordDecl();
3138+
3139+
for (const auto &Field : CxxRecord->fields()) {
3140+
MemberNameInx[Field->getIdentifier()] = Field->getFieldIndex();
3141+
}
3142+
3143+
for (const auto *Init : IList->inits()) {
3144+
if (const auto *DI = dyn_cast_if_present<DesignatedInitExpr>(Init)) {
3145+
// We expect only one Designator
3146+
if (DI->size() != 1)
3147+
return {};
3148+
3149+
const auto *const FieldName = DI->getDesignator(0)->getFieldName();
3150+
// In case we have an unknown initializer in the source, not in the
3151+
// record
3152+
if (MemberNameInx.contains(FieldName))
3153+
ReorderedInitExprs.emplace_back(
3154+
ReorderInfo{MemberNameInx.at(FieldName), Init});
3155+
}
3156+
}
3157+
3158+
llvm::sort(ReorderedInitExprs,
3159+
[](const auto &A, const auto &B) { return A.Pos < B.Pos; });
3160+
3161+
// generate replacement
3162+
llvm::SmallString<128> FixedInitList{};
3163+
SourceManager &SM = SemaRef.getSourceManager();
3164+
const LangOptions &LangOpts = SemaRef.getLangOpts();
3165+
3166+
FixedInitList += "{";
3167+
for (const auto &Item : ReorderedInitExprs) {
3168+
CharSourceRange CharRange =
3169+
CharSourceRange::getTokenRange(Item.InitExpr->getSourceRange());
3170+
const auto InitText =
3171+
Lexer::getSourceText(CharRange, SM, LangOpts) + ", ";
3172+
FixedInitList += InitText.str();
3173+
}
3174+
FixedInitList.pop_back_n(2); // remove trailing comma
3175+
FixedInitList += "}";
3176+
3177+
return FixItHint::CreateReplacement(IList->getSourceRange(),
3178+
FixedInitList);
3179+
};
3180+
30953181
if (PrevField &&
30963182
PrevField->getFieldIndex() > KnownField->getFieldIndex()) {
30973183
SemaRef.Diag(DIE->getInit()->getBeginLoc(),
@@ -3101,9 +3187,10 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,
31013187
unsigned OldIndex = StructuredIndex - 1;
31023188
if (StructuredList && OldIndex <= StructuredList->getNumInits()) {
31033189
if (Expr *PrevInit = StructuredList->getInit(OldIndex)) {
3190+
auto ReorderFixit = GenerateDesignatedInitReorderingFixit();
31043191
SemaRef.Diag(PrevInit->getBeginLoc(),
31053192
diag::note_previous_field_init)
3106-
<< PrevField << PrevInit->getSourceRange();
3193+
<< PrevField << PrevInit->getSourceRange() << ReorderFixit;
31073194
}
31083195
}
31093196
}

0 commit comments

Comments
 (0)