Index: clang-reorder-fields/ReorderFieldsAction.cpp =================================================================== --- clang-reorder-fields/ReorderFieldsAction.cpp +++ clang-reorder-fields/ReorderFieldsAction.cpp @@ -32,10 +32,10 @@ /// \brief Finds the definition of a record by name. /// /// \returns nullptr if the name is ambiguous or not found. -static const CXXRecordDecl *findDefinition(StringRef RecordName, - ASTContext &Context) { +static const RecordDecl *findDefinition(StringRef RecordName, + ASTContext &Context) { auto Results = match( - recordDecl(hasName(RecordName), isDefinition()).bind("cxxRecordDecl"), + recordDecl(hasName(RecordName), isDefinition()).bind("recordDecl"), Context); if (Results.empty()) { llvm::errs() << "Definition of " << RecordName << " not found\n"; @@ -46,14 +46,14 @@ << " is ambiguous, several definitions found\n"; return nullptr; } - return selectFirst("cxxRecordDecl", Results); + return selectFirst("recordDecl", Results); } /// \brief Calculates the new order of fields. /// /// \returns empty vector if the list of fields doesn't match the definition. static SmallVector -getNewFieldsOrder(const CXXRecordDecl *Definition, +getNewFieldsOrder(const RecordDecl *Definition, ArrayRef DesiredFieldsOrder) { assert(Definition && "Definition is null"); @@ -97,7 +97,7 @@ /// different accesses (public/protected/private) is not supported. /// \returns true on success. static bool reorderFieldsInDefinition( - const CXXRecordDecl *Definition, ArrayRef NewFieldsOrder, + const RecordDecl *Definition, ArrayRef NewFieldsOrder, const ASTContext &Context, std::map &Replacements) { assert(Definition && "Definition is null"); @@ -223,7 +223,7 @@ ReorderingConsumer &operator=(const ReorderingConsumer &) = delete; void HandleTranslationUnit(ASTContext &Context) override { - const CXXRecordDecl *RD = findDefinition(RecordName, Context); + const RecordDecl *RD = findDefinition(RecordName, Context); if (!RD) return; SmallVector NewFieldsOrder = @@ -232,16 +232,21 @@ return; if (!reorderFieldsInDefinition(RD, NewFieldsOrder, Context, Replacements)) return; - for (const auto *C : RD->ctors()) - if (const auto *D = dyn_cast(C->getDefinition())) - reorderFieldsInConstructor(cast(D), - NewFieldsOrder, Context, Replacements); - // We only need to reorder init list expressions for aggregate types. + // CXXRD will be nullptr if C code (not C++) is being processed. + const CXXRecordDecl *CXXRD = dyn_cast(RD); + if (CXXRD) + for (const auto *C : CXXRD->ctors()) + if (const auto *D = dyn_cast(C->getDefinition())) + reorderFieldsInConstructor(cast(D), + NewFieldsOrder, Context, Replacements); + + // We only need to reorder init list expressions for + // plain C structs or C++ aggregate types. // For other types the order of constructor parameters is used, // which we don't change at the moment. // Now (v0) partial initialization is not supported. - if (RD->isAggregate()) + if (!CXXRD || CXXRD->isAggregate()) for (auto Result : match(initListExpr(hasType(equalsNode(RD))).bind("initListExpr"), Context)) Index: test/clang-reorder-fields/PlainCStructFieldsOrder.c =================================================================== --- test/clang-reorder-fields/PlainCStructFieldsOrder.c +++ test/clang-reorder-fields/PlainCStructFieldsOrder.c @@ -0,0 +1,14 @@ +// RUN: clang-reorder-fields -record-name Foo -fields-order z,w,y,x %s -- | FileCheck %s + +struct Foo { + const int* x; // CHECK: {{^ double z;}} + int y; // CHECK-NEXT: {{^ int w;}} + double z; // CHECK-NEXT: {{^ int y;}} + int w; // CHECK-NEXT: {{^ const int\* x}} +}; + +int main() { + const int x = 13; + struct Foo foo = { &x, 0, 1.29, 17 }; // CHECK: {{^ struct Foo foo = { 1.29, 17, 0, &x };}} + return 0; +}