[PATCH] D30210: [include-fixer] Add usage count to find-all-symbols.

2017-02-22 Thread Haojian Wu via Phabricator via cfe-commits
hokein added a comment.

Thanks for the contributions!




Comment at: include-fixer/find-all-symbols/FindAllSymbols.cpp:244
 
-  const auto *ND = Result.Nodes.getNodeAs("decl");
-  assert(ND && "Matched declaration must be a NamedDecl!");
+  auto report = ::reportSymbol;
+  const NamedDecl *ND;

The way seems too tricky to me. I'd use a flag variable like `isUsedDecl` to 
distinguish and handle `use` and `decl` cases.



Comment at: include-fixer/find-all-symbols/FindAllSymbols.cpp:250
+  } else {
+assert(!"Must match a NamedDecl!");
+  }

Is the preceding `!` intended?



Comment at: include-fixer/find-all-symbols/SymbolInfo.h:83
+  /// run. Populated by the reducer and used to rank results.
+  mutable unsigned NumOccurrences;
+  /// \brief The number of times this symbol was used during an indexing run.

A blank between class members.



Comment at: unittests/include-fixer/find-all-symbols/FindAllSymbolsTests.cpp:551
   EXPECT_TRUE(hasSymbol(Symbol));
+  EXPECT_FALSE(hasUse(Symbol));  // Not yet implemented.
 

The same.



Comment at: unittests/include-fixer/find-all-symbols/FindAllSymbolsTests.cpp:48
   bool hasSymbol(const SymbolInfo ) const {
-for (const auto  : Symbols) {
-  if (S == Symbol)
-return true;
-}
-return false;
+return std::find(Symbols.begin(), Symbols.end(), Symbol) != Symbols.end();
+  }

nit: You can use `llvm::is_contained` here.



Comment at: unittests/include-fixer/find-all-symbols/FindAllSymbolsTests.cpp:52
+  bool hasUse(const SymbolInfo ) const {
+return std::find(Used.begin(), Used.end(), Symbol) != Used.end();
   }

The same.



Comment at: unittests/include-fixer/find-all-symbols/FindAllSymbolsTests.cpp:65
   }
+  bool hasUse(const SymbolInfo ) {
+return Reporter.hasUse(Symbol);

nit: a blank line between methods.



Comment at: unittests/include-fixer/find-all-symbols/FindAllSymbolsTests.cpp:526
   EXPECT_TRUE(hasSymbol(Symbol));
+  EXPECT_FALSE(hasUse(Symbol));  // Not yet implemented.
 

I'd put a `FIXME` comment here.


https://reviews.llvm.org/D30210



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D30210: [include-fixer] Add usage count to find-all-symbols.

2017-02-23 Thread Haojian Wu via Phabricator via cfe-commits
hokein added inline comments.



Comment at: unittests/include-fixer/find-all-symbols/FindAllSymbolsTests.cpp:40
+  void reportSymbols(llvm::StringRef FileName,
+ SymbolInfo::SignalMap NewSymbols) override {
+for (const auto  : NewSymbols)

A new catch: `NewSymbols` should be passed by reference, otherwise a copy will 
be generated. 


https://reviews.llvm.org/D30210



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D30210: [include-fixer] Add usage count to find-all-symbols.

2017-02-24 Thread Haojian Wu via Phabricator via cfe-commits
hokein added a comment.

Thanks, still LGTM with one nit.




Comment at: include-fixer/find-all-symbols/FindAllSymbols.cpp:262
+  if (Filename != "") {
+Reporter->reportSymbols(Filename, std::move(FileSymbols));
+FileSymbols = {};

We don't need `std::move` right now.


https://reviews.llvm.org/D30210



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D30328: [change-namepsace] make it possible to whitelist symbols so they don't get updated.

2017-02-24 Thread Haojian Wu via Phabricator via cfe-commits
hokein accepted this revision.
hokein added a comment.
This revision is now accepted and ready to land.

LGTM.




Comment at: change-namespace/tool/ClangChangeNamespace.cpp:78
+// changing namespaces around them.
+constexpr const char *WhiteListedSymbolPatterns[] = {"^std::.*$"};
+

Maybe consider create a command-line option for it? It will make the tool more 
pluggable IMO.


https://reviews.llvm.org/D30328



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D30328: [change-namepsace] make it possible to whitelist symbols so they don't get updated.

2017-02-24 Thread Haojian Wu via Phabricator via cfe-commits
hokein added inline comments.



Comment at: change-namespace/tool/ClangChangeNamespace.cpp:82
+
+llvm::ErrorOr GetWhiteListedSymbolPatterns() {
+  llvm::SmallVector Lines;

Instead `std::vector`, maybe std::vector is better, 
with that we don't need to do transform stuff in `ChangeNamespaceTool`.



Comment at: test/change-namespace/Inputs/white-list.txt:1
+^std::.*$

As this is only one-line file, I'd create this file in `whitelist` lint test 
like `echo XX > whitelist.txt` to avoid adding a new file in test.



Comment at: unittests/change-namespace/ChangeNamespaceTests.cpp:42
 change_namespace::ChangeNamespaceTool NamespaceTool(
-OldNamespace, NewNamespace, FilePattern, );
+OldNamespace, NewNamespace, FilePattern, WhiteList,
+);

`/*WhiteListedSymbolPatterns*/{}` is enough.


https://reviews.llvm.org/D30328



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D30337: [clang-move] Extend clang-move to support moving global variable.

2017-02-24 Thread Haojian Wu via Phabricator via cfe-commits
hokein updated this revision to Diff 89659.
hokein added a comment.

No accident changes.


https://reviews.llvm.org/D30337

Files:
  clang-move/ClangMove.cpp
  test/clang-move/Inputs/var_test.cpp
  test/clang-move/Inputs/var_test.h
  test/clang-move/move-var.cpp
  unittests/clang-move/ClangMoveTests.cpp

Index: unittests/clang-move/ClangMoveTests.cpp
===
--- unittests/clang-move/ClangMoveTests.cpp
+++ unittests/clang-move/ClangMoveTests.cpp
@@ -539,6 +539,8 @@
 "enum class E2 { Red };\n"
 "typedef int Int2;\n"
 "using Int = int;\n"
+"extern int kGlobalInt;\n"
+"extern const char* const kGlobalStr;\n"
 "} // namespace b\n"
 "} // namespace a\n";
   const char TestCode[] = "#include \"foo.h\"\n";
@@ -553,7 +555,8 @@
   {"A", "Class"}, {"B", "Class"},{"a::Move1", "Class"},
   {"a::f1", "Function"},  {"a::f2", "Function"}, {"a::b::Move1", "Class"},
   {"a::b::f", "Function"}, {"a::b::E1", "Enum"}, {"a::b::E2", "Enum"},
-  {"a::b::Int2", "TypeAlias"}, {"a::b::Int", "TypeAlias"} };
+  {"a::b::Int2", "TypeAlias"}, {"a::b::Int", "TypeAlias"},
+  {"a::b::kGlobalInt", "Variable"}, {"a::b::kGlobalStr", "Variable"}};
   runClangMoveOnCode(Spec, TestHeader, TestCode, );
   std::set Results;
   for (const auto& DelPair : Reporter.getDeclarationList())
Index: test/clang-move/move-var.cpp
===
--- /dev/null
+++ test/clang-move/move-var.cpp
@@ -0,0 +1,46 @@
+// RUN: mkdir -p %T/move-var
+// RUN: cp %S/Inputs/var_test*  %T/move-var
+// RUN: cd %T/move-var
+// RUN: clang-move -names="a::kGlobalInt" -new_header=%T/move-var/new_var_test.h -old_header=../move-var/var_test.h -old_cc=../move-var/var_test.cpp -new_cc=%T/move-var/new_var_test.cpp %T/move-var/var_test.cpp --
+// RUN: FileCheck -input-file=%T/move-var/var_test.h -check-prefix=CHECK-OLD-VAR-H-CASE1 %s
+// RUN: FileCheck -input-file=%T/move-var/var_test.cpp -check-prefix=CHECK-OLD-VAR-CPP-CASE1 %s
+// RUN: FileCheck -input-file=%T/move-var/new_var_test.h -check-prefix=CHECK-NEW-VAR-H-CASE1 %s
+// RUN: FileCheck -input-file=%T/move-var/new_var_test.cpp -check-prefix=CHECK-NEW-VAR-CPP-CASE1 %s
+
+// CHECK-OLD-VAR-H-CASE1-NOT: extern int kGlobalInt;
+// CHECK-OLD-VAR-H-CASE1: int kGlobalInt = 3;
+
+// CHECK-OLD-VAR-CPP-CASE1-NOT: int kGlobalInt = 1;
+
+// CHECK-NEW-VAR-H-CASE1: extern int kGlobalInt;
+// CHECK-NEW-VAR-H-CASE1-NOT: int kGlobalInt = 3;
+
+// CHECK-NEW-VAR-CPP-CASE1: int kGlobalInt = 1;
+
+
+// RUN: cp %S/Inputs/var_test*  %T/move-var
+// RUN: clang-move -names="a::kGlobalStr" -new_header=%T/move-var/new_var_test.h -old_header=../move-var/var_test.h -old_cc=../move-var/var_test.cpp -new_cc=%T/move-var/new_var_test.cpp %T/move-var/var_test.cpp --
+// RUN: FileCheck -input-file=%T/move-var/var_test.h -check-prefix=CHECK-OLD-VAR-H-CASE2 %s
+// RUN: FileCheck -input-file=%T/move-var/var_test.cpp -check-prefix=CHECK-OLD-VAR-CPP-CASE2 %s
+// RUN: FileCheck -input-file=%T/move-var/new_var_test.h -check-prefix=CHECK-NEW-VAR-H-CASE2 %s
+// RUN: FileCheck -input-file=%T/move-var/new_var_test.cpp -check-prefix=CHECK-NEW-VAR-CPP-CASE2 %s
+
+// CHECK-OLD-VAR-H-CASE2-NOT: extern const char *const kGlobalStr;
+// CHECK-OLD-VAR-H-CASE2: const char *const kGlobalStr = "Hello2";
+
+// CHECK-OLD-VAR-CPP-CASE2-NOT: const char *const kGlobalStr = "Hello";
+
+// CHECK-NEW-VAR-H-CASE2: extern const char *const kGlobalStr;
+// CHECK-NEW-VAR-H-CASE2-NOT: const char *const kGlobalStr = "Hello2";
+
+// CHECK-NEW-VAR-CPP-CASE2: const char *const kGlobalStr = "Hello";
+
+
+// RUN: cp %S/Inputs/var_test*  %T/move-var
+// RUN: clang-move -names="kEvilInt" -new_header=%T/move-var/new_var_test.h -old_header=../move-var/var_test.h -old_cc=../move-var/var_test.cpp -new_cc=%T/move-var/new_var_test.cpp %T/move-var/var_test.cpp --
+// RUN: FileCheck -input-file=%T/move-var/var_test.h -check-prefix=CHECK-OLD-VAR-H-CASE3 %s
+// RUN: FileCheck -input-file=%T/move-var/new_var_test.h -check-prefix=CHECK-NEW-VAR-H-CASE3 %s
+
+// CHECK-OLD-VAR-H-CASE3-NOT: int kEvilInt = 2;
+
+// CHECK-NEW-VAR-H-CASE3: int kEvilInt = 2;
Index: test/clang-move/Inputs/var_test.h
===
--- /dev/null
+++ test/clang-move/Inputs/var_test.h
@@ -0,0 +1,11 @@
+namespace a {
+extern int kGlobalInt;
+extern const char *const kGlobalStr;
+}
+
+int kEvilInt = 2;
+
+inline void f1() {
+  int kGlobalInt = 3;
+  const char *const kGlobalStr = "Hello2";
+}
Index: test/clang-move/Inputs/var_test.cpp
===
--- /dev/null
+++ test/clang-move/Inputs/var_test.cpp
@@ -0,0 +1,6 @@
+#include "var_test.h"
+
+namespace a{
+int kGlobalInt = 1;
+const char *const 

[PATCH] D30337: [clang-move] Extend clang-move to support moving global variable.

2017-02-24 Thread Haojian Wu via Phabricator via cfe-commits
hokein created this revision.

Also support dumping global variables.


https://reviews.llvm.org/D30337

Files:
  clang-move/ClangMove.cpp
  test/clang-move/Inputs/var_test.cpp
  test/clang-move/Inputs/var_test.h
  test/clang-move/move-var.cpp
  unittests/clang-move/ClangMoveTests.cpp

Index: unittests/clang-move/ClangMoveTests.cpp
===
--- unittests/clang-move/ClangMoveTests.cpp
+++ unittests/clang-move/ClangMoveTests.cpp
@@ -539,6 +539,8 @@
 "enum class E2 { Red };\n"
 "typedef int Int2;\n"
 "using Int = int;\n"
+"extern int kGlobalInt;\n"
+"extern const char* const kGlobalStr;\n"
 "} // namespace b\n"
 "} // namespace a\n";
   const char TestCode[] = "#include \"foo.h\"\n";
@@ -553,7 +555,8 @@
   {"A", "Class"}, {"B", "Class"},{"a::Move1", "Class"},
   {"a::f1", "Function"},  {"a::f2", "Function"}, {"a::b::Move1", "Class"},
   {"a::b::f", "Function"}, {"a::b::E1", "Enum"}, {"a::b::E2", "Enum"},
-  {"a::b::Int2", "TypeAlias"}, {"a::b::Int", "TypeAlias"} };
+  {"a::b::Int2", "TypeAlias"}, {"a::b::Int", "TypeAlias"},
+  {"a::b::kGlobalInt", "Variable"}, {"a::b::kGlobalStr", "Variable"}};
   runClangMoveOnCode(Spec, TestHeader, TestCode, );
   std::set Results;
   for (const auto& DelPair : Reporter.getDeclarationList())
Index: test/clang-move/move-var.cpp
===
--- /dev/null
+++ test/clang-move/move-var.cpp
@@ -0,0 +1,47 @@
+// RUN: mkdir -p %T/move-var
+// RUN: cp %S/Inputs/var_test*  %T/move-var
+// RUN: cd %T/move-var
+// RUN: clang-move -names="a::kGlobalInt" -new_header=%T/move-var/new_var_test.h -old_header=../move-var/var_test.h -old_cc=../move-var/var_test.cpp -new_cc=%T/move-var/new_var_test.cpp %T/move-var/var_test.cpp --
+// RUN: FileCheck -input-file=%T/move-var/var_test.h -check-prefix=CHECK-OLD-VAR-H-CASE1 %s
+// RUN: FileCheck -input-file=%T/move-var/var_test.cpp -check-prefix=CHECK-OLD-VAR-CPP-CASE1 %s
+// RUN: FileCheck -input-file=%T/move-var/new_var_test.h -check-prefix=CHECK-NEW-VAR-H-CASE1 %s
+// RUN: FileCheck -input-file=%T/move-var/new_var_test.cpp -check-prefix=CHECK-NEW-VAR-CPP-CASE1 %s
+
+// CHECK-OLD-VAR-H-CASE1-NOT: extern int kGlobalInt;
+// CHECK-OLD-VAR-H-CASE1: int kGlobalInt = 3;
+
+// CHECK-OLD-VAR-CPP-CASE1-NOT: int kGlobalInt = 1;
+
+// CHECK-NEW-VAR-H-CASE1: extern int kGlobalInt;
+// CHECK-NEW-VAR-H-CASE1-NOT: int kGlobalInt = 3;
+
+// CHECK-NEW-VAR-CPP-CASE1: int kGlobalInt = 1;
+
+
+// RUN: cp %S/Inputs/var_test*  %T/move-var
+// RUN: clang-move -names="a::kGlobalStr" -new_header=%T/move-var/new_var_test.h -old_header=../move-var/var_test.h -old_cc=../move-var/var_test.cpp -new_cc=%T/move-var/new_var_test.cpp %T/move-var/var_test.cpp --
+// RUN: FileCheck -input-file=%T/move-var/var_test.h -check-prefix=CHECK-OLD-VAR-H-CASE2 %s
+// RUN: FileCheck -input-file=%T/move-var/var_test.cpp -check-prefix=CHECK-OLD-VAR-CPP-CASE2 %s
+// RUN: FileCheck -input-file=%T/move-var/new_var_test.h -check-prefix=CHECK-NEW-VAR-H-CASE2 %s
+// RUN: FileCheck -input-file=%T/move-var/new_var_test.cpp -check-prefix=CHECK-NEW-VAR-CPP-CASE2 %s
+
+// CHECK-OLD-VAR-H-CASE2-NOT: extern const char *const kGlobalStr;
+// CHECK-OLD-VAR-H-CASE2: const char *const kGlobalStr = "Hello2";
+
+// CHECK-OLD-VAR-CPP-CASE2-NOT: const char *const kGlobalStr = "Hello";
+
+// CHECK-NEW-VAR-H-CASE2: extern const char *const kGlobalStr;
+// CHECK-NEW-VAR-H-CASE2-NOT: const char *const kGlobalStr = "Hello2";
+
+// CHECK-NEW-VAR-CPP-CASE2: const char *const kGlobalStr = "Hello";
+
+
+
+// RUN: cp %S/Inputs/var_test*  %T/move-var
+// RUN: clang-move -names="kEvilInt" -new_header=%T/move-var/new_var_test.h -old_header=../move-var/var_test.h -old_cc=../move-var/var_test.cpp -new_cc=%T/move-var/new_var_test.cpp %T/move-var/var_test.cpp --
+// RUN: FileCheck -input-file=%T/move-var/var_test.h -check-prefix=CHECK-OLD-VAR-H-CASE3 %s
+// RUN: FileCheck -input-file=%T/move-var/new_var_test.h -check-prefix=CHECK-NEW-VAR-H-CASE3 %s
+
+// CHECK-OLD-VAR-H-CASE3-NOT: int kEvilInt = 2;
+
+// CHECK-NEW-VAR-H-CASE3: int kEvilInt = 2;
Index: test/clang-move/Inputs/var_test.h
===
--- /dev/null
+++ test/clang-move/Inputs/var_test.h
@@ -0,0 +1,11 @@
+namespace a {
+extern int kGlobalInt;
+extern const char *const kGlobalStr;
+}
+
+int kEvilInt = 2;
+
+inline void f1() {
+  int kGlobalInt = 3;
+  const char *const kGlobalStr = "Hello2";
+}
Index: test/clang-move/Inputs/var_test.cpp
===
--- /dev/null
+++ test/clang-move/Inputs/var_test.cpp
@@ -0,0 +1,6 @@
+#include "var_test.h"
+
+namespace a{
+int kGlobalInt = 1;
+const char *const kGlobalStr = "Hello";

[PATCH] D30210: [include-fixer] Add usage count to find-all-symbols.

2017-02-23 Thread Haojian Wu via Phabricator via cfe-commits
hokein accepted this revision.
hokein added a comment.
This revision is now accepted and ready to land.

Thanks! Looks good from my side.

I'd wait to see whether @bkramer has more comments before commit it.




Comment at: include-fixer/find-all-symbols/SymbolInfo.h:50
+  // used. These are used to rank results.
+  struct Signals {
+Signals() {}

hokein wrote:
> sammccall wrote:
> > hokein wrote:
> > > I think we can make a standalone class instead of making it a nested 
> > > class of `SymbolInfo` because I don't see strong relationship between 
> > > them. Maybe name it `FindingSignals` or `FindingInfo`.
> > The relationship between them is a strong scoping one: signals only make 
> > sense in the context of a particular SymbolInfo.
> > 
> > If it was a parallel top-level class, it needs a name that communicates 
> > this relationship, most likely SymbolSignals. I don't think that's 
> > significantly better than SymbolInfo::Signals.
> > 
> > (If I had my druthers, these would probably be Symbol and Symbol::Signals - 
> > the "info" is the main reason that SymbolInfo::Signals is noisy. But not 
> > worth the churn I think)
> > 
> You convinced me.  Please keep the comment of `Signals` updated.
> 
> > If I had my druthers, these would probably be Symbol and Symbol::Signals - 
> > the "info" is the main reason that SymbolInfo::Signals is noisy. But not 
> > worth the churn I think)
> 
> In the initial design, `SymbolInfo` merely represents a cpp symbol. But as 
> more features developed, `SymbolInfo` might be not a good name at the moment. 
> `Symbol` seems not a better name as LLVM already has many classes named 
> `Symbol`. We can leave it here.
> 
> 
>  keep the comment of Signals updated.

You are missing this.


https://reviews.llvm.org/D30210



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D30210: [include-fixer] Add usage count to find-all-symbols.

2017-02-23 Thread Haojian Wu via Phabricator via cfe-commits
hokein added inline comments.



Comment at: include-fixer/InMemorySymbolIndex.h:27
 
-  std::vector
+  std::vector
   search(llvm::StringRef Identifier) override;

sammccall wrote:
> hokein wrote:
> > There are many places using 
> > `std::vector`. Maybe we can use 
> > a type alias for it, so that we can type less.  
> I guess? It's the namespaces that are the problem (vector 
> is fine) and most of the namespace noise wouldn't go away here.
> 
> is `clang::find_all_symbols::SymbolsSignalsList` better enough to obscure 
> what the actual type is? It's 45 chars vs 54.
> 
> IMO it's not worth it here, though 
> `clang::find_all_symbols::SymbolInfo::SignalMap` vs 
> `std::map clang::find_all_symbols::SymbolInfo::Signals>` is.
If we put the type alias under `clang::include_fixer` namespace, it will 
shorten the name more. Agree it is not worth the effect as the full name only 
happens in headers. 

We could save a few characters by getting rid of `clang` because we are always 
in `clang` namespace. So `std::vector` 
should work, this looks slightly better. :)



Comment at: include-fixer/find-all-symbols/FindAllMacros.cpp:38
+  if (auto Symbol = CreateMacroSymbol(MacroNameTok, MD->getMacroInfo()))
+FileSymbols[*Symbol].Seen++;
+}

code style: use prefix `++`. The same below.



Comment at: include-fixer/find-all-symbols/FindAllMacros.h:39
+
+  void Ifdef(SourceLocation Loc, const Token ,
+ const MacroDefinition ) override;

sammccall wrote:
> hokein wrote:
> > We are missing tests for these macro usages.
> These are covered by FindAllSymbolsTests, which (despite the name) tests the 
> whole FindAllSymbolsAction.
> 
> Specifically, MacroTest and MacroTestWithIWYU cover these.
Acked. You combined them in current tests (I originally thought there should be 
some separate tests for these).



Comment at: include-fixer/find-all-symbols/SymbolInfo.cpp:79
const std::vector ,
-   unsigned NumOccurrences)
+   unsigned NumOccurrences, unsigned NumUses)
 : Name(Name), Type(Type), FilePath(FilePath), Contexts(Contexts),

You forgot to update this?



Comment at: include-fixer/find-all-symbols/SymbolInfo.h:50
+  // used. These are used to rank results.
+  struct Signals {
+Signals() {}

sammccall wrote:
> hokein wrote:
> > I think we can make a standalone class instead of making it a nested class 
> > of `SymbolInfo` because I don't see strong relationship between them. Maybe 
> > name it `FindingSignals` or `FindingInfo`.
> The relationship between them is a strong scoping one: signals only make 
> sense in the context of a particular SymbolInfo.
> 
> If it was a parallel top-level class, it needs a name that communicates this 
> relationship, most likely SymbolSignals. I don't think that's significantly 
> better than SymbolInfo::Signals.
> 
> (If I had my druthers, these would probably be Symbol and Symbol::Signals - 
> the "info" is the main reason that SymbolInfo::Signals is noisy. But not 
> worth the churn I think)
> 
You convinced me.  Please keep the comment of `Signals` updated.

> If I had my druthers, these would probably be Symbol and Symbol::Signals - 
> the "info" is the main reason that SymbolInfo::Signals is noisy. But not 
> worth the churn I think)

In the initial design, `SymbolInfo` merely represents a cpp symbol. But as more 
features developed, `SymbolInfo` might be not a good name at the moment. 
`Symbol` seems not a better name as LLVM already has many classes named 
`Symbol`. We can leave it here.





Comment at: include-fixer/find-all-symbols/SymbolInfo.h:101
 private:
-  friend struct llvm::yaml::MappingTraits;
+  friend struct llvm::yaml::MappingTraits;
 

sammccall wrote:
> hokein wrote:
> > I'd put this statement inside `SymbolAndSignals`.
> That won't compile: it's the members of SymbolInfo that are private, not the 
> members of SymbolAndSignals.
Acked. Thanks for explanations. Sorry for misleading.



Comment at: include-fixer/find-all-symbols/SymbolInfo.h:129
 
-  /// \brief The number of times this symbol was found during an indexing
-  /// run. Populated by the reducer and used to rank results.
-  unsigned NumOccurrences;
+struct SymbolAndSignals {
+  SymbolInfo Symbol;

sammccall wrote:
> hokein wrote:
> > Not much better idea on names, how about `SymbolFinding`?
> > 
> > ```
> > struct SymbolFinding {
> >SymbolInfo Symbol;
> >FindingInfo Finding;
> > };
> > ```
> I don't think SymbolFinding is better:
>  - it can be misinterpreted as finding *for* a signal, not findings *and* a 
> signal. I think the And is important
>  - "finding" is vague while "signal" is more specific. I changed this from 
> finding -> signal already based 

[PATCH] D30210: [include-fixer] Add usage count to find-all-symbols.

2017-02-23 Thread Haojian Wu via Phabricator via cfe-commits
hokein added inline comments.



Comment at: include-fixer/InMemorySymbolIndex.h:27
 
-  std::vector
+  std::vector
   search(llvm::StringRef Identifier) override;

There are many places using 
`std::vector`. Maybe we can use a 
type alias for it, so that we can type less.  



Comment at: include-fixer/SymbolIndexManager.cpp:104
+for (const auto  : Symbols) {
+  const SymbolInfo Symbol = SymAndSig.Symbol;
   // Match the identifier name without qualifier.

I think you miss `&` here.



Comment at: include-fixer/find-all-symbols/FindAllMacros.cpp:37
  const MacroDirective *MD) {
-  SourceLocation Loc = SM->getExpansionLoc(MacroNameTok.getLocation());
-  std::string FilePath = getIncludePath(*SM, Loc, Collector);
-  if (FilePath.empty()) return;
+  if (auto Symbol = CreateMacroSymbol(MacroNameTok, MD->getMacroInfo())) {
+FileSymbols[*Symbol].Seen++;

Nit: No `{}` for single statement in `if`. The same below.



Comment at: include-fixer/find-all-symbols/FindAllMacros.h:39
+
+  void Ifdef(SourceLocation Loc, const Token ,
+ const MacroDefinition ) override;

We are missing tests for these macro usages.



Comment at: include-fixer/find-all-symbols/FindAllSymbols.h:52
+  std::string Filename;
+  // Findings for the current source file, flushed on EndSourceFileAction.
+  SymbolInfo::SignalMap FileSymbols;

s/`on EndSourceFileAction`/`onEndOfTranslationUnit`.



Comment at: include-fixer/find-all-symbols/SymbolInfo.h:50
+  // used. These are used to rank results.
+  struct Signals {
+Signals() {}

I think we can make a standalone class instead of making it a nested class of 
`SymbolInfo` because I don't see strong relationship between them. Maybe name 
it `FindingSignals` or `FindingInfo`.



Comment at: include-fixer/find-all-symbols/SymbolInfo.h:72
  int LineNumber, const std::vector ,
- unsigned NumOccurrences = 0);
+ unsigned NumOccurrences = 0, unsigned NumUses = 0);
 

We don't need this method since we have `SymbolAndSignals`?



Comment at: include-fixer/find-all-symbols/SymbolInfo.h:101
 private:
-  friend struct llvm::yaml::MappingTraits;
+  friend struct llvm::yaml::MappingTraits;
 

I'd put this statement inside `SymbolAndSignals`.



Comment at: include-fixer/find-all-symbols/SymbolInfo.h:129
 
-  /// \brief The number of times this symbol was found during an indexing
-  /// run. Populated by the reducer and used to rank results.
-  unsigned NumOccurrences;
+struct SymbolAndSignals {
+  SymbolInfo Symbol;

Not much better idea on names, how about `SymbolFinding`?

```
struct SymbolFinding {
   SymbolInfo Symbol;
   FindingInfo Finding;
};
```


https://reviews.llvm.org/D30210



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D29928: [clang-tidy] Improve diagnostic message for misc-definitions-in-header.

2017-02-14 Thread Haojian Wu via Phabricator via cfe-commits
hokein created this revision.
Herald added a subscriber: JDevlieghere.

Users might get confused easily when they see the check's message on
full template function speciliations.

Add a note to the output message, which mentions these kind of function
specializations are treated as regular functions.


https://reviews.llvm.org/D29928

Files:
  clang-tidy/misc/DefinitionsInHeadersCheck.cpp
  test/clang-tidy/misc-definitions-in-headers.hpp


Index: test/clang-tidy/misc-definitions-in-headers.hpp
===
--- test/clang-tidy/misc-definitions-in-headers.hpp
+++ test/clang-tidy/misc-definitions-in-headers.hpp
@@ -29,6 +29,7 @@
 template <>
 int CA::f3() {
 // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: function 'f3' defined in a 
header file;
+// CHECK-MESSAGES: :[[@LINE-2]]:9: note: this is a full function template 
specilization
 // CHECK-FIXES: inline int CA::f3() {
   int a = 1;
   return a;
@@ -93,6 +94,7 @@
 template <>
 int f3() {
 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: function 'f3' defined in a 
header file;
+// CHECK-MESSAGES: :[[@LINE-2]]:5: note: this is a full function template 
specilization
 // CHECK-FIXES: inline int f3() {
   int a = 1;
   return a;
Index: clang-tidy/misc/DefinitionsInHeadersCheck.cpp
===
--- clang-tidy/misc/DefinitionsInHeadersCheck.cpp
+++ clang-tidy/misc/DefinitionsInHeadersCheck.cpp
@@ -127,6 +127,12 @@
  "function definitions in header files can lead to ODR violations")
 << FD << FixItHint::CreateInsertion(
  FD->getReturnTypeSourceRange().getBegin(), "inline ");
+// Output notes for full function template specializations.
+if (FD->getTemplateSpecializationKind() != TSK_Undeclared)
+  diag(FD->getLocation(), "this is a full function template specilization "
+  "which behaves as a regular function, so the ODR 
"
+  "still applies",
+   DiagnosticIDs::Note);
   } else if (const auto *VD = dyn_cast(ND)) {
 // Static data members of a class template are allowed.
 if (VD->getDeclContext()->isDependentContext() && VD->isStaticDataMember())


Index: test/clang-tidy/misc-definitions-in-headers.hpp
===
--- test/clang-tidy/misc-definitions-in-headers.hpp
+++ test/clang-tidy/misc-definitions-in-headers.hpp
@@ -29,6 +29,7 @@
 template <>
 int CA::f3() {
 // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: function 'f3' defined in a header file;
+// CHECK-MESSAGES: :[[@LINE-2]]:9: note: this is a full function template specilization
 // CHECK-FIXES: inline int CA::f3() {
   int a = 1;
   return a;
@@ -93,6 +94,7 @@
 template <>
 int f3() {
 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: function 'f3' defined in a header file;
+// CHECK-MESSAGES: :[[@LINE-2]]:5: note: this is a full function template specilization
 // CHECK-FIXES: inline int f3() {
   int a = 1;
   return a;
Index: clang-tidy/misc/DefinitionsInHeadersCheck.cpp
===
--- clang-tidy/misc/DefinitionsInHeadersCheck.cpp
+++ clang-tidy/misc/DefinitionsInHeadersCheck.cpp
@@ -127,6 +127,12 @@
  "function definitions in header files can lead to ODR violations")
 << FD << FixItHint::CreateInsertion(
  FD->getReturnTypeSourceRange().getBegin(), "inline ");
+// Output notes for full function template specializations.
+if (FD->getTemplateSpecializationKind() != TSK_Undeclared)
+  diag(FD->getLocation(), "this is a full function template specilization "
+  "which behaves as a regular function, so the ODR "
+  "still applies",
+   DiagnosticIDs::Note);
   } else if (const auto *VD = dyn_cast(ND)) {
 // Static data members of a class template are allowed.
 if (VD->getDeclContext()->isDependentContext() && VD->isStaticDataMember())
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D29928: [clang-tidy] Improve diagnostic message for misc-definitions-in-header.

2017-02-14 Thread Haojian Wu via Phabricator via cfe-commits
hokein marked an inline comment as done.
hokein added inline comments.



Comment at: clang-tidy/misc/DefinitionsInHeadersCheck.cpp:131-135
+if (FD->getTemplateSpecializationKind() != TSK_Undeclared)
+  diag(FD->getLocation(), "this is a full function template specilization "
+  "which behaves as a regular function, so the ODR 
"
+  "still applies",
+   DiagnosticIDs::Note);

alexfh wrote:
> Notes are useful for pointing at related but different locations (e.g. point 
> to the declaration of an entity when the diagnostic is issued at a reference 
> to the entity).
> 
> Here I would suggest just issuing a different message (e.g. `diag(..., 
> "%select{function|full function template specialization}0 %1 defined in a 
> header file ") << (FD->getTemplateSpecializationKind() != TSK_Undeclared) 
> << FD << ...;`) or if it seems more helpful, add a note pointing to the 
> template being specialized.
SG. Didn't know `%select` before, thanks for pointing it out.


https://reviews.llvm.org/D29928



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D29928: [clang-tidy] Improve diagnostic message for misc-definitions-in-header.

2017-02-14 Thread Haojian Wu via Phabricator via cfe-commits
hokein updated this revision to Diff 88336.
hokein added a comment.

Address review comment.


https://reviews.llvm.org/D29928

Files:
  clang-tidy/misc/DefinitionsInHeadersCheck.cpp
  test/clang-tidy/misc-definitions-in-headers.hpp


Index: test/clang-tidy/misc-definitions-in-headers.hpp
===
--- test/clang-tidy/misc-definitions-in-headers.hpp
+++ test/clang-tidy/misc-definitions-in-headers.hpp
@@ -28,7 +28,7 @@
 
 template <>
 int CA::f3() {
-// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: function 'f3' defined in a 
header file;
+// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: full function template 
specialization 'f3' defined in a header file;
 // CHECK-FIXES: inline int CA::f3() {
   int a = 1;
   return a;
@@ -92,7 +92,7 @@
 
 template <>
 int f3() {
-// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: function 'f3' defined in a 
header file;
+// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: full function template 
specialization 'f3' defined in a header file;
 // CHECK-FIXES: inline int f3() {
   int a = 1;
   return a;
Index: clang-tidy/misc/DefinitionsInHeadersCheck.cpp
===
--- clang-tidy/misc/DefinitionsInHeadersCheck.cpp
+++ clang-tidy/misc/DefinitionsInHeadersCheck.cpp
@@ -122,10 +122,12 @@
   }
 }
 
+bool is_full_spec = FD->getTemplateSpecializationKind() != TSK_Undeclared;
 diag(FD->getLocation(),
- "function %0 defined in a header file; "
- "function definitions in header files can lead to ODR violations")
-<< FD << FixItHint::CreateInsertion(
+ "%select{function|full function template specialization}0 %1 defined "
+ "in a header file; function definitions in header files can lead to "
+ "ODR violations")
+<< is_full_spec << FD << FixItHint::CreateInsertion(
  FD->getReturnTypeSourceRange().getBegin(), "inline ");
   } else if (const auto *VD = dyn_cast(ND)) {
 // Static data members of a class template are allowed.


Index: test/clang-tidy/misc-definitions-in-headers.hpp
===
--- test/clang-tidy/misc-definitions-in-headers.hpp
+++ test/clang-tidy/misc-definitions-in-headers.hpp
@@ -28,7 +28,7 @@
 
 template <>
 int CA::f3() {
-// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: function 'f3' defined in a header file;
+// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: full function template specialization 'f3' defined in a header file;
 // CHECK-FIXES: inline int CA::f3() {
   int a = 1;
   return a;
@@ -92,7 +92,7 @@
 
 template <>
 int f3() {
-// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: function 'f3' defined in a header file;
+// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: full function template specialization 'f3' defined in a header file;
 // CHECK-FIXES: inline int f3() {
   int a = 1;
   return a;
Index: clang-tidy/misc/DefinitionsInHeadersCheck.cpp
===
--- clang-tidy/misc/DefinitionsInHeadersCheck.cpp
+++ clang-tidy/misc/DefinitionsInHeadersCheck.cpp
@@ -122,10 +122,12 @@
   }
 }
 
+bool is_full_spec = FD->getTemplateSpecializationKind() != TSK_Undeclared;
 diag(FD->getLocation(),
- "function %0 defined in a header file; "
- "function definitions in header files can lead to ODR violations")
-<< FD << FixItHint::CreateInsertion(
+ "%select{function|full function template specialization}0 %1 defined "
+ "in a header file; function definitions in header files can lead to "
+ "ODR violations")
+<< is_full_spec << FD << FixItHint::CreateInsertion(
  FD->getReturnTypeSourceRange().getBegin(), "inline ");
   } else if (const auto *VD = dyn_cast(ND)) {
 // Static data members of a class template are allowed.
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D29928: [clang-tidy] Improve diagnostic message for misc-definitions-in-header.

2017-02-14 Thread Haojian Wu via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
hokein marked an inline comment as done.
Closed by commit rL295048: [clang-tidy] Improve diagnostic message for 
misc-definitions-in-header. (authored by hokein).

Changed prior to commit:
  https://reviews.llvm.org/D29928?vs=88336=88350#toc

Repository:
  rL LLVM

https://reviews.llvm.org/D29928

Files:
  clang-tools-extra/trunk/clang-tidy/misc/DefinitionsInHeadersCheck.cpp
  clang-tools-extra/trunk/test/clang-tidy/misc-definitions-in-headers.hpp


Index: clang-tools-extra/trunk/test/clang-tidy/misc-definitions-in-headers.hpp
===
--- clang-tools-extra/trunk/test/clang-tidy/misc-definitions-in-headers.hpp
+++ clang-tools-extra/trunk/test/clang-tidy/misc-definitions-in-headers.hpp
@@ -28,7 +28,7 @@
 
 template <>
 int CA::f3() {
-// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: function 'f3' defined in a 
header file;
+// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: full function template 
specialization 'f3' defined in a header file;
 // CHECK-FIXES: inline int CA::f3() {
   int a = 1;
   return a;
@@ -92,7 +92,7 @@
 
 template <>
 int f3() {
-// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: function 'f3' defined in a 
header file;
+// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: full function template 
specialization 'f3' defined in a header file;
 // CHECK-FIXES: inline int f3() {
   int a = 1;
   return a;
Index: clang-tools-extra/trunk/clang-tidy/misc/DefinitionsInHeadersCheck.cpp
===
--- clang-tools-extra/trunk/clang-tidy/misc/DefinitionsInHeadersCheck.cpp
+++ clang-tools-extra/trunk/clang-tidy/misc/DefinitionsInHeadersCheck.cpp
@@ -122,10 +122,12 @@
   }
 }
 
+bool is_full_spec = FD->getTemplateSpecializationKind() != TSK_Undeclared;
 diag(FD->getLocation(),
- "function %0 defined in a header file; "
- "function definitions in header files can lead to ODR violations")
-<< FD << FixItHint::CreateInsertion(
+ "%select{function|full function template specialization}0 %1 defined "
+ "in a header file; function definitions in header files can lead to "
+ "ODR violations")
+<< is_full_spec << FD << FixItHint::CreateInsertion(
  FD->getReturnTypeSourceRange().getBegin(), "inline ");
   } else if (const auto *VD = dyn_cast(ND)) {
 // Static data members of a class template are allowed.


Index: clang-tools-extra/trunk/test/clang-tidy/misc-definitions-in-headers.hpp
===
--- clang-tools-extra/trunk/test/clang-tidy/misc-definitions-in-headers.hpp
+++ clang-tools-extra/trunk/test/clang-tidy/misc-definitions-in-headers.hpp
@@ -28,7 +28,7 @@
 
 template <>
 int CA::f3() {
-// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: function 'f3' defined in a header file;
+// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: full function template specialization 'f3' defined in a header file;
 // CHECK-FIXES: inline int CA::f3() {
   int a = 1;
   return a;
@@ -92,7 +92,7 @@
 
 template <>
 int f3() {
-// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: function 'f3' defined in a header file;
+// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: full function template specialization 'f3' defined in a header file;
 // CHECK-FIXES: inline int f3() {
   int a = 1;
   return a;
Index: clang-tools-extra/trunk/clang-tidy/misc/DefinitionsInHeadersCheck.cpp
===
--- clang-tools-extra/trunk/clang-tidy/misc/DefinitionsInHeadersCheck.cpp
+++ clang-tools-extra/trunk/clang-tidy/misc/DefinitionsInHeadersCheck.cpp
@@ -122,10 +122,12 @@
   }
 }
 
+bool is_full_spec = FD->getTemplateSpecializationKind() != TSK_Undeclared;
 diag(FD->getLocation(),
- "function %0 defined in a header file; "
- "function definitions in header files can lead to ODR violations")
-<< FD << FixItHint::CreateInsertion(
+ "%select{function|full function template specialization}0 %1 defined "
+ "in a header file; function definitions in header files can lead to "
+ "ODR violations")
+<< is_full_spec << FD << FixItHint::CreateInsertion(
  FD->getReturnTypeSourceRange().getBegin(), "inline ");
   } else if (const auto *VD = dyn_cast(ND)) {
 // Static data members of a class template are allowed.
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D29957: [clang-tidy] Ignore instantiated functions and static data members of classes in misc-definitions-in-headers.

2017-02-14 Thread Haojian Wu via Phabricator via cfe-commits
hokein created this revision.
Herald added a subscriber: JDevlieghere.

https://reviews.llvm.org/D29957

Files:
  clang-tidy/misc/DefinitionsInHeadersCheck.cpp
  test/clang-tidy/misc-definitions-in-headers.hpp


Index: test/clang-tidy/misc-definitions-in-headers.hpp
===
--- test/clang-tidy/misc-definitions-in-headers.hpp
+++ test/clang-tidy/misc-definitions-in-headers.hpp
@@ -71,6 +71,12 @@
 template 
 int CB::a = 2; // OK: static data member definition of a class template.
 
+template class CB; // OK: explicitly instantiated static data member of a 
class template.
+inline int callCB() {
+  CB cb; // OK: implicitly instantiated static data member of a class 
template.
+  return cb.a;
+}
+
 template 
 T tf() { // OK: template function definition.
   T a;
@@ -107,6 +113,12 @@
 
 int f8() = delete; // OK: the function being marked delete is not callable.
 
+template 
+int f9(T t) { return 1; }
+
+inline void callF9() { f9(1); } // OK: implicitly instantiated function.
+template int f9(double); // OK: explicitly instantiated function.
+
 int a = 1;
 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: variable 'a' defined in a header 
file; variable definitions in header files can lead to ODR violations 
[misc-definitions-in-headers]
 CA a1;
Index: clang-tidy/misc/DefinitionsInHeadersCheck.cpp
===
--- clang-tidy/misc/DefinitionsInHeadersCheck.cpp
+++ clang-tidy/misc/DefinitionsInHeadersCheck.cpp
@@ -104,8 +104,8 @@
 // Function templates are allowed.
 if (FD->getTemplatedKind() == FunctionDecl::TK_FunctionTemplate)
   return;
-// Function template full specialization is prohibited in header file.
-if (FD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation)
+// Ignore instantiated functions.
+if (FD->isTemplateInstantiation())
   return;
 // Member function of a class template and member function of a nested 
class
 // in a class template are allowed.
@@ -131,7 +131,8 @@
 // Static data members of a class template are allowed.
 if (VD->getDeclContext()->isDependentContext() && VD->isStaticDataMember())
   return;
-if (VD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation)
+// Ignore instantiated static data members of classes.
+if (isTemplateInstantiation(VD->getTemplateSpecializationKind()))
   return;
 // Ignore variable definition within function scope.
 if (VD->hasLocalStorage() || VD->isStaticLocal())


Index: test/clang-tidy/misc-definitions-in-headers.hpp
===
--- test/clang-tidy/misc-definitions-in-headers.hpp
+++ test/clang-tidy/misc-definitions-in-headers.hpp
@@ -71,6 +71,12 @@
 template 
 int CB::a = 2; // OK: static data member definition of a class template.
 
+template class CB; // OK: explicitly instantiated static data member of a class template.
+inline int callCB() {
+  CB cb; // OK: implicitly instantiated static data member of a class template.
+  return cb.a;
+}
+
 template 
 T tf() { // OK: template function definition.
   T a;
@@ -107,6 +113,12 @@
 
 int f8() = delete; // OK: the function being marked delete is not callable.
 
+template 
+int f9(T t) { return 1; }
+
+inline void callF9() { f9(1); } // OK: implicitly instantiated function.
+template int f9(double); // OK: explicitly instantiated function.
+
 int a = 1;
 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: variable 'a' defined in a header file; variable definitions in header files can lead to ODR violations [misc-definitions-in-headers]
 CA a1;
Index: clang-tidy/misc/DefinitionsInHeadersCheck.cpp
===
--- clang-tidy/misc/DefinitionsInHeadersCheck.cpp
+++ clang-tidy/misc/DefinitionsInHeadersCheck.cpp
@@ -104,8 +104,8 @@
 // Function templates are allowed.
 if (FD->getTemplatedKind() == FunctionDecl::TK_FunctionTemplate)
   return;
-// Function template full specialization is prohibited in header file.
-if (FD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation)
+// Ignore instantiated functions.
+if (FD->isTemplateInstantiation())
   return;
 // Member function of a class template and member function of a nested class
 // in a class template are allowed.
@@ -131,7 +131,8 @@
 // Static data members of a class template are allowed.
 if (VD->getDeclContext()->isDependentContext() && VD->isStaticDataMember())
   return;
-if (VD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation)
+// Ignore instantiated static data members of classes.
+if (isTemplateInstantiation(VD->getTemplateSpecializationKind()))
   return;
 // Ignore variable definition within function scope.
 if (VD->hasLocalStorage() || VD->isStaticLocal())
___
cfe-commits mailing list

[PATCH] D29893: [change-namespace] add an option to dump changed files in YAML.

2017-02-13 Thread Haojian Wu via Phabricator via cfe-commits
hokein added inline comments.



Comment at: change-namespace/tool/ClangChangeNamespace.cpp:68
+cl::opt
+DumpYAML("dump_yaml",
+ cl::desc("Dump new file content in YAML, if specified."),

`dump_result` maybe a clearer name, which also is consistent with clang-move's.



Comment at: change-namespace/tool/ClangChangeNamespace.cpp:137
+
+  for (const auto  : ChangedFiles) {
 const auto *Entry = FileMgr.getFile(File);

Is this duplicated as we already have "dump_results" option now?


https://reviews.llvm.org/D29893



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D29893: [change-namespace] add an option to dump changed files in YAML.

2017-02-13 Thread Haojian Wu via Phabricator via cfe-commits
hokein accepted this revision.
hokein added inline comments.
This revision is now accepted and ready to land.



Comment at: change-namespace/tool/ClangChangeNamespace.cpp:68
+cl::opt
+DumpYAML("dump_yaml",
+ cl::desc("Dump new file content in YAML, if specified."),

hokein wrote:
> `dump_result` maybe a clearer name, which also is consistent with 
> clang-move's.
Nit: Also change the variable name to `DumpResult`.



Comment at: change-namespace/tool/ClangChangeNamespace.cpp:137
+
+  for (const auto  : ChangedFiles) {
 const auto *Entry = FileMgr.getFile(File);

ioeric wrote:
> hokein wrote:
> > Is this duplicated as we already have "dump_results" option now?
> I'd like this to be default since this produces readable results.
OK, it is up to you.


https://reviews.llvm.org/D29893



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D29957: [clang-tidy] Ignore instantiated functions and static data members of classes in misc-definitions-in-headers.

2017-02-15 Thread Haojian Wu via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL295178: [clang-tidy] Ignore instantiated functions and 
static data members of classes… (authored by hokein).

Changed prior to commit:
  https://reviews.llvm.org/D29957?vs=88413=88520#toc

Repository:
  rL LLVM

https://reviews.llvm.org/D29957

Files:
  clang-tools-extra/trunk/clang-tidy/misc/DefinitionsInHeadersCheck.cpp
  clang-tools-extra/trunk/test/clang-tidy/misc-definitions-in-headers.hpp


Index: clang-tools-extra/trunk/clang-tidy/misc/DefinitionsInHeadersCheck.cpp
===
--- clang-tools-extra/trunk/clang-tidy/misc/DefinitionsInHeadersCheck.cpp
+++ clang-tools-extra/trunk/clang-tidy/misc/DefinitionsInHeadersCheck.cpp
@@ -104,8 +104,8 @@
 // Function templates are allowed.
 if (FD->getTemplatedKind() == FunctionDecl::TK_FunctionTemplate)
   return;
-// Function template full specialization is prohibited in header file.
-if (FD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation)
+// Ignore instantiated functions.
+if (FD->isTemplateInstantiation())
   return;
 // Member function of a class template and member function of a nested 
class
 // in a class template are allowed.
@@ -133,7 +133,8 @@
 // Static data members of a class template are allowed.
 if (VD->getDeclContext()->isDependentContext() && VD->isStaticDataMember())
   return;
-if (VD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation)
+// Ignore instantiated static data members of classes.
+if (isTemplateInstantiation(VD->getTemplateSpecializationKind()))
   return;
 // Ignore variable definition within function scope.
 if (VD->hasLocalStorage() || VD->isStaticLocal())
Index: clang-tools-extra/trunk/test/clang-tidy/misc-definitions-in-headers.hpp
===
--- clang-tools-extra/trunk/test/clang-tidy/misc-definitions-in-headers.hpp
+++ clang-tools-extra/trunk/test/clang-tidy/misc-definitions-in-headers.hpp
@@ -71,6 +71,12 @@
 template 
 int CB::a = 2; // OK: static data member definition of a class template.
 
+template class CB; // OK: explicitly instantiated static data member of a 
class template.
+inline int callCB() {
+  CB cb; // OK: implicitly instantiated static data member of a class 
template.
+  return cb.a;
+}
+
 template 
 T tf() { // OK: template function definition.
   T a;
@@ -107,6 +113,12 @@
 
 int f8() = delete; // OK: the function being marked delete is not callable.
 
+template 
+int f9(T t) { return 1; }
+
+inline void callF9() { f9(1); } // OK: implicitly instantiated function.
+template int f9(double); // OK: explicitly instantiated function.
+
 int a = 1;
 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: variable 'a' defined in a header 
file; variable definitions in header files can lead to ODR violations 
[misc-definitions-in-headers]
 CA a1;


Index: clang-tools-extra/trunk/clang-tidy/misc/DefinitionsInHeadersCheck.cpp
===
--- clang-tools-extra/trunk/clang-tidy/misc/DefinitionsInHeadersCheck.cpp
+++ clang-tools-extra/trunk/clang-tidy/misc/DefinitionsInHeadersCheck.cpp
@@ -104,8 +104,8 @@
 // Function templates are allowed.
 if (FD->getTemplatedKind() == FunctionDecl::TK_FunctionTemplate)
   return;
-// Function template full specialization is prohibited in header file.
-if (FD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation)
+// Ignore instantiated functions.
+if (FD->isTemplateInstantiation())
   return;
 // Member function of a class template and member function of a nested class
 // in a class template are allowed.
@@ -133,7 +133,8 @@
 // Static data members of a class template are allowed.
 if (VD->getDeclContext()->isDependentContext() && VD->isStaticDataMember())
   return;
-if (VD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation)
+// Ignore instantiated static data members of classes.
+if (isTemplateInstantiation(VD->getTemplateSpecializationKind()))
   return;
 // Ignore variable definition within function scope.
 if (VD->hasLocalStorage() || VD->isStaticLocal())
Index: clang-tools-extra/trunk/test/clang-tidy/misc-definitions-in-headers.hpp
===
--- clang-tools-extra/trunk/test/clang-tidy/misc-definitions-in-headers.hpp
+++ clang-tools-extra/trunk/test/clang-tidy/misc-definitions-in-headers.hpp
@@ -71,6 +71,12 @@
 template 
 int CB::a = 2; // OK: static data member definition of a class template.
 
+template class CB; // OK: explicitly instantiated static data member of a class template.
+inline int callCB() {
+  CB cb; // OK: implicitly instantiated static data member of a class template.
+  return cb.a;
+}
+
 template 
 T tf() { // OK: template function definition.
   T a;
@@ 

[PATCH] D28895: [clang-move] Also move using decls which are defined in header file.

2017-01-19 Thread Haojian Wu via Phabricator via cfe-commits
hokein created this revision.

https://reviews.llvm.org/D28895

Files:
  clang-move/ClangMove.cpp
  test/clang-move/Inputs/multiple_class_test.h
  test/clang-move/move-multiple-classes.cpp

Index: test/clang-move/move-multiple-classes.cpp
===
--- test/clang-move/move-multiple-classes.cpp
+++ test/clang-move/move-multiple-classes.cpp
@@ -11,94 +11,128 @@
 // CHECK-EMPTY: [{{[[:space:]]*}}]
 //
 // CHECK-OLD-TEST-H: namespace c {
-// CHECK-OLD-TEST-H: class NoMove {
-// CHECK-OLD-TEST-H: public:
-// CHECK-OLD-TEST-H:   int f();
-// CHECK-OLD-TEST-H: };
-// CHECK-OLD-TEST-H: } // namespace c
+// CHECK-OLD-TEST-H-NEXT: using a::Move1;
+// CHECK-OLD-TEST-H-NEXT: using namespace a;
+// CHECK-OLD-TEST-H-SAME: {{[[:space:]]}}
+// CHECK-OLD-TEST-H-NEXT: class NoMove {
+// CHECK-OLD-TEST-H-NEXT: public:
+// CHECK-OLD-TEST-H-NEXT:   int f();
+// CHECK-OLD-TEST-H-NEXT: };
+// CHECK-OLD-TEST-H-NEXT: } // namespace c
 
 // CHECK-OLD-TEST-CPP: #include "{{.*}}multiple_class_test.h"
-// CHECK-OLD-TEST-CPP: using a::Move1;
-// CHECK-OLD-TEST-CPP: using namespace a;
-// CHECK-OLD-TEST-CPP: using A = a::Move1;
-// CHECK-OLD-TEST-CPP: static int g = 0;
-// CHECK-OLD-TEST-CPP: namespace {
-// CHECK-OLD-TEST-CPP: using a::Move1;
-// CHECK-OLD-TEST-CPP: using namespace a;
-// CHECK-OLD-TEST-CPP: } // namespace
-// CHECK-OLD-TEST-CPP: namespace b {
-// CHECK-OLD-TEST-CPP: using a::Move1;
-// CHECK-OLD-TEST-CPP: using namespace a;
-// CHECK-OLD-TEST-CPP: using T = a::Move1;
-// CHECK-OLD-TEST-CPP: } // namespace b
-// CHECK-OLD-TEST-CPP: namespace c {
-// CHECK-OLD-TEST-CPP: int NoMove::f() {
-// CHECK-OLD-TEST-CPP:   static int F = 0;
-// CHECK-OLD-TEST-CPP:   return g;
-// CHECK-OLD-TEST-CPP: }
-// CHECK-OLD-TEST-CPP: } // namespace c
+// CHECK-OLD-TEST-CPP-SAME: {{[[:space:]]}}
+// CHECK-OLD-TEST-CPP-NEXT: using a::Move1;
+// CHECK-OLD-TEST-CPP-NEXT: using namespace a;
+// CHECK-OLD-TEST-CPP-NEXT: using A = a::Move1;
+// CHECK-OLD-TEST-CPP-NEXT: static int g = 0;
+// CHECK-OLD-TEST-CPP-SAME: {{[[:space:]]}}
+// CHECK-OLD-TEST-CPP-NEXT: namespace {
+// CHECK-OLD-TEST-CPP-NEXT: using a::Move1;
+// CHECK-OLD-TEST-CPP-NEXT: using namespace a;
+// CHECK-OLD-TEST-CPP-NEXT: } // namespace
+// CHECK-OLD-TEST-CPP-SAME: {{[[:space:]]}}
+// CHECK-OLD-TEST-CPP-NEXT: namespace b {
+// CHECK-OLD-TEST-CPP-NEXT: using a::Move1;
+// CHECK-OLD-TEST-CPP-NEXT: using namespace a;
+// CHECK-OLD-TEST-CPP-NEXT: using T = a::Move1;
+// CHECK-OLD-TEST-CPP-NEXT: } // namespace b
+// CHECK-OLD-TEST-CPP-SAME: {{[[:space:]]}}
+// CHECK-OLD-TEST-CPP-NEXT: namespace c {
+// CHECK-OLD-TEST-CPP-SAME: {{[[:space:]]}}
+// CHECK-OLD-TEST-CPP-NEXT: int NoMove::f() {
+// CHECK-OLD-TEST-CPP-NEXT:   static int F = 0;
+// CHECK-OLD-TEST-CPP-NEXT:   return g;
+// CHECK-OLD-TEST-CPP-NEXT: }
+// CHECK-OLD-TEST-CPP-NEXT: } // namespace c
 
 // CHECK-NEW-TEST-H: #ifndef {{.*}}NEW_MULTIPLE_CLASS_TEST_H
-// CHECK-NEW-TEST-H: #define {{.*}}NEW_MULTIPLE_CLASS_TEST_H
-// CHECK-NEW-TEST-H: namespace a {
-// CHECK-NEW-TEST-H: class Move1 {
-// CHECK-NEW-TEST-H: public:
-// CHECK-NEW-TEST-H:   int f();
-// CHECK-NEW-TEST-H: };
-// CHECK-NEW-TEST-H: } // namespace a
-// CHECK-NEW-TEST-H: namespace b {
-// CHECK-NEW-TEST-H: class Move2 {
-// CHECK-NEW-TEST-H: public:
-// CHECK-NEW-TEST-H:   int f();
-// CHECK-NEW-TEST-H: };
-// CHECK-NEW-TEST-H: } // namespace b
-// CHECK-NEW-TEST-H: namespace c {
-// CHECK-NEW-TEST-H: class Move3 {
-// CHECK-NEW-TEST-H: public:
-// CHECK-NEW-TEST-H:   int f();
-// CHECK-NEW-TEST-H: };
-// CHECK-NEW-TEST-H: class Move4 {
-// CHECK-NEW-TEST-H: public:
-// CHECK-NEW-TEST-H:   int f();
-// CHECK-NEW-TEST-H: };
-// CHECK-NEW-TEST-H: class EnclosingMove5 {
-// CHECK-NEW-TEST-H: public:
-// CHECK-NEW-TEST-H:   class Nested {
-// CHECK-NEW-TEST-H: int f();
-// CHECK-NEW-TEST-H: static int b;
-// CHECK-NEW-TEST-H:   };
-// CHECK-NEW-TEST-H:   static int a;
-// CHECK-NEW-TEST-H: };
-// CHECK-NEW-TEST-H: } // namespace c
+// CHECK-NEW-TEST-H-NEXT: #define {{.*}}NEW_MULTIPLE_CLASS_TEST_H
+// CHECK-NEW-TEST-H-SAME: {{[[:space:]]}}
+// CHECK-NEW-TEST-H-NEXT: namespace a {
+// CHECK-NEW-TEST-H-NEXT: class Move1 {
+// CHECK-NEW-TEST-H-NEXT: public:
+// CHECK-NEW-TEST-H-NEXT:   int f();
+// CHECK-NEW-TEST-H-NEXT: };
+// CHECK-NEW-TEST-H-NEXT: } // namespace a
+// CHECK-NEW-TEST-H-SAME: {{[[:space:]]}}
+// CHECK-NEW-TEST-H-NEXT: namespace b {
+// CHECK-NEW-TEST-H-NEXT: class Move2 {
+// CHECK-NEW-TEST-H-NEXT: public:
+// CHECK-NEW-TEST-H-NEXT:   int f();
+// CHECK-NEW-TEST-H-NEXT: };
+// CHECK-NEW-TEST-H-NEXT: } // namespace b
+// CHECK-NEW-TEST-H-SAME: {{[[:space:]]}}
+// CHECK-NEW-TEST-H-NEXT: namespace c {
+// CHECK-NEW-TEST-H-NEXT: using a::Move1;
+// CHECK-NEW-TEST-H-SAME: {{[[:space:]]}}
+// CHECK-NEW-TEST-H-NEXT: using namespace a;
+// CHECK-NEW-TEST-H-SAME: {{[[:space:]]}}
+// CHECK-NEW-TEST-H-NEXT: class Move3 {
+// CHECK-NEW-TEST-H-NEXT: public:
+// CHECK-NEW-TEST-H-NEXT:   int f();

[PATCH] D28293: [clang-move] Dump enum and type alias declarations.

2017-01-16 Thread Haojian Wu via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL292098: [clang-move] Dump enum and type alias declarations. 
(authored by hokein).

Changed prior to commit:
  https://reviews.llvm.org/D28293?vs=83054=84525#toc

Repository:
  rL LLVM

https://reviews.llvm.org/D28293

Files:
  clang-tools-extra/trunk/clang-move/ClangMove.cpp
  clang-tools-extra/trunk/unittests/clang-move/ClangMoveTests.cpp


Index: clang-tools-extra/trunk/unittests/clang-move/ClangMoveTests.cpp
===
--- clang-tools-extra/trunk/unittests/clang-move/ClangMoveTests.cpp
+++ clang-tools-extra/trunk/unittests/clang-move/ClangMoveTests.cpp
@@ -535,6 +535,10 @@
 "namespace b {\n"
 "class Move1 { public : void f(); };\n"
 "void f() {}\n"
+"enum E1 { Green };\n"
+"enum class E2 { Red };\n"
+"typedef int Int2;\n"
+"using Int = int;\n"
 "} // namespace b\n"
 "} // namespace a\n";
   const char TestCode[] = "#include \"foo.h\"\n";
@@ -545,22 +549,16 @@
   Spec.NewHeader = "new_foo.h";
   Spec.NewCC = "new_foo.cc";
   DeclarationReporter Reporter;
-  std::vector ExpectedDeclarations = {
+  std::set ExpectedDeclarations = {
   {"A", "Class"}, {"B", "Class"},{"a::Move1", "Class"},
   {"a::f1", "Function"},  {"a::f2", "Function"}, {"a::b::Move1", "Class"},
-  {"a::b::f", "Function"}};
+  {"a::b::f", "Function"}, {"a::b::E1", "Enum"}, {"a::b::E2", "Enum"},
+  {"a::b::Int2", "TypeAlias"}, {"a::b::Int", "TypeAlias"} };
   runClangMoveOnCode(Spec, TestHeader, TestCode, );
-  const auto& Results = Reporter.getDeclarationList();
-  auto ActualDeclIter = Results.begin();
-  auto ExpectedDeclIter = ExpectedDeclarations.begin();
-  while (ActualDeclIter != Results.end() &&
- ExpectedDeclIter != ExpectedDeclarations.end()) {
-EXPECT_EQ(*ActualDeclIter, *ExpectedDeclIter);
-++ActualDeclIter;
-++ExpectedDeclIter;
-  }
-  ASSERT_TRUE(ActualDeclIter == Results.end());
-  ASSERT_TRUE(ExpectedDeclIter == ExpectedDeclarations.end());
+  std::set Results;
+  for (const auto& DelPair : Reporter.getDeclarationList())
+Results.insert(DelPair);
+  EXPECT_EQ(ExpectedDeclarations, Results);
 }
 
 } // namespace
Index: clang-tools-extra/trunk/clang-move/ClangMove.cpp
===
--- clang-tools-extra/trunk/clang-move/ClangMove.cpp
+++ clang-tools-extra/trunk/clang-move/ClangMove.cpp
@@ -841,6 +841,12 @@
   else if (Kind == Decl::Kind::ClassTemplate ||
Kind == Decl::Kind::CXXRecord)
 Reporter->reportDeclaration(QualifiedName, "Class");
+  else if (Kind == Decl::Kind::Enum)
+Reporter->reportDeclaration(QualifiedName, "Enum");
+  else if (Kind == Decl::Kind::Typedef ||
+   Kind == Decl::Kind::TypeAlias ||
+   Kind == Decl::Kind::TypeAliasTemplate)
+Reporter->reportDeclaration(QualifiedName, "TypeAlias");
 }
 return;
   }


Index: clang-tools-extra/trunk/unittests/clang-move/ClangMoveTests.cpp
===
--- clang-tools-extra/trunk/unittests/clang-move/ClangMoveTests.cpp
+++ clang-tools-extra/trunk/unittests/clang-move/ClangMoveTests.cpp
@@ -535,6 +535,10 @@
 "namespace b {\n"
 "class Move1 { public : void f(); };\n"
 "void f() {}\n"
+"enum E1 { Green };\n"
+"enum class E2 { Red };\n"
+"typedef int Int2;\n"
+"using Int = int;\n"
 "} // namespace b\n"
 "} // namespace a\n";
   const char TestCode[] = "#include \"foo.h\"\n";
@@ -545,22 +549,16 @@
   Spec.NewHeader = "new_foo.h";
   Spec.NewCC = "new_foo.cc";
   DeclarationReporter Reporter;
-  std::vector ExpectedDeclarations = {
+  std::set ExpectedDeclarations = {
   {"A", "Class"}, {"B", "Class"},{"a::Move1", "Class"},
   {"a::f1", "Function"},  {"a::f2", "Function"}, {"a::b::Move1", "Class"},
-  {"a::b::f", "Function"}};
+  {"a::b::f", "Function"}, {"a::b::E1", "Enum"}, {"a::b::E2", "Enum"},
+  {"a::b::Int2", "TypeAlias"}, {"a::b::Int", "TypeAlias"} };
   runClangMoveOnCode(Spec, TestHeader, TestCode, );
-  const auto& Results = Reporter.getDeclarationList();
-  auto ActualDeclIter = Results.begin();
-  auto ExpectedDeclIter = ExpectedDeclarations.begin();
-  while (ActualDeclIter != Results.end() &&
- ExpectedDeclIter != ExpectedDeclarations.end()) {
-EXPECT_EQ(*ActualDeclIter, *ExpectedDeclIter);
-++ActualDeclIter;
-

[PATCH] D28774: [clang-move] Ignore using decls which are defined in macros.

2017-01-16 Thread Haojian Wu via Phabricator via cfe-commits
hokein created this revision.
hokein added a reviewer: ioeric.
hokein added a subscriber: cfe-commits.

Also ignore helpers which are defined in macro. Currently clang-move doesn't
handle macro well enough, especiall for complex macros. This patch will ignore
declarations in macros to make the behavior of clang-move more correct.


https://reviews.llvm.org/D28774

Files:
  clang-move/ClangMove.cpp
  test/clang-move/Inputs/macro_helper_test.cpp
  test/clang-move/Inputs/macro_helper_test.h
  test/clang-move/no-move-macro-helpers.cpp


Index: test/clang-move/no-move-macro-helpers.cpp
===
--- /dev/null
+++ test/clang-move/no-move-macro-helpers.cpp
@@ -0,0 +1,19 @@
+// RUN: mkdir -p %T/no-move-macro-helper
+// RUN: cp %S/Inputs/macro_helper_test.h  
%T/no-move-macro-helper/macro_helper_test.h
+// RUN: cp %S/Inputs/macro_helper_test.cpp 
%T/no-move-macro-helper/macro_helper_test.cpp
+// RUN: cd %T/no-move-macro-helper
+//
+// 
-
+// Test no moving helpers in macro.
+// 
-
+// RUN: clang-move -names="A" -new_cc=%T/no-move-macro-helper/new_test.cpp 
-new_header=%T/no-move-macro-helper/new_test.h 
-old_cc=%T/no-move-macro-helper/macro_helper_test.cpp 
-old_header=%T/no-move-macro-helper/macro_helper_test.h 
%T/no-move-macro-helper/macro_helper_test.cpp -- -std=c++11
+// RUN: FileCheck -input-file=%T/no-move-macro-helper/new_test.h 
-check-prefix=CHECK-NEW-TEST-H %s
+// RUN: FileCheck -input-file=%T/no-move-macro-helper/macro_helper_test.h 
-check-prefix=CHECK-OLD-TEST-H %s
+// RUN: FileCheck -input-file=%T/no-move-macro-helper/new_test.cpp 
-check-prefix=CHECK-NEW-TEST-CPP %s
+
+
+// CHECK-NEW-TEST-H: class A {};
+
+// CHECK-OLD-TEST-H-NOT: class A {};
+
+// CHECK-NEW-TEST-CPP-NOT: DEFINE(test)
Index: test/clang-move/Inputs/macro_helper_test.h
===
--- /dev/null
+++ test/clang-move/Inputs/macro_helper_test.h
@@ -0,0 +1,2 @@
+class A {};
+void f1();
Index: test/clang-move/Inputs/macro_helper_test.cpp
===
--- /dev/null
+++ test/clang-move/Inputs/macro_helper_test.cpp
@@ -0,0 +1,13 @@
+#include "macro_helper_test.h"
+
+#define DEFINE(name) \
+  namespace ns { \
+  static const bool t1 = false; \
+  bool t2_##name = t1; \
+  bool t3_##name = t1; \
+  } \
+  using ns::t2_##name;
+
+DEFINE(test)
+
+void f1() {}
Index: clang-move/ClangMove.cpp
===
--- clang-move/ClangMove.cpp
+++ clang-move/ClangMove.cpp
@@ -31,6 +31,8 @@
 // FIXME: Move to ASTMatchers.
 AST_MATCHER(VarDecl, isStaticDataMember) { return Node.isStaticDataMember(); }
 
+AST_MATCHER(NamedDecl, notInMacro) { return !Node.getLocation().isMacroID(); }
+
 AST_MATCHER_P(Decl, hasOutermostEnclosingClass,
   ast_matchers::internal::Matcher, InnerMatcher) {
   const auto *Context = Node.getDeclContext();
@@ -525,12 +527,12 @@
   // Matching using decls/type alias decls which are in named/anonymous/global
   // namespace, these decls are always copied to new.h/cc. Those in classes,
   // functions are covered in other matchers.
-  Finder->addMatcher(
-  namedDecl(anyOf(usingDecl(IsOldCCTopLevelDecl),
-  usingDirectiveDecl(IsOldCCTopLevelDecl),
-  typeAliasDecl(IsOldCCTopLevelDecl)))
-  .bind("using_decl"),
-  this);
+  Finder->addMatcher(namedDecl(anyOf(usingDecl(IsOldCCTopLevelDecl),
+ usingDirectiveDecl(IsOldCCTopLevelDecl),
+ typeAliasDecl(IsOldCCTopLevelDecl)),
+   notInMacro())
+ .bind("using_decl"),
+ this);
 
   // Match static functions/variable definitions which are defined in named
   // namespaces.
@@ -556,9 +558,11 @@
   allOf(DefinitionInOldCC, anyOf(isStaticStorageClass(), InAnonymousNS));
   // Match helper classes separately with helper functions/variables since we
   // want to reuse these matchers in finding helpers usage below.
-  auto HelperFuncOrVar = namedDecl(anyOf(functionDecl(IsOldCCHelperDefinition),
- varDecl(IsOldCCHelperDefinition)));
-  auto HelperClasses = cxxRecordDecl(DefinitionInOldCC, InAnonymousNS);
+  auto HelperFuncOrVar =
+  namedDecl(notInMacro(), anyOf(functionDecl(IsOldCCHelperDefinition),
+varDecl(IsOldCCHelperDefinition)));
+  auto HelperClasses =
+  cxxRecordDecl(notInMacro(), DefinitionInOldCC, InAnonymousNS);
   // Save all helper declarations in old.cc.
   Finder->addMatcher(
   namedDecl(anyOf(HelperFuncOrVar, HelperClasses)).bind("helper_decls"),


Index: test/clang-move/no-move-macro-helpers.cpp

[PATCH] D28774: [clang-move] Ignore using decls which are defined in macros.

2017-01-17 Thread Haojian Wu via Phabricator via cfe-commits
hokein updated this revision to Diff 84639.
hokein marked 2 inline comments as done.
hokein added a comment.

Add more tests.


https://reviews.llvm.org/D28774

Files:
  clang-move/ClangMove.cpp
  test/clang-move/Inputs/macro_helper_test.cpp
  test/clang-move/Inputs/macro_helper_test.h
  test/clang-move/no-move-macro-helpers.cpp

Index: test/clang-move/no-move-macro-helpers.cpp
===
--- /dev/null
+++ test/clang-move/no-move-macro-helpers.cpp
@@ -0,0 +1,43 @@
+// RUN: mkdir -p %T/no-move-macro-helper
+// RUN: cp %S/Inputs/macro_helper_test.h  %T/no-move-macro-helper/macro_helper_test.h
+// RUN: cp %S/Inputs/macro_helper_test.cpp %T/no-move-macro-helper/macro_helper_test.cpp
+// RUN: cd %T/no-move-macro-helper
+//
+// -
+// Test no moving helpers in macro.
+// -
+// RUN: clang-move -names="A" -new_cc=%T/no-move-macro-helper/new_test.cpp -new_header=%T/no-move-macro-helper/new_test.h -old_cc=%T/no-move-macro-helper/macro_helper_test.cpp -old_header=%T/no-move-macro-helper/macro_helper_test.h %T/no-move-macro-helper/macro_helper_test.cpp -- -std=c++11
+// RUN: FileCheck -input-file=%T/no-move-macro-helper/new_test.h -check-prefix=CHECK-NEW-TEST-CASE1-H %s
+// RUN: FileCheck -input-file=%T/no-move-macro-helper/new_test.cpp -check-prefix=CHECK-NEW-TEST-CASE1-CPP %s
+// RUN: FileCheck -input-file=%T/no-move-macro-helper/macro_helper_test.h -check-prefix=CHECK-OLD-TEST-CASE1-H %s
+// RUN: FileCheck -input-file=%T/no-move-macro-helper/macro_helper_test.cpp -check-prefix=CHECK-OLD-TEST-CASE1-CPP %s
+
+// CHECK-NEW-TEST-CASE1-H: class A {};
+
+// CHECK-OLD-TEST-CASE1-H-NOT: class A {};
+
+// CHECK-OLD-TEST-CASE1-CPP: DEFINE(test)
+
+// CHECK-NEW-TEST-CASE1-CPP-NOT: DEFINE(test)
+
+
+// -
+// Test moving all.
+// -
+// RUN: cp %S/Inputs/macro_helper_test.h  %T/no-move-macro-helper/macro_helper_test.h
+// RUN: cp %S/Inputs/macro_helper_test.cpp %T/no-move-macro-helper/macro_helper_test.cpp
+// RUN: clang-move -names="A, f1" -new_cc=%T/no-move-macro-helper/new_test.cpp -new_header=%T/no-move-macro-helper/new_test.h -old_cc=%T/no-move-macro-helper/macro_helper_test.cpp -old_header=%T/no-move-macro-helper/macro_helper_test.h %T/no-move-macro-helper/macro_helper_test.cpp -- -std=c++11
+//
+// RUN: FileCheck -input-file=%T/no-move-macro-helper/new_test.h -check-prefix=CHECK-NEW-TEST-CASE2-H %s
+// RUN: FileCheck -input-file=%T/no-move-macro-helper/new_test.cpp -check-prefix=CHECK-NEW-TEST-CASE2-CPP %s
+// RUN: FileCheck -input-file=%T/no-move-macro-helper/macro_helper_test.h -allow-empty -check-prefix=CHECK-EMPTY %s
+// RUN: FileCheck -input-file=%T/no-move-macro-helper/macro_helper_test.cpp -allow-empty -check-prefix=CHECK-EMPTY %s
+
+// CHECK-NEW-TEST-CASE2-H: class A {};
+// CHECK-NEW-TEST-CASE2-H-NEXT:void f1();
+
+
+// CHECK-NEW-TEST-CASE2-CPP: DEFINE(test)
+// CHECK-NEW-TEST-CASE2-CPP: void f1() {}
+
+// CHECK-EMPTY: {{^}}{{$}}
Index: test/clang-move/Inputs/macro_helper_test.h
===
--- /dev/null
+++ test/clang-move/Inputs/macro_helper_test.h
@@ -0,0 +1,2 @@
+class A {};
+void f1();
Index: test/clang-move/Inputs/macro_helper_test.cpp
===
--- /dev/null
+++ test/clang-move/Inputs/macro_helper_test.cpp
@@ -0,0 +1,13 @@
+#include "macro_helper_test.h"
+
+#define DEFINE(name) \
+  namespace ns { \
+  static const bool t1 = false; \
+  bool t2_##name = t1; \
+  bool t3_##name = t1; \
+  } \
+  using ns::t2_##name;
+
+DEFINE(test)
+
+void f1() {}
Index: clang-move/ClangMove.cpp
===
--- clang-move/ClangMove.cpp
+++ clang-move/ClangMove.cpp
@@ -31,6 +31,8 @@
 // FIXME: Move to ASTMatchers.
 AST_MATCHER(VarDecl, isStaticDataMember) { return Node.isStaticDataMember(); }
 
+AST_MATCHER(NamedDecl, notInMacro) { return !Node.getLocation().isMacroID(); }
+
 AST_MATCHER_P(Decl, hasOutermostEnclosingClass,
   ast_matchers::internal::Matcher, InnerMatcher) {
   const auto *Context = Node.getDeclContext();
@@ -525,12 +527,12 @@
   // Matching using decls/type alias decls which are in named/anonymous/global
   // namespace, these decls are always copied to new.h/cc. Those in classes,
   // functions are covered in other matchers.
-  Finder->addMatcher(
-  namedDecl(anyOf(usingDecl(IsOldCCTopLevelDecl),
-  usingDirectiveDecl(IsOldCCTopLevelDecl),
-  typeAliasDecl(IsOldCCTopLevelDecl)))
-  .bind("using_decl"),
-  this);
+  Finder->addMatcher(namedDecl(anyOf(usingDecl(IsOldCCTopLevelDecl),
+ 

[PATCH] D28801: [clang-move] Handle helpers with forward declarations.

2017-01-17 Thread Haojian Wu via Phabricator via cfe-commits
hokein created this revision.

https://reviews.llvm.org/D28801

Files:
  clang-move/ClangMove.cpp
  clang-move/HelperDeclRefGraph.cpp
  test/clang-move/Inputs/helper_decls_test.cpp
  test/clang-move/Inputs/helper_decls_test.h
  test/clang-move/move-used-helper-decls.cpp

Index: test/clang-move/move-used-helper-decls.cpp
===
--- test/clang-move/move-used-helper-decls.cpp
+++ test/clang-move/move-used-helper-decls.cpp
@@ -259,12 +259,43 @@
 
 // CHECK-OLD-FUN2-H-NOT: inline void Fun2() {}
 
+// 
+// Test moving used helper function and its transively used functions.
+// 
+// RUN: cp %S/Inputs/helper_decls_test*  %T/used-helper-decls/
+// RUN: clang-move -names="b::Fun3" -new_cc=%T/used-helper-decls/new_helper_decls_test.cpp -new_header=%T/used-helper-decls/new_helper_decls_test.h -old_cc=%T/used-helper-decls/helper_decls_test.cpp -old_header=../used-helper-decls/helper_decls_test.h %T/used-helper-decls/helper_decls_test.cpp -- -std=c++11
+// RUN: FileCheck -input-file=%T/used-helper-decls/new_helper_decls_test.cpp -check-prefix=CHECK-NEW-FUN3-CPP %s
+// RUN: FileCheck -input-file=%T/used-helper-decls/helper_decls_test.cpp -check-prefix=CHECK-OLD-FUN3-CPP %s
+
+// CHECK-NEW-FUN3-CPP: #include "{{.*}}new_helper_decls_test.h"
+// CHECK-NEW-FUN3-CPP-SAME: {{[[:space:]]}}
+// CHECK-NEW-FUN3-CPP-NEXT: namespace b {
+// CHECK-NEW-FUN3-CPP-NEXT: namespace {
+// CHECK-NEW-FUN3-CPP-NEXT: void HelperFun7();
+// CHECK-NEW-FUN3-CPP-SAME: {{[[:space:]]}}
+// CHECK-NEW-FUN3-CPP-NEXT: class HelperC4;
+// CHECK-NEW-FUN3-CPP-NEXT: } // namespace
+// CHECK-NEW-FUN3-CPP-SAME: {{[[:space:]]}}
+// CHECK-NEW-FUN3-CPP-NEXT: void Fun3() {
+// CHECK-NEW-FUN3-CPP-NEXT:   HelperFun7();
+// CHECK-NEW-FUN3-CPP-NEXT:   HelperC4 *t;
+// CHECK-NEW-FUN3-CPP-NEXT: }
+// CHECK-NEW-FUN3-CPP-NEXT: namespace {
+// CHECK-NEW-FUN3-CPP-NEXT: void HelperFun7() {}
+// CHECK-NEW-FUN3-CPP-SAME: {{[[:space:]]}}
+// CHECK-NEW-FUN3-CPP-NEXT: class HelperC4 {};
+// CHECK-NEW-FUN3-CPP-NEXT: } // namespace
+// CHECK-NEW-FUN3-CPP-NEXT: } // namespace b
+//
+// CHECK-OLD-FUN3-CPP-NOT: void HelperFun7();
+// CHECK-OLD-FUN3-CPP-NOT: void HelperFun7() {}
+// CHECK-OLD-FUN3-CPP-NOT: void Fun3() { HelperFun7(); }
 
 // 
 // Test moving all symbols in headers.
 // 
 // RUN: cp %S/Inputs/helper_decls_test*  %T/used-helper-decls/
-// RUN: clang-move -names="a::Class1, a::Class2, a::Class3, a::Class4, a::Class5, a::Class5, a::Class6, a::Class7, a::Fun1, a::Fun2" -new_cc=%T/used-helper-decls/new_helper_decls_test.cpp -new_header=%T/used-helper-decls/new_helper_decls_test.h -old_cc=%T/used-helper-decls/helper_decls_test.cpp -old_header=../used-helper-decls/helper_decls_test.h %T/used-helper-decls/helper_decls_test.cpp -- -std=c++11
+// RUN: clang-move -names="a::Class1, a::Class2, a::Class3, a::Class4, a::Class5, a::Class5, a::Class6, a::Class7, a::Fun1, a::Fun2, b::Fun3" -new_cc=%T/used-helper-decls/new_helper_decls_test.cpp -new_header=%T/used-helper-decls/new_helper_decls_test.h -old_cc=%T/used-helper-decls/helper_decls_test.cpp -old_header=../used-helper-decls/helper_decls_test.h %T/used-helper-decls/helper_decls_test.cpp -- -std=c++11
 // RUN: FileCheck -input-file=%T/used-helper-decls/new_helper_decls_test.h -check-prefix=CHECK-NEW-H %s
 // RUN: FileCheck -input-file=%T/used-helper-decls/new_helper_decls_test.cpp -check-prefix=CHECK-NEW-CPP %s
 // RUN: FileCheck -input-file=%T/used-helper-decls/helper_decls_test.h -allow-empty -check-prefix=CHECK-EMPTY %s
@@ -384,5 +415,24 @@
 // CHECK-NEW-CPP-NEXT: void Fun1() { HelperFun5(); }
 // CHECK-NEW-CPP-SAME: {{[[:space:]]}}
 // CHECK-NEW-CPP-NEXT: } // namespace a
+// CHECK-NEW-CPP-SAME: {{[[:space:]]}}
+// CHECK-NEW-CPP-NEXT: namespace b {
+// CHECK-NEW-CPP-NEXT: namespace {
+// CHECK-NEW-CPP-NEXT: void HelperFun7();
+// CHECK-NEW-CPP-SAME: {{[[:space:]]}}
+// CHECK-NEW-CPP-NEXT: class HelperC4;
+// CHECK-NEW-CPP-NEXT: } // namespace
+// CHECK-NEW-CPP-SAME: {{[[:space:]]}}
+// CHECK-NEW-CPP-NEXT: void Fun3() {
+// CHECK-NEW-CPP-NEXT:   HelperFun7();
+// CHECK-NEW-CPP-NEXT:   HelperC4 *t;
+// CHECK-NEW-CPP-NEXT: }
+// CHECK-NEW-CPP-SAME: {{[[:space:]]}}
+// CHECK-NEW-CPP-NEXT: namespace {
+// CHECK-NEW-CPP-NEXT: void HelperFun7() {}
+// CHECK-NEW-CPP-SAME: {{[[:space:]]}}
+// CHECK-NEW-CPP-NEXT: class HelperC4 {};
+// CHECK-NEW-CPP-NEXT: } // namespace
+// CHECK-NEW-CPP-NEXT: } // namespace b
 
 // CHECK-EMPTY: {{^}}{{$}}
Index: test/clang-move/Inputs/helper_decls_test.h
===
--- test/clang-move/Inputs/helper_decls_test.h
+++ test/clang-move/Inputs/helper_decls_test.h
@@ -33,3 +33,7 @@
 inline void 

[PATCH] D28801: [clang-move] Handle helpers with forward declarations.

2017-01-17 Thread Haojian Wu via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL292215: [clang-move] Handle helpers with forward 
declarations. (authored by hokein).

Changed prior to commit:
  https://reviews.llvm.org/D28801?vs=84655=84659#toc

Repository:
  rL LLVM

https://reviews.llvm.org/D28801

Files:
  clang-tools-extra/trunk/clang-move/ClangMove.cpp
  clang-tools-extra/trunk/clang-move/HelperDeclRefGraph.cpp
  clang-tools-extra/trunk/test/clang-move/Inputs/helper_decls_test.cpp
  clang-tools-extra/trunk/test/clang-move/Inputs/helper_decls_test.h
  clang-tools-extra/trunk/test/clang-move/move-used-helper-decls.cpp

Index: clang-tools-extra/trunk/clang-move/HelperDeclRefGraph.cpp
===
--- clang-tools-extra/trunk/clang-move/HelperDeclRefGraph.cpp
+++ clang-tools-extra/trunk/clang-move/HelperDeclRefGraph.cpp
@@ -10,8 +10,11 @@
 #include "HelperDeclRefGraph.h"
 #include "ClangMove.h"
 #include "clang/AST/Decl.h"
+#include "llvm/Support/Debug.h"
 #include 
 
+#define DEBUG_TYPE "clang-move"
+
 namespace clang {
 namespace move {
 
@@ -113,13 +116,19 @@
   if (const auto *FuncRef = Result.Nodes.getNodeAs("func_ref")) {
 const auto *DC = Result.Nodes.getNodeAs("dc");
 assert(DC);
-
-RG->addEdge(getOutmostClassOrFunDecl(DC->getCanonicalDecl()),
-getOutmostClassOrFunDecl(FuncRef->getDecl()));
+DEBUG(llvm::dbgs() << "Find helper function usage: "
+   << FuncRef->getDecl()->getNameAsString() << " ("
+   << FuncRef->getDecl() << ")\n");
+RG->addEdge(
+getOutmostClassOrFunDecl(DC->getCanonicalDecl()),
+getOutmostClassOrFunDecl(FuncRef->getDecl()->getCanonicalDecl()));
   } else if (const auto *UsedClass =
  Result.Nodes.getNodeAs("used_class")) {
 const auto *DC = Result.Nodes.getNodeAs("dc");
 assert(DC);
+DEBUG(llvm::dbgs() << "Find helper class usage: "
+   << UsedClass->getNameAsString() << " (" << UsedClass
+   << ")\n");
 RG->addEdge(getOutmostClassOrFunDecl(DC->getCanonicalDecl()), UsedClass);
   }
 }
Index: clang-tools-extra/trunk/clang-move/ClangMove.cpp
===
--- clang-tools-extra/trunk/clang-move/ClangMove.cpp
+++ clang-tools-extra/trunk/clang-move/ClangMove.cpp
@@ -553,16 +553,22 @@
 
   // Matchers for helper declarations in old.cc.
   auto InAnonymousNS = hasParent(namespaceDecl(isAnonymous()));
-  auto DefinitionInOldCC = allOf(isDefinition(), unless(InMovedClass), InOldCC);
-  auto IsOldCCHelperDefinition =
-  allOf(DefinitionInOldCC, anyOf(isStaticStorageClass(), InAnonymousNS));
+  auto NotInMovedClass= allOf(unless(InMovedClass), InOldCC);
+  auto IsOldCCHelper =
+  allOf(NotInMovedClass, anyOf(isStaticStorageClass(), InAnonymousNS));
   // Match helper classes separately with helper functions/variables since we
   // want to reuse these matchers in finding helpers usage below.
-  auto HelperFuncOrVar =
-  namedDecl(notInMacro(), anyOf(functionDecl(IsOldCCHelperDefinition),
-varDecl(IsOldCCHelperDefinition)));
+  //
+  // There could be forward declarations usage for helpers, especially for
+  // classes and functions. We need include these forward declarations.
+  //
+  // Forward declarations for variable helpers will be excluded as these
+  // declarations (with "extern") are not supposed in cpp file.
+   auto HelperFuncOrVar =
+  namedDecl(notInMacro(), anyOf(functionDecl(IsOldCCHelper),
+varDecl(isDefinition(), IsOldCCHelper)));
   auto HelperClasses =
-  cxxRecordDecl(notInMacro(), DefinitionInOldCC, InAnonymousNS);
+  cxxRecordDecl(notInMacro(), NotInMovedClass, InAnonymousNS);
   // Save all helper declarations in old.cc.
   Finder->addMatcher(
   namedDecl(anyOf(HelperFuncOrVar, HelperClasses)).bind("helper_decls"),
@@ -650,6 +656,8 @@
  Result.Nodes.getNodeAs("helper_decls")) {
 MovedDecls.push_back(ND);
 HelperDeclarations.push_back(ND);
+DEBUG(llvm::dbgs() << "Add helper : "
+   << ND->getNameAsString() << " (" << ND << ")\n");
   } else if (const auto *UD =
  Result.Nodes.getNodeAs("using_decl")) {
 MovedDecls.push_back(UD);
@@ -703,9 +711,12 @@
 // We remove the helper declarations which are not used in the old.cc after
 // moving the given declarations.
 for (const auto *D : HelperDeclarations) {
-  if (!UsedDecls.count(HelperDeclRGBuilder::getOutmostClassOrFunDecl(D))) {
+  DEBUG(llvm::dbgs() << "Check helper is used: "
+ << D->getNameAsString() << " (" << D << ")\n");
+  if (!UsedDecls.count(HelperDeclRGBuilder::getOutmostClassOrFunDecl(
+  D->getCanonicalDecl( {
 DEBUG(llvm::dbgs() << "Helper removed in old.cc: "
-   << 

[PATCH] D28774: [clang-move] Ignore using decls which are defined in macros.

2017-01-17 Thread Haojian Wu via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL292207: [clang-move] Ignore using decls which are defined in 
macros. (authored by hokein).

Changed prior to commit:
  https://reviews.llvm.org/D28774?vs=84639=84643#toc

Repository:
  rL LLVM

https://reviews.llvm.org/D28774

Files:
  clang-tools-extra/trunk/clang-move/ClangMove.cpp
  clang-tools-extra/trunk/test/clang-move/Inputs/macro_helper_test.cpp
  clang-tools-extra/trunk/test/clang-move/Inputs/macro_helper_test.h
  clang-tools-extra/trunk/test/clang-move/no-move-macro-helpers.cpp

Index: clang-tools-extra/trunk/clang-move/ClangMove.cpp
===
--- clang-tools-extra/trunk/clang-move/ClangMove.cpp
+++ clang-tools-extra/trunk/clang-move/ClangMove.cpp
@@ -31,6 +31,8 @@
 // FIXME: Move to ASTMatchers.
 AST_MATCHER(VarDecl, isStaticDataMember) { return Node.isStaticDataMember(); }
 
+AST_MATCHER(NamedDecl, notInMacro) { return !Node.getLocation().isMacroID(); }
+
 AST_MATCHER_P(Decl, hasOutermostEnclosingClass,
   ast_matchers::internal::Matcher, InnerMatcher) {
   const auto *Context = Node.getDeclContext();
@@ -525,12 +527,12 @@
   // Matching using decls/type alias decls which are in named/anonymous/global
   // namespace, these decls are always copied to new.h/cc. Those in classes,
   // functions are covered in other matchers.
-  Finder->addMatcher(
-  namedDecl(anyOf(usingDecl(IsOldCCTopLevelDecl),
-  usingDirectiveDecl(IsOldCCTopLevelDecl),
-  typeAliasDecl(IsOldCCTopLevelDecl)))
-  .bind("using_decl"),
-  this);
+  Finder->addMatcher(namedDecl(anyOf(usingDecl(IsOldCCTopLevelDecl),
+ usingDirectiveDecl(IsOldCCTopLevelDecl),
+ typeAliasDecl(IsOldCCTopLevelDecl)),
+   notInMacro())
+ .bind("using_decl"),
+ this);
 
   // Match static functions/variable definitions which are defined in named
   // namespaces.
@@ -556,9 +558,11 @@
   allOf(DefinitionInOldCC, anyOf(isStaticStorageClass(), InAnonymousNS));
   // Match helper classes separately with helper functions/variables since we
   // want to reuse these matchers in finding helpers usage below.
-  auto HelperFuncOrVar = namedDecl(anyOf(functionDecl(IsOldCCHelperDefinition),
- varDecl(IsOldCCHelperDefinition)));
-  auto HelperClasses = cxxRecordDecl(DefinitionInOldCC, InAnonymousNS);
+  auto HelperFuncOrVar =
+  namedDecl(notInMacro(), anyOf(functionDecl(IsOldCCHelperDefinition),
+varDecl(IsOldCCHelperDefinition)));
+  auto HelperClasses =
+  cxxRecordDecl(notInMacro(), DefinitionInOldCC, InAnonymousNS);
   // Save all helper declarations in old.cc.
   Finder->addMatcher(
   namedDecl(anyOf(HelperFuncOrVar, HelperClasses)).bind("helper_decls"),
Index: clang-tools-extra/trunk/test/clang-move/Inputs/macro_helper_test.h
===
--- clang-tools-extra/trunk/test/clang-move/Inputs/macro_helper_test.h
+++ clang-tools-extra/trunk/test/clang-move/Inputs/macro_helper_test.h
@@ -0,0 +1,2 @@
+class A {};
+void f1();
Index: clang-tools-extra/trunk/test/clang-move/Inputs/macro_helper_test.cpp
===
--- clang-tools-extra/trunk/test/clang-move/Inputs/macro_helper_test.cpp
+++ clang-tools-extra/trunk/test/clang-move/Inputs/macro_helper_test.cpp
@@ -0,0 +1,13 @@
+#include "macro_helper_test.h"
+
+#define DEFINE(name) \
+  namespace ns { \
+  static const bool t1 = false; \
+  bool t2_##name = t1; \
+  bool t3_##name = t1; \
+  } \
+  using ns::t2_##name;
+
+DEFINE(test)
+
+void f1() {}
Index: clang-tools-extra/trunk/test/clang-move/no-move-macro-helpers.cpp
===
--- clang-tools-extra/trunk/test/clang-move/no-move-macro-helpers.cpp
+++ clang-tools-extra/trunk/test/clang-move/no-move-macro-helpers.cpp
@@ -0,0 +1,43 @@
+// RUN: mkdir -p %T/no-move-macro-helper
+// RUN: cp %S/Inputs/macro_helper_test.h  %T/no-move-macro-helper/macro_helper_test.h
+// RUN: cp %S/Inputs/macro_helper_test.cpp %T/no-move-macro-helper/macro_helper_test.cpp
+// RUN: cd %T/no-move-macro-helper
+//
+// -
+// Test no moving helpers in macro.
+// -
+// RUN: clang-move -names="A" -new_cc=%T/no-move-macro-helper/new_test.cpp -new_header=%T/no-move-macro-helper/new_test.h -old_cc=%T/no-move-macro-helper/macro_helper_test.cpp -old_header=%T/no-move-macro-helper/macro_helper_test.h %T/no-move-macro-helper/macro_helper_test.cpp -- -std=c++11
+// RUN: FileCheck -input-file=%T/no-move-macro-helper/new_test.h 

[PATCH] D30337: [clang-move] Extend clang-move to support moving global variable.

2017-02-27 Thread Haojian Wu via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL296337: [clang-move] Extend clang-move to support moving 
global variable. (authored by hokein).

Changed prior to commit:
  https://reviews.llvm.org/D30337?vs=89659=89869#toc

Repository:
  rL LLVM

https://reviews.llvm.org/D30337

Files:
  clang-tools-extra/trunk/clang-move/ClangMove.cpp
  clang-tools-extra/trunk/test/clang-move/Inputs/var_test.cpp
  clang-tools-extra/trunk/test/clang-move/Inputs/var_test.h
  clang-tools-extra/trunk/test/clang-move/move-var.cpp
  clang-tools-extra/trunk/unittests/clang-move/ClangMoveTests.cpp

Index: clang-tools-extra/trunk/unittests/clang-move/ClangMoveTests.cpp
===
--- clang-tools-extra/trunk/unittests/clang-move/ClangMoveTests.cpp
+++ clang-tools-extra/trunk/unittests/clang-move/ClangMoveTests.cpp
@@ -539,6 +539,8 @@
 "enum class E2 { Red };\n"
 "typedef int Int2;\n"
 "using Int = int;\n"
+"extern int kGlobalInt;\n"
+"extern const char* const kGlobalStr;\n"
 "} // namespace b\n"
 "} // namespace a\n";
   const char TestCode[] = "#include \"foo.h\"\n";
@@ -553,7 +555,8 @@
   {"A", "Class"}, {"B", "Class"},{"a::Move1", "Class"},
   {"a::f1", "Function"},  {"a::f2", "Function"}, {"a::b::Move1", "Class"},
   {"a::b::f", "Function"}, {"a::b::E1", "Enum"}, {"a::b::E2", "Enum"},
-  {"a::b::Int2", "TypeAlias"}, {"a::b::Int", "TypeAlias"} };
+  {"a::b::Int2", "TypeAlias"}, {"a::b::Int", "TypeAlias"},
+  {"a::b::kGlobalInt", "Variable"}, {"a::b::kGlobalStr", "Variable"}};
   runClangMoveOnCode(Spec, TestHeader, TestCode, );
   std::set Results;
   for (const auto& DelPair : Reporter.getDeclarationList())
Index: clang-tools-extra/trunk/clang-move/ClangMove.cpp
===
--- clang-tools-extra/trunk/clang-move/ClangMove.cpp
+++ clang-tools-extra/trunk/clang-move/ClangMove.cpp
@@ -168,6 +168,21 @@
   ClangMoveTool *MoveTool;
 };
 
+class VarDeclarationMatch : public MatchFinder::MatchCallback {
+public:
+  explicit VarDeclarationMatch(ClangMoveTool *MoveTool)
+  : MoveTool(MoveTool) {}
+
+  void run(const MatchFinder::MatchResult ) override {
+const auto *VD = Result.Nodes.getNodeAs("var");
+assert(VD);
+MoveDeclFromOldFileToNewFile(MoveTool, VD);
+  }
+
+private:
+  ClangMoveTool *MoveTool;
+};
+
 class TypeAliasMatch : public MatchFinder::MatchCallback {
 public:
   explicit TypeAliasMatch(ClangMoveTool *MoveTool)
@@ -618,6 +633,11 @@
  .bind("function"),
  MatchCallbacks.back().get());
 
+  MatchCallbacks.push_back(llvm::make_unique(this));
+  Finder->addMatcher(
+  varDecl(InOldFiles, *HasAnySymbolNames, TopLevelDecl).bind("var"),
+  MatchCallbacks.back().get());
+
   // Match enum definition in old.h. Enum helpers (which are defined in old.cc)
   // will not be moved for now no matter whether they are used or not.
   MatchCallbacks.push_back(llvm::make_unique(this));
@@ -852,7 +872,10 @@
 for (const auto *Decl : UnremovedDeclsInOldHeader) {
   auto Kind = Decl->getKind();
   const std::string QualifiedName = Decl->getQualifiedNameAsString();
-  if (Kind == Decl::Kind::Function || Kind == Decl::Kind::FunctionTemplate)
+  if (Kind == Decl::Kind::Var)
+Reporter->reportDeclaration(QualifiedName, "Variable");
+  else if (Kind == Decl::Kind::Function ||
+   Kind == Decl::Kind::FunctionTemplate)
 Reporter->reportDeclaration(QualifiedName, "Function");
   else if (Kind == Decl::Kind::ClassTemplate ||
Kind == Decl::Kind::CXXRecord)
@@ -883,6 +906,7 @@
 case Decl::Kind::Typedef:
 case Decl::Kind::TypeAlias:
 case Decl::Kind::TypeAliasTemplate:
+case Decl::Kind::Var:
   return true;
 default:
   return false;
Index: clang-tools-extra/trunk/test/clang-move/Inputs/var_test.h
===
--- clang-tools-extra/trunk/test/clang-move/Inputs/var_test.h
+++ clang-tools-extra/trunk/test/clang-move/Inputs/var_test.h
@@ -0,0 +1,11 @@
+namespace a {
+extern int kGlobalInt;
+extern const char *const kGlobalStr;
+}
+
+int kEvilInt = 2;
+
+inline void f1() {
+  int kGlobalInt = 3;
+  const char *const kGlobalStr = "Hello2";
+}
Index: clang-tools-extra/trunk/test/clang-move/Inputs/var_test.cpp
===
--- clang-tools-extra/trunk/test/clang-move/Inputs/var_test.cpp
+++ clang-tools-extra/trunk/test/clang-move/Inputs/var_test.cpp
@@ -0,0 +1,6 @@
+#include "var_test.h"
+
+namespace a{
+int kGlobalInt = 1;
+const char *const kGlobalStr = "Hello";
+}
Index: 

[PATCH] D30412: [clang-tidy] Fix a false positive on modernize-use-nullptr check.

2017-02-28 Thread Haojian Wu via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL296479: [clang-tidy] Fix a false positive on 
modernize-use-nullptr check. (authored by hokein).

Changed prior to commit:
  https://reviews.llvm.org/D30412?vs=89894=90032#toc

Repository:
  rL LLVM

https://reviews.llvm.org/D30412

Files:
  clang-tools-extra/trunk/clang-tidy/modernize/UseNullptrCheck.cpp
  clang-tools-extra/trunk/test/clang-tidy/modernize-use-nullptr.cpp


Index: clang-tools-extra/trunk/clang-tidy/modernize/UseNullptrCheck.cpp
===
--- clang-tools-extra/trunk/clang-tidy/modernize/UseNullptrCheck.cpp
+++ clang-tools-extra/trunk/clang-tidy/modernize/UseNullptrCheck.cpp
@@ -190,8 +190,10 @@
   bool VisitStmt(Stmt *S) {
 auto *C = dyn_cast(S);
 // Catch the castExpr inside cxxDefaultArgExpr.
-if (auto *E = dyn_cast(S))
+if (auto *E = dyn_cast(S)) {
   C = dyn_cast(E->getExpr());
+  FirstSubExpr = nullptr;
+}
 if (!C) {
   FirstSubExpr = nullptr;
   return true;
Index: clang-tools-extra/trunk/test/clang-tidy/modernize-use-nullptr.cpp
===
--- clang-tools-extra/trunk/test/clang-tidy/modernize-use-nullptr.cpp
+++ clang-tools-extra/trunk/test/clang-tidy/modernize-use-nullptr.cpp
@@ -228,3 +228,19 @@
 void test_default_argument() {
   D(nullptr);
 }
+
+// Test on two neighbour CXXDefaultArgExprs nodes.
+typedef unsigned long long uint64;
+struct ZZ {
+  explicit ZZ(uint64, const uint64* = NULL) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:39: warning: use nullptr
+// CHECK-FIXES: explicit ZZ(uint64, const uint64* = nullptr) {}
+  operator bool()  { return true; }
+};
+
+uint64 Hash(uint64 seed = 0) { return 0; }
+
+void f() {
+  bool a;
+  a = ZZ(Hash());
+}


Index: clang-tools-extra/trunk/clang-tidy/modernize/UseNullptrCheck.cpp
===
--- clang-tools-extra/trunk/clang-tidy/modernize/UseNullptrCheck.cpp
+++ clang-tools-extra/trunk/clang-tidy/modernize/UseNullptrCheck.cpp
@@ -190,8 +190,10 @@
   bool VisitStmt(Stmt *S) {
 auto *C = dyn_cast(S);
 // Catch the castExpr inside cxxDefaultArgExpr.
-if (auto *E = dyn_cast(S))
+if (auto *E = dyn_cast(S)) {
   C = dyn_cast(E->getExpr());
+  FirstSubExpr = nullptr;
+}
 if (!C) {
   FirstSubExpr = nullptr;
   return true;
Index: clang-tools-extra/trunk/test/clang-tidy/modernize-use-nullptr.cpp
===
--- clang-tools-extra/trunk/test/clang-tidy/modernize-use-nullptr.cpp
+++ clang-tools-extra/trunk/test/clang-tidy/modernize-use-nullptr.cpp
@@ -228,3 +228,19 @@
 void test_default_argument() {
   D(nullptr);
 }
+
+// Test on two neighbour CXXDefaultArgExprs nodes.
+typedef unsigned long long uint64;
+struct ZZ {
+  explicit ZZ(uint64, const uint64* = NULL) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:39: warning: use nullptr
+// CHECK-FIXES: explicit ZZ(uint64, const uint64* = nullptr) {}
+  operator bool()  { return true; }
+};
+
+uint64 Hash(uint64 seed = 0) { return 0; }
+
+void f() {
+  bool a;
+  a = ZZ(Hash());
+}
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D30493: [change-namespace] avoid adding leading '::' when possible.

2017-03-02 Thread Haojian Wu via Phabricator via cfe-commits
hokein added a comment.

I like removing the leading "::" when possible. :)




Comment at: change-namespace/ChangeNamespace.cpp:291
+  assert(!SymbolSplitted.empty());
+  SymbolSplitted.pop_back();
+

Is this needed? Looks like you are removing the name of the symbol here, but 
from the code below, you only use the first element of it.  The QualifiedSymbol 
should always be a fully-qualified name with at least 1 namespace qualifier in 
the code, right?



Comment at: change-namespace/ChangeNamespace.cpp:296
+assert(!NsSplitted.empty());
+for (auto I = NsSplitted.begin() + 1, E = NsSplitted.end(); I != E; ++I) {
+  if (*I == SymbolSplitted.front())

Why skipping the first element? And use `is_contained` instead?



Comment at: unittests/change-namespace/ChangeNamespaceTests.cpp:718
   "void f() {\n"
-  " auto *ref1 = ::na::A::f;\n"
-  " auto *ref2 = ::na::a_f;\n"
-  " auto *ref3 = ::na::s_f;\n"
+  " auto *ref1 = na::A::f;\n"
+  " auto *ref2 = na::a_f;\n"

The code style is not correct. Also fix it.


https://reviews.llvm.org/D30493



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D30412: [clang-tidy] Fix a false positive on modernize-use-nullptr check.

2017-02-27 Thread Haojian Wu via Phabricator via cfe-commits
hokein created this revision.
Herald added a subscriber: JDevlieghere.

The false positive happens on two neighbour CXXDefaultArgExpr AST nodes.
like below:

CXXFunctionalCastExpr 0x85c9670  'struct ZZ' functional cast to 
struct ZZ 
 `-CXXConstructExpr 0x85c9518  'struct ZZ' 'void (uint64, const 
uint64 *)'

| -CallExpr 0x85a0a90  'uint64':'unsigned long long'   |
|  
| -ImplicitCastExpr 0x85a0a78  'uint64 (*)(uint64)' 
|
|  
| `-DeclRefExpr 0x85a09f0  'uint64 (uint64)' lvalue Function 0x85a06a0 
'Hash' 'uint64 (uint64)' |
| `-CXXDefaultArgExpr 0x85a0ac8 <> 'uint64':'unsigned long long' |

  `-CXXDefaultArgExpr 0x85c94f8 <> 'const uint64 *'

For each particular CXXDefaultArgExpr node, we need to reset
FirstSubExpr, otherwise FirstSubExpr will refer to an incorrect expr.


https://reviews.llvm.org/D30412

Files:
  clang-tidy/modernize/UseNullptrCheck.cpp
  test/clang-tidy/modernize-use-nullptr.cpp


Index: test/clang-tidy/modernize-use-nullptr.cpp
===
--- test/clang-tidy/modernize-use-nullptr.cpp
+++ test/clang-tidy/modernize-use-nullptr.cpp
@@ -228,3 +228,19 @@
 void test_default_argument() {
   D(nullptr);
 }
+
+// Test on two neighbour CXXDefaultArgExprs nodes.
+typedef unsigned long long uint64;
+struct ZZ {
+  explicit ZZ(uint64, const uint64* = NULL) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:39: warning: use nullptr
+// CHECK-FIXES: explicit ZZ(uint64, const uint64* = nullptr) {}
+  operator bool()  { return true; }
+};
+
+uint64 Hash(uint64 seed = 0) { return 0; }
+
+void f() {
+  bool a;
+  a = ZZ(Hash());
+}
Index: clang-tidy/modernize/UseNullptrCheck.cpp
===
--- clang-tidy/modernize/UseNullptrCheck.cpp
+++ clang-tidy/modernize/UseNullptrCheck.cpp
@@ -190,8 +190,10 @@
   bool VisitStmt(Stmt *S) {
 auto *C = dyn_cast(S);
 // Catch the castExpr inside cxxDefaultArgExpr.
-if (auto *E = dyn_cast(S))
+if (auto *E = dyn_cast(S)) {
   C = dyn_cast(E->getExpr());
+  FirstSubExpr = nullptr;
+}
 if (!C) {
   FirstSubExpr = nullptr;
   return true;


Index: test/clang-tidy/modernize-use-nullptr.cpp
===
--- test/clang-tidy/modernize-use-nullptr.cpp
+++ test/clang-tidy/modernize-use-nullptr.cpp
@@ -228,3 +228,19 @@
 void test_default_argument() {
   D(nullptr);
 }
+
+// Test on two neighbour CXXDefaultArgExprs nodes.
+typedef unsigned long long uint64;
+struct ZZ {
+  explicit ZZ(uint64, const uint64* = NULL) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:39: warning: use nullptr
+// CHECK-FIXES: explicit ZZ(uint64, const uint64* = nullptr) {}
+  operator bool()  { return true; }
+};
+
+uint64 Hash(uint64 seed = 0) { return 0; }
+
+void f() {
+  bool a;
+  a = ZZ(Hash());
+}
Index: clang-tidy/modernize/UseNullptrCheck.cpp
===
--- clang-tidy/modernize/UseNullptrCheck.cpp
+++ clang-tidy/modernize/UseNullptrCheck.cpp
@@ -190,8 +190,10 @@
   bool VisitStmt(Stmt *S) {
 auto *C = dyn_cast(S);
 // Catch the castExpr inside cxxDefaultArgExpr.
-if (auto *E = dyn_cast(S))
+if (auto *E = dyn_cast(S)) {
   C = dyn_cast(E->getExpr());
+  FirstSubExpr = nullptr;
+}
 if (!C) {
   FirstSubExpr = nullptr;
   return true;
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D30490: [change-namespace] get insertion points of forward declarations correct.

2017-03-01 Thread Haojian Wu via Phabricator via cfe-commits
hokein added inline comments.



Comment at: unittests/change-namespace/ChangeNamespaceTests.cpp:354
  "namespace nb {\n"
+ "\n"
  "class FWD;\n"

I'd create a new test for the fix instead of modifying the current one.


https://reviews.llvm.org/D30490



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D27758: [change-namespace] don't crash when type reference is in function type parameter list.

2016-12-14 Thread Haojian Wu via Phabricator via cfe-commits
hokein accepted this revision.
hokein added a comment.
This revision is now accepted and ready to land.

LGTM.


https://reviews.llvm.org/D27758



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D27673: [clang-move] Only move used helper declarations.

2016-12-16 Thread Haojian Wu via Phabricator via cfe-commits
hokein updated this revision to Diff 81741.
hokein marked 15 inline comments as done.
hokein added a comment.



- address code review comments
- add more tests


https://reviews.llvm.org/D27673

Files:
  clang-move/CMakeLists.txt
  clang-move/ClangMove.cpp
  clang-move/ClangMove.h
  clang-move/UsedHelperDeclFinder.cpp
  clang-move/UsedHelperDeclFinder.h
  test/clang-move/Inputs/helper_decls_test.cpp
  test/clang-move/Inputs/helper_decls_test.h
  test/clang-move/Inputs/multiple_class_test.cpp
  test/clang-move/move-multiple-classes.cpp
  test/clang-move/move-used-helper-decls.cpp
  unittests/clang-move/ClangMoveTests.cpp

Index: unittests/clang-move/ClangMoveTests.cpp
===
--- unittests/clang-move/ClangMoveTests.cpp
+++ unittests/clang-move/ClangMoveTests.cpp
@@ -73,13 +73,21 @@
   "\n"
   "// comment5\n"
   "// comment5\n"
-  "void Foo::f() { f1(); }\n"
+  "void Foo::f() {\n"
+  "  f1();\n"
+  "  kConstInt1;\n"
+  "  kConstInt2;\n"
+  "  help();\n"
+  "}\n"
   "\n"
   "/\n"
   "// comment //\n"
   "/\n"
   "int Foo::b = 2;\n"
   "int Foo2::f() {\n"
+  "  kConstInt1;\n"
+  "  kConstInt2;\n"
+  "  help();\n"
   "  f1();\n"
   "  return 1;\n"
   "}\n"
@@ -119,6 +127,9 @@
   "}\n"
   "\n"
   "int Foo2::f() {\n"
+  "  kConstInt1;\n"
+  "  kConstInt2;\n"
+  "  help();\n"
   "  f1();\n"
   "  return 1;\n"
   "}\n"
@@ -154,6 +165,7 @@
  "namespace {\n"
  "// comment1.\n"
  "void f1() {}\n"
+ "\n"
  "/// comment2.\n"
  "int kConstInt1 = 0;\n"
  "} // namespace\n"
@@ -170,7 +182,12 @@
  "\n"
  "// comment5\n"
  "// comment5\n"
- "void Foo::f() { f1(); }\n"
+ "void Foo::f() {\n"
+ "  f1();\n"
+ "  kConstInt1;\n"
+ "  kConstInt2;\n"
+ "  help();\n"
+ "}\n"
  "\n"
  "/\n"
  "// comment //\n"
Index: test/clang-move/move-used-helper-decls.cpp
===
--- /dev/null
+++ test/clang-move/move-used-helper-decls.cpp
@@ -0,0 +1,202 @@
+// RUN: mkdir -p %T/used-helper-decls
+// RUN: cp %S/Inputs/helper_decls_test*  %T/used-helper-decls/
+// RUN: cd %T/used-helper-decls
+
+// RUN: clang-move -names="a::Class1" -new_cc=%T/used-helper-decls/new_helper_decls_test.cpp -new_header=%T/used-helper-decls/new_helper_decls_test.h -old_cc=%T/used-helper-decls/helper_decls_test.cpp -old_header=../used-helper-decls/helper_decls_test.h %T/used-helper-decls/helper_decls_test.cpp -- -std=c++11
+// RUN: FileCheck -input-file=%T/used-helper-decls/new_helper_decls_test.cpp -check-prefix=CHECK-NEW-CLASS1-CPP %s
+// RUN: FileCheck -input-file=%T/used-helper-decls/helper_decls_test.cpp -check-prefix=CHECK-OLD-CLASS1-CPP %s
+
+// CHECK-NEW-CLASS1-CPP: #include "{{.*}}new_helper_decls_test.h"
+// CHECK-NEW-CLASS1-CPP-SAME: {{[[:space:]]}}
+// CHECK-NEW-CLASS1-CPP-NEXT: namespace {
+// CHECK-NEW-CLASS1-CPP-NEXT: void HelperFun1() {}
+// CHECK-NEW-CLASS1-CPP-SAME: {{[[:space:]]}}
+// CHECK-NEW-CLASS1-CPP-NEXT: void HelperFun2() { HelperFun1(); }
+// CHECK-NEW-CLASS1-CPP-NEXT: } // namespace
+// CHECK-NEW-CLASS1-CPP-SAME: {{[[:space:]]}}
+// CHECK-NEW-CLASS1-CPP-NEXT: namespace a {
+// CHECK-NEW-CLASS1-CPP-NEXT: void Class1::f() { HelperFun2(); }
+// CHECK-NEW-CLASS1-CPP-NEXT: } // namespace a
+//
+// CHECK-OLD-CLASS1-CPP: void HelperFun1() {}
+// CHECK-OLD-CLASS1-CPP-NOT: void HelperFun2() { HelperFun1(); }
+// CHECK-OLD-CLASS1-CPP-NOT: void Class1::f() { HelperFun2(); }
+// CHECK-OLD-CLASS1-CPP: void Class2::f() {
+// CHECK-OLD-CLASS1-CPP:   HelperFun1();
+
+// RUN: cp %S/Inputs/helper_decls_test*  %T/used-helper-decls/
+// RUN: clang-move -names="a::Class2" -new_cc=%T/used-helper-decls/new_helper_decls_test.cpp -new_header=%T/used-helper-decls/new_helper_decls_test.h 

[PATCH] D27673: [clang-move] Only move used helper declarations.

2016-12-16 Thread Haojian Wu via Phabricator via cfe-commits
hokein added inline comments.



Comment at: clang-move/ClangMove.cpp:492
+  isDefinition(), unless(InMovedClass), InOldCC,
+  anyOf(isStaticStorageClass(), hasParent(namespaceDecl(isAnonymous();
+  auto HelperFuncOrVar = namedDecl(anyOf(functionDecl(IsOldCCHelperDefinition),

ioeric wrote:
> hokein wrote:
> > ioeric wrote:
> > > It seems that `isStaticStorageClass` is preventing combining matchers for 
> > > functions, variables, and classes. Maybe only apply this matcher on 
> > > `functionDecl` and `varDecl` below, so that helper classes can be matched 
> > > with the same matcher?
> > Seems that it is hard to reuse the same matcher for 
> > `functionDecl`/`varDecl` and `CXXRecordDecl` since `isStaticStorageClass` 
> > is not available to  `CXXRecordDecl`. So we have to match helper classes, 
> > helper functions/vars separately.  Have cleaned the code to make it clearer.
> I mean merging helper classes into `helperFuncOrVar` (maybe need to be 
> renamed) so that class helpers are parallel with `functionDecl` and `varDecl` 
> here.
We need to match helper classes separately because we want to reuse these two 
matchers (HelperFuncOrVar, HelperClasses) in finding helpers' usage below.



Comment at: clang-move/ClangMove.cpp:459
   
//
-  auto InOldCCNamedOrGlobalNamespace =
-  allOf(hasParent(decl(anyOf(namespaceDecl(unless(isAnonymous())),
- translationUnitDecl(,
-InOldCC);
-  // Matching using decls/type alias decls which are in named namespace or
-  // global namespace. Those in classes, functions and anonymous namespaces are
-  // covered in other matchers.
+  auto InOldCCNamespace = allOf(
+  hasParent(decl(anyOf(namespaceDecl(), translationUnitDecl(, InOldCC);

ioeric wrote:
> I got the meaning here, but the name is a bit inaccurate since this also 
> includes `TranslationUnitDecl`.
but`TranslationUnitDecl` also means in global namespace, right?



Comment at: clang-move/ClangMove.cpp:461
+  hasParent(decl(anyOf(namespaceDecl(), translationUnitDecl(, InOldCC);
+  // Matching using decls/type alias decls which are in named/anonymous/global
+  // namespace. Those in classes, functions are covered in other matchers.

ioeric wrote:
> Maybe also explain a bit on how you handle these using and alias decls here.
> 
> Are they always copied/moved regardless where they are?
Yeah, added comment.



Comment at: clang-move/ClangMove.cpp:493
+ varDecl(IsOldCCHelperDefinition)));
+  auto HelperClasses =
+  cxxRecordDecl(isDefinition(), unless(InMovedClass), InOldCC,

ioeric wrote:
> Thinking about this some more. Helpers might be (incorrectly) defined in 
> non-anonymous namespaces without static qualifier. Do we want to consider 
> these?
hmm, in theory, "helpers" defined accidently in non-anonymous namespaces are 
not helpers as they are visible outside of the current TU. The implementation 
relies on the invisible property of helpers to verify whether a 
function/variable is a helper, so this would be hard to achieve.



Comment at: clang-move/UsedHelperDeclFinder.cpp:22
+// by a single node which belongs to the class.
+const Decl *getOutmostEnclosingClassOrFunDecl(const Decl *D) {
+  const auto *DC = D->getDeclContext();

ioeric wrote:
> If we always only match outermost decls, we might be able to get rid of this. 
> I feel that this kind of function (that traverse up AST) can easily hit into 
> corner cases.
Beside construction of the graph, this function is also used in checking 
whether a given Declaration is used or not.



Comment at: clang-move/UsedHelperDeclFinder.cpp:22
+// by a single node which belongs to that class.
+const Decl *getOutmostEnclosingClassOrFunDecl(const Decl *D) {
+  const auto *DC = D->getDeclContext();

ioeric wrote:
> Maybe just `getOutermostDecls` and add FIXME for other data types.
The name might be too long, I have renamed it to `getOutermostClassOrFunDecls` 
(I prefer to keep the `ClassOrFunDecl` postfix which clearly indicates what 
this function exactly does without reading the comment, I'm happy to rename it 
in the future if needed).

Is there any types we want to support? From my understanding, it is sufficient 
to cover our usage now.



Comment at: clang-move/UsedHelperDeclFinder.cpp:30
+  Result = FD;
+  if (const auto *RD = dyn_cast(FD->getParent()))
+Result = RD;

ioeric wrote:
> Why do you need this? And when is a function's parent a class?
This is for the template method in a class.



Comment at: clang-move/UsedHelperDeclFinder.cpp:103
+
+UsedHelperDeclFinder::HelperDeclsSet UsedHelperDeclFinder::getUsedHelperDecls(

[PATCH] D27713: [clang-move] Fix incorrect EndLoc for declarations in macros.

2016-12-13 Thread Haojian Wu via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL289541: [clang-move] Fix incorrect EndLoc for declarations 
in macros. (authored by hokein).

Changed prior to commit:
  https://reviews.llvm.org/D27713?vs=81231=81234#toc

Repository:
  rL LLVM

https://reviews.llvm.org/D27713

Files:
  clang-tools-extra/trunk/clang-move/ClangMove.cpp
  clang-tools-extra/trunk/unittests/clang-move/ClangMoveTests.cpp


Index: clang-tools-extra/trunk/clang-move/ClangMove.cpp
===
--- clang-tools-extra/trunk/clang-move/ClangMove.cpp
+++ clang-tools-extra/trunk/clang-move/ClangMove.cpp
@@ -219,7 +219,8 @@
 getLocForEndOfDecl(const clang::Decl *D,
const LangOptions  = clang::LangOptions()) {
   const auto  = D->getASTContext().getSourceManager();
-  std::pair LocInfo = SM.getDecomposedLoc(D->getLocEnd());
+  auto EndExpansionLoc = SM.getExpansionLoc(D->getLocEnd());
+  std::pair LocInfo = SM.getDecomposedLoc(EndExpansionLoc);
   // Try to load the file buffer.
   bool InvalidTemp = false;
   llvm::StringRef File = SM.getBufferData(LocInfo.first, );
@@ -235,7 +236,7 @@
   // FIXME: this is a bit hacky to get ReadToEndOfLine work.
   Lex.setParsingPreprocessorDirective(true);
   Lex.ReadToEndOfLine();
-  SourceLocation EndLoc = D->getLocEnd().getLocWithOffset(Line.size());
+  SourceLocation EndLoc = EndExpansionLoc.getLocWithOffset(Line.size());
   // If we already reach EOF, just return the EOF SourceLocation;
   // otherwise, move 1 offset ahead to include the trailing newline character
   // '\n'.
Index: clang-tools-extra/trunk/unittests/clang-move/ClangMoveTests.cpp
===
--- clang-tools-extra/trunk/unittests/clang-move/ClangMoveTests.cpp
+++ clang-tools-extra/trunk/unittests/clang-move/ClangMoveTests.cpp
@@ -386,6 +386,24 @@
   EXPECT_EQ(ExpectedNewCode, Results[Spec.NewCC]);
 }
 
+TEST(ClangMove, DefinitionInMacro) {
+  const char TestHeader[] = "#define DEF(CLASS) void CLASS##_::f() {}\n"
+"class A_ {\nvoid f();\n};\n"
+"class B {};\n";
+  const char TestCode[] = "#include \"foo.h\"\n"
+  "DEF(A)\n";
+  const char ExpectedNewCode[] = "#include \"new_foo.h\"\n\n"
+ "DEF(A)\n";
+  move::MoveDefinitionSpec Spec;
+  Spec.Names.push_back("A_");
+  Spec.OldHeader = "foo.h";
+  Spec.OldCC = "foo.cc";
+  Spec.NewHeader = "new_foo.h";
+  Spec.NewCC = "new_foo.cc";
+  auto Results = runClangMoveOnCode(Spec, TestHeader, TestCode);
+  EXPECT_EQ(ExpectedNewCode, Results[Spec.NewCC]);
+}
+
 TEST(ClangMove, WellFormattedCode) {
   const std::string CommonHeader =
   "namespace a {\n"


Index: clang-tools-extra/trunk/clang-move/ClangMove.cpp
===
--- clang-tools-extra/trunk/clang-move/ClangMove.cpp
+++ clang-tools-extra/trunk/clang-move/ClangMove.cpp
@@ -219,7 +219,8 @@
 getLocForEndOfDecl(const clang::Decl *D,
const LangOptions  = clang::LangOptions()) {
   const auto  = D->getASTContext().getSourceManager();
-  std::pair LocInfo = SM.getDecomposedLoc(D->getLocEnd());
+  auto EndExpansionLoc = SM.getExpansionLoc(D->getLocEnd());
+  std::pair LocInfo = SM.getDecomposedLoc(EndExpansionLoc);
   // Try to load the file buffer.
   bool InvalidTemp = false;
   llvm::StringRef File = SM.getBufferData(LocInfo.first, );
@@ -235,7 +236,7 @@
   // FIXME: this is a bit hacky to get ReadToEndOfLine work.
   Lex.setParsingPreprocessorDirective(true);
   Lex.ReadToEndOfLine();
-  SourceLocation EndLoc = D->getLocEnd().getLocWithOffset(Line.size());
+  SourceLocation EndLoc = EndExpansionLoc.getLocWithOffset(Line.size());
   // If we already reach EOF, just return the EOF SourceLocation;
   // otherwise, move 1 offset ahead to include the trailing newline character
   // '\n'.
Index: clang-tools-extra/trunk/unittests/clang-move/ClangMoveTests.cpp
===
--- clang-tools-extra/trunk/unittests/clang-move/ClangMoveTests.cpp
+++ clang-tools-extra/trunk/unittests/clang-move/ClangMoveTests.cpp
@@ -386,6 +386,24 @@
   EXPECT_EQ(ExpectedNewCode, Results[Spec.NewCC]);
 }
 
+TEST(ClangMove, DefinitionInMacro) {
+  const char TestHeader[] = "#define DEF(CLASS) void CLASS##_::f() {}\n"
+"class A_ {\nvoid f();\n};\n"
+"class B {};\n";
+  const char TestCode[] = "#include \"foo.h\"\n"
+  "DEF(A)\n";
+  const char ExpectedNewCode[] = "#include \"new_foo.h\"\n\n"
+ "DEF(A)\n";
+  move::MoveDefinitionSpec Spec;
+  Spec.Names.push_back("A_");
+  Spec.OldHeader = "foo.h";
+  Spec.OldCC = "foo.cc";
+  Spec.NewHeader = "new_foo.h";
+  Spec.NewCC = 

[PATCH] D27713: [clang-move] Fix incorrect EndLoc for declarations in macros.

2016-12-13 Thread Haojian Wu via Phabricator via cfe-commits
hokein created this revision.
hokein added a reviewer: ioeric.
hokein added a subscriber: cfe-commits.

https://reviews.llvm.org/D27713

Files:
  clang-move/ClangMove.cpp
  unittests/clang-move/ClangMoveTests.cpp


Index: unittests/clang-move/ClangMoveTests.cpp
===
--- unittests/clang-move/ClangMoveTests.cpp
+++ unittests/clang-move/ClangMoveTests.cpp
@@ -386,6 +386,24 @@
   EXPECT_EQ(ExpectedNewCode, Results[Spec.NewCC]);
 }
 
+TEST(ClangMove, DefinitionInMacro) {
+  const char TestHeader[] = "#define DEF(CLASS) void CLASS##_::f() {}\n"
+"class A_ {\nvoid f();\n};\n"
+"class B {};\n";
+  const char TestCode[] = "#include \"foo.h\"\n"
+  "DEF(A)\n";
+  const char ExpectedNewCode[] = "#include \"new_foo.h\"\n\n"
+ "DEF(A)\n";
+  move::MoveDefinitionSpec Spec;
+  Spec.Names.push_back("A_");
+  Spec.OldHeader = "foo.h";
+  Spec.OldCC = "foo.cc";
+  Spec.NewHeader = "new_foo.h";
+  Spec.NewCC = "new_foo.cc";
+  auto Results = runClangMoveOnCode(Spec, TestHeader, TestCode);
+  EXPECT_EQ(ExpectedNewCode, Results[Spec.NewCC]);
+}
+
 TEST(ClangMove, WellFormattedCode) {
   const std::string CommonHeader =
   "namespace a {\n"
Index: clang-move/ClangMove.cpp
===
--- clang-move/ClangMove.cpp
+++ clang-move/ClangMove.cpp
@@ -219,7 +219,8 @@
 getLocForEndOfDecl(const clang::Decl *D,
const LangOptions  = clang::LangOptions()) {
   const auto  = D->getASTContext().getSourceManager();
-  std::pair LocInfo = SM.getDecomposedLoc(D->getLocEnd());
+  auto EndExpansionLoc = SM.getExpansionLoc(D->getLocEnd());
+  std::pair LocInfo = SM.getDecomposedLoc(EndExpansionLoc);
   // Try to load the file buffer.
   bool InvalidTemp = false;
   llvm::StringRef File = SM.getBufferData(LocInfo.first, );
@@ -235,7 +236,7 @@
   // FIXME: this is a bit hacky to get ReadToEndOfLine work.
   Lex.setParsingPreprocessorDirective(true);
   Lex.ReadToEndOfLine();
-  SourceLocation EndLoc = D->getLocEnd().getLocWithOffset(Line.size());
+  SourceLocation EndLoc = EndExpansionLoc.getLocWithOffset(Line.size());
   // If we already reach EOF, just return the EOF SourceLocation;
   // otherwise, move 1 offset ahead to include the trailing newline character
   // '\n'.


Index: unittests/clang-move/ClangMoveTests.cpp
===
--- unittests/clang-move/ClangMoveTests.cpp
+++ unittests/clang-move/ClangMoveTests.cpp
@@ -386,6 +386,24 @@
   EXPECT_EQ(ExpectedNewCode, Results[Spec.NewCC]);
 }
 
+TEST(ClangMove, DefinitionInMacro) {
+  const char TestHeader[] = "#define DEF(CLASS) void CLASS##_::f() {}\n"
+"class A_ {\nvoid f();\n};\n"
+"class B {};\n";
+  const char TestCode[] = "#include \"foo.h\"\n"
+  "DEF(A)\n";
+  const char ExpectedNewCode[] = "#include \"new_foo.h\"\n\n"
+ "DEF(A)\n";
+  move::MoveDefinitionSpec Spec;
+  Spec.Names.push_back("A_");
+  Spec.OldHeader = "foo.h";
+  Spec.OldCC = "foo.cc";
+  Spec.NewHeader = "new_foo.h";
+  Spec.NewCC = "new_foo.cc";
+  auto Results = runClangMoveOnCode(Spec, TestHeader, TestCode);
+  EXPECT_EQ(ExpectedNewCode, Results[Spec.NewCC]);
+}
+
 TEST(ClangMove, WellFormattedCode) {
   const std::string CommonHeader =
   "namespace a {\n"
Index: clang-move/ClangMove.cpp
===
--- clang-move/ClangMove.cpp
+++ clang-move/ClangMove.cpp
@@ -219,7 +219,8 @@
 getLocForEndOfDecl(const clang::Decl *D,
const LangOptions  = clang::LangOptions()) {
   const auto  = D->getASTContext().getSourceManager();
-  std::pair LocInfo = SM.getDecomposedLoc(D->getLocEnd());
+  auto EndExpansionLoc = SM.getExpansionLoc(D->getLocEnd());
+  std::pair LocInfo = SM.getDecomposedLoc(EndExpansionLoc);
   // Try to load the file buffer.
   bool InvalidTemp = false;
   llvm::StringRef File = SM.getBufferData(LocInfo.first, );
@@ -235,7 +236,7 @@
   // FIXME: this is a bit hacky to get ReadToEndOfLine work.
   Lex.setParsingPreprocessorDirective(true);
   Lex.ReadToEndOfLine();
-  SourceLocation EndLoc = D->getLocEnd().getLocWithOffset(Line.size());
+  SourceLocation EndLoc = EndExpansionLoc.getLocWithOffset(Line.size());
   // If we already reach EOF, just return the EOF SourceLocation;
   // otherwise, move 1 offset ahead to include the trailing newline character
   // '\n'.
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D27674: [StaticAnalysis] Remove unnecessary parameter in CallGraphNode::addCallee.

2016-12-12 Thread Haojian Wu via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL289431: [StaticAnalysis] Remove unnecessary parameter in 
CallGraphNode::addCallee. (authored by hokein).

Changed prior to commit:
  https://reviews.llvm.org/D27674?vs=81078=81081#toc

Repository:
  rL LLVM

https://reviews.llvm.org/D27674

Files:
  cfe/trunk/include/clang/Analysis/CallGraph.h
  cfe/trunk/lib/Analysis/CallGraph.cpp


Index: cfe/trunk/include/clang/Analysis/CallGraph.h
===
--- cfe/trunk/include/clang/Analysis/CallGraph.h
+++ cfe/trunk/include/clang/Analysis/CallGraph.h
@@ -157,7 +157,7 @@
   inline bool empty() const {return CalledFunctions.empty(); }
   inline unsigned size() const {return CalledFunctions.size(); }
 
-  void addCallee(CallGraphNode *N, CallGraph *CG) {
+  void addCallee(CallGraphNode *N) {
 CalledFunctions.push_back(N);
   }
 
Index: cfe/trunk/lib/Analysis/CallGraph.cpp
===
--- cfe/trunk/lib/Analysis/CallGraph.cpp
+++ cfe/trunk/lib/Analysis/CallGraph.cpp
@@ -55,7 +55,7 @@
   void addCalledDecl(Decl *D) {
 if (G->includeInGraph(D)) {
   CallGraphNode *CalleeNode = G->getOrInsertNode(D);
-  CallerNode->addCallee(CalleeNode, G);
+  CallerNode->addCallee(CalleeNode);
 }
   }
 
@@ -154,7 +154,7 @@
   Node = llvm::make_unique(F);
   // Make Root node a parent of all functions to make sure all are reachable.
   if (F)
-Root->addCallee(Node.get(), this);
+Root->addCallee(Node.get());
   return Node.get();
 }
 


Index: cfe/trunk/include/clang/Analysis/CallGraph.h
===
--- cfe/trunk/include/clang/Analysis/CallGraph.h
+++ cfe/trunk/include/clang/Analysis/CallGraph.h
@@ -157,7 +157,7 @@
   inline bool empty() const {return CalledFunctions.empty(); }
   inline unsigned size() const {return CalledFunctions.size(); }
 
-  void addCallee(CallGraphNode *N, CallGraph *CG) {
+  void addCallee(CallGraphNode *N) {
 CalledFunctions.push_back(N);
   }
 
Index: cfe/trunk/lib/Analysis/CallGraph.cpp
===
--- cfe/trunk/lib/Analysis/CallGraph.cpp
+++ cfe/trunk/lib/Analysis/CallGraph.cpp
@@ -55,7 +55,7 @@
   void addCalledDecl(Decl *D) {
 if (G->includeInGraph(D)) {
   CallGraphNode *CalleeNode = G->getOrInsertNode(D);
-  CallerNode->addCallee(CalleeNode, G);
+  CallerNode->addCallee(CalleeNode);
 }
   }
 
@@ -154,7 +154,7 @@
   Node = llvm::make_unique(F);
   // Make Root node a parent of all functions to make sure all are reachable.
   if (F)
-Root->addCallee(Node.get(), this);
+Root->addCallee(Node.get());
   return Node.get();
 }
 
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D27669: [clang-move] Use appendArgumentsAdjuster for adding extra arguments

2016-12-12 Thread Haojian Wu via Phabricator via cfe-commits
hokein accepted this revision.
hokein added a comment.
This revision is now accepted and ready to land.

LGTM, Thanks!




Comment at: clang-move/tool/ClangMoveMain.cpp:109
 OptionsParser.getSourcePathList());
+  // Add "-fparse-all-comments" compile option to make clang parse all comments
+  Tool.appendArgumentsAdjuster(tooling::getInsertArgumentAdjuster(

Nit: Missing a trailing `.`.


Repository:
  rL LLVM

https://reviews.llvm.org/D27669



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D27674: [StaticAnalysis] Remove unnecessary parameter in CallGraphNode::addCallee.

2016-12-12 Thread Haojian Wu via Phabricator via cfe-commits
hokein created this revision.
hokein added a reviewer: bkramer.
hokein added subscribers: ioeric, cfe-commits.

Remove the CallGraph in addCallee as it is not used in addCallee.
It decouples addCallee from CallGraph, so that we can use CallGraphNode
within our customized CallGraph.


https://reviews.llvm.org/D27674

Files:
  include/clang/Analysis/CallGraph.h
  lib/Analysis/CallGraph.cpp


Index: lib/Analysis/CallGraph.cpp
===
--- lib/Analysis/CallGraph.cpp
+++ lib/Analysis/CallGraph.cpp
@@ -55,7 +55,7 @@
   void addCalledDecl(Decl *D) {
 if (G->includeInGraph(D)) {
   CallGraphNode *CalleeNode = G->getOrInsertNode(D);
-  CallerNode->addCallee(CalleeNode, G);
+  CallerNode->addCallee(CalleeNode);
 }
   }
 
@@ -154,7 +154,7 @@
   Node = llvm::make_unique(F);
   // Make Root node a parent of all functions to make sure all are reachable.
   if (F)
-Root->addCallee(Node.get(), this);
+Root->addCallee(Node.get());
   return Node.get();
 }
 
Index: include/clang/Analysis/CallGraph.h
===
--- include/clang/Analysis/CallGraph.h
+++ include/clang/Analysis/CallGraph.h
@@ -157,7 +157,7 @@
   inline bool empty() const {return CalledFunctions.empty(); }
   inline unsigned size() const {return CalledFunctions.size(); }
 
-  void addCallee(CallGraphNode *N, CallGraph *CG) {
+  void addCallee(CallGraphNode *N) {
 CalledFunctions.push_back(N);
   }
 


Index: lib/Analysis/CallGraph.cpp
===
--- lib/Analysis/CallGraph.cpp
+++ lib/Analysis/CallGraph.cpp
@@ -55,7 +55,7 @@
   void addCalledDecl(Decl *D) {
 if (G->includeInGraph(D)) {
   CallGraphNode *CalleeNode = G->getOrInsertNode(D);
-  CallerNode->addCallee(CalleeNode, G);
+  CallerNode->addCallee(CalleeNode);
 }
   }
 
@@ -154,7 +154,7 @@
   Node = llvm::make_unique(F);
   // Make Root node a parent of all functions to make sure all are reachable.
   if (F)
-Root->addCallee(Node.get(), this);
+Root->addCallee(Node.get());
   return Node.get();
 }
 
Index: include/clang/Analysis/CallGraph.h
===
--- include/clang/Analysis/CallGraph.h
+++ include/clang/Analysis/CallGraph.h
@@ -157,7 +157,7 @@
   inline bool empty() const {return CalledFunctions.empty(); }
   inline unsigned size() const {return CalledFunctions.size(); }
 
-  void addCallee(CallGraphNode *N, CallGraph *CG) {
+  void addCallee(CallGraphNode *N) {
 CalledFunctions.push_back(N);
   }
 
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D27673: [clang-move] Only move used helper declarations.

2016-12-12 Thread Haojian Wu via Phabricator via cfe-commits
hokein updated this revision to Diff 81079.
hokein added a comment.

Fix code style.


https://reviews.llvm.org/D27673

Files:
  clang-move/CMakeLists.txt
  clang-move/ClangMove.cpp
  clang-move/ClangMove.h
  clang-move/UsedHelperDeclFinder.cpp
  clang-move/UsedHelperDeclFinder.h
  test/clang-move/Inputs/helper_decls_test.cpp
  test/clang-move/Inputs/helper_decls_test.h
  test/clang-move/Inputs/multiple_class_test.cpp
  test/clang-move/move-multiple-classes.cpp
  test/clang-move/move-used-helper-decls.cpp
  unittests/clang-move/ClangMoveTests.cpp

Index: unittests/clang-move/ClangMoveTests.cpp
===
--- unittests/clang-move/ClangMoveTests.cpp
+++ unittests/clang-move/ClangMoveTests.cpp
@@ -73,13 +73,21 @@
   "\n"
   "// comment5\n"
   "// comment5\n"
-  "void Foo::f() { f1(); }\n"
+  "void Foo::f() {\n"
+  "  f1();\n"
+  "  kConstInt1;\n"
+  "  kConstInt2;\n"
+  "  help();\n"
+  "}\n"
   "\n"
   "/\n"
   "// comment //\n"
   "/\n"
   "int Foo::b = 2;\n"
   "int Foo2::f() {\n"
+  "  kConstInt1;\n"
+  "  kConstInt2;\n"
+  "  help();\n"
   "  f1();\n"
   "  return 1;\n"
   "}\n"
@@ -119,6 +127,9 @@
   "}\n"
   "\n"
   "int Foo2::f() {\n"
+  "  kConstInt1;\n"
+  "  kConstInt2;\n"
+  "  help();\n"
   "  f1();\n"
   "  return 1;\n"
   "}\n"
@@ -154,6 +165,7 @@
  "namespace {\n"
  "// comment1.\n"
  "void f1() {}\n"
+ "\n"
  "/// comment2.\n"
  "int kConstInt1 = 0;\n"
  "} // namespace\n"
@@ -170,7 +182,12 @@
  "\n"
  "// comment5\n"
  "// comment5\n"
- "void Foo::f() { f1(); }\n"
+ "void Foo::f() {\n"
+ "  f1();\n"
+ "  kConstInt1;\n"
+ "  kConstInt2;\n"
+ "  help();\n"
+ "}\n"
  "\n"
  "/\n"
  "// comment //\n"
Index: test/clang-move/move-used-helper-decls.cpp
===
--- /dev/null
+++ test/clang-move/move-used-helper-decls.cpp
@@ -0,0 +1,130 @@
+// RUN: mkdir -p %T/used-helper-decls
+// RUN: cp %S/Inputs/helper_decls_test*  %T/used-helper-decls/
+// RUN: cd %T/used-helper-decls
+
+// RUN: clang-move -names="a::Class1" -new_cc=%T/used-helper-decls/new_helper_decls_test.cpp -new_header=%T/used-helper-decls/new_helper_decls_test.h -old_cc=%T/used-helper-decls/helper_decls_test.cpp -old_header=../used-helper-decls/helper_decls_test.h %T/used-helper-decls/helper_decls_test.cpp -- -std=c++11
+// RUN: FileCheck -input-file=%T/used-helper-decls/new_helper_decls_test.cpp -check-prefix=CHECK-NEW-CLASS1-CPP %s
+// RUN: FileCheck -input-file=%T/used-helper-decls/helper_decls_test.cpp -check-prefix=CHECK-OLD-CLASS1-CPP %s
+
+// CHECK-NEW-CLASS1-CPP: #include "{{.*}}new_helper_decls_test.h"
+// CHECK-NEW-CLASS1-CPP-SAME: {{[[:space:]]}}
+// CHECK-NEW-CLASS1-CPP-NEXT: namespace {
+// CHECK-NEW-CLASS1-CPP-NEXT: void HelperFun1() {}
+// CHECK-NEW-CLASS1-CPP-SAME: {{[[:space:]]}}
+// CHECK-NEW-CLASS1-CPP-NEXT: void HelperFun2() { HelperFun1(); }
+// CHECK-NEW-CLASS1-CPP-NEXT: } // namespace
+// CHECK-NEW-CLASS1-CPP-SAME: {{[[:space:]]}}
+// CHECK-NEW-CLASS1-CPP-NEXT: namespace a {
+// CHECK-NEW-CLASS1-CPP-NEXT: void Class1::f() { HelperFun2(); }
+// CHECK-NEW-CLASS1-CPP-NEXT: } // namespace a
+//
+// CHECK-OLD-CLASS1-CPP: void HelperFun1() {}
+// CHECK-OLD-CLASS1-CPP-NOT: void HelperFun2() { HelperFun1(); }
+// CHECK-OLD-CLASS1-CPP-NOT: void Class1::f() { HelperFun2(); }
+// CHECK-OLD-CLASS1-CPP: void Class2::f() {
+// CHECK-OLD-CLASS1-CPP:   HelperFun1();
+
+// RUN: cp %S/Inputs/helper_decls_test*  %T/used-helper-decls/
+// RUN: clang-move -names="a::Class2" -new_cc=%T/used-helper-decls/new_helper_decls_test.cpp -new_header=%T/used-helper-decls/new_helper_decls_test.h -old_cc=%T/used-helper-decls/helper_decls_test.cpp 

[PATCH] D27673: [clang-move] Only move used helper declarations.

2016-12-12 Thread Haojian Wu via Phabricator via cfe-commits
hokein created this revision.
hokein added a reviewer: ioeric.
hokein added a subscriber: cfe-commits.
Herald added a subscriber: mgorny.

Instead of moving all the helper declarations blindly, this patch
implement an AST-based call graph solution to make clang-move only move used
helper decls to new.cc and remove unused decls in old.cc.


https://reviews.llvm.org/D27673

Files:
  clang-move/CMakeLists.txt
  clang-move/ClangMove.cpp
  clang-move/ClangMove.h
  clang-move/UsedHelperDeclFinder.cpp
  clang-move/UsedHelperDeclFinder.h
  test/clang-move/Inputs/helper_decls_test.cpp
  test/clang-move/Inputs/helper_decls_test.h
  test/clang-move/Inputs/multiple_class_test.cpp
  test/clang-move/move-multiple-classes.cpp
  test/clang-move/move-used-helper-decls.cpp
  unittests/clang-move/ClangMoveTests.cpp

Index: unittests/clang-move/ClangMoveTests.cpp
===
--- unittests/clang-move/ClangMoveTests.cpp
+++ unittests/clang-move/ClangMoveTests.cpp
@@ -73,13 +73,21 @@
   "\n"
   "// comment5\n"
   "// comment5\n"
-  "void Foo::f() { f1(); }\n"
+  "void Foo::f() {\n"
+  "  f1();\n"
+  "  kConstInt1;\n"
+  "  kConstInt2;\n"
+  "  help();\n"
+  "}\n"
   "\n"
   "/\n"
   "// comment //\n"
   "/\n"
   "int Foo::b = 2;\n"
   "int Foo2::f() {\n"
+  "  kConstInt1;\n"
+  "  kConstInt2;\n"
+  "  help();\n"
   "  f1();\n"
   "  return 1;\n"
   "}\n"
@@ -119,6 +127,9 @@
   "}\n"
   "\n"
   "int Foo2::f() {\n"
+  "  kConstInt1;\n"
+  "  kConstInt2;\n"
+  "  help();\n"
   "  f1();\n"
   "  return 1;\n"
   "}\n"
@@ -154,6 +165,7 @@
  "namespace {\n"
  "// comment1.\n"
  "void f1() {}\n"
+ "\n"
  "/// comment2.\n"
  "int kConstInt1 = 0;\n"
  "} // namespace\n"
@@ -170,7 +182,12 @@
  "\n"
  "// comment5\n"
  "// comment5\n"
- "void Foo::f() { f1(); }\n"
+ "void Foo::f() {\n"
+ "  f1();\n"
+ "  kConstInt1;\n"
+ "  kConstInt2;\n"
+ "  help();\n"
+ "}\n"
  "\n"
  "/\n"
  "// comment //\n"
Index: test/clang-move/move-used-helper-decls.cpp
===
--- /dev/null
+++ test/clang-move/move-used-helper-decls.cpp
@@ -0,0 +1,130 @@
+// RUN: mkdir -p %T/used-helper-decls
+// RUN: cp %S/Inputs/helper_decls_test*  %T/used-helper-decls/
+// RUN: cd %T/used-helper-decls
+
+// RUN: clang-move -names="a::Class1" -new_cc=%T/used-helper-decls/new_helper_decls_test.cpp -new_header=%T/used-helper-decls/new_helper_decls_test.h -old_cc=%T/used-helper-decls/helper_decls_test.cpp -old_header=../used-helper-decls/helper_decls_test.h %T/used-helper-decls/helper_decls_test.cpp -- -std=c++11
+// RUN: FileCheck -input-file=%T/used-helper-decls/new_helper_decls_test.cpp -check-prefix=CHECK-NEW-CLASS1-CPP %s
+// RUN: FileCheck -input-file=%T/used-helper-decls/helper_decls_test.cpp -check-prefix=CHECK-OLD-CLASS1-CPP %s
+
+// CHECK-NEW-CLASS1-CPP: #include "{{.*}}new_helper_decls_test.h"
+// CHECK-NEW-CLASS1-CPP-SAME: {{[[:space:]]}}
+// CHECK-NEW-CLASS1-CPP-NEXT: namespace {
+// CHECK-NEW-CLASS1-CPP-NEXT: void HelperFun1() {}
+// CHECK-NEW-CLASS1-CPP-SAME: {{[[:space:]]}}
+// CHECK-NEW-CLASS1-CPP-NEXT: void HelperFun2() { HelperFun1(); }
+// CHECK-NEW-CLASS1-CPP-NEXT: } // namespace
+// CHECK-NEW-CLASS1-CPP-SAME: {{[[:space:]]}}
+// CHECK-NEW-CLASS1-CPP-NEXT: namespace a {
+// CHECK-NEW-CLASS1-CPP-NEXT: void Class1::f() { HelperFun2(); }
+// CHECK-NEW-CLASS1-CPP-NEXT: } // namespace a
+//
+// CHECK-OLD-CLASS1-CPP: void HelperFun1() {}
+// CHECK-OLD-CLASS1-CPP-NOT: void HelperFun2() { HelperFun1(); }
+// CHECK-OLD-CLASS1-CPP-NOT: void Class1::f() { HelperFun2(); }
+// CHECK-OLD-CLASS1-CPP: void Class2::f() {
+// CHECK-OLD-CLASS1-CPP:   HelperFun1();
+
+// RUN: cp 

[PATCH] D27673: [clang-move] Only move used helper declarations.

2016-12-14 Thread Haojian Wu via Phabricator via cfe-commits
hokein added inline comments.



Comment at: clang-move/ClangMove.cpp:492
+  isDefinition(), unless(InMovedClass), InOldCC,
+  anyOf(isStaticStorageClass(), hasParent(namespaceDecl(isAnonymous();
+  auto HelperFuncOrVar = namedDecl(anyOf(functionDecl(IsOldCCHelperDefinition),

ioeric wrote:
> It seems that `isStaticStorageClass` is preventing combining matchers for 
> functions, variables, and classes. Maybe only apply this matcher on 
> `functionDecl` and `varDecl` below, so that helper classes can be matched 
> with the same matcher?
Seems that it is hard to reuse the same matcher for `functionDecl`/`varDecl` 
and `CXXRecordDecl` since `isStaticStorageClass` is not available to  
`CXXRecordDecl`. So we have to match helper classes, helper functions/vars 
separately.  Have cleaned the code to make it clearer.



Comment at: clang-move/ClangMove.cpp:587
+  } else if (const auto *UD = Result.Nodes.getNodeAs(
+ "using_decl_in_anonymous_ns")) {
+MovedDecls.push_back(UD);

ioeric wrote:
> What about using declarations in non-anonymous namespaces in old cc? Do we 
> also move those?
Those using-decls in named namespace are covered in "using_decl" (see above 
`if` statement). Have combined them together.



Comment at: clang-move/ClangMove.cpp:627
+  // If old_header is not specified (only move declarations from old.cc), 
remain
+  // all the helper function declarations in old.cc as UnremovedDecls is empty
+  // in this case.

ioeric wrote:
> Why is `UnremovedDecls` empty in this case btw?
In this case , `UnremovedDeclsInOldHeader`  is empty, there is no way to verify 
unused/used helper declarations.




Comment at: clang-move/ClangMove.cpp:715
+if (!llvm::is_contained(HelperDeclarations, D) ||
+UsedHelperDeclFinder::isUsed(D, HelperDecls))
+  RealNewCCDecls.push_back(D);

ioeric wrote:
> IIUC, this condition makes sure helpers used by helpers are moved. If so, 
> please explain this in the comment.
Yes.



Comment at: clang-move/ClangMove.h:166
   std::vector CCIncludes;
+  // Records all helper declarations (functions/variables declared as static or
+  // declared in anonymous namespace) in old.cc, saving in an AST-visited 
order.

ioeric wrote:
> Is helper class considered here? 
Yes. Have made the comment a bit clearer.



Comment at: clang-move/UsedHelperDeclFinder.h:22
+
+// Call graph for helper declarations in a single translation unit e.g. old.cc.
+// Helper declarations include following types:

ioeric wrote:
> What's the relationship between this and the `CallGraph` class in 
> `clang/Analysis/CallGraph.h`?
There is no relationship between them. We build our own CallGraph class to meet 
our use cases. The CallGraph in `clang/Analysis` only supports function decls, 
and it seems hard to reuse it. The thing we reuse is the `CallGraphNode`. 



Comment at: clang-move/UsedHelperDeclFinder.h:25
+//   * function/variable/class definitions in an anonymous namespace.
+//   * static function/variable definitions in a global namespace.
+//

ioeric wrote:
> What about static decls in named namespaces? I think they can also be helpers 
> right?
Yeah, it is already covered. Corrected the confusing comment.



Comment at: clang-move/UsedHelperDeclFinder.h:49
+  // D's node, including D.
+  llvm::DenseSet getConnectedNodes(const Decl *D) const;
+

ioeric wrote:
> What does `connected` mean in this context? The graph is directed; does this 
> mean reachable from D or to D?
renamed it to `getReachableNodes`.


https://reviews.llvm.org/D27673



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D27673: [clang-move] Only move used helper declarations.

2016-12-14 Thread Haojian Wu via Phabricator via cfe-commits
hokein updated this revision to Diff 81413.
hokein marked 18 inline comments as done.
hokein added a comment.

- Address review comments.
- Add more test cases.


https://reviews.llvm.org/D27673

Files:
  clang-move/CMakeLists.txt
  clang-move/ClangMove.cpp
  clang-move/ClangMove.h
  clang-move/UsedHelperDeclFinder.cpp
  clang-move/UsedHelperDeclFinder.h
  test/clang-move/Inputs/helper_decls_test.cpp
  test/clang-move/Inputs/helper_decls_test.h
  test/clang-move/Inputs/multiple_class_test.cpp
  test/clang-move/move-multiple-classes.cpp
  test/clang-move/move-used-helper-decls.cpp
  unittests/clang-move/ClangMoveTests.cpp

Index: unittests/clang-move/ClangMoveTests.cpp
===
--- unittests/clang-move/ClangMoveTests.cpp
+++ unittests/clang-move/ClangMoveTests.cpp
@@ -73,13 +73,21 @@
   "\n"
   "// comment5\n"
   "// comment5\n"
-  "void Foo::f() { f1(); }\n"
+  "void Foo::f() {\n"
+  "  f1();\n"
+  "  kConstInt1;\n"
+  "  kConstInt2;\n"
+  "  help();\n"
+  "}\n"
   "\n"
   "/\n"
   "// comment //\n"
   "/\n"
   "int Foo::b = 2;\n"
   "int Foo2::f() {\n"
+  "  kConstInt1;\n"
+  "  kConstInt2;\n"
+  "  help();\n"
   "  f1();\n"
   "  return 1;\n"
   "}\n"
@@ -119,6 +127,9 @@
   "}\n"
   "\n"
   "int Foo2::f() {\n"
+  "  kConstInt1;\n"
+  "  kConstInt2;\n"
+  "  help();\n"
   "  f1();\n"
   "  return 1;\n"
   "}\n"
@@ -154,6 +165,7 @@
  "namespace {\n"
  "// comment1.\n"
  "void f1() {}\n"
+ "\n"
  "/// comment2.\n"
  "int kConstInt1 = 0;\n"
  "} // namespace\n"
@@ -170,7 +182,12 @@
  "\n"
  "// comment5\n"
  "// comment5\n"
- "void Foo::f() { f1(); }\n"
+ "void Foo::f() {\n"
+ "  f1();\n"
+ "  kConstInt1;\n"
+ "  kConstInt2;\n"
+ "  help();\n"
+ "}\n"
  "\n"
  "/\n"
  "// comment //\n"
Index: test/clang-move/move-used-helper-decls.cpp
===
--- /dev/null
+++ test/clang-move/move-used-helper-decls.cpp
@@ -0,0 +1,195 @@
+// RUN: mkdir -p %T/used-helper-decls
+// RUN: cp %S/Inputs/helper_decls_test*  %T/used-helper-decls/
+// RUN: cd %T/used-helper-decls
+
+// RUN: clang-move -names="a::Class1" -new_cc=%T/used-helper-decls/new_helper_decls_test.cpp -new_header=%T/used-helper-decls/new_helper_decls_test.h -old_cc=%T/used-helper-decls/helper_decls_test.cpp -old_header=../used-helper-decls/helper_decls_test.h %T/used-helper-decls/helper_decls_test.cpp -- -std=c++11
+// RUN: FileCheck -input-file=%T/used-helper-decls/new_helper_decls_test.cpp -check-prefix=CHECK-NEW-CLASS1-CPP %s
+// RUN: FileCheck -input-file=%T/used-helper-decls/helper_decls_test.cpp -check-prefix=CHECK-OLD-CLASS1-CPP %s
+
+// CHECK-NEW-CLASS1-CPP: #include "{{.*}}new_helper_decls_test.h"
+// CHECK-NEW-CLASS1-CPP-SAME: {{[[:space:]]}}
+// CHECK-NEW-CLASS1-CPP-NEXT: namespace {
+// CHECK-NEW-CLASS1-CPP-NEXT: void HelperFun1() {}
+// CHECK-NEW-CLASS1-CPP-SAME: {{[[:space:]]}}
+// CHECK-NEW-CLASS1-CPP-NEXT: void HelperFun2() { HelperFun1(); }
+// CHECK-NEW-CLASS1-CPP-NEXT: } // namespace
+// CHECK-NEW-CLASS1-CPP-SAME: {{[[:space:]]}}
+// CHECK-NEW-CLASS1-CPP-NEXT: namespace a {
+// CHECK-NEW-CLASS1-CPP-NEXT: void Class1::f() { HelperFun2(); }
+// CHECK-NEW-CLASS1-CPP-NEXT: } // namespace a
+//
+// CHECK-OLD-CLASS1-CPP: void HelperFun1() {}
+// CHECK-OLD-CLASS1-CPP-NOT: void HelperFun2() { HelperFun1(); }
+// CHECK-OLD-CLASS1-CPP-NOT: void Class1::f() { HelperFun2(); }
+// CHECK-OLD-CLASS1-CPP: void Class2::f() {
+// CHECK-OLD-CLASS1-CPP:   HelperFun1();
+
+// RUN: cp %S/Inputs/helper_decls_test*  %T/used-helper-decls/
+// RUN: clang-move -names="a::Class2" -new_cc=%T/used-helper-decls/new_helper_decls_test.cpp -new_header=%T/used-helper-decls/new_helper_decls_test.h 

[PATCH] D27801: [change-namespace] handling templated type aliases correctly.

2016-12-15 Thread Haojian Wu via Phabricator via cfe-commits
hokein accepted this revision.
hokein added a comment.
This revision is now accepted and ready to land.

LGTM.




Comment at: change-namespace/ChangeNamespace.cpp:730
+  // Make `FromDecl` the immediate declaration that `Type` refers to, i.e. if
+  // `Type` is an alias type, we make `FromDecl` the type aias declaration.
+  // Also, don't fix the \p Type if it refers to a type alias decl in the moved

s/aias/alias



Comment at: unittests/change-namespace/ChangeNamespaceTests.cpp:1329
+ "using GG = some_ns::G;\n"
+ "}\n"
+ "namespace na {\n"

Add a trailing `// namespace na`. The same below.


https://reviews.llvm.org/D27801



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D27673: [clang-move] Only move used helper declarations.

2016-12-16 Thread Haojian Wu via Phabricator via cfe-commits
hokein added a comment.

Thanks for the awesome suggestions on the names.  I refactored the patch, hope 
it is clearer now.




Comment at: clang-move/UsedHelperDeclFinder.cpp:30
+  Result = FD;
+  if (const auto *RD = dyn_cast(FD->getParent()))
+Result = RD;

ioeric wrote:
> hokein wrote:
> > ioeric wrote:
> > > Why do you need this? And when is a function's parent a class?
> > This is for the template method in a class.
> Wouldn't that be handled in the next iteration?
> 
> Also, if you do another `getParent` here, do you also need to update `DC`?
Yep, that would be handled in next iteration, removed it.



Comment at: clang-move/UsedHelperDeclFinder.cpp:103
+
+UsedHelperDeclFinder::HelperDeclsSet UsedHelperDeclFinder::getUsedHelperDecls(
+const std::vector ) const {

ioeric wrote:
> hokein wrote:
> > ioeric wrote:
> > > Do you assume that all nodes/decls in the graph are helpers?
> > > 
> > > What if some moved `Decl` refers to unmoved decls?
> > The node in the graph can present moved/unmoved decls and helpers.
> > 
> > > What if some moved Decl refers to unmoved decls?
> > 
> > The graph doesn't contain this information, it only contains the reference  
> > between moved/unmoved decls and helpers. So in this case, we just move the 
> > moved Decl.
> So, IIUC, the graph can contain both non-helper decls and helper decls. In 
> that case, why do we name it `HelperDecl` Graph? And this 
> `getUsedHelperDecls` does not make sense either. Would be less confusing if 
> it is just `getUsedDecls`.
Good point. Renamed to `getUsedDecls`, but I still keep the `Helper` keyword in 
`HelperDeclRefGraph`, because "helper" indicates we use it for helpers.


https://reviews.llvm.org/D27673



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D27520: [clang-tidy] Add check for redundant function pointer dereferences

2016-12-12 Thread Haojian Wu via Phabricator via cfe-commits
hokein accepted this revision.
hokein added a comment.
This revision is now accepted and ready to land.

Nice, the patch looks good to me.




Comment at: 
docs/clang-tidy/checks/readability-redundant-function-ptr-dereference.rst:25
+  int i = (*p)(10, 50);
+

Nit: an extra blank line.


https://reviews.llvm.org/D27520



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D28671: [ASTMatchers] add typeAliasTemplateDecl matcher.

2017-01-13 Thread Haojian Wu via Phabricator via cfe-commits
hokein added a comment.

You also need to add a new generated document 
(`docs/LibASTMatchersReference.html`) for that. Please run 
`clang/docs/tools/dump_ast_matchers.py`, it will do the stuff for you.


https://reviews.llvm.org/D28671



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D27920: [find-all-symbols] Index partial template specializations.

2017-01-11 Thread Haojian Wu via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL291669: [find-all-symbols] Index partial template 
specializations. (authored by hokein).

Changed prior to commit:
  https://reviews.llvm.org/D27920?vs=83944=83951#toc

Repository:
  rL LLVM

https://reviews.llvm.org/D27920

Files:
  clang-tools-extra/trunk/include-fixer/find-all-symbols/FindAllSymbols.cpp
  
clang-tools-extra/trunk/unittests/include-fixer/find-all-symbols/FindAllSymbolsTests.cpp


Index: 
clang-tools-extra/trunk/unittests/include-fixer/find-all-symbols/FindAllSymbolsTests.cpp
===
--- 
clang-tools-extra/trunk/unittests/include-fixer/find-all-symbols/FindAllSymbolsTests.cpp
+++ 
clang-tools-extra/trunk/unittests/include-fixer/find-all-symbols/FindAllSymbolsTests.cpp
@@ -229,6 +229,28 @@
   EXPECT_TRUE(hasSymbol(Symbol));
 }
 
+TEST_F(FindAllSymbolsTest, DontIgnoreTemplatePartialSpecialization) {
+  static const char Code[] = R"(
+  template class Class; // undefined
+  template
+  class Class {
+  };
+
+  template void f() {};
+  template<> void f() {};
+  )";
+  runFindAllSymbols(Code);
+  SymbolInfo Symbol =
+  SymbolInfo("Class", SymbolInfo::SymbolKind::Class, HeaderName, 4, {});
+  EXPECT_TRUE(hasSymbol(Symbol));
+  Symbol =
+  SymbolInfo("f", SymbolInfo::SymbolKind::Function, HeaderName, 7, {});
+  EXPECT_TRUE(hasSymbol(Symbol));
+  Symbol =
+  SymbolInfo("f", SymbolInfo::SymbolKind::Function, HeaderName, 8, {});
+  EXPECT_FALSE(hasSymbol(Symbol));
+}
+
 TEST_F(FindAllSymbolsTest, FunctionSymbols) {
   static const char Code[] = R"(
   namespace na {
Index: clang-tools-extra/trunk/include-fixer/find-all-symbols/FindAllSymbols.cpp
===
--- clang-tools-extra/trunk/include-fixer/find-all-symbols/FindAllSymbols.cpp
+++ clang-tools-extra/trunk/include-fixer/find-all-symbols/FindAllSymbols.cpp
@@ -32,6 +32,18 @@
   return false;
 }
 
+AST_POLYMORPHIC_MATCHER(isFullySpecialized,
+AST_POLYMORPHIC_SUPPORTED_TYPES(FunctionDecl, VarDecl,
+CXXRecordDecl)) {
+  if (Node.getTemplateSpecializationKind() == TSK_ExplicitSpecialization) {
+bool IsPartialSpecialization =
+llvm::isa(Node) ||
+llvm::isa(Node);
+return !IsPartialSpecialization;
+  }
+  return false;
+}
+
 std::vector GetContexts(const NamedDecl *ND) {
   std::vector Contexts;
   for (const auto *Context = ND->getDeclContext(); Context;
@@ -126,8 +138,7 @@
   auto CCMatcher =
   allOf(HasNSOrTUCtxMatcher, unless(IsInSpecialization),
 unless(ast_matchers::isTemplateInstantiation()),
-unless(isInstantiated()), 
unless(classTemplateSpecializationDecl()),
-unless(isExplicitTemplateSpecialization()));
+unless(isInstantiated()), unless(isFullySpecialized()));
 
   // Matchers specific to code in extern "C" {...}.
   auto ExternCMatcher = hasDeclContext(linkageSpecDecl());
@@ -156,8 +167,7 @@
 
   // Matchers for C++ record declarations.
   auto CxxRecordDecl =
-  cxxRecordDecl(CommonFilter, CCMatcher, isDefinition(),
-unless(isExplicitTemplateSpecialization()));
+  cxxRecordDecl(CommonFilter, CCMatcher, isDefinition());
   MatchFinder->addMatcher(CxxRecordDecl.bind("decl"), this);
 
   // Matchers for function declarations.


Index: clang-tools-extra/trunk/unittests/include-fixer/find-all-symbols/FindAllSymbolsTests.cpp
===
--- clang-tools-extra/trunk/unittests/include-fixer/find-all-symbols/FindAllSymbolsTests.cpp
+++ clang-tools-extra/trunk/unittests/include-fixer/find-all-symbols/FindAllSymbolsTests.cpp
@@ -229,6 +229,28 @@
   EXPECT_TRUE(hasSymbol(Symbol));
 }
 
+TEST_F(FindAllSymbolsTest, DontIgnoreTemplatePartialSpecialization) {
+  static const char Code[] = R"(
+  template class Class; // undefined
+  template
+  class Class {
+  };
+
+  template void f() {};
+  template<> void f() {};
+  )";
+  runFindAllSymbols(Code);
+  SymbolInfo Symbol =
+  SymbolInfo("Class", SymbolInfo::SymbolKind::Class, HeaderName, 4, {});
+  EXPECT_TRUE(hasSymbol(Symbol));
+  Symbol =
+  SymbolInfo("f", SymbolInfo::SymbolKind::Function, HeaderName, 7, {});
+  EXPECT_TRUE(hasSymbol(Symbol));
+  Symbol =
+  SymbolInfo("f", SymbolInfo::SymbolKind::Function, HeaderName, 8, {});
+  EXPECT_FALSE(hasSymbol(Symbol));
+}
+
 TEST_F(FindAllSymbolsTest, FunctionSymbols) {
   static const char Code[] = R"(
   namespace na {
Index: clang-tools-extra/trunk/include-fixer/find-all-symbols/FindAllSymbols.cpp
===
--- clang-tools-extra/trunk/include-fixer/find-all-symbols/FindAllSymbols.cpp
+++ 

[PATCH] D27920: [find-all-symbols] Index partial template specializations.

2017-01-11 Thread Haojian Wu via Phabricator via cfe-commits
hokein updated this revision to Diff 83944.
hokein marked an inline comment as done.
hokein added a comment.

Fix code style nit.


https://reviews.llvm.org/D27920

Files:
  include-fixer/find-all-symbols/FindAllSymbols.cpp
  unittests/include-fixer/find-all-symbols/FindAllSymbolsTests.cpp


Index: unittests/include-fixer/find-all-symbols/FindAllSymbolsTests.cpp
===
--- unittests/include-fixer/find-all-symbols/FindAllSymbolsTests.cpp
+++ unittests/include-fixer/find-all-symbols/FindAllSymbolsTests.cpp
@@ -229,6 +229,28 @@
   EXPECT_TRUE(hasSymbol(Symbol));
 }
 
+TEST_F(FindAllSymbolsTest, DontIgnoreTemplatePartialSpecialization) {
+  static const char Code[] = R"(
+  template class Class; // undefined
+  template
+  class Class {
+  };
+
+  template void f() {};
+  template<> void f() {};
+  )";
+  runFindAllSymbols(Code);
+  SymbolInfo Symbol =
+  SymbolInfo("Class", SymbolInfo::SymbolKind::Class, HeaderName, 4, {});
+  EXPECT_TRUE(hasSymbol(Symbol));
+  Symbol =
+  SymbolInfo("f", SymbolInfo::SymbolKind::Function, HeaderName, 7, {});
+  EXPECT_TRUE(hasSymbol(Symbol));
+  Symbol =
+  SymbolInfo("f", SymbolInfo::SymbolKind::Function, HeaderName, 8, {});
+  EXPECT_FALSE(hasSymbol(Symbol));
+}
+
 TEST_F(FindAllSymbolsTest, FunctionSymbols) {
   static const char Code[] = R"(
   namespace na {
Index: include-fixer/find-all-symbols/FindAllSymbols.cpp
===
--- include-fixer/find-all-symbols/FindAllSymbols.cpp
+++ include-fixer/find-all-symbols/FindAllSymbols.cpp
@@ -32,6 +32,18 @@
   return false;
 }
 
+AST_POLYMORPHIC_MATCHER(isFullySpecialized,
+AST_POLYMORPHIC_SUPPORTED_TYPES(FunctionDecl, VarDecl,
+CXXRecordDecl)) {
+  if (Node.getTemplateSpecializationKind() == TSK_ExplicitSpecialization) {
+bool IsPartialSpecialization =
+llvm::isa(Node) ||
+llvm::isa(Node);
+return !IsPartialSpecialization;
+  }
+  return false;
+}
+
 std::vector GetContexts(const NamedDecl *ND) {
   std::vector Contexts;
   for (const auto *Context = ND->getDeclContext(); Context;
@@ -126,8 +138,7 @@
   auto CCMatcher =
   allOf(HasNSOrTUCtxMatcher, unless(IsInSpecialization),
 unless(ast_matchers::isTemplateInstantiation()),
-unless(isInstantiated()), 
unless(classTemplateSpecializationDecl()),
-unless(isExplicitTemplateSpecialization()));
+unless(isInstantiated()), unless(isFullySpecialized()));
 
   // Matchers specific to code in extern "C" {...}.
   auto ExternCMatcher = hasDeclContext(linkageSpecDecl());
@@ -156,8 +167,7 @@
 
   // Matchers for C++ record declarations.
   auto CxxRecordDecl =
-  cxxRecordDecl(CommonFilter, CCMatcher, isDefinition(),
-unless(isExplicitTemplateSpecialization()));
+  cxxRecordDecl(CommonFilter, CCMatcher, isDefinition());
   MatchFinder->addMatcher(CxxRecordDecl.bind("decl"), this);
 
   // Matchers for function declarations.


Index: unittests/include-fixer/find-all-symbols/FindAllSymbolsTests.cpp
===
--- unittests/include-fixer/find-all-symbols/FindAllSymbolsTests.cpp
+++ unittests/include-fixer/find-all-symbols/FindAllSymbolsTests.cpp
@@ -229,6 +229,28 @@
   EXPECT_TRUE(hasSymbol(Symbol));
 }
 
+TEST_F(FindAllSymbolsTest, DontIgnoreTemplatePartialSpecialization) {
+  static const char Code[] = R"(
+  template class Class; // undefined
+  template
+  class Class {
+  };
+
+  template void f() {};
+  template<> void f() {};
+  )";
+  runFindAllSymbols(Code);
+  SymbolInfo Symbol =
+  SymbolInfo("Class", SymbolInfo::SymbolKind::Class, HeaderName, 4, {});
+  EXPECT_TRUE(hasSymbol(Symbol));
+  Symbol =
+  SymbolInfo("f", SymbolInfo::SymbolKind::Function, HeaderName, 7, {});
+  EXPECT_TRUE(hasSymbol(Symbol));
+  Symbol =
+  SymbolInfo("f", SymbolInfo::SymbolKind::Function, HeaderName, 8, {});
+  EXPECT_FALSE(hasSymbol(Symbol));
+}
+
 TEST_F(FindAllSymbolsTest, FunctionSymbols) {
   static const char Code[] = R"(
   namespace na {
Index: include-fixer/find-all-symbols/FindAllSymbols.cpp
===
--- include-fixer/find-all-symbols/FindAllSymbols.cpp
+++ include-fixer/find-all-symbols/FindAllSymbols.cpp
@@ -32,6 +32,18 @@
   return false;
 }
 
+AST_POLYMORPHIC_MATCHER(isFullySpecialized,
+AST_POLYMORPHIC_SUPPORTED_TYPES(FunctionDecl, VarDecl,
+CXXRecordDecl)) {
+  if (Node.getTemplateSpecializationKind() == TSK_ExplicitSpecialization) {
+bool IsPartialSpecialization =
+llvm::isa(Node) ||
+llvm::isa(Node);
+return !IsPartialSpecialization;
+  }
+  return false;

[PATCH] D27302: [change-namespace] don't generate replacements for files that don't match file pattern.

2016-12-01 Thread Haojian Wu via Phabricator via cfe-commits
hokein accepted this revision.
hokein added a comment.
This revision is now accepted and ready to land.

LGTM with two nits.




Comment at: change-namespace/ChangeNamespace.cpp:786
+  for (auto  : FileToReplacements)
+if (!FilePatternRE.match(Entry.first))
+  Entry.second.clear();

How about creating `FilePatternRE` from `FilePattern` here? So that you don't 
need save `FilePatternRE` as a member variable.



Comment at: test/change-namespace/Inputs/macro.h:1
+#define USING using na::nc::X

For the simple file like this, I would use `echo "#define USING using 
na::nc::X" > macro.h` in `macro.cc` instead of creating a new file.


https://reviews.llvm.org/D27302



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D27208: [change-namespace] fix non-calling function references.

2016-11-29 Thread Haojian Wu via Phabricator via cfe-commits
hokein accepted this revision.
hokein added a comment.
This revision is now accepted and ready to land.

LGTM with few nits.




Comment at: change-namespace/ChangeNamespace.cpp:434
+assert(Func);
+const Decl *Context = Result.Nodes.getNodeAs("dc");
+assert(Context && "Empty decl context.");

auto



Comment at: change-namespace/ChangeNamespace.cpp:449
   return;
-const clang::Decl *Context = Result.Nodes.getNodeAs("dc");
+const Decl *Context = Result.Nodes.getNodeAs("dc");
 assert(Context && "Empty decl context.");

auto.



Comment at: change-namespace/ChangeNamespace.cpp:713
+const DeclRefExpr *Ref) {
+SourceRange RefRange = Ref->getSourceRange();
+replaceQualifiedSymbolInDeclContext(Result, UseContext, 
RefRange.getBegin(),

nits: incorrect indentation. Should be two space.


https://reviews.llvm.org/D27208



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D27248: [clang-tidy] Do not trigger unnecessary-value-param check on methods marked as final

2016-11-30 Thread Haojian Wu via Phabricator via cfe-commits
hokein accepted this revision.
hokein added a comment.
This revision is now accepted and ready to land.

LGTM.


Repository:
  rL LLVM

https://reviews.llvm.org/D27248



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D21298: [Clang-tidy] delete null check

2016-12-01 Thread Haojian Wu via Phabricator via cfe-commits
hokein accepted this revision.
hokein added a reviewer: hokein.
hokein added a comment.

It looks good to me, but you'd better wait for the approval from @aaron.ballman.




Comment at: clang-tidy/readability/DeleteNullPointerCheck.cpp:55
+  "'if' statement is unnecessary; deleting null pointer has no effect");
+  if (!IfWithDelete->getElse()) {
+std::string ReplacementText = Lexer::getSourceText(

I would use an early return `if (IfWithDelete->getElse()) return` here.


https://reviews.llvm.org/D21298



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D28315: Update tools to use new getStyle API

2017-01-05 Thread Haojian Wu via Phabricator via cfe-commits
hokein added a comment.

In https://reviews.llvm.org/D28315#636821, @amaiorano wrote:

> Is there a way to run tests without ninja? I'm on Windows. If not, I'll use 
> my Linux VM.


It is not related to the build system. There should be a `check-clang-tools` 
project, you can run tests by building it.  For example, if you are using make, 
just run `make check-clang-tools`; If you are using Visual Studio, build the 
`check-clang-tools` project.


https://reviews.llvm.org/D28315



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D28279: [clang-move] Support moving type alias declarations.

2017-01-04 Thread Haojian Wu via Phabricator via cfe-commits
hokein created this revision.
hokein added a reviewer: ioeric.
hokein added a subscriber: cfe-commits.

https://reviews.llvm.org/D28279

Files:
  clang-move/ClangMove.cpp
  test/clang-move/Inputs/type_alias.h
  test/clang-move/move-type-alias.cpp
  unittests/clang-move/ClangMoveTests.cpp

Index: unittests/clang-move/ClangMoveTests.cpp
===
--- unittests/clang-move/ClangMoveTests.cpp
+++ unittests/clang-move/ClangMoveTests.cpp
@@ -365,25 +365,6 @@
   }
 }
 
-TEST(ClangMove, IgnoreUnsupportedKindsAndMoveAll) {
-  const char Code[] = "#include \"foo.h\"\nint A::f() { return 0; }";
-  std::vector TestHeaders = {
-  "typedef int Int;\nclass A {\npublic:\n  int f();\n};\n",
-  "using Int = int;\nclass A {\npublic:\n  int f();\n};\n",
-  };
-  move::MoveDefinitionSpec Spec;
-  Spec.Names.push_back("A");
-  Spec.OldHeader = "foo.h";
-  Spec.OldCC = "foo.cc";
-  Spec.NewHeader = "new_foo.h";
-  Spec.NewCC = "new_foo.cc";
-  for (const auto  : TestHeaders) {
-auto Results = runClangMoveOnCode(Spec, Header.c_str(), Code);
-EXPECT_EQ(Header, Results[Spec.NewHeader]);
-EXPECT_EQ("", Results[Spec.OldHeader]);
-  }
-}
-
 TEST(ClangMove, MacroInFunction) {
   const char TestHeader[] = "#define INT int\n"
 "class A {\npublic:\n  int f();\n};\n"
Index: test/clang-move/move-type-alias.cpp
===
--- /dev/null
+++ test/clang-move/move-type-alias.cpp
@@ -0,0 +1,52 @@
+// RUN: mkdir -p %T/move-type-alias
+// RUN: cp %S/Inputs/type_alias.h  %T/move-type-alias/type_alias.h
+// RUN: echo '#include "type_alias.h"' > %T/move-type-alias/type_alias.cpp
+// RUN: cd %T/move-type-alias
+//
+// -
+// Test moving typedef declarations.
+// -
+// RUN: clang-move -names="Int1" -new_cc=%T/move-type-alias/new_test.cpp -new_header=%T/move-type-alias/new_test.h -old_cc=%T/move-type-alias/type_alias.cpp -old_header=%T/move-type-alias/type_alias.h %T/move-type-alias/type_alias.cpp -- -std=c++11
+// RUN: FileCheck -input-file=%T/move-type-alias/new_test.h -check-prefix=CHECK-NEW-TEST-H-CASE1 %s
+// RUN: FileCheck -input-file=%T/move-type-alias/type_alias.h -check-prefix=CHECK-OLD-TEST-H-CASE1 %s
+
+// CHECK-NEW-TEST-H-CASE1: typedef int Int1;
+
+// CHECK-OLD-TEST-H-CASE1-NOT: typedef int Int1;
+
+
+// -
+// Test moving type alias declarations.
+// -
+// RUN: cp %S/Inputs/type_alias.h  %T/move-type-alias/type_alias.h
+// RUN: echo '#include "type_alias.h"' > %T/move-type-alias/type_alias.cpp
+// RUN: clang-move -names="Int2" -new_cc=%T/move-type-alias/new_test.cpp -new_header=%T/move-type-alias/new_test.h -old_cc=%T/move-type-alias/type_alias.cpp -old_header=%T/move-type-alias/type_alias.h %T/move-type-alias/type_alias.cpp -- -std=c++11
+// RUN: FileCheck -input-file=%T/move-type-alias/new_test.h -check-prefix=CHECK-NEW-TEST-H-CASE2 %s
+// RUN: FileCheck -input-file=%T/move-type-alias/type_alias.h -check-prefix=CHECK-OLD-TEST-H-CASE2 %s
+
+// CHECK-NEW-TEST-H-CASE2: using Int2 = int;
+
+// CHECK-OLD-TEST-H-CASE2-NOT: using Int2 = int;
+
+
+// -
+// Test moving template type alias declarations.
+// -
+// RUN: cp %S/Inputs/type_alias.h  %T/move-type-alias/type_alias.h
+// RUN: echo '#include "type_alias.h"' > %T/move-type-alias/type_alias.cpp
+// RUN: clang-move -names="B" -new_cc=%T/move-type-alias/new_test.cpp -new_header=%T/move-type-alias/new_test.h -old_cc=%T/move-type-alias/type_alias.cpp -old_header=%T/move-type-alias/type_alias.h %T/move-type-alias/type_alias.cpp -- -std=c++11
+// RUN: FileCheck -input-file=%T/move-type-alias/new_test.h -check-prefix=CHECK-OLD-TEST-H-CASE3 %s
+
+// CHECK-NEW-TEST-H-CASE3: template using B = A;
+// CHECK-OLD-TEST-H-CASE3-NOT: template using B = A;
+
+
+// -
+// Test not moving class-insided typedef declarations.
+// -
+// RUN: cp %S/Inputs/type_alias.h  %T/move-type-alias/type_alias.h
+// RUN: echo '#include "type_alias.h"' > %T/move-type-alias/type_alias.cpp
+// RUN: clang-move -names="C::Int3" -new_cc=%T/move-type-alias/new_test.cpp -new_header=%T/move-type-alias/new_test.h -old_cc=%T/move-type-alias/type_alias.cpp -old_header=%T/move-type-alias/type_alias.h %T/move-type-alias/type_alias.cpp -- -std=c++11
+// RUN: FileCheck -input-file=%T/move-type-alias/new_test.h -allow-empty -check-prefix=CHECK-EMPTY %s
+
+// CHECK-EMPTY: {{^}}{{$}}
Index: 

[PATCH] D27673: [clang-move] Only move used helper declarations.

2017-01-03 Thread Haojian Wu via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL290873: [clang-move] Only move used helper declarations. 
(authored by hokein).

Changed prior to commit:
  https://reviews.llvm.org/D27673?vs=82804=82847#toc

Repository:
  rL LLVM

https://reviews.llvm.org/D27673

Files:
  clang-tools-extra/trunk/clang-move/CMakeLists.txt
  clang-tools-extra/trunk/clang-move/ClangMove.cpp
  clang-tools-extra/trunk/clang-move/ClangMove.h
  clang-tools-extra/trunk/clang-move/HelperDeclRefGraph.cpp
  clang-tools-extra/trunk/clang-move/HelperDeclRefGraph.h
  clang-tools-extra/trunk/test/clang-move/Inputs/helper_decls_test.cpp
  clang-tools-extra/trunk/test/clang-move/Inputs/helper_decls_test.h
  clang-tools-extra/trunk/test/clang-move/Inputs/multiple_class_test.cpp
  clang-tools-extra/trunk/test/clang-move/move-multiple-classes.cpp
  clang-tools-extra/trunk/test/clang-move/move-used-helper-decls.cpp
  clang-tools-extra/trunk/unittests/clang-move/ClangMoveTests.cpp

Index: clang-tools-extra/trunk/test/clang-move/Inputs/multiple_class_test.cpp
===
--- clang-tools-extra/trunk/test/clang-move/Inputs/multiple_class_test.cpp
+++ clang-tools-extra/trunk/test/clang-move/Inputs/multiple_class_test.cpp
@@ -15,7 +15,7 @@
 using a::Move1;
 using namespace a;
 static int k = 0;
-} // anonymous namespace
+} // namespace
 
 namespace b {
 using a::Move1;
@@ -34,19 +34,19 @@
 }
 
 int Move4::f() {
-  return 0;
+  return k;
 }
 
 int EnclosingMove5::a = 1;
 
 int EnclosingMove5::Nested::f() {
-  return 0;
+  return g;
 }
 
 int EnclosingMove5::Nested::b = 1;
 
 int NoMove::f() {
   static int F = 0;
-  return 0;
+  return g;
 }
 } // namespace c
Index: clang-tools-extra/trunk/test/clang-move/Inputs/helper_decls_test.h
===
--- clang-tools-extra/trunk/test/clang-move/Inputs/helper_decls_test.h
+++ clang-tools-extra/trunk/test/clang-move/Inputs/helper_decls_test.h
@@ -0,0 +1,35 @@
+namespace a {
+class Class1 {
+  void f();
+};
+
+class Class2 {
+  void f();
+};
+
+class Class3 {
+  void f();
+};
+
+class Class4 {
+  void f();
+};
+
+class Class5 {
+  void f();
+};
+
+class Class6 {
+  int f();
+};
+
+class Class7 {
+  int f();
+  int g();
+};
+
+void Fun1();
+
+inline void Fun2() {}
+
+} // namespace a
Index: clang-tools-extra/trunk/test/clang-move/Inputs/helper_decls_test.cpp
===
--- clang-tools-extra/trunk/test/clang-move/Inputs/helper_decls_test.cpp
+++ clang-tools-extra/trunk/test/clang-move/Inputs/helper_decls_test.cpp
@@ -0,0 +1,78 @@
+#include "helper_decls_test.h"
+
+namespace {
+class HelperC1 {
+public:
+  static int I;
+};
+
+int HelperC1::I = 0;
+
+class HelperC2 {};
+
+class HelperC3 {
+ public:
+  static int I;
+};
+
+int HelperC3::I = 0;
+
+void HelperFun1() {}
+
+void HelperFun2() { HelperFun1(); }
+
+const int K1 = 1;
+} // namespace
+
+static const int K2 = 2;
+static void HelperFun3() { K2; }
+
+namespace a {
+
+static const int K3 = 3;
+static const int K4 = HelperC3::I;
+static const int K5 = 5;
+static const int K6 = 6;
+
+static void HelperFun4() {}
+static void HelperFun6() {}
+
+void Class1::f() { HelperFun2(); }
+
+void Class2::f() {
+  HelperFun1();
+  HelperFun3();
+}
+
+void Class3::f() { HelperC1::I; }
+
+void Class4::f() { HelperC2 c2; }
+
+void Class5::f() {
+  int Result = K1 + K2 + K3;
+  HelperFun4();
+}
+
+int Class6::f() {
+  int R = K4;
+  return R;
+}
+
+int Class7::f() {
+  int R = K6;
+  return R;
+}
+
+int Class7::g() {
+  HelperFun6();
+  return 1;
+}
+
+static int HelperFun5() {
+  int R = K5;
+  return R;
+}
+
+void Fun1() { HelperFun5(); }
+
+} // namespace a
Index: clang-tools-extra/trunk/test/clang-move/move-multiple-classes.cpp
===
--- clang-tools-extra/trunk/test/clang-move/move-multiple-classes.cpp
+++ clang-tools-extra/trunk/test/clang-move/move-multiple-classes.cpp
@@ -25,17 +25,16 @@
 // CHECK-OLD-TEST-CPP: namespace {
 // CHECK-OLD-TEST-CPP: using a::Move1;
 // CHECK-OLD-TEST-CPP: using namespace a;
-// CHECK-OLD-TEST-CPP: static int k = 0;
-// CHECK-OLD-TEST-CPP: } // anonymous namespace
+// CHECK-OLD-TEST-CPP: } // namespace
 // CHECK-OLD-TEST-CPP: namespace b {
 // CHECK-OLD-TEST-CPP: using a::Move1;
 // CHECK-OLD-TEST-CPP: using namespace a;
 // CHECK-OLD-TEST-CPP: using T = a::Move1;
 // CHECK-OLD-TEST-CPP: } // namespace b
 // CHECK-OLD-TEST-CPP: namespace c {
 // CHECK-OLD-TEST-CPP: int NoMove::f() {
 // CHECK-OLD-TEST-CPP:   static int F = 0;
-// CHECK-OLD-TEST-CPP:   return 0;
+// CHECK-OLD-TEST-CPP:   return g;
 // CHECK-OLD-TEST-CPP: }
 // CHECK-OLD-TEST-CPP: } // namespace c
 
@@ -85,7 +84,7 @@
 // CHECK-NEW-TEST-CPP: using a::Move1;
 // CHECK-NEW-TEST-CPP: using namespace a;
 // CHECK-NEW-TEST-CPP: static int k = 0;
-// CHECK-NEW-TEST-CPP: } // anonymous namespace
+// 

[PATCH] D28228: [clang-move] Support moving enum declarations.

2017-01-03 Thread Haojian Wu via Phabricator via cfe-commits
hokein created this revision.
hokein added a reviewer: ioeric.
hokein added a subscriber: cfe-commits.

https://reviews.llvm.org/D28228

Files:
  clang-move/ClangMove.cpp
  test/clang-move/Inputs/enum.h
  test/clang-move/move-enum-decl.cpp
  unittests/clang-move/ClangMoveTests.cpp

Index: unittests/clang-move/ClangMoveTests.cpp
===
--- unittests/clang-move/ClangMoveTests.cpp
+++ unittests/clang-move/ClangMoveTests.cpp
@@ -370,7 +370,6 @@
   std::vector TestHeaders = {
   "typedef int Int;\nclass A {\npublic:\n  int f();\n};\n",
   "using Int = int;\nclass A {\npublic:\n  int f();\n};\n",
-  "enum Color { RED };\nclass A {\npublic:\n  int f();\n};\n",
   };
   move::MoveDefinitionSpec Spec;
   Spec.Names.push_back("A");
Index: test/clang-move/move-enum-decl.cpp
===
--- /dev/null
+++ test/clang-move/move-enum-decl.cpp
@@ -0,0 +1,44 @@
+// RUN: mkdir -p %T/move-enum
+// RUN: cp %S/Inputs/enum.h  %T/move-enum/enum.h
+// RUN: echo '#include "enum.h"' > %T/move-enum/enum.cpp
+// RUN: cd %T/move-enum
+//
+// -
+// Test moving enum declarations.
+// -
+// RUN: clang-move -names="a::E1" -new_cc=%T/move-enum/new_test.cpp -new_header=%T/move-enum/new_test.h -old_cc=%T/move-enum/enum.cpp -old_header=%T/move-enum/enum.h %T/move-enum/enum.cpp -- -std=c++11
+// RUN: FileCheck -input-file=%T/move-enum/new_test.h -check-prefix=CHECK-NEW-TEST-H-CASE1 %s
+// RUN: FileCheck -input-file=%T/move-enum/enum.h -check-prefix=CHECK-OLD-TEST-H-CASE1 %s
+//
+// CHECK-NEW-TEST-H-CASE1: namespace a {
+// CHECK-NEW-TEST-H-CASE1-NEXT: enum E1 { Green, Red };
+// CHECK-NEW-TEST-H-CASE1-NEXT: }
+
+// CHECK-OLD-TEST-H-CASE1-NOT: enum E1 { Green, Red };
+
+
+// -
+// Test moving scoped enum declarations.
+// -
+// RUN: cp %S/Inputs/enum.h  %T/move-enum/enum.h
+// RUN: echo '#include "enum.h"' > %T/move-enum/enum.cpp
+// RUN: clang-move -names="a::E2" -new_cc=%T/move-enum/new_test.cpp -new_header=%T/move-enum/new_test.h -old_cc=%T/move-enum/enum.cpp -old_header=%T/move-enum/enum.h %T/move-enum/enum.cpp -- -std=c++11
+// RUN: FileCheck -input-file=%T/move-enum/new_test.h -check-prefix=CHECK-NEW-TEST-H-CASE2 %s
+// RUN: FileCheck -input-file=%T/move-enum/enum.h -check-prefix=CHECK-OLD-TEST-H-CASE2 %s
+
+// CHECK-NEW-TEST-H-CASE2: namespace a {
+// CHECK-NEW-TEST-H-CASE2-NEXT: enum class E2 { Yellow };
+// CHECK-NEW-TEST-H-CASE2-NEXT: }
+
+// CHECK-OLD-TEST-H-CASE2-NOT: enum class E2 { Yellow };
+
+
+// -
+// Test not moving class-insided enum declarations.
+// -
+// RUN: cp %S/Inputs/enum.h  %T/move-enum/enum.h
+// RUN: echo '#include "enum.h"' > %T/move-enum/enum.cpp
+// RUN: clang-move -names="a::C::E3" -new_cc=%T/move-enum/new_test.cpp -new_header=%T/move-enum/new_test.h -old_cc=%T/move-enum/enum.cpp -old_header=%T/move-enum/enum.h %T/move-enum/enum.cpp -- -std=c++11
+// RUN: FileCheck -input-file=%T/move-enum/new_test.h -allow-empty -check-prefix=CHECK-EMPTY %s
+
+// CHECK-EMPTY: {{^}}{{$}}
Index: test/clang-move/Inputs/enum.h
===
--- /dev/null
+++ test/clang-move/Inputs/enum.h
@@ -0,0 +1,9 @@
+namespace a {
+enum E1 { Green, Red };
+
+enum class E2 { Yellow };
+
+class C {
+  enum E3 { Blue };
+};
+} // namespace a
Index: clang-move/ClangMove.cpp
===
--- clang-move/ClangMove.cpp
+++ clang-move/ClangMove.cpp
@@ -160,6 +160,23 @@
   ClangMoveTool *MoveTool;
 };
 
+class EnumDeclarationMatch : public MatchFinder::MatchCallback {
+public:
+  explicit EnumDeclarationMatch(ClangMoveTool *MoveTool)
+  : MoveTool(MoveTool) {}
+
+  void run(const MatchFinder::MatchResult ) override {
+const auto *ED = Result.Nodes.getNodeAs("enum");
+assert(ED);
+MoveTool->getMovedDecls().push_back(ED);
+MoveTool->getUnremovedDeclsInOldHeader().erase(ED);
+MoveTool->addRemovedDecl(ED);
+  }
+
+private:
+  ClangMoveTool *MoveTool;
+};
+
 class ClassDeclarationMatch : public MatchFinder::MatchCallback {
 public:
   explicit ClassDeclarationMatch(ClangMoveTool *MoveTool)
@@ -449,6 +466,8 @@
   auto InOldFiles = anyOf(InOldHeader, InOldCC);
   auto ForwardDecls =
   cxxRecordDecl(unless(anyOf(isImplicit(), isDefinition(;
+  auto TopLevelDecl =
+  hasDeclContext(anyOf(namespaceDecl(), translationUnitDecl()));
 
   //
   // Matchers for old header
@@ 

[PATCH] D28228: [clang-move] Support moving enum declarations.

2017-01-03 Thread Haojian Wu via Phabricator via cfe-commits
hokein updated this revision to Diff 82872.
hokein marked an inline comment as done.
hokein added a comment.

Address review comment.


https://reviews.llvm.org/D28228

Files:
  clang-move/ClangMove.cpp
  clang-move/ClangMove.h
  test/clang-move/Inputs/enum.h
  test/clang-move/move-enum-decl.cpp
  unittests/clang-move/ClangMoveTests.cpp

Index: unittests/clang-move/ClangMoveTests.cpp
===
--- unittests/clang-move/ClangMoveTests.cpp
+++ unittests/clang-move/ClangMoveTests.cpp
@@ -370,7 +370,6 @@
   std::vector TestHeaders = {
   "typedef int Int;\nclass A {\npublic:\n  int f();\n};\n",
   "using Int = int;\nclass A {\npublic:\n  int f();\n};\n",
-  "enum Color { RED };\nclass A {\npublic:\n  int f();\n};\n",
   };
   move::MoveDefinitionSpec Spec;
   Spec.Names.push_back("A");
Index: test/clang-move/move-enum-decl.cpp
===
--- /dev/null
+++ test/clang-move/move-enum-decl.cpp
@@ -0,0 +1,44 @@
+// RUN: mkdir -p %T/move-enum
+// RUN: cp %S/Inputs/enum.h  %T/move-enum/enum.h
+// RUN: echo '#include "enum.h"' > %T/move-enum/enum.cpp
+// RUN: cd %T/move-enum
+//
+// -
+// Test moving enum declarations.
+// -
+// RUN: clang-move -names="a::E1" -new_cc=%T/move-enum/new_test.cpp -new_header=%T/move-enum/new_test.h -old_cc=%T/move-enum/enum.cpp -old_header=%T/move-enum/enum.h %T/move-enum/enum.cpp -- -std=c++11
+// RUN: FileCheck -input-file=%T/move-enum/new_test.h -check-prefix=CHECK-NEW-TEST-H-CASE1 %s
+// RUN: FileCheck -input-file=%T/move-enum/enum.h -check-prefix=CHECK-OLD-TEST-H-CASE1 %s
+//
+// CHECK-NEW-TEST-H-CASE1: namespace a {
+// CHECK-NEW-TEST-H-CASE1-NEXT: enum E1 { Green, Red };
+// CHECK-NEW-TEST-H-CASE1-NEXT: }
+
+// CHECK-OLD-TEST-H-CASE1-NOT: enum E1 { Green, Red };
+
+
+// -
+// Test moving scoped enum declarations.
+// -
+// RUN: cp %S/Inputs/enum.h  %T/move-enum/enum.h
+// RUN: echo '#include "enum.h"' > %T/move-enum/enum.cpp
+// RUN: clang-move -names="a::E2" -new_cc=%T/move-enum/new_test.cpp -new_header=%T/move-enum/new_test.h -old_cc=%T/move-enum/enum.cpp -old_header=%T/move-enum/enum.h %T/move-enum/enum.cpp -- -std=c++11
+// RUN: FileCheck -input-file=%T/move-enum/new_test.h -check-prefix=CHECK-NEW-TEST-H-CASE2 %s
+// RUN: FileCheck -input-file=%T/move-enum/enum.h -check-prefix=CHECK-OLD-TEST-H-CASE2 %s
+
+// CHECK-NEW-TEST-H-CASE2: namespace a {
+// CHECK-NEW-TEST-H-CASE2-NEXT: enum class E2 { Yellow };
+// CHECK-NEW-TEST-H-CASE2-NEXT: }
+
+// CHECK-OLD-TEST-H-CASE2-NOT: enum class E2 { Yellow };
+
+
+// -
+// Test not moving class-insided enum declarations.
+// -
+// RUN: cp %S/Inputs/enum.h  %T/move-enum/enum.h
+// RUN: echo '#include "enum.h"' > %T/move-enum/enum.cpp
+// RUN: clang-move -names="a::C::E3" -new_cc=%T/move-enum/new_test.cpp -new_header=%T/move-enum/new_test.h -old_cc=%T/move-enum/enum.cpp -old_header=%T/move-enum/enum.h %T/move-enum/enum.cpp -- -std=c++11
+// RUN: FileCheck -input-file=%T/move-enum/new_test.h -allow-empty -check-prefix=CHECK-EMPTY %s
+
+// CHECK-EMPTY: {{^}}{{$}}
Index: test/clang-move/Inputs/enum.h
===
--- /dev/null
+++ test/clang-move/Inputs/enum.h
@@ -0,0 +1,9 @@
+namespace a {
+enum E1 { Green, Red };
+
+enum class E2 { Yellow };
+
+class C {
+  enum E3 { Blue };
+};
+} // namespace a
Index: clang-move/ClangMove.h
===
--- clang-move/ClangMove.h
+++ clang-move/ClangMove.h
@@ -135,6 +135,10 @@
 
   std::vector () { return MovedDecls; }
 
+  /// Add declatrations which are being moved to new.h/cc and being deleted in
+  /// old.h/cc.
+  void addMovedAndDeletedDecl(const NamedDecl *Decl);
+
   /// Add declarations being removed from old.h/cc. For each declarations, the
   /// method also records the mapping relationship between the corresponding
   /// FilePath and its FileID.
@@ -153,6 +157,7 @@
   void moveDeclsToNewFiles();
   void moveAll(SourceManager& SM, StringRef OldFile, StringRef NewFile);
 
+
   // Stores all MatchCallbacks created by this tool.
   std::vector
   MatchCallbacks;
Index: clang-move/ClangMove.cpp
===
--- clang-move/ClangMove.cpp
+++ clang-move/ClangMove.cpp
@@ -151,9 +151,22 @@
 const clang::NamedDecl *D = FD;
 if (const auto *FTD = FD->getDescribedFunctionTemplate())
   D = FTD;
-MoveTool->getMovedDecls().push_back(D);
-   

[PATCH] D28228: [clang-move] Support moving enum declarations.

2017-01-03 Thread Haojian Wu via Phabricator via cfe-commits
hokein added a comment.

In https://reviews.llvm.org/D28228#633863, @ioeric wrote:

> Do we consider enum helpers?


This patch excludes enum helpers, only considers the enum declarations which 
are defined in old.h. 
Ideally, we should support enum helpers which are defined in old.cc, but that's 
another topic.




Comment at: clang-move/ClangMove.cpp:171
+assert(ED);
+MoveTool->getMovedDecls().push_back(ED);
+MoveTool->getUnremovedDeclsInOldHeader().erase(ED);

ioeric wrote:
> These 3 lines seen to be repeated. Maybe pull them out as a `MoveTool` method?
Done. I made a function for these repeated lines, but it seems hard to figure 
out a pretty name for it.


https://reviews.llvm.org/D28228



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D28228: [clang-move] Support moving enum declarations.

2017-01-03 Thread Haojian Wu via Phabricator via cfe-commits
hokein updated this revision to Diff 82875.
hokein added a comment.

Remove forgot-deleted code.


https://reviews.llvm.org/D28228

Files:
  clang-move/ClangMove.cpp
  clang-move/ClangMove.h
  test/clang-move/Inputs/enum.h
  test/clang-move/move-enum-decl.cpp
  unittests/clang-move/ClangMoveTests.cpp

Index: unittests/clang-move/ClangMoveTests.cpp
===
--- unittests/clang-move/ClangMoveTests.cpp
+++ unittests/clang-move/ClangMoveTests.cpp
@@ -370,7 +370,6 @@
   std::vector TestHeaders = {
   "typedef int Int;\nclass A {\npublic:\n  int f();\n};\n",
   "using Int = int;\nclass A {\npublic:\n  int f();\n};\n",
-  "enum Color { RED };\nclass A {\npublic:\n  int f();\n};\n",
   };
   move::MoveDefinitionSpec Spec;
   Spec.Names.push_back("A");
Index: test/clang-move/move-enum-decl.cpp
===
--- /dev/null
+++ test/clang-move/move-enum-decl.cpp
@@ -0,0 +1,44 @@
+// RUN: mkdir -p %T/move-enum
+// RUN: cp %S/Inputs/enum.h  %T/move-enum/enum.h
+// RUN: echo '#include "enum.h"' > %T/move-enum/enum.cpp
+// RUN: cd %T/move-enum
+//
+// -
+// Test moving enum declarations.
+// -
+// RUN: clang-move -names="a::E1" -new_cc=%T/move-enum/new_test.cpp -new_header=%T/move-enum/new_test.h -old_cc=%T/move-enum/enum.cpp -old_header=%T/move-enum/enum.h %T/move-enum/enum.cpp -- -std=c++11
+// RUN: FileCheck -input-file=%T/move-enum/new_test.h -check-prefix=CHECK-NEW-TEST-H-CASE1 %s
+// RUN: FileCheck -input-file=%T/move-enum/enum.h -check-prefix=CHECK-OLD-TEST-H-CASE1 %s
+//
+// CHECK-NEW-TEST-H-CASE1: namespace a {
+// CHECK-NEW-TEST-H-CASE1-NEXT: enum E1 { Green, Red };
+// CHECK-NEW-TEST-H-CASE1-NEXT: }
+
+// CHECK-OLD-TEST-H-CASE1-NOT: enum E1 { Green, Red };
+
+
+// -
+// Test moving scoped enum declarations.
+// -
+// RUN: cp %S/Inputs/enum.h  %T/move-enum/enum.h
+// RUN: echo '#include "enum.h"' > %T/move-enum/enum.cpp
+// RUN: clang-move -names="a::E2" -new_cc=%T/move-enum/new_test.cpp -new_header=%T/move-enum/new_test.h -old_cc=%T/move-enum/enum.cpp -old_header=%T/move-enum/enum.h %T/move-enum/enum.cpp -- -std=c++11
+// RUN: FileCheck -input-file=%T/move-enum/new_test.h -check-prefix=CHECK-NEW-TEST-H-CASE2 %s
+// RUN: FileCheck -input-file=%T/move-enum/enum.h -check-prefix=CHECK-OLD-TEST-H-CASE2 %s
+
+// CHECK-NEW-TEST-H-CASE2: namespace a {
+// CHECK-NEW-TEST-H-CASE2-NEXT: enum class E2 { Yellow };
+// CHECK-NEW-TEST-H-CASE2-NEXT: }
+
+// CHECK-OLD-TEST-H-CASE2-NOT: enum class E2 { Yellow };
+
+
+// -
+// Test not moving class-insided enum declarations.
+// -
+// RUN: cp %S/Inputs/enum.h  %T/move-enum/enum.h
+// RUN: echo '#include "enum.h"' > %T/move-enum/enum.cpp
+// RUN: clang-move -names="a::C::E3" -new_cc=%T/move-enum/new_test.cpp -new_header=%T/move-enum/new_test.h -old_cc=%T/move-enum/enum.cpp -old_header=%T/move-enum/enum.h %T/move-enum/enum.cpp -- -std=c++11
+// RUN: FileCheck -input-file=%T/move-enum/new_test.h -allow-empty -check-prefix=CHECK-EMPTY %s
+
+// CHECK-EMPTY: {{^}}{{$}}
Index: test/clang-move/Inputs/enum.h
===
--- /dev/null
+++ test/clang-move/Inputs/enum.h
@@ -0,0 +1,9 @@
+namespace a {
+enum E1 { Green, Red };
+
+enum class E2 { Yellow };
+
+class C {
+  enum E3 { Blue };
+};
+} // namespace a
Index: clang-move/ClangMove.h
===
--- clang-move/ClangMove.h
+++ clang-move/ClangMove.h
@@ -153,6 +153,7 @@
   void moveDeclsToNewFiles();
   void moveAll(SourceManager& SM, StringRef OldFile, StringRef NewFile);
 
+
   // Stores all MatchCallbacks created by this tool.
   std::vector
   MatchCallbacks;
Index: clang-move/ClangMove.cpp
===
--- clang-move/ClangMove.cpp
+++ clang-move/ClangMove.cpp
@@ -140,6 +140,14 @@
   ClangMoveTool *const MoveTool;
 };
 
+/// Add a declatration being moved to new.h/cc. Note that the declaration will
+/// also be deleted in old.h/cc.
+void MoveDeclFromOldFileToNewFile(ClangMoveTool *MoveTool, const NamedDecl *D) {
+  MoveTool->getMovedDecls().push_back(D);
+  MoveTool->addRemovedDecl(D);
+  MoveTool->getUnremovedDeclsInOldHeader().erase(D);
+}
+
 class FunctionDeclarationMatch : public MatchFinder::MatchCallback {
 public:
   explicit FunctionDeclarationMatch(ClangMoveTool *MoveTool)
@@ -151,9 +159,22 @@
 const clang::NamedDecl *D = FD;
 if (const auto *FTD = 

[PATCH] D28228: [clang-move] Support moving enum declarations.

2017-01-03 Thread Haojian Wu via Phabricator via cfe-commits
hokein updated this revision to Diff 82874.
hokein marked an inline comment as done.
hokein added a comment.

Refine function name and add a comment for enum helpers.


https://reviews.llvm.org/D28228

Files:
  clang-move/ClangMove.cpp
  clang-move/ClangMove.h
  test/clang-move/Inputs/enum.h
  test/clang-move/move-enum-decl.cpp
  unittests/clang-move/ClangMoveTests.cpp

Index: unittests/clang-move/ClangMoveTests.cpp
===
--- unittests/clang-move/ClangMoveTests.cpp
+++ unittests/clang-move/ClangMoveTests.cpp
@@ -370,7 +370,6 @@
   std::vector TestHeaders = {
   "typedef int Int;\nclass A {\npublic:\n  int f();\n};\n",
   "using Int = int;\nclass A {\npublic:\n  int f();\n};\n",
-  "enum Color { RED };\nclass A {\npublic:\n  int f();\n};\n",
   };
   move::MoveDefinitionSpec Spec;
   Spec.Names.push_back("A");
Index: test/clang-move/move-enum-decl.cpp
===
--- /dev/null
+++ test/clang-move/move-enum-decl.cpp
@@ -0,0 +1,44 @@
+// RUN: mkdir -p %T/move-enum
+// RUN: cp %S/Inputs/enum.h  %T/move-enum/enum.h
+// RUN: echo '#include "enum.h"' > %T/move-enum/enum.cpp
+// RUN: cd %T/move-enum
+//
+// -
+// Test moving enum declarations.
+// -
+// RUN: clang-move -names="a::E1" -new_cc=%T/move-enum/new_test.cpp -new_header=%T/move-enum/new_test.h -old_cc=%T/move-enum/enum.cpp -old_header=%T/move-enum/enum.h %T/move-enum/enum.cpp -- -std=c++11
+// RUN: FileCheck -input-file=%T/move-enum/new_test.h -check-prefix=CHECK-NEW-TEST-H-CASE1 %s
+// RUN: FileCheck -input-file=%T/move-enum/enum.h -check-prefix=CHECK-OLD-TEST-H-CASE1 %s
+//
+// CHECK-NEW-TEST-H-CASE1: namespace a {
+// CHECK-NEW-TEST-H-CASE1-NEXT: enum E1 { Green, Red };
+// CHECK-NEW-TEST-H-CASE1-NEXT: }
+
+// CHECK-OLD-TEST-H-CASE1-NOT: enum E1 { Green, Red };
+
+
+// -
+// Test moving scoped enum declarations.
+// -
+// RUN: cp %S/Inputs/enum.h  %T/move-enum/enum.h
+// RUN: echo '#include "enum.h"' > %T/move-enum/enum.cpp
+// RUN: clang-move -names="a::E2" -new_cc=%T/move-enum/new_test.cpp -new_header=%T/move-enum/new_test.h -old_cc=%T/move-enum/enum.cpp -old_header=%T/move-enum/enum.h %T/move-enum/enum.cpp -- -std=c++11
+// RUN: FileCheck -input-file=%T/move-enum/new_test.h -check-prefix=CHECK-NEW-TEST-H-CASE2 %s
+// RUN: FileCheck -input-file=%T/move-enum/enum.h -check-prefix=CHECK-OLD-TEST-H-CASE2 %s
+
+// CHECK-NEW-TEST-H-CASE2: namespace a {
+// CHECK-NEW-TEST-H-CASE2-NEXT: enum class E2 { Yellow };
+// CHECK-NEW-TEST-H-CASE2-NEXT: }
+
+// CHECK-OLD-TEST-H-CASE2-NOT: enum class E2 { Yellow };
+
+
+// -
+// Test not moving class-insided enum declarations.
+// -
+// RUN: cp %S/Inputs/enum.h  %T/move-enum/enum.h
+// RUN: echo '#include "enum.h"' > %T/move-enum/enum.cpp
+// RUN: clang-move -names="a::C::E3" -new_cc=%T/move-enum/new_test.cpp -new_header=%T/move-enum/new_test.h -old_cc=%T/move-enum/enum.cpp -old_header=%T/move-enum/enum.h %T/move-enum/enum.cpp -- -std=c++11
+// RUN: FileCheck -input-file=%T/move-enum/new_test.h -allow-empty -check-prefix=CHECK-EMPTY %s
+
+// CHECK-EMPTY: {{^}}{{$}}
Index: test/clang-move/Inputs/enum.h
===
--- /dev/null
+++ test/clang-move/Inputs/enum.h
@@ -0,0 +1,9 @@
+namespace a {
+enum E1 { Green, Red };
+
+enum class E2 { Yellow };
+
+class C {
+  enum E3 { Blue };
+};
+} // namespace a
Index: clang-move/ClangMove.h
===
--- clang-move/ClangMove.h
+++ clang-move/ClangMove.h
@@ -153,6 +153,7 @@
   void moveDeclsToNewFiles();
   void moveAll(SourceManager& SM, StringRef OldFile, StringRef NewFile);
 
+
   // Stores all MatchCallbacks created by this tool.
   std::vector
   MatchCallbacks;
Index: clang-move/ClangMove.cpp
===
--- clang-move/ClangMove.cpp
+++ clang-move/ClangMove.cpp
@@ -140,6 +140,14 @@
   ClangMoveTool *const MoveTool;
 };
 
+/// Add a declatration being moved to new.h/cc. Note that the declaration will
+/// also be deleted in old.h/cc.
+void MoveDeclFromOldFileToNewFile(ClangMoveTool *MoveTool, const NamedDecl *D) {
+  MoveTool->getMovedDecls().push_back(D);
+  MoveTool->addRemovedDecl(D);
+  MoveTool->getUnremovedDeclsInOldHeader().erase(D);
+}
+
 class FunctionDeclarationMatch : public MatchFinder::MatchCallback {
 public:
   explicit FunctionDeclarationMatch(ClangMoveTool *MoveTool)
@@ -151,9 +159,22 @@
 

[PATCH] D28228: [clang-move] Support moving enum declarations.

2017-01-03 Thread Haojian Wu via Phabricator via cfe-commits
hokein updated this revision to Diff 82876.
hokein marked an inline comment as done.
hokein added a comment.

Not change in ClangMove.h


https://reviews.llvm.org/D28228

Files:
  clang-move/ClangMove.cpp
  test/clang-move/Inputs/enum.h
  test/clang-move/move-enum-decl.cpp
  unittests/clang-move/ClangMoveTests.cpp

Index: unittests/clang-move/ClangMoveTests.cpp
===
--- unittests/clang-move/ClangMoveTests.cpp
+++ unittests/clang-move/ClangMoveTests.cpp
@@ -370,7 +370,6 @@
   std::vector TestHeaders = {
   "typedef int Int;\nclass A {\npublic:\n  int f();\n};\n",
   "using Int = int;\nclass A {\npublic:\n  int f();\n};\n",
-  "enum Color { RED };\nclass A {\npublic:\n  int f();\n};\n",
   };
   move::MoveDefinitionSpec Spec;
   Spec.Names.push_back("A");
Index: test/clang-move/move-enum-decl.cpp
===
--- /dev/null
+++ test/clang-move/move-enum-decl.cpp
@@ -0,0 +1,44 @@
+// RUN: mkdir -p %T/move-enum
+// RUN: cp %S/Inputs/enum.h  %T/move-enum/enum.h
+// RUN: echo '#include "enum.h"' > %T/move-enum/enum.cpp
+// RUN: cd %T/move-enum
+//
+// -
+// Test moving enum declarations.
+// -
+// RUN: clang-move -names="a::E1" -new_cc=%T/move-enum/new_test.cpp -new_header=%T/move-enum/new_test.h -old_cc=%T/move-enum/enum.cpp -old_header=%T/move-enum/enum.h %T/move-enum/enum.cpp -- -std=c++11
+// RUN: FileCheck -input-file=%T/move-enum/new_test.h -check-prefix=CHECK-NEW-TEST-H-CASE1 %s
+// RUN: FileCheck -input-file=%T/move-enum/enum.h -check-prefix=CHECK-OLD-TEST-H-CASE1 %s
+//
+// CHECK-NEW-TEST-H-CASE1: namespace a {
+// CHECK-NEW-TEST-H-CASE1-NEXT: enum E1 { Green, Red };
+// CHECK-NEW-TEST-H-CASE1-NEXT: }
+
+// CHECK-OLD-TEST-H-CASE1-NOT: enum E1 { Green, Red };
+
+
+// -
+// Test moving scoped enum declarations.
+// -
+// RUN: cp %S/Inputs/enum.h  %T/move-enum/enum.h
+// RUN: echo '#include "enum.h"' > %T/move-enum/enum.cpp
+// RUN: clang-move -names="a::E2" -new_cc=%T/move-enum/new_test.cpp -new_header=%T/move-enum/new_test.h -old_cc=%T/move-enum/enum.cpp -old_header=%T/move-enum/enum.h %T/move-enum/enum.cpp -- -std=c++11
+// RUN: FileCheck -input-file=%T/move-enum/new_test.h -check-prefix=CHECK-NEW-TEST-H-CASE2 %s
+// RUN: FileCheck -input-file=%T/move-enum/enum.h -check-prefix=CHECK-OLD-TEST-H-CASE2 %s
+
+// CHECK-NEW-TEST-H-CASE2: namespace a {
+// CHECK-NEW-TEST-H-CASE2-NEXT: enum class E2 { Yellow };
+// CHECK-NEW-TEST-H-CASE2-NEXT: }
+
+// CHECK-OLD-TEST-H-CASE2-NOT: enum class E2 { Yellow };
+
+
+// -
+// Test not moving class-insided enum declarations.
+// -
+// RUN: cp %S/Inputs/enum.h  %T/move-enum/enum.h
+// RUN: echo '#include "enum.h"' > %T/move-enum/enum.cpp
+// RUN: clang-move -names="a::C::E3" -new_cc=%T/move-enum/new_test.cpp -new_header=%T/move-enum/new_test.h -old_cc=%T/move-enum/enum.cpp -old_header=%T/move-enum/enum.h %T/move-enum/enum.cpp -- -std=c++11
+// RUN: FileCheck -input-file=%T/move-enum/new_test.h -allow-empty -check-prefix=CHECK-EMPTY %s
+
+// CHECK-EMPTY: {{^}}{{$}}
Index: test/clang-move/Inputs/enum.h
===
--- /dev/null
+++ test/clang-move/Inputs/enum.h
@@ -0,0 +1,9 @@
+namespace a {
+enum E1 { Green, Red };
+
+enum class E2 { Yellow };
+
+class C {
+  enum E3 { Blue };
+};
+} // namespace a
Index: clang-move/ClangMove.cpp
===
--- clang-move/ClangMove.cpp
+++ clang-move/ClangMove.cpp
@@ -140,6 +140,14 @@
   ClangMoveTool *const MoveTool;
 };
 
+/// Add a declatration being moved to new.h/cc. Note that the declaration will
+/// also be deleted in old.h/cc.
+void MoveDeclFromOldFileToNewFile(ClangMoveTool *MoveTool, const NamedDecl *D) {
+  MoveTool->getMovedDecls().push_back(D);
+  MoveTool->addRemovedDecl(D);
+  MoveTool->getUnremovedDeclsInOldHeader().erase(D);
+}
+
 class FunctionDeclarationMatch : public MatchFinder::MatchCallback {
 public:
   explicit FunctionDeclarationMatch(ClangMoveTool *MoveTool)
@@ -151,9 +159,22 @@
 const clang::NamedDecl *D = FD;
 if (const auto *FTD = FD->getDescribedFunctionTemplate())
   D = FTD;
-MoveTool->getMovedDecls().push_back(D);
-MoveTool->getUnremovedDeclsInOldHeader().erase(D);
-MoveTool->addRemovedDecl(D);
+MoveDeclFromOldFileToNewFile(MoveTool, D);
+  }
+
+private:
+  ClangMoveTool *MoveTool;
+};
+
+class EnumDeclarationMatch : public MatchFinder::MatchCallback {
+public:
+  explicit 

[PATCH] D28228: [clang-move] Support moving enum declarations.

2017-01-03 Thread Haojian Wu via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL290891: [clang-move] Support moving enum declarations. 
(authored by hokein).

Changed prior to commit:
  https://reviews.llvm.org/D28228?vs=82876=82879#toc

Repository:
  rL LLVM

https://reviews.llvm.org/D28228

Files:
  clang-tools-extra/trunk/clang-move/ClangMove.cpp
  clang-tools-extra/trunk/test/clang-move/Inputs/enum.h
  clang-tools-extra/trunk/test/clang-move/move-enum-decl.cpp
  clang-tools-extra/trunk/unittests/clang-move/ClangMoveTests.cpp

Index: clang-tools-extra/trunk/unittests/clang-move/ClangMoveTests.cpp
===
--- clang-tools-extra/trunk/unittests/clang-move/ClangMoveTests.cpp
+++ clang-tools-extra/trunk/unittests/clang-move/ClangMoveTests.cpp
@@ -370,7 +370,6 @@
   std::vector TestHeaders = {
   "typedef int Int;\nclass A {\npublic:\n  int f();\n};\n",
   "using Int = int;\nclass A {\npublic:\n  int f();\n};\n",
-  "enum Color { RED };\nclass A {\npublic:\n  int f();\n};\n",
   };
   move::MoveDefinitionSpec Spec;
   Spec.Names.push_back("A");
Index: clang-tools-extra/trunk/clang-move/ClangMove.cpp
===
--- clang-tools-extra/trunk/clang-move/ClangMove.cpp
+++ clang-tools-extra/trunk/clang-move/ClangMove.cpp
@@ -140,6 +140,14 @@
   ClangMoveTool *const MoveTool;
 };
 
+/// Add a declatration being moved to new.h/cc. Note that the declaration will
+/// also be deleted in old.h/cc.
+void MoveDeclFromOldFileToNewFile(ClangMoveTool *MoveTool, const NamedDecl *D) {
+  MoveTool->getMovedDecls().push_back(D);
+  MoveTool->addRemovedDecl(D);
+  MoveTool->getUnremovedDeclsInOldHeader().erase(D);
+}
+
 class FunctionDeclarationMatch : public MatchFinder::MatchCallback {
 public:
   explicit FunctionDeclarationMatch(ClangMoveTool *MoveTool)
@@ -151,9 +159,22 @@
 const clang::NamedDecl *D = FD;
 if (const auto *FTD = FD->getDescribedFunctionTemplate())
   D = FTD;
-MoveTool->getMovedDecls().push_back(D);
-MoveTool->getUnremovedDeclsInOldHeader().erase(D);
-MoveTool->addRemovedDecl(D);
+MoveDeclFromOldFileToNewFile(MoveTool, D);
+  }
+
+private:
+  ClangMoveTool *MoveTool;
+};
+
+class EnumDeclarationMatch : public MatchFinder::MatchCallback {
+public:
+  explicit EnumDeclarationMatch(ClangMoveTool *MoveTool)
+  : MoveTool(MoveTool) {}
+
+  void run(const MatchFinder::MatchResult ) override {
+const auto *ED = Result.Nodes.getNodeAs("enum");
+assert(ED);
+MoveDeclFromOldFileToNewFile(MoveTool, ED);
   }
 
 private:
@@ -196,9 +217,7 @@
 
   void MatchClassStaticVariable(const clang::NamedDecl *VD,
 clang::SourceManager* SM) {
-MoveTool->getMovedDecls().push_back(VD);
-MoveTool->addRemovedDecl(VD);
-MoveTool->getUnremovedDeclsInOldHeader().erase(VD);
+MoveDeclFromOldFileToNewFile(MoveTool, VD);
   }
 
   void MatchClassDeclaration(const clang::CXXRecordDecl *CD,
@@ -449,6 +468,8 @@
   auto InOldFiles = anyOf(InOldHeader, InOldCC);
   auto ForwardDecls =
   cxxRecordDecl(unless(anyOf(isImplicit(), isDefinition(;
+  auto TopLevelDecl =
+  hasDeclContext(anyOf(namespaceDecl(), translationUnitDecl()));
 
   //
   // Matchers for old header
@@ -544,11 +565,9 @@
   // Create a MatchCallback for class declarations.
   MatchCallbacks.push_back(llvm::make_unique(this));
   // Match moved class declarations.
-  auto MovedClass =
-  cxxRecordDecl(
-  InOldFiles, *HasAnySymbolNames, isDefinition(),
-  hasDeclContext(anyOf(namespaceDecl(), translationUnitDecl(
-  .bind("moved_class");
+  auto MovedClass = cxxRecordDecl(InOldFiles, *HasAnySymbolNames,
+  isDefinition(), TopLevelDecl)
+.bind("moved_class");
   Finder->addMatcher(MovedClass, MatchCallbacks.back().get());
   // Match moved class methods (static methods included) which are defined
   // outside moved class declaration.
@@ -564,11 +583,17 @@
   MatchCallbacks.back().get());
 
   MatchCallbacks.push_back(llvm::make_unique(this));
-  Finder->addMatcher(functionDecl(InOldFiles, *HasAnySymbolNames,
-  anyOf(hasDeclContext(namespaceDecl()),
-hasDeclContext(translationUnitDecl(
+  Finder->addMatcher(functionDecl(InOldFiles, *HasAnySymbolNames, TopLevelDecl)
  .bind("function"),
  MatchCallbacks.back().get());
+
+  // Match enum definition in old.h. Enum helpers (which are definied in old.cc)
+  // will not be moved for now no matter whether they are used or not.
+  MatchCallbacks.push_back(llvm::make_unique(this));
+  Finder->addMatcher(
+  enumDecl(InOldHeader, *HasAnySymbolNames, isDefinition(), TopLevelDecl)
+  .bind("enum"),
+  

[PATCH] D28228: [clang-move] Support moving enum declarations.

2017-01-03 Thread Haojian Wu via Phabricator via cfe-commits
hokein added a comment.

In https://reviews.llvm.org/D28228#633930, @ioeric wrote:

> I mean, if a enum helper used in say only old cc, will it be moved? The 
> question is related to https://reviews.llvm.org/D27673. You don't need to 
> support enum helper now, but it would be nice to drop a comment somewhere.


Done. Add a comment about this. Enum helpers will not moved whether they are 
used or not.




Comment at: clang-move/ClangMove.h:140
+  /// old.h/cc.
+  void addMovedAndDeletedDecl(const NamedDecl *Decl);
+

ioeric wrote:
> Maybe just `addMovedDecl`? `move` indicates move and delete IMO. But you 
> might need to explain what's really going on in the comment.
Instead of making an interface in the class, I put this function as a helper 
function in .cc, and named it as `MoveDeclFromOldFileToNewFile`. Hope this will 
make it clearer.


https://reviews.llvm.org/D28228



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D28279: [clang-move] Support moving type alias declarations.

2017-01-04 Thread Haojian Wu via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL290967: [clang-move] Support moving type alias declarations. 
(authored by hokein).

Changed prior to commit:
  https://reviews.llvm.org/D28279?vs=83016=83053#toc

Repository:
  rL LLVM

https://reviews.llvm.org/D28279

Files:
  clang-tools-extra/trunk/clang-move/ClangMove.cpp
  clang-tools-extra/trunk/test/clang-move/Inputs/type_alias.h
  clang-tools-extra/trunk/test/clang-move/move-type-alias.cpp
  clang-tools-extra/trunk/unittests/clang-move/ClangMoveTests.cpp

Index: clang-tools-extra/trunk/clang-move/ClangMove.cpp
===
--- clang-tools-extra/trunk/clang-move/ClangMove.cpp
+++ clang-tools-extra/trunk/clang-move/ClangMove.cpp
@@ -166,6 +166,27 @@
   ClangMoveTool *MoveTool;
 };
 
+class TypeAliasMatch : public MatchFinder::MatchCallback {
+public:
+  explicit TypeAliasMatch(ClangMoveTool *MoveTool)
+  : MoveTool(MoveTool) {}
+
+  void run(const MatchFinder::MatchResult ) override {
+if (const auto *TD = Result.Nodes.getNodeAs("typedef"))
+  MoveDeclFromOldFileToNewFile(MoveTool, TD);
+else if (const auto *TAD =
+ Result.Nodes.getNodeAs("type_alias")) {
+  const NamedDecl * D = TAD;
+  if (const auto * TD = TAD->getDescribedAliasTemplate())
+D = TD;
+  MoveDeclFromOldFileToNewFile(MoveTool, D);
+}
+  }
+
+private:
+  ClangMoveTool *MoveTool;
+};
+
 class EnumDeclarationMatch : public MatchFinder::MatchCallback {
 public:
   explicit EnumDeclarationMatch(ClangMoveTool *MoveTool)
@@ -587,13 +608,22 @@
  .bind("function"),
  MatchCallbacks.back().get());
 
-  // Match enum definition in old.h. Enum helpers (which are definied in old.cc)
+  // Match enum definition in old.h. Enum helpers (which are defined in old.cc)
   // will not be moved for now no matter whether they are used or not.
   MatchCallbacks.push_back(llvm::make_unique(this));
   Finder->addMatcher(
   enumDecl(InOldHeader, *HasAnySymbolNames, isDefinition(), TopLevelDecl)
   .bind("enum"),
   MatchCallbacks.back().get());
+
+  // Match type alias in old.h, this includes "typedef" and "using" type alias
+  // declarations. Type alias helpers (which are defined in old.cc) will not be
+  // moved for now no matter whether they are used or not.
+  MatchCallbacks.push_back(llvm::make_unique(this));
+  Finder->addMatcher(namedDecl(anyOf(typedefDecl().bind("typedef"),
+ typeAliasDecl().bind("type_alias")),
+   InOldHeader, *HasAnySymbolNames, TopLevelDecl),
+ MatchCallbacks.back().get());
 }
 
 void ClangMoveTool::run(const ast_matchers::MatchFinder::MatchResult ) {
@@ -828,6 +858,9 @@
 case Decl::Kind::ClassTemplate:
 case Decl::Kind::CXXRecord:
 case Decl::Kind::Enum:
+case Decl::Kind::Typedef:
+case Decl::Kind::TypeAlias:
+case Decl::Kind::TypeAliasTemplate:
   return true;
 default:
   return false;
Index: clang-tools-extra/trunk/test/clang-move/Inputs/type_alias.h
===
--- clang-tools-extra/trunk/test/clang-move/Inputs/type_alias.h
+++ clang-tools-extra/trunk/test/clang-move/Inputs/type_alias.h
@@ -0,0 +1,11 @@
+typedef int Int1;
+using Int2 = int;
+
+template
+struct A {};
+
+template  using B = A;
+
+class C {
+  typedef int Int3;
+};
Index: clang-tools-extra/trunk/test/clang-move/move-type-alias.cpp
===
--- clang-tools-extra/trunk/test/clang-move/move-type-alias.cpp
+++ clang-tools-extra/trunk/test/clang-move/move-type-alias.cpp
@@ -0,0 +1,52 @@
+// RUN: mkdir -p %T/move-type-alias
+// RUN: cp %S/Inputs/type_alias.h  %T/move-type-alias/type_alias.h
+// RUN: echo '#include "type_alias.h"' > %T/move-type-alias/type_alias.cpp
+// RUN: cd %T/move-type-alias
+//
+// -
+// Test moving typedef declarations.
+// -
+// RUN: clang-move -names="Int1" -new_cc=%T/move-type-alias/new_test.cpp -new_header=%T/move-type-alias/new_test.h -old_cc=%T/move-type-alias/type_alias.cpp -old_header=%T/move-type-alias/type_alias.h %T/move-type-alias/type_alias.cpp -- -std=c++11
+// RUN: FileCheck -input-file=%T/move-type-alias/new_test.h -check-prefix=CHECK-NEW-TEST-H-CASE1 %s
+// RUN: FileCheck -input-file=%T/move-type-alias/type_alias.h -check-prefix=CHECK-OLD-TEST-H-CASE1 %s
+
+// CHECK-NEW-TEST-H-CASE1: typedef int Int1;
+
+// CHECK-OLD-TEST-H-CASE1-NOT: typedef int Int1;
+
+
+// -
+// Test moving type alias declarations.
+// -
+// RUN: cp 

[PATCH] D28282: [change-namespace] get whitespaces right when moving old namespaces.

2017-01-04 Thread Haojian Wu via Phabricator via cfe-commits
hokein accepted this revision.
hokein added a comment.
This revision is now accepted and ready to land.

LGTM with some nits.

Would be clearer to elaborate more descriptions in the commit message. Looks 
like the patch actually resolves newline character "\n" rather than 
whitespace...




Comment at: change-namespace/ChangeNamespace.cpp:568
+  MoveNs.Length =
+  SM.getFileOffset(NsDecl->getRBraceLoc()) - SM.getFileOffset(Start);
 

Maybe use `MoveNs.Offset` instead of recalling `SM.getFileOffset(Start);`


https://reviews.llvm.org/D28282



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D28315: Update tools to use new getStyle API

2017-01-05 Thread Haojian Wu via Phabricator via cfe-commits
hokein added a comment.

In https://reviews.llvm.org/D28315#635865, @amaiorano wrote:

> I made these changes, and they build, but I didn't really test them. Are 
> there unit tests for these tools that I can run?


If you use ninja build, you can run `ninja check-clang-tools` to run all tests.


https://reviews.llvm.org/D28315



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D28293: [clang-move] Dump enum and type alias declarations.

2017-01-04 Thread Haojian Wu via Phabricator via cfe-commits
hokein created this revision.
hokein added a reviewer: ioeric.
hokein added a subscriber: cfe-commits.

https://reviews.llvm.org/D28293

Files:
  clang-move/ClangMove.cpp
  unittests/clang-move/ClangMoveTests.cpp


Index: unittests/clang-move/ClangMoveTests.cpp
===
--- unittests/clang-move/ClangMoveTests.cpp
+++ unittests/clang-move/ClangMoveTests.cpp
@@ -535,6 +535,10 @@
 "namespace b {\n"
 "class Move1 { public : void f(); };\n"
 "void f() {}\n"
+"enum E1 { Green };\n"
+"enum class E2 { Red };\n"
+"typedef int Int2;\n"
+"using Int = int;\n"
 "} // namespace b\n"
 "} // namespace a\n";
   const char TestCode[] = "#include \"foo.h\"\n";
@@ -545,22 +549,16 @@
   Spec.NewHeader = "new_foo.h";
   Spec.NewCC = "new_foo.cc";
   DeclarationReporter Reporter;
-  std::vector ExpectedDeclarations = {
+  std::set ExpectedDeclarations = {
   {"A", "Class"}, {"B", "Class"},{"a::Move1", "Class"},
   {"a::f1", "Function"},  {"a::f2", "Function"}, {"a::b::Move1", "Class"},
-  {"a::b::f", "Function"}};
+  {"a::b::f", "Function"}, {"a::b::E1", "Enum"}, {"a::b::E2", "Enum"},
+  {"a::b::Int2", "TypeAlias"}, {"a::b::Int", "TypeAlias"} };
   runClangMoveOnCode(Spec, TestHeader, TestCode, );
-  const auto& Results = Reporter.getDeclarationList();
-  auto ActualDeclIter = Results.begin();
-  auto ExpectedDeclIter = ExpectedDeclarations.begin();
-  while (ActualDeclIter != Results.end() &&
- ExpectedDeclIter != ExpectedDeclarations.end()) {
-EXPECT_EQ(*ActualDeclIter, *ExpectedDeclIter);
-++ActualDeclIter;
-++ExpectedDeclIter;
-  }
-  ASSERT_TRUE(ActualDeclIter == Results.end());
-  ASSERT_TRUE(ExpectedDeclIter == ExpectedDeclarations.end());
+  std::set Results;
+  for (const auto& DelPair : Reporter.getDeclarationList())
+Results.insert(DelPair);
+  EXPECT_EQ(ExpectedDeclarations, Results);
 }
 
 } // namespace
Index: clang-move/ClangMove.cpp
===
--- clang-move/ClangMove.cpp
+++ clang-move/ClangMove.cpp
@@ -841,6 +841,12 @@
   else if (Kind == Decl::Kind::ClassTemplate ||
Kind == Decl::Kind::CXXRecord)
 Reporter->reportDeclaration(QualifiedName, "Class");
+  else if (Kind == Decl::Kind::Enum)
+Reporter->reportDeclaration(QualifiedName, "Enum");
+  else if (Kind == Decl::Kind::Typedef ||
+   Kind == Decl::Kind::TypeAlias ||
+   Kind == Decl::Kind::TypeAliasTemplate)
+Reporter->reportDeclaration(QualifiedName, "TypeAlias");
 }
 return;
   }


Index: unittests/clang-move/ClangMoveTests.cpp
===
--- unittests/clang-move/ClangMoveTests.cpp
+++ unittests/clang-move/ClangMoveTests.cpp
@@ -535,6 +535,10 @@
 "namespace b {\n"
 "class Move1 { public : void f(); };\n"
 "void f() {}\n"
+"enum E1 { Green };\n"
+"enum class E2 { Red };\n"
+"typedef int Int2;\n"
+"using Int = int;\n"
 "} // namespace b\n"
 "} // namespace a\n";
   const char TestCode[] = "#include \"foo.h\"\n";
@@ -545,22 +549,16 @@
   Spec.NewHeader = "new_foo.h";
   Spec.NewCC = "new_foo.cc";
   DeclarationReporter Reporter;
-  std::vector ExpectedDeclarations = {
+  std::set ExpectedDeclarations = {
   {"A", "Class"}, {"B", "Class"},{"a::Move1", "Class"},
   {"a::f1", "Function"},  {"a::f2", "Function"}, {"a::b::Move1", "Class"},
-  {"a::b::f", "Function"}};
+  {"a::b::f", "Function"}, {"a::b::E1", "Enum"}, {"a::b::E2", "Enum"},
+  {"a::b::Int2", "TypeAlias"}, {"a::b::Int", "TypeAlias"} };
   runClangMoveOnCode(Spec, TestHeader, TestCode, );
-  const auto& Results = Reporter.getDeclarationList();
-  auto ActualDeclIter = Results.begin();
-  auto ExpectedDeclIter = ExpectedDeclarations.begin();
-  while (ActualDeclIter != Results.end() &&
- ExpectedDeclIter != ExpectedDeclarations.end()) {
-EXPECT_EQ(*ActualDeclIter, *ExpectedDeclIter);
-++ActualDeclIter;
-++ExpectedDeclIter;
-  }
-  ASSERT_TRUE(ActualDeclIter == Results.end());
-  ASSERT_TRUE(ExpectedDeclIter == ExpectedDeclarations.end());
+  std::set Results;
+  for (const auto& DelPair : Reporter.getDeclarationList())
+Results.insert(DelPair);
+  EXPECT_EQ(ExpectedDeclarations, Results);
 }
 
 } // namespace
Index: clang-move/ClangMove.cpp
===
--- clang-move/ClangMove.cpp

[PATCH] D27673: [clang-move] Only move used helper declarations.

2017-01-02 Thread Haojian Wu via Phabricator via cfe-commits
hokein updated this revision to Diff 82804.
hokein marked 3 inline comments as done.
hokein added a comment.

Add more test cases.


https://reviews.llvm.org/D27673

Files:
  clang-move/CMakeLists.txt
  clang-move/ClangMove.cpp
  clang-move/ClangMove.h
  clang-move/HelperDeclRefGraph.cpp
  clang-move/HelperDeclRefGraph.h
  test/clang-move/Inputs/helper_decls_test.cpp
  test/clang-move/Inputs/helper_decls_test.h
  test/clang-move/Inputs/multiple_class_test.cpp
  test/clang-move/move-multiple-classes.cpp
  test/clang-move/move-used-helper-decls.cpp
  unittests/clang-move/ClangMoveTests.cpp

Index: unittests/clang-move/ClangMoveTests.cpp
===
--- unittests/clang-move/ClangMoveTests.cpp
+++ unittests/clang-move/ClangMoveTests.cpp
@@ -73,13 +73,21 @@
   "\n"
   "// comment5\n"
   "// comment5\n"
-  "void Foo::f() { f1(); }\n"
+  "void Foo::f() {\n"
+  "  f1();\n"
+  "  kConstInt1;\n"
+  "  kConstInt2;\n"
+  "  help();\n"
+  "}\n"
   "\n"
   "/\n"
   "// comment //\n"
   "/\n"
   "int Foo::b = 2;\n"
   "int Foo2::f() {\n"
+  "  kConstInt1;\n"
+  "  kConstInt2;\n"
+  "  help();\n"
   "  f1();\n"
   "  return 1;\n"
   "}\n"
@@ -119,6 +127,9 @@
   "}\n"
   "\n"
   "int Foo2::f() {\n"
+  "  kConstInt1;\n"
+  "  kConstInt2;\n"
+  "  help();\n"
   "  f1();\n"
   "  return 1;\n"
   "}\n"
@@ -154,6 +165,7 @@
  "namespace {\n"
  "// comment1.\n"
  "void f1() {}\n"
+ "\n"
  "/// comment2.\n"
  "int kConstInt1 = 0;\n"
  "} // namespace\n"
@@ -170,7 +182,12 @@
  "\n"
  "// comment5\n"
  "// comment5\n"
- "void Foo::f() { f1(); }\n"
+ "void Foo::f() {\n"
+ "  f1();\n"
+ "  kConstInt1;\n"
+ "  kConstInt2;\n"
+ "  help();\n"
+ "}\n"
  "\n"
  "/\n"
  "// comment //\n"
Index: test/clang-move/move-used-helper-decls.cpp
===
--- /dev/null
+++ test/clang-move/move-used-helper-decls.cpp
@@ -0,0 +1,388 @@
+// RUN: mkdir -p %T/used-helper-decls
+// RUN: cp %S/Inputs/helper_decls_test*  %T/used-helper-decls/
+// RUN: cd %T/used-helper-decls
+
+// 
+// Test moving used helper function and its transively used functions.
+// 
+// RUN: clang-move -names="a::Class1" -new_cc=%T/used-helper-decls/new_helper_decls_test.cpp -new_header=%T/used-helper-decls/new_helper_decls_test.h -old_cc=%T/used-helper-decls/helper_decls_test.cpp -old_header=../used-helper-decls/helper_decls_test.h %T/used-helper-decls/helper_decls_test.cpp -- -std=c++11
+// RUN: FileCheck -input-file=%T/used-helper-decls/new_helper_decls_test.cpp -check-prefix=CHECK-NEW-CLASS1-CPP %s
+// RUN: FileCheck -input-file=%T/used-helper-decls/helper_decls_test.cpp -check-prefix=CHECK-OLD-CLASS1-CPP %s
+
+// CHECK-NEW-CLASS1-CPP: #include "{{.*}}new_helper_decls_test.h"
+// CHECK-NEW-CLASS1-CPP-SAME: {{[[:space:]]}}
+// CHECK-NEW-CLASS1-CPP-NEXT: namespace {
+// CHECK-NEW-CLASS1-CPP-NEXT: void HelperFun1() {}
+// CHECK-NEW-CLASS1-CPP-SAME: {{[[:space:]]}}
+// CHECK-NEW-CLASS1-CPP-NEXT: void HelperFun2() { HelperFun1(); }
+// CHECK-NEW-CLASS1-CPP-NEXT: } // namespace
+// CHECK-NEW-CLASS1-CPP-SAME: {{[[:space:]]}}
+// CHECK-NEW-CLASS1-CPP-NEXT: namespace a {
+// CHECK-NEW-CLASS1-CPP-NEXT: void Class1::f() { HelperFun2(); }
+// CHECK-NEW-CLASS1-CPP-NEXT: } // namespace a
+//
+// CHECK-OLD-CLASS1-CPP: void HelperFun1() {}
+// CHECK-OLD-CLASS1-CPP-NOT: void HelperFun2() { HelperFun1(); }
+// CHECK-OLD-CLASS1-CPP-NOT: void Class1::f() { HelperFun2(); }
+// CHECK-OLD-CLASS1-CPP: void Class2::f() {
+// CHECK-OLD-CLASS1-CPP:   HelperFun1();
+
+
+// 

[PATCH] D27920: [find-all-symbols] Index partial template specializations.

2016-12-19 Thread Haojian Wu via Phabricator via cfe-commits
hokein created this revision.
hokein added a reviewer: ioeric.
hokein added subscribers: bkramer, cfe-commits.

Fix no std::function index.


https://reviews.llvm.org/D27920

Files:
  include-fixer/find-all-symbols/FindAllSymbols.cpp
  unittests/include-fixer/find-all-symbols/FindAllSymbolsTests.cpp


Index: unittests/include-fixer/find-all-symbols/FindAllSymbolsTests.cpp
===
--- unittests/include-fixer/find-all-symbols/FindAllSymbolsTests.cpp
+++ unittests/include-fixer/find-all-symbols/FindAllSymbolsTests.cpp
@@ -229,6 +229,28 @@
   EXPECT_TRUE(hasSymbol(Symbol));
 }
 
+TEST_F(FindAllSymbolsTest, DontIgnoreTemplatePartialSpecialization) {
+  static const char Code[] = R"(
+  template class Class; // undefined
+  template
+  class Class {
+  };
+
+  template void f() {};
+  template<> void f() {};
+  )";
+  runFindAllSymbols(Code);
+  SymbolInfo Symbol =
+  SymbolInfo("Class", SymbolInfo::SymbolKind::Class, HeaderName, 4, {});
+  EXPECT_TRUE(hasSymbol(Symbol));
+  Symbol =
+  SymbolInfo("f", SymbolInfo::SymbolKind::Function, HeaderName, 7, {});
+  EXPECT_TRUE(hasSymbol(Symbol));
+  Symbol =
+  SymbolInfo("f", SymbolInfo::SymbolKind::Function, HeaderName, 8, {});
+  EXPECT_FALSE(hasSymbol(Symbol));
+}
+
 TEST_F(FindAllSymbolsTest, FunctionSymbols) {
   static const char Code[] = R"(
   namespace na {
Index: include-fixer/find-all-symbols/FindAllSymbols.cpp
===
--- include-fixer/find-all-symbols/FindAllSymbols.cpp
+++ include-fixer/find-all-symbols/FindAllSymbols.cpp
@@ -32,6 +32,18 @@
   return false;
 }
 
+AST_POLYMORPHIC_MATCHER(isFullySpecialized,
+AST_POLYMORPHIC_SUPPORTED_TYPES(FunctionDecl, VarDecl,
+CXXRecordDecl)) {
+  if (Node.getTemplateSpecializationKind() == TSK_ExplicitSpecialization) {
+bool is_partial_specialization =
+llvm::isa(Node) ||
+llvm::isa(Node);
+return !is_partial_specialization;
+  }
+  return false;
+}
+
 std::vector GetContexts(const NamedDecl *ND) {
   std::vector Contexts;
   for (const auto *Context = ND->getDeclContext(); Context;
@@ -126,8 +138,7 @@
   auto CCMatcher =
   allOf(HasNSOrTUCtxMatcher, unless(IsInSpecialization),
 unless(ast_matchers::isTemplateInstantiation()),
-unless(isInstantiated()), 
unless(classTemplateSpecializationDecl()),
-unless(isExplicitTemplateSpecialization()));
+unless(isInstantiated()), unless(isFullySpecialized()));
 
   // Matchers specific to code in extern "C" {...}.
   auto ExternCMatcher = hasDeclContext(linkageSpecDecl());
@@ -156,8 +167,7 @@
 
   // Matchers for C++ record declarations.
   auto CxxRecordDecl =
-  cxxRecordDecl(CommonFilter, CCMatcher, isDefinition(),
-unless(isExplicitTemplateSpecialization()));
+  cxxRecordDecl(CommonFilter, CCMatcher, isDefinition());
   MatchFinder->addMatcher(CxxRecordDecl.bind("decl"), this);
 
   // Matchers for function declarations.


Index: unittests/include-fixer/find-all-symbols/FindAllSymbolsTests.cpp
===
--- unittests/include-fixer/find-all-symbols/FindAllSymbolsTests.cpp
+++ unittests/include-fixer/find-all-symbols/FindAllSymbolsTests.cpp
@@ -229,6 +229,28 @@
   EXPECT_TRUE(hasSymbol(Symbol));
 }
 
+TEST_F(FindAllSymbolsTest, DontIgnoreTemplatePartialSpecialization) {
+  static const char Code[] = R"(
+  template class Class; // undefined
+  template
+  class Class {
+  };
+
+  template void f() {};
+  template<> void f() {};
+  )";
+  runFindAllSymbols(Code);
+  SymbolInfo Symbol =
+  SymbolInfo("Class", SymbolInfo::SymbolKind::Class, HeaderName, 4, {});
+  EXPECT_TRUE(hasSymbol(Symbol));
+  Symbol =
+  SymbolInfo("f", SymbolInfo::SymbolKind::Function, HeaderName, 7, {});
+  EXPECT_TRUE(hasSymbol(Symbol));
+  Symbol =
+  SymbolInfo("f", SymbolInfo::SymbolKind::Function, HeaderName, 8, {});
+  EXPECT_FALSE(hasSymbol(Symbol));
+}
+
 TEST_F(FindAllSymbolsTest, FunctionSymbols) {
   static const char Code[] = R"(
   namespace na {
Index: include-fixer/find-all-symbols/FindAllSymbols.cpp
===
--- include-fixer/find-all-symbols/FindAllSymbols.cpp
+++ include-fixer/find-all-symbols/FindAllSymbols.cpp
@@ -32,6 +32,18 @@
   return false;
 }
 
+AST_POLYMORPHIC_MATCHER(isFullySpecialized,
+AST_POLYMORPHIC_SUPPORTED_TYPES(FunctionDecl, VarDecl,
+CXXRecordDecl)) {
+  if (Node.getTemplateSpecializationKind() == TSK_ExplicitSpecialization) {
+bool is_partial_specialization =
+llvm::isa(Node) ||
+llvm::isa(Node);
+return !is_partial_specialization;
+  

[PATCH] D27920: [find-all-symbols] Index partial template specializations.

2016-12-21 Thread Haojian Wu via Phabricator via cfe-commits
hokein added a comment.

In https://reviews.llvm.org/D27920#628586, @ioeric wrote:

> Why do we allow partially specialization but fully specialization now? Could 
> you elaborate in the cl description?


Done.


https://reviews.llvm.org/D27920



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D27982: [change-namespace] do not fix calls to overloaded operator functions.

2016-12-20 Thread Haojian Wu via Phabricator via cfe-commits
hokein accepted this revision.
hokein added a comment.
This revision is now accepted and ready to land.

LGTM.




Comment at: unittests/change-namespace/ChangeNamespaceTests.cpp:578
 
+// FIXME: function calls to overloaded operators are not fixed now even if they
+// are referenced by qualified names.

Maybe also add this case in the test although it is not fixed yet.



Comment at: unittests/change-namespace/ChangeNamespaceTests.cpp:592
+  "  A x, y;\n"
+  "  auto f = operator<;"
+  "  return (x == y) && (x < y) && (operator<(x, y));"

missing a `\n`, the same below.


https://reviews.llvm.org/D27982



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D28052: [change-namespace] consider namespace aliases to shorten qualified names.

2016-12-23 Thread Haojian Wu via Phabricator via cfe-commits
hokein accepted this revision.
hokein added a comment.
This revision is now accepted and ready to land.

LGTM.


https://reviews.llvm.org/D28052



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D28052: [change-namespace] consider namespace aliases to shorten qualified names.

2016-12-22 Thread Haojian Wu via Phabricator via cfe-commits
hokein added inline comments.



Comment at: change-namespace/ChangeNamespace.cpp:719
+// The alias is defined in some namespace.
+assert(AliasQualifiedName.size() >= AliasName.size() + 2);
+llvm::StringRef AliasNs =

maybe `assert(StringRef(AliasQualifiedName).end_with("::"+AliasName))`?



Comment at: change-namespace/ChangeNamespace.cpp:741
 if (TargetDecl == FromDecl) {
   ReplaceName = FromDecl->getNameAsString();
   Matched = true;

Do we also need to check  `FromDecl->getNameAsString().size() < 
ReplaceName.size()` before assigning the name to `ReplaceName`?



Comment at: unittests/change-namespace/ChangeNamespaceTests.cpp:832
+ "}\n"
+ "namespace gl = glob;\n"
+ "namespace na {\n"

Add a testcase for the namespace alias decl with preceding `::`,  e.g. 
`namespace gl = ::glob`?


https://reviews.llvm.org/D28052



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D27673: [clang-move] Only move used helper declarations.

2016-12-16 Thread Haojian Wu via Phabricator via cfe-commits
hokein updated this revision to Diff 81762.
hokein marked 3 inline comments as done.
hokein added a comment.

refactoring the patch.


https://reviews.llvm.org/D27673

Files:
  clang-move/CMakeLists.txt
  clang-move/ClangMove.cpp
  clang-move/ClangMove.h
  clang-move/HelperDeclRefGraph.cpp
  clang-move/HelperDeclRefGraph.h
  test/clang-move/Inputs/helper_decls_test.cpp
  test/clang-move/Inputs/helper_decls_test.h
  test/clang-move/Inputs/multiple_class_test.cpp
  test/clang-move/move-multiple-classes.cpp
  test/clang-move/move-used-helper-decls.cpp
  unittests/clang-move/ClangMoveTests.cpp

Index: unittests/clang-move/ClangMoveTests.cpp
===
--- unittests/clang-move/ClangMoveTests.cpp
+++ unittests/clang-move/ClangMoveTests.cpp
@@ -73,13 +73,21 @@
   "\n"
   "// comment5\n"
   "// comment5\n"
-  "void Foo::f() { f1(); }\n"
+  "void Foo::f() {\n"
+  "  f1();\n"
+  "  kConstInt1;\n"
+  "  kConstInt2;\n"
+  "  help();\n"
+  "}\n"
   "\n"
   "/\n"
   "// comment //\n"
   "/\n"
   "int Foo::b = 2;\n"
   "int Foo2::f() {\n"
+  "  kConstInt1;\n"
+  "  kConstInt2;\n"
+  "  help();\n"
   "  f1();\n"
   "  return 1;\n"
   "}\n"
@@ -119,6 +127,9 @@
   "}\n"
   "\n"
   "int Foo2::f() {\n"
+  "  kConstInt1;\n"
+  "  kConstInt2;\n"
+  "  help();\n"
   "  f1();\n"
   "  return 1;\n"
   "}\n"
@@ -154,6 +165,7 @@
  "namespace {\n"
  "// comment1.\n"
  "void f1() {}\n"
+ "\n"
  "/// comment2.\n"
  "int kConstInt1 = 0;\n"
  "} // namespace\n"
@@ -170,7 +182,12 @@
  "\n"
  "// comment5\n"
  "// comment5\n"
- "void Foo::f() { f1(); }\n"
+ "void Foo::f() {\n"
+ "  f1();\n"
+ "  kConstInt1;\n"
+ "  kConstInt2;\n"
+ "  help();\n"
+ "}\n"
  "\n"
  "/\n"
  "// comment //\n"
Index: test/clang-move/move-used-helper-decls.cpp
===
--- /dev/null
+++ test/clang-move/move-used-helper-decls.cpp
@@ -0,0 +1,202 @@
+// RUN: mkdir -p %T/used-helper-decls
+// RUN: cp %S/Inputs/helper_decls_test*  %T/used-helper-decls/
+// RUN: cd %T/used-helper-decls
+
+// RUN: clang-move -names="a::Class1" -new_cc=%T/used-helper-decls/new_helper_decls_test.cpp -new_header=%T/used-helper-decls/new_helper_decls_test.h -old_cc=%T/used-helper-decls/helper_decls_test.cpp -old_header=../used-helper-decls/helper_decls_test.h %T/used-helper-decls/helper_decls_test.cpp -- -std=c++11
+// RUN: FileCheck -input-file=%T/used-helper-decls/new_helper_decls_test.cpp -check-prefix=CHECK-NEW-CLASS1-CPP %s
+// RUN: FileCheck -input-file=%T/used-helper-decls/helper_decls_test.cpp -check-prefix=CHECK-OLD-CLASS1-CPP %s
+
+// CHECK-NEW-CLASS1-CPP: #include "{{.*}}new_helper_decls_test.h"
+// CHECK-NEW-CLASS1-CPP-SAME: {{[[:space:]]}}
+// CHECK-NEW-CLASS1-CPP-NEXT: namespace {
+// CHECK-NEW-CLASS1-CPP-NEXT: void HelperFun1() {}
+// CHECK-NEW-CLASS1-CPP-SAME: {{[[:space:]]}}
+// CHECK-NEW-CLASS1-CPP-NEXT: void HelperFun2() { HelperFun1(); }
+// CHECK-NEW-CLASS1-CPP-NEXT: } // namespace
+// CHECK-NEW-CLASS1-CPP-SAME: {{[[:space:]]}}
+// CHECK-NEW-CLASS1-CPP-NEXT: namespace a {
+// CHECK-NEW-CLASS1-CPP-NEXT: void Class1::f() { HelperFun2(); }
+// CHECK-NEW-CLASS1-CPP-NEXT: } // namespace a
+//
+// CHECK-OLD-CLASS1-CPP: void HelperFun1() {}
+// CHECK-OLD-CLASS1-CPP-NOT: void HelperFun2() { HelperFun1(); }
+// CHECK-OLD-CLASS1-CPP-NOT: void Class1::f() { HelperFun2(); }
+// CHECK-OLD-CLASS1-CPP: void Class2::f() {
+// CHECK-OLD-CLASS1-CPP:   HelperFun1();
+
+// RUN: cp %S/Inputs/helper_decls_test*  %T/used-helper-decls/
+// RUN: clang-move -names="a::Class2" -new_cc=%T/used-helper-decls/new_helper_decls_test.cpp -new_header=%T/used-helper-decls/new_helper_decls_test.h 

[PATCH] D27673: [clang-move] Only move used helper declarations.

2016-12-16 Thread Haojian Wu via Phabricator via cfe-commits
hokein updated this revision to Diff 81763.
hokein added a comment.

Update outdated comment.


https://reviews.llvm.org/D27673

Files:
  clang-move/CMakeLists.txt
  clang-move/ClangMove.cpp
  clang-move/ClangMove.h
  clang-move/HelperDeclRefGraph.cpp
  clang-move/HelperDeclRefGraph.h
  test/clang-move/Inputs/helper_decls_test.cpp
  test/clang-move/Inputs/helper_decls_test.h
  test/clang-move/Inputs/multiple_class_test.cpp
  test/clang-move/move-multiple-classes.cpp
  test/clang-move/move-used-helper-decls.cpp
  unittests/clang-move/ClangMoveTests.cpp

Index: unittests/clang-move/ClangMoveTests.cpp
===
--- unittests/clang-move/ClangMoveTests.cpp
+++ unittests/clang-move/ClangMoveTests.cpp
@@ -73,13 +73,21 @@
   "\n"
   "// comment5\n"
   "// comment5\n"
-  "void Foo::f() { f1(); }\n"
+  "void Foo::f() {\n"
+  "  f1();\n"
+  "  kConstInt1;\n"
+  "  kConstInt2;\n"
+  "  help();\n"
+  "}\n"
   "\n"
   "/\n"
   "// comment //\n"
   "/\n"
   "int Foo::b = 2;\n"
   "int Foo2::f() {\n"
+  "  kConstInt1;\n"
+  "  kConstInt2;\n"
+  "  help();\n"
   "  f1();\n"
   "  return 1;\n"
   "}\n"
@@ -119,6 +127,9 @@
   "}\n"
   "\n"
   "int Foo2::f() {\n"
+  "  kConstInt1;\n"
+  "  kConstInt2;\n"
+  "  help();\n"
   "  f1();\n"
   "  return 1;\n"
   "}\n"
@@ -154,6 +165,7 @@
  "namespace {\n"
  "// comment1.\n"
  "void f1() {}\n"
+ "\n"
  "/// comment2.\n"
  "int kConstInt1 = 0;\n"
  "} // namespace\n"
@@ -170,7 +182,12 @@
  "\n"
  "// comment5\n"
  "// comment5\n"
- "void Foo::f() { f1(); }\n"
+ "void Foo::f() {\n"
+ "  f1();\n"
+ "  kConstInt1;\n"
+ "  kConstInt2;\n"
+ "  help();\n"
+ "}\n"
  "\n"
  "/\n"
  "// comment //\n"
Index: test/clang-move/move-used-helper-decls.cpp
===
--- /dev/null
+++ test/clang-move/move-used-helper-decls.cpp
@@ -0,0 +1,202 @@
+// RUN: mkdir -p %T/used-helper-decls
+// RUN: cp %S/Inputs/helper_decls_test*  %T/used-helper-decls/
+// RUN: cd %T/used-helper-decls
+
+// RUN: clang-move -names="a::Class1" -new_cc=%T/used-helper-decls/new_helper_decls_test.cpp -new_header=%T/used-helper-decls/new_helper_decls_test.h -old_cc=%T/used-helper-decls/helper_decls_test.cpp -old_header=../used-helper-decls/helper_decls_test.h %T/used-helper-decls/helper_decls_test.cpp -- -std=c++11
+// RUN: FileCheck -input-file=%T/used-helper-decls/new_helper_decls_test.cpp -check-prefix=CHECK-NEW-CLASS1-CPP %s
+// RUN: FileCheck -input-file=%T/used-helper-decls/helper_decls_test.cpp -check-prefix=CHECK-OLD-CLASS1-CPP %s
+
+// CHECK-NEW-CLASS1-CPP: #include "{{.*}}new_helper_decls_test.h"
+// CHECK-NEW-CLASS1-CPP-SAME: {{[[:space:]]}}
+// CHECK-NEW-CLASS1-CPP-NEXT: namespace {
+// CHECK-NEW-CLASS1-CPP-NEXT: void HelperFun1() {}
+// CHECK-NEW-CLASS1-CPP-SAME: {{[[:space:]]}}
+// CHECK-NEW-CLASS1-CPP-NEXT: void HelperFun2() { HelperFun1(); }
+// CHECK-NEW-CLASS1-CPP-NEXT: } // namespace
+// CHECK-NEW-CLASS1-CPP-SAME: {{[[:space:]]}}
+// CHECK-NEW-CLASS1-CPP-NEXT: namespace a {
+// CHECK-NEW-CLASS1-CPP-NEXT: void Class1::f() { HelperFun2(); }
+// CHECK-NEW-CLASS1-CPP-NEXT: } // namespace a
+//
+// CHECK-OLD-CLASS1-CPP: void HelperFun1() {}
+// CHECK-OLD-CLASS1-CPP-NOT: void HelperFun2() { HelperFun1(); }
+// CHECK-OLD-CLASS1-CPP-NOT: void Class1::f() { HelperFun2(); }
+// CHECK-OLD-CLASS1-CPP: void Class2::f() {
+// CHECK-OLD-CLASS1-CPP:   HelperFun1();
+
+// RUN: cp %S/Inputs/helper_decls_test*  %T/used-helper-decls/
+// RUN: clang-move -names="a::Class2" -new_cc=%T/used-helper-decls/new_helper_decls_test.cpp -new_header=%T/used-helper-decls/new_helper_decls_test.h -old_cc=%T/used-helper-decls/helper_decls_test.cpp 

[PATCH] D31176: [clang-rename] Support renaming qualified symbol

2017-03-22 Thread Haojian Wu via Phabricator via cfe-commits
hokein updated this revision to Diff 92636.
hokein marked 14 inline comments as done.
hokein added a comment.

Address review comments.


https://reviews.llvm.org/D31176

Files:
  clang-rename/RenamingAction.cpp
  clang-rename/RenamingAction.h
  clang-rename/USRFinder.cpp
  clang-rename/USRFindingAction.cpp
  clang-rename/USRLocFinder.cpp
  clang-rename/USRLocFinder.h
  unittests/clang-rename/CMakeLists.txt
  unittests/clang-rename/ClangRenameTest.h
  unittests/clang-rename/ClangRenameTests.cpp
  unittests/clang-rename/RenameClassTest.cpp

Index: unittests/clang-rename/RenameClassTest.cpp
===
--- /dev/null
+++ unittests/clang-rename/RenameClassTest.cpp
@@ -0,0 +1,670 @@
+//===-- RenameClassTest.cpp - unit tests for renaming classes -===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===--===//
+
+#include "ClangRenameTest.h"
+
+namespace clang {
+namespace clang_rename {
+namespace test {
+namespace {
+
+class RenameClassTest : public ClangRenameTest {
+public:
+  RenameClassTest() {
+AppendToHeader(R"(
+  namespace a {
+class Foo {
+  public:
+struct Nested {
+  enum NestedEnum {E1, E2};
+};
+void func() {}
+};
+class Goo {
+  public:
+struct Nested {
+  enum NestedEnum {E1, E2};
+};
+};
+  } // namespace a
+  namespace b {
+  class Foo {};
+  } // namespace b
+
+  #define MACRO(x) x
+
+  template class ptr {};
+)");
+  }
+};
+
+INSTANTIATE_TEST_CASE_P(
+RenameClassTests, RenameClassTest,
+testing::ValuesIn(std::vector({
+// basic classes
+{"a::Foo f;", "b::Bar f;", "a::Foo", "b::Bar"},
+{"void f(a::Foo f) {}", "void f(b::Bar f) {}", "a::Foo", "b::Bar"},
+{"void f(a::Foo *f) {}", "void f(b::Bar *f) {}", "a::Foo", "b::Bar"},
+{"a::Foo f() { return a::Foo(); }", "b::Bar f() { return b::Bar(); }",
+ "a::Foo", "b::Bar"},
+{"namespace a {a::Foo f() { return Foo(); }}",
+ "namespace a {b::Bar f() { return b::Bar(); }}", "a::Foo", "b::Bar"},
+{"void f(const a::Foo& a1) {}", "void f(const b::Bar& a1) {}", "a::Foo",
+ "b::Bar"},
+{"void f(const a::Foo* a1) {}", "void f(const b::Bar* a1) {}", "a::Foo",
+ "b::Bar"},
+{"namespace a { void f(Foo a1) {} }",
+ "namespace a { void f(b::Bar a1) {} }", "a::Foo", "b::Bar"},
+{"void f(MACRO(a::Foo) a1) {}", "void f(MACRO(b::Bar) a1) {}", "a::Foo",
+ "b::Bar"},
+{"void f(MACRO(a::Foo a1)) {}", "void f(MACRO(b::Bar a1)) {}", "a::Foo",
+ "b::Bar"},
+
+// use namespace and typedefs
+{"using a::Foo; Foo gA;", "using b::Bar; b::Bar gA;"},
+{"using a::Foo; void f(Foo gA) {}", "using b::Bar; void f(Bar gA) {}"},
+{"using a::Foo; namespace x { Foo gA; }",
+ "using b::Bar; namespace x { Bar gA; }"},
+{"struct S { using T = a::Foo; T a_; };",
+ "struct S { using T = b::Bar; T a_; };"},
+{"using T = a::Foo; T gA;", "using T = b::Bar; T gA;"},
+{"typedef a::Foo T; T gA;", "typedef b::Bar T; T gA;"},
+{"typedef MACRO(a::Foo) T; T gA;", "typedef MACRO(b::Bar) T; T gA;"},
+
+// struct members and other oddities
+{"struct S : public a::Foo {};", "struct S : public b::Bar {};"},
+{"struct F { void f(a::Foo a1) {} };",
+ "struct F { void f(b::Bar a1) {} };"},
+{"struct F { a::Foo a_; };", "struct F { b::Bar a_; };"},
+{"struct F { ptr a_; };", "struct F { ptr a_; };"},
+
+{"void f() { a::Foo::Nested ne; }", "void f() { b::Bar::Nested ne; }",
+ "a::Foo", "b::Bar"},
+{"void f() { a::Goo::Nested ne; }", "void f() { a::Goo::Nested ne; }",
+ "a::Foo", "b::Bar"},
+{"void f() { a::Foo::Nested::NestedEnum e; }",
+ "void f() { b::Bar::Nested::NestedEnum e; }", "a::Foo", "b::Bar"},
+{"void f() { auto e = a::Foo::Nested::NestedEnum::E1; }",
+ "void f() { auto e = b::Bar::Nested::NestedEnum::E1; }", "a::Foo",
+ "b::Bar"},
+{"void f() { auto e = a::Foo::Nested::E1; }",
+ "void f() { auto e = b::Bar::Nested::E1; }", "a::Foo", "b::Bar"},
+
+// templates
+{"template  struct Foo { T t; };\n"
+ "void f() { Foo foo; }",
+ "template  struct Foo { T t; };\n"
+ "void f() { Foo foo; }"},
+{"template  struct Foo { a::Foo a; };",
+ "template  struct Foo { b::Bar a; };"},
+{"template  void f(T t) {}\n"
+ "void g() { f(a::Foo()); }",
+ "template  void f(T t) {}\n"
+ "void g() { f(b::Bar()); }"},
+{"template  int f() { 

[PATCH] D31176: [clang-rename] Support renaming qualified symbol

2017-03-22 Thread Haojian Wu via Phabricator via cfe-commits
hokein added inline comments.



Comment at: clang-rename/USRLocFinder.cpp:157
+clang::NestedNameSpecifierLoc nested_name_specifier =
+TL.castAs().getQualifierLoc();
+if (nested_name_specifier.getNestedNameSpecifier())

ioeric wrote:
> Is this cast always safe? 
Yes, because we have checked the type of the TL is an elaborated type. I have 
changed to `getAs` which makes the indication more explicitly.



Comment at: clang-rename/USRLocFinder.cpp:196
+
+class RenameLocFindingASTVisitor
+: public clang::RecursiveASTVisitor {

ioeric wrote:
> ioeric wrote:
> > Comments.
> I think this visitor deserves a file of its own.
I'm not sure it is the right time to do it at the moment since it is in early 
stage. I'd keep it here. We can do it when needed. 



Comment at: clang-rename/USRLocFinder.cpp:368
+private:
+  bool IsTypeAliasWhichWillBeRenamedElsewhere(TypeLoc TL) const {
+while (!TL.isNull()) {

ioeric wrote:
> Note this is not expected behavior for alias types which would always be 
> skipped in this check.
Acked. Add a FIXME.


https://reviews.llvm.org/D31176



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D31492: Add `replace` interface with range in AtomicChange.

2017-03-30 Thread Haojian Wu via Phabricator via cfe-commits
hokein updated this revision to Diff 93467.
hokein added a comment.

Rebase to master.


https://reviews.llvm.org/D31492

Files:
  include/clang/Tooling/Refactoring/AtomicChange.h
  lib/Tooling/Refactoring/AtomicChange.cpp


Index: lib/Tooling/Refactoring/AtomicChange.cpp
===
--- lib/Tooling/Refactoring/AtomicChange.cpp
+++ lib/Tooling/Refactoring/AtomicChange.cpp
@@ -132,6 +132,12 @@
   return E;
 }
 
+llvm::Error AtomicChange::replace(const SourceManager ,
+  const CharSourceRange ,
+  llvm::StringRef ReplacementText) {
+  return Replaces.add(Replacement(SM, Range, ReplacementText));
+}
+
 llvm::Error AtomicChange::replace(const SourceManager , SourceLocation Loc,
   unsigned Length, llvm::StringRef Text) {
   return Replaces.add(Replacement(SM, Loc, Length, Text));
Index: include/clang/Tooling/Refactoring/AtomicChange.h
===
--- include/clang/Tooling/Refactoring/AtomicChange.h
+++ include/clang/Tooling/Refactoring/AtomicChange.h
@@ -70,6 +70,12 @@
   /// \brief Returns the error message or an empty string if it does not exist.
   const std::string () const { return Error; }
 
+  /// \brief Adds a replacement that replaces the given Range with
+  /// ReplacementText.
+  /// \returns An llvm::Error carrying ReplacementError on error.
+  llvm::Error replace(const SourceManager , const CharSourceRange ,
+  llvm::StringRef ReplacementText);
+
   /// \brief Adds a replacement that replaces range [Loc, Loc+Length) with
   /// \p Text.
   /// \returns An llvm::Error carrying ReplacementError on error.


Index: lib/Tooling/Refactoring/AtomicChange.cpp
===
--- lib/Tooling/Refactoring/AtomicChange.cpp
+++ lib/Tooling/Refactoring/AtomicChange.cpp
@@ -132,6 +132,12 @@
   return E;
 }
 
+llvm::Error AtomicChange::replace(const SourceManager ,
+  const CharSourceRange ,
+  llvm::StringRef ReplacementText) {
+  return Replaces.add(Replacement(SM, Range, ReplacementText));
+}
+
 llvm::Error AtomicChange::replace(const SourceManager , SourceLocation Loc,
   unsigned Length, llvm::StringRef Text) {
   return Replaces.add(Replacement(SM, Loc, Length, Text));
Index: include/clang/Tooling/Refactoring/AtomicChange.h
===
--- include/clang/Tooling/Refactoring/AtomicChange.h
+++ include/clang/Tooling/Refactoring/AtomicChange.h
@@ -70,6 +70,12 @@
   /// \brief Returns the error message or an empty string if it does not exist.
   const std::string () const { return Error; }
 
+  /// \brief Adds a replacement that replaces the given Range with
+  /// ReplacementText.
+  /// \returns An llvm::Error carrying ReplacementError on error.
+  llvm::Error replace(const SourceManager , const CharSourceRange ,
+  llvm::StringRef ReplacementText);
+
   /// \brief Adds a replacement that replaces range [Loc, Loc+Length) with
   /// \p Text.
   /// \returns An llvm::Error carrying ReplacementError on error.
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D31176: [clang-rename] Support renaming qualified symbol

2017-03-30 Thread Haojian Wu via Phabricator via cfe-commits
hokein updated this revision to Diff 93469.
hokein marked an inline comment as done.
hokein added a comment.

update comments.


https://reviews.llvm.org/D31176

Files:
  clang-rename/CMakeLists.txt
  clang-rename/RenamingAction.cpp
  clang-rename/RenamingAction.h
  clang-rename/USRFinder.cpp
  clang-rename/USRFindingAction.cpp
  clang-rename/USRLocFinder.cpp
  clang-rename/USRLocFinder.h
  unittests/clang-rename/CMakeLists.txt
  unittests/clang-rename/ClangRenameTest.h
  unittests/clang-rename/ClangRenameTests.cpp
  unittests/clang-rename/RenameClassTest.cpp

Index: unittests/clang-rename/RenameClassTest.cpp
===
--- /dev/null
+++ unittests/clang-rename/RenameClassTest.cpp
@@ -0,0 +1,668 @@
+//===-- RenameClassTest.cpp - unit tests for renaming classes -===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===--===//
+
+#include "ClangRenameTest.h"
+
+namespace clang {
+namespace clang_rename {
+namespace test {
+namespace {
+
+class RenameClassTest : public ClangRenameTest {
+public:
+  RenameClassTest() {
+AppendToHeader(R"(
+  namespace a {
+class Foo {
+  public:
+struct Nested {
+  enum NestedEnum {E1, E2};
+};
+void func() {}
+  static int Constant;
+};
+class Goo {
+  public:
+struct Nested {
+  enum NestedEnum {E1, E2};
+};
+};
+int Foo::Constant = 1;
+  } // namespace a
+  namespace b {
+  class Foo {};
+  } // namespace b
+
+  #define MACRO(x) x
+
+  template class ptr {};
+)");
+  }
+};
+
+INSTANTIATE_TEST_CASE_P(
+RenameClassTests, RenameClassTest,
+testing::ValuesIn(std::vector({
+// basic classes
+{"a::Foo f;", "b::Bar f;"},
+{"void f(a::Foo f) {}", "void f(b::Bar f) {}"},
+{"void f(a::Foo *f) {}", "void f(b::Bar *f) {}"},
+{"a::Foo f() { return a::Foo(); }", "b::Bar f() { return b::Bar(); }"},
+{"namespace a {a::Foo f() { return Foo(); }}",
+ "namespace a {b::Bar f() { return b::Bar(); }}"},
+{"void f(const a::Foo& a1) {}", "void f(const b::Bar& a1) {}"},
+{"void f(const a::Foo* a1) {}", "void f(const b::Bar* a1) {}"},
+{"namespace a { void f(Foo a1) {} }",
+ "namespace a { void f(b::Bar a1) {} }"},
+{"void f(MACRO(a::Foo) a1) {}", "void f(MACRO(b::Bar) a1) {}"},
+{"void f(MACRO(a::Foo a1)) {}", "void f(MACRO(b::Bar a1)) {}"},
+{"a::Foo::Nested ns;", "b::Bar::Nested ns;"},
+{"auto t = a::Foo::Constant;", "auto t = b::Bar::Constant;"},
+{"a::Foo::Nested ns;", "a::Foo::Nested2 ns;", "a::Foo::Nested",
+ "a::Foo::Nested2"},
+
+// use namespace and typedefs
+{"using a::Foo; Foo gA;", "using b::Bar; b::Bar gA;"},
+{"using a::Foo; void f(Foo gA) {}", "using b::Bar; void f(Bar gA) {}"},
+{"using a::Foo; namespace x { Foo gA; }",
+ "using b::Bar; namespace x { Bar gA; }"},
+{"struct S { using T = a::Foo; T a_; };",
+ "struct S { using T = b::Bar; T a_; };"},
+{"using T = a::Foo; T gA;", "using T = b::Bar; T gA;"},
+{"typedef a::Foo T; T gA;", "typedef b::Bar T; T gA;"},
+{"typedef MACRO(a::Foo) T; T gA;", "typedef MACRO(b::Bar) T; T gA;"},
+
+// struct members and other oddities
+{"struct S : public a::Foo {};", "struct S : public b::Bar {};"},
+{"struct F { void f(a::Foo a1) {} };",
+ "struct F { void f(b::Bar a1) {} };"},
+{"struct F { a::Foo a_; };", "struct F { b::Bar a_; };"},
+{"struct F { ptr a_; };", "struct F { ptr a_; };"},
+
+{"void f() { a::Foo::Nested ne; }", "void f() { b::Bar::Nested ne; }"},
+{"void f() { a::Goo::Nested ne; }", "void f() { a::Goo::Nested ne; }"},
+{"void f() { a::Foo::Nested::NestedEnum e; }",
+ "void f() { b::Bar::Nested::NestedEnum e; }"},
+{"void f() { auto e = a::Foo::Nested::NestedEnum::E1; }",
+ "void f() { auto e = b::Bar::Nested::NestedEnum::E1; }"},
+{"void f() { auto e = a::Foo::Nested::E1; }",
+ "void f() { auto e = b::Bar::Nested::E1; }"},
+
+// templates
+{"template  struct Foo { T t; };\n"
+ "void f() { Foo foo; }",
+ "template  struct Foo { T t; };\n"
+ "void f() { Foo foo; }"},
+{"template  struct Foo { a::Foo a; };",
+ "template  struct Foo { b::Bar a; };"},
+{"template  void f(T t) {}\n"
+ "void g() { f(a::Foo()); }",
+ "template  void f(T t) {}\n"
+ "void g() { f(b::Bar()); }"},
+{"template  int f() { return 1; }\n"
+ "template <> int f() { return 2; }\n"
+  

[PATCH] D31176: [clang-rename] Support renaming qualified symbol

2017-03-30 Thread Haojian Wu via Phabricator via cfe-commits
hokein added inline comments.



Comment at: clang-rename/USRLocFinder.cpp:359
+
+  // Returns a list of using declarations which are needed to update.
+  const std::vector () const {

ioeric wrote:
> hokein wrote:
> > ioeric wrote:
> > > I think these are using shadows only?
> > These are interested `UsingDecl`s which contain `UsingShadowDecl` of the 
> > symbol declarations being renamed.
> Sure. But maybe also document it?
I have documented it at the "UsingDecls" member definition.



Comment at: clang-rename/USRLocFinder.h:36
+/// \return Replacement for renaming.
+std::vector
+createRenameReplacement(llvm::ArrayRef USRs,

ioeric wrote:
> hokein wrote:
> > ioeric wrote:
> > > Why use `std::vector` instead of `tooling::Replacements`?
> > Seems that we don't get many benefits from using `tooling::Replacements` 
> > here. This function could be called multiple times (for renaming multiple 
> > symbols), we need to merge/add all replacements in caller side. if using 
> > `tooling::Replacements`, we will merge twice (one is in the API 
> > implementation).
> I think what we really want is `AtomicChange`. We shouldn't be using 
> `std::vector` or `std::set` replacements anymore.
Good idea. Done. I think we might still need to refine the interface in the 
future.


https://reviews.llvm.org/D31176



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D31492: Add `replace` interface with range in AtomicChange.

2017-03-30 Thread Haojian Wu via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL299073: Add `replace` interface with range in AtomicChange. 
(authored by hokein).

Changed prior to commit:
  https://reviews.llvm.org/D31492?vs=93472=93473#toc

Repository:
  rL LLVM

https://reviews.llvm.org/D31492

Files:
  cfe/trunk/include/clang/Tooling/Refactoring/AtomicChange.h
  cfe/trunk/lib/Tooling/Refactoring/AtomicChange.cpp
  cfe/trunk/unittests/Tooling/RefactoringTest.cpp

Index: cfe/trunk/include/clang/Tooling/Refactoring/AtomicChange.h
===
--- cfe/trunk/include/clang/Tooling/Refactoring/AtomicChange.h
+++ cfe/trunk/include/clang/Tooling/Refactoring/AtomicChange.h
@@ -70,6 +70,12 @@
   /// \brief Returns the error message or an empty string if it does not exist.
   const std::string () const { return Error; }
 
+  /// \brief Adds a replacement that replaces the given Range with
+  /// ReplacementText.
+  /// \returns An llvm::Error carrying ReplacementError on error.
+  llvm::Error replace(const SourceManager , const CharSourceRange ,
+  llvm::StringRef ReplacementText);
+
   /// \brief Adds a replacement that replaces range [Loc, Loc+Length) with
   /// \p Text.
   /// \returns An llvm::Error carrying ReplacementError on error.
Index: cfe/trunk/lib/Tooling/Refactoring/AtomicChange.cpp
===
--- cfe/trunk/lib/Tooling/Refactoring/AtomicChange.cpp
+++ cfe/trunk/lib/Tooling/Refactoring/AtomicChange.cpp
@@ -132,6 +132,12 @@
   return E;
 }
 
+llvm::Error AtomicChange::replace(const SourceManager ,
+  const CharSourceRange ,
+  llvm::StringRef ReplacementText) {
+  return Replaces.add(Replacement(SM, Range, ReplacementText));
+}
+
 llvm::Error AtomicChange::replace(const SourceManager , SourceLocation Loc,
   unsigned Length, llvm::StringRef Text) {
   return Replaces.add(Replacement(SM, Loc, Length, Text));
Index: cfe/trunk/unittests/Tooling/RefactoringTest.cpp
===
--- cfe/trunk/unittests/Tooling/RefactoringTest.cpp
+++ cfe/trunk/unittests/Tooling/RefactoringTest.cpp
@@ -1092,7 +1092,7 @@
 
 class AtomicChangeTest : public ::testing::Test {
   protected:
-void setUp() {
+void SetUp() override {
   DefaultFileID = Context.createInMemoryFile("input.cpp", DefaultCode);
   DefaultLoc = Context.Sources.getLocForStartOfFile(DefaultFileID)
.getLocWithOffset(20);
@@ -1107,7 +1107,6 @@
 };
 
 TEST_F(AtomicChangeTest, AtomicChangeToYAML) {
-  setUp();
   AtomicChange Change(Context.Sources, DefaultLoc);
   llvm::Error Err =
   Change.insert(Context.Sources, DefaultLoc, "aa", /*InsertAfter=*/false);
@@ -1140,7 +1139,6 @@
 }
 
 TEST_F(AtomicChangeTest, YAMLToAtomicChange) {
-  setUp();
   std::string YamlContent = "---\n"
 "Key: 'input.cpp:20'\n"
 "FilePath:input.cpp\n"
@@ -1187,14 +1185,12 @@
 }
 
 TEST_F(AtomicChangeTest, CheckKeyAndKeyFile) {
-  setUp();
   AtomicChange Change(Context.Sources, DefaultLoc);
   EXPECT_EQ("input.cpp:20", Change.getKey());
   EXPECT_EQ("input.cpp", Change.getFilePath());
 }
 
 TEST_F(AtomicChangeTest, Replace) {
-  setUp();
   AtomicChange Change(Context.Sources, DefaultLoc);
   llvm::Error Err = Change.replace(Context.Sources, DefaultLoc, 2, "aa");
   ASSERT_TRUE(!Err);
@@ -1209,8 +1205,18 @@
   EXPECT_EQ(Change.getReplacements().size(), 1u);
 }
 
+TEST_F(AtomicChangeTest, ReplaceWithRange) {
+  AtomicChange Change(Context.Sources, DefaultLoc);
+  SourceLocation End = DefaultLoc.getLocWithOffset(20);
+  llvm::Error Err = Change.replace(
+  Context.Sources, CharSourceRange::getCharRange(DefaultLoc, End), "aa");
+  ASSERT_TRUE(!Err);
+  EXPECT_EQ(Change.getReplacements().size(), 1u);
+  EXPECT_EQ(*Change.getReplacements().begin(),
+Replacement(Context.Sources, DefaultLoc, 20, "aa"));
+}
+
 TEST_F(AtomicChangeTest, InsertBefore) {
-  setUp();
   AtomicChange Change(Context.Sources, DefaultLoc);
   llvm::Error Err = Change.insert(Context.Sources, DefaultLoc, "aa");
   ASSERT_TRUE(!Err);
@@ -1225,7 +1231,6 @@
 }
 
 TEST_F(AtomicChangeTest, InsertAfter) {
-  setUp();
   AtomicChange Change(Context.Sources, DefaultLoc);
   llvm::Error Err = Change.insert(Context.Sources, DefaultLoc, "aa");
   ASSERT_TRUE(!Err);
@@ -1240,7 +1245,6 @@
 }
 
 TEST_F(AtomicChangeTest, InsertBeforeWithInvalidLocation) {
-  setUp();
   AtomicChange Change(Context.Sources, DefaultLoc);
   llvm::Error Err =
   Change.insert(Context.Sources, DefaultLoc, "a", /*InsertAfter=*/false);
@@ -1254,11 +1258,9 @@
   std::move(Err), replacement_error::wrong_file_path,
   Replacement(Context.Sources, DefaultLoc, 0, "a"),
   Replacement(Context.Sources, SourceLocation(), 0, 

[PATCH] D31492: Add `replace` interface with range in AtomicChange.

2017-03-30 Thread Haojian Wu via Phabricator via cfe-commits
hokein added a comment.

> are the tools like clang-rename, change-namespace and clang-reorder-fields 
> supposed to use AtomicChange (via the methods insert, replace etc) ?

Yeah. We are using AtomicChange in clang-rename refinement 
(https://reviews.llvm.org/D31176).


Repository:
  rL LLVM

https://reviews.llvm.org/D31492



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D31492: Add `replace` interface with range in AtomicChange.

2017-03-30 Thread Haojian Wu via Phabricator via cfe-commits
hokein updated this revision to Diff 93472.
hokein added a comment.

Add unittest.


https://reviews.llvm.org/D31492

Files:
  include/clang/Tooling/Refactoring/AtomicChange.h
  lib/Tooling/Refactoring/AtomicChange.cpp
  unittests/Tooling/RefactoringTest.cpp

Index: unittests/Tooling/RefactoringTest.cpp
===
--- unittests/Tooling/RefactoringTest.cpp
+++ unittests/Tooling/RefactoringTest.cpp
@@ -1092,7 +1092,7 @@
 
 class AtomicChangeTest : public ::testing::Test {
   protected:
-void setUp() {
+void SetUp() override {
   DefaultFileID = Context.createInMemoryFile("input.cpp", DefaultCode);
   DefaultLoc = Context.Sources.getLocForStartOfFile(DefaultFileID)
.getLocWithOffset(20);
@@ -1107,7 +1107,6 @@
 };
 
 TEST_F(AtomicChangeTest, AtomicChangeToYAML) {
-  setUp();
   AtomicChange Change(Context.Sources, DefaultLoc);
   llvm::Error Err =
   Change.insert(Context.Sources, DefaultLoc, "aa", /*InsertAfter=*/false);
@@ -1140,7 +1139,6 @@
 }
 
 TEST_F(AtomicChangeTest, YAMLToAtomicChange) {
-  setUp();
   std::string YamlContent = "---\n"
 "Key: 'input.cpp:20'\n"
 "FilePath:input.cpp\n"
@@ -1187,14 +1185,12 @@
 }
 
 TEST_F(AtomicChangeTest, CheckKeyAndKeyFile) {
-  setUp();
   AtomicChange Change(Context.Sources, DefaultLoc);
   EXPECT_EQ("input.cpp:20", Change.getKey());
   EXPECT_EQ("input.cpp", Change.getFilePath());
 }
 
 TEST_F(AtomicChangeTest, Replace) {
-  setUp();
   AtomicChange Change(Context.Sources, DefaultLoc);
   llvm::Error Err = Change.replace(Context.Sources, DefaultLoc, 2, "aa");
   ASSERT_TRUE(!Err);
@@ -1209,8 +1205,18 @@
   EXPECT_EQ(Change.getReplacements().size(), 1u);
 }
 
+TEST_F(AtomicChangeTest, ReplaceWithRange) {
+  AtomicChange Change(Context.Sources, DefaultLoc);
+  SourceLocation End = DefaultLoc.getLocWithOffset(20);
+  llvm::Error Err = Change.replace(
+  Context.Sources, CharSourceRange::getCharRange(DefaultLoc, End), "aa");
+  ASSERT_TRUE(!Err);
+  EXPECT_EQ(Change.getReplacements().size(), 1u);
+  EXPECT_EQ(*Change.getReplacements().begin(),
+Replacement(Context.Sources, DefaultLoc, 20, "aa"));
+}
+
 TEST_F(AtomicChangeTest, InsertBefore) {
-  setUp();
   AtomicChange Change(Context.Sources, DefaultLoc);
   llvm::Error Err = Change.insert(Context.Sources, DefaultLoc, "aa");
   ASSERT_TRUE(!Err);
@@ -1225,7 +1231,6 @@
 }
 
 TEST_F(AtomicChangeTest, InsertAfter) {
-  setUp();
   AtomicChange Change(Context.Sources, DefaultLoc);
   llvm::Error Err = Change.insert(Context.Sources, DefaultLoc, "aa");
   ASSERT_TRUE(!Err);
@@ -1240,7 +1245,6 @@
 }
 
 TEST_F(AtomicChangeTest, InsertBeforeWithInvalidLocation) {
-  setUp();
   AtomicChange Change(Context.Sources, DefaultLoc);
   llvm::Error Err =
   Change.insert(Context.Sources, DefaultLoc, "a", /*InsertAfter=*/false);
@@ -1254,11 +1258,9 @@
   std::move(Err), replacement_error::wrong_file_path,
   Replacement(Context.Sources, DefaultLoc, 0, "a"),
   Replacement(Context.Sources, SourceLocation(), 0, "a")));
-
 }
 
 TEST_F(AtomicChangeTest, InsertBeforeToWrongFile) {
-  setUp();
   AtomicChange Change(Context.Sources, DefaultLoc);
   llvm::Error Err =
   Change.insert(Context.Sources, DefaultLoc, "a", /*InsertAfter=*/false);
@@ -1276,7 +1278,6 @@
 }
 
 TEST_F(AtomicChangeTest, InsertAfterWithInvalidLocation) {
-  setUp();
   AtomicChange Change(Context.Sources, DefaultLoc);
   llvm::Error Err = Change.insert(Context.Sources, DefaultLoc, "a");
   ASSERT_TRUE(!Err);
Index: lib/Tooling/Refactoring/AtomicChange.cpp
===
--- lib/Tooling/Refactoring/AtomicChange.cpp
+++ lib/Tooling/Refactoring/AtomicChange.cpp
@@ -132,6 +132,12 @@
   return E;
 }
 
+llvm::Error AtomicChange::replace(const SourceManager ,
+  const CharSourceRange ,
+  llvm::StringRef ReplacementText) {
+  return Replaces.add(Replacement(SM, Range, ReplacementText));
+}
+
 llvm::Error AtomicChange::replace(const SourceManager , SourceLocation Loc,
   unsigned Length, llvm::StringRef Text) {
   return Replaces.add(Replacement(SM, Loc, Length, Text));
Index: include/clang/Tooling/Refactoring/AtomicChange.h
===
--- include/clang/Tooling/Refactoring/AtomicChange.h
+++ include/clang/Tooling/Refactoring/AtomicChange.h
@@ -70,6 +70,12 @@
   /// \brief Returns the error message or an empty string if it does not exist.
   const std::string () const { return Error; }
 
+  /// \brief Adds a replacement that replaces the given Range with
+  /// ReplacementText.
+  /// \returns An llvm::Error carrying ReplacementError on error.
+  llvm::Error replace(const SourceManager , const CharSourceRange ,
+  llvm::StringRef ReplacementText);

[PATCH] D31176: [clang-rename] Support renaming qualified symbol

2017-03-30 Thread Haojian Wu via Phabricator via cfe-commits
hokein updated this revision to Diff 93474.
hokein marked 2 inline comments as done.
hokein added a comment.

Fix a few nits.


https://reviews.llvm.org/D31176

Files:
  clang-rename/CMakeLists.txt
  clang-rename/RenamingAction.cpp
  clang-rename/RenamingAction.h
  clang-rename/USRFinder.cpp
  clang-rename/USRFindingAction.cpp
  clang-rename/USRLocFinder.cpp
  clang-rename/USRLocFinder.h
  unittests/clang-rename/CMakeLists.txt
  unittests/clang-rename/ClangRenameTest.h
  unittests/clang-rename/ClangRenameTests.cpp
  unittests/clang-rename/RenameClassTest.cpp

Index: unittests/clang-rename/RenameClassTest.cpp
===
--- /dev/null
+++ unittests/clang-rename/RenameClassTest.cpp
@@ -0,0 +1,668 @@
+//===-- RenameClassTest.cpp - unit tests for renaming classes -===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===--===//
+
+#include "ClangRenameTest.h"
+
+namespace clang {
+namespace clang_rename {
+namespace test {
+namespace {
+
+class RenameClassTest : public ClangRenameTest {
+public:
+  RenameClassTest() {
+AppendToHeader(R"(
+  namespace a {
+class Foo {
+  public:
+struct Nested {
+  enum NestedEnum {E1, E2};
+};
+void func() {}
+  static int Constant;
+};
+class Goo {
+  public:
+struct Nested {
+  enum NestedEnum {E1, E2};
+};
+};
+int Foo::Constant = 1;
+  } // namespace a
+  namespace b {
+  class Foo {};
+  } // namespace b
+
+  #define MACRO(x) x
+
+  template class ptr {};
+)");
+  }
+};
+
+INSTANTIATE_TEST_CASE_P(
+RenameClassTests, RenameClassTest,
+testing::ValuesIn(std::vector({
+// basic classes
+{"a::Foo f;", "b::Bar f;"},
+{"void f(a::Foo f) {}", "void f(b::Bar f) {}"},
+{"void f(a::Foo *f) {}", "void f(b::Bar *f) {}"},
+{"a::Foo f() { return a::Foo(); }", "b::Bar f() { return b::Bar(); }"},
+{"namespace a {a::Foo f() { return Foo(); }}",
+ "namespace a {b::Bar f() { return b::Bar(); }}"},
+{"void f(const a::Foo& a1) {}", "void f(const b::Bar& a1) {}"},
+{"void f(const a::Foo* a1) {}", "void f(const b::Bar* a1) {}"},
+{"namespace a { void f(Foo a1) {} }",
+ "namespace a { void f(b::Bar a1) {} }"},
+{"void f(MACRO(a::Foo) a1) {}", "void f(MACRO(b::Bar) a1) {}"},
+{"void f(MACRO(a::Foo a1)) {}", "void f(MACRO(b::Bar a1)) {}"},
+{"a::Foo::Nested ns;", "b::Bar::Nested ns;"},
+{"auto t = a::Foo::Constant;", "auto t = b::Bar::Constant;"},
+{"a::Foo::Nested ns;", "a::Foo::Nested2 ns;", "a::Foo::Nested",
+ "a::Foo::Nested2"},
+
+// use namespace and typedefs
+{"using a::Foo; Foo gA;", "using b::Bar; b::Bar gA;"},
+{"using a::Foo; void f(Foo gA) {}", "using b::Bar; void f(Bar gA) {}"},
+{"using a::Foo; namespace x { Foo gA; }",
+ "using b::Bar; namespace x { Bar gA; }"},
+{"struct S { using T = a::Foo; T a_; };",
+ "struct S { using T = b::Bar; T a_; };"},
+{"using T = a::Foo; T gA;", "using T = b::Bar; T gA;"},
+{"typedef a::Foo T; T gA;", "typedef b::Bar T; T gA;"},
+{"typedef MACRO(a::Foo) T; T gA;", "typedef MACRO(b::Bar) T; T gA;"},
+
+// struct members and other oddities
+{"struct S : public a::Foo {};", "struct S : public b::Bar {};"},
+{"struct F { void f(a::Foo a1) {} };",
+ "struct F { void f(b::Bar a1) {} };"},
+{"struct F { a::Foo a_; };", "struct F { b::Bar a_; };"},
+{"struct F { ptr a_; };", "struct F { ptr a_; };"},
+
+{"void f() { a::Foo::Nested ne; }", "void f() { b::Bar::Nested ne; }"},
+{"void f() { a::Goo::Nested ne; }", "void f() { a::Goo::Nested ne; }"},
+{"void f() { a::Foo::Nested::NestedEnum e; }",
+ "void f() { b::Bar::Nested::NestedEnum e; }"},
+{"void f() { auto e = a::Foo::Nested::NestedEnum::E1; }",
+ "void f() { auto e = b::Bar::Nested::NestedEnum::E1; }"},
+{"void f() { auto e = a::Foo::Nested::E1; }",
+ "void f() { auto e = b::Bar::Nested::E1; }"},
+
+// templates
+{"template  struct Foo { T t; };\n"
+ "void f() { Foo foo; }",
+ "template  struct Foo { T t; };\n"
+ "void f() { Foo foo; }"},
+{"template  struct Foo { a::Foo a; };",
+ "template  struct Foo { b::Bar a; };"},
+{"template  void f(T t) {}\n"
+ "void g() { f(a::Foo()); }",
+ "template  void f(T t) {}\n"
+ "void g() { f(b::Bar()); }"},
+{"template  int f() { return 1; }\n"
+ "template <> int f() { return 2; }\n"
+   

[PATCH] D31176: [clang-rename] Support renaming qualified symbol

2017-03-30 Thread Haojian Wu via Phabricator via cfe-commits
hokein updated this revision to Diff 93468.
hokein marked 2 inline comments as done.
hokein added a comment.

Use AtomicChange.


https://reviews.llvm.org/D31176

Files:
  clang-rename/CMakeLists.txt
  clang-rename/RenamingAction.cpp
  clang-rename/RenamingAction.h
  clang-rename/USRFinder.cpp
  clang-rename/USRFindingAction.cpp
  clang-rename/USRLocFinder.cpp
  clang-rename/USRLocFinder.h
  unittests/clang-rename/CMakeLists.txt
  unittests/clang-rename/ClangRenameTest.h
  unittests/clang-rename/ClangRenameTests.cpp
  unittests/clang-rename/RenameClassTest.cpp

Index: unittests/clang-rename/RenameClassTest.cpp
===
--- /dev/null
+++ unittests/clang-rename/RenameClassTest.cpp
@@ -0,0 +1,668 @@
+//===-- RenameClassTest.cpp - unit tests for renaming classes -===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===--===//
+
+#include "ClangRenameTest.h"
+
+namespace clang {
+namespace clang_rename {
+namespace test {
+namespace {
+
+class RenameClassTest : public ClangRenameTest {
+public:
+  RenameClassTest() {
+AppendToHeader(R"(
+  namespace a {
+class Foo {
+  public:
+struct Nested {
+  enum NestedEnum {E1, E2};
+};
+void func() {}
+  static int Constant;
+};
+class Goo {
+  public:
+struct Nested {
+  enum NestedEnum {E1, E2};
+};
+};
+int Foo::Constant = 1;
+  } // namespace a
+  namespace b {
+  class Foo {};
+  } // namespace b
+
+  #define MACRO(x) x
+
+  template class ptr {};
+)");
+  }
+};
+
+INSTANTIATE_TEST_CASE_P(
+RenameClassTests, RenameClassTest,
+testing::ValuesIn(std::vector({
+// basic classes
+{"a::Foo f;", "b::Bar f;"},
+{"void f(a::Foo f) {}", "void f(b::Bar f) {}"},
+{"void f(a::Foo *f) {}", "void f(b::Bar *f) {}"},
+{"a::Foo f() { return a::Foo(); }", "b::Bar f() { return b::Bar(); }"},
+{"namespace a {a::Foo f() { return Foo(); }}",
+ "namespace a {b::Bar f() { return b::Bar(); }}"},
+{"void f(const a::Foo& a1) {}", "void f(const b::Bar& a1) {}"},
+{"void f(const a::Foo* a1) {}", "void f(const b::Bar* a1) {}"},
+{"namespace a { void f(Foo a1) {} }",
+ "namespace a { void f(b::Bar a1) {} }"},
+{"void f(MACRO(a::Foo) a1) {}", "void f(MACRO(b::Bar) a1) {}"},
+{"void f(MACRO(a::Foo a1)) {}", "void f(MACRO(b::Bar a1)) {}"},
+{"a::Foo::Nested ns;", "b::Bar::Nested ns;"},
+{"auto t = a::Foo::Constant;", "auto t = b::Bar::Constant;"},
+{"a::Foo::Nested ns;", "a::Foo::Nested2 ns;", "a::Foo::Nested",
+ "a::Foo::Nested2"},
+
+// use namespace and typedefs
+{"using a::Foo; Foo gA;", "using b::Bar; b::Bar gA;"},
+{"using a::Foo; void f(Foo gA) {}", "using b::Bar; void f(Bar gA) {}"},
+{"using a::Foo; namespace x { Foo gA; }",
+ "using b::Bar; namespace x { Bar gA; }"},
+{"struct S { using T = a::Foo; T a_; };",
+ "struct S { using T = b::Bar; T a_; };"},
+{"using T = a::Foo; T gA;", "using T = b::Bar; T gA;"},
+{"typedef a::Foo T; T gA;", "typedef b::Bar T; T gA;"},
+{"typedef MACRO(a::Foo) T; T gA;", "typedef MACRO(b::Bar) T; T gA;"},
+
+// struct members and other oddities
+{"struct S : public a::Foo {};", "struct S : public b::Bar {};"},
+{"struct F { void f(a::Foo a1) {} };",
+ "struct F { void f(b::Bar a1) {} };"},
+{"struct F { a::Foo a_; };", "struct F { b::Bar a_; };"},
+{"struct F { ptr a_; };", "struct F { ptr a_; };"},
+
+{"void f() { a::Foo::Nested ne; }", "void f() { b::Bar::Nested ne; }"},
+{"void f() { a::Goo::Nested ne; }", "void f() { a::Goo::Nested ne; }"},
+{"void f() { a::Foo::Nested::NestedEnum e; }",
+ "void f() { b::Bar::Nested::NestedEnum e; }"},
+{"void f() { auto e = a::Foo::Nested::NestedEnum::E1; }",
+ "void f() { auto e = b::Bar::Nested::NestedEnum::E1; }"},
+{"void f() { auto e = a::Foo::Nested::E1; }",
+ "void f() { auto e = b::Bar::Nested::E1; }"},
+
+// templates
+{"template  struct Foo { T t; };\n"
+ "void f() { Foo foo; }",
+ "template  struct Foo { T t; };\n"
+ "void f() { Foo foo; }"},
+{"template  struct Foo { a::Foo a; };",
+ "template  struct Foo { b::Bar a; };"},
+{"template  void f(T t) {}\n"
+ "void g() { f(a::Foo()); }",
+ "template  void f(T t) {}\n"
+ "void g() { f(b::Bar()); }"},
+{"template  int f() { return 1; }\n"
+ "template <> int f() { return 2; }\n"
+ 

[PATCH] D31492: Add `addReplacement` interface in AtomicChange.

2017-03-30 Thread Haojian Wu via Phabricator via cfe-commits
hokein created this revision.
Herald added a subscriber: klimek.

https://reviews.llvm.org/D31492

Files:
  include/clang/Tooling/Refactoring/AtomicChange.h
  lib/Tooling/Refactoring/AtomicChange.cpp


Index: lib/Tooling/Refactoring/AtomicChange.cpp
===
--- lib/Tooling/Refactoring/AtomicChange.cpp
+++ lib/Tooling/Refactoring/AtomicChange.cpp
@@ -132,6 +132,10 @@
   return E;
 }
 
+llvm::Error AtomicChange::addReplacement(const Replacement& R) {
+  return Replaces.add(R);
+}
+
 llvm::Error AtomicChange::insert(const SourceManager , SourceLocation Loc,
  llvm::StringRef Text, bool InsertAfter) {
   if (Text.empty())
Index: include/clang/Tooling/Refactoring/AtomicChange.h
===
--- include/clang/Tooling/Refactoring/AtomicChange.h
+++ include/clang/Tooling/Refactoring/AtomicChange.h
@@ -70,6 +70,9 @@
   /// \brief Returns the error message or an empty string if it does not exist.
   const std::string () const { return Error; }
 
+  /// \brief Adds a replacement to the atomic change.
+  llvm::Error addReplacement(const Replacement& R);
+
   /// \brief Adds a replacement that replaces range [Loc, Loc+Length) with
   /// \p Text.
   /// \returns An llvm::Error carrying ReplacementError on error.


Index: lib/Tooling/Refactoring/AtomicChange.cpp
===
--- lib/Tooling/Refactoring/AtomicChange.cpp
+++ lib/Tooling/Refactoring/AtomicChange.cpp
@@ -132,6 +132,10 @@
   return E;
 }
 
+llvm::Error AtomicChange::addReplacement(const Replacement& R) {
+  return Replaces.add(R);
+}
+
 llvm::Error AtomicChange::insert(const SourceManager , SourceLocation Loc,
  llvm::StringRef Text, bool InsertAfter) {
   if (Text.empty())
Index: include/clang/Tooling/Refactoring/AtomicChange.h
===
--- include/clang/Tooling/Refactoring/AtomicChange.h
+++ include/clang/Tooling/Refactoring/AtomicChange.h
@@ -70,6 +70,9 @@
   /// \brief Returns the error message or an empty string if it does not exist.
   const std::string () const { return Error; }
 
+  /// \brief Adds a replacement to the atomic change.
+  llvm::Error addReplacement(const Replacement& R);
+
   /// \brief Adds a replacement that replaces range [Loc, Loc+Length) with
   /// \p Text.
   /// \returns An llvm::Error carrying ReplacementError on error.
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D31492: Add `addReplacement` interface in AtomicChange.

2017-03-30 Thread Haojian Wu via Phabricator via cfe-commits
hokein updated this revision to Diff 93456.
hokein added a comment.

Get rid of Replacement, and implement "replace" interface with range.


https://reviews.llvm.org/D31492

Files:
  include/clang/Tooling/Refactoring/AtomicChange.h
  lib/Tooling/Refactoring/AtomicChange.cpp


Index: lib/Tooling/Refactoring/AtomicChange.cpp
===
--- lib/Tooling/Refactoring/AtomicChange.cpp
+++ lib/Tooling/Refactoring/AtomicChange.cpp
@@ -132,6 +132,12 @@
   return E;
 }
 
+llvm::Error AtomicChange::replace(const SourceManager ,
+  const CharSourceRange ,
+  llvm::StringRef ReplacementText) {
+  return Replacements.add(Replacement(SM, Range, ReplacementText));
+}
+
 llvm::Error AtomicChange::insert(const SourceManager , SourceLocation Loc,
  llvm::StringRef Text, bool InsertAfter) {
   if (Text.empty())
Index: include/clang/Tooling/Refactoring/AtomicChange.h
===
--- include/clang/Tooling/Refactoring/AtomicChange.h
+++ include/clang/Tooling/Refactoring/AtomicChange.h
@@ -70,6 +70,12 @@
   /// \brief Returns the error message or an empty string if it does not exist.
   const std::string () const { return Error; }
 
+  /// \brief Adds a replacement that replaces the given Range with
+  /// ReplacementText.
+  /// \returns An llvm::Error carrying ReplacementError on error.
+  llvm::Error replace(const SourceManager , const CharSourceRange ,
+  llvm::StringRef ReplacementText);
+
   /// \brief Adds a replacement that replaces range [Loc, Loc+Length) with
   /// \p Text.
   /// \returns An llvm::Error carrying ReplacementError on error.


Index: lib/Tooling/Refactoring/AtomicChange.cpp
===
--- lib/Tooling/Refactoring/AtomicChange.cpp
+++ lib/Tooling/Refactoring/AtomicChange.cpp
@@ -132,6 +132,12 @@
   return E;
 }
 
+llvm::Error AtomicChange::replace(const SourceManager ,
+  const CharSourceRange ,
+  llvm::StringRef ReplacementText) {
+  return Replacements.add(Replacement(SM, Range, ReplacementText));
+}
+
 llvm::Error AtomicChange::insert(const SourceManager , SourceLocation Loc,
  llvm::StringRef Text, bool InsertAfter) {
   if (Text.empty())
Index: include/clang/Tooling/Refactoring/AtomicChange.h
===
--- include/clang/Tooling/Refactoring/AtomicChange.h
+++ include/clang/Tooling/Refactoring/AtomicChange.h
@@ -70,6 +70,12 @@
   /// \brief Returns the error message or an empty string if it does not exist.
   const std::string () const { return Error; }
 
+  /// \brief Adds a replacement that replaces the given Range with
+  /// ReplacementText.
+  /// \returns An llvm::Error carrying ReplacementError on error.
+  llvm::Error replace(const SourceManager , const CharSourceRange ,
+  llvm::StringRef ReplacementText);
+
   /// \brief Adds a replacement that replaces range [Loc, Loc+Length) with
   /// \p Text.
   /// \returns An llvm::Error carrying ReplacementError on error.
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D31176: [clang-rename] Support renaming qualified symbol

2017-03-24 Thread Haojian Wu via Phabricator via cfe-commits
hokein updated this revision to Diff 92954.
hokein marked 3 inline comments as done.
hokein added a comment.

Add comments and polish tests.


https://reviews.llvm.org/D31176

Files:
  clang-rename/RenamingAction.cpp
  clang-rename/RenamingAction.h
  clang-rename/USRFinder.cpp
  clang-rename/USRFindingAction.cpp
  clang-rename/USRLocFinder.cpp
  clang-rename/USRLocFinder.h
  unittests/clang-rename/CMakeLists.txt
  unittests/clang-rename/ClangRenameTest.h
  unittests/clang-rename/ClangRenameTests.cpp
  unittests/clang-rename/RenameClassTest.cpp

Index: unittests/clang-rename/RenameClassTest.cpp
===
--- /dev/null
+++ unittests/clang-rename/RenameClassTest.cpp
@@ -0,0 +1,668 @@
+//===-- RenameClassTest.cpp - unit tests for renaming classes -===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===--===//
+
+#include "ClangRenameTest.h"
+
+namespace clang {
+namespace clang_rename {
+namespace test {
+namespace {
+
+class RenameClassTest : public ClangRenameTest {
+public:
+  RenameClassTest() {
+AppendToHeader(R"(
+  namespace a {
+class Foo {
+  public:
+struct Nested {
+  enum NestedEnum {E1, E2};
+};
+void func() {}
+  static int Constant;
+};
+class Goo {
+  public:
+struct Nested {
+  enum NestedEnum {E1, E2};
+};
+};
+int Foo::Constant = 1;
+  } // namespace a
+  namespace b {
+  class Foo {};
+  } // namespace b
+
+  #define MACRO(x) x
+
+  template class ptr {};
+)");
+  }
+};
+
+INSTANTIATE_TEST_CASE_P(
+RenameClassTests, RenameClassTest,
+testing::ValuesIn(std::vector({
+// basic classes
+{"a::Foo f;", "b::Bar f;"},
+{"void f(a::Foo f) {}", "void f(b::Bar f) {}"},
+{"void f(a::Foo *f) {}", "void f(b::Bar *f) {}"},
+{"a::Foo f() { return a::Foo(); }", "b::Bar f() { return b::Bar(); }"},
+{"namespace a {a::Foo f() { return Foo(); }}",
+ "namespace a {b::Bar f() { return b::Bar(); }}"},
+{"void f(const a::Foo& a1) {}", "void f(const b::Bar& a1) {}"},
+{"void f(const a::Foo* a1) {}", "void f(const b::Bar* a1) {}"},
+{"namespace a { void f(Foo a1) {} }",
+ "namespace a { void f(b::Bar a1) {} }"},
+{"void f(MACRO(a::Foo) a1) {}", "void f(MACRO(b::Bar) a1) {}"},
+{"void f(MACRO(a::Foo a1)) {}", "void f(MACRO(b::Bar a1)) {}"},
+{"a::Foo::Nested ns;", "b::Bar::Nested ns;"},
+{"auto t = a::Foo::Constant;", "auto t = b::Bar::Constant;"},
+{"a::Foo::Nested ns;", "a::Foo::Nested2 ns;", "a::Foo::Nested",
+ "a::Foo::Nested2"},
+
+// use namespace and typedefs
+{"using a::Foo; Foo gA;", "using b::Bar; b::Bar gA;"},
+{"using a::Foo; void f(Foo gA) {}", "using b::Bar; void f(Bar gA) {}"},
+{"using a::Foo; namespace x { Foo gA; }",
+ "using b::Bar; namespace x { Bar gA; }"},
+{"struct S { using T = a::Foo; T a_; };",
+ "struct S { using T = b::Bar; T a_; };"},
+{"using T = a::Foo; T gA;", "using T = b::Bar; T gA;"},
+{"typedef a::Foo T; T gA;", "typedef b::Bar T; T gA;"},
+{"typedef MACRO(a::Foo) T; T gA;", "typedef MACRO(b::Bar) T; T gA;"},
+
+// struct members and other oddities
+{"struct S : public a::Foo {};", "struct S : public b::Bar {};"},
+{"struct F { void f(a::Foo a1) {} };",
+ "struct F { void f(b::Bar a1) {} };"},
+{"struct F { a::Foo a_; };", "struct F { b::Bar a_; };"},
+{"struct F { ptr a_; };", "struct F { ptr a_; };"},
+
+{"void f() { a::Foo::Nested ne; }", "void f() { b::Bar::Nested ne; }"},
+{"void f() { a::Goo::Nested ne; }", "void f() { a::Goo::Nested ne; }"},
+{"void f() { a::Foo::Nested::NestedEnum e; }",
+ "void f() { b::Bar::Nested::NestedEnum e; }"},
+{"void f() { auto e = a::Foo::Nested::NestedEnum::E1; }",
+ "void f() { auto e = b::Bar::Nested::NestedEnum::E1; }"},
+{"void f() { auto e = a::Foo::Nested::E1; }",
+ "void f() { auto e = b::Bar::Nested::E1; }"},
+
+// templates
+{"template  struct Foo { T t; };\n"
+ "void f() { Foo foo; }",
+ "template  struct Foo { T t; };\n"
+ "void f() { Foo foo; }"},
+{"template  struct Foo { a::Foo a; };",
+ "template  struct Foo { b::Bar a; };"},
+{"template  void f(T t) {}\n"
+ "void g() { f(a::Foo()); }",
+ "template  void f(T t) {}\n"
+ "void g() { f(b::Bar()); }"},
+{"template  int f() { return 1; }\n"
+ "template <> int f() { return 2; }\n"
+ "int g() 

[PATCH] D31176: [clang-rename] Support renaming qualified symbol

2017-03-24 Thread Haojian Wu via Phabricator via cfe-commits
hokein added inline comments.



Comment at: clang-rename/USRLocFinder.cpp:195
+// Find all locations identified by the given USRs. Traverse the AST and find
+// every AST node whose USR is in the given USRs' set.
+class RenameLocFinder

ioeric wrote:
> I think this also does some renaming?
No, this class is only responsible for finding rename locations and other 
information which are used for renaming. The renaming stuff is done by 
`USRSymbolRenamer`.



Comment at: clang-rename/USRLocFinder.cpp:217
+
+  // FIXME: For renaming declarations/definitions, prefix qualifiers should be
+  // filtered out.

ioeric wrote:
> Could you be more specific in this FIXME? I don't quite get it. Maybe an 
> example?
You can also see the `FIXME` in the test.



Comment at: clang-rename/USRLocFinder.cpp:359
+
+  // Returns a list of using declarations which are needed to update.
+  const std::vector () const {

ioeric wrote:
> I think these are using shadows only?
These are interested `UsingDecl`s which contain `UsingShadowDecl` of the symbol 
declarations being renamed.



Comment at: clang-rename/USRLocFinder.h:36
+/// \return Replacement for renaming.
+std::vector
+createRenameReplacement(llvm::ArrayRef USRs,

ioeric wrote:
> Why use `std::vector` instead of `tooling::Replacements`?
Seems that we don't get many benefits from using `tooling::Replacements` here. 
This function could be called multiple times (for renaming multiple symbols), 
we need to merge/add all replacements in caller side. if using 
`tooling::Replacements`, we will merge twice (one is in the API implementation).


https://reviews.llvm.org/D31176



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D31076: [change-namespace] do not rename specialized template parameters.

2017-03-17 Thread Haojian Wu via Phabricator via cfe-commits
hokein accepted this revision.
hokein added a comment.
This revision is now accepted and ready to land.

LGTM.


https://reviews.llvm.org/D31076



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D30493: [change-namespace] avoid adding leading '::' when possible.

2017-03-21 Thread Haojian Wu via Phabricator via cfe-commits
hokein accepted this revision.
hokein added a comment.
This revision is now accepted and ready to land.

Sorry, I missed this patch.

LGTM with one nit.




Comment at: change-namespace/ChangeNamespace.cpp:296
+assert(!NsSplitted.empty());
+for (auto I = NsSplitted.begin() + 1, E = NsSplitted.end(); I != E; ++I) {
+  if (*I == SymbolSplitted.front())

ioeric wrote:
> hokein wrote:
> > Why skipping the first element? And use `is_contained` instead?
> See newly added comments for reasoning.
I see. This sounds the `conflictInNamespace` is too coupled with caller because 
it relies on "it equals to the symbol's outermost namespace and the symbol name 
would have been shortened" assumption. It is not straightforward especially for 
readers who read the code at the first time.  So I'd like to search from 0 (and 
this operation is trivial). 


https://reviews.llvm.org/D30493



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D31757: [clang-tidy] Add a clang-tidy check for possible inefficient vector operations

2017-04-10 Thread Haojian Wu via Phabricator via cfe-commits
hokein updated this revision to Diff 94734.
hokein marked 7 inline comments as done.
hokein added a comment.

Address review comments.


https://reviews.llvm.org/D31757

Files:
  clang-tidy/performance/CMakeLists.txt
  clang-tidy/performance/InefficientVectorOperationCheck.cpp
  clang-tidy/performance/InefficientVectorOperationCheck.h
  clang-tidy/performance/PerformanceTidyModule.cpp
  docs/ReleaseNotes.rst
  docs/clang-tidy/checks/list.rst
  docs/clang-tidy/checks/performance-inefficient-vector-operation.rst
  test/clang-tidy/performance-inefficient-vector-operation.cpp

Index: test/clang-tidy/performance-inefficient-vector-operation.cpp
===
--- /dev/null
+++ test/clang-tidy/performance-inefficient-vector-operation.cpp
@@ -0,0 +1,120 @@
+// RUN: %check_clang_tidy %s performance-inefficient-vector-operation %t -- -format-style=llvm --
+
+typedef int size_t;
+
+namespace std {
+template 
+class vector {
+ public:
+  typedef T* iterator;
+  typedef const T* const_iterator;
+  typedef T& reference;
+  typedef const T& const_reference;
+  typedef size_t size_type;
+
+  explicit vector();
+  explicit vector(size_type n);
+
+  void push_back(const T& val);
+  void reserve(size_t n);
+  size_t size();
+  const_reference operator[] (size_type) const;
+  reference operator[] (size_type);
+};
+} // namespace std
+
+void f(std::vector& t) {
+  {
+std::vector v;
+// CHECK-FIXES: v.reserve(10);
+for (int i = 0; i < 10; ++i)
+  v.push_back(i);
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: 'push_back' is called inside a loop; consider pre-allocating the vector capacity before the loop
+  }
+  {
+std::vector v;
+std::vector v2;
+v2.reserve(3);
+// CHECK-FIXES: v.reserve(10);
+for (int i = 0; i < 10; ++i)
+  v.push_back(i);
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: 'push_back' is called
+  }
+  {
+std::vector v;
+// CHECK-FIXES: v.reserve(t.size());
+for (size_t i = 0; i < t.size(); ++i) {
+  v.push_back(t[i]);
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: 'push_back' is called
+}
+  }
+  {
+std::vector v;
+// CHECK-FIXES: v.reserve(t.size() - 1);
+for (size_t i = 0; i < t.size() - 1; ++i) {
+  v.push_back(t[i]);
+} // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: 'push_back' is called
+  }
+
+  //  Non-fixed Cases 
+  {
+std::vector v;
+v.reserve(20);
+// CHECK-FIXES-NOT: v.reserve(10);
+// There is a "reserve" call already.
+for (int i = 0; i < 10; ++i) {
+  v.push_back(i);
+}
+  }
+  {
+std::vector v;
+v.reserve(5);
+// CHECK-FIXES-NOT: v.reserve(10);
+// There is a "reserve" call already.
+for (int i = 0; i < 10; ++i) {
+  v.push_back(i);
+}
+  }
+  {
+std::vector v(20);
+// CHECK-FIXES-NOT: v.reserve(10);
+// v is not constructed with default constructor.
+for (int i = 0; i < 10; ++i) {
+  v.push_back(i);
+}
+  }
+  {
+std::vector v;
+// CHECK-FIXES-NOT: v.reserve(10);
+// For-loop is not started with 0.
+for (int i = 1; i < 10; ++i) {
+  v.push_back(i);
+}
+  }
+  {
+std::vector v;
+// CHECK-FIXES-NOT: v.reserve(t.size());
+// v isn't referenced in for-loop body.
+for (size_t i = 0; i < t.size(); ++i) {
+  t.push_back(i);
+}
+  }
+  {
+std::vector v;
+int k;
+// CHECK-FIXES-NOT: v.reserve(10);
+// For-loop isn't a fixable loop.
+for (size_t i = 0; k < 10; ++i) {
+  v.push_back(t[i]);
+}
+  }
+  {
+std::vector v;
+int k;
+// CHECK-FIXES-NOT: v.reserve(10);
+// For-loop isn't a fixable loop.
+for (size_t i = 0; i < 10; ++k) {
+  v.push_back(t[i]);
+}
+  }
+}
Index: docs/clang-tidy/checks/performance-inefficient-vector-operation.rst
===
--- /dev/null
+++ docs/clang-tidy/checks/performance-inefficient-vector-operation.rst
@@ -0,0 +1,17 @@
+.. title:: clang-tidy - performance-inefficient-vector-operation
+
+performance-inefficient-vector-operation
+
+
+Finds possible inefficient `std::vector` operations (e.g. `push_back`) that may
+cause unnecessary memory reallocations.
+
+.. code-block:: c++
+
+  std::vector v;
+  for (int i = 0; i < n; ++i) {
+v.push_back(n);
+// This will trigger the warning since the push_back may cause multiple
+// memory reallocations in v. This can be avoid by inserting a reserve(n)
+// statment before the for statment.
+  }
Index: docs/clang-tidy/checks/list.rst
===
--- docs/clang-tidy/checks/list.rst
+++ docs/clang-tidy/checks/list.rst
@@ -141,6 +141,7 @@
performance-for-range-copy
performance-implicit-cast-in-loop
performance-inefficient-string-concatenation
+   performance-inefficient-vector-operation
performance-type-promotion-in-math-fn

[PATCH] D31757: [clang-tidy] Add a clang-tidy check for possible inefficient vector operations

2017-04-10 Thread Haojian Wu via Phabricator via cfe-commits
hokein added inline comments.



Comment at: clang-tidy/performance/InefficientVectorOperationCheck.cpp:22
+void InefficientVectorOperationCheck::registerMatchers(MatchFinder *Finder) {
+  const auto VectorDecl = cxxRecordDecl(hasName("std::vector"));
+  const auto VectorDefaultConstructorCall = cxxConstructExpr(

aaron.ballman wrote:
> Why does this check only focus on vector? Other containers allow you to 
> preallocate space for their elements or lend themselves to inefficient 
> operations.
> 
> Also, this should be checking `::std::vector` instead.
> Why does this check only focus on vector? Other containers allow you to 
> preallocate space for their elements or lend themselves to inefficient 
> operations.

Only a few std containers (`vector`, `unordered_map`, `unorder_set`) provide 
the preallocate ability ("reserve") to users. `vector` is the most widely used 
container with these inefficient operations in the real world. 

Yes, we could extend this check to support other containers, but it will make 
the check more complicated (in the future, I plan to support for-range loops 
and for loops with iterators, and use other  elegant fix-it solutions like 
"range insert" or "range constructor" in some specific cases rather than merely 
inserting `reserve` statements).  So I think it makes more sense to make this 
check only focus on `vector`.




Comment at: clang-tidy/performance/InefficientVectorOperationCheck.cpp:32
+  const auto ReserveCall = cxxMemberCallExpr(
+  callee(cxxMethodDecl(hasName("reserve"))), on(hasType(VectorDecl)));
+  const auto PushBackCall =

aaron.ballman wrote:
> This isn't paying attention to what is being reserved.
Good catch. Added a test for it.



Comment at: clang-tidy/performance/InefficientVectorOperationCheck.cpp:46-50
+  hasCondition(binaryOperator(hasOperatorName("<"),
+  hasLHS(RefersToLoopVar),
+  hasRHS(expr().bind("loop_end_expr",
+  hasIncrement(unaryOperator(hasOperatorName("++"),
+ hasUnaryOperand(RefersToLoopVar))),

aaron.ballman wrote:
> These conditions seem rather restrictive -- why should you not get the same 
> issue with a range-based for loop?
Yeah, this is intended. We want to match typical for-loops with counters here.  
For-range loop will be supported in the future.



Comment at: clang-tidy/performance/InefficientVectorOperationCheck.cpp:53-54
+PushBackCall)),
+  hasParent(compoundStmt(unless(has(ReserveCall)),
+ has(VectorVarDefStmt
+  .bind("for_loop"),

aaron.ballman wrote:
> I'm really not keen on this. It will catch trivial cases, so there is some 
> utility, but this will quickly fall apart with anything past the trivial case.
The motivation of this check is to find code patterns like `for (int i = 0; i < 
n; ++i) { v.push_back(i); }` and clean them in our codebase (we have lots of 
similar cases). 
[These](https://docs.google.com/document/d/1Bbc-6DlNs6zQujWD5-XOHWbfPJVMG7Z_T27Kv0WcFb4/edit?usp=sharing)
 are all cases we want to support. Using `hasParent` is a simple and sufficient 
way to do it IMO.



Comment at: test/clang-tidy/performance-inefficient-vector-operation.cpp:53
+std::vector v;
+v.reserve(20);
+// CHECK-FIXES-NOT: v.reserve(10);

aaron.ballman wrote:
> I'd like to see a test where you reserve 5 elements and then loop for 10 
> elements.
Even for this case, the check will also ignore it.


https://reviews.llvm.org/D31757



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D31757: [clang-tidy] Add a clang-tidy check for possible inefficient vector operations

2017-04-11 Thread Haojian Wu via Phabricator via cfe-commits
hokein added inline comments.



Comment at: clang-tidy/performance/InefficientVectorOperationCheck.cpp:53-54
+PushBackCall)),
+  hasParent(compoundStmt(unless(has(ReserveCall)),
+ has(VectorVarDefStmt
+  .bind("for_loop"),

aaron.ballman wrote:
> hokein wrote:
> > aaron.ballman wrote:
> > > I'm really not keen on this. It will catch trivial cases, so there is 
> > > some utility, but this will quickly fall apart with anything past the 
> > > trivial case.
> > The motivation of this check is to find code patterns like `for (int i = 0; 
> > i < n; ++i) { v.push_back(i); }` and clean them in our codebase (we have 
> > lots of similar cases). 
> > [These](https://docs.google.com/document/d/1Bbc-6DlNs6zQujWD5-XOHWbfPJVMG7Z_T27Kv0WcFb4/edit?usp=sharing)
> >  are all cases we want to support. Using `hasParent` is a simple and 
> > sufficient way to do it IMO.
> I'm not convinced of the utility without implementing this in a more 
> sensitive way. Have you run this across any large code bases and found that 
> it catches issues?
Yeah, the check catches ~2800 cases (regexp shows ~17,000 total usages) in our 
internal codebase. And all caught cases are what we are interested in. It would 
catch more if we support for-range loops and iterator-based for-loops. 


https://reviews.llvm.org/D31757



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D31757: [clang-tidy] Add a clang-tidy check for possible inefficient vector operations

2017-04-11 Thread Haojian Wu via Phabricator via cfe-commits
hokein added inline comments.



Comment at: clang-tidy/performance/InefficientVectorOperationCheck.cpp:53-54
+PushBackCall)),
+  hasParent(compoundStmt(unless(has(ReserveCall)),
+ has(VectorVarDefStmt
+  .bind("for_loop"),

aaron.ballman wrote:
> hokein wrote:
> > aaron.ballman wrote:
> > > hokein wrote:
> > > > aaron.ballman wrote:
> > > > > I'm really not keen on this. It will catch trivial cases, so there is 
> > > > > some utility, but this will quickly fall apart with anything past the 
> > > > > trivial case.
> > > > The motivation of this check is to find code patterns like `for (int i 
> > > > = 0; i < n; ++i) { v.push_back(i); }` and clean them in our codebase 
> > > > (we have lots of similar cases). 
> > > > [These](https://docs.google.com/document/d/1Bbc-6DlNs6zQujWD5-XOHWbfPJVMG7Z_T27Kv0WcFb4/edit?usp=sharing)
> > > >  are all cases we want to support. Using `hasParent` is a simple and 
> > > > sufficient way to do it IMO.
> > > I'm not convinced of the utility without implementing this in a more 
> > > sensitive way. Have you run this across any large code bases and found 
> > > that it catches issues?
> > Yeah, the check catches ~2800 cases (regexp shows ~17,000 total usages) in 
> > our internal codebase. And all caught cases are what we are interested in. 
> > It would catch more if we support for-range loops and iterator-based 
> > for-loops. 
> I wasn't worried about it not triggering often enough, I was worried about it 
> triggering too often because of the lack of sensitivity. If you randomly 
> sample some of those 2800 cases, do they reserve the space in a way that your 
> check isn't catching?
Ok, I see your concern now, thanks for pointing it out.

I have read through these caught cases. The results look reasonable. Most cases 
(> 95%) are what we expected, the code pattern is like `vector v; for (...) 
{ v.push_back(...); }` where the vector definition statement and for-loop 
statement are consecutive. Another option is to make the check more strict 
(only detects the consecutive code pattern).


https://reviews.llvm.org/D31757



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D31176: [clang-rename] Support renaming qualified symbol

2017-04-04 Thread Haojian Wu via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL299419: [clang-rename] Support renaming qualified symbol 
(authored by hokein).

Changed prior to commit:
  https://reviews.llvm.org/D31176?vs=93474=94021#toc

Repository:
  rL LLVM

https://reviews.llvm.org/D31176

Files:
  clang-tools-extra/trunk/clang-rename/CMakeLists.txt
  clang-tools-extra/trunk/clang-rename/RenamingAction.cpp
  clang-tools-extra/trunk/clang-rename/RenamingAction.h
  clang-tools-extra/trunk/clang-rename/USRFinder.cpp
  clang-tools-extra/trunk/clang-rename/USRFindingAction.cpp
  clang-tools-extra/trunk/clang-rename/USRLocFinder.cpp
  clang-tools-extra/trunk/clang-rename/USRLocFinder.h
  clang-tools-extra/trunk/unittests/clang-rename/CMakeLists.txt
  clang-tools-extra/trunk/unittests/clang-rename/ClangRenameTest.h
  clang-tools-extra/trunk/unittests/clang-rename/ClangRenameTests.cpp
  clang-tools-extra/trunk/unittests/clang-rename/RenameClassTest.cpp

Index: clang-tools-extra/trunk/unittests/clang-rename/ClangRenameTest.h
===
--- clang-tools-extra/trunk/unittests/clang-rename/ClangRenameTest.h
+++ clang-tools-extra/trunk/unittests/clang-rename/ClangRenameTest.h
@@ -0,0 +1,112 @@
+//===-- ClangRenameTests.cpp - clang-rename unit tests ===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===--===//
+
+#include "RenamingAction.h"
+#include "USRFindingAction.h"
+#include "unittests/Tooling/RewriterTestContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/FileSystemOptions.h"
+#include "clang/Basic/VirtualFileSystem.h"
+#include "clang/Format/Format.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/PCHContainerOperations.h"
+#include "clang/Tooling/Refactoring.h"
+#include "clang/Tooling/Tooling.h"
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "gtest/gtest.h"
+#include 
+#include 
+#include 
+
+namespace clang {
+namespace clang_rename {
+namespace test {
+
+struct Case {
+  std::string Before;
+  std::string After;
+  std::string OldName;
+  std::string NewName;
+};
+
+class ClangRenameTest : public testing::Test,
+public testing::WithParamInterface {
+protected:
+  void AppendToHeader(StringRef Code) { HeaderContent += Code.str(); }
+
+  std::string runClangRenameOnCode(llvm::StringRef Code,
+   llvm::StringRef OldName,
+   llvm::StringRef NewName) {
+std::string NewCode;
+llvm::raw_string_ostream(NewCode) << llvm::format(
+"#include \"%s\"\n%s", HeaderName.c_str(), Code.str().c_str());
+tooling::FileContentMappings FileContents = {{HeaderName, HeaderContent},
+ {CCName, NewCode}};
+clang::RewriterTestContext Context;
+Context.createInMemoryFile(HeaderName, HeaderContent);
+clang::FileID InputFileID = Context.createInMemoryFile(CCName, NewCode);
+
+rename::USRFindingAction FindingAction({}, {OldName});
+std::unique_ptr USRFindingActionFactory =
+tooling::newFrontendActionFactory();
+
+if (!tooling::runToolOnCodeWithArgs(
+USRFindingActionFactory->create(), NewCode, {"-std=c++11"}, CCName,
+"clang-rename", std::make_shared(),
+FileContents))
+  return "";
+
+const std::vector  =
+FindingAction.getUSRList();
+std::vector NewNames = {NewName};
+std::map FileToReplacements;
+rename::QualifiedRenamingAction RenameAction(NewNames, USRList,
+ FileToReplacements);
+auto RenameActionFactory = tooling::newFrontendActionFactory();
+if (!tooling::runToolOnCodeWithArgs(
+RenameActionFactory->create(), NewCode, {"-std=c++11"}, CCName,
+"clang-rename", std::make_shared(),
+FileContents))
+  return "";
+
+formatAndApplyAllReplacements(FileToReplacements, Context.Rewrite, "llvm");
+return Context.getRewrittenText(InputFileID);
+  }
+
+  void CompareSnippets(StringRef Expected, StringRef Actual) {
+std::string ExpectedCode;
+llvm::raw_string_ostream(ExpectedCode) << llvm::format(
+"#include \"%s\"\n%s", HeaderName.c_str(), Expected.str().c_str());
+EXPECT_EQ(format(ExpectedCode), format(Actual));
+  }
+
+  std::string format(llvm::StringRef Code) {
+tooling::Replacements Replaces = format::reformat(
+format::getLLVMStyle(), Code, {tooling::Range(0, Code.size())});
+auto ChangedCode = 

[PATCH] D31757: [clang-tidy] Add a clang-tidy check for possible inefficient vector operations

2017-04-12 Thread Haojian Wu via Phabricator via cfe-commits
hokein updated this revision to Diff 94969.
hokein added a comment.

Improve the way of detecting pre-allocation usage before the loop.


https://reviews.llvm.org/D31757

Files:
  clang-tidy/performance/CMakeLists.txt
  clang-tidy/performance/InefficientVectorOperationCheck.cpp
  clang-tidy/performance/InefficientVectorOperationCheck.h
  clang-tidy/performance/PerformanceTidyModule.cpp
  docs/ReleaseNotes.rst
  docs/clang-tidy/checks/list.rst
  docs/clang-tidy/checks/performance-inefficient-vector-operation.rst
  test/clang-tidy/performance-inefficient-vector-operation.cpp

Index: test/clang-tidy/performance-inefficient-vector-operation.cpp
===
--- /dev/null
+++ test/clang-tidy/performance-inefficient-vector-operation.cpp
@@ -0,0 +1,162 @@
+// RUN: %check_clang_tidy %s performance-inefficient-vector-operation %t -- -format-style=llvm --
+
+typedef int size_t;
+
+namespace std {
+template 
+class vector {
+ public:
+  typedef T* iterator;
+  typedef const T* const_iterator;
+  typedef T& reference;
+  typedef const T& const_reference;
+  typedef size_t size_type;
+
+  explicit vector();
+  explicit vector(size_type n);
+
+  void push_back(const T& val);
+  void reserve(size_t n);
+  void resize(size_t n);
+
+  size_t size();
+  const_reference operator[] (size_type) const;
+  reference operator[] (size_type);
+};
+} // namespace std
+
+void f(std::vector& t) {
+  {
+std::vector v;
+// CHECK-FIXES: v.reserve(10);
+for (int i = 0; i < 10; ++i)
+  v.push_back(i);
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: 'push_back' is called inside a loop; consider pre-allocating the vector capacity before the loop
+  }
+  {
+std::vector v;
+// CHECK-FIXES: v.reserve(5);
+for (int i = 0; i < 5; ++i) {
+  v.push_back(i);
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: 'push_back' is called
+}
+// CHECK-FIXES-NOT: v.reserve(10);
+for (int i = 0; i < 10; ++i) {
+  // No fix for this loop as we encounter the prior loops.
+  v.push_back(i);
+}
+  }
+  {
+std::vector v;
+std::vector v2;
+v2.reserve(3);
+// CHECK-FIXES: v.reserve(10);
+for (int i = 0; i < 10; ++i)
+  v.push_back(i);
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: 'push_back' is called
+  }
+  {
+std::vector v;
+// CHECK-FIXES: v.reserve(t.size());
+for (size_t i = 0; i < t.size(); ++i) {
+  v.push_back(t[i]);
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: 'push_back' is called
+}
+  }
+  {
+std::vector v;
+// CHECK-FIXES: v.reserve(t.size() - 1);
+for (size_t i = 0; i < t.size() - 1; ++i) {
+  v.push_back(t[i]);
+} // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: 'push_back' is called
+  }
+
+  //  Non-fixed Cases 
+  {
+std::vector v;
+v.reserve(20);
+// CHECK-FIXES-NOT: v.reserve(10);
+// There is a "reserve" call already.
+for (int i = 0; i < 10; ++i) {
+  v.push_back(i);
+}
+  }
+  {
+std::vector v;
+v.reserve(5);
+// CHECK-FIXES-NOT: v.reserve(10);
+// There is a "reserve" call already.
+for (int i = 0; i < 10; ++i) {
+  v.push_back(i);
+}
+  }
+  {
+std::vector v;
+v.resize(5);
+// CHECK-FIXES-NOT: v.reserve(10);
+// There is a ref usage of v before the loop.
+for (int i = 0; i < 10; ++i) {
+  v.push_back(i);
+}
+  }
+  {
+std::vector v;
+v.push_back(0);
+// CHECK-FIXES-NOT: v.reserve(10);
+// There is a ref usage of v before the loop.
+for (int i = 0; i < 10; ++i) {
+  v.push_back(i);
+}
+  }
+  {
+std::vector v;
+f(v);
+// CHECK-FIXES-NOT: v.reserve(10);
+// There is a ref usage of v before the loop.
+for (int i = 0; i < 10; ++i) {
+  v.push_back(i);
+}
+  }
+  {
+std::vector v(20);
+// CHECK-FIXES-NOT: v.reserve(10);
+// v is not constructed with default constructor.
+for (int i = 0; i < 10; ++i) {
+  v.push_back(i);
+}
+  }
+  {
+std::vector v;
+// CHECK-FIXES-NOT: v.reserve(10);
+// For-loop is not started with 0.
+for (int i = 1; i < 10; ++i) {
+  v.push_back(i);
+}
+  }
+  {
+std::vector v;
+// CHECK-FIXES-NOT: v.reserve(t.size());
+// v isn't referenced in for-loop body.
+for (size_t i = 0; i < t.size(); ++i) {
+  t.push_back(i);
+}
+  }
+  {
+std::vector v;
+int k;
+// CHECK-FIXES-NOT: v.reserve(10);
+// For-loop isn't a fixable loop.
+for (size_t i = 0; k < 10; ++i) {
+  v.push_back(t[i]);
+}
+  }
+  {
+std::vector v;
+int k;
+// CHECK-FIXES-NOT: v.reserve(10);
+// For-loop isn't a fixable loop.
+for (size_t i = 0; i < 10; ++k) {
+  v.push_back(t[i]);
+}
+  }
+}
Index: docs/clang-tidy/checks/performance-inefficient-vector-operation.rst
===
--- /dev/null
+++ 

[PATCH] D31757: [clang-tidy] Add a clang-tidy check for possible inefficient vector operations

2017-04-12 Thread Haojian Wu via Phabricator via cfe-commits
hokein marked an inline comment as done.
hokein added a comment.

friendly ping @alexfh.




Comment at: clang-tidy/performance/InefficientVectorOperationCheck.cpp:53-54
+PushBackCall)),
+  hasParent(compoundStmt(unless(has(ReserveCall)),
+ has(VectorVarDefStmt
+  .bind("for_loop"),

aaron.ballman wrote:
> hokein wrote:
> > aaron.ballman wrote:
> > > hokein wrote:
> > > > aaron.ballman wrote:
> > > > > hokein wrote:
> > > > > > aaron.ballman wrote:
> > > > > > > I'm really not keen on this. It will catch trivial cases, so 
> > > > > > > there is some utility, but this will quickly fall apart with 
> > > > > > > anything past the trivial case.
> > > > > > The motivation of this check is to find code patterns like `for 
> > > > > > (int i = 0; i < n; ++i) { v.push_back(i); }` and clean them in our 
> > > > > > codebase (we have lots of similar cases). 
> > > > > > [These](https://docs.google.com/document/d/1Bbc-6DlNs6zQujWD5-XOHWbfPJVMG7Z_T27Kv0WcFb4/edit?usp=sharing)
> > > > > >  are all cases we want to support. Using `hasParent` is a simple 
> > > > > > and sufficient way to do it IMO.
> > > > > I'm not convinced of the utility without implementing this in a more 
> > > > > sensitive way. Have you run this across any large code bases and 
> > > > > found that it catches issues?
> > > > Yeah, the check catches ~2800 cases (regexp shows ~17,000 total usages) 
> > > > in our internal codebase. And all caught cases are what we are 
> > > > interested in. It would catch more if we support for-range loops and 
> > > > iterator-based for-loops. 
> > > I wasn't worried about it not triggering often enough, I was worried 
> > > about it triggering too often because of the lack of sensitivity. If you 
> > > randomly sample some of those 2800 cases, do they reserve the space in a 
> > > way that your check isn't catching?
> > Ok, I see your concern now, thanks for pointing it out.
> > 
> > I have read through these caught cases. The results look reasonable. Most 
> > cases (> 95%) are what we expected, the code pattern is like `vector v; 
> > for (...) { v.push_back(...); }` where the vector definition statement and 
> > for-loop statement are consecutive. Another option is to make the check 
> > more strict (only detects the consecutive code pattern).
> Okay, that sounds like it has utility then. Thank you for clarifying!
I improved the way of catching the preallocations before the loop. Could you 
take a look again?


https://reviews.llvm.org/D31757



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D31757: [clang-tidy] Add a clang-tidy check for possible inefficient vector operations

2017-04-06 Thread Haojian Wu via Phabricator via cfe-commits
hokein updated this revision to Diff 94356.
hokein added a comment.

Fix a small nit.


https://reviews.llvm.org/D31757

Files:
  clang-tidy/performance/CMakeLists.txt
  clang-tidy/performance/InefficientVectorOperationCheck.cpp
  clang-tidy/performance/InefficientVectorOperationCheck.h
  clang-tidy/performance/PerformanceTidyModule.cpp
  docs/clang-tidy/checks/list.rst
  docs/clang-tidy/checks/performance-inefficient-vector-operation.rst
  test/clang-tidy/performance-inefficient-vector-operation.cpp

Index: test/clang-tidy/performance-inefficient-vector-operation.cpp
===
--- /dev/null
+++ test/clang-tidy/performance-inefficient-vector-operation.cpp
@@ -0,0 +1,102 @@
+// RUN: %check_clang_tidy %s performance-inefficient-vector-operation %t -- -format-style=llvm --
+
+typedef int size_t;
+
+namespace std {
+template 
+class vector {
+ public:
+  typedef T* iterator;
+  typedef const T* const_iterator;
+  typedef T& reference;
+  typedef const T& const_reference;
+  typedef size_t size_type;
+
+  explicit vector();
+  explicit vector(size_type n);
+
+  void push_back(const T& val);
+  void reserve(size_t n);
+  size_t size();
+  const_reference operator[] (size_type) const;
+  reference operator[] (size_type);
+};
+} // namespace std
+
+void f(std::vector& t) {
+  {
+std::vector v;
+// CHECK-FIXES: v.reserve(10);
+for (int i = 0; i < 10; ++i)
+  v.push_back(i);
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: push_back is called inside a loop; consider pre-allocating the vector capacity before the loop
+  }
+  {
+std::vector v;
+// CHECK-FIXES: v.reserve(t.size());
+for (size_t i = 0; i < t.size(); ++i) {
+  v.push_back(t[i]);
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: push_back is called
+}
+  }
+  {
+std::vector v;
+// CHECK-FIXES: v.reserve(t.size() - 1);
+for (size_t i = 0; i < t.size() - 1; ++i) {
+  v.push_back(t[i]);
+} // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: push_back is called
+  }
+
+  //  Non-fixed Cases 
+  {
+std::vector v;
+v.reserve(20);
+// CHECK-FIXES-NOT: v.reserve(10);
+// There is a "reserve" call already.
+for (int i = 0; i < 10; ++i) {
+  v.push_back(i);
+}
+  }
+  {
+std::vector v(20);
+// CHECK-FIXES-NOT: v.reserve(10);
+// v is not constructed with default constructor.
+for (int i = 0; i < 10; ++i) {
+  v.push_back(i);
+}
+  }
+  {
+std::vector v;
+// CHECK-FIXES-NOT: v.reserve(10);
+// For-loop is not started with 0.
+for (int i = 1; i < 10; ++i) {
+  v.push_back(i);
+}
+  }
+  {
+std::vector v;
+// CHECK-FIXES-NOT: v.reserve(t.size());
+// v isn't referenced in for-loop body.
+for (size_t i = 0; i < t.size(); ++i) {
+  t.push_back(i);
+}
+  }
+  {
+std::vector v;
+int k;
+// CHECK-FIXES-NOT: v.reserve(10);
+// For-loop isn't a fixable loop.
+for (size_t i = 0; k < 10; ++i) {
+  v.push_back(t[i]);
+}
+  }
+  {
+std::vector v;
+int k;
+// CHECK-FIXES-NOT: v.reserve(10);
+// For-loop isn't a fixable loop.
+for (size_t i = 0; i < 10; ++k) {
+  v.push_back(t[i]);
+}
+  }
+}
Index: docs/clang-tidy/checks/performance-inefficient-vector-operation.rst
===
--- /dev/null
+++ docs/clang-tidy/checks/performance-inefficient-vector-operation.rst
@@ -0,0 +1,17 @@
+.. title:: clang-tidy - performance-inefficient-vector-operation
+
+performance-inefficient-vector-operation
+
+
+Finds possible inefficient vector push_back operation that causes unnecessary
+memory reallocation.
+
+.. code-block:: c++
+
+  std::vector v;
+  for (int i = 0; i < n; ++i) {
+v.push_back(n);
+// This will trigger the warning since the push_back may cause multiple
+// memory reallocations in v. This can be avoid by inserting a reserve(n)
+// statment before the for statment.
+  }
Index: docs/clang-tidy/checks/list.rst
===
--- docs/clang-tidy/checks/list.rst
+++ docs/clang-tidy/checks/list.rst
@@ -141,6 +141,7 @@
performance-for-range-copy
performance-implicit-cast-in-loop
performance-inefficient-string-concatenation
+   performance-inefficient-vector-operation
performance-type-promotion-in-math-fn
performance-unnecessary-copy-initialization
performance-unnecessary-value-param
Index: clang-tidy/performance/PerformanceTidyModule.cpp
===
--- clang-tidy/performance/PerformanceTidyModule.cpp
+++ clang-tidy/performance/PerformanceTidyModule.cpp
@@ -14,6 +14,7 @@
 #include "ForRangeCopyCheck.h"
 #include "ImplicitCastInLoopCheck.h"
 #include "InefficientStringConcatenationCheck.h"
+#include "InefficientVectorOperationCheck.h"
 #include "TypePromotionInMathFnCheck.h"
 

[PATCH] D31757: [clang-tidy] Add a clang-tidy check for possible inefficient vector operations

2017-04-06 Thread Haojian Wu via Phabricator via cfe-commits
hokein created this revision.
Herald added a subscriber: mgorny.

The "performance-inefficient-vector-operation" check finds vector oprations in
for-loop statements which may cause multiple memory reallocations.

This is the first version, only detects typical for-loop:

  std::vector v;
  for (int i = 0; i < n; ++i) {
v.push_back(i);
  }
  
  // or
  
  for (int i = 0; i < v2.size(); ++i) {
v.push_back(v2[i]);
  }

We can extend it to handle more cases like for-range loop in the future.


https://reviews.llvm.org/D31757

Files:
  clang-tidy/performance/CMakeLists.txt
  clang-tidy/performance/InefficientVectorOperationCheck.cpp
  clang-tidy/performance/InefficientVectorOperationCheck.h
  clang-tidy/performance/PerformanceTidyModule.cpp
  docs/clang-tidy/checks/list.rst
  docs/clang-tidy/checks/performance-inefficient-vector-operation.rst
  test/clang-tidy/performance-inefficient-vector-operation.cpp

Index: test/clang-tidy/performance-inefficient-vector-operation.cpp
===
--- /dev/null
+++ test/clang-tidy/performance-inefficient-vector-operation.cpp
@@ -0,0 +1,102 @@
+// RUN: %check_clang_tidy %s performance-inefficient-vector-operation %t -- -format-style=llvm --
+
+typedef int size_t;
+
+namespace std {
+template 
+class vector {
+ public:
+  typedef T* iterator;
+  typedef const T* const_iterator;
+  typedef T& reference;
+  typedef const T& const_reference;
+  typedef size_t size_type;
+
+  explicit vector();
+  explicit vector(size_type n);
+
+  void push_back(const T& val);
+  void reserve(size_t n);
+  size_t size();
+  const_reference operator[] (size_type) const;
+  reference operator[] (size_type);
+};
+} // namespace std
+
+void f(std::vector& t) {
+  {
+std::vector v;
+// CHECK-FIXES: v.reserve(10);
+for (int i = 0; i < 10; ++i)
+  v.push_back(i);
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: push_back is called inside a loop; consider pre-allocating the vector capacity before the loop
+  }
+  {
+std::vector v;
+// CHECK-FIXES: v.reserve(t.size());
+for (size_t i = 0; i < t.size(); ++i) {
+  v.push_back(t[i]);
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: push_back is called
+}
+  }
+  {
+std::vector v;
+// CHECK-FIXES: v.reserve(t.size() - 1);
+for (size_t i = 0; i < t.size() - 1; ++i) {
+  v.push_back(t[i]);
+} // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: push_back is called
+  }
+
+  //  Non-fixed Cases 
+  {
+std::vector v;
+v.reserve(20);
+// CHECK-FIXES-NOT: v.reserve(10);
+// There is a "reserve" call already.
+for (int i = 0; i < 10; ++i) {
+  v.push_back(i);
+}
+  }
+  {
+std::vector v(20);
+// CHECK-FIXES-NOT: v.reserve(10);
+// v is not constructed with default constructor.
+for (int i = 0; i < 10; ++i) {
+  v.push_back(i);
+}
+  }
+  {
+std::vector v;
+// CHECK-FIXES-NOT: v.reserve(10);
+// For-loop is not started with 0.
+for (int i = 1; i < 10; ++i) {
+  v.push_back(i);
+}
+  }
+  {
+std::vector v;
+// CHECK-FIXES-NOT: v.reserve(t.size());
+// v isn't referenced in for-loop body.
+for (size_t i = 0; i < t.size(); ++i) {
+  t.push_back(i);
+}
+  }
+  {
+std::vector v;
+int k;
+// CHECK-FIXES-NOT: v.reserve(10);
+// For-loop isn't a fixable loop.
+for (size_t i = 0; k < 10; ++i) {
+  v.push_back(t[i]);
+}
+  }
+  {
+std::vector v;
+int k;
+// CHECK-FIXES-NOT: v.reserve(10);
+// For-loop isn't a fixable loop.
+for (size_t i = 0; i < 10; ++k) {
+  v.push_back(t[i]);
+}
+  }
+}
Index: docs/clang-tidy/checks/performance-inefficient-vector-operation.rst
===
--- /dev/null
+++ docs/clang-tidy/checks/performance-inefficient-vector-operation.rst
@@ -0,0 +1,17 @@
+.. title:: clang-tidy - performance-inefficient-vector-operation
+
+performance-inefficient-vector-operation
+
+
+Finds possible inefficient vector push_back operation that causes unnecessary
+memory reallocation.
+
+.. code-block:: c++
+
+  std::vector v;
+  for (int i = 0; i < n; ++i) {
+v.push_back(n);
+// This will trigger the warning since the push_back may cause multiple
+// memory reallocations in v. This can be avoid by inserting a reserve(n)
+// statment before the for statment.
+  }
Index: docs/clang-tidy/checks/list.rst
===
--- docs/clang-tidy/checks/list.rst
+++ docs/clang-tidy/checks/list.rst
@@ -141,6 +141,7 @@
performance-for-range-copy
performance-implicit-cast-in-loop
performance-inefficient-string-concatenation
+   performance-inefficient-vector-operation
performance-type-promotion-in-math-fn
performance-unnecessary-copy-initialization
performance-unnecessary-value-param
Index: 

  1   2   3   4   5   6   7   8   9   10   >