@@ -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.
86100static 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.
196210static 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.
233247static 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
296306static 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