Skip to content

Commit 69381c7

Browse files
committed
[clang-reorder-fields] Refactor the new order information
Move the new fields order information to a new struct.
1 parent 76bd5da commit 69381c7

File tree

1 file changed

+48
-34
lines changed

1 file changed

+48
-34
lines changed

clang-tools-extra/clang-reorder-fields/ReorderFieldsAction.cpp

Lines changed: 48 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,20 @@ getNewFieldsOrder(const RecordDecl *Definition,
8181
return NewFieldsOrder;
8282
}
8383

84+
struct ReorderedStruct {
85+
public:
86+
ReorderedStruct(const RecordDecl *Decl, ArrayRef<unsigned> NewFieldsOrder)
87+
: Definition(Decl), NewFieldsOrder(NewFieldsOrder),
88+
NewFieldsPositions(NewFieldsOrder.size()) {
89+
for (unsigned I = 0; I < NewFieldsPositions.size(); ++I)
90+
NewFieldsPositions[NewFieldsOrder[I]] = I;
91+
}
92+
93+
const RecordDecl *Definition;
94+
ArrayRef<unsigned> NewFieldsOrder;
95+
SmallVector<unsigned, 4> NewFieldsPositions;
96+
};
97+
8498
// FIXME: error-handling
8599
/// Replaces one range of source code by another.
86100
static void
@@ -194,33 +208,33 @@ static SourceRange getFullFieldSourceRange(const FieldDecl &Field,
194208
/// different accesses (public/protected/private) is not supported.
195209
/// \returns true on success.
196210
static bool reorderFieldsInDefinition(
197-
const RecordDecl *Definition, ArrayRef<unsigned> NewFieldsOrder,
198-
const ASTContext &Context,
211+
const ReorderedStruct &RS, const ASTContext &Context,
199212
std::map<std::string, tooling::Replacements> &Replacements) {
200-
assert(Definition && "Definition is null");
213+
assert(RS.Definition && "Definition is null");
201214

202215
SmallVector<const FieldDecl *, 10> Fields;
203-
for (const auto *Field : Definition->fields())
216+
for (const auto *Field : RS.Definition->fields())
204217
Fields.push_back(Field);
205218

206219
// Check that the permutation of the fields doesn't change the accesses
207-
for (const auto *Field : Definition->fields()) {
220+
for (const auto *Field : RS.Definition->fields()) {
208221
const auto FieldIndex = Field->getFieldIndex();
209-
if (Field->getAccess() != Fields[NewFieldsOrder[FieldIndex]]->getAccess()) {
222+
if (Field->getAccess() !=
223+
Fields[RS.NewFieldsOrder[FieldIndex]]->getAccess()) {
210224
llvm::errs() << "Currently reordering of fields with different accesses "
211225
"is not supported\n";
212226
return false;
213227
}
214228
}
215229

216-
for (const auto *Field : Definition->fields()) {
230+
for (const auto *Field : RS.Definition->fields()) {
217231
const auto FieldIndex = Field->getFieldIndex();
218-
if (FieldIndex == NewFieldsOrder[FieldIndex])
232+
if (FieldIndex == RS.NewFieldsOrder[FieldIndex])
219233
continue;
220-
addReplacement(
221-
getFullFieldSourceRange(*Field, Context),
222-
getFullFieldSourceRange(*Fields[NewFieldsOrder[FieldIndex]], Context),
223-
Context, Replacements);
234+
addReplacement(getFullFieldSourceRange(*Field, Context),
235+
getFullFieldSourceRange(
236+
*Fields[RS.NewFieldsOrder[FieldIndex]], Context),
237+
Context, Replacements);
224238
}
225239
return true;
226240
}
@@ -231,7 +245,7 @@ static bool reorderFieldsInDefinition(
231245
/// fields. Thus, we need to ensure that we reorder just the initializers that
232246
/// are present.
233247
static void reorderFieldsInConstructor(
234-
const CXXConstructorDecl *CtorDecl, ArrayRef<unsigned> NewFieldsOrder,
248+
const CXXConstructorDecl *CtorDecl, const ReorderedStruct &RS,
235249
ASTContext &Context,
236250
std::map<std::string, tooling::Replacements> &Replacements) {
237251
assert(CtorDecl && "Constructor declaration is null");
@@ -243,10 +257,6 @@ static void reorderFieldsInConstructor(
243257
// Thus this assert needs to be after the previous checks.
244258
assert(CtorDecl->isThisDeclarationADefinition() && "Not a definition");
245259

246-
SmallVector<unsigned, 10> NewFieldsPositions(NewFieldsOrder.size());
247-
for (unsigned i = 0, e = NewFieldsOrder.size(); i < e; ++i)
248-
NewFieldsPositions[NewFieldsOrder[i]] = i;
249-
250260
SmallVector<const CXXCtorInitializer *, 10> OldWrittenInitializersOrder;
251261
SmallVector<const CXXCtorInitializer *, 10> NewWrittenInitializersOrder;
252262
for (const auto *Initializer : CtorDecl->inits()) {
@@ -257,8 +267,8 @@ static void reorderFieldsInConstructor(
257267
const FieldDecl *ThisM = Initializer->getMember();
258268
const auto UsedMembers = findMembersUsedInInitExpr(Initializer, Context);
259269
for (const FieldDecl *UM : UsedMembers) {
260-
if (NewFieldsPositions[UM->getFieldIndex()] >
261-
NewFieldsPositions[ThisM->getFieldIndex()]) {
270+
if (RS.NewFieldsPositions[UM->getFieldIndex()] >
271+
RS.NewFieldsPositions[ThisM->getFieldIndex()]) {
262272
DiagnosticsEngine &DiagEngine = Context.getDiagnostics();
263273
auto Description = ("reordering field " + UM->getName() + " after " +
264274
ThisM->getName() + " makes " + UM->getName() +
@@ -276,8 +286,8 @@ static void reorderFieldsInConstructor(
276286
auto ByFieldNewPosition = [&](const CXXCtorInitializer *LHS,
277287
const CXXCtorInitializer *RHS) {
278288
assert(LHS && RHS);
279-
return NewFieldsPositions[LHS->getMember()->getFieldIndex()] <
280-
NewFieldsPositions[RHS->getMember()->getFieldIndex()];
289+
return RS.NewFieldsPositions[LHS->getMember()->getFieldIndex()] <
290+
RS.NewFieldsPositions[RHS->getMember()->getFieldIndex()];
281291
};
282292
llvm::sort(NewWrittenInitializersOrder, ByFieldNewPosition);
283293
assert(OldWrittenInitializersOrder.size() ==
@@ -294,8 +304,8 @@ static void reorderFieldsInConstructor(
294304
/// At the moment partial initialization is not supported.
295305
/// \returns true on success
296306
static bool reorderFieldsInInitListExpr(
297-
const InitListExpr *InitListEx, ArrayRef<unsigned> NewFieldsOrder,
298-
const ASTContext &Context,
307+
const InitListExpr *InitListEx, const ReorderedStruct &RS,
308+
ASTContext &Context,
299309
std::map<std::string, tooling::Replacements> &Replacements) {
300310
assert(InitListEx && "Init list expression is null");
301311
// We care only about InitListExprs which originate from source code.
@@ -309,15 +319,16 @@ static bool reorderFieldsInInitListExpr(
309319
// If there are no initializers we do not need to change anything.
310320
if (!InitListEx->getNumInits())
311321
return true;
312-
if (InitListEx->getNumInits() != NewFieldsOrder.size()) {
322+
if (InitListEx->getNumInits() != RS.NewFieldsOrder.size()) {
313323
llvm::errs() << "Currently only full initialization is supported\n";
314324
return false;
315325
}
316326
for (unsigned i = 0, e = InitListEx->getNumInits(); i < e; ++i)
317-
if (i != NewFieldsOrder[i])
318-
addReplacement(InitListEx->getInit(i)->getSourceRange(),
319-
InitListEx->getInit(NewFieldsOrder[i])->getSourceRange(),
320-
Context, Replacements);
327+
if (i != RS.NewFieldsOrder[i])
328+
addReplacement(
329+
InitListEx->getInit(i)->getSourceRange(),
330+
InitListEx->getInit(RS.NewFieldsOrder[i])->getSourceRange(), Context,
331+
Replacements);
321332
return true;
322333
}
323334

@@ -345,32 +356,35 @@ class ReorderingConsumer : public ASTConsumer {
345356
getNewFieldsOrder(RD, DesiredFieldsOrder);
346357
if (NewFieldsOrder.empty())
347358
return;
348-
if (!reorderFieldsInDefinition(RD, NewFieldsOrder, Context, Replacements))
359+
ReorderedStruct RS{RD, NewFieldsOrder};
360+
361+
if (!reorderFieldsInDefinition(RS, Context, Replacements))
349362
return;
350363

351364
// CXXRD will be nullptr if C code (not C++) is being processed.
352365
const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD);
353366
if (CXXRD)
354367
for (const auto *C : CXXRD->ctors())
355368
if (const auto *D = dyn_cast<CXXConstructorDecl>(C->getDefinition()))
356-
reorderFieldsInConstructor(cast<const CXXConstructorDecl>(D),
357-
NewFieldsOrder, Context, Replacements);
369+
reorderFieldsInConstructor(cast<const CXXConstructorDecl>(D), RS,
370+
Context, Replacements);
358371

359372
// We only need to reorder init list expressions for
360373
// plain C structs or C++ aggregate types.
361374
// For other types the order of constructor parameters is used,
362375
// which we don't change at the moment.
363376
// Now (v0) partial initialization is not supported.
364-
if (!CXXRD || CXXRD->isAggregate())
377+
if (!CXXRD || CXXRD->isAggregate()) {
365378
for (auto Result :
366379
match(initListExpr(hasType(equalsNode(RD))).bind("initListExpr"),
367380
Context))
368381
if (!reorderFieldsInInitListExpr(
369-
Result.getNodeAs<InitListExpr>("initListExpr"), NewFieldsOrder,
370-
Context, Replacements)) {
382+
Result.getNodeAs<InitListExpr>("initListExpr"), RS, Context,
383+
Replacements)) {
371384
Replacements.clear();
372385
return;
373386
}
387+
}
374388
}
375389
};
376390
} // end anonymous namespace

0 commit comments

Comments
 (0)