alexshap created this revision.
alexshap added reviewers: klimek, compnerd.
alexshap added a subscriber: cfe-commits.
alexshap changed the visibility of this Differential Revision from "Public (No
Login Required)" to "All Users".
This diff adds v0 of clang-reorder-fields tool to clang/tools/extra.
The main idea behind this tool is to simplify and make less error-prone
refactoring of large codebases when
someone needs to change the order fields of a struct/class (for example to
remove excess padding).
https://reviews.llvm.org/D23279
Files:
CMakeLists.txt
clang-reorder-fields/CMakeLists.txt
clang-reorder-fields/ReorderFieldsAction.cpp
clang-reorder-fields/ReorderFieldsAction.h
clang-reorder-fields/tool/CMakeLists.txt
clang-reorder-fields/tool/ClangReorderFields.cpp
test/CMakeLists.txt
test/clang-reorder-fields/CStructAmbiguousName.cpp
test/clang-reorder-fields/CStructFieldPos.cpp
test/clang-reorder-fields/CStructFieldsOrder.cpp
Index: test/clang-reorder-fields/CStructFieldsOrder.cpp
===================================================================
--- test/clang-reorder-fields/CStructFieldsOrder.cpp
+++ test/clang-reorder-fields/CStructFieldsOrder.cpp
@@ -0,0 +1,18 @@
+// RUN: cat %s > %t.cpp
+// RUN: clang-reorder-fields -record-name ::bar::Foo -fields-order z,w,y,x %t.cpp -i --
+// RUN: sed 's,//.*,,' %t.cpp | FileCheck %s
+
+namespace bar {
+struct Foo {
+ const int* x; // CHECK: double z;
+ int y; // CHECK: int w;
+ double z; // CHECK: int y;
+ int w; // CHECK: const int* x;
+};
+} // end namespace bar
+
+int main() {
+ const int x = 13;
+ bar::Foo foo = { &x, 17, 1.29, 0 }; // CHECK: bar::Foo foo = { 1.29, 0, 17, &x };
+ return 0;
+}
Index: test/clang-reorder-fields/CStructFieldPos.cpp
===================================================================
--- test/clang-reorder-fields/CStructFieldPos.cpp
+++ test/clang-reorder-fields/CStructFieldPos.cpp
@@ -0,0 +1,16 @@
+// RUN: cat %s > %t.cpp
+// RUN: clang-reorder-fields -record-name ::Foo -field-pos z:0 %t.cpp -i --
+// RUN: sed 's,//.*,,' %t.cpp | FileCheck %s
+
+struct Foo {
+ const int* x; // CHECK: double z;
+ int y; // CHECK: const int* x;
+ double z; // CHECK: int y;
+ int w; // CHECK: int w;
+};
+
+int main() {
+ const int x = 13;
+ Foo foo = { &x, 17, 1.29, 0 }; // CHECK: Foo foo = { 1.29, &x, 17, 0 };
+ return 0;
+}
Index: test/clang-reorder-fields/CStructAmbiguousName.cpp
===================================================================
--- test/clang-reorder-fields/CStructAmbiguousName.cpp
+++ test/clang-reorder-fields/CStructAmbiguousName.cpp
@@ -0,0 +1,20 @@
+// RUN: cat %s > %t.cpp
+// RUN: clang-reorder-fields -record-name Foo -fields-order y,x %t.cpp -i --
+// RUN: sed 's,//.*,,' %t.cpp | FileCheck %s
+
+struct Foo {
+ int x; // CHECK: int x;
+ double y; // CHECK: double y;
+};
+
+namespace bar {
+struct Foo {
+ int x; // CHECK: int x;
+ double y; // CHECK: double y;
+};
+} // end namespace bar
+
+int main() {
+ Foo foo = { 1, 1.7 }; // CHECK: Foo foo = { 1, 1.7 };
+ return 0;
+}
Index: test/CMakeLists.txt
===================================================================
--- test/CMakeLists.txt
+++ test/CMakeLists.txt
@@ -45,6 +45,7 @@
clang-include-fixer
clang-query
clang-rename
+ clang-reorder-fields
clang-tidy
find-all-symbols
modularize
Index: clang-reorder-fields/tool/ClangReorderFields.cpp
===================================================================
--- clang-reorder-fields/tool/ClangReorderFields.cpp
+++ clang-reorder-fields/tool/ClangReorderFields.cpp
@@ -0,0 +1,135 @@
+//===-- tools/extra/clang-reorder-fields/tool/ClangReorderFields.cpp -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file contains the implementation of clang-reorder-fields tool
+///
+//===----------------------------------------------------------------------===//
+
+#include "../ReorderFieldsAction.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/DiagnosticOptions.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Frontend/TextDiagnosticPrinter.h"
+#include "clang/Rewrite/Core/Rewriter.h"
+#include "clang/Tooling/CommonOptionsParser.h"
+#include "clang/Tooling/Refactoring.h"
+#include "clang/Tooling/Tooling.h"
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/FileSystem.h"
+#include <cstdlib>
+#include <string>
+#include <system_error>
+#include <tuple>
+
+using namespace llvm;
+using namespace clang;
+
+cl::OptionCategory ClangReorderFieldsCategory("clang-reorder-fields options");
+
+// FIXME: error-handling
+struct FieldsOrderParser : cl::parser<SmallVector<std::string, 4>> {
+ explicit FieldsOrderParser(cl::Option &O)
+ : cl::parser<SmallVector<std::string, 4>>(O){};
+
+ bool parse(cl::Option &O, StringRef ArgName, const std::string &ArgValue,
+ SmallVector<std::string, 4> &Val) {
+ Val.clear();
+ SmallVector<StringRef, 4> Parts;
+ StringRef(ArgValue).split(Parts, ',');
+ for (const auto Part : Parts)
+ Val.push_back(Part.str());
+ return Val.empty();
+ }
+};
+
+// FIXME: error-handling
+struct FieldPositionParser : cl::parser<reorder_fields::FieldPosition> {
+ explicit FieldPositionParser(cl::Option &O)
+ : cl::parser<reorder_fields::FieldPosition>(O){};
+
+ bool parse(cl::Option &O, StringRef ArgName, const std::string &ArgValue,
+ reorder_fields::FieldPosition &Val) {
+ StringRef Name;
+ StringRef Position;
+ std::tie(Name, Position) = StringRef(ArgValue).split(":");
+ Val.Name = Name.str();
+ return Position.getAsInteger(10, Val.Position);
+ }
+};
+
+static cl::opt<std::string> RecordName("record-name",
+ cl::desc("The name of the struct/class."),
+ cl::cat(ClangReorderFieldsCategory));
+
+static cl::opt<SmallVector<std::string, 4>, false, FieldsOrderParser>
+ FieldsOrder("fields-order", cl::desc("The desired fields order."),
+ cl::cat(ClangReorderFieldsCategory));
+
+static cl::list<reorder_fields::FieldPosition, bool, FieldPositionParser>
+ FieldsPositions("field-pos", cl::desc("The new field position."),
+ cl::cat(ClangReorderFieldsCategory));
+
+static cl::opt<bool> Inplace("i", cl::desc("Overwrite edited <file>s."),
+ cl::cat(ClangReorderFieldsCategory));
+
+const char Usage[] = "A tool to reorder fields in C/C++ structs/classes.\n";
+
+int main(int argc, const char **argv) {
+ tooling::CommonOptionsParser OP(argc, argv, ClangReorderFieldsCategory,
+ Usage);
+
+ auto Files = OP.getSourcePathList();
+ tooling::RefactoringTool Tool(OP.getCompilations(), Files);
+
+ if (!FieldsOrder.empty() && !FieldsPositions.empty()) {
+ errs() << "Either fields-order or field-pos should not be specified\n";
+ exit(1);
+ }
+
+ std::unique_ptr<reorder_fields::ReorderFieldsAction> Action;
+ if (!FieldsOrder.empty())
+ Action.reset(new reorder_fields::ReorderFieldsAction(
+ RecordName, FieldsOrder, Tool.getReplacements()));
+
+ if (!FieldsPositions.empty())
+ Action.reset(new reorder_fields::ReorderFieldsAction(
+ RecordName, FieldsPositions, Tool.getReplacements()));
+
+ auto Factory = tooling::newFrontendActionFactory(Action.get());
+ int ExitCode;
+
+ if (Inplace) {
+ ExitCode = Tool.runAndSave(Factory.get());
+ } else {
+ ExitCode = Tool.run(Factory.get());
+
+ LangOptions DefaultLangOptions;
+ IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts(new DiagnosticOptions());
+ TextDiagnosticPrinter DiagnosticPrinter(errs(), &*DiagOpts);
+ DiagnosticsEngine Diagnostics(
+ IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs()), &*DiagOpts,
+ &DiagnosticPrinter, false);
+
+ auto &FileMgr = Tool.getFiles();
+ SourceManager Sources(Diagnostics, FileMgr);
+ Rewriter Rewrite(Sources, DefaultLangOptions);
+ Tool.applyAllReplacements(Rewrite);
+
+ for (const auto &File : Files) {
+ const auto *Entry = FileMgr.getFile(File);
+ const auto ID = Sources.translateFile(Entry);
+ Rewrite.getEditBuffer(ID).write(outs());
+ }
+ }
+ exit(ExitCode);
+}
Index: clang-reorder-fields/tool/CMakeLists.txt
===================================================================
--- clang-reorder-fields/tool/CMakeLists.txt
+++ clang-reorder-fields/tool/CMakeLists.txt
@@ -0,0 +1,12 @@
+add_clang_executable(clang-reorder-fields ClangReorderFields.cpp)
+
+target_link_libraries(clang-reorder-fields
+ clangBasic
+ clangFrontend
+ clangReorderFields
+ clangRewrite
+ clangTooling
+ clangToolingCore
+ )
+
+install(TARGETS clang-reorder-fields RUNTIME DESTINATION bin)
Index: clang-reorder-fields/ReorderFieldsAction.h
===================================================================
--- clang-reorder-fields/ReorderFieldsAction.h
+++ clang-reorder-fields/ReorderFieldsAction.h
@@ -0,0 +1,59 @@
+//===-- tools/extra/clang-reorder-fields/ReorderFieldsAction.h -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file contains the declarations of the ReorderFieldsAction class and
+/// the FieldPosition struct.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_REORDER_FIELDS_ACTION_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_REORDER_FIELDS_ACTION_H
+
+#include "clang/Tooling/Refactoring.h"
+
+namespace clang {
+class ASTConsumer;
+
+namespace reorder_fields {
+struct FieldPosition {
+ std::string Name;
+ unsigned Position;
+};
+
+class ReorderFieldsAction {
+ llvm::StringRef RecordName;
+ llvm::ArrayRef<std::string> DesiredFieldsOrder;
+ llvm::ArrayRef<FieldPosition> DesiredFieldsPositions;
+ std::map<std::string, tooling::Replacements> &Replacements;
+
+public:
+ ReorderFieldsAction(
+ llvm::StringRef RecordName,
+ llvm::ArrayRef<std::string> DesiredFieldsOrder,
+ std::map<std::string, tooling::Replacements> &Replacements)
+ : RecordName(RecordName), DesiredFieldsOrder(DesiredFieldsOrder),
+ Replacements(Replacements) {}
+
+ ReorderFieldsAction(
+ llvm::StringRef RecordName,
+ llvm::ArrayRef<FieldPosition> DesiredFieldsPositions,
+ std::map<std::string, tooling::Replacements> &Replacements)
+ : RecordName(RecordName), DesiredFieldsPositions(DesiredFieldsPositions),
+ Replacements(Replacements) {}
+
+ ReorderFieldsAction(const ReorderFieldsAction &) = delete;
+ ReorderFieldsAction &operator=(const ReorderFieldsAction &) = delete;
+
+ std::unique_ptr<ASTConsumer> newASTConsumer();
+};
+} // namespace reorder_fields
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_REORDER_FIELDS_ACTION_H
Index: clang-reorder-fields/ReorderFieldsAction.cpp
===================================================================
--- clang-reorder-fields/ReorderFieldsAction.cpp
+++ clang-reorder-fields/ReorderFieldsAction.cpp
@@ -0,0 +1,271 @@
+//===-- tools/extra/clang-reorder-fields/ReorderFieldsAction.cpp -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file contains the definition of the
+/// ReorderFieldsAction::newASTConsumer method
+///
+//===----------------------------------------------------------------------===//
+
+#include "ReorderFieldsAction.h"
+#include "clang/AST/AST.h"
+#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Tooling/Refactoring.h"
+#include <algorithm>
+#include <limits>
+#include <string>
+#include <unordered_map>
+#include <vector>
+
+using namespace llvm;
+using namespace clang;
+using namespace clang::ast_matchers;
+
+static const CXXRecordDecl *findDefinition(StringRef RecordName,
+ ASTContext &Context) {
+ struct DefinitionMatchCallback : MatchFinder::MatchCallback {
+ DefinitionMatchCallback() : RecordDecl(nullptr) {}
+ virtual void run(const MatchFinder::MatchResult &Result) override {
+ const auto *RD = Result.Nodes.getNodeAs<CXXRecordDecl>("cxxRecordDecl");
+ if (RecordDecl) {
+ errs() << "Ambiguous name, several matches found: "
+ << RecordDecl->getQualifiedNameAsString() << ", "
+ << RD->getQualifiedNameAsString() << "\n";
+ RecordDecl = nullptr;
+ return;
+ }
+ RecordDecl = RD;
+ }
+ const CXXRecordDecl *RecordDecl;
+ };
+
+ MatchFinder Finder;
+ DefinitionMatchCallback Callback;
+ const auto Matcher =
+ recordDecl(hasName(RecordName), isDefinition()).bind("cxxRecordDecl");
+ Finder.addMatcher(Matcher, &Callback);
+ Finder.matchAST(Context);
+ return Callback.RecordDecl;
+}
+
+static void
+addReplacement(SourceRange Old, SourceRange New, const ASTContext &Context,
+ std::map<std::string, tooling::Replacements> &Replacements) {
+ StringRef NewText =
+ Lexer::getSourceText(CharSourceRange::getTokenRange(New),
+ Context.getSourceManager(), Context.getLangOpts());
+ tooling::Replacement R(Context.getSourceManager(),
+ CharSourceRange::getTokenRange(Old), NewText,
+ Context.getLangOpts());
+ if (auto Err = Replacements[R.getFilePath()].add(R))
+ llvm::errs() << "Failed to add replacement, file: " << R.getFilePath()
+ << ", error: " << llvm::toString(std::move(Err)) << "\n";
+}
+
+static void reorderFieldsInDefinition(
+ const CXXRecordDecl *Definition, ArrayRef<unsigned> NewFieldsOrder,
+ const ASTContext &Context,
+ std::map<std::string, tooling::Replacements> &Replacements) {
+ assert(Definition && "Definition is null");
+
+ std::unordered_map<size_t, SourceRange> FieldToSource;
+ for (const auto *Field : Definition->fields())
+ FieldToSource[Field->getFieldIndex()] = Field->getSourceRange();
+
+ for (const auto *Field : Definition->fields()) {
+ const auto FieldIndex = Field->getFieldIndex();
+ if (FieldIndex == NewFieldsOrder[FieldIndex])
+ continue;
+ addReplacement(FieldToSource[FieldIndex],
+ FieldToSource[NewFieldsOrder[FieldIndex]], Context,
+ Replacements);
+ }
+}
+
+namespace clang {
+namespace reorder_fields {
+namespace {
+class ReorderingASTVisitor : public RecursiveASTVisitor<ReorderingASTVisitor> {
+ const CXXRecordDecl *Definition;
+ ArrayRef<unsigned> NewFieldsOrder;
+ const ASTContext &Context;
+ std::map<std::string, tooling::Replacements> &Replacements;
+
+public:
+ ReorderingASTVisitor(
+ const CXXRecordDecl *Definition, ArrayRef<unsigned> NewFieldsOrder,
+ const ASTContext &Context,
+ std::map<std::string, tooling::Replacements> &Replacements)
+ : Definition(Definition), NewFieldsOrder(NewFieldsOrder),
+ Context(Context), Replacements(Replacements) {}
+
+ ReorderingASTVisitor(const ReorderingASTVisitor &) = delete;
+ ReorderingASTVisitor &operator=(const ReorderingASTVisitor &) = delete;
+
+ bool VisitInitListExpr(InitListExpr *InitListEx) {
+ if (!InitListEx->isExplicit() || !InitListEx->getNumInits())
+ return true;
+
+ const auto *RD = InitListEx->getType()
+ .getCanonicalType()
+ .getTypePtr()
+ ->getAsCXXRecordDecl();
+ assert(RD && "CXXRecordDecl is null");
+ if (RD->getDefinition() != Definition)
+ return true;
+ if (InitListEx->getNumInits() != NewFieldsOrder.size()) {
+ errs() << "Currently support only full initialization.\n";
+ return true;
+ }
+
+ for (unsigned Index = 0, NumInits = InitListEx->getNumInits();
+ Index < NumInits; ++Index) {
+ if (Index == NewFieldsOrder[Index])
+ continue;
+ addReplacement(
+ InitListEx->getInit(Index)->getSourceRange(),
+ InitListEx->getInit(NewFieldsOrder[Index])->getSourceRange(), Context,
+ Replacements);
+ }
+ return true;
+ }
+};
+
+class ReorderingConsumer : public ASTConsumer {
+ StringRef RecordName;
+ ArrayRef<std::string> DesiredFieldsOrder;
+ ArrayRef<FieldPosition> DesiredFieldsPositions;
+ std::map<std::string, tooling::Replacements> &Replacements;
+ SmallVector<unsigned, 4> NewFieldsOrder;
+
+ bool setNewFieldsOrder(const CXXRecordDecl *Definition,
+ ArrayRef<std::string> DesiredFieldsOrder) {
+ assert(Definition && "Definition is null");
+
+ StringMap<unsigned> NameToIndex;
+ for (const auto *Field : Definition->fields())
+ NameToIndex[Field->getName()] = Field->getFieldIndex();
+
+ if (DesiredFieldsOrder.size() != NameToIndex.size()) {
+ errs() << "Number of provided fields doesn't match definition.\n";
+ return false;
+ }
+
+ NewFieldsOrder.clear();
+ for (const auto &Name : DesiredFieldsOrder) {
+ if (!NameToIndex.count(Name)) {
+ errs() << "Field " << Name << " not found in definition.\n";
+ return false;
+ }
+ NewFieldsOrder.push_back(NameToIndex[Name]);
+ }
+ assert(NewFieldsOrder.size() == NameToIndex.size());
+ return true;
+ }
+
+ bool setNewFieldsOrder(const CXXRecordDecl *Definition,
+ ArrayRef<FieldPosition> DesiredFieldsPositions) {
+ assert(Definition && "Definition is null");
+
+ StringMap<unsigned> NameToIndex;
+ for (const auto *Field : Definition->fields())
+ NameToIndex[Field->getName()] = Field->getFieldIndex();
+
+ StringSet<> AllocatedFields;
+ LLVM_CONSTEXPR unsigned INF = std::numeric_limits<unsigned>::max();
+ NewFieldsOrder.assign(NameToIndex.size(), INF);
+ for (const auto &FP : DesiredFieldsPositions) {
+ if (!NameToIndex.count(FP.Name)) {
+ errs() << "Field " << FP.Name << " not found in the definition\n";
+ return false;
+ }
+ if (FP.Position >= NewFieldsOrder.size()) {
+ errs() << "Field [" << FP.Name << "]"
+ << " position [" << FP.Position << "] out of range\n";
+ return false;
+ }
+ if (AllocatedFields.count(FP.Name)) {
+ errs() << "Field " << FP.Name << " specified twice\n";
+ return false;
+ }
+ NewFieldsOrder[FP.Position] = NameToIndex[FP.Name];
+ AllocatedFields.insert(FP.Name);
+ }
+
+ unsigned NextFreePosition = 0;
+ for (const auto *Field : Definition->fields()) {
+ if (AllocatedFields.count(Field->getName()))
+ continue;
+ while (NextFreePosition < NewFieldsOrder.size() &&
+ NewFieldsOrder[NextFreePosition] != INF)
+ ++NextFreePosition;
+ assert(NextFreePosition < NewFieldsOrder.size());
+ NewFieldsOrder[NextFreePosition] = Field->getFieldIndex();
+ }
+ return true;
+ }
+
+public:
+ ReorderingConsumer(StringRef RecordName,
+ ArrayRef<std::string> DesiredFieldsOrder,
+ std::map<std::string, tooling::Replacements> &Replacements)
+ : RecordName(RecordName), DesiredFieldsOrder(DesiredFieldsOrder),
+ Replacements(Replacements) {}
+
+ ReorderingConsumer(StringRef RecordName,
+ ArrayRef<FieldPosition> DesiredFieldsPositions,
+ std::map<std::string, tooling::Replacements> &Replacements)
+ : RecordName(RecordName), DesiredFieldsPositions(DesiredFieldsPositions),
+ Replacements(Replacements) {}
+
+ ReorderingConsumer(const ReorderingConsumer &) = delete;
+ ReorderingConsumer &operator=(const ReorderingConsumer &) = delete;
+
+ void HandleTranslationUnit(ASTContext &Context) override {
+ const CXXRecordDecl *RD = findDefinition(RecordName, Context);
+ if (!RD) {
+ errs() << "Definition for name " << RecordName
+ << " not found or ambiguous.\n";
+ return;
+ }
+ if (!RD->isCLike()) {
+ errs() << "Now only C-like structs are supported.\n";
+ return;
+ }
+ if (!DesiredFieldsOrder.empty() &&
+ !setNewFieldsOrder(RD, DesiredFieldsOrder))
+ return;
+ if (!DesiredFieldsPositions.empty() &&
+ !setNewFieldsOrder(RD, DesiredFieldsPositions))
+ return;
+ reorderFieldsInDefinition(RD, NewFieldsOrder, Context, Replacements);
+ ReorderingASTVisitor Visitor(RD, NewFieldsOrder, Context, Replacements);
+ Visitor.TraverseDecl(Context.getTranslationUnitDecl());
+ }
+};
+} // end anonymous namespace
+
+std::unique_ptr<ASTConsumer> ReorderFieldsAction::newASTConsumer() {
+ assert(!DesiredFieldsOrder.empty() || !DesiredFieldsPositions.empty());
+ if (!DesiredFieldsOrder.empty())
+ return llvm::make_unique<ReorderingConsumer>(RecordName, DesiredFieldsOrder,
+ Replacements);
+ if (!DesiredFieldsPositions.empty())
+ return llvm::make_unique<ReorderingConsumer>(
+ RecordName, DesiredFieldsPositions, Replacements);
+ llvm_unreachable("Either list of fields or list of positions is not empty");
+}
+
+} // namespace reorder_fields
+} // namespace clang
Index: clang-reorder-fields/CMakeLists.txt
===================================================================
--- clang-reorder-fields/CMakeLists.txt
+++ clang-reorder-fields/CMakeLists.txt
@@ -0,0 +1,15 @@
+set(LLVM_LINK_COMPONENTS support)
+
+add_clang_library(clangReorderFields
+ ReorderFieldsAction.cpp
+
+ LINK_LIBS
+ clangAST
+ clangASTMatchers
+ clangBasic
+ clangIndex
+ clangLex
+ clangToolingCore
+ )
+
+add_subdirectory(tool)
Index: CMakeLists.txt
===================================================================
--- CMakeLists.txt
+++ CMakeLists.txt
@@ -1,5 +1,6 @@
add_subdirectory(clang-apply-replacements)
add_subdirectory(clang-rename)
+add_subdirectory(clang-reorder-fields)
add_subdirectory(modularize)
if(CLANG_ENABLE_STATIC_ANALYZER)
add_subdirectory(clang-tidy)
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits