alexshap updated this revision to Diff 68953.
alexshap added a comment.

Drop support of -field-pos for now


Repository:
  rL LLVM

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/CStructFieldsOrder.cpp
  test/clang-reorder-fields/ClassMixedInitialization.cpp
  test/clang-reorder-fields/ClassSimpleCtor.cpp

Index: test/clang-reorder-fields/ClassSimpleCtor.cpp
===================================================================
--- test/clang-reorder-fields/ClassSimpleCtor.cpp
+++ test/clang-reorder-fields/ClassSimpleCtor.cpp
@@ -0,0 +1,26 @@
+// RUN: cat %s > %t.cpp
+// RUN: clang-reorder-fields -record-name Foo -fields-order s1,x,z,s2 %t.cpp -i --
+// RUN: sed 's,//.*,,' %t.cpp | FileCheck %s
+
+class Foo {
+public:
+  Foo();
+
+private:
+  int x;              // CHECK: const char *s1;
+  const char *s1;     // CHECK: int x;
+  const char *s2;     // CHECK: double z;
+  double z;           // CHECK: const char *s2;
+};
+
+Foo::Foo():
+  x(12),      // CHECK: s1("abc"),
+  s1("abc"),  // CHECK: x(12),
+  s2("def"),  // CHECK: z(3.14),
+  z(3.14)     // CHECK: s2("def")
+{}
+
+int main() {
+  Foo foo;
+  return 0;
+}
Index: test/clang-reorder-fields/ClassMixedInitialization.cpp
===================================================================
--- test/clang-reorder-fields/ClassMixedInitialization.cpp
+++ test/clang-reorder-fields/ClassMixedInitialization.cpp
@@ -0,0 +1,26 @@
+// RUN: cat %s > %t.cpp
+// RUN: clang-reorder-fields -record-name Foo -fields-order e,x,pi,s2,s1 %t.cpp -i -- -std=c++11
+// RUN: sed 's,//.*,,' %t.cpp | FileCheck %s
+
+class Foo {
+public:
+  Foo();
+
+private:
+  int x;              // CHECK: double e = 2.71;
+  const char *s1;     // CHECK: int x;
+  const char *s2;     // CHECK: double pi = 3.14;
+  double pi = 3.14;   // CHECK: const char *s2;
+  double e = 2.71;    // CHECK: const char *s1;
+};
+
+Foo::Foo():
+  x(12),      // CHECK: x(12),
+  s1("abc"),  // CHECK: s2("def"),
+  s2("def")   // CHECK: s1("abc")
+{}
+
+int main() {
+  Foo foo;
+  return 0;
+}
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/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,104 @@
+//===-- 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>
+
+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();
+  }
+};
+
+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::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);
+
+  reorder_fields::ReorderFieldsAction Action(RecordName, FieldsOrder,
+                                             Tool.getReplacements());
+
+  auto Factory = tooling::newFrontendActionFactory(&Action);
+  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,47 @@
+//===-- 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 {
+
+class ReorderFieldsAction {
+  llvm::StringRef RecordName;
+  llvm::ArrayRef<std::string> DesiredFieldsOrder;
+  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(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,263 @@
+//===-- 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 <string>
+
+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 bool setNewFieldsOrder(const CXXRecordDecl *Definition,
+                              ArrayRef<std::string> DesiredFieldsOrder,
+                              SmallVector<unsigned, 4> &NewFieldsOrder) {
+  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;
+}
+
+// FIXME: error-handling
+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());
+  consumeError(Replacements[R.getFilePath()].add(R));
+}
+
+static void reorderFieldsInDefinition(
+    const CXXRecordDecl *Definition, ArrayRef<unsigned> NewFieldsOrder,
+    const ASTContext &Context,
+    std::map<std::string, tooling::Replacements> &Replacements) {
+  assert(Definition && "Definition is null");
+
+  SmallVector<const FieldDecl *, 10> Fields;
+  for (const auto *Field : Definition->fields())
+    Fields.push_back(Field);
+  for (const auto *Field : Definition->fields()) {
+    const auto FieldIndex = Field->getFieldIndex();
+    if (FieldIndex == NewFieldsOrder[FieldIndex])
+      continue;
+    assert(Field->getAccess() ==
+               Fields[NewFieldsOrder[FieldIndex]]->getAccess() &&
+           "Currently reodering of fields with different accesses is not "
+           "supported");
+    addReplacement(Field->getSourceRange(),
+                   Fields[NewFieldsOrder[FieldIndex]]->getSourceRange(),
+                   Context, Replacements);
+  }
+}
+
+static void reorderFieldsInConstructor(
+    const CXXConstructorDecl *CtorDecl, ArrayRef<unsigned> NewFieldsOrder,
+    const ASTContext &Context,
+    std::map<std::string, tooling::Replacements> &Replacements) {
+  assert(CtorDecl && "Constructor declaration is null");
+  assert(CtorDecl->isThisDeclarationADefinition() && "Not a definition");
+
+  SmallVector<unsigned, 10> NewFieldsPositions(NewFieldsOrder.size());
+  for (unsigned Index = 0; Index < NewFieldsOrder.size(); ++Index)
+    NewFieldsPositions[NewFieldsOrder[Index]] = Index;
+
+  SmallVector<const CXXCtorInitializer *, 10> OldWrittenInitializersOrder;
+  SmallVector<const CXXCtorInitializer *, 10> NewWrittenInitializersOrder;
+  for (const auto *Initializer : CtorDecl->inits()) {
+    if (!Initializer->isWritten())
+      continue;
+    OldWrittenInitializersOrder.push_back(Initializer);
+    NewWrittenInitializersOrder.push_back(Initializer);
+  }
+  auto ByFieldNewPosition = [&](const CXXCtorInitializer *LHS,
+                                const CXXCtorInitializer *RHS) {
+    assert(LHS && RHS);
+    return NewFieldsPositions[LHS->getMember()->getFieldIndex()] <
+           NewFieldsPositions[RHS->getMember()->getFieldIndex()];
+  };
+  std::sort(std::begin(NewWrittenInitializersOrder),
+            std::end(NewWrittenInitializersOrder), ByFieldNewPosition);
+  assert(OldWrittenInitializersOrder.size() ==
+         NewWrittenInitializersOrder.size());
+  for (unsigned Index = 0; Index < NewWrittenInitializersOrder.size(); ++Index)
+    addReplacement(OldWrittenInitializersOrder[Index]->getSourceRange(),
+                   NewWrittenInitializersOrder[Index]->getSourceRange(),
+                   Context, Replacements);
+}
+
+static void reorderFieldsInInitListExpr(
+    const InitListExpr *InitListEx, ArrayRef<unsigned> NewFieldsOrder,
+    const ASTContext &Context,
+    std::map<std::string, tooling::Replacements> &Replacements) {
+  assert(InitListEx && "Init list expression is null");
+  // FIXME: InitListExpr::isExplicit probably should be const because
+  // SourceLocation::isValid is const.
+  if (!const_cast<clang::InitListExpr *>(InitListEx)->isExplicit() ||
+      !InitListEx->getNumInits())
+    return;
+  assert(InitListEx->getNumInits() == NewFieldsOrder.size() &&
+         "Currently only full initialization is supported");
+  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);
+  }
+}
+
+namespace clang {
+namespace reorder_fields {
+namespace {
+class InitListExprMatchCallback : public MatchFinder::MatchCallback {
+  const CXXRecordDecl *Definition;
+  ArrayRef<unsigned> NewFieldsOrder;
+  const ASTContext &Context;
+  std::map<std::string, tooling::Replacements> &Replacements;
+
+public:
+  InitListExprMatchCallback(
+      const CXXRecordDecl *Definition, ArrayRef<unsigned> NewFieldsOrder,
+      const ASTContext &Context,
+      std::map<std::string, tooling::Replacements> &Replacements)
+      : Definition(Definition), NewFieldsOrder(NewFieldsOrder),
+        Context(Context), Replacements(Replacements) {}
+
+  virtual void run(const MatchFinder::MatchResult &Result) override {
+    const auto *E = Result.Nodes.getNodeAs<InitListExpr>("initListExpr");
+    assert(E && "InitListExpr is null");
+    const auto *T = E->getType().getCanonicalType().getTypePtr();
+    assert(T && "Type is null");
+    const auto *RD = T->getAsCXXRecordDecl();
+    if (!RD)
+      return;
+    if (Definition != RD->getDefinition())
+      return;
+    reorderFieldsInInitListExpr(E, NewFieldsOrder, Context, Replacements);
+  }
+};
+
+class ReorderingConsumer : public ASTConsumer {
+  StringRef RecordName;
+  ArrayRef<std::string> DesiredFieldsOrder;
+  std::map<std::string, tooling::Replacements> &Replacements;
+
+public:
+  ReorderingConsumer(StringRef RecordName,
+                     ArrayRef<std::string> DesiredFieldsOrder,
+                     std::map<std::string, tooling::Replacements> &Replacements)
+      : RecordName(RecordName), DesiredFieldsOrder(DesiredFieldsOrder),
+        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;
+    }
+
+    SmallVector<unsigned, 4> NewFieldsOrder;
+    if (!setNewFieldsOrder(RD, DesiredFieldsOrder, NewFieldsOrder))
+      return;
+    reorderFieldsInDefinition(RD, NewFieldsOrder, Context, Replacements);
+    for (const auto *C : RD->ctors()) {
+      if (C->isImplicit() || C->isDelegatingConstructor())
+        continue;
+      const auto *D = C->getDefinition();
+      if (!D)
+        continue;
+      reorderFieldsInConstructor(cast<const CXXConstructorDecl>(D),
+                                 NewFieldsOrder, Context, Replacements);
+    }
+    if (!RD->isAggregate())
+      return;
+    MatchFinder Finder;
+    InitListExprMatchCallback Callback(RD, NewFieldsOrder, Context,
+                                       Replacements);
+    const auto Matcher = initListExpr().bind("initListExpr");
+    Finder.addMatcher(Matcher, &Callback);
+    Finder.matchAST(Context);
+  }
+};
+} // end anonymous namespace
+
+std::unique_ptr<ASTConsumer> ReorderFieldsAction::newASTConsumer() {
+  return llvm::make_unique<ReorderingConsumer>(RecordName, DesiredFieldsOrder,
+                                               Replacements);
+}
+
+} // 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
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to