[PATCH] D70613: Add method to ignore invisible AST nodes

2019-12-18 Thread Stephen Kelly via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rG98e8f774eb6c: Add method to ignore invisible AST nodes 
(authored by stephenkelly).

Changed prior to commit:
  https://reviews.llvm.org/D70613?vs=233183&id=234623#toc

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D70613/new/

https://reviews.llvm.org/D70613

Files:
  clang/include/clang/AST/ASTNodeTraverser.h
  clang/include/clang/AST/ASTTypeTraits.h
  clang/include/clang/AST/Expr.h
  clang/lib/AST/ASTContext.cpp
  clang/lib/AST/Expr.cpp
  clang/unittests/AST/ASTTraverserTest.cpp
  clang/unittests/AST/CMakeLists.txt
  clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp

Index: clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
===
--- clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
+++ clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
@@ -1680,6 +1680,149 @@
  functionDecl(hasDescendant(Matcher)));
 }
 
+TEST(Traversal, traverseUnlessSpelledInSource) {
+
+  StringRef Code = R"cpp(
+
+struct A
+{
+};
+
+struct B
+{
+  B(int);
+  B(A const& a);
+  B();
+};
+
+struct C
+{
+  operator B();
+};
+
+B func1() {
+  return 42;
+}
+
+B func2() {
+  return B{42};
+}
+
+B func3() {
+  return B(42);
+}
+
+B func4() {
+  return B();
+}
+
+B func5() {
+  return B{};
+}
+
+B func6() {
+  return C();
+}
+
+B func7() {
+  return A();
+}
+
+B func8() {
+  return C{};
+}
+
+B func9() {
+  return A{};
+}
+
+B func10() {
+  A a;
+  return a;
+}
+
+B func11() {
+  B b;
+  return b;
+}
+
+B func12() {
+  C c;
+  return c;
+}
+
+)cpp";
+
+  EXPECT_TRUE(matches(
+  Code, traverse(ast_type_traits::TK_IgnoreUnlessSpelledInSource,
+ returnStmt(forFunction(functionDecl(hasName("func1"))),
+hasReturnValue(integerLiteral(equals(42)));
+
+  EXPECT_TRUE(matches(
+  Code,
+  traverse(ast_type_traits::TK_IgnoreUnlessSpelledInSource,
+   returnStmt(forFunction(functionDecl(hasName("func2"))),
+  hasReturnValue(cxxTemporaryObjectExpr(
+  hasArgument(0, integerLiteral(equals(42);
+
+  EXPECT_TRUE(matches(
+  Code, traverse(ast_type_traits::TK_IgnoreUnlessSpelledInSource,
+ returnStmt(forFunction(functionDecl(hasName("func3"))),
+hasReturnValue(
+cxxFunctionalCastExpr(hasSourceExpression(
+integerLiteral(equals(42);
+
+  EXPECT_TRUE(matches(
+  Code, traverse(ast_type_traits::TK_IgnoreUnlessSpelledInSource,
+ returnStmt(forFunction(functionDecl(hasName("func4"))),
+hasReturnValue(cxxTemporaryObjectExpr());
+
+  EXPECT_TRUE(matches(
+  Code, traverse(ast_type_traits::TK_IgnoreUnlessSpelledInSource,
+ returnStmt(forFunction(functionDecl(hasName("func5"))),
+hasReturnValue(cxxTemporaryObjectExpr());
+
+  EXPECT_TRUE(matches(
+  Code, traverse(ast_type_traits::TK_IgnoreUnlessSpelledInSource,
+ returnStmt(forFunction(functionDecl(hasName("func6"))),
+hasReturnValue(cxxTemporaryObjectExpr());
+
+  EXPECT_TRUE(matches(
+  Code, traverse(ast_type_traits::TK_IgnoreUnlessSpelledInSource,
+ returnStmt(forFunction(functionDecl(hasName("func7"))),
+hasReturnValue(cxxTemporaryObjectExpr());
+
+  EXPECT_TRUE(matches(
+  Code, traverse(ast_type_traits::TK_IgnoreUnlessSpelledInSource,
+ returnStmt(forFunction(functionDecl(hasName("func8"))),
+hasReturnValue(cxxFunctionalCastExpr(
+hasSourceExpression(initListExpr(;
+
+  EXPECT_TRUE(matches(
+  Code, traverse(ast_type_traits::TK_IgnoreUnlessSpelledInSource,
+ returnStmt(forFunction(functionDecl(hasName("func9"))),
+hasReturnValue(cxxFunctionalCastExpr(
+hasSourceExpression(initListExpr(;
+
+  EXPECT_TRUE(matches(
+  Code, traverse(ast_type_traits::TK_IgnoreUnlessSpelledInSource,
+ returnStmt(forFunction(functionDecl(hasName("func10"))),
+hasReturnValue(
+declRefExpr(to(varDecl(hasName("a");
+
+  EXPECT_TRUE(matches(
+  Code, traverse(ast_type_traits::TK_IgnoreUnlessSpelledInSource,
+ returnStmt(forFunction(functionDecl(hasName("func11"))),
+hasReturnValue(
+declRefExpr(to(varDecl(hasName("b");
+
+  EXPECT_TRUE(matches(
+  Code, traverse(ast_type_traits

[PATCH] D70613: Add method to ignore invisible AST nodes

2019-12-11 Thread Aaron Ballman via Phabricator via cfe-commits
aaron.ballman accepted this revision.
aaron.ballman added a comment.
This revision is now accepted and ready to land.

LGTM


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D70613/new/

https://reviews.llvm.org/D70613



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


[PATCH] D70613: Add method to ignore invisible AST nodes

2019-12-10 Thread Stephen Kelly via Phabricator via cfe-commits
steveire updated this revision to Diff 233183.
steveire added a comment.

Update


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D70613/new/

https://reviews.llvm.org/D70613

Files:
  clang/include/clang/AST/ASTNodeTraverser.h
  clang/include/clang/AST/ASTTypeTraits.h
  clang/include/clang/AST/Expr.h
  clang/lib/AST/ASTContext.cpp
  clang/lib/AST/Expr.cpp
  clang/unittests/AST/ASTTraverserTest.cpp
  clang/unittests/AST/CMakeLists.txt
  clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp

Index: clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
===
--- clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
+++ clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
@@ -1680,6 +1680,149 @@
  functionDecl(hasDescendant(Matcher)));
 }
 
+TEST(Traversal, traverseUnlessSpelledInSource) {
+
+  StringRef Code = R"cpp(
+
+struct A
+{
+};
+
+struct B
+{
+  B(int);
+  B(A const& a);
+  B();
+};
+
+struct C
+{
+  operator B();
+};
+
+B func1() {
+  return 42;
+}
+
+B func2() {
+  return B{42};
+}
+
+B func3() {
+  return B(42);
+}
+
+B func4() {
+  return B();
+}
+
+B func5() {
+  return B{};
+}
+
+B func6() {
+  return C();
+}
+
+B func7() {
+  return A();
+}
+
+B func8() {
+  return C{};
+}
+
+B func9() {
+  return A{};
+}
+
+B func10() {
+  A a;
+  return a;
+}
+
+B func11() {
+  B b;
+  return b;
+}
+
+B func12() {
+  C c;
+  return c;
+}
+
+)cpp";
+
+  EXPECT_TRUE(matches(
+  Code, traverse(ast_type_traits::TK_IgnoreUnlessSpelledInSource,
+ returnStmt(forFunction(functionDecl(hasName("func1"))),
+hasReturnValue(integerLiteral(equals(42)));
+
+  EXPECT_TRUE(matches(
+  Code,
+  traverse(ast_type_traits::TK_IgnoreUnlessSpelledInSource,
+   returnStmt(forFunction(functionDecl(hasName("func2"))),
+  hasReturnValue(cxxTemporaryObjectExpr(
+  hasArgument(0, integerLiteral(equals(42);
+
+  EXPECT_TRUE(matches(
+  Code, traverse(ast_type_traits::TK_IgnoreUnlessSpelledInSource,
+ returnStmt(forFunction(functionDecl(hasName("func3"))),
+hasReturnValue(
+cxxFunctionalCastExpr(hasSourceExpression(
+integerLiteral(equals(42);
+
+  EXPECT_TRUE(matches(
+  Code, traverse(ast_type_traits::TK_IgnoreUnlessSpelledInSource,
+ returnStmt(forFunction(functionDecl(hasName("func4"))),
+hasReturnValue(cxxTemporaryObjectExpr());
+
+  EXPECT_TRUE(matches(
+  Code, traverse(ast_type_traits::TK_IgnoreUnlessSpelledInSource,
+ returnStmt(forFunction(functionDecl(hasName("func5"))),
+hasReturnValue(cxxTemporaryObjectExpr());
+
+  EXPECT_TRUE(matches(
+  Code, traverse(ast_type_traits::TK_IgnoreUnlessSpelledInSource,
+ returnStmt(forFunction(functionDecl(hasName("func6"))),
+hasReturnValue(cxxTemporaryObjectExpr());
+
+  EXPECT_TRUE(matches(
+  Code, traverse(ast_type_traits::TK_IgnoreUnlessSpelledInSource,
+ returnStmt(forFunction(functionDecl(hasName("func7"))),
+hasReturnValue(cxxTemporaryObjectExpr());
+
+  EXPECT_TRUE(matches(
+  Code, traverse(ast_type_traits::TK_IgnoreUnlessSpelledInSource,
+ returnStmt(forFunction(functionDecl(hasName("func8"))),
+hasReturnValue(cxxFunctionalCastExpr(
+hasSourceExpression(initListExpr(;
+
+  EXPECT_TRUE(matches(
+  Code, traverse(ast_type_traits::TK_IgnoreUnlessSpelledInSource,
+ returnStmt(forFunction(functionDecl(hasName("func9"))),
+hasReturnValue(cxxFunctionalCastExpr(
+hasSourceExpression(initListExpr(;
+
+  EXPECT_TRUE(matches(
+  Code, traverse(ast_type_traits::TK_IgnoreUnlessSpelledInSource,
+ returnStmt(forFunction(functionDecl(hasName("func10"))),
+hasReturnValue(
+declRefExpr(to(varDecl(hasName("a");
+
+  EXPECT_TRUE(matches(
+  Code, traverse(ast_type_traits::TK_IgnoreUnlessSpelledInSource,
+ returnStmt(forFunction(functionDecl(hasName("func11"))),
+hasReturnValue(
+declRefExpr(to(varDecl(hasName("b");
+
+  EXPECT_TRUE(matches(
+  Code, traverse(ast_type_traits::TK_IgnoreUnlessSpelledInSource,
+ returnStmt(forFunction(functionDecl(hasName("func12"))),
+hasReturnValue(
+

[PATCH] D70613: Add method to ignore invisible AST nodes

2019-12-10 Thread Stephen Kelly via Phabricator via cfe-commits
steveire marked 10 inline comments as done.
steveire added a comment.

It wasn't possible to add the `const` because of the return type.




Comment at: clang/include/clang/AST/Expr.h:769-770
+  /// implicit conversions.
+  Expr *IgnoreInvisible();
+  const Expr *IgnoreInvisible() const {
+return const_cast(this)->IgnoreInvisible();

aaron.ballman wrote:
> `Invisible` is a bit of an odd term because the AST nodes themselves are in 
> fact visible within the AST. I think this means "invisible" as in "not 
> corresponding directly to syntax the user wrote". Bikeshedding some other 
> names:
> 
> * IgnoreAllImplicitExprs
> * IgnoreAllImplicitNodes
> * IgnoreNodesNotWrittenByUser
> * IgnoreNotWrittenInSource
> 
> other suggestions welcome.
> 
Changed as discussed on IRC.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D70613/new/

https://reviews.llvm.org/D70613



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


[PATCH] D70613: Add method to ignore invisible AST nodes

2019-12-10 Thread Aaron Ballman via Phabricator via cfe-commits
aaron.ballman added inline comments.



Comment at: clang/include/clang/AST/Expr.h:769-770
+  /// implicit conversions.
+  Expr *IgnoreInvisible();
+  const Expr *IgnoreInvisible() const {
+return const_cast(this)->IgnoreInvisible();

`Invisible` is a bit of an odd term because the AST nodes themselves are in 
fact visible within the AST. I think this means "invisible" as in "not 
corresponding directly to syntax the user wrote". Bikeshedding some other names:

* IgnoreAllImplicitExprs
* IgnoreAllImplicitNodes
* IgnoreNodesNotWrittenByUser
* IgnoreNotWrittenInSource

other suggestions welcome.




Comment at: clang/lib/AST/Expr.cpp:3004-3006
+  Expr *s = this;
+
+  Expr *lasts = nullptr;

Can remove the spurious newline, and these should be named according to the 
usual naming conventions (I'd go with `E` and `LastE`, but feel free to pick 
less terrible names).



Comment at: clang/lib/AST/Expr.cpp:3012
+
+const auto SR = s->getSourceRange();
+

Drop top-level `const` (I wouldn't be sad if it also lost the `auto` at the 
same time).



Comment at: clang/lib/AST/Expr.cpp:3014
+
+if (auto C = dyn_cast(s)) {
+  if (C->getNumArgs() == 1) {

`const auto *`



Comment at: clang/lib/AST/Expr.cpp:3016
+  if (C->getNumArgs() == 1) {
+auto A = C->getArg(0);
+if (A->getSourceRange() == SR || !dyn_cast(C))

`const Expr *`



Comment at: clang/lib/AST/Expr.cpp:3017
+auto A = C->getArg(0);
+if (A->getSourceRange() == SR || !dyn_cast(C))
+  s = A;

`!isa(C)` since you're not using the returned value 
anyway.



Comment at: clang/lib/AST/Expr.cpp:3022
+
+if (auto C = dyn_cast(s)) {
+  auto *ExprNode = C->getImplicitObjectArgument()->IgnoreParenImpCasts();

`const auto *`



Comment at: clang/lib/AST/Expr.cpp:3023
+if (auto C = dyn_cast(s)) {
+  auto *ExprNode = C->getImplicitObjectArgument()->IgnoreParenImpCasts();
+  if (ExprNode->getSourceRange() == SR) {

`const Expr *`

Are you sure you mean to skip parens here, as those are written in source?



Comment at: clang/lib/AST/Expr.cpp:3024
+  auto *ExprNode = C->getImplicitObjectArgument()->IgnoreParenImpCasts();
+  if (ExprNode->getSourceRange() == SR) {
+s = ExprNode;

Elide braces


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D70613/new/

https://reviews.llvm.org/D70613



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


[PATCH] D70613: Add method to ignore invisible AST nodes

2019-11-22 Thread Stephen Kelly via Phabricator via cfe-commits
steveire created this revision.
steveire added a reviewer: aaron.ballman.
Herald added subscribers: cfe-commits, mgorny.
Herald added a project: clang.

Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D70613

Files:
  clang/include/clang/AST/ASTNodeTraverser.h
  clang/include/clang/AST/ASTTypeTraits.h
  clang/include/clang/AST/Expr.h
  clang/lib/AST/ASTContext.cpp
  clang/lib/AST/Expr.cpp
  clang/unittests/AST/ASTTraverserTest.cpp
  clang/unittests/AST/CMakeLists.txt
  clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp

Index: clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
===
--- clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
+++ clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
@@ -1680,6 +1680,149 @@
  functionDecl(hasDescendant(Matcher)));
 }
 
+TEST(Traversal, traverseInvisible) {
+
+  StringRef Code = R"cpp(
+
+struct A
+{
+};
+
+struct B
+{
+  B(int);
+  B(A const& a);
+  B();
+};
+
+struct C
+{
+  operator B();
+};
+
+B func1() {
+  return 42;
+}
+
+B func2() {
+  return B{42};
+}
+
+B func3() {
+  return B(42);
+}
+
+B func4() {
+  return B();
+}
+
+B func5() {
+  return B{};
+}
+
+B func6() {
+  return C();
+}
+
+B func7() {
+  return A();
+}
+
+B func8() {
+  return C{};
+}
+
+B func9() {
+  return A{};
+}
+
+B func10() {
+  A a;
+  return a;
+}
+
+B func11() {
+  B b;
+  return b;
+}
+
+B func12() {
+  C c;
+  return c;
+}
+
+)cpp";
+
+  EXPECT_TRUE(matches(
+  Code, traverse(ast_type_traits::TK_IgnoreInvisible,
+ returnStmt(forFunction(functionDecl(hasName("func1"))),
+hasReturnValue(integerLiteral(equals(42)));
+
+  EXPECT_TRUE(matches(
+  Code,
+  traverse(ast_type_traits::TK_IgnoreInvisible,
+   returnStmt(forFunction(functionDecl(hasName("func2"))),
+  hasReturnValue(cxxTemporaryObjectExpr(
+  hasArgument(0, integerLiteral(equals(42);
+
+  EXPECT_TRUE(matches(
+  Code, traverse(ast_type_traits::TK_IgnoreInvisible,
+ returnStmt(forFunction(functionDecl(hasName("func3"))),
+hasReturnValue(
+cxxFunctionalCastExpr(hasSourceExpression(
+integerLiteral(equals(42);
+
+  EXPECT_TRUE(matches(
+  Code, traverse(ast_type_traits::TK_IgnoreInvisible,
+ returnStmt(forFunction(functionDecl(hasName("func4"))),
+hasReturnValue(cxxTemporaryObjectExpr());
+
+  EXPECT_TRUE(matches(
+  Code, traverse(ast_type_traits::TK_IgnoreInvisible,
+ returnStmt(forFunction(functionDecl(hasName("func5"))),
+hasReturnValue(cxxTemporaryObjectExpr());
+
+  EXPECT_TRUE(matches(
+  Code, traverse(ast_type_traits::TK_IgnoreInvisible,
+ returnStmt(forFunction(functionDecl(hasName("func6"))),
+hasReturnValue(cxxTemporaryObjectExpr());
+
+  EXPECT_TRUE(matches(
+  Code, traverse(ast_type_traits::TK_IgnoreInvisible,
+ returnStmt(forFunction(functionDecl(hasName("func7"))),
+hasReturnValue(cxxTemporaryObjectExpr());
+
+  EXPECT_TRUE(matches(
+  Code, traverse(ast_type_traits::TK_IgnoreInvisible,
+ returnStmt(forFunction(functionDecl(hasName("func8"))),
+hasReturnValue(cxxFunctionalCastExpr(
+hasSourceExpression(initListExpr(;
+
+  EXPECT_TRUE(matches(
+  Code, traverse(ast_type_traits::TK_IgnoreInvisible,
+ returnStmt(forFunction(functionDecl(hasName("func9"))),
+hasReturnValue(cxxFunctionalCastExpr(
+hasSourceExpression(initListExpr(;
+
+  EXPECT_TRUE(matches(
+  Code, traverse(ast_type_traits::TK_IgnoreInvisible,
+ returnStmt(forFunction(functionDecl(hasName("func10"))),
+hasReturnValue(
+declRefExpr(to(varDecl(hasName("a");
+
+  EXPECT_TRUE(matches(
+  Code, traverse(ast_type_traits::TK_IgnoreInvisible,
+ returnStmt(forFunction(functionDecl(hasName("func11"))),
+hasReturnValue(
+declRefExpr(to(varDecl(hasName("b");
+
+  EXPECT_TRUE(matches(
+  Code, traverse(ast_type_traits::TK_IgnoreInvisible,
+ returnStmt(forFunction(functionDecl(hasName("func12"))),
+hasReturnValue(
+declRefExpr(to(varDecl(hasName("c");
+}
+
 TEST(IgnoringImpCasts, MatchesImpCasts) {
   // This test checks that ignoringImp