[PATCH] D113917: Add infrastructure to support matcher names.

2021-12-03 Thread James King via Phabricator via cfe-commits
jcking1034 added a comment.

@hokein @aaron.ballman Following up on this, let me know if there are any other 
action items to address!


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D113917

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


[PATCH] D114809: Fix documentation for `forEachLambdaCapture` and `hasAnyCapture`

2021-11-30 Thread James King via Phabricator via cfe-commits
jcking1034 created this revision.
jcking1034 added reviewers: ymandel, tdl-g, aaron.ballman.
jcking1034 requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Updates the return types of these matchers' definitions to use
`internal::Matcher` instead of `LambdaCaptureMatcher`.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D114809

Files:
  clang/docs/LibASTMatchersReference.html
  clang/include/clang/ASTMatchers/ASTMatchers.h

Index: clang/include/clang/ASTMatchers/ASTMatchers.h
===
--- clang/include/clang/ASTMatchers/ASTMatchers.h
+++ clang/include/clang/ASTMatchers/ASTMatchers.h
@@ -4227,8 +4227,8 @@
 /// lambdaExpr(forEachLambdaCapture(
 /// lambdaCapture(capturesVar(varDecl(hasType(isInteger()))
 /// will trigger two matches, binding for 'x' and 'y' respectively.
-AST_MATCHER_P(LambdaExpr, forEachLambdaCapture, LambdaCaptureMatcher,
-  InnerMatcher) {
+AST_MATCHER_P(LambdaExpr, forEachLambdaCapture,
+  internal::Matcher, InnerMatcher) {
   BoundNodesTreeBuilder Result;
   bool Matched = false;
   for (const auto  : Node.captures()) {
@@ -4655,7 +4655,8 @@
 /// lambdaExpr(hasAnyCapture(lambdaCapture())) and
 /// lambdaExpr(hasAnyCapture(lambdaCapture(refersToVarDecl(hasName("t")
 ///   both match `[=](){ return t; }`.
-AST_MATCHER_P(LambdaExpr, hasAnyCapture, LambdaCaptureMatcher, InnerMatcher) {
+AST_MATCHER_P(LambdaExpr, hasAnyCapture, internal::Matcher,
+  InnerMatcher) {
   for (const LambdaCapture  : Node.captures()) {
 clang::ast_matchers::internal::BoundNodesTreeBuilder Result(*Builder);
 if (InnerMatcher.matches(Capture, Finder, )) {
Index: clang/docs/LibASTMatchersReference.html
===
--- clang/docs/LibASTMatchersReference.html
+++ clang/docs/LibASTMatchersReference.html
@@ -4550,35 +4550,6 @@
 
 
 
-Matcherhttps://clang.llvm.org/doxygen/classclang_1_1LambdaExpr.html;>LambdaExprforEachLambdaCaptureLambdaCaptureMatcher InnerMatcher
-Matches each lambda capture in a lambda expression.
-
-Given
-  int main() {
-int x, y;
-float z;
-auto f = [=]() { return x + y + z; };
-  }
-lambdaExpr(forEachLambdaCapture(
-lambdaCapture(capturesVar(varDecl(hasType(isInteger()))
-will trigger two matches, binding for 'x' and 'y' respectively.
-
-
-
-Matcherhttps://clang.llvm.org/doxygen/classclang_1_1LambdaExpr.html;>LambdaExprhasAnyCaptureLambdaCaptureMatcher InnerMatcher
-Matches any capture in a lambda expression.
-
-Given
-  void foo() {
-int t = 5;
-auto f = [=](){ return t; };
-  }
-lambdaExpr(hasAnyCapture(lambdaCapture())) and
-lambdaExpr(hasAnyCapture(lambdaCapture(refersToVarDecl(hasName("t")
-  both match `[=](){ return t; }`.
-
-
-
 Matcherhttps://clang.llvm.org/doxygen/classclang_1_1MemberExpr.html;>MemberExprisArrow
 Matches member expressions that are called with '-' as opposed
 to '.'.
@@ -8405,6 +8376,35 @@
 
 
 
+Matcherhttps://clang.llvm.org/doxygen/classclang_1_1LambdaExpr.html;>LambdaExprforEachLambdaCaptureMatcherhttps://clang.llvm.org/doxygen/classclang_1_1LambdaCapture.html;>LambdaCapture InnerMatcher
+Matches each lambda capture in a lambda expression.
+
+Given
+  int main() {
+int x, y;
+float z;
+auto f = [=]() { return x + y + z; };
+  }
+lambdaExpr(forEachLambdaCapture(
+lambdaCapture(capturesVar(varDecl(hasType(isInteger()))
+will trigger two matches, binding for 'x' and 'y' respectively.
+
+
+
+Matcherhttps://clang.llvm.org/doxygen/classclang_1_1LambdaExpr.html;>LambdaExprhasAnyCaptureMatcherhttps://clang.llvm.org/doxygen/classclang_1_1LambdaCapture.html;>LambdaCapture InnerMatcher
+Matches any capture in a lambda expression.
+
+Given
+  void foo() {
+int t = 5;
+auto f = [=](){ return t; };
+  }
+lambdaExpr(hasAnyCapture(lambdaCapture())) and
+lambdaExpr(hasAnyCapture(lambdaCapture(refersToVarDecl(hasName("t")
+  both match `[=](){ return t; }`.
+
+
+
 Matcherhttps://clang.llvm.org/doxygen/classclang_1_1MemberExpr.html;>MemberExprhasDeclarationMatcherhttps://clang.llvm.org/doxygen/classclang_1_1Decl.html;>Decl  InnerMatcher
 Matches a node if the declaration associated with that node
 matches the given matcher.
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D113943: Add `withTag` matcher.

2021-11-29 Thread James King via Phabricator via cfe-commits
jcking1034 updated this revision to Diff 390429.
jcking1034 added a comment.

Chang `withTag` to `withIntrospection`


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D113943

Files:
  clang/include/clang/ASTMatchers/ASTMatchers.h
  clang/include/clang/ASTMatchers/ASTMatchersInternal.h

Index: clang/include/clang/ASTMatchers/ASTMatchersInternal.h
===
--- clang/include/clang/ASTMatchers/ASTMatchersInternal.h
+++ clang/include/clang/ASTMatchers/ASTMatchersInternal.h
@@ -43,6 +43,7 @@
 #include "clang/AST/ExprCXX.h"
 #include "clang/AST/ExprObjC.h"
 #include "clang/AST/NestedNameSpecifier.h"
+#include "clang/AST/PrettyPrinter.h"
 #include "clang/AST/Stmt.h"
 #include "clang/AST/TemplateName.h"
 #include "clang/AST/Type.h"
@@ -1057,6 +1058,46 @@
   std::vector Names;
 };
 
+template 
+class WithIntrospectionMatcher : public MatcherInterface {
+public:
+  explicit WithIntrospectionMatcher(std::string _BeforeTag,
+std::string _AfterTag,
+internal::Matcher _InnerMatcher)
+  : BeforeTag(std::move(_BeforeTag)), AfterTag(std::move(_AfterTag)),
+InnerMatcher(_InnerMatcher) {}
+  explicit WithIntrospectionMatcher(internal::Matcher _InnerMatcher)
+  : BeforeTag("⭐ Attempting new match"),
+AfterTag("✔️ Concluding attempt"), InnerMatcher(_InnerMatcher) {}
+  bool matches(const T , ASTMatchFinder *Finder,
+   BoundNodesTreeBuilder *Builder) const override {
+DynTypedNode DTN = DynTypedNode::create(Node);
+
+llvm::errs() << BeforeTag << "\n";
+
+llvm::errs() << "Matcher Name: " << InnerMatcher.getName() << "\n";
+
+llvm::errs() << "Node Kind: " << DTN.getNodeKind().asStringRef() << "\n"
+ << "Node Value:\n```\n";
+DTN.print(llvm::errs(), PrintingPolicy(LangOptions()));
+llvm::errs() << "\n```\n"
+ << "Node AST:\n";
+DTN.dump(llvm::errs(), Finder->getASTContext());
+
+bool result = InnerMatcher.matches(Node, Finder, Builder);
+llvm::errs() << "Result: " << (result ? "Successful\n" : "Unsuccessful\n");
+
+llvm::errs() << AfterTag << "\n\n";
+
+return result;
+  }
+
+private:
+  std::string BeforeTag;
+  std::string AfterTag;
+  internal::Matcher InnerMatcher;
+};
+
 /// Matches named declarations with a specific name.
 ///
 /// See \c hasName() and \c hasAnyName() in ASTMatchers.h for details.
@@ -1734,6 +1775,38 @@
   std::tuple Params;
 };
 
+template  class MatcherT,
+  typename ReturnTypesF, typename... ParamTypes>
+class PolymorphicWithIntrospectionMatcher {
+public:
+  PolymorphicWithIntrospectionMatcher(
+  internal::PolymorphicMatcher
+  _InnerMatcher)
+  : InnerMatcher(_InnerMatcher) {}
+
+  using ReturnTypes = typename ExtractFunctionArgMeta::type;
+
+  template  operator Matcher() const LLVM_LVALUE_FUNCTION {
+static_assert(TypeListContainsSuperOf::value,
+  "right polymorphic conversion");
+return internal::Matcher(new internal::WithIntrospectionMatcher(
+internal::Matcher(InnerMatcher)));
+  }
+
+#if LLVM_HAS_RVALUE_REFERENCE_THIS
+  template  operator Matcher() && {
+static_assert(TypeListContainsSuperOf::value,
+  "right polymorphic conversion");
+return internal::Matcher(new internal::WithIntrospectionMatcher(
+internal::Matcher(std::move(InnerMatcher;
+  }
+#endif
+
+private:
+  internal::PolymorphicMatcher
+  InnerMatcher;
+};
+
 /// Matches nodes of type T that have child nodes of type ChildT for
 /// which a specified child matcher matches.
 ///
Index: clang/include/clang/ASTMatchers/ASTMatchers.h
===
--- clang/include/clang/ASTMatchers/ASTMatchers.h
+++ clang/include/clang/ASTMatchers/ASTMatchers.h
@@ -2993,6 +2993,46 @@
   new internal::HasNameMatcher({std::string(Name)}));
 }
 
+template 
+inline internal::Matcher
+withIntrospection(std::string BeforeTag, std::string AfterTag,
+  const internal::Matcher ) {
+  return internal::Matcher(new internal::WithIntrospectionMatcher(
+  BeforeTag, AfterTag, InnerMatcher));
+}
+
+template  class MatcherT,
+  typename ReturnTypesF, typename... ParamTypes>
+inline internal::PolymorphicWithIntrospectionMatcher
+withIntrospection(
+std::string BeforeTag, std::string AfterTag,
+const internal::PolymorphicMatcher
+) {
+  return internal::PolymorphicWithIntrospectionMatcher(
+  BeforeTag, AfterTag, InnerMatcher);
+}
+
+template 
+inline internal::Matcher
+withIntrospection(const internal::Matcher ) {
+  return internal::Matcher(
+  new internal::WithIntrospectionMatcher(InnerMatcher));
+}
+
+template  class MatcherT,
+  typename ReturnTypesF, typename... ParamTypes>
+inline internal::PolymorphicWithIntrospectionMatcher

[PATCH] D113917: Add infrastructure to support matcher names.

2021-11-24 Thread James King via Phabricator via cfe-commits
jcking1034 added inline comments.



Comment at: clang/include/clang/ASTMatchers/ASTMatchersInternal.h:152
+  }
+MAKE_MATCHER_NAME_FROM_TYPE(TemplateArgument)
+MAKE_MATCHER_NAME_FROM_TYPE(TemplateArgumentLoc)

hokein wrote:
> These are types that are not covered in the above gen .inc files. I wonder is 
> there a way to verify this list is complete? 
I compared this list to other portions of the code where a similar pattern was 
used, and have just added specializations for OMP-related nodes. In these other 
portions of code, I didn't notice anything that verifies completeness, but I 
agree that this would be preferable.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D113917

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


[PATCH] D113917: Add infrastructure to support matcher names.

2021-11-24 Thread James King via Phabricator via cfe-commits
jcking1034 updated this revision to Diff 389620.
jcking1034 marked 3 inline comments as done.
jcking1034 added a comment.
Herald added a reviewer: jdoerfert.
Herald added a subscriber: sstefan1.

Address comments.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D113917

Files:
  clang/include/clang/ASTMatchers/ASTMatchersInternal.h
  clang/include/clang/ASTMatchers/ASTMatchersMacros.h
  clang/lib/ASTMatchers/ASTMatchersInternal.cpp
  clang/unittests/ASTMatchers/ASTMatchersInternalTest.cpp

Index: clang/unittests/ASTMatchers/ASTMatchersInternalTest.cpp
===
--- clang/unittests/ASTMatchers/ASTMatchersInternalTest.cpp
+++ clang/unittests/ASTMatchers/ASTMatchersInternalTest.cpp
@@ -20,6 +20,30 @@
 namespace ast_matchers {
 using internal::DynTypedMatcher;
 
+TEST(GetNameTest, ReturnsCorrectName) {
+  // Node
+  EXPECT_EQ(typeLoc().getName(), "`TypeLoc` Node");
+  EXPECT_EQ(typeLoc(pointerTypeLoc()).getName(), "`TypeLoc` Node");
+  EXPECT_EQ(pointerTypeLoc(hasPointeeLoc(typeLoc())).getName(),
+"`PointerTypeLoc` Node");
+  EXPECT_EQ(varDecl(hasInitializer(expr()), hasTypeLoc(typeLoc())).getName(),
+"`VarDecl` Node");
+  EXPECT_EQ(ompDefaultClause().getName(), "`OMPDefaultClause` Node");
+
+  // Narrowing
+  EXPECT_EQ(isConst().getName(), "isConst");
+
+  // Traversal
+  EXPECT_EQ(hasLoopVariable(varDecl()).getName(), "hasLoopVariable");
+
+  // Polymorphic
+  EXPECT_EQ(internal::Matcher(hasLHS(expr())).getName(),
+"hasLHS");
+
+  // Bound
+  EXPECT_EQ((typeLoc().bind("TL")).getName(), "`TypeLoc` Node");
+}
+
 #if GTEST_HAS_DEATH_TEST
 TEST(HasNameDeathTest, DiesOnEmptyName) {
   ASSERT_DEBUG_DEATH({
Index: clang/lib/ASTMatchers/ASTMatchersInternal.cpp
===
--- clang/lib/ASTMatchers/ASTMatchersInternal.cpp
+++ clang/lib/ASTMatchers/ASTMatchersInternal.cpp
@@ -115,15 +115,20 @@
 template 
 class VariadicMatcher : public DynMatcherInterface {
 public:
-  VariadicMatcher(std::vector InnerMatchers)
-  : InnerMatchers(std::move(InnerMatchers)) {}
+  VariadicMatcher(std::string MatcherName,
+  std::vector InnerMatchers)
+  : MatcherName(std::move(MatcherName)),
+InnerMatchers(std::move(InnerMatchers)) {}
 
   bool dynMatches(const DynTypedNode , ASTMatchFinder *Finder,
   BoundNodesTreeBuilder *Builder) const override {
 return Func(DynNode, Finder, Builder, InnerMatchers);
   }
 
+  std::string getName() const override { return MatcherName; }
+
 private:
+  const std::string MatcherName;
   std::vector InnerMatchers;
 };
 
@@ -144,11 +149,40 @@
 return InnerMatcher->TraversalKind();
   }
 
+  std::string getName() const override { return InnerMatcher->getName(); }
+
 private:
   const std::string ID;
   const IntrusiveRefCntPtr InnerMatcher;
 };
 
+/// A matcher that specifies a particular name.
+///
+/// The name provided to the constructor overrides any name that may be
+/// specified by the `InnerMatcher`.
+class NameMatcherImpl : public DynMatcherInterface {
+public:
+  NameMatcherImpl(std::string MatcherName,
+  IntrusiveRefCntPtr InnerMatcher)
+  : MatcherName(std::move(MatcherName)),
+InnerMatcher(std::move(InnerMatcher)) {}
+
+  bool dynMatches(const DynTypedNode , ASTMatchFinder *Finder,
+  BoundNodesTreeBuilder *Builder) const override {
+return InnerMatcher->dynMatches(DynNode, Finder, Builder);
+  }
+
+  std::string getName() const override { return MatcherName; }
+
+  llvm::Optional TraversalKind() const override {
+return InnerMatcher->TraversalKind();
+  }
+
+private:
+  const std::string MatcherName;
+  const IntrusiveRefCntPtr InnerMatcher;
+};
+
 /// A matcher that always returns true.
 class TrueMatcherImpl : public DynMatcherInterface {
 public:
@@ -158,6 +192,8 @@
   BoundNodesTreeBuilder *) const override {
 return true;
   }
+
+  std::string getName() const override { return "TrueMatcher"; }
 };
 
 /// A matcher that specifies a particular \c TraversalKind.
@@ -180,6 +216,8 @@
 return TK;
   }
 
+  std::string getName() const override { return InnerMatcher->getName(); }
+
 private:
   clang::TraversalKind TK;
   IntrusiveRefCntPtr InnerMatcher;
@@ -219,31 +257,31 @@
   RestrictKind =
   ASTNodeKind::getMostDerivedType(RestrictKind, IM.RestrictKind);
 }
-return DynTypedMatcher(
-SupportedKind, RestrictKind,
-new VariadicMatcher(std::move(InnerMatchers)));
+return DynTypedMatcher(SupportedKind, RestrictKind,
+   new VariadicMatcher(
+   "allOf", std::move(InnerMatchers)));
 
   case VO_AnyOf:
-return DynTypedMatcher(
-SupportedKind, RestrictKind,
-new VariadicMatcher(std::move(InnerMatchers)));
+return 

[PATCH] D113917: Add infrastructure to support matcher names.

2021-11-18 Thread James King via Phabricator via cfe-commits
jcking1034 marked an inline comment as done.
jcking1034 added inline comments.



Comment at: clang/include/clang/ASTMatchers/ASTMatchersInternal.h:1022
+  std::string getName() const override {
+return "HasOverloadedOperatorNameMatcher";
+  }

ymandel wrote:
> here and below: drop the "Matcher" suffix?
Done. I've realized that this is a separate issue, but I'm still somewhat 
concerned about how the `HasOverloadedOperatorNameMatcher` is used in two 
different matchers, such that both `hasOverloadedOperatorName` and 
`hasAnyOverloadedOperatorName` will both have the name 
"HasOverloadedOperatorName".


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D113917

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


[PATCH] D113917: Add infrastructure to support matcher names.

2021-11-18 Thread James King via Phabricator via cfe-commits
jcking1034 updated this revision to Diff 388327.
jcking1034 marked 2 inline comments as done.
jcking1034 added a comment.

Update comments, drop "Matcher" suffix from `getName`s


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D113917

Files:
  clang/include/clang/ASTMatchers/ASTMatchersInternal.h
  clang/include/clang/ASTMatchers/ASTMatchersMacros.h
  clang/lib/ASTMatchers/ASTMatchersInternal.cpp
  clang/unittests/ASTMatchers/ASTMatchersInternalTest.cpp

Index: clang/unittests/ASTMatchers/ASTMatchersInternalTest.cpp
===
--- clang/unittests/ASTMatchers/ASTMatchersInternalTest.cpp
+++ clang/unittests/ASTMatchers/ASTMatchersInternalTest.cpp
@@ -20,6 +20,29 @@
 namespace ast_matchers {
 using internal::DynTypedMatcher;
 
+TEST(GetNameTest, ReturnsCorrectName) {
+  // Node
+  EXPECT_EQ(typeLoc().getName(), "`TypeLoc` Node");
+  EXPECT_EQ(typeLoc(pointerTypeLoc()).getName(), "`TypeLoc` Node");
+  EXPECT_EQ(pointerTypeLoc(hasPointeeLoc(typeLoc())).getName(),
+"`PointerTypeLoc` Node");
+  EXPECT_EQ(varDecl(hasInitializer(expr()), hasTypeLoc(typeLoc())).getName(),
+"`VarDecl` Node");
+
+  // Narrowing
+  EXPECT_EQ(isConst().getName(), "isConst");
+
+  // Traversal
+  EXPECT_EQ(hasLoopVariable(varDecl()).getName(), "hasLoopVariable");
+
+  // Polymorphic
+  EXPECT_EQ(internal::Matcher(hasLHS(expr())).getName(),
+"hasLHS");
+
+  // Bound
+  EXPECT_EQ((typeLoc().bind("TL")).getName(), "`TypeLoc` Node");
+}
+
 #if GTEST_HAS_DEATH_TEST
 TEST(HasNameDeathTest, DiesOnEmptyName) {
   ASSERT_DEBUG_DEATH({
Index: clang/lib/ASTMatchers/ASTMatchersInternal.cpp
===
--- clang/lib/ASTMatchers/ASTMatchersInternal.cpp
+++ clang/lib/ASTMatchers/ASTMatchersInternal.cpp
@@ -115,15 +115,19 @@
 template 
 class VariadicMatcher : public DynMatcherInterface {
 public:
-  VariadicMatcher(std::vector InnerMatchers)
-  : InnerMatchers(std::move(InnerMatchers)) {}
+  VariadicMatcher(std::string MatcherName,
+  std::vector InnerMatchers)
+  : MatcherName(MatcherName), InnerMatchers(std::move(InnerMatchers)) {}
 
   bool dynMatches(const DynTypedNode , ASTMatchFinder *Finder,
   BoundNodesTreeBuilder *Builder) const override {
 return Func(DynNode, Finder, Builder, InnerMatchers);
   }
 
+  std::string getName() const override { return MatcherName; }
+
 private:
+  const std::string MatcherName;
   std::vector InnerMatchers;
 };
 
@@ -144,11 +148,39 @@
 return InnerMatcher->TraversalKind();
   }
 
+  std::string getName() const override { return InnerMatcher->getName(); }
+
 private:
   const std::string ID;
   const IntrusiveRefCntPtr InnerMatcher;
 };
 
+/// A matcher that specifies a particular name.
+///
+/// The name provided to the constructor overrides any name that may be
+/// specified by the `InnerMatcher`.
+class NameMatcherImpl : public DynMatcherInterface {
+public:
+  NameMatcherImpl(std::string _MatcherName,
+  IntrusiveRefCntPtr InnerMatcher)
+  : MatcherName(_MatcherName), InnerMatcher(std::move(InnerMatcher)) {}
+
+  bool dynMatches(const DynTypedNode , ASTMatchFinder *Finder,
+  BoundNodesTreeBuilder *Builder) const override {
+return InnerMatcher->dynMatches(DynNode, Finder, Builder);
+  }
+
+  std::string getName() const override { return MatcherName; }
+
+  llvm::Optional TraversalKind() const override {
+return InnerMatcher->TraversalKind();
+  }
+
+private:
+  const std::string MatcherName;
+  const IntrusiveRefCntPtr InnerMatcher;
+};
+
 /// A matcher that always returns true.
 class TrueMatcherImpl : public DynMatcherInterface {
 public:
@@ -158,6 +190,8 @@
   BoundNodesTreeBuilder *) const override {
 return true;
   }
+
+  std::string getName() const override { return "TrueMatcher"; }
 };
 
 /// A matcher that specifies a particular \c TraversalKind.
@@ -180,6 +214,8 @@
 return TK;
   }
 
+  std::string getName() const override { return InnerMatcher->getName(); }
+
 private:
   clang::TraversalKind TK;
   IntrusiveRefCntPtr InnerMatcher;
@@ -219,31 +255,31 @@
   RestrictKind =
   ASTNodeKind::getMostDerivedType(RestrictKind, IM.RestrictKind);
 }
-return DynTypedMatcher(
-SupportedKind, RestrictKind,
-new VariadicMatcher(std::move(InnerMatchers)));
+return DynTypedMatcher(SupportedKind, RestrictKind,
+   new VariadicMatcher(
+   "allOf", std::move(InnerMatchers)));
 
   case VO_AnyOf:
-return DynTypedMatcher(
-SupportedKind, RestrictKind,
-new VariadicMatcher(std::move(InnerMatchers)));
+return DynTypedMatcher(SupportedKind, RestrictKind,
+   new VariadicMatcher(
+   "anyOf", 

[PATCH] D113917: Add infrastructure to support matcher names.

2021-11-17 Thread James King via Phabricator via cfe-commits
jcking1034 added inline comments.



Comment at: clang/include/clang/ASTMatchers/ASTMatchersInternal.h:1409
   return BindableMatcher(
-  makeAllOfComposite(InnerMatchers).template dynCastTo());
+  makeAllOfComposite(InnerMatchers).template dynCastTo(),
+  makeMatcherNameFromType());

jcking1034 wrote:
> @ymandel suggested an alternate implementation where we instead pass the 
> matcher name to `makeAllOfComposite`, which then passes the name to 
> `constructVariadic`, to avoid making changes to `BindableMatcher`. I may look 
> into this again, but my previous attempts to try this approach seemed messy 
> due to the fact that these functions are used in a few different places, and 
> because `makeAllOfComposite` handles cases with 0 or 1 inner matchers without 
> constructing a variadic matcher.
Following up on this, I've gone ahead and implemented @ymandel 's approach, as 
the original implementation led to some issues with `getName` returning the 
wrong name.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D113917

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


[PATCH] D113943: Add `withTag` matcher.

2021-11-17 Thread James King via Phabricator via cfe-commits
jcking1034 updated this revision to Diff 388045.
jcking1034 added a comment.

Change `getMatcherName` to `getName`


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D113943

Files:
  clang/include/clang/ASTMatchers/ASTMatchers.h
  clang/include/clang/ASTMatchers/ASTMatchersInternal.h

Index: clang/include/clang/ASTMatchers/ASTMatchersInternal.h
===
--- clang/include/clang/ASTMatchers/ASTMatchersInternal.h
+++ clang/include/clang/ASTMatchers/ASTMatchersInternal.h
@@ -43,6 +43,7 @@
 #include "clang/AST/ExprCXX.h"
 #include "clang/AST/ExprObjC.h"
 #include "clang/AST/NestedNameSpecifier.h"
+#include "clang/AST/PrettyPrinter.h"
 #include "clang/AST/Stmt.h"
 #include "clang/AST/TemplateName.h"
 #include "clang/AST/Type.h"
@@ -1042,6 +1043,44 @@
   std::vector Names;
 };
 
+template  class WithTagMatcher : public MatcherInterface {
+public:
+  explicit WithTagMatcher(std::string _BeforeTag, std::string _AfterTag,
+  internal::Matcher _InnerMatcher)
+  : BeforeTag(std::move(_BeforeTag)), AfterTag(std::move(_AfterTag)),
+InnerMatcher(_InnerMatcher) {}
+  explicit WithTagMatcher(internal::Matcher _InnerMatcher)
+  : BeforeTag("⭐ Attempting new match"),
+AfterTag("✔️ Concluding attempt"), InnerMatcher(_InnerMatcher) {}
+  bool matches(const T , ASTMatchFinder *Finder,
+   BoundNodesTreeBuilder *Builder) const override {
+DynTypedNode DTN = DynTypedNode::create(Node);
+
+llvm::errs() << BeforeTag << "\n";
+
+llvm::errs() << "Matcher Name: " << InnerMatcher.getName() << "\n";
+
+llvm::errs() << "Node Kind: " << DTN.getNodeKind().asStringRef() << "\n"
+ << "Node Value:\n```\n";
+DTN.print(llvm::errs(), PrintingPolicy(LangOptions()));
+llvm::errs() << "\n```\n"
+ << "Node AST:\n";
+DTN.dump(llvm::errs(), Finder->getASTContext());
+
+bool result = InnerMatcher.matches(Node, Finder, Builder);
+llvm::errs() << "Result: " << (result ? "Successful\n" : "Unsuccessful\n");
+
+llvm::errs() << AfterTag << "\n\n";
+
+return result;
+  }
+
+private:
+  std::string BeforeTag;
+  std::string AfterTag;
+  internal::Matcher InnerMatcher;
+};
+
 /// Matches named declarations with a specific name.
 ///
 /// See \c hasName() and \c hasAnyName() in ASTMatchers.h for details.
@@ -1719,6 +1758,38 @@
   std::tuple Params;
 };
 
+template  class MatcherT,
+  typename ReturnTypesF, typename... ParamTypes>
+class PolymorphicWithTagMatcher {
+public:
+  PolymorphicWithTagMatcher(
+  internal::PolymorphicMatcher
+  _InnerMatcher)
+  : InnerMatcher(_InnerMatcher) {}
+
+  using ReturnTypes = typename ExtractFunctionArgMeta::type;
+
+  template  operator Matcher() const LLVM_LVALUE_FUNCTION {
+static_assert(TypeListContainsSuperOf::value,
+  "right polymorphic conversion");
+return internal::Matcher(
+new internal::WithTagMatcher(internal::Matcher(InnerMatcher)));
+  }
+
+#if LLVM_HAS_RVALUE_REFERENCE_THIS
+  template  operator Matcher() && {
+static_assert(TypeListContainsSuperOf::value,
+  "right polymorphic conversion");
+return internal::Matcher(new internal::WithTagMatcher(
+internal::Matcher(std::move(InnerMatcher;
+  }
+#endif
+
+private:
+  internal::PolymorphicMatcher
+  InnerMatcher;
+};
+
 /// Matches nodes of type T that have child nodes of type ChildT for
 /// which a specified child matcher matches.
 ///
Index: clang/include/clang/ASTMatchers/ASTMatchers.h
===
--- clang/include/clang/ASTMatchers/ASTMatchers.h
+++ clang/include/clang/ASTMatchers/ASTMatchers.h
@@ -2993,6 +2993,40 @@
   new internal::HasNameMatcher({std::string(Name)}));
 }
 
+template 
+inline internal::Matcher withTag(std::string BeforeTag, std::string AfterTag,
+const internal::Matcher ) {
+  return internal::Matcher(
+  new internal::WithTagMatcher(BeforeTag, AfterTag, InnerMatcher));
+}
+
+template  class MatcherT,
+  typename ReturnTypesF, typename... ParamTypes>
+inline internal::PolymorphicWithTagMatcher
+withTag(std::string BeforeTag, std::string AfterTag,
+const internal::PolymorphicMatcher ) {
+  return internal::PolymorphicWithTagMatcher(BeforeTag, AfterTag,
+InnerMatcher);
+}
+
+template 
+inline internal::Matcher withTag(const internal::Matcher ) {
+  return internal::Matcher(new internal::WithTagMatcher(InnerMatcher));
+}
+
+template  class MatcherT,
+  typename ReturnTypesF, typename... ParamTypes>
+inline internal::PolymorphicWithTagMatcher
+withTag(const internal::PolymorphicMatcher ) {
+  return internal::PolymorphicWithTagMatcher(InnerMatcher);
+}
+
 /// Matches NamedDecl nodes that 

[PATCH] D113917: Add infrastructure to support matcher names.

2021-11-17 Thread James King via Phabricator via cfe-commits
jcking1034 updated this revision to Diff 388041.
jcking1034 added a comment.

Add tests, rename `getMatcherName` to `getName`, update `makeAllOfComposite`


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D113917

Files:
  clang/include/clang/ASTMatchers/ASTMatchersInternal.h
  clang/include/clang/ASTMatchers/ASTMatchersMacros.h
  clang/lib/ASTMatchers/ASTMatchersInternal.cpp
  clang/unittests/ASTMatchers/ASTMatchersInternalTest.cpp

Index: clang/unittests/ASTMatchers/ASTMatchersInternalTest.cpp
===
--- clang/unittests/ASTMatchers/ASTMatchersInternalTest.cpp
+++ clang/unittests/ASTMatchers/ASTMatchersInternalTest.cpp
@@ -20,6 +20,29 @@
 namespace ast_matchers {
 using internal::DynTypedMatcher;
 
+TEST(GetNameTest, ReturnsCorrectName) {
+  // Node
+  EXPECT_EQ(typeLoc().getName(), "`TypeLoc` Node");
+  EXPECT_EQ(typeLoc(pointerTypeLoc()).getName(), "`TypeLoc` Node");
+  EXPECT_EQ(pointerTypeLoc(hasPointeeLoc(typeLoc())).getName(),
+"`PointerTypeLoc` Node");
+  EXPECT_EQ(varDecl(hasInitializer(expr()), hasTypeLoc(typeLoc())).getName(),
+"`VarDecl` Node");
+
+  // Narrowing
+  EXPECT_EQ(isConst().getName(), "isConst");
+
+  // Traversal
+  EXPECT_EQ(hasLoopVariable(varDecl()).getName(), "hasLoopVariable");
+
+  // Polymorphic
+  EXPECT_EQ(internal::Matcher(hasLHS(expr())).getName(),
+"hasLHS");
+
+  // Bound
+  EXPECT_EQ((typeLoc().bind("TL")).getName(), "`TypeLoc` Node");
+}
+
 #if GTEST_HAS_DEATH_TEST
 TEST(HasNameDeathTest, DiesOnEmptyName) {
   ASSERT_DEBUG_DEATH({
Index: clang/lib/ASTMatchers/ASTMatchersInternal.cpp
===
--- clang/lib/ASTMatchers/ASTMatchersInternal.cpp
+++ clang/lib/ASTMatchers/ASTMatchersInternal.cpp
@@ -115,15 +115,19 @@
 template 
 class VariadicMatcher : public DynMatcherInterface {
 public:
-  VariadicMatcher(std::vector InnerMatchers)
-  : InnerMatchers(std::move(InnerMatchers)) {}
+  VariadicMatcher(std::string MatcherName,
+  std::vector InnerMatchers)
+  : MatcherName(MatcherName), InnerMatchers(std::move(InnerMatchers)) {}
 
   bool dynMatches(const DynTypedNode , ASTMatchFinder *Finder,
   BoundNodesTreeBuilder *Builder) const override {
 return Func(DynNode, Finder, Builder, InnerMatchers);
   }
 
+  std::string getName() const override { return MatcherName; }
+
 private:
+  const std::string MatcherName;
   std::vector InnerMatchers;
 };
 
@@ -144,11 +148,39 @@
 return InnerMatcher->TraversalKind();
   }
 
+  std::string getName() const override { return InnerMatcher->getName(); }
+
 private:
   const std::string ID;
   const IntrusiveRefCntPtr InnerMatcher;
 };
 
+/// A matcher that specifies a particular name.
+///
+/// The name provided to the constructor overrides any name that may be
+/// specified by the `InnerMatcher`.
+class NameMatcherImpl : public DynMatcherInterface {
+public:
+  NameMatcherImpl(std::string _MatcherName,
+  IntrusiveRefCntPtr InnerMatcher)
+  : MatcherName(_MatcherName), InnerMatcher(std::move(InnerMatcher)) {}
+
+  bool dynMatches(const DynTypedNode , ASTMatchFinder *Finder,
+  BoundNodesTreeBuilder *Builder) const override {
+return InnerMatcher->dynMatches(DynNode, Finder, Builder);
+  }
+
+  std::string getName() const override { return MatcherName; }
+
+  llvm::Optional TraversalKind() const override {
+return InnerMatcher->TraversalKind();
+  }
+
+private:
+  const std::string MatcherName;
+  const IntrusiveRefCntPtr InnerMatcher;
+};
+
 /// A matcher that always returns true.
 class TrueMatcherImpl : public DynMatcherInterface {
 public:
@@ -158,6 +190,8 @@
   BoundNodesTreeBuilder *) const override {
 return true;
   }
+
+  std::string getName() const override { return "TrueMatcher"; }
 };
 
 /// A matcher that specifies a particular \c TraversalKind.
@@ -180,6 +214,8 @@
 return TK;
   }
 
+  std::string getName() const override { return InnerMatcher->getName(); }
+
 private:
   clang::TraversalKind TK;
   IntrusiveRefCntPtr InnerMatcher;
@@ -219,31 +255,31 @@
   RestrictKind =
   ASTNodeKind::getMostDerivedType(RestrictKind, IM.RestrictKind);
 }
-return DynTypedMatcher(
-SupportedKind, RestrictKind,
-new VariadicMatcher(std::move(InnerMatchers)));
+return DynTypedMatcher(SupportedKind, RestrictKind,
+   new VariadicMatcher(
+   "allOf", std::move(InnerMatchers)));
 
   case VO_AnyOf:
-return DynTypedMatcher(
-SupportedKind, RestrictKind,
-new VariadicMatcher(std::move(InnerMatchers)));
+return DynTypedMatcher(SupportedKind, RestrictKind,
+   new VariadicMatcher(
+   "anyOf", std::move(InnerMatchers)));
 
   case 

[PATCH] D113943: Add `withTag` matcher.

2021-11-16 Thread James King via Phabricator via cfe-commits
jcking1034 updated this revision to Diff 387769.
jcking1034 added a comment.

Improve wrapping of PolymorphicMatchers


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D113943

Files:
  clang/include/clang/ASTMatchers/ASTMatchers.h
  clang/include/clang/ASTMatchers/ASTMatchersInternal.h

Index: clang/include/clang/ASTMatchers/ASTMatchersInternal.h
===
--- clang/include/clang/ASTMatchers/ASTMatchersInternal.h
+++ clang/include/clang/ASTMatchers/ASTMatchersInternal.h
@@ -43,6 +43,7 @@
 #include "clang/AST/ExprCXX.h"
 #include "clang/AST/ExprObjC.h"
 #include "clang/AST/NestedNameSpecifier.h"
+#include "clang/AST/PrettyPrinter.h"
 #include "clang/AST/Stmt.h"
 #include "clang/AST/TemplateName.h"
 #include "clang/AST/Type.h"
@@ -1042,6 +1043,44 @@
   std::vector Names;
 };
 
+template  class WithTagMatcher : public MatcherInterface {
+public:
+  explicit WithTagMatcher(std::string _BeforeTag, std::string _AfterTag,
+  internal::Matcher _InnerMatcher)
+  : BeforeTag(std::move(_BeforeTag)), AfterTag(std::move(_AfterTag)),
+InnerMatcher(_InnerMatcher) {}
+  explicit WithTagMatcher(internal::Matcher _InnerMatcher)
+  : BeforeTag("⭐ Attempting new match"),
+AfterTag("✔️ Concluding attempt"), InnerMatcher(_InnerMatcher) {}
+  bool matches(const T , ASTMatchFinder *Finder,
+   BoundNodesTreeBuilder *Builder) const override {
+DynTypedNode DTN = DynTypedNode::create(Node);
+
+llvm::errs() << BeforeTag << "\n";
+
+llvm::errs() << "Matcher Name: " << InnerMatcher.getMatcherName() << "\n";
+
+llvm::errs() << "Node Kind: " << DTN.getNodeKind().asStringRef() << "\n"
+ << "Node Value:\n```\n";
+DTN.print(llvm::errs(), PrintingPolicy(LangOptions()));
+llvm::errs() << "\n```\n"
+ << "Node AST:\n";
+DTN.dump(llvm::errs(), Finder->getASTContext());
+
+bool result = InnerMatcher.matches(Node, Finder, Builder);
+llvm::errs() << "Result: " << (result ? "Successful\n" : "Unsuccessful\n");
+
+llvm::errs() << AfterTag << "\n\n";
+
+return result;
+  }
+
+private:
+  std::string BeforeTag;
+  std::string AfterTag;
+  internal::Matcher InnerMatcher;
+};
+
 /// Matches named declarations with a specific name.
 ///
 /// See \c hasName() and \c hasAnyName() in ASTMatchers.h for details.
@@ -1718,6 +1757,38 @@
   std::tuple Params;
 };
 
+template  class MatcherT,
+  typename ReturnTypesF, typename... ParamTypes>
+class PolymorphicWithTagMatcher {
+public:
+  PolymorphicWithTagMatcher(
+  internal::PolymorphicMatcher
+  _InnerMatcher)
+  : InnerMatcher(_InnerMatcher) {}
+
+  using ReturnTypes = typename ExtractFunctionArgMeta::type;
+
+  template  operator Matcher() const LLVM_LVALUE_FUNCTION {
+static_assert(TypeListContainsSuperOf::value,
+  "right polymorphic conversion");
+return internal::Matcher(
+new internal::WithTagMatcher(internal::Matcher(InnerMatcher)));
+  }
+
+#if LLVM_HAS_RVALUE_REFERENCE_THIS
+  template  operator Matcher() && {
+static_assert(TypeListContainsSuperOf::value,
+  "right polymorphic conversion");
+return internal::Matcher(new internal::WithTagMatcher(
+internal::Matcher(std::move(InnerMatcher;
+  }
+#endif
+
+private:
+  internal::PolymorphicMatcher
+  InnerMatcher;
+};
+
 /// Matches nodes of type T that have child nodes of type ChildT for
 /// which a specified child matcher matches.
 ///
Index: clang/include/clang/ASTMatchers/ASTMatchers.h
===
--- clang/include/clang/ASTMatchers/ASTMatchers.h
+++ clang/include/clang/ASTMatchers/ASTMatchers.h
@@ -2993,6 +2993,40 @@
   new internal::HasNameMatcher({std::string(Name)}));
 }
 
+template 
+inline internal::Matcher withTag(std::string BeforeTag, std::string AfterTag,
+const internal::Matcher ) {
+  return internal::Matcher(
+  new internal::WithTagMatcher(BeforeTag, AfterTag, InnerMatcher));
+}
+
+template  class MatcherT,
+  typename ReturnTypesF, typename... ParamTypes>
+inline internal::PolymorphicWithTagMatcher
+withTag(std::string BeforeTag, std::string AfterTag,
+const internal::PolymorphicMatcher ) {
+  return internal::PolymorphicWithTagMatcher(BeforeTag, AfterTag,
+InnerMatcher);
+}
+
+template 
+inline internal::Matcher withTag(const internal::Matcher ) {
+  return internal::Matcher(new internal::WithTagMatcher(InnerMatcher));
+}
+
+template  class MatcherT,
+  typename ReturnTypesF, typename... ParamTypes>
+inline internal::PolymorphicWithTagMatcher
+withTag(const internal::PolymorphicMatcher ) {
+  return internal::PolymorphicWithTagMatcher(InnerMatcher);
+}
+
 /// Matches NamedDecl 

[PATCH] D113943: Add withTag matcher.

2021-11-15 Thread James King via Phabricator via cfe-commits
jcking1034 created this revision.
jcking1034 added reviewers: ymandel, tdl-g, aaron.ballman.
jcking1034 requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Adds a `withTag` matcher which outputs contextual information for
better debugging. This relies on changes made in
https://reviews.llvm.org/D113917 to access the names of matchers.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D113943

Files:
  clang/include/clang/ASTMatchers/ASTMatchers.h
  clang/include/clang/ASTMatchers/ASTMatchersInternal.h


Index: clang/include/clang/ASTMatchers/ASTMatchersInternal.h
===
--- clang/include/clang/ASTMatchers/ASTMatchersInternal.h
+++ clang/include/clang/ASTMatchers/ASTMatchersInternal.h
@@ -43,6 +43,7 @@
 #include "clang/AST/ExprCXX.h"
 #include "clang/AST/ExprObjC.h"
 #include "clang/AST/NestedNameSpecifier.h"
+#include "clang/AST/PrettyPrinter.h"
 #include "clang/AST/Stmt.h"
 #include "clang/AST/TemplateName.h"
 #include "clang/AST/Type.h"
@@ -1042,6 +1043,44 @@
   std::vector Names;
 };
 
+template  class WithTagMatcher : public MatcherInterface {
+public:
+  explicit WithTagMatcher(std::string _BeforeTag, std::string _AfterTag,
+  internal::Matcher _InnerMatcher)
+  : BeforeTag(std::move(_BeforeTag)), AfterTag(std::move(_AfterTag)),
+InnerMatcher(_InnerMatcher) {}
+  explicit WithTagMatcher(internal::Matcher _InnerMatcher)
+  : BeforeTag("⭐ Attempting new match"),
+AfterTag("✔️ Concluding attempt"), InnerMatcher(_InnerMatcher) {}
+  bool matches(const T , ASTMatchFinder *Finder,
+   BoundNodesTreeBuilder *Builder) const override {
+DynTypedNode DTN = DynTypedNode::create(Node);
+
+llvm::errs() << BeforeTag << "\n";
+
+llvm::errs() << "Matcher Name: " << InnerMatcher.getMatcherName() << "\n";
+
+llvm::errs() << "Node Kind: " << DTN.getNodeKind().asStringRef() << "\n"
+ << "Node Value:\n```\n";
+DTN.print(llvm::errs(), PrintingPolicy(LangOptions()));
+llvm::errs() << "\n```\n"
+ << "Node AST:\n";
+DTN.dump(llvm::errs(), Finder->getASTContext());
+
+bool result = InnerMatcher.matches(Node, Finder, Builder);
+llvm::errs() << "Result: " << (result ? "Successful\n" : "Unsuccessful\n");
+
+llvm::errs() << AfterTag << "\n\n";
+
+return result;
+  }
+
+private:
+  std::string BeforeTag;
+  std::string AfterTag;
+  internal::Matcher InnerMatcher;
+};
+
 /// Matches named declarations with a specific name.
 ///
 /// See \c hasName() and \c hasAnyName() in ASTMatchers.h for details.
Index: clang/include/clang/ASTMatchers/ASTMatchers.h
===
--- clang/include/clang/ASTMatchers/ASTMatchers.h
+++ clang/include/clang/ASTMatchers/ASTMatchers.h
@@ -2993,6 +2993,37 @@
   new internal::HasNameMatcher({std::string(Name)}));
 }
 
+template 
+inline internal::Matcher withTag(std::string BeforeTag, std::string 
AfterTag,
+const internal::Matcher ) {
+  return internal::Matcher(
+  new internal::WithTagMatcher(BeforeTag, AfterTag, InnerMatcher));
+}
+
+template  class MatcherT,
+  typename ReturnTypesF, typename... ParamTypes>
+inline MatcherT
+withTag(std::string BeforeTag, std::string AfterTag,
+const internal::PolymorphicMatcher ) {
+  return internal::Matcher(new internal::WithTagMatcher(
+  BeforeTag, AfterTag, internal::Matcher(InnerMatcher)));
+}
+
+template 
+inline internal::Matcher withTag(const internal::Matcher ) {
+  return internal::Matcher(new internal::WithTagMatcher(InnerMatcher));
+}
+
+template  class MatcherT,
+  typename ReturnTypesF, typename... ParamTypes>
+inline MatcherT
+withTag(const internal::PolymorphicMatcher ) {
+  return internal::Matcher(
+  new internal::WithTagMatcher(internal::Matcher(InnerMatcher)));
+}
+
 /// Matches NamedDecl nodes that have any of the specified names.
 ///
 /// This matcher is only provided as a performance optimization of hasName.


Index: clang/include/clang/ASTMatchers/ASTMatchersInternal.h
===
--- clang/include/clang/ASTMatchers/ASTMatchersInternal.h
+++ clang/include/clang/ASTMatchers/ASTMatchersInternal.h
@@ -43,6 +43,7 @@
 #include "clang/AST/ExprCXX.h"
 #include "clang/AST/ExprObjC.h"
 #include "clang/AST/NestedNameSpecifier.h"
+#include "clang/AST/PrettyPrinter.h"
 #include "clang/AST/Stmt.h"
 #include "clang/AST/TemplateName.h"
 #include "clang/AST/Type.h"
@@ -1042,6 +1043,44 @@
   std::vector Names;
 };
 
+template  class WithTagMatcher : public MatcherInterface {
+public:
+  explicit WithTagMatcher(std::string _BeforeTag, std::string _AfterTag,
+  internal::Matcher _InnerMatcher)
+  : BeforeTag(std::move(_BeforeTag)), AfterTag(std::move(_AfterTag)),
+

[PATCH] D113917: Add infrastructure to support matcher names.

2021-11-15 Thread James King via Phabricator via cfe-commits
jcking1034 added inline comments.



Comment at: clang/include/clang/ASTMatchers/ASTMatchersInternal.h:1021
 
+  std::string getName() const override {
+return "HasOverloadedOperatorNameMatcher";

Here and below, we have the option to use the name of the matcher (for this, we 
could use "hasOverloadedOperatorName" instead). However, some of these classes 
are used in multiple matchers. For example, `HasOverloadedOperatorNameMatcher` 
is used in both `hasOverloadedOperatorName` and `hasAnyOverloadedOperatorName`, 
which I'm a bit concerned about.



Comment at: clang/include/clang/ASTMatchers/ASTMatchersInternal.h:1409
   return BindableMatcher(
-  makeAllOfComposite(InnerMatchers).template dynCastTo());
+  makeAllOfComposite(InnerMatchers).template dynCastTo(),
+  makeMatcherNameFromType());

@ymandel suggested an alternate implementation where we instead pass the 
matcher name to `makeAllOfComposite`, which then passes the name to 
`constructVariadic`, to avoid making changes to `BindableMatcher`. I may look 
into this again, but my previous attempts to try this approach seemed messy due 
to the fact that these functions are used in a few different places, and 
because `makeAllOfComposite` handles cases with 0 or 1 inner matchers without 
constructing a variadic matcher.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D113917

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


[PATCH] D113917: Add infrastructure to support matcher names.

2021-11-15 Thread James King via Phabricator via cfe-commits
jcking1034 created this revision.
jcking1034 added reviewers: ymandel, tdl-g, aaron.ballman.
jcking1034 requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

This contains changes to the AST Matcher infrastructure in order to provide
contextual information about each matcher. This information can be useful for
tasks such as performing introspection on matchers.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D113917

Files:
  clang/include/clang/ASTMatchers/ASTMatchersInternal.h
  clang/include/clang/ASTMatchers/ASTMatchersMacros.h
  clang/lib/ASTMatchers/ASTMatchersInternal.cpp

Index: clang/lib/ASTMatchers/ASTMatchersInternal.cpp
===
--- clang/lib/ASTMatchers/ASTMatchersInternal.cpp
+++ clang/lib/ASTMatchers/ASTMatchersInternal.cpp
@@ -115,15 +115,19 @@
 template 
 class VariadicMatcher : public DynMatcherInterface {
 public:
-  VariadicMatcher(std::vector InnerMatchers)
-  : InnerMatchers(std::move(InnerMatchers)) {}
+  VariadicMatcher(std::string MatcherName,
+  std::vector InnerMatchers)
+  : MatcherName(MatcherName), InnerMatchers(std::move(InnerMatchers)) {}
 
   bool dynMatches(const DynTypedNode , ASTMatchFinder *Finder,
   BoundNodesTreeBuilder *Builder) const override {
 return Func(DynNode, Finder, Builder, InnerMatchers);
   }
 
+  std::string getName() const override { return MatcherName; }
+
 private:
+  const std::string MatcherName;
   std::vector InnerMatchers;
 };
 
@@ -144,11 +148,39 @@
 return InnerMatcher->TraversalKind();
   }
 
+  std::string getName() const override { return InnerMatcher->getName(); }
+
 private:
   const std::string ID;
   const IntrusiveRefCntPtr InnerMatcher;
 };
 
+/// A matcher that specifies a particular name.
+///
+/// The name provided to the constructor overrides any name that may be
+/// specified by the `InnerMatcher`.
+class NameMatcherImpl : public DynMatcherInterface {
+public:
+  NameMatcherImpl(std::string _MatcherName,
+  IntrusiveRefCntPtr InnerMatcher)
+  : MatcherName(_MatcherName), InnerMatcher(std::move(InnerMatcher)) {}
+
+  bool dynMatches(const DynTypedNode , ASTMatchFinder *Finder,
+  BoundNodesTreeBuilder *Builder) const override {
+return InnerMatcher->dynMatches(DynNode, Finder, Builder);
+  }
+
+  std::string getName() const override { return MatcherName; }
+
+  llvm::Optional TraversalKind() const override {
+return InnerMatcher->TraversalKind();
+  }
+
+private:
+  const std::string MatcherName;
+  const IntrusiveRefCntPtr InnerMatcher;
+};
+
 /// A matcher that always returns true.
 class TrueMatcherImpl : public DynMatcherInterface {
 public:
@@ -158,6 +190,8 @@
   BoundNodesTreeBuilder *) const override {
 return true;
   }
+
+  std::string getName() const override { return "TrueMatcher"; }
 };
 
 /// A matcher that specifies a particular \c TraversalKind.
@@ -180,6 +214,8 @@
 return TK;
   }
 
+  std::string getName() const override { return InnerMatcher->getName(); }
+
 private:
   clang::TraversalKind TK;
   IntrusiveRefCntPtr InnerMatcher;
@@ -219,31 +255,31 @@
   RestrictKind =
   ASTNodeKind::getMostDerivedType(RestrictKind, IM.RestrictKind);
 }
-return DynTypedMatcher(
-SupportedKind, RestrictKind,
-new VariadicMatcher(std::move(InnerMatchers)));
+return DynTypedMatcher(SupportedKind, RestrictKind,
+   new VariadicMatcher(
+   "allOf", std::move(InnerMatchers)));
 
   case VO_AnyOf:
-return DynTypedMatcher(
-SupportedKind, RestrictKind,
-new VariadicMatcher(std::move(InnerMatchers)));
+return DynTypedMatcher(SupportedKind, RestrictKind,
+   new VariadicMatcher(
+   "anyOf", std::move(InnerMatchers)));
 
   case VO_EachOf:
-return DynTypedMatcher(
-SupportedKind, RestrictKind,
-new VariadicMatcher(std::move(InnerMatchers)));
+return DynTypedMatcher(SupportedKind, RestrictKind,
+   new VariadicMatcher(
+   "eachOf", std::move(InnerMatchers)));
 
   case VO_Optionally:
 return DynTypedMatcher(SupportedKind, RestrictKind,
new VariadicMatcher(
-   std::move(InnerMatchers)));
+   "optionally", std::move(InnerMatchers)));
 
   case VO_UnaryNot:
 // FIXME: Implement the Not operator to take a single matcher instead of a
 // vector.
 return DynTypedMatcher(
 SupportedKind, RestrictKind,
-new VariadicMatcher(std::move(InnerMatchers)));
+new VariadicMatcher("not", std::move(InnerMatchers)));
   }
   llvm_unreachable("Invalid Op value.");
 }
@@ -263,6 +299,14 @@
   return Copy;
 }
 
+DynTypedMatcher

[PATCH] D113575: Add `isInitCapture` and `forEachLambdaCapture` matchers.

2021-11-11 Thread James King via Phabricator via cfe-commits
jcking1034 marked an inline comment as done.
jcking1034 added inline comments.



Comment at: clang/include/clang/ASTMatchers/ASTMatchers.h:4224
+/// float z;
+/// auto f = [=]() { return x + y + z; };
+///   }

fowles wrote:
> it would be nice to be able to do something like
> 
> ```
> int main() {
>   int x, y;
>   float z;
>   auto f = [=, z]() { return x+ y + z; };
> }
> ```
> 
> `lambdaExpr(forEachLambdaCapture(isImplicit())` matches `x` and `y` but not 
> `z`
I believe that this should be possible, I've gone ahead and added some unit 
tests to demonstrate (see the tests named `MatchImplicitCapturesOnly` and 
`MatchExplicitCapturesOnly`).


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D113575

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


[PATCH] D113575: Add `isInitCapture` and `forEachLambdaCapture` matchers.

2021-11-11 Thread James King via Phabricator via cfe-commits
jcking1034 updated this revision to Diff 386577.
jcking1034 added a comment.

Add additional unit tests.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D113575

Files:
  clang/docs/LibASTMatchersReference.html
  clang/include/clang/ASTMatchers/ASTMatchers.h
  clang/lib/ASTMatchers/Dynamic/Registry.cpp
  clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
  clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp

Index: clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
===
--- clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
+++ clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
@@ -4769,6 +4769,66 @@
 cxxConstructorDecl(forEachConstructorInitializer(cxxCtorInitializer();
 }
 
+TEST(ForEachLambdaCapture, MatchesCaptures) {
+  EXPECT_TRUE(matches(
+  "int main() { int x, y; auto f = [x, y]() { return x + y; }; }",
+  lambdaExpr(forEachLambdaCapture(lambdaCapture())), langCxx11OrLater()));
+  auto matcher = lambdaExpr(forEachLambdaCapture(
+  lambdaCapture(capturesVar(varDecl(hasType(isInteger().bind("LC")));
+  EXPECT_TRUE(matchAndVerifyResultTrue(
+  "int main() { int x, y; float z; auto f = [=]() { return x + y + z; }; }",
+  matcher, std::make_unique>("LC", 2)));
+  EXPECT_TRUE(matchAndVerifyResultTrue(
+  "int main() { int x, y; float z; auto f = [x, y, z]() { return x + y + "
+  "z; }; }",
+  matcher, std::make_unique>("LC", 2)));
+}
+
+TEST(ForEachLambdaCapture, IgnoreUnlessSpelledInSource) {
+  auto matcher =
+  traverse(TK_IgnoreUnlessSpelledInSource,
+   lambdaExpr(forEachLambdaCapture(
+   lambdaCapture(capturesVar(varDecl(hasType(isInteger()
+   .bind("LC";
+  EXPECT_TRUE(
+  notMatches("int main() { int x, y; auto f = [=]() { return x + y; }; }",
+ matcher, langCxx11OrLater()));
+  EXPECT_TRUE(
+  notMatches("int main() { int x, y; auto f = [&]() { return x + y; }; }",
+ matcher, langCxx11OrLater()));
+  EXPECT_TRUE(matchAndVerifyResultTrue(
+  R"cc(
+  int main() {
+int x, y;
+float z;
+auto f = [=, ]() { return x + y + z; };
+  }
+  )cc",
+  matcher, std::make_unique>("LC", 1)));
+}
+
+TEST(ForEachLambdaCapture, MatchImplicitCapturesOnly) {
+  auto matcher =
+  lambdaExpr(forEachLambdaCapture(lambdaCapture(isImplicit()).bind("LC")));
+  EXPECT_TRUE(matchAndVerifyResultTrue(
+  "int main() { int x, y, z; auto f = [=, ]() { return x + y + z; }; }",
+  matcher, std::make_unique>("LC", 2)));
+  EXPECT_TRUE(matchAndVerifyResultTrue(
+  "int main() { int x, y, z; auto f = [&, z]() { return x + y + z; }; }",
+  matcher, std::make_unique>("LC", 2)));
+}
+
+TEST(ForEachLambdaCapture, MatchExplicitCapturesOnly) {
+  auto matcher = lambdaExpr(
+  forEachLambdaCapture(lambdaCapture(unless(isImplicit())).bind("LC")));
+  EXPECT_TRUE(matchAndVerifyResultTrue(
+  "int main() { int x, y, z; auto f = [=, ]() { return x + y + z; }; }",
+  matcher, std::make_unique>("LC", 1)));
+  EXPECT_TRUE(matchAndVerifyResultTrue(
+  "int main() { int x, y, z; auto f = [&, z]() { return x + y + z; }; }",
+  matcher, std::make_unique>("LC", 1)));
+}
+
 TEST(HasConditionVariableStatement, DoesNotMatchCondition) {
   EXPECT_TRUE(notMatches(
 "void x() { if(true) {} }",
Index: clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
===
--- clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
+++ clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
@@ -1439,6 +1439,22 @@
   EXPECT_TRUE(notMatches("int X;", M));
 }
 
+TEST_P(ASTMatchersTest, IsInitCapture) {
+  if (!GetParam().isCXX11OrLater()) {
+return;
+  }
+  auto M = varDecl(hasName("vd"), isInitCapture());
+  EXPECT_TRUE(notMatches(
+  "int main() { int vd = 3; auto f = [vd]() { return vd; }; }", M));
+
+  if (!GetParam().isCXX14OrLater()) {
+return;
+  }
+  EXPECT_TRUE(matches("int main() { auto f = [vd=3]() { return vd; }; }", M));
+  EXPECT_TRUE(matches(
+  "int main() { int x = 3; auto f = [vd=x]() { return vd; }; }", M));
+}
+
 TEST_P(ASTMatchersTest, StorageDuration) {
   StringRef T =
   "void f() { int x; static int y; } int a;static int b;extern int c;";
Index: clang/lib/ASTMatchers/Dynamic/Registry.cpp
===
--- clang/lib/ASTMatchers/Dynamic/Registry.cpp
+++ clang/lib/ASTMatchers/Dynamic/Registry.cpp
@@ -246,6 +246,7 @@
   REGISTER_MATCHER(forEachArgumentWithParamType);
   REGISTER_MATCHER(forEachConstructorInitializer);
   REGISTER_MATCHER(forEachDescendant);
+  REGISTER_MATCHER(forEachLambdaCapture);
   REGISTER_MATCHER(forEachOverridden);
   REGISTER_MATCHER(forEachSwitchCase);
   REGISTER_MATCHER(forField);

[PATCH] D113575: Add `isInitCapture` and `forEachLambdaCapture` matchers.

2021-11-10 Thread James King via Phabricator via cfe-commits
jcking1034 created this revision.
jcking1034 added reviewers: ymandel, tdl-g, aaron.ballman, fowles.
jcking1034 requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

This contributes follow-up work from https://reviews.llvm.org/D112491, which
allows for increased control over the matching of lambda captures. This also
updates the documentation for the `lambdaCapture` matcher.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D113575

Files:
  clang/docs/LibASTMatchersReference.html
  clang/include/clang/ASTMatchers/ASTMatchers.h
  clang/lib/ASTMatchers/Dynamic/Registry.cpp
  clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
  clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp

Index: clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
===
--- clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
+++ clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
@@ -4769,6 +4769,36 @@
 cxxConstructorDecl(forEachConstructorInitializer(cxxCtorInitializer();
 }
 
+TEST(ForEachLambdaCapture, MatchesCaptures) {
+  EXPECT_TRUE(matches(
+  "int main() { int x, y; auto f = [x, y]() { return x + y; }; }",
+  lambdaExpr(forEachLambdaCapture(lambdaCapture())), langCxx11OrLater()));
+  auto matcher = lambdaExpr(forEachLambdaCapture(
+  lambdaCapture(capturesVar(varDecl(hasType(isInteger().bind("LC")));
+  EXPECT_TRUE(matchAndVerifyResultTrue(
+  "int main() { int x, y; float z; auto f = [=]() { return x + y + z; }; }",
+  matcher, std::make_unique>("LC", 2)));
+  EXPECT_TRUE(matchAndVerifyResultTrue(
+  "int main() { int x, y; float z; auto f = [x, y, z]() { return x + y + "
+  "z; }; }",
+  matcher, std::make_unique>("LC", 2)));
+}
+
+TEST(ForEachLambdaCapture, IgnoreUnlessSpelledInSource) {
+  auto matcher =
+  traverse(TK_IgnoreUnlessSpelledInSource,
+   lambdaExpr(forEachLambdaCapture(
+   lambdaCapture(capturesVar(varDecl(hasType(isInteger()
+   .bind("LC";
+  EXPECT_TRUE(
+  notMatches("int main() { int x, y; auto f = [=]() { return x + y; }; }",
+ matcher, langCxx11OrLater()));
+  EXPECT_TRUE(matchAndVerifyResultTrue(
+  "int main() { int x, y; float z; auto f = [=, ]() { return x + y + z; "
+  "}; }",
+  matcher, std::make_unique>("LC", 1)));
+}
+
 TEST(HasConditionVariableStatement, DoesNotMatchCondition) {
   EXPECT_TRUE(notMatches(
 "void x() { if(true) {} }",
Index: clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
===
--- clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
+++ clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
@@ -1439,6 +1439,22 @@
   EXPECT_TRUE(notMatches("int X;", M));
 }
 
+TEST_P(ASTMatchersTest, IsInitCapture) {
+  if (!GetParam().isCXX11OrLater()) {
+return;
+  }
+  auto M = varDecl(hasName("vd"), isInitCapture());
+  EXPECT_TRUE(notMatches(
+  "int main() { int vd = 3; auto f = [vd]() { return vd; }; }", M));
+
+  if (!GetParam().isCXX14OrLater()) {
+return;
+  }
+  EXPECT_TRUE(matches("int main() { auto f = [vd=3]() { return vd; }; }", M));
+  EXPECT_TRUE(matches(
+  "int main() { int x = 3; auto f = [vd=x]() { return vd; }; }", M));
+}
+
 TEST_P(ASTMatchersTest, StorageDuration) {
   StringRef T =
   "void f() { int x; static int y; } int a;static int b;extern int c;";
Index: clang/lib/ASTMatchers/Dynamic/Registry.cpp
===
--- clang/lib/ASTMatchers/Dynamic/Registry.cpp
+++ clang/lib/ASTMatchers/Dynamic/Registry.cpp
@@ -246,6 +246,7 @@
   REGISTER_MATCHER(forEachArgumentWithParamType);
   REGISTER_MATCHER(forEachConstructorInitializer);
   REGISTER_MATCHER(forEachDescendant);
+  REGISTER_MATCHER(forEachLambdaCapture);
   REGISTER_MATCHER(forEachOverridden);
   REGISTER_MATCHER(forEachSwitchCase);
   REGISTER_MATCHER(forField);
@@ -424,6 +425,7 @@
   REGISTER_MATCHER(isImplicit);
   REGISTER_MATCHER(isInStdNamespace);
   REGISTER_MATCHER(isInTemplateInstantiation);
+  REGISTER_MATCHER(isInitCapture);
   REGISTER_MATCHER(isInline);
   REGISTER_MATCHER(isInstanceMessage);
   REGISTER_MATCHER(isInstanceMethod);
Index: clang/include/clang/ASTMatchers/ASTMatchers.h
===
--- clang/include/clang/ASTMatchers/ASTMatchers.h
+++ clang/include/clang/ASTMatchers/ASTMatchers.h
@@ -4205,6 +4205,45 @@
   InnerMatcher.matches(*Initializer, Finder, Builder));
 }
 
+/// Matches a variable serving as the implicit variable for a lambda init-
+/// capture.
+///
+/// Example matches x (matcher = varDecl(isInitCapture()))
+/// \code
+/// auto f = [x=3]() { return x; };
+/// \endcode
+AST_MATCHER(VarDecl, isInitCapture) { return Node.isInitCapture(); }
+
+/// Matches each lambda capture in 

[PATCH] D112491: Add `LambdaCapture`-related matchers.

2021-11-08 Thread James King via Phabricator via cfe-commits
jcking1034 added a comment.

@aaron.ballman Just wanted to confirm with you that the work here and release 
notes look good and can be wrapped up so that I can have @ymandel submit!


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D112491

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


[PATCH] D112491: Add `LambdaCapture`-related matchers.

2021-11-04 Thread James King via Phabricator via cfe-commits
jcking1034 marked an inline comment as done.
jcking1034 added a comment.

@fowles @aaron.ballman I'll take a look at `forEachCapture` in the next patch. 
Also, I've discovered that the `VarDecl` node has a member function 
`isInitCapture` that seems like it could allow us to distinguish between 
captures with and without initializers (link 
)
 - I want to play around with that, as well.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D112491

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


[PATCH] D112491: Add `LambdaCapture`-related matchers.

2021-11-04 Thread James King via Phabricator via cfe-commits
jcking1034 marked an inline comment as done.
jcking1034 added inline comments.



Comment at: clang/docs/ReleaseNotes.rst:223-229
+- ``LambdaCapture`` AST Matchers are now available. These matchers allow for
+  the binding of ``LambdaCapture`` nodes, and include the ``lambdaCapture``,
+  ``capturesVar``, and ``capturesThis`` matchers. In addition, the
+  ``hasAnyCapture`` matcher has been updated to accept an inner matcher of
+  type ``Matcher`` - its original interface accepted an inner
+  matcher of type ``Matcher`` or ``Matcher``, but did
+  not allow for the binding of ``LambdaCapture`` nodes.

aaron.ballman wrote:
> We should have an additional note about the removal of the old matchers.
I believe that the only change made to the old matchers is that `hasAnyCapture` 
now accepts an inner matcher of type `Matcher`, and no longer 
accepts inner matchers of type `Matcher` or `Matcher`. 
I've revised this note and broken it up into two points for clarity.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D112491

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


[PATCH] D112491: Add `LambdaCapture`-related matchers.

2021-11-04 Thread James King via Phabricator via cfe-commits
jcking1034 updated this revision to Diff 384835.
jcking1034 added a comment.

Update release notes.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D112491

Files:
  clang/docs/LibASTMatchersReference.html
  clang/docs/ReleaseNotes.rst
  clang/include/clang/AST/ASTTypeTraits.h
  clang/include/clang/ASTMatchers/ASTMatchers.h
  clang/lib/AST/ASTTypeTraits.cpp
  clang/lib/ASTMatchers/Dynamic/Registry.cpp
  clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
  clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
  clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp

Index: clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
===
--- clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
+++ clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
@@ -563,26 +563,6 @@
   objcMessageExpr(hasReceiver(declRefExpr(to(varDecl(hasName("x";
 }
 
-TEST(Matcher, HasAnyCapture) {
-  auto HasCaptureX = lambdaExpr(hasAnyCapture(varDecl(hasName("x";
-  EXPECT_TRUE(matches("void f() { int x = 3; [x](){}; }", HasCaptureX));
-  EXPECT_TRUE(matches("void f() { int x = 3; [](){}; }", HasCaptureX));
-  EXPECT_TRUE(notMatches("void f() { [](){}; }", HasCaptureX));
-  EXPECT_TRUE(notMatches("void f() { int z = 3; [](){}; }", HasCaptureX));
-  EXPECT_TRUE(
-  notMatches("struct a { void f() { [this](){}; }; };", HasCaptureX));
-}
-
-TEST(Matcher, CapturesThis) {
-  auto HasCaptureThis = lambdaExpr(hasAnyCapture(cxxThisExpr()));
-  EXPECT_TRUE(
-  matches("struct a { void f() { [this](){}; }; };", HasCaptureThis));
-  EXPECT_TRUE(notMatches("void f() { [](){}; }", HasCaptureThis));
-  EXPECT_TRUE(notMatches("void f() { int x = 3; [x](){}; }", HasCaptureThis));
-  EXPECT_TRUE(notMatches("void f() { int x = 3; [](){}; }", HasCaptureThis));
-  EXPECT_TRUE(notMatches("void f() { int z = 3; [](){}; }", HasCaptureThis));
-}
-
 TEST(Matcher, MatchesMethodsOnLambda) {
   StringRef Code = R"cpp(
 struct A {
Index: clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
===
--- clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
+++ clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
@@ -2237,6 +2237,65 @@
  varDecl(hasName("ss"), hasTypeLoc(elaboratedTypeLoc();
 }
 
+TEST_P(ASTMatchersTest, LambdaCaptureTest) {
+  if (!GetParam().isCXX11OrLater()) {
+return;
+  }
+  EXPECT_TRUE(matches("int main() { int cc; auto f = [cc](){ return cc; }; }",
+  lambdaExpr(hasAnyCapture(lambdaCapture();
+}
+
+TEST_P(ASTMatchersTest, LambdaCaptureTest_BindsToCaptureOfVarDecl) {
+  if (!GetParam().isCXX11OrLater()) {
+return;
+  }
+  auto matcher = lambdaExpr(
+  hasAnyCapture(lambdaCapture(capturesVar(varDecl(hasName("cc"));
+  EXPECT_TRUE(matches("int main() { int cc; auto f = [cc](){ return cc; }; }",
+  matcher));
+  EXPECT_TRUE(matches("int main() { int cc; auto f = [](){ return cc; }; }",
+  matcher));
+  EXPECT_TRUE(
+  matches("int main() { int cc; auto f = [=](){ return cc; }; }", matcher));
+  EXPECT_TRUE(
+  matches("int main() { int cc; auto f = [&](){ return cc; }; }", matcher));
+}
+
+TEST_P(ASTMatchersTest, LambdaCaptureTest_BindsToCaptureWithInitializer) {
+  if (!GetParam().isCXX14OrLater()) {
+return;
+  }
+  auto matcher = lambdaExpr(hasAnyCapture(lambdaCapture(capturesVar(
+  varDecl(hasName("cc"), hasInitializer(integerLiteral(equals(1;
+  EXPECT_TRUE(
+  matches("int main() { auto lambda = [cc = 1] {return cc;}; }", matcher));
+  EXPECT_TRUE(
+  matches("int main() { int cc = 2; auto lambda = [cc = 1] {return cc;}; }",
+  matcher));
+}
+
+TEST_P(ASTMatchersTest, LambdaCaptureTest_DoesNotBindToCaptureOfVarDecl) {
+  if (!GetParam().isCXX11OrLater()) {
+return;
+  }
+  auto matcher = lambdaExpr(
+  hasAnyCapture(lambdaCapture(capturesVar(varDecl(hasName("cc"));
+  EXPECT_FALSE(matches("int main() { auto f = [](){ return 5; }; }", matcher));
+  EXPECT_FALSE(matches("int main() { int xx; auto f = [xx](){ return xx; }; }",
+   matcher));
+}
+
+TEST_P(ASTMatchersTest,
+   LambdaCaptureTest_DoesNotBindToCaptureWithInitializerAndDifferentName) {
+  if (!GetParam().isCXX14OrLater()) {
+return;
+  }
+  EXPECT_FALSE(matches(
+  "int main() { auto lambda = [xx = 1] {return xx;}; }",
+  lambdaExpr(hasAnyCapture(lambdaCapture(capturesVar(varDecl(
+  hasName("cc"), hasInitializer(integerLiteral(equals(1));
+}
+
 TEST(ASTMatchersTestObjC, ObjCMessageExpr) {
   // Don't find ObjCMessageExpr where none are present.
   EXPECT_TRUE(notMatchesObjC("", objcMessageExpr(anything(;
Index: clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
===

[PATCH] D112491: Add `LambdaCapture`-related matchers.

2021-11-03 Thread James King via Phabricator via cfe-commits
jcking1034 updated this revision to Diff 384578.
jcking1034 added a comment.

Rebase onto main.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D112491

Files:
  clang/docs/LibASTMatchersReference.html
  clang/docs/ReleaseNotes.rst
  clang/include/clang/AST/ASTTypeTraits.h
  clang/include/clang/ASTMatchers/ASTMatchers.h
  clang/lib/AST/ASTTypeTraits.cpp
  clang/lib/ASTMatchers/Dynamic/Registry.cpp
  clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
  clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
  clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp

Index: clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
===
--- clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
+++ clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
@@ -563,26 +563,6 @@
   objcMessageExpr(hasReceiver(declRefExpr(to(varDecl(hasName("x";
 }
 
-TEST(Matcher, HasAnyCapture) {
-  auto HasCaptureX = lambdaExpr(hasAnyCapture(varDecl(hasName("x";
-  EXPECT_TRUE(matches("void f() { int x = 3; [x](){}; }", HasCaptureX));
-  EXPECT_TRUE(matches("void f() { int x = 3; [](){}; }", HasCaptureX));
-  EXPECT_TRUE(notMatches("void f() { [](){}; }", HasCaptureX));
-  EXPECT_TRUE(notMatches("void f() { int z = 3; [](){}; }", HasCaptureX));
-  EXPECT_TRUE(
-  notMatches("struct a { void f() { [this](){}; }; };", HasCaptureX));
-}
-
-TEST(Matcher, CapturesThis) {
-  auto HasCaptureThis = lambdaExpr(hasAnyCapture(cxxThisExpr()));
-  EXPECT_TRUE(
-  matches("struct a { void f() { [this](){}; }; };", HasCaptureThis));
-  EXPECT_TRUE(notMatches("void f() { [](){}; }", HasCaptureThis));
-  EXPECT_TRUE(notMatches("void f() { int x = 3; [x](){}; }", HasCaptureThis));
-  EXPECT_TRUE(notMatches("void f() { int x = 3; [](){}; }", HasCaptureThis));
-  EXPECT_TRUE(notMatches("void f() { int z = 3; [](){}; }", HasCaptureThis));
-}
-
 TEST(Matcher, MatchesMethodsOnLambda) {
   StringRef Code = R"cpp(
 struct A {
Index: clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
===
--- clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
+++ clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
@@ -2237,6 +2237,65 @@
  varDecl(hasName("ss"), hasTypeLoc(elaboratedTypeLoc();
 }
 
+TEST_P(ASTMatchersTest, LambdaCaptureTest) {
+  if (!GetParam().isCXX11OrLater()) {
+return;
+  }
+  EXPECT_TRUE(matches("int main() { int cc; auto f = [cc](){ return cc; }; }",
+  lambdaExpr(hasAnyCapture(lambdaCapture();
+}
+
+TEST_P(ASTMatchersTest, LambdaCaptureTest_BindsToCaptureOfVarDecl) {
+  if (!GetParam().isCXX11OrLater()) {
+return;
+  }
+  auto matcher = lambdaExpr(
+  hasAnyCapture(lambdaCapture(capturesVar(varDecl(hasName("cc"));
+  EXPECT_TRUE(matches("int main() { int cc; auto f = [cc](){ return cc; }; }",
+  matcher));
+  EXPECT_TRUE(matches("int main() { int cc; auto f = [](){ return cc; }; }",
+  matcher));
+  EXPECT_TRUE(
+  matches("int main() { int cc; auto f = [=](){ return cc; }; }", matcher));
+  EXPECT_TRUE(
+  matches("int main() { int cc; auto f = [&](){ return cc; }; }", matcher));
+}
+
+TEST_P(ASTMatchersTest, LambdaCaptureTest_BindsToCaptureWithInitializer) {
+  if (!GetParam().isCXX14OrLater()) {
+return;
+  }
+  auto matcher = lambdaExpr(hasAnyCapture(lambdaCapture(capturesVar(
+  varDecl(hasName("cc"), hasInitializer(integerLiteral(equals(1;
+  EXPECT_TRUE(
+  matches("int main() { auto lambda = [cc = 1] {return cc;}; }", matcher));
+  EXPECT_TRUE(
+  matches("int main() { int cc = 2; auto lambda = [cc = 1] {return cc;}; }",
+  matcher));
+}
+
+TEST_P(ASTMatchersTest, LambdaCaptureTest_DoesNotBindToCaptureOfVarDecl) {
+  if (!GetParam().isCXX11OrLater()) {
+return;
+  }
+  auto matcher = lambdaExpr(
+  hasAnyCapture(lambdaCapture(capturesVar(varDecl(hasName("cc"));
+  EXPECT_FALSE(matches("int main() { auto f = [](){ return 5; }; }", matcher));
+  EXPECT_FALSE(matches("int main() { int xx; auto f = [xx](){ return xx; }; }",
+   matcher));
+}
+
+TEST_P(ASTMatchersTest,
+   LambdaCaptureTest_DoesNotBindToCaptureWithInitializerAndDifferentName) {
+  if (!GetParam().isCXX14OrLater()) {
+return;
+  }
+  EXPECT_FALSE(matches(
+  "int main() { auto lambda = [xx = 1] {return xx;}; }",
+  lambdaExpr(hasAnyCapture(lambdaCapture(capturesVar(varDecl(
+  hasName("cc"), hasInitializer(integerLiteral(equals(1));
+}
+
 TEST(ASTMatchersTestObjC, ObjCMessageExpr) {
   // Don't find ObjCMessageExpr where none are present.
   EXPECT_TRUE(notMatchesObjC("", objcMessageExpr(anything(;
Index: clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
===
--- 

[PATCH] D112491: Add `LambdaCapture`-related matchers.

2021-11-02 Thread James King via Phabricator via cfe-commits
jcking1034 updated this revision to Diff 384114.
jcking1034 added a comment.

Update documentation for `capturesVar` matcher.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D112491

Files:
  clang/docs/LibASTMatchersReference.html
  clang/docs/ReleaseNotes.rst
  clang/include/clang/AST/ASTTypeTraits.h
  clang/include/clang/ASTMatchers/ASTMatchers.h
  clang/lib/AST/ASTTypeTraits.cpp
  clang/lib/ASTMatchers/Dynamic/Registry.cpp
  clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
  clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
  clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp

Index: clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
===
--- clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
+++ clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
@@ -563,26 +563,6 @@
   objcMessageExpr(hasReceiver(declRefExpr(to(varDecl(hasName("x";
 }
 
-TEST(Matcher, HasAnyCapture) {
-  auto HasCaptureX = lambdaExpr(hasAnyCapture(varDecl(hasName("x";
-  EXPECT_TRUE(matches("void f() { int x = 3; [x](){}; }", HasCaptureX));
-  EXPECT_TRUE(matches("void f() { int x = 3; [](){}; }", HasCaptureX));
-  EXPECT_TRUE(notMatches("void f() { [](){}; }", HasCaptureX));
-  EXPECT_TRUE(notMatches("void f() { int z = 3; [](){}; }", HasCaptureX));
-  EXPECT_TRUE(
-  notMatches("struct a { void f() { [this](){}; }; };", HasCaptureX));
-}
-
-TEST(Matcher, CapturesThis) {
-  auto HasCaptureThis = lambdaExpr(hasAnyCapture(cxxThisExpr()));
-  EXPECT_TRUE(
-  matches("struct a { void f() { [this](){}; }; };", HasCaptureThis));
-  EXPECT_TRUE(notMatches("void f() { [](){}; }", HasCaptureThis));
-  EXPECT_TRUE(notMatches("void f() { int x = 3; [x](){}; }", HasCaptureThis));
-  EXPECT_TRUE(notMatches("void f() { int x = 3; [](){}; }", HasCaptureThis));
-  EXPECT_TRUE(notMatches("void f() { int z = 3; [](){}; }", HasCaptureThis));
-}
-
 TEST(Matcher, MatchesMethodsOnLambda) {
   StringRef Code = R"cpp(
 struct A {
Index: clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
===
--- clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
+++ clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
@@ -2237,6 +2237,65 @@
  varDecl(hasName("ss"), hasTypeLoc(elaboratedTypeLoc();
 }
 
+TEST_P(ASTMatchersTest, LambdaCaptureTest) {
+  if (!GetParam().isCXX11OrLater()) {
+return;
+  }
+  EXPECT_TRUE(matches("int main() { int cc; auto f = [cc](){ return cc; }; }",
+  lambdaExpr(hasAnyCapture(lambdaCapture();
+}
+
+TEST_P(ASTMatchersTest, LambdaCaptureTest_BindsToCaptureOfVarDecl) {
+  if (!GetParam().isCXX11OrLater()) {
+return;
+  }
+  auto matcher = lambdaExpr(
+  hasAnyCapture(lambdaCapture(capturesVar(varDecl(hasName("cc"));
+  EXPECT_TRUE(matches("int main() { int cc; auto f = [cc](){ return cc; }; }",
+  matcher));
+  EXPECT_TRUE(matches("int main() { int cc; auto f = [](){ return cc; }; }",
+  matcher));
+  EXPECT_TRUE(
+  matches("int main() { int cc; auto f = [=](){ return cc; }; }", matcher));
+  EXPECT_TRUE(
+  matches("int main() { int cc; auto f = [&](){ return cc; }; }", matcher));
+}
+
+TEST_P(ASTMatchersTest, LambdaCaptureTest_BindsToCaptureWithInitializer) {
+  if (!GetParam().isCXX14OrLater()) {
+return;
+  }
+  auto matcher = lambdaExpr(hasAnyCapture(lambdaCapture(capturesVar(
+  varDecl(hasName("cc"), hasInitializer(integerLiteral(equals(1;
+  EXPECT_TRUE(
+  matches("int main() { auto lambda = [cc = 1] {return cc;}; }", matcher));
+  EXPECT_TRUE(
+  matches("int main() { int cc = 2; auto lambda = [cc = 1] {return cc;}; }",
+  matcher));
+}
+
+TEST_P(ASTMatchersTest, LambdaCaptureTest_DoesNotBindToCaptureOfVarDecl) {
+  if (!GetParam().isCXX11OrLater()) {
+return;
+  }
+  auto matcher = lambdaExpr(
+  hasAnyCapture(lambdaCapture(capturesVar(varDecl(hasName("cc"));
+  EXPECT_FALSE(matches("int main() { auto f = [](){ return 5; }; }", matcher));
+  EXPECT_FALSE(matches("int main() { int xx; auto f = [xx](){ return xx; }; }",
+   matcher));
+}
+
+TEST_P(ASTMatchersTest,
+   LambdaCaptureTest_DoesNotBindToCaptureWithInitializerAndDifferentName) {
+  if (!GetParam().isCXX14OrLater()) {
+return;
+  }
+  EXPECT_FALSE(matches(
+  "int main() { auto lambda = [xx = 1] {return xx;}; }",
+  lambdaExpr(hasAnyCapture(lambdaCapture(capturesVar(varDecl(
+  hasName("cc"), hasInitializer(integerLiteral(equals(1));
+}
+
 TEST(ASTMatchersTestObjC, ObjCMessageExpr) {
   // Don't find ObjCMessageExpr where none are present.
   EXPECT_TRUE(notMatchesObjC("", objcMessageExpr(anything(;
Index: clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp

[PATCH] D112491: Add `LambdaCapture`-related matchers.

2021-11-01 Thread James King via Phabricator via cfe-commits
jcking1034 updated this revision to Diff 383823.
jcking1034 marked 4 inline comments as done.
jcking1034 added a comment.

Update missed names; remove original implementations of `hasAnyCapture`.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D112491

Files:
  clang/docs/LibASTMatchersReference.html
  clang/docs/ReleaseNotes.rst
  clang/include/clang/AST/ASTTypeTraits.h
  clang/include/clang/ASTMatchers/ASTMatchers.h
  clang/lib/AST/ASTTypeTraits.cpp
  clang/lib/ASTMatchers/Dynamic/Registry.cpp
  clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
  clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
  clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp

Index: clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
===
--- clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
+++ clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
@@ -563,26 +563,6 @@
   objcMessageExpr(hasReceiver(declRefExpr(to(varDecl(hasName("x";
 }
 
-TEST(Matcher, HasAnyCapture) {
-  auto HasCaptureX = lambdaExpr(hasAnyCapture(varDecl(hasName("x";
-  EXPECT_TRUE(matches("void f() { int x = 3; [x](){}; }", HasCaptureX));
-  EXPECT_TRUE(matches("void f() { int x = 3; [](){}; }", HasCaptureX));
-  EXPECT_TRUE(notMatches("void f() { [](){}; }", HasCaptureX));
-  EXPECT_TRUE(notMatches("void f() { int z = 3; [](){}; }", HasCaptureX));
-  EXPECT_TRUE(
-  notMatches("struct a { void f() { [this](){}; }; };", HasCaptureX));
-}
-
-TEST(Matcher, CapturesThis) {
-  auto HasCaptureThis = lambdaExpr(hasAnyCapture(cxxThisExpr()));
-  EXPECT_TRUE(
-  matches("struct a { void f() { [this](){}; }; };", HasCaptureThis));
-  EXPECT_TRUE(notMatches("void f() { [](){}; }", HasCaptureThis));
-  EXPECT_TRUE(notMatches("void f() { int x = 3; [x](){}; }", HasCaptureThis));
-  EXPECT_TRUE(notMatches("void f() { int x = 3; [](){}; }", HasCaptureThis));
-  EXPECT_TRUE(notMatches("void f() { int z = 3; [](){}; }", HasCaptureThis));
-}
-
 TEST(Matcher, MatchesMethodsOnLambda) {
   StringRef Code = R"cpp(
 struct A {
Index: clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
===
--- clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
+++ clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
@@ -2237,6 +2237,65 @@
  varDecl(hasName("ss"), hasTypeLoc(elaboratedTypeLoc();
 }
 
+TEST_P(ASTMatchersTest, LambdaCaptureTest) {
+  if (!GetParam().isCXX11OrLater()) {
+return;
+  }
+  EXPECT_TRUE(matches("int main() { int cc; auto f = [cc](){ return cc; }; }",
+  lambdaExpr(hasAnyCapture(lambdaCapture();
+}
+
+TEST_P(ASTMatchersTest, LambdaCaptureTest_BindsToCaptureOfVarDecl) {
+  if (!GetParam().isCXX11OrLater()) {
+return;
+  }
+  auto matcher = lambdaExpr(
+  hasAnyCapture(lambdaCapture(capturesVar(varDecl(hasName("cc"));
+  EXPECT_TRUE(matches("int main() { int cc; auto f = [cc](){ return cc; }; }",
+  matcher));
+  EXPECT_TRUE(matches("int main() { int cc; auto f = [](){ return cc; }; }",
+  matcher));
+  EXPECT_TRUE(
+  matches("int main() { int cc; auto f = [=](){ return cc; }; }", matcher));
+  EXPECT_TRUE(
+  matches("int main() { int cc; auto f = [&](){ return cc; }; }", matcher));
+}
+
+TEST_P(ASTMatchersTest, LambdaCaptureTest_BindsToCaptureWithInitializer) {
+  if (!GetParam().isCXX14OrLater()) {
+return;
+  }
+  auto matcher = lambdaExpr(hasAnyCapture(lambdaCapture(capturesVar(
+  varDecl(hasName("cc"), hasInitializer(integerLiteral(equals(1;
+  EXPECT_TRUE(
+  matches("int main() { auto lambda = [cc = 1] {return cc;}; }", matcher));
+  EXPECT_TRUE(
+  matches("int main() { int cc = 2; auto lambda = [cc = 1] {return cc;}; }",
+  matcher));
+}
+
+TEST_P(ASTMatchersTest, LambdaCaptureTest_DoesNotBindToCaptureOfVarDecl) {
+  if (!GetParam().isCXX11OrLater()) {
+return;
+  }
+  auto matcher = lambdaExpr(
+  hasAnyCapture(lambdaCapture(capturesVar(varDecl(hasName("cc"));
+  EXPECT_FALSE(matches("int main() { auto f = [](){ return 5; }; }", matcher));
+  EXPECT_FALSE(matches("int main() { int xx; auto f = [xx](){ return xx; }; }",
+   matcher));
+}
+
+TEST_P(ASTMatchersTest,
+   LambdaCaptureTest_DoesNotBindToCaptureWithInitializerAndDifferentName) {
+  if (!GetParam().isCXX14OrLater()) {
+return;
+  }
+  EXPECT_FALSE(matches(
+  "int main() { auto lambda = [xx = 1] {return xx;}; }",
+  lambdaExpr(hasAnyCapture(lambdaCapture(capturesVar(varDecl(
+  hasName("cc"), hasInitializer(integerLiteral(equals(1));
+}
+
 TEST(ASTMatchersTestObjC, ObjCMessageExpr) {
   // Don't find ObjCMessageExpr where none are present.
   EXPECT_TRUE(notMatchesObjC("", objcMessageExpr(anything(;
Index: 

[PATCH] D112491: Add `LambdaCapture`-related matchers.

2021-10-29 Thread James King via Phabricator via cfe-commits
jcking1034 added inline comments.



Comment at: clang/include/clang/ASTMatchers/ASTMatchers.h:4652
+///   matches `[this]() { return cc; }`.
+AST_MATCHER(LambdaCapture, refersToThis) { return Node.capturesThis(); }
+

sammccall wrote:
> Again, why `refersToThis` rather than `capturesThis`, which is more specific 
> and matches the AST?
Initially, I think I saw that there were a few `TemplateArgument` matchers of 
the form `refersToX`, so I wanted to maintain some consistency with that. But I 
think I your suggestion makes things clearer, so will opt for that.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D112491

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


[PATCH] D112491: Add `LambdaCapture`-related matchers.

2021-10-29 Thread James King via Phabricator via cfe-commits
jcking1034 updated this revision to Diff 383458.
jcking1034 marked 2 inline comments as done.
jcking1034 added a comment.

Update matcher names for clarity.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D112491

Files:
  clang/docs/LibASTMatchersReference.html
  clang/include/clang/AST/ASTTypeTraits.h
  clang/include/clang/ASTMatchers/ASTMatchers.h
  clang/lib/AST/ASTTypeTraits.cpp
  clang/lib/ASTMatchers/Dynamic/Registry.cpp
  clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
  clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp

Index: clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
===
--- clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
+++ clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
@@ -2237,6 +2237,66 @@
  varDecl(hasName("ss"), hasTypeLoc(elaboratedTypeLoc();
 }
 
+TEST_P(ASTMatchersTest, LambdaCaptureTest) {
+  if (!GetParam().isCXX11OrLater()) {
+return;
+  }
+  EXPECT_TRUE(matches("int main() { int cc; auto f = [cc](){ return cc; }; }",
+  lambdaExpr(hasAnyCapture(lambdaCapture();
+}
+
+TEST_P(ASTMatchersTest, LambdaCaptureTest_BindsToCaptureReferringToVarDecl) {
+  if (!GetParam().isCXX11OrLater()) {
+return;
+  }
+  auto matcher = lambdaExpr(
+  hasAnyCapture(lambdaCapture(capturesVar(varDecl(hasName("cc"));
+  EXPECT_TRUE(matches("int main() { int cc; auto f = [cc](){ return cc; }; }",
+  matcher));
+  EXPECT_TRUE(matches("int main() { int cc; auto f = [](){ return cc; }; }",
+  matcher));
+  EXPECT_TRUE(
+  matches("int main() { int cc; auto f = [=](){ return cc; }; }", matcher));
+  EXPECT_TRUE(
+  matches("int main() { int cc; auto f = [&](){ return cc; }; }", matcher));
+}
+
+TEST_P(ASTMatchersTest, LambdaCaptureTest_BindsToCaptureWithInitializer) {
+  if (!GetParam().isCXX14OrLater()) {
+return;
+  }
+  auto matcher = lambdaExpr(hasAnyCapture(lambdaCapture(capturesVar(
+  varDecl(hasName("cc"), hasInitializer(integerLiteral(equals(1;
+  EXPECT_TRUE(
+  matches("int main() { auto lambda = [cc = 1] {return cc;}; }", matcher));
+  EXPECT_TRUE(
+  matches("int main() { int cc = 2; auto lambda = [cc = 1] {return cc;}; }",
+  matcher));
+}
+
+TEST_P(ASTMatchersTest,
+   LambdaCaptureTest_DoesNotBindToCaptureReferringToVarDecl) {
+  if (!GetParam().isCXX11OrLater()) {
+return;
+  }
+  auto matcher = lambdaExpr(
+  hasAnyCapture(lambdaCapture(capturesVar(varDecl(hasName("cc"));
+  EXPECT_FALSE(matches("int main() { auto f = [](){ return 5; }; }", matcher));
+  EXPECT_FALSE(matches("int main() { int xx; auto f = [xx](){ return xx; }; }",
+   matcher));
+}
+
+TEST_P(ASTMatchersTest,
+   LambdaCaptureTest_DoesNotBindToCaptureWithInitializerAndDifferentName) {
+  if (!GetParam().isCXX14OrLater()) {
+return;
+  }
+  EXPECT_FALSE(matches(
+  "int main() { auto lambda = [xx = 1] {return xx;}; }",
+  lambdaExpr(hasAnyCapture(lambdaCapture(capturesVar(varDecl(
+  hasName("cc"), hasInitializer(integerLiteral(equals(1));
+}
+
 TEST(ASTMatchersTestObjC, ObjCMessageExpr) {
   // Don't find ObjCMessageExpr where none are present.
   EXPECT_TRUE(notMatchesObjC("", objcMessageExpr(anything(;
Index: clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
===
--- clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
+++ clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
@@ -4445,5 +4445,42 @@
   cxxRecordDecl(hasName("Derived"),
 hasDirectBase(hasType(cxxRecordDecl(hasName("Base")));
 }
+
+TEST_P(ASTMatchersTest, RefersToThis) {
+  if (!GetParam().isCXX11OrLater()) {
+return;
+  }
+  auto matcher = lambdaExpr(hasAnyCapture(lambdaCapture(capturesThis(;
+  EXPECT_TRUE(matches("class C { int cc; int f() { auto l = [this](){ return "
+  "cc; }; return l(); } };",
+  matcher));
+  EXPECT_TRUE(matches("class C { int cc; int f() { auto l = [=](){ return cc; "
+  "}; return l(); } };",
+  matcher));
+  EXPECT_TRUE(matches("class C { int cc; int f() { auto l = [&](){ return cc; "
+  "}; return l(); } };",
+  matcher));
+  EXPECT_FALSE(matches("class C { int cc; int f() { auto l = [cc](){ return "
+   "cc; }; return l(); } };",
+   matcher));
+  EXPECT_FALSE(matches("class C { int this; int f() { auto l = [this](){ "
+   "return this; }; return l(); } };",
+   matcher));
+}
+
+TEST_P(ASTMatchersTest, IsImplicit_LambdaCapture) {
+  if (!GetParam().isCXX11OrLater()) {
+return;
+  }
+  auto matcher = lambdaExpr(hasAnyCapture(
+  

[PATCH] D112491: Add `LambdaCapture`-related matchers.

2021-10-28 Thread James King via Phabricator via cfe-commits
jcking1034 updated this revision to Diff 383128.
jcking1034 added a comment.

Regenerate documentation.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D112491

Files:
  clang/docs/LibASTMatchersReference.html
  clang/include/clang/AST/ASTTypeTraits.h
  clang/include/clang/ASTMatchers/ASTMatchers.h
  clang/lib/AST/ASTTypeTraits.cpp
  clang/lib/ASTMatchers/Dynamic/Registry.cpp
  clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
  clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp

Index: clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
===
--- clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
+++ clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
@@ -2237,6 +2237,66 @@
  varDecl(hasName("ss"), hasTypeLoc(elaboratedTypeLoc();
 }
 
+TEST_P(ASTMatchersTest, LambdaCaptureTest) {
+  if (!GetParam().isCXX11OrLater()) {
+return;
+  }
+  EXPECT_TRUE(matches("int main() { int cc; auto f = [cc](){ return cc; }; }",
+  lambdaExpr(hasAnyCapture(lambdaCapture();
+}
+
+TEST_P(ASTMatchersTest, LambdaCaptureTest_BindsToCaptureReferringToVarDecl) {
+  if (!GetParam().isCXX11OrLater()) {
+return;
+  }
+  auto matcher = lambdaExpr(
+  hasAnyCapture(lambdaCapture(refersToVarDecl(varDecl(hasName("cc"));
+  EXPECT_TRUE(matches("int main() { int cc; auto f = [cc](){ return cc; }; }",
+  matcher));
+  EXPECT_TRUE(matches("int main() { int cc; auto f = [](){ return cc; }; }",
+  matcher));
+  EXPECT_TRUE(
+  matches("int main() { int cc; auto f = [=](){ return cc; }; }", matcher));
+  EXPECT_TRUE(
+  matches("int main() { int cc; auto f = [&](){ return cc; }; }", matcher));
+}
+
+TEST_P(ASTMatchersTest, LambdaCaptureTest_BindsToCaptureWithInitializer) {
+  if (!GetParam().isCXX14OrLater()) {
+return;
+  }
+  auto matcher = lambdaExpr(hasAnyCapture(lambdaCapture(refersToVarDecl(
+  varDecl(hasName("cc"), hasInitializer(integerLiteral(equals(1;
+  EXPECT_TRUE(
+  matches("int main() { auto lambda = [cc = 1] {return cc;}; }", matcher));
+  EXPECT_TRUE(
+  matches("int main() { int cc = 2; auto lambda = [cc = 1] {return cc;}; }",
+  matcher));
+}
+
+TEST_P(ASTMatchersTest,
+   LambdaCaptureTest_DoesNotBindToCaptureReferringToVarDecl) {
+  if (!GetParam().isCXX11OrLater()) {
+return;
+  }
+  auto matcher = lambdaExpr(
+  hasAnyCapture(lambdaCapture(refersToVarDecl(varDecl(hasName("cc"));
+  EXPECT_FALSE(matches("int main() { auto f = [](){ return 5; }; }", matcher));
+  EXPECT_FALSE(matches("int main() { int xx; auto f = [xx](){ return xx; }; }",
+   matcher));
+}
+
+TEST_P(ASTMatchersTest,
+   LambdaCaptureTest_DoesNotBindToCaptureWithInitializerAndDifferentName) {
+  if (!GetParam().isCXX14OrLater()) {
+return;
+  }
+  EXPECT_FALSE(matches(
+  "int main() { auto lambda = [xx = 1] {return xx;}; }",
+  lambdaExpr(hasAnyCapture(lambdaCapture(refersToVarDecl(varDecl(
+  hasName("cc"), hasInitializer(integerLiteral(equals(1));
+}
+
 TEST(ASTMatchersTestObjC, ObjCMessageExpr) {
   // Don't find ObjCMessageExpr where none are present.
   EXPECT_TRUE(notMatchesObjC("", objcMessageExpr(anything(;
Index: clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
===
--- clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
+++ clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
@@ -4445,5 +4445,42 @@
   cxxRecordDecl(hasName("Derived"),
 hasDirectBase(hasType(cxxRecordDecl(hasName("Base")));
 }
+
+TEST_P(ASTMatchersTest, RefersToThis) {
+  if (!GetParam().isCXX11OrLater()) {
+return;
+  }
+  auto matcher = lambdaExpr(hasAnyCapture(lambdaCapture(refersToThis(;
+  EXPECT_TRUE(matches("class C { int cc; int f() { auto l = [this](){ return "
+  "cc; }; return l(); } };",
+  matcher));
+  EXPECT_TRUE(matches("class C { int cc; int f() { auto l = [=](){ return cc; "
+  "}; return l(); } };",
+  matcher));
+  EXPECT_TRUE(matches("class C { int cc; int f() { auto l = [&](){ return cc; "
+  "}; return l(); } };",
+  matcher));
+  EXPECT_FALSE(matches("class C { int cc; int f() { auto l = [cc](){ return "
+   "cc; }; return l(); } };",
+   matcher));
+  EXPECT_FALSE(matches("class C { int this; int f() { auto l = [this](){ "
+   "return this; }; return l(); } };",
+   matcher));
+}
+
+TEST_P(ASTMatchersTest, IsImplicit_LambdaCapture) {
+  if (!GetParam().isCXX11OrLater()) {
+return;
+  }
+  auto matcher = lambdaExpr(hasAnyCapture(
+  lambdaCapture(isImplicit(), 

[PATCH] D112491: Add `LambdaCapture`-related matchers.

2021-10-28 Thread James King via Phabricator via cfe-commits
jcking1034 updated this revision to Diff 383126.
jcking1034 added a comment.

Deprecate original overloads of `hasAnyCapture`.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D112491

Files:
  clang/docs/LibASTMatchersReference.html
  clang/include/clang/AST/ASTTypeTraits.h
  clang/include/clang/ASTMatchers/ASTMatchers.h
  clang/lib/AST/ASTTypeTraits.cpp
  clang/lib/ASTMatchers/Dynamic/Registry.cpp
  clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
  clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp

Index: clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
===
--- clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
+++ clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
@@ -2237,6 +2237,66 @@
  varDecl(hasName("ss"), hasTypeLoc(elaboratedTypeLoc();
 }
 
+TEST_P(ASTMatchersTest, LambdaCaptureTest) {
+  if (!GetParam().isCXX11OrLater()) {
+return;
+  }
+  EXPECT_TRUE(matches("int main() { int cc; auto f = [cc](){ return cc; }; }",
+  lambdaExpr(hasAnyCapture(lambdaCapture();
+}
+
+TEST_P(ASTMatchersTest, LambdaCaptureTest_BindsToCaptureReferringToVarDecl) {
+  if (!GetParam().isCXX11OrLater()) {
+return;
+  }
+  auto matcher = lambdaExpr(
+  hasAnyCapture(lambdaCapture(refersToVarDecl(varDecl(hasName("cc"));
+  EXPECT_TRUE(matches("int main() { int cc; auto f = [cc](){ return cc; }; }",
+  matcher));
+  EXPECT_TRUE(matches("int main() { int cc; auto f = [](){ return cc; }; }",
+  matcher));
+  EXPECT_TRUE(
+  matches("int main() { int cc; auto f = [=](){ return cc; }; }", matcher));
+  EXPECT_TRUE(
+  matches("int main() { int cc; auto f = [&](){ return cc; }; }", matcher));
+}
+
+TEST_P(ASTMatchersTest, LambdaCaptureTest_BindsToCaptureWithInitializer) {
+  if (!GetParam().isCXX14OrLater()) {
+return;
+  }
+  auto matcher = lambdaExpr(hasAnyCapture(lambdaCapture(refersToVarDecl(
+  varDecl(hasName("cc"), hasInitializer(integerLiteral(equals(1;
+  EXPECT_TRUE(
+  matches("int main() { auto lambda = [cc = 1] {return cc;}; }", matcher));
+  EXPECT_TRUE(
+  matches("int main() { int cc = 2; auto lambda = [cc = 1] {return cc;}; }",
+  matcher));
+}
+
+TEST_P(ASTMatchersTest,
+   LambdaCaptureTest_DoesNotBindToCaptureReferringToVarDecl) {
+  if (!GetParam().isCXX11OrLater()) {
+return;
+  }
+  auto matcher = lambdaExpr(
+  hasAnyCapture(lambdaCapture(refersToVarDecl(varDecl(hasName("cc"));
+  EXPECT_FALSE(matches("int main() { auto f = [](){ return 5; }; }", matcher));
+  EXPECT_FALSE(matches("int main() { int xx; auto f = [xx](){ return xx; }; }",
+   matcher));
+}
+
+TEST_P(ASTMatchersTest,
+   LambdaCaptureTest_DoesNotBindToCaptureWithInitializerAndDifferentName) {
+  if (!GetParam().isCXX14OrLater()) {
+return;
+  }
+  EXPECT_FALSE(matches(
+  "int main() { auto lambda = [xx = 1] {return xx;}; }",
+  lambdaExpr(hasAnyCapture(lambdaCapture(refersToVarDecl(varDecl(
+  hasName("cc"), hasInitializer(integerLiteral(equals(1));
+}
+
 TEST(ASTMatchersTestObjC, ObjCMessageExpr) {
   // Don't find ObjCMessageExpr where none are present.
   EXPECT_TRUE(notMatchesObjC("", objcMessageExpr(anything(;
Index: clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
===
--- clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
+++ clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
@@ -4445,5 +4445,42 @@
   cxxRecordDecl(hasName("Derived"),
 hasDirectBase(hasType(cxxRecordDecl(hasName("Base")));
 }
+
+TEST_P(ASTMatchersTest, RefersToThis) {
+  if (!GetParam().isCXX11OrLater()) {
+return;
+  }
+  auto matcher = lambdaExpr(hasAnyCapture(lambdaCapture(refersToThis(;
+  EXPECT_TRUE(matches("class C { int cc; int f() { auto l = [this](){ return "
+  "cc; }; return l(); } };",
+  matcher));
+  EXPECT_TRUE(matches("class C { int cc; int f() { auto l = [=](){ return cc; "
+  "}; return l(); } };",
+  matcher));
+  EXPECT_TRUE(matches("class C { int cc; int f() { auto l = [&](){ return cc; "
+  "}; return l(); } };",
+  matcher));
+  EXPECT_FALSE(matches("class C { int cc; int f() { auto l = [cc](){ return "
+   "cc; }; return l(); } };",
+   matcher));
+  EXPECT_FALSE(matches("class C { int this; int f() { auto l = [this](){ "
+   "return this; }; return l(); } };",
+   matcher));
+}
+
+TEST_P(ASTMatchersTest, IsImplicit_LambdaCapture) {
+  if (!GetParam().isCXX11OrLater()) {
+return;
+  }
+  auto matcher = lambdaExpr(hasAnyCapture(
+  

[PATCH] D112491: Add `LambdaCapture`-related matchers.

2021-10-28 Thread James King via Phabricator via cfe-commits
jcking1034 marked an inline comment as not done.
jcking1034 added a comment.

I agree that having two ways to match the same thing is a usability concern and 
could definitely be confusing. Deprecating non-bindable matchers could be a 
possibility and is probably the right way to go if we choose to include these 
matchers, but I'm not sure of if doing so will have any side effects.




Comment at: clang/include/clang/ASTMatchers/ASTMatchers.h:4629-4630
+///   matches `[x](){}`.
+AST_MATCHER_P(LambdaCapture, refersToVarDecl, internal::Matcher,
+  InnerMatcher) {
+  auto *capturedVar = Node.getCapturedVar();

aaron.ballman wrote:
> jcking1034 wrote:
> > ymandel wrote:
> > > aaron.ballman wrote:
> > > > The name here is a bit unclear -- whether it is the matcher matching 
> > > > `int x;` or the `x` from the capture is not clear from the name. The 
> > > > comment suggests it's matching `x` from the capture, but I think it's 
> > > > actually matching the `int x;` variable declaration.
> > > > 
> > > > Being clear on what's matched here is important when we think about 
> > > > initializers:
> > > > ```
> > > > void foo() {
> > > >   int x = 12;
> > > >   auto f = [x = 100](){};
> > > > }
> > > > ```
> > > > and
> > > > ```
> > > > lambdaExpr(hasAnyCapture(lambdaCapture(refersToVarDecl(hasName("x"), 
> > > > hasInitializer(integerLiteral(equals(100))
> > > > ```
> > > > Would you expect this to match? (This might be a good test case to add.)
> > > In a similar vein, do we want a separate matcher on the name of the 
> > > capture itself? e.g. an overload of `hasName`? And what about matchers 
> > > for the initializers?  Those don't have to land in this patch, but do you 
> > > think those would be doable?
> > I would expect @aaron.ballman's initializer example to match, and I added a 
> > similar test case to the one  described. I think that if a capture does not 
> > have an initializer, then `refersToVarDecl` will match on the variable 
> > declaration before the lambda. However, if a capture does have an 
> > initializer, that initializer itself seems to be represented as a `VarDecl` 
> > in the AST, which is the `VarDecl` that gets matched.
> > 
> > For that reason, I think we may not need to have a separate matcher on the 
> > name of the capture itself. Additionally, since captures with/without 
> > initializers are both represented the same way, there may not be a good way 
> > to distinguish between them, so matchers for initializers may not be 
> > possible.
> > I think that if a capture does not have an initializer, then 
> > refersToVarDecl will match on the variable declaration before the lambda. 
> > However, if a capture does have an initializer, that initializer itself 
> > seems to be represented as a VarDecl in the AST, which is the VarDecl that 
> > gets matched.
> 
> Oof, that'd be confusing! :-(
> 
> > For that reason, I think we may not need to have a separate matcher on the 
> > name of the capture itself.
> 
> Er, but there are init captures where you can introduce a whole new 
> declaration. I think we do want to be able to match on that, right? e.g.,
> ```
> [x = 12](){ return x; }();
> ```
> 
> > Additionally, since captures with/without initializers are both represented 
> > the same way, there may not be a good way to distinguish between them, so 
> > matchers for initializers may not be possible.
> 
> That's a bummer! :-( If this turns out to be a limitation, we should probably 
> document it as such.
For the example you've provided, these can be matched with the 
`refersToVarDecl` matcher, as seen in the test 
`LambdaCaptureTest_BindsToCaptureWithInitializer`. I've gone ahead and updated 
the documentation to include an example with an initializer.

Having that limitation with initializer representation is definitely a concern, 
though. Looking through the [[ 
https://clang.llvm.org/doxygen/LambdaCapture_8h_source.html | source ]] for the 
`LambdaCapture` class, the documentation for the `DeclAndBits` (line 42-48) 
suggests that there isn't a distinguishment between the two cases. However, do 
you think it's feasible to update the classes related to `LambdaCapture` obtain 
and store this information (possibly through updating the `LambdaCaptureKind` 
enum, updating the constructor/fields of the class, etc)?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D112491

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


[PATCH] D112491: Add `LambdaCapture`-related matchers.

2021-10-28 Thread James King via Phabricator via cfe-commits
jcking1034 updated this revision to Diff 383115.
jcking1034 added a comment.

Update comment with additional example.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D112491

Files:
  clang/docs/LibASTMatchersReference.html
  clang/include/clang/AST/ASTTypeTraits.h
  clang/include/clang/ASTMatchers/ASTMatchers.h
  clang/lib/AST/ASTTypeTraits.cpp
  clang/lib/ASTMatchers/Dynamic/Registry.cpp
  clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
  clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp

Index: clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
===
--- clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
+++ clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
@@ -2237,6 +2237,66 @@
  varDecl(hasName("ss"), hasTypeLoc(elaboratedTypeLoc();
 }
 
+TEST_P(ASTMatchersTest, LambdaCaptureTest) {
+  if (!GetParam().isCXX11OrLater()) {
+return;
+  }
+  EXPECT_TRUE(matches("int main() { int cc; auto f = [cc](){ return cc; }; }",
+  lambdaExpr(hasAnyCapture(lambdaCapture();
+}
+
+TEST_P(ASTMatchersTest, LambdaCaptureTest_BindsToCaptureReferringToVarDecl) {
+  if (!GetParam().isCXX11OrLater()) {
+return;
+  }
+  auto matcher = lambdaExpr(
+  hasAnyCapture(lambdaCapture(refersToVarDecl(varDecl(hasName("cc"));
+  EXPECT_TRUE(matches("int main() { int cc; auto f = [cc](){ return cc; }; }",
+  matcher));
+  EXPECT_TRUE(matches("int main() { int cc; auto f = [](){ return cc; }; }",
+  matcher));
+  EXPECT_TRUE(
+  matches("int main() { int cc; auto f = [=](){ return cc; }; }", matcher));
+  EXPECT_TRUE(
+  matches("int main() { int cc; auto f = [&](){ return cc; }; }", matcher));
+}
+
+TEST_P(ASTMatchersTest, LambdaCaptureTest_BindsToCaptureWithInitializer) {
+  if (!GetParam().isCXX14OrLater()) {
+return;
+  }
+  auto matcher = lambdaExpr(hasAnyCapture(lambdaCapture(refersToVarDecl(
+  varDecl(hasName("cc"), hasInitializer(integerLiteral(equals(1;
+  EXPECT_TRUE(
+  matches("int main() { auto lambda = [cc = 1] {return cc;}; }", matcher));
+  EXPECT_TRUE(
+  matches("int main() { int cc = 2; auto lambda = [cc = 1] {return cc;}; }",
+  matcher));
+}
+
+TEST_P(ASTMatchersTest,
+   LambdaCaptureTest_DoesNotBindToCaptureReferringToVarDecl) {
+  if (!GetParam().isCXX11OrLater()) {
+return;
+  }
+  auto matcher = lambdaExpr(
+  hasAnyCapture(lambdaCapture(refersToVarDecl(varDecl(hasName("cc"));
+  EXPECT_FALSE(matches("int main() { auto f = [](){ return 5; }; }", matcher));
+  EXPECT_FALSE(matches("int main() { int xx; auto f = [xx](){ return xx; }; }",
+   matcher));
+}
+
+TEST_P(ASTMatchersTest,
+   LambdaCaptureTest_DoesNotBindToCaptureWithInitializerAndDifferentName) {
+  if (!GetParam().isCXX14OrLater()) {
+return;
+  }
+  EXPECT_FALSE(matches(
+  "int main() { auto lambda = [xx = 1] {return xx;}; }",
+  lambdaExpr(hasAnyCapture(lambdaCapture(refersToVarDecl(varDecl(
+  hasName("cc"), hasInitializer(integerLiteral(equals(1));
+}
+
 TEST(ASTMatchersTestObjC, ObjCMessageExpr) {
   // Don't find ObjCMessageExpr where none are present.
   EXPECT_TRUE(notMatchesObjC("", objcMessageExpr(anything(;
Index: clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
===
--- clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
+++ clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
@@ -4445,5 +4445,42 @@
   cxxRecordDecl(hasName("Derived"),
 hasDirectBase(hasType(cxxRecordDecl(hasName("Base")));
 }
+
+TEST_P(ASTMatchersTest, RefersToThis) {
+  if (!GetParam().isCXX11OrLater()) {
+return;
+  }
+  auto matcher = lambdaExpr(hasAnyCapture(lambdaCapture(refersToThis(;
+  EXPECT_TRUE(matches("class C { int cc; int f() { auto l = [this](){ return "
+  "cc; }; return l(); } };",
+  matcher));
+  EXPECT_TRUE(matches("class C { int cc; int f() { auto l = [=](){ return cc; "
+  "}; return l(); } };",
+  matcher));
+  EXPECT_TRUE(matches("class C { int cc; int f() { auto l = [&](){ return cc; "
+  "}; return l(); } };",
+  matcher));
+  EXPECT_FALSE(matches("class C { int cc; int f() { auto l = [cc](){ return "
+   "cc; }; return l(); } };",
+   matcher));
+  EXPECT_FALSE(matches("class C { int this; int f() { auto l = [this](){ "
+   "return this; }; return l(); } };",
+   matcher));
+}
+
+TEST_P(ASTMatchersTest, IsImplicit_LambdaCapture) {
+  if (!GetParam().isCXX11OrLater()) {
+return;
+  }
+  auto matcher = lambdaExpr(hasAnyCapture(
+  

[PATCH] D112491: Add `LambdaCapture`-related matchers.

2021-10-26 Thread James King via Phabricator via cfe-commits
jcking1034 added a comment.

@aaron.ballman for the purpose of these matchers, what @ymandel said is correct 
- the goal is to allow `LambdaCapture`s themselves to be bindable.




Comment at: clang/include/clang/ASTMatchers/ASTMatchers.h:4629-4630
+///   matches `[x](){}`.
+AST_MATCHER_P(LambdaCapture, refersToVarDecl, internal::Matcher,
+  InnerMatcher) {
+  auto *capturedVar = Node.getCapturedVar();

ymandel wrote:
> aaron.ballman wrote:
> > The name here is a bit unclear -- whether it is the matcher matching `int 
> > x;` or the `x` from the capture is not clear from the name. The comment 
> > suggests it's matching `x` from the capture, but I think it's actually 
> > matching the `int x;` variable declaration.
> > 
> > Being clear on what's matched here is important when we think about 
> > initializers:
> > ```
> > void foo() {
> >   int x = 12;
> >   auto f = [x = 100](){};
> > }
> > ```
> > and
> > ```
> > lambdaExpr(hasAnyCapture(lambdaCapture(refersToVarDecl(hasName("x"), 
> > hasInitializer(integerLiteral(equals(100))
> > ```
> > Would you expect this to match? (This might be a good test case to add.)
> In a similar vein, do we want a separate matcher on the name of the capture 
> itself? e.g. an overload of `hasName`? And what about matchers for the 
> initializers?  Those don't have to land in this patch, but do you think those 
> would be doable?
I would expect @aaron.ballman's initializer example to match, and I added a 
similar test case to the one  described. I think that if a capture does not 
have an initializer, then `refersToVarDecl` will match on the variable 
declaration before the lambda. However, if a capture does have an initializer, 
that initializer itself seems to be represented as a `VarDecl` in the AST, 
which is the `VarDecl` that gets matched.

For that reason, I think we may not need to have a separate matcher on the name 
of the capture itself. Additionally, since captures with/without initializers 
are both represented the same way, there may not be a good way to distinguish 
between them, so matchers for initializers may not be possible.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D112491

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


[PATCH] D112491: Add `LambdaCapture`-related matchers.

2021-10-26 Thread James King via Phabricator via cfe-commits
jcking1034 updated this revision to Diff 382410.
jcking1034 added a comment.

Update comments and tests


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D112491

Files:
  clang/docs/LibASTMatchersReference.html
  clang/include/clang/AST/ASTTypeTraits.h
  clang/include/clang/ASTMatchers/ASTMatchers.h
  clang/lib/AST/ASTTypeTraits.cpp
  clang/lib/ASTMatchers/Dynamic/Registry.cpp
  clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
  clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp

Index: clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
===
--- clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
+++ clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
@@ -2237,6 +2237,66 @@
  varDecl(hasName("ss"), hasTypeLoc(elaboratedTypeLoc();
 }
 
+TEST_P(ASTMatchersTest, LambdaCaptureTest) {
+  if (!GetParam().isCXX11OrLater()) {
+return;
+  }
+  EXPECT_TRUE(matches("int main() { int cc; auto f = [cc](){ return cc; }; }",
+  lambdaExpr(hasAnyCapture(lambdaCapture();
+}
+
+TEST_P(ASTMatchersTest, LambdaCaptureTest_BindsToCaptureReferringToVarDecl) {
+  if (!GetParam().isCXX11OrLater()) {
+return;
+  }
+  auto matcher = lambdaExpr(
+  hasAnyCapture(lambdaCapture(refersToVarDecl(varDecl(hasName("cc"));
+  EXPECT_TRUE(matches("int main() { int cc; auto f = [cc](){ return cc; }; }",
+  matcher));
+  EXPECT_TRUE(matches("int main() { int cc; auto f = [](){ return cc; }; }",
+  matcher));
+  EXPECT_TRUE(
+  matches("int main() { int cc; auto f = [=](){ return cc; }; }", matcher));
+  EXPECT_TRUE(
+  matches("int main() { int cc; auto f = [&](){ return cc; }; }", matcher));
+}
+
+TEST_P(ASTMatchersTest, LambdaCaptureTest_BindsToCaptureWithInitializer) {
+  if (!GetParam().isCXX14OrLater()) {
+return;
+  }
+  auto matcher = lambdaExpr(hasAnyCapture(lambdaCapture(refersToVarDecl(
+  varDecl(hasName("cc"), hasInitializer(integerLiteral(equals(1;
+  EXPECT_TRUE(
+  matches("int main() { auto lambda = [cc = 1] {return cc;}; }", matcher));
+  EXPECT_TRUE(
+  matches("int main() { int cc = 2; auto lambda = [cc = 1] {return cc;}; }",
+  matcher));
+}
+
+TEST_P(ASTMatchersTest,
+   LambdaCaptureTest_DoesNotBindToCaptureReferringToVarDecl) {
+  if (!GetParam().isCXX11OrLater()) {
+return;
+  }
+  auto matcher = lambdaExpr(
+  hasAnyCapture(lambdaCapture(refersToVarDecl(varDecl(hasName("cc"));
+  EXPECT_FALSE(matches("int main() { auto f = [](){ return 5; }; }", matcher));
+  EXPECT_FALSE(matches("int main() { int xx; auto f = [xx](){ return xx; }; }",
+   matcher));
+}
+
+TEST_P(ASTMatchersTest,
+   LambdaCaptureTest_DoesNotBindToCaptureWithInitializerAndDifferentName) {
+  if (!GetParam().isCXX14OrLater()) {
+return;
+  }
+  EXPECT_FALSE(matches(
+  "int main() { auto lambda = [xx = 1] {return xx;}; }",
+  lambdaExpr(hasAnyCapture(lambdaCapture(refersToVarDecl(varDecl(
+  hasName("cc"), hasInitializer(integerLiteral(equals(1));
+}
+
 TEST(ASTMatchersTestObjC, ObjCMessageExpr) {
   // Don't find ObjCMessageExpr where none are present.
   EXPECT_TRUE(notMatchesObjC("", objcMessageExpr(anything(;
Index: clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
===
--- clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
+++ clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
@@ -4445,5 +4445,42 @@
   cxxRecordDecl(hasName("Derived"),
 hasDirectBase(hasType(cxxRecordDecl(hasName("Base")));
 }
+
+TEST_P(ASTMatchersTest, RefersToThis) {
+  if (!GetParam().isCXX11OrLater()) {
+return;
+  }
+  auto matcher = lambdaExpr(hasAnyCapture(lambdaCapture(refersToThis(;
+  EXPECT_TRUE(matches("class C { int cc; int f() { auto l = [this](){ return "
+  "cc; }; return l(); } };",
+  matcher));
+  EXPECT_TRUE(matches("class C { int cc; int f() { auto l = [=](){ return cc; "
+  "}; return l(); } };",
+  matcher));
+  EXPECT_TRUE(matches("class C { int cc; int f() { auto l = [&](){ return cc; "
+  "}; return l(); } };",
+  matcher));
+  EXPECT_FALSE(matches("class C { int cc; int f() { auto l = [cc](){ return "
+   "cc; }; return l(); } };",
+   matcher));
+  EXPECT_FALSE(matches("class C { int this; int f() { auto l = [this](){ "
+   "return this; }; return l(); } };",
+   matcher));
+}
+
+TEST_P(ASTMatchersTest, IsImplicit_LambdaCapture) {
+  if (!GetParam().isCXX11OrLater()) {
+return;
+  }
+  auto matcher = lambdaExpr(hasAnyCapture(
+  lambdaCapture(isImplicit(), 

[PATCH] D112491: Add `LambdaCapture`-related matchers.

2021-10-26 Thread James King via Phabricator via cfe-commits
jcking1034 updated this revision to Diff 382397.
jcking1034 marked an inline comment as done.
jcking1034 added a comment.

Update comment with example


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D112491

Files:
  clang/docs/LibASTMatchersReference.html
  clang/include/clang/AST/ASTTypeTraits.h
  clang/include/clang/ASTMatchers/ASTMatchers.h
  clang/lib/AST/ASTTypeTraits.cpp
  clang/lib/ASTMatchers/Dynamic/Registry.cpp
  clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
  clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp

Index: clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
===
--- clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
+++ clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
@@ -2237,6 +2237,52 @@
  varDecl(hasName("ss"), hasTypeLoc(elaboratedTypeLoc();
 }
 
+TEST_P(ASTMatchersTest, LambdaCaptureTest) {
+  if (!GetParam().isCXX11OrLater()) {
+return;
+  }
+  EXPECT_TRUE(matches("int main() { int cc; auto f = [cc](){ return cc; }; }",
+  lambdaExpr(hasAnyCapture(lambdaCapture();
+}
+
+TEST_P(ASTMatchersTest, LambdaCaptureTest_BindsToCaptureReferringToVarDecl) {
+  if (!GetParam().isCXX11OrLater()) {
+return;
+  }
+  auto matcher = lambdaExpr(
+  hasAnyCapture(lambdaCapture(refersToVarDecl(varDecl(hasName("cc"));
+  EXPECT_TRUE(matches("int main() { int cc; auto f = [cc](){ return cc; }; }",
+  matcher));
+  EXPECT_TRUE(matches("int main() { int cc; auto f = [](){ return cc; }; }",
+  matcher));
+  EXPECT_TRUE(
+  matches("int main() { int cc; auto f = [=](){ return cc; }; }", matcher));
+  EXPECT_TRUE(
+  matches("int main() { int cc; auto f = [&](){ return cc; }; }", matcher));
+  if (!GetParam().isCXX14OrLater()) {
+return;
+  }
+  EXPECT_TRUE(
+  matches("int main() { auto lambda = [cc = 1] {return cc;}; }", matcher));
+}
+
+TEST_P(ASTMatchersTest,
+   LambdaCaptureTest_DoesNotBindToCaptureReferringToVarDecl) {
+  if (!GetParam().isCXX11OrLater()) {
+return;
+  }
+  auto matcher = lambdaExpr(
+  hasAnyCapture(lambdaCapture(refersToVarDecl(varDecl(hasName("cc"));
+  EXPECT_FALSE(matches("int main() { auto f = [](){ return 5; }; }", matcher));
+  EXPECT_FALSE(matches("int main() { int xx; auto f = [xx](){ return xx; }; }",
+   matcher));
+  if (!GetParam().isCXX14OrLater()) {
+return;
+  }
+  EXPECT_FALSE(
+  matches("int main() { auto lambda = [xx = 1] {return xx;}; }", matcher));
+}
+
 TEST(ASTMatchersTestObjC, ObjCMessageExpr) {
   // Don't find ObjCMessageExpr where none are present.
   EXPECT_TRUE(notMatchesObjC("", objcMessageExpr(anything(;
Index: clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
===
--- clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
+++ clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
@@ -4445,5 +4445,42 @@
   cxxRecordDecl(hasName("Derived"),
 hasDirectBase(hasType(cxxRecordDecl(hasName("Base")));
 }
+
+TEST_P(ASTMatchersTest, RefersToThis) {
+  if (!GetParam().isCXX11OrLater()) {
+return;
+  }
+  auto matcher = lambdaExpr(hasAnyCapture(lambdaCapture(refersToThis(;
+  EXPECT_TRUE(matches("class C { int cc; int f() { auto l = [this](){ return "
+  "cc; }; return l(); } };",
+  matcher));
+  EXPECT_TRUE(matches("class C { int cc; int f() { auto l = [=](){ return cc; "
+  "}; return l(); } };",
+  matcher));
+  EXPECT_TRUE(matches("class C { int cc; int f() { auto l = [&](){ return cc; "
+  "}; return l(); } };",
+  matcher));
+  EXPECT_FALSE(matches("class C { int cc; int f() { auto l = [cc](){ return "
+   "cc; }; return l(); } };",
+   matcher));
+  EXPECT_FALSE(matches("class C { int this; int f() { auto l = [this](){ "
+   "return this; }; return l(); } };",
+   matcher));
+}
+
+TEST_P(ASTMatchersTest, IsImplicit_LambdaCapture) {
+  if (!GetParam().isCXX11OrLater()) {
+return;
+  }
+  auto matcher = lambdaExpr(hasAnyCapture(
+  lambdaCapture(isImplicit(), refersToVarDecl(varDecl(hasName("cc"));
+  EXPECT_TRUE(
+  matches("int main() { int cc; auto f = [&](){ return cc; }; }", matcher));
+  EXPECT_TRUE(
+  matches("int main() { int cc; auto f = [=](){ return cc; }; }", matcher));
+  EXPECT_FALSE(matches("int main() { int cc; auto f = [cc](){ return cc; }; }",
+   matcher));
+}
+
 } // namespace ast_matchers
 } // namespace clang
Index: clang/lib/ASTMatchers/Dynamic/Registry.cpp
===
--- 

[PATCH] D112491: Add `LambdaCapture`-related matchers.

2021-10-26 Thread James King via Phabricator via cfe-commits
jcking1034 updated this revision to Diff 382391.
jcking1034 marked 3 inline comments as done.
jcking1034 added a comment.

Revert changes to ASTMatchFinder


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D112491

Files:
  clang/docs/LibASTMatchersReference.html
  clang/include/clang/AST/ASTTypeTraits.h
  clang/include/clang/ASTMatchers/ASTMatchers.h
  clang/lib/AST/ASTTypeTraits.cpp
  clang/lib/ASTMatchers/Dynamic/Registry.cpp
  clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
  clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp

Index: clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
===
--- clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
+++ clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
@@ -2237,6 +2237,52 @@
  varDecl(hasName("ss"), hasTypeLoc(elaboratedTypeLoc();
 }
 
+TEST_P(ASTMatchersTest, LambdaCaptureTest) {
+  if (!GetParam().isCXX11OrLater()) {
+return;
+  }
+  EXPECT_TRUE(matches("int main() { int cc; auto f = [cc](){ return cc; }; }",
+  lambdaExpr(hasAnyCapture(lambdaCapture();
+}
+
+TEST_P(ASTMatchersTest, LambdaCaptureTest_BindsToCaptureReferringToVarDecl) {
+  if (!GetParam().isCXX11OrLater()) {
+return;
+  }
+  auto matcher = lambdaExpr(
+  hasAnyCapture(lambdaCapture(refersToVarDecl(varDecl(hasName("cc"));
+  EXPECT_TRUE(matches("int main() { int cc; auto f = [cc](){ return cc; }; }",
+  matcher));
+  EXPECT_TRUE(matches("int main() { int cc; auto f = [](){ return cc; }; }",
+  matcher));
+  EXPECT_TRUE(
+  matches("int main() { int cc; auto f = [=](){ return cc; }; }", matcher));
+  EXPECT_TRUE(
+  matches("int main() { int cc; auto f = [&](){ return cc; }; }", matcher));
+  if (!GetParam().isCXX14OrLater()) {
+return;
+  }
+  EXPECT_TRUE(
+  matches("int main() { auto lambda = [cc = 1] {return cc;}; }", matcher));
+}
+
+TEST_P(ASTMatchersTest,
+   LambdaCaptureTest_DoesNotBindToCaptureReferringToVarDecl) {
+  if (!GetParam().isCXX11OrLater()) {
+return;
+  }
+  auto matcher = lambdaExpr(
+  hasAnyCapture(lambdaCapture(refersToVarDecl(varDecl(hasName("cc"));
+  EXPECT_FALSE(matches("int main() { auto f = [](){ return 5; }; }", matcher));
+  EXPECT_FALSE(matches("int main() { int xx; auto f = [xx](){ return xx; }; }",
+   matcher));
+  if (!GetParam().isCXX14OrLater()) {
+return;
+  }
+  EXPECT_FALSE(
+  matches("int main() { auto lambda = [xx = 1] {return xx;}; }", matcher));
+}
+
 TEST(ASTMatchersTestObjC, ObjCMessageExpr) {
   // Don't find ObjCMessageExpr where none are present.
   EXPECT_TRUE(notMatchesObjC("", objcMessageExpr(anything(;
Index: clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
===
--- clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
+++ clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
@@ -4445,5 +4445,42 @@
   cxxRecordDecl(hasName("Derived"),
 hasDirectBase(hasType(cxxRecordDecl(hasName("Base")));
 }
+
+TEST_P(ASTMatchersTest, RefersToThis) {
+  if (!GetParam().isCXX11OrLater()) {
+return;
+  }
+  auto matcher = lambdaExpr(hasAnyCapture(lambdaCapture(refersToThis(;
+  EXPECT_TRUE(matches("class C { int cc; int f() { auto l = [this](){ return "
+  "cc; }; return l(); } };",
+  matcher));
+  EXPECT_TRUE(matches("class C { int cc; int f() { auto l = [=](){ return cc; "
+  "}; return l(); } };",
+  matcher));
+  EXPECT_TRUE(matches("class C { int cc; int f() { auto l = [&](){ return cc; "
+  "}; return l(); } };",
+  matcher));
+  EXPECT_FALSE(matches("class C { int cc; int f() { auto l = [cc](){ return "
+   "cc; }; return l(); } };",
+   matcher));
+  EXPECT_FALSE(matches("class C { int this; int f() { auto l = [this](){ "
+   "return this; }; return l(); } };",
+   matcher));
+}
+
+TEST_P(ASTMatchersTest, IsImplicit_LambdaCapture) {
+  if (!GetParam().isCXX11OrLater()) {
+return;
+  }
+  auto matcher = lambdaExpr(hasAnyCapture(
+  lambdaCapture(isImplicit(), refersToVarDecl(varDecl(hasName("cc"));
+  EXPECT_TRUE(
+  matches("int main() { int cc; auto f = [&](){ return cc; }; }", matcher));
+  EXPECT_TRUE(
+  matches("int main() { int cc; auto f = [=](){ return cc; }; }", matcher));
+  EXPECT_FALSE(matches("int main() { int cc; auto f = [cc](){ return cc; }; }",
+   matcher));
+}
+
 } // namespace ast_matchers
 } // namespace clang
Index: clang/lib/ASTMatchers/Dynamic/Registry.cpp
===
--- 

[PATCH] D112491: Add `LambdaCapture`-related matchers.

2021-10-25 Thread James King via Phabricator via cfe-commits
jcking1034 created this revision.
jcking1034 added reviewers: ymandel, aaron.ballman.
jcking1034 requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

This provides better support for `LambdaCapture`s, and implements several
`LambdaCapture`-related matchers. This does not update how lambdas are
traversed. As a result, something like trying to match `lambdaCapture()` by
itself will not work - it must be used as an inner matcher.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D112491

Files:
  clang/docs/LibASTMatchersReference.html
  clang/include/clang/AST/ASTTypeTraits.h
  clang/include/clang/ASTMatchers/ASTMatchFinder.h
  clang/include/clang/ASTMatchers/ASTMatchers.h
  clang/lib/AST/ASTTypeTraits.cpp
  clang/lib/ASTMatchers/ASTMatchFinder.cpp
  clang/lib/ASTMatchers/Dynamic/Registry.cpp
  clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
  clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp

Index: clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
===
--- clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
+++ clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
@@ -2237,6 +2237,52 @@
  varDecl(hasName("ss"), hasTypeLoc(elaboratedTypeLoc();
 }
 
+TEST_P(ASTMatchersTest, LambdaCaptureTest) {
+  if (!GetParam().isCXX11OrLater()) {
+return;
+  }
+  EXPECT_TRUE(matches("int main() { int cc; auto f = [cc](){ return cc; }; }",
+  lambdaExpr(hasAnyCapture(lambdaCapture();
+}
+
+TEST_P(ASTMatchersTest, LambdaCaptureTest_BindsToCaptureReferringToVarDecl) {
+  if (!GetParam().isCXX11OrLater()) {
+return;
+  }
+  auto matcher = lambdaExpr(
+  hasAnyCapture(lambdaCapture(refersToVarDecl(varDecl(hasName("cc"));
+  EXPECT_TRUE(matches("int main() { int cc; auto f = [cc](){ return cc; }; }",
+  matcher));
+  EXPECT_TRUE(matches("int main() { int cc; auto f = [](){ return cc; }; }",
+  matcher));
+  EXPECT_TRUE(
+  matches("int main() { int cc; auto f = [=](){ return cc; }; }", matcher));
+  EXPECT_TRUE(
+  matches("int main() { int cc; auto f = [&](){ return cc; }; }", matcher));
+  if (!GetParam().isCXX14OrLater()) {
+return;
+  }
+  EXPECT_TRUE(
+  matches("int main() { auto lambda = [cc = 1] {return cc;}; }", matcher));
+}
+
+TEST_P(ASTMatchersTest,
+   LambdaCaptureTest_DoesNotBindToCaptureReferringToVarDecl) {
+  if (!GetParam().isCXX11OrLater()) {
+return;
+  }
+  auto matcher = lambdaExpr(
+  hasAnyCapture(lambdaCapture(refersToVarDecl(varDecl(hasName("cc"));
+  EXPECT_FALSE(matches("int main() { auto f = [](){ return 5; }; }", matcher));
+  EXPECT_FALSE(matches("int main() { int xx; auto f = [xx](){ return xx; }; }",
+   matcher));
+  if (!GetParam().isCXX14OrLater()) {
+return;
+  }
+  EXPECT_FALSE(
+  matches("int main() { auto lambda = [xx = 1] {return xx;}; }", matcher));
+}
+
 TEST(ASTMatchersTestObjC, ObjCMessageExpr) {
   // Don't find ObjCMessageExpr where none are present.
   EXPECT_TRUE(notMatchesObjC("", objcMessageExpr(anything(;
Index: clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
===
--- clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
+++ clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
@@ -4445,5 +4445,42 @@
   cxxRecordDecl(hasName("Derived"),
 hasDirectBase(hasType(cxxRecordDecl(hasName("Base")));
 }
+
+TEST_P(ASTMatchersTest, RefersToThis) {
+  if (!GetParam().isCXX11OrLater()) {
+return;
+  }
+  auto matcher = lambdaExpr(hasAnyCapture(lambdaCapture(refersToThis(;
+  EXPECT_TRUE(matches("class C { int cc; int f() { auto l = [this](){ return "
+  "cc; }; return l(); } };",
+  matcher));
+  EXPECT_TRUE(matches("class C { int cc; int f() { auto l = [=](){ return cc; "
+  "}; return l(); } };",
+  matcher));
+  EXPECT_TRUE(matches("class C { int cc; int f() { auto l = [&](){ return cc; "
+  "}; return l(); } };",
+  matcher));
+  EXPECT_FALSE(matches("class C { int cc; int f() { auto l = [cc](){ return "
+   "cc; }; return l(); } };",
+   matcher));
+  EXPECT_FALSE(matches("class C { int this; int f() { auto l = [this](){ "
+   "return this; }; return l(); } };",
+   matcher));
+}
+
+TEST_P(ASTMatchersTest, IsImplicit_LambdaCapture) {
+  if (!GetParam().isCXX11OrLater()) {
+return;
+  }
+  auto matcher = lambdaExpr(hasAnyCapture(
+  lambdaCapture(isImplicit(), refersToVarDecl(varDecl(hasName("cc"));
+  EXPECT_TRUE(
+  matches("int main() { int cc; auto f = [&](){ return cc; }; }", matcher));
+  EXPECT_TRUE(
+  matches("int main() { int cc; auto f = 

[PATCH] D111518: Add release note about `TypeLoc` matchers.

2021-10-10 Thread James King via Phabricator via cfe-commits
jcking1034 created this revision.
jcking1034 added reviewers: ymandel, aaron.ballman, tdl-g.
jcking1034 requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D111518

Files:
  clang/docs/ReleaseNotes.rst


Index: clang/docs/ReleaseNotes.rst
===
--- clang/docs/ReleaseNotes.rst
+++ clang/docs/ReleaseNotes.rst
@@ -183,7 +183,11 @@
 AST Matchers
 
 
-- ...
+- ``TypeLoc`` AST Matchers are now available. These matchers provide helpful
+  utilities for matching ``TypeLoc`` nodes, such as the ``pointerTypeLoc``
+  matcher or the ``hasReturnTypeLoc`` matcher. The addition of these matchers
+  was made possible by changes to the handling of ``TypeLoc`` nodes that
+  allows them to enjoy the same static type checking as other AST node kinds.
 
 clang-format
 


Index: clang/docs/ReleaseNotes.rst
===
--- clang/docs/ReleaseNotes.rst
+++ clang/docs/ReleaseNotes.rst
@@ -183,7 +183,11 @@
 AST Matchers
 
 
-- ...
+- ``TypeLoc`` AST Matchers are now available. These matchers provide helpful
+  utilities for matching ``TypeLoc`` nodes, such as the ``pointerTypeLoc``
+  matcher or the ``hasReturnTypeLoc`` matcher. The addition of these matchers
+  was made possible by changes to the handling of ``TypeLoc`` nodes that
+  allows them to enjoy the same static type checking as other AST node kinds.
 
 clang-format
 
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D111242: Add `TypeLoc`-related matchers.

2021-10-08 Thread James King via Phabricator via cfe-commits
jcking1034 added a comment.

@aaron.ballman that sounds like a good idea, what's the process for adding a 
release note?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D111242

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


[PATCH] D111242: Add `TypeLoc`-related matchers.

2021-10-08 Thread James King via Phabricator via cfe-commits
jcking1034 updated this revision to Diff 378298.
jcking1034 added a comment.

Rebase onto master


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D111242

Files:
  clang/docs/LibASTMatchersReference.html
  clang/include/clang/ASTMatchers/ASTMatchers.h
  clang/include/clang/ASTMatchers/ASTMatchersInternal.h
  clang/lib/ASTMatchers/ASTMatchersInternal.cpp
  clang/lib/ASTMatchers/Dynamic/Registry.cpp
  clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
  clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp

Index: clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
===
--- clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
+++ clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
@@ -5764,5 +5764,454 @@
  IsPlacementNew));
 }
 
+TEST(HasUnqualifiedLoc, BindsToConstIntVarDecl) {
+  EXPECT_TRUE(matches(
+  "const int x = 0;",
+  varDecl(hasName("x"), hasTypeLoc(qualifiedTypeLoc(
+hasUnqualifiedLoc(loc(asString("int";
+}
+
+TEST(HasUnqualifiedLoc, BindsToVolatileIntVarDecl) {
+  EXPECT_TRUE(matches(
+  "volatile int x = 0;",
+  varDecl(hasName("x"), hasTypeLoc(qualifiedTypeLoc(
+hasUnqualifiedLoc(loc(asString("int";
+}
+
+TEST(HasUnqualifiedLoc, BindsToConstVolatileIntVarDecl) {
+  EXPECT_TRUE(matches(
+  "const volatile int x = 0;",
+  varDecl(hasName("x"), hasTypeLoc(qualifiedTypeLoc(
+hasUnqualifiedLoc(loc(asString("int";
+}
+
+TEST(HasUnqualifiedLoc, BindsToConstPointerVarDecl) {
+  auto matcher = varDecl(
+  hasName("x"),
+  hasTypeLoc(qualifiedTypeLoc(hasUnqualifiedLoc(pointerTypeLoc();
+  EXPECT_TRUE(matches("int* const x = 0;", matcher));
+  EXPECT_TRUE(notMatches("int const x = 0;", matcher));
+}
+
+TEST(HasUnqualifiedLoc, BindsToPointerToConstVolatileIntVarDecl) {
+  EXPECT_TRUE(
+  matches("const volatile int* x = 0;",
+  varDecl(hasName("x"),
+  hasTypeLoc(pointerTypeLoc(hasPointeeLoc(qualifiedTypeLoc(
+  hasUnqualifiedLoc(loc(asString("int"));
+}
+
+TEST(HasUnqualifiedLoc, BindsToConstIntFunctionDecl) {
+  EXPECT_TRUE(
+  matches("const int f() { return 5; }",
+  functionDecl(hasName("f"),
+   hasReturnTypeLoc(qualifiedTypeLoc(
+   hasUnqualifiedLoc(loc(asString("int";
+}
+
+TEST(HasUnqualifiedLoc, FloatBindsToConstFloatVarDecl) {
+  EXPECT_TRUE(matches(
+  "const float x = 0;",
+  varDecl(hasName("x"), hasTypeLoc(qualifiedTypeLoc(
+hasUnqualifiedLoc(loc(asString("float";
+}
+
+TEST(HasUnqualifiedLoc, FloatDoesNotBindToIntVarDecl) {
+  EXPECT_TRUE(notMatches(
+  "int x = 0;",
+  varDecl(hasName("x"), hasTypeLoc(qualifiedTypeLoc(
+hasUnqualifiedLoc(loc(asString("float";
+}
+
+TEST(HasUnqualifiedLoc, FloatDoesNotBindToConstIntVarDecl) {
+  EXPECT_TRUE(notMatches(
+  "const int x = 0;",
+  varDecl(hasName("x"), hasTypeLoc(qualifiedTypeLoc(
+hasUnqualifiedLoc(loc(asString("float";
+}
+
+TEST(HasReturnTypeLoc, BindsToIntReturnTypeLoc) {
+  EXPECT_TRUE(matches(
+  "int f() { return 5; }",
+  functionDecl(hasName("f"), hasReturnTypeLoc(loc(asString("int"));
+}
+
+TEST(HasReturnTypeLoc, BindsToFloatReturnTypeLoc) {
+  EXPECT_TRUE(matches(
+  "float f() { return 5.0; }",
+  functionDecl(hasName("f"), hasReturnTypeLoc(loc(asString("float"));
+}
+
+TEST(HasReturnTypeLoc, BindsToVoidReturnTypeLoc) {
+  EXPECT_TRUE(matches(
+  "void f() {}",
+  functionDecl(hasName("f"), hasReturnTypeLoc(loc(asString("void"));
+}
+
+TEST(HasReturnTypeLoc, FloatDoesNotBindToIntReturnTypeLoc) {
+  EXPECT_TRUE(notMatches(
+  "int f() { return 5; }",
+  functionDecl(hasName("f"), hasReturnTypeLoc(loc(asString("float"));
+}
+
+TEST(HasReturnTypeLoc, IntDoesNotBindToFloatReturnTypeLoc) {
+  EXPECT_TRUE(notMatches(
+  "float f() { return 5.0; }",
+  functionDecl(hasName("f"), hasReturnTypeLoc(loc(asString("int"));
+}
+
+TEST(HasPointeeLoc, BindsToAnyPointeeTypeLoc) {
+  auto matcher = varDecl(hasName("x"),
+ hasTypeLoc(pointerTypeLoc(hasPointeeLoc(typeLoc();
+  EXPECT_TRUE(matches("int* x;", matcher));
+  EXPECT_TRUE(matches("float* x;", matcher));
+  EXPECT_TRUE(matches("char* x;", matcher));
+  EXPECT_TRUE(matches("void* x;", matcher));
+}
+
+TEST(HasPointeeLoc, DoesNotBindToTypeLocWithoutPointee) {
+  auto matcher = varDecl(hasName("x"),
+ hasTypeLoc(pointerTypeLoc(hasPointeeLoc(typeLoc();
+  EXPECT_TRUE(notMatches("int x;", matcher));
+  EXPECT_TRUE(notMatches("float x;", matcher));
+  

[PATCH] D111332: [AST Matchers] Update dump_ast_matchers.py to query only class index page.

2021-10-08 Thread James King via Phabricator via cfe-commits
jcking1034 updated this revision to Diff 378279.
jcking1034 added a comment.

Rebase onto master


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D111332

Files:
  clang/docs/LibASTMatchersReference.html
  clang/docs/tools/dump_ast_matchers.py

Index: clang/docs/tools/dump_ast_matchers.py
===
--- clang/docs/tools/dump_ast_matchers.py
+++ clang/docs/tools/dump_ast_matchers.py
@@ -10,6 +10,12 @@
 except ImportError:
 from urllib2 import urlopen
 
+CLASS_INDEX_PAGE_URL = 'https://clang.llvm.org/doxygen/classes.html'
+try:
+  CLASS_INDEX_PAGE = urlopen(CLASS_INDEX_PAGE_URL).read()
+except Exception as e:
+  raise Exception('Unable to get %s: %s' % (CLASS_INDEX_PAGE_URL, e))
+
 MATCHERS_FILE = '../../include/clang/ASTMatchers/ASTMatchers.h'
 
 # Each matcher is documented in one row of the form:
@@ -40,15 +46,18 @@
   text = re.sub(r'<', '', text)
   text = re.sub(r'>', '', text)
   def link_if_exists(m):
+"""Wrap a likely AST node name in a link to its clang docs.
+
+   We want to do this only if the page exists, in which case it will be
+   referenced from the class index page.
+"""
 name = m.group(1)
 url = 'https://clang.llvm.org/doxygen/classclang_1_1%s.html' % name
 if url not in doxygen_probes:
-  try:
-print('Probing %s...' % url)
-urlopen(url)
-doxygen_probes[url] = True
-  except:
-doxygen_probes[url] = False
+  search_str = 'href="classclang_1_1%s.html"' % name
+  doxygen_probes[url] = search_str in CLASS_INDEX_PAGE
+  if not doxygen_probes[url]:
+print('Did not find %s in class index page' % name)
 if doxygen_probes[url]:
   return r'Matcher%s' % (url, name)
 else:
Index: clang/docs/LibASTMatchersReference.html
===
--- clang/docs/LibASTMatchersReference.html
+++ clang/docs/LibASTMatchersReference.html
@@ -573,15 +573,6 @@
 Return typeNameParameters
 
 
-Matcherhttps://clang.llvm.org/doxygen/classclang_1_1CXXBaseSpecifier.html;>CXXBaseSpecifiercxxBaseSpecifierMatcherhttps://clang.llvm.org/doxygen/classclang_1_1CXXBaseSpecifier.html;>CXXBaseSpecifier...
-Matches class bases.
-
-Examples matches public virtual B.
-  class B {};
-  class C : public virtual B {};
-
-
-
 Matcherhttps://clang.llvm.org/doxygen/classclang_1_1Attr.html;>AttrattrMatcherhttps://clang.llvm.org/doxygen/classclang_1_1Attr.html;>Attr...
 Matches attributes.
 Attributes may be attached with a variety of different syntaxes (including
@@ -600,6 +591,15 @@
 
 
 
+Matcherhttps://clang.llvm.org/doxygen/classclang_1_1CXXBaseSpecifier.html;>CXXBaseSpecifiercxxBaseSpecifierMatcherhttps://clang.llvm.org/doxygen/classclang_1_1CXXBaseSpecifier.html;>CXXBaseSpecifier...
+Matches class bases.
+
+Examples matches public virtual B.
+  class B {};
+  class C : public virtual B {};
+
+
+
 Matcherhttps://clang.llvm.org/doxygen/classclang_1_1CXXCtorInitializer.html;>CXXCtorInitializercxxCtorInitializerMatcherhttps://clang.llvm.org/doxygen/classclang_1_1CXXCtorInitializer.html;>CXXCtorInitializer...
 Matches constructor initializers.
 
@@ -1160,6 +1160,16 @@
   matches using namespace X 
 
 
+Matcherhttps://clang.llvm.org/doxygen/classclang_1_1Decl.html;>DeclusingEnumDeclMatcherhttps://clang.llvm.org/doxygen/classclang_1_1UsingEnumDecl.html;>UsingEnumDecl...
+Matches using-enum declarations.
+
+Given
+  namespace X { enum x {...}; }
+  using enum X::x;
+usingEnumDecl()
+  matches using enum X::x 
+
+
 Matcherhttps://clang.llvm.org/doxygen/classclang_1_1Decl.html;>DeclvalueDeclMatcherhttps://clang.llvm.org/doxygen/classclang_1_1ValueDecl.html;>ValueDecl...
 Matches any value declaration.
 
@@ -3031,6 +3041,10 @@
 
 
 
+Matcherhttps://clang.llvm.org/doxygen/classclang_1_1CXXConstructorDecl.html;>CXXConstructorDeclisInheritingConstructor
+
+
+
 Matcherhttps://clang.llvm.org/doxygen/classclang_1_1CXXConstructorDecl.html;>CXXConstructorDeclisMoveConstructor
 Matches constructor declarations that are move constructors.
 
@@ -3779,7 +3793,7 @@
 Matcherhttps://clang.llvm.org/doxygen/classclang_1_1Decl.html;>DeclisExpandedFromMacrostd::string MacroName
 Matches statements that are (transitively) expanded from the named macro.
 Does not match if only part of the statement is expanded from that macro or
-if different parts of the the statement are expanded from different
+if different parts of the statement are expanded from different
 appearances of the macro.
 
 
@@ -5232,7 +5246,7 @@
 Matcherhttps://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html;>TypeLocisExpandedFromMacrostd::string MacroName
 Matches statements that are (transitively) expanded from the named macro.
 Does not match if only part of the statement is expanded from that macro or
-if different parts of the the statement are expanded from different
+if different parts of the statement 

[PATCH] D111332: [AST Matchers] Update dump_ast_matchers.py to query only class index page.

2021-10-08 Thread James King via Phabricator via cfe-commits
jcking1034 updated this revision to Diff 378236.
jcking1034 added a comment.

Add docstring to `link_if_exists`.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D111332

Files:
  clang/docs/LibASTMatchersReference.html
  clang/docs/tools/dump_ast_matchers.py

Index: clang/docs/tools/dump_ast_matchers.py
===
--- clang/docs/tools/dump_ast_matchers.py
+++ clang/docs/tools/dump_ast_matchers.py
@@ -10,6 +10,12 @@
 except ImportError:
 from urllib2 import urlopen
 
+CLASS_INDEX_PAGE_URL = 'https://clang.llvm.org/doxygen/classes.html'
+try:
+  CLASS_INDEX_PAGE = urlopen(CLASS_INDEX_PAGE_URL).read()
+except Exception as e:
+  raise Exception('Unable to get %s: %s' % (CLASS_INDEX_PAGE_URL, e))
+
 MATCHERS_FILE = '../../include/clang/ASTMatchers/ASTMatchers.h'
 
 # Each matcher is documented in one row of the form:
@@ -40,15 +46,18 @@
   text = re.sub(r'<', '', text)
   text = re.sub(r'>', '', text)
   def link_if_exists(m):
+"""Wrap a likely AST node name in a link to its clang docs.
+
+   We want to do this only if the page exists, in which case it will be
+   referenced from the class index page.
+"""
 name = m.group(1)
 url = 'https://clang.llvm.org/doxygen/classclang_1_1%s.html' % name
 if url not in doxygen_probes:
-  try:
-print('Probing %s...' % url)
-urlopen(url)
-doxygen_probes[url] = True
-  except:
-doxygen_probes[url] = False
+  search_str = 'href="classclang_1_1%s.html"' % name
+  doxygen_probes[url] = search_str in CLASS_INDEX_PAGE
+  if not doxygen_probes[url]:
+print('Did not find %s in class index page' % name)
 if doxygen_probes[url]:
   return r'Matcher%s' % (url, name)
 else:
Index: clang/docs/LibASTMatchersReference.html
===
--- clang/docs/LibASTMatchersReference.html
+++ clang/docs/LibASTMatchersReference.html
@@ -573,15 +573,6 @@
 Return typeNameParameters
 
 
-Matcherhttps://clang.llvm.org/doxygen/classclang_1_1CXXBaseSpecifier.html;>CXXBaseSpecifiercxxBaseSpecifierMatcherhttps://clang.llvm.org/doxygen/classclang_1_1CXXBaseSpecifier.html;>CXXBaseSpecifier...
-Matches class bases.
-
-Examples matches public virtual B.
-  class B {};
-  class C : public virtual B {};
-
-
-
 Matcherhttps://clang.llvm.org/doxygen/classclang_1_1Attr.html;>AttrattrMatcherhttps://clang.llvm.org/doxygen/classclang_1_1Attr.html;>Attr...
 Matches attributes.
 Attributes may be attached with a variety of different syntaxes (including
@@ -600,6 +591,15 @@
 
 
 
+Matcherhttps://clang.llvm.org/doxygen/classclang_1_1CXXBaseSpecifier.html;>CXXBaseSpecifiercxxBaseSpecifierMatcherhttps://clang.llvm.org/doxygen/classclang_1_1CXXBaseSpecifier.html;>CXXBaseSpecifier...
+Matches class bases.
+
+Examples matches public virtual B.
+  class B {};
+  class C : public virtual B {};
+
+
+
 Matcherhttps://clang.llvm.org/doxygen/classclang_1_1CXXCtorInitializer.html;>CXXCtorInitializercxxCtorInitializerMatcherhttps://clang.llvm.org/doxygen/classclang_1_1CXXCtorInitializer.html;>CXXCtorInitializer...
 Matches constructor initializers.
 
@@ -1160,6 +1160,16 @@
   matches using namespace X 
 
 
+Matcherhttps://clang.llvm.org/doxygen/classclang_1_1Decl.html;>DeclusingEnumDeclMatcherhttps://clang.llvm.org/doxygen/classclang_1_1UsingEnumDecl.html;>UsingEnumDecl...
+Matches using-enum declarations.
+
+Given
+  namespace X { enum x {...}; }
+  using enum X::x;
+usingEnumDecl()
+  matches using enum X::x 
+
+
 Matcherhttps://clang.llvm.org/doxygen/classclang_1_1Decl.html;>DeclvalueDeclMatcherhttps://clang.llvm.org/doxygen/classclang_1_1ValueDecl.html;>ValueDecl...
 Matches any value declaration.
 
@@ -3031,6 +3041,10 @@
 
 
 
+Matcherhttps://clang.llvm.org/doxygen/classclang_1_1CXXConstructorDecl.html;>CXXConstructorDeclisInheritingConstructor
+
+
+
 Matcherhttps://clang.llvm.org/doxygen/classclang_1_1CXXConstructorDecl.html;>CXXConstructorDeclisMoveConstructor
 Matches constructor declarations that are move constructors.
 
@@ -3779,7 +3793,7 @@
 Matcherhttps://clang.llvm.org/doxygen/classclang_1_1Decl.html;>DeclisExpandedFromMacrostd::string MacroName
 Matches statements that are (transitively) expanded from the named macro.
 Does not match if only part of the statement is expanded from that macro or
-if different parts of the the statement are expanded from different
+if different parts of the statement are expanded from different
 appearances of the macro.
 
 
@@ -5232,7 +5246,7 @@
 Matcherhttps://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html;>TypeLocisExpandedFromMacrostd::string MacroName
 Matches statements that are (transitively) expanded from the named macro.
 Does not match if only part of the statement is expanded from that macro or
-if different parts of the the statement are expanded from different
+if different parts 

[PATCH] D111332: [AST Matchers] Update dump_ast_matchers.py to query only class index page.

2021-10-07 Thread James King via Phabricator via cfe-commits
jcking1034 added inline comments.



Comment at: clang/docs/tools/dump_ast_matchers.py:13
 
+CLASS_INDEX_PAGE = 
urlopen("https://clang.llvm.org/doxygen/classes.html;).read()
+

aaron.ballman wrote:
> Do we need to handle an exception here if there are network issues?
Technically, if there is a network issue, any exceptions would cause the script 
to terminate. But I think you're right that we should handle this case more 
carefully.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D111332

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


[PATCH] D111332: [AST Matchers] Update dump_ast_matchers.py to query only class index page.

2021-10-07 Thread James King via Phabricator via cfe-commits
jcking1034 updated this revision to Diff 378037.
jcking1034 added a comment.

Catch and reraise exceptions with an appropriate message.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D111332

Files:
  clang/docs/LibASTMatchersReference.html
  clang/docs/tools/dump_ast_matchers.py

Index: clang/docs/tools/dump_ast_matchers.py
===
--- clang/docs/tools/dump_ast_matchers.py
+++ clang/docs/tools/dump_ast_matchers.py
@@ -10,6 +10,12 @@
 except ImportError:
 from urllib2 import urlopen
 
+CLASS_INDEX_PAGE_URL = 'https://clang.llvm.org/doxygen/classes.html'
+try:
+  CLASS_INDEX_PAGE = urlopen(CLASS_INDEX_PAGE_URL).read()
+except Exception as e:
+  raise Exception('Unable to get %s: %s' % (CLASS_INDEX_PAGE_URL, e))
+
 MATCHERS_FILE = '../../include/clang/ASTMatchers/ASTMatchers.h'
 
 # Each matcher is documented in one row of the form:
@@ -43,12 +49,10 @@
 name = m.group(1)
 url = 'https://clang.llvm.org/doxygen/classclang_1_1%s.html' % name
 if url not in doxygen_probes:
-  try:
-print('Probing %s...' % url)
-urlopen(url)
-doxygen_probes[url] = True
-  except:
-doxygen_probes[url] = False
+  search_str = 'href="classclang_1_1%s.html"' % name
+  doxygen_probes[url] = search_str in CLASS_INDEX_PAGE
+  if not doxygen_probes[url]:
+print('Did not find %s in class index page' % name)
 if doxygen_probes[url]:
   return r'Matcher%s' % (url, name)
 else:
Index: clang/docs/LibASTMatchersReference.html
===
--- clang/docs/LibASTMatchersReference.html
+++ clang/docs/LibASTMatchersReference.html
@@ -573,15 +573,6 @@
 Return typeNameParameters
 
 
-Matcherhttps://clang.llvm.org/doxygen/classclang_1_1CXXBaseSpecifier.html;>CXXBaseSpecifiercxxBaseSpecifierMatcherhttps://clang.llvm.org/doxygen/classclang_1_1CXXBaseSpecifier.html;>CXXBaseSpecifier...
-Matches class bases.
-
-Examples matches public virtual B.
-  class B {};
-  class C : public virtual B {};
-
-
-
 Matcherhttps://clang.llvm.org/doxygen/classclang_1_1Attr.html;>AttrattrMatcherhttps://clang.llvm.org/doxygen/classclang_1_1Attr.html;>Attr...
 Matches attributes.
 Attributes may be attached with a variety of different syntaxes (including
@@ -600,6 +591,15 @@
 
 
 
+Matcherhttps://clang.llvm.org/doxygen/classclang_1_1CXXBaseSpecifier.html;>CXXBaseSpecifiercxxBaseSpecifierMatcherhttps://clang.llvm.org/doxygen/classclang_1_1CXXBaseSpecifier.html;>CXXBaseSpecifier...
+Matches class bases.
+
+Examples matches public virtual B.
+  class B {};
+  class C : public virtual B {};
+
+
+
 Matcherhttps://clang.llvm.org/doxygen/classclang_1_1CXXCtorInitializer.html;>CXXCtorInitializercxxCtorInitializerMatcherhttps://clang.llvm.org/doxygen/classclang_1_1CXXCtorInitializer.html;>CXXCtorInitializer...
 Matches constructor initializers.
 
@@ -1160,6 +1160,16 @@
   matches using namespace X 
 
 
+Matcherhttps://clang.llvm.org/doxygen/classclang_1_1Decl.html;>DeclusingEnumDeclMatcherhttps://clang.llvm.org/doxygen/classclang_1_1UsingEnumDecl.html;>UsingEnumDecl...
+Matches using-enum declarations.
+
+Given
+  namespace X { enum x {...}; }
+  using enum X::x;
+usingEnumDecl()
+  matches using enum X::x 
+
+
 Matcherhttps://clang.llvm.org/doxygen/classclang_1_1Decl.html;>DeclvalueDeclMatcherhttps://clang.llvm.org/doxygen/classclang_1_1ValueDecl.html;>ValueDecl...
 Matches any value declaration.
 
@@ -3031,6 +3041,10 @@
 
 
 
+Matcherhttps://clang.llvm.org/doxygen/classclang_1_1CXXConstructorDecl.html;>CXXConstructorDeclisInheritingConstructor
+
+
+
 Matcherhttps://clang.llvm.org/doxygen/classclang_1_1CXXConstructorDecl.html;>CXXConstructorDeclisMoveConstructor
 Matches constructor declarations that are move constructors.
 
@@ -3779,7 +3793,7 @@
 Matcherhttps://clang.llvm.org/doxygen/classclang_1_1Decl.html;>DeclisExpandedFromMacrostd::string MacroName
 Matches statements that are (transitively) expanded from the named macro.
 Does not match if only part of the statement is expanded from that macro or
-if different parts of the the statement are expanded from different
+if different parts of the statement are expanded from different
 appearances of the macro.
 
 
@@ -5232,7 +5246,7 @@
 Matcherhttps://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html;>TypeLocisExpandedFromMacrostd::string MacroName
 Matches statements that are (transitively) expanded from the named macro.
 Does not match if only part of the statement is expanded from that macro or
-if different parts of the the statement are expanded from different
+if different parts of the statement are expanded from different
 appearances of the macro.
 
 
@@ -6060,6 +6074,16 @@
 
 
 

[PATCH] D111242: Add `TypeLoc`-related matchers.

2021-10-07 Thread James King via Phabricator via cfe-commits
jcking1034 added inline comments.



Comment at: clang/include/clang/ASTMatchers/ASTMatchers.h:6406-6414
+/// Matches reference `TypeLoc`s.
+///
+/// Given
+/// \code
+///   int x = 3;
+///   int& xx = x;
+/// \endcode

jcking1034 wrote:
> aaron.ballman wrote:
> > I'd appreciate more documentation on whether this is expected to match both 
> > lvalue and rvalue references. I suppose there's a secondary question of 
> > whether this matches member functions too:
> > ```
> > struct S {
> >   void func() &; // Can this match this as a reference type loc?
> > };
> > ```
> I've added an example to clarify that this matches both lvalue and rvalue 
> references. Having some trouble addressing your second point, but will keep 
> playing around with it.
After looking into it, it seems that this matcher will not match ref-qualified 
member functions. Essentially, this node isn't represented in a way that allows 
for it to be matched by `referenceTypeLoc`.

For a more detailed explaination: In this example, we are able to use 
`cxxMethodDecl` to match `void func() &`. If we wished to match the `Type` of 
the member function, we could use 
`cxxMethodDecl(hasType(functionProtoType().bind("t")))`, and from the 
`FunctionProtoType` node you could determine if the function is ref-qualified 
through a call to `getRefQualifier` 
(https://clang.llvm.org/doxygen/classclang_1_1FunctionProtoType.html). It's not 
possible to match using `cxxMethodDecl(hasType(referenceType().bind("t")))`. So 
it seems that the type of the member function is not a reference type, but 
instead a `FunctionProtoType` from which you'd programmatically have to 
determine if it's a reference type. In the realm of `TypeLoc`s, there is no 
`TypeLoc` that corresponds to the `FunctionProtoType` node, and so the best you 
could do may be something like 
`cxxMethodDecl(hasTypeLoc(loc(functionProtoType().bind("t"` and 
programmatically analyzing the bound node. For reference, please see 
https://godbolt.org/z/qxsEb6a5Y.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D111242

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


[PATCH] D111332: Update dump_ast_matchers.py to query only class index page.

2021-10-07 Thread James King via Phabricator via cfe-commits
jcking1034 created this revision.
jcking1034 added a reviewer: ymandel.
Herald added a subscriber: arphaman.
jcking1034 requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

It may be possible to avoid relying on accessing many individual class pages,
by instead scanning the class index page at
https://clang.llvm.org/doxygen/classes.html. This updates the script to do so,
and includes updates to `LibASTMatchersReference.html` generated by the
modified script.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D111332

Files:
  clang/docs/LibASTMatchersReference.html
  clang/docs/tools/dump_ast_matchers.py

Index: clang/docs/tools/dump_ast_matchers.py
===
--- clang/docs/tools/dump_ast_matchers.py
+++ clang/docs/tools/dump_ast_matchers.py
@@ -10,6 +10,8 @@
 except ImportError:
 from urllib2 import urlopen
 
+CLASS_INDEX_PAGE = urlopen("https://clang.llvm.org/doxygen/classes.html;).read()
+
 MATCHERS_FILE = '../../include/clang/ASTMatchers/ASTMatchers.h'
 
 # Each matcher is documented in one row of the form:
@@ -43,12 +45,10 @@
 name = m.group(1)
 url = 'https://clang.llvm.org/doxygen/classclang_1_1%s.html' % name
 if url not in doxygen_probes:
-  try:
-print('Probing %s...' % url)
-urlopen(url)
-doxygen_probes[url] = True
-  except:
-doxygen_probes[url] = False
+  search_str = 'href="classclang_1_1%s.html"' % name
+  doxygen_probes[url] = search_str in CLASS_INDEX_PAGE
+  if not doxygen_probes[url]:
+print('Did not find %s in class index page' % name)
 if doxygen_probes[url]:
   return r'Matcher%s' % (url, name)
 else:
Index: clang/docs/LibASTMatchersReference.html
===
--- clang/docs/LibASTMatchersReference.html
+++ clang/docs/LibASTMatchersReference.html
@@ -573,15 +573,6 @@
 Return typeNameParameters
 
 
-Matcherhttps://clang.llvm.org/doxygen/classclang_1_1CXXBaseSpecifier.html;>CXXBaseSpecifiercxxBaseSpecifierMatcherhttps://clang.llvm.org/doxygen/classclang_1_1CXXBaseSpecifier.html;>CXXBaseSpecifier...
-Matches class bases.
-
-Examples matches public virtual B.
-  class B {};
-  class C : public virtual B {};
-
-
-
 Matcherhttps://clang.llvm.org/doxygen/classclang_1_1Attr.html;>AttrattrMatcherhttps://clang.llvm.org/doxygen/classclang_1_1Attr.html;>Attr...
 Matches attributes.
 Attributes may be attached with a variety of different syntaxes (including
@@ -600,6 +591,15 @@
 
 
 
+Matcherhttps://clang.llvm.org/doxygen/classclang_1_1CXXBaseSpecifier.html;>CXXBaseSpecifiercxxBaseSpecifierMatcherhttps://clang.llvm.org/doxygen/classclang_1_1CXXBaseSpecifier.html;>CXXBaseSpecifier...
+Matches class bases.
+
+Examples matches public virtual B.
+  class B {};
+  class C : public virtual B {};
+
+
+
 Matcherhttps://clang.llvm.org/doxygen/classclang_1_1CXXCtorInitializer.html;>CXXCtorInitializercxxCtorInitializerMatcherhttps://clang.llvm.org/doxygen/classclang_1_1CXXCtorInitializer.html;>CXXCtorInitializer...
 Matches constructor initializers.
 
@@ -1160,6 +1160,16 @@
   matches using namespace X 
 
 
+Matcherhttps://clang.llvm.org/doxygen/classclang_1_1Decl.html;>DeclusingEnumDeclMatcherhttps://clang.llvm.org/doxygen/classclang_1_1UsingEnumDecl.html;>UsingEnumDecl...
+Matches using-enum declarations.
+
+Given
+  namespace X { enum x {...}; }
+  using enum X::x;
+usingEnumDecl()
+  matches using enum X::x 
+
+
 Matcherhttps://clang.llvm.org/doxygen/classclang_1_1Decl.html;>DeclvalueDeclMatcherhttps://clang.llvm.org/doxygen/classclang_1_1ValueDecl.html;>ValueDecl...
 Matches any value declaration.
 
@@ -3031,6 +3041,10 @@
 
 
 
+Matcherhttps://clang.llvm.org/doxygen/classclang_1_1CXXConstructorDecl.html;>CXXConstructorDeclisInheritingConstructor
+
+
+
 Matcherhttps://clang.llvm.org/doxygen/classclang_1_1CXXConstructorDecl.html;>CXXConstructorDeclisMoveConstructor
 Matches constructor declarations that are move constructors.
 
@@ -3779,7 +3793,7 @@
 Matcherhttps://clang.llvm.org/doxygen/classclang_1_1Decl.html;>DeclisExpandedFromMacrostd::string MacroName
 Matches statements that are (transitively) expanded from the named macro.
 Does not match if only part of the statement is expanded from that macro or
-if different parts of the the statement are expanded from different
+if different parts of the statement are expanded from different
 appearances of the macro.
 
 
@@ -5232,7 +5246,7 @@
 Matcherhttps://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html;>TypeLocisExpandedFromMacrostd::string MacroName
 Matches statements that are (transitively) expanded from the named macro.
 Does not match if only part of the statement is expanded from that macro or
-if different parts of the the statement are expanded from different
+if different parts of the statement are expanded from different
 appearances of the macro.
 
 
@@ -6060,6 +6074,16 @@
 
 
 

[PATCH] D111242: Add `TypeLoc`-related matchers.

2021-10-07 Thread James King via Phabricator via cfe-commits
jcking1034 marked an inline comment as not done.
jcking1034 added inline comments.



Comment at: clang/docs/LibASTMatchersReference.html:636
 
-Matcherhttps://clang.llvm.org/doxygen/classclang_1_1Decl.html;>DeclblockDeclMatcherhttps://clang.llvm.org/doxygen/classclang_1_1BlockDecl.html;>BlockDecl...
+Matcherhttps://clang.llvm.org/doxygen/classclang_1_1Decl.html;>DeclblockDeclMatcherBlockDecl...
 Matches block 
declarations.

ymandel wrote:
> ymandel wrote:
> > Here and below. These changes look wrong. Did the script encounter an error?
> Any luck fixing these edits?
I think I got it to work!



Comment at: clang/include/clang/ASTMatchers/ASTMatchers.h:6361-6362
+/// \endcode
+/// qualifiedTypeLoc(hasUnqualifiedLoc(pointerTypeLoc()))
+///   matches the `TypeLoc` of the variable declaration of `x`, but not `y`.
+AST_MATCHER_P(QualifiedTypeLoc, hasUnqualifiedLoc, TypeLocMatcher,

aaron.ballman wrote:
> I'm trying to reason my way through this. You want to match a qualified type 
> location and `int * const` matches that. Then you want it to match an 
> unqualified type loc and `int` matches that. Then it should be a pointer 
> type... but `int` does not match that. So I wouldn't expect `x` to be 
> matched. What have I misunderstood?
The `hasUnqualifiedLoc` will actually be matched by `int *` (the `*` is part of 
the unqualified `TypeLoc`), which will then be a pointer `TypeLoc` that can be 
matched by `pointerTypeLoc`. Thus, the `TypeLoc` of `x` should be matched.

I just realized that the unit test `BindsToConstVolatilePointerVarDecl` which 
covers a similar situation is broken, where the match is producing a false 
positive (probably matching some hidden boiler plate code) - I've gone ahead 
and fixed the test, which hopefully clarifies things. I'll also add a unit test 
for these cases, as well.



Comment at: clang/include/clang/ASTMatchers/ASTMatchers.h:6406-6414
+/// Matches reference `TypeLoc`s.
+///
+/// Given
+/// \code
+///   int x = 3;
+///   int& xx = x;
+/// \endcode

aaron.ballman wrote:
> I'd appreciate more documentation on whether this is expected to match both 
> lvalue and rvalue references. I suppose there's a secondary question of 
> whether this matches member functions too:
> ```
> struct S {
>   void func() &; // Can this match this as a reference type loc?
> };
> ```
I've added an example to clarify that this matches both lvalue and rvalue 
references. Having some trouble addressing your second point, but will keep 
playing around with it.



Comment at: clang/include/clang/ASTMatchers/ASTMatchers.h:6510-6520
+/// Matches elaborated `TypeLoc`s.
+///
+/// Given
+/// \code
+///   class C {};
+///   class C c;
+/// \endcode

aaron.ballman wrote:
> It'd be helpful to document how this behaves in C where the tag needs to be 
> used (unlike in C++ where the tag can be elided unless you want an elaborated 
> type). Same below.
This matcher should match in C, I've updated the comment to reflect this. I've 
also updated the unit test 
`ElaboratedTypeLocTest_BindsToElaboratedStructDeclaration` to cover both the C 
and C++ cases.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D111242

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


[PATCH] D111242: Add `TypeLoc`-related matchers.

2021-10-07 Thread James King via Phabricator via cfe-commits
jcking1034 updated this revision to Diff 377933.
jcking1034 marked 2 inline comments as done.
jcking1034 added a comment.

Address comments.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D111242

Files:
  clang/docs/LibASTMatchersReference.html
  clang/include/clang/ASTMatchers/ASTMatchers.h
  clang/include/clang/ASTMatchers/ASTMatchersInternal.h
  clang/lib/ASTMatchers/ASTMatchersInternal.cpp
  clang/lib/ASTMatchers/Dynamic/Registry.cpp
  clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
  clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp

Index: clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
===
--- clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
+++ clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
@@ -5764,5 +5764,454 @@
  IsPlacementNew));
 }
 
+TEST(HasUnqualifiedLoc, BindsToConstIntVarDecl) {
+  EXPECT_TRUE(matches(
+  "const int x = 0;",
+  varDecl(hasName("x"), hasTypeLoc(qualifiedTypeLoc(
+hasUnqualifiedLoc(loc(asString("int";
+}
+
+TEST(HasUnqualifiedLoc, BindsToVolatileIntVarDecl) {
+  EXPECT_TRUE(matches(
+  "volatile int x = 0;",
+  varDecl(hasName("x"), hasTypeLoc(qualifiedTypeLoc(
+hasUnqualifiedLoc(loc(asString("int";
+}
+
+TEST(HasUnqualifiedLoc, BindsToConstVolatileIntVarDecl) {
+  EXPECT_TRUE(matches(
+  "const volatile int x = 0;",
+  varDecl(hasName("x"), hasTypeLoc(qualifiedTypeLoc(
+hasUnqualifiedLoc(loc(asString("int";
+}
+
+TEST(HasUnqualifiedLoc, BindsToConstPointerVarDecl) {
+  auto matcher = varDecl(
+  hasName("x"),
+  hasTypeLoc(qualifiedTypeLoc(hasUnqualifiedLoc(pointerTypeLoc();
+  EXPECT_TRUE(matches("int* const x = 0;", matcher));
+  EXPECT_TRUE(notMatches("int const x = 0;", matcher));
+}
+
+TEST(HasUnqualifiedLoc, BindsToPointerToConstVolatileIntVarDecl) {
+  EXPECT_TRUE(
+  matches("const volatile int* x = 0;",
+  varDecl(hasName("x"),
+  hasTypeLoc(pointerTypeLoc(hasPointeeLoc(qualifiedTypeLoc(
+  hasUnqualifiedLoc(loc(asString("int"));
+}
+
+TEST(HasUnqualifiedLoc, BindsToConstIntFunctionDecl) {
+  EXPECT_TRUE(
+  matches("const int f() { return 5; }",
+  functionDecl(hasName("f"),
+   hasReturnTypeLoc(qualifiedTypeLoc(
+   hasUnqualifiedLoc(loc(asString("int";
+}
+
+TEST(HasUnqualifiedLoc, FloatBindsToConstFloatVarDecl) {
+  EXPECT_TRUE(matches(
+  "const float x = 0;",
+  varDecl(hasName("x"), hasTypeLoc(qualifiedTypeLoc(
+hasUnqualifiedLoc(loc(asString("float";
+}
+
+TEST(HasUnqualifiedLoc, FloatDoesNotBindToIntVarDecl) {
+  EXPECT_TRUE(notMatches(
+  "int x = 0;",
+  varDecl(hasName("x"), hasTypeLoc(qualifiedTypeLoc(
+hasUnqualifiedLoc(loc(asString("float";
+}
+
+TEST(HasUnqualifiedLoc, FloatDoesNotBindToConstIntVarDecl) {
+  EXPECT_TRUE(notMatches(
+  "const int x = 0;",
+  varDecl(hasName("x"), hasTypeLoc(qualifiedTypeLoc(
+hasUnqualifiedLoc(loc(asString("float";
+}
+
+TEST(HasReturnTypeLoc, BindsToIntReturnTypeLoc) {
+  EXPECT_TRUE(matches(
+  "int f() { return 5; }",
+  functionDecl(hasName("f"), hasReturnTypeLoc(loc(asString("int"));
+}
+
+TEST(HasReturnTypeLoc, BindsToFloatReturnTypeLoc) {
+  EXPECT_TRUE(matches(
+  "float f() { return 5.0; }",
+  functionDecl(hasName("f"), hasReturnTypeLoc(loc(asString("float"));
+}
+
+TEST(HasReturnTypeLoc, BindsToVoidReturnTypeLoc) {
+  EXPECT_TRUE(matches(
+  "void f() {}",
+  functionDecl(hasName("f"), hasReturnTypeLoc(loc(asString("void"));
+}
+
+TEST(HasReturnTypeLoc, FloatDoesNotBindToIntReturnTypeLoc) {
+  EXPECT_TRUE(notMatches(
+  "int f() { return 5; }",
+  functionDecl(hasName("f"), hasReturnTypeLoc(loc(asString("float"));
+}
+
+TEST(HasReturnTypeLoc, IntDoesNotBindToFloatReturnTypeLoc) {
+  EXPECT_TRUE(notMatches(
+  "float f() { return 5.0; }",
+  functionDecl(hasName("f"), hasReturnTypeLoc(loc(asString("int"));
+}
+
+TEST(HasPointeeLoc, BindsToAnyPointeeTypeLoc) {
+  auto matcher = varDecl(hasName("x"),
+ hasTypeLoc(pointerTypeLoc(hasPointeeLoc(typeLoc();
+  EXPECT_TRUE(matches("int* x;", matcher));
+  EXPECT_TRUE(matches("float* x;", matcher));
+  EXPECT_TRUE(matches("char* x;", matcher));
+  EXPECT_TRUE(matches("void* x;", matcher));
+}
+
+TEST(HasPointeeLoc, DoesNotBindToTypeLocWithoutPointee) {
+  auto matcher = varDecl(hasName("x"),
+ hasTypeLoc(pointerTypeLoc(hasPointeeLoc(typeLoc();
+  EXPECT_TRUE(notMatches("int x;", matcher));
+  

[PATCH] D111242: Add `TypeLoc`-related matchers.

2021-10-07 Thread James King via Phabricator via cfe-commits
jcking1034 updated this revision to Diff 377885.
jcking1034 added a comment.

Actually fix documentation for `hasTemplateArgumentLoc`.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D111242

Files:
  clang/docs/LibASTMatchersReference.html
  clang/include/clang/ASTMatchers/ASTMatchers.h
  clang/lib/ASTMatchers/ASTMatchersInternal.cpp
  clang/lib/ASTMatchers/Dynamic/Registry.cpp
  clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
  clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp

Index: clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
===
--- clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
+++ clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
@@ -5764,5 +5764,425 @@
  IsPlacementNew));
 }
 
+TEST(HasUnqualifiedLoc, BindsToConstIntVarDecl) {
+  EXPECT_TRUE(matches("const int x = 0;", qualifiedTypeLoc(hasUnqualifiedLoc(
+  loc(asString("int"));
+}
+
+TEST(HasUnqualifiedLoc, BindsToVolatileIntVarDecl) {
+  EXPECT_TRUE(matches("volatile int x = 0;", qualifiedTypeLoc(hasUnqualifiedLoc(
+ loc(asString("int"));
+}
+
+TEST(HasUnqualifiedLoc, BindsToConstVolatileIntPointerVarDecl) {
+  EXPECT_TRUE(
+  matches("const volatile int* x = 0;",
+  qualifiedTypeLoc(hasUnqualifiedLoc(loc(asString("int"));
+}
+
+TEST(HasUnqualifiedLoc, BindsToConstIntFunctionDecl) {
+  EXPECT_TRUE(
+  matches("const int f() { return 5; }",
+  qualifiedTypeLoc(hasUnqualifiedLoc(loc(asString("int"));
+}
+
+TEST(HasUnqualifiedLoc, FloatBindsToConstFloatVarDecl) {
+  EXPECT_TRUE(matches("const float x = 0;", qualifiedTypeLoc(hasUnqualifiedLoc(
+loc(asString("float"));
+}
+
+TEST(HasUnqualifiedLoc, FloatDoesNotBindToIntVarDecl) {
+  EXPECT_TRUE(notMatches("int x = 0;", qualifiedTypeLoc(hasUnqualifiedLoc(
+   loc(asString("float"));
+}
+
+TEST(HasUnqualifiedLoc, FloatDoesNotBindToConstIntVarDecl) {
+  EXPECT_TRUE(notMatches("const int x = 0;", qualifiedTypeLoc(hasUnqualifiedLoc(
+ loc(asString("float"));
+}
+
+TEST(HasReturnTypeLoc, BindsToIntReturnTypeLoc) {
+  EXPECT_TRUE(matches(
+  "int f() { return 5; }",
+  functionDecl(hasName("f"), hasReturnTypeLoc(loc(asString("int"));
+}
+
+TEST(HasReturnTypeLoc, BindsToFloatReturnTypeLoc) {
+  EXPECT_TRUE(matches(
+  "float f() { return 5.0; }",
+  functionDecl(hasName("f"), hasReturnTypeLoc(loc(asString("float"));
+}
+
+TEST(HasReturnTypeLoc, BindsToVoidReturnTypeLoc) {
+  EXPECT_TRUE(matches(
+  "void f() {}",
+  functionDecl(hasName("f"), hasReturnTypeLoc(loc(asString("void"));
+}
+
+TEST(HasReturnTypeLoc, FloatDoesNotBindToIntReturnTypeLoc) {
+  EXPECT_TRUE(notMatches(
+  "int f() { return 5; }",
+  functionDecl(hasName("f"), hasReturnTypeLoc(loc(asString("float"));
+}
+
+TEST(HasReturnTypeLoc, IntDoesNotBindToFloatReturnTypeLoc) {
+  EXPECT_TRUE(notMatches(
+  "float f() { return 5.0; }",
+  functionDecl(hasName("f"), hasReturnTypeLoc(loc(asString("int"));
+}
+
+TEST(HasPointeeLoc, BindsToAnyPointeeTypeLoc) {
+  auto matcher = varDecl(hasName("x"),
+ hasTypeLoc(pointerTypeLoc(hasPointeeLoc(typeLoc();
+  EXPECT_TRUE(matches("int* x;", matcher));
+  EXPECT_TRUE(matches("float* x;", matcher));
+  EXPECT_TRUE(matches("char* x;", matcher));
+  EXPECT_TRUE(matches("void* x;", matcher));
+}
+
+TEST(HasPointeeLoc, DoesNotBindToTypeLocWithoutPointee) {
+  auto matcher = varDecl(hasName("x"),
+ hasTypeLoc(pointerTypeLoc(hasPointeeLoc(typeLoc();
+  EXPECT_TRUE(notMatches("int x;", matcher));
+  EXPECT_TRUE(notMatches("float x;", matcher));
+  EXPECT_TRUE(notMatches("char x;", matcher));
+}
+
+TEST(HasPointeeLoc, BindsToTypeLocPointingToInt) {
+  EXPECT_TRUE(
+  matches("int* x;", pointerTypeLoc(hasPointeeLoc(loc(asString("int"));
+}
+
+TEST(HasPointeeLoc, BindsToTypeLocPointingToIntPointer) {
+  EXPECT_TRUE(matches("int** x;",
+  pointerTypeLoc(hasPointeeLoc(loc(asString("int *"));
+}
+
+TEST(HasPointeeLoc, BindsToTypeLocPointingToTypeLocPointingToInt) {
+  EXPECT_TRUE(matches("int** x;", pointerTypeLoc(hasPointeeLoc(pointerTypeLoc(
+  hasPointeeLoc(loc(asString("int";
+}
+
+TEST(HasPointeeLoc, BindsToTypeLocPointingToFloat) {
+  EXPECT_TRUE(matches("float* x;",
+  pointerTypeLoc(hasPointeeLoc(loc(asString("float"));
+}
+
+TEST(HasPointeeLoc, IntPointeeDoesNotBindToTypeLocPointingToFloat) {
+  EXPECT_TRUE(notMatches("float* x;",
+ pointerTypeLoc(hasPointeeLoc(loc(asString("int"));

[PATCH] D111242: Add `TypeLoc`-related matchers.

2021-10-07 Thread James King via Phabricator via cfe-commits
jcking1034 updated this revision to Diff 377854.
jcking1034 added a comment.

Fix documentation for hasTemplateArgumentLoc.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D111242

Files:
  clang/docs/LibASTMatchersReference.html
  clang/include/clang/ASTMatchers/ASTMatchers.h
  clang/lib/ASTMatchers/ASTMatchersInternal.cpp
  clang/lib/ASTMatchers/Dynamic/Registry.cpp
  clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
  clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp

Index: clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
===
--- clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
+++ clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
@@ -5764,5 +5764,425 @@
  IsPlacementNew));
 }
 
+TEST(HasUnqualifiedLoc, BindsToConstIntVarDecl) {
+  EXPECT_TRUE(matches("const int x = 0;", qualifiedTypeLoc(hasUnqualifiedLoc(
+  loc(asString("int"));
+}
+
+TEST(HasUnqualifiedLoc, BindsToVolatileIntVarDecl) {
+  EXPECT_TRUE(matches("volatile int x = 0;", qualifiedTypeLoc(hasUnqualifiedLoc(
+ loc(asString("int"));
+}
+
+TEST(HasUnqualifiedLoc, BindsToConstVolatileIntPointerVarDecl) {
+  EXPECT_TRUE(
+  matches("const volatile int* x = 0;",
+  qualifiedTypeLoc(hasUnqualifiedLoc(loc(asString("int"));
+}
+
+TEST(HasUnqualifiedLoc, BindsToConstIntFunctionDecl) {
+  EXPECT_TRUE(
+  matches("const int f() { return 5; }",
+  qualifiedTypeLoc(hasUnqualifiedLoc(loc(asString("int"));
+}
+
+TEST(HasUnqualifiedLoc, FloatBindsToConstFloatVarDecl) {
+  EXPECT_TRUE(matches("const float x = 0;", qualifiedTypeLoc(hasUnqualifiedLoc(
+loc(asString("float"));
+}
+
+TEST(HasUnqualifiedLoc, FloatDoesNotBindToIntVarDecl) {
+  EXPECT_TRUE(notMatches("int x = 0;", qualifiedTypeLoc(hasUnqualifiedLoc(
+   loc(asString("float"));
+}
+
+TEST(HasUnqualifiedLoc, FloatDoesNotBindToConstIntVarDecl) {
+  EXPECT_TRUE(notMatches("const int x = 0;", qualifiedTypeLoc(hasUnqualifiedLoc(
+ loc(asString("float"));
+}
+
+TEST(HasReturnTypeLoc, BindsToIntReturnTypeLoc) {
+  EXPECT_TRUE(matches(
+  "int f() { return 5; }",
+  functionDecl(hasName("f"), hasReturnTypeLoc(loc(asString("int"));
+}
+
+TEST(HasReturnTypeLoc, BindsToFloatReturnTypeLoc) {
+  EXPECT_TRUE(matches(
+  "float f() { return 5.0; }",
+  functionDecl(hasName("f"), hasReturnTypeLoc(loc(asString("float"));
+}
+
+TEST(HasReturnTypeLoc, BindsToVoidReturnTypeLoc) {
+  EXPECT_TRUE(matches(
+  "void f() {}",
+  functionDecl(hasName("f"), hasReturnTypeLoc(loc(asString("void"));
+}
+
+TEST(HasReturnTypeLoc, FloatDoesNotBindToIntReturnTypeLoc) {
+  EXPECT_TRUE(notMatches(
+  "int f() { return 5; }",
+  functionDecl(hasName("f"), hasReturnTypeLoc(loc(asString("float"));
+}
+
+TEST(HasReturnTypeLoc, IntDoesNotBindToFloatReturnTypeLoc) {
+  EXPECT_TRUE(notMatches(
+  "float f() { return 5.0; }",
+  functionDecl(hasName("f"), hasReturnTypeLoc(loc(asString("int"));
+}
+
+TEST(HasPointeeLoc, BindsToAnyPointeeTypeLoc) {
+  auto matcher = varDecl(hasName("x"),
+ hasTypeLoc(pointerTypeLoc(hasPointeeLoc(typeLoc();
+  EXPECT_TRUE(matches("int* x;", matcher));
+  EXPECT_TRUE(matches("float* x;", matcher));
+  EXPECT_TRUE(matches("char* x;", matcher));
+  EXPECT_TRUE(matches("void* x;", matcher));
+}
+
+TEST(HasPointeeLoc, DoesNotBindToTypeLocWithoutPointee) {
+  auto matcher = varDecl(hasName("x"),
+ hasTypeLoc(pointerTypeLoc(hasPointeeLoc(typeLoc();
+  EXPECT_TRUE(notMatches("int x;", matcher));
+  EXPECT_TRUE(notMatches("float x;", matcher));
+  EXPECT_TRUE(notMatches("char x;", matcher));
+}
+
+TEST(HasPointeeLoc, BindsToTypeLocPointingToInt) {
+  EXPECT_TRUE(
+  matches("int* x;", pointerTypeLoc(hasPointeeLoc(loc(asString("int"));
+}
+
+TEST(HasPointeeLoc, BindsToTypeLocPointingToIntPointer) {
+  EXPECT_TRUE(matches("int** x;",
+  pointerTypeLoc(hasPointeeLoc(loc(asString("int *"));
+}
+
+TEST(HasPointeeLoc, BindsToTypeLocPointingToTypeLocPointingToInt) {
+  EXPECT_TRUE(matches("int** x;", pointerTypeLoc(hasPointeeLoc(pointerTypeLoc(
+  hasPointeeLoc(loc(asString("int";
+}
+
+TEST(HasPointeeLoc, BindsToTypeLocPointingToFloat) {
+  EXPECT_TRUE(matches("float* x;",
+  pointerTypeLoc(hasPointeeLoc(loc(asString("float"));
+}
+
+TEST(HasPointeeLoc, IntPointeeDoesNotBindToTypeLocPointingToFloat) {
+  EXPECT_TRUE(notMatches("float* x;",
+ pointerTypeLoc(hasPointeeLoc(loc(asString("int"));
+}
+

[PATCH] D111242: Add `TypeLoc`-related matchers.

2021-10-07 Thread James King via Phabricator via cfe-commits
jcking1034 updated this revision to Diff 377845.
jcking1034 added a comment.

Update matchers reference page.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D111242

Files:
  clang/docs/LibASTMatchersReference.html
  clang/include/clang/ASTMatchers/ASTMatchers.h
  clang/lib/ASTMatchers/ASTMatchersInternal.cpp
  clang/lib/ASTMatchers/Dynamic/Registry.cpp
  clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
  clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp

Index: clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
===
--- clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
+++ clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
@@ -5764,5 +5764,425 @@
  IsPlacementNew));
 }
 
+TEST(HasUnqualifiedLoc, BindsToConstIntVarDecl) {
+  EXPECT_TRUE(matches("const int x = 0;", qualifiedTypeLoc(hasUnqualifiedLoc(
+  loc(asString("int"));
+}
+
+TEST(HasUnqualifiedLoc, BindsToVolatileIntVarDecl) {
+  EXPECT_TRUE(matches("volatile int x = 0;", qualifiedTypeLoc(hasUnqualifiedLoc(
+ loc(asString("int"));
+}
+
+TEST(HasUnqualifiedLoc, BindsToConstVolatileIntPointerVarDecl) {
+  EXPECT_TRUE(
+  matches("const volatile int* x = 0;",
+  qualifiedTypeLoc(hasUnqualifiedLoc(loc(asString("int"));
+}
+
+TEST(HasUnqualifiedLoc, BindsToConstIntFunctionDecl) {
+  EXPECT_TRUE(
+  matches("const int f() { return 5; }",
+  qualifiedTypeLoc(hasUnqualifiedLoc(loc(asString("int"));
+}
+
+TEST(HasUnqualifiedLoc, FloatBindsToConstFloatVarDecl) {
+  EXPECT_TRUE(matches("const float x = 0;", qualifiedTypeLoc(hasUnqualifiedLoc(
+loc(asString("float"));
+}
+
+TEST(HasUnqualifiedLoc, FloatDoesNotBindToIntVarDecl) {
+  EXPECT_TRUE(notMatches("int x = 0;", qualifiedTypeLoc(hasUnqualifiedLoc(
+   loc(asString("float"));
+}
+
+TEST(HasUnqualifiedLoc, FloatDoesNotBindToConstIntVarDecl) {
+  EXPECT_TRUE(notMatches("const int x = 0;", qualifiedTypeLoc(hasUnqualifiedLoc(
+ loc(asString("float"));
+}
+
+TEST(HasReturnTypeLoc, BindsToIntReturnTypeLoc) {
+  EXPECT_TRUE(matches(
+  "int f() { return 5; }",
+  functionDecl(hasName("f"), hasReturnTypeLoc(loc(asString("int"));
+}
+
+TEST(HasReturnTypeLoc, BindsToFloatReturnTypeLoc) {
+  EXPECT_TRUE(matches(
+  "float f() { return 5.0; }",
+  functionDecl(hasName("f"), hasReturnTypeLoc(loc(asString("float"));
+}
+
+TEST(HasReturnTypeLoc, BindsToVoidReturnTypeLoc) {
+  EXPECT_TRUE(matches(
+  "void f() {}",
+  functionDecl(hasName("f"), hasReturnTypeLoc(loc(asString("void"));
+}
+
+TEST(HasReturnTypeLoc, FloatDoesNotBindToIntReturnTypeLoc) {
+  EXPECT_TRUE(notMatches(
+  "int f() { return 5; }",
+  functionDecl(hasName("f"), hasReturnTypeLoc(loc(asString("float"));
+}
+
+TEST(HasReturnTypeLoc, IntDoesNotBindToFloatReturnTypeLoc) {
+  EXPECT_TRUE(notMatches(
+  "float f() { return 5.0; }",
+  functionDecl(hasName("f"), hasReturnTypeLoc(loc(asString("int"));
+}
+
+TEST(HasPointeeLoc, BindsToAnyPointeeTypeLoc) {
+  auto matcher = varDecl(hasName("x"),
+ hasTypeLoc(pointerTypeLoc(hasPointeeLoc(typeLoc();
+  EXPECT_TRUE(matches("int* x;", matcher));
+  EXPECT_TRUE(matches("float* x;", matcher));
+  EXPECT_TRUE(matches("char* x;", matcher));
+  EXPECT_TRUE(matches("void* x;", matcher));
+}
+
+TEST(HasPointeeLoc, DoesNotBindToTypeLocWithoutPointee) {
+  auto matcher = varDecl(hasName("x"),
+ hasTypeLoc(pointerTypeLoc(hasPointeeLoc(typeLoc();
+  EXPECT_TRUE(notMatches("int x;", matcher));
+  EXPECT_TRUE(notMatches("float x;", matcher));
+  EXPECT_TRUE(notMatches("char x;", matcher));
+}
+
+TEST(HasPointeeLoc, BindsToTypeLocPointingToInt) {
+  EXPECT_TRUE(
+  matches("int* x;", pointerTypeLoc(hasPointeeLoc(loc(asString("int"));
+}
+
+TEST(HasPointeeLoc, BindsToTypeLocPointingToIntPointer) {
+  EXPECT_TRUE(matches("int** x;",
+  pointerTypeLoc(hasPointeeLoc(loc(asString("int *"));
+}
+
+TEST(HasPointeeLoc, BindsToTypeLocPointingToTypeLocPointingToInt) {
+  EXPECT_TRUE(matches("int** x;", pointerTypeLoc(hasPointeeLoc(pointerTypeLoc(
+  hasPointeeLoc(loc(asString("int";
+}
+
+TEST(HasPointeeLoc, BindsToTypeLocPointingToFloat) {
+  EXPECT_TRUE(matches("float* x;",
+  pointerTypeLoc(hasPointeeLoc(loc(asString("float"));
+}
+
+TEST(HasPointeeLoc, IntPointeeDoesNotBindToTypeLocPointingToFloat) {
+  EXPECT_TRUE(notMatches("float* x;",
+ pointerTypeLoc(hasPointeeLoc(loc(asString("int"));
+}
+
+TEST(HasPointeeLoc, 

[PATCH] D111242: Add `TypeLoc`-related matchers.

2021-10-06 Thread James King via Phabricator via cfe-commits
jcking1034 marked an inline comment as not done.
jcking1034 added inline comments.



Comment at: clang/include/clang/ASTMatchers/ASTMatchers.h:6358
+/// \code
+///   int* x = 0;
+/// \endcode

ymandel wrote:
> I think you need a const here (to the right) to be considered a qualified 
> type loc.
I've decided to use a different example to be a bit clearer.



Comment at: clang/include/clang/ASTMatchers/ASTMatchers.h:6400
+/// pointerTypeLoc(hasPointeeLoc(loc(asString("int"
+///   matches `int*`.
+AST_MATCHER_P(PointerTypeLoc, hasPointeeLoc, TypeLocMatcher, PointeeMatcher) {

ymandel wrote:
> I think `int` not `int*`?
I think this should be correct. If we were to look at `int** x`, 
`pointerTypeLoc(hasPointeeLoc(pointerTypeLoc(hasPointeeLoc(loc(asString("int"))`
 will match the whole `TypeLoc` and 
`pointerTypeLoc(hasPointeeLoc(loc(asString("int"` will match `int*`.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D111242

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


[PATCH] D111242: Add `TypeLoc`-related matchers.

2021-10-06 Thread James King via Phabricator via cfe-commits
jcking1034 created this revision.
jcking1034 added reviewers: ymandel, tdl-g.
jcking1034 requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Contributes several matchers that involve `TypeLoc`s.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D111242

Files:
  clang/include/clang/ASTMatchers/ASTMatchers.h
  clang/lib/ASTMatchers/ASTMatchersInternal.cpp
  clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
  clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp

Index: clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
===
--- clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
+++ clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
@@ -5764,5 +5764,425 @@
  IsPlacementNew));
 }
 
+TEST(HasUnqualifiedLoc, BindsToConstIntVarDecl) {
+  EXPECT_TRUE(matches("const int x = 0;", qualifiedTypeLoc(hasUnqualifiedLoc(
+  loc(asString("int"));
+}
+
+TEST(HasUnqualifiedLoc, BindsToVolatileIntVarDecl) {
+  EXPECT_TRUE(matches("volatile int x = 0;", qualifiedTypeLoc(hasUnqualifiedLoc(
+ loc(asString("int"));
+}
+
+TEST(HasUnqualifiedLoc, BindsToConstVolatileIntPointerVarDecl) {
+  EXPECT_TRUE(
+  matches("const volatile int* x = 0;",
+  qualifiedTypeLoc(hasUnqualifiedLoc(loc(asString("int"));
+}
+
+TEST(HasUnqualifiedLoc, BindsToConstIntFunctionDecl) {
+  EXPECT_TRUE(
+  matches("const int f() { return 5; }",
+  qualifiedTypeLoc(hasUnqualifiedLoc(loc(asString("int"));
+}
+
+TEST(HasUnqualifiedLoc, FloatBindsToConstFloatVarDecl) {
+  EXPECT_TRUE(matches("const float x = 0;", qualifiedTypeLoc(hasUnqualifiedLoc(
+loc(asString("float"));
+}
+
+TEST(HasUnqualifiedLoc, FloatDoesNotBindToIntVarDecl) {
+  EXPECT_TRUE(notMatches("int x = 0;", qualifiedTypeLoc(hasUnqualifiedLoc(
+   loc(asString("float"));
+}
+
+TEST(HasUnqualifiedLoc, FloatDoesNotBindToConstIntVarDecl) {
+  EXPECT_TRUE(notMatches("const int x = 0;", qualifiedTypeLoc(hasUnqualifiedLoc(
+ loc(asString("float"));
+}
+
+TEST(HasReturnTypeLoc, BindsToIntReturnTypeLoc) {
+  EXPECT_TRUE(matches(
+  "int f() { return 5; }",
+  functionDecl(hasName("f"), hasReturnTypeLoc(loc(asString("int"));
+}
+
+TEST(HasReturnTypeLoc, BindsToFloatReturnTypeLoc) {
+  EXPECT_TRUE(matches(
+  "float f() { return 5.0; }",
+  functionDecl(hasName("f"), hasReturnTypeLoc(loc(asString("float"));
+}
+
+TEST(HasReturnTypeLoc, BindsToVoidReturnTypeLoc) {
+  EXPECT_TRUE(matches(
+  "void f() {}",
+  functionDecl(hasName("f"), hasReturnTypeLoc(loc(asString("void"));
+}
+
+TEST(HasReturnTypeLoc, FloatDoesNotBindToIntReturnTypeLoc) {
+  EXPECT_TRUE(notMatches(
+  "int f() { return 5; }",
+  functionDecl(hasName("f"), hasReturnTypeLoc(loc(asString("float"));
+}
+
+TEST(HasReturnTypeLoc, IntDoesNotBindToFloatReturnTypeLoc) {
+  EXPECT_TRUE(notMatches(
+  "float f() { return 5.0; }",
+  functionDecl(hasName("f"), hasReturnTypeLoc(loc(asString("int"));
+}
+
+TEST(HasPointeeLoc, BindsToAnyPointeeTypeLoc) {
+  auto matcher = varDecl(hasName("x"),
+ hasTypeLoc(pointerTypeLoc(hasPointeeLoc(typeLoc();
+  EXPECT_TRUE(matches("int* x;", matcher));
+  EXPECT_TRUE(matches("float* x;", matcher));
+  EXPECT_TRUE(matches("char* x;", matcher));
+  EXPECT_TRUE(matches("void* x;", matcher));
+}
+
+TEST(HasPointeeLoc, DoesNotBindToTypeLocWithoutPointee) {
+  auto matcher = varDecl(hasName("x"),
+ hasTypeLoc(pointerTypeLoc(hasPointeeLoc(typeLoc();
+  EXPECT_TRUE(notMatches("int x;", matcher));
+  EXPECT_TRUE(notMatches("float x;", matcher));
+  EXPECT_TRUE(notMatches("char x;", matcher));
+}
+
+TEST(HasPointeeLoc, BindsToTypeLocPointingToInt) {
+  EXPECT_TRUE(
+  matches("int* x;", pointerTypeLoc(hasPointeeLoc(loc(asString("int"));
+}
+
+TEST(HasPointeeLoc, BindsToTypeLocPointingToIntPointer) {
+  EXPECT_TRUE(matches("int** x;",
+  pointerTypeLoc(hasPointeeLoc(loc(asString("int *"));
+}
+
+TEST(HasPointeeLoc, BindsToTypeLocPointingToTypeLocPointingToInt) {
+  EXPECT_TRUE(matches("int** x;", pointerTypeLoc(hasPointeeLoc(pointerTypeLoc(
+  hasPointeeLoc(loc(asString("int";
+}
+
+TEST(HasPointeeLoc, BindsToTypeLocPointingToFloat) {
+  EXPECT_TRUE(matches("float* x;",
+  pointerTypeLoc(hasPointeeLoc(loc(asString("float"));
+}
+
+TEST(HasPointeeLoc, IntPointeeDoesNotBindToTypeLocPointingToFloat) {
+  EXPECT_TRUE(notMatches("float* x;",
+ pointerTypeLoc(hasPointeeLoc(loc(asString("int"));
+}
+
+TEST(HasPointeeLoc, 

[PATCH] D110586: Update `DynTypedNode` to support the conversion of `TypeLoc`s.

2021-10-04 Thread James King via Phabricator via cfe-commits
jcking1034 updated this revision to Diff 376944.
jcking1034 added a comment.

Fix pointer style


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D110586

Files:
  clang/include/clang/AST/ASTTypeTraits.h
  clang/lib/AST/ASTTypeTraits.cpp
  clang/unittests/AST/ASTTypeTraitsTest.cpp

Index: clang/unittests/AST/ASTTypeTraitsTest.cpp
===
--- clang/unittests/AST/ASTTypeTraitsTest.cpp
+++ clang/unittests/AST/ASTTypeTraitsTest.cpp
@@ -199,5 +199,41 @@
   EXPECT_FALSE(Node < Node);
 }
 
+TEST(DynTypedNode, TypeLoc) {
+  std::string code = R"cc(void example() { int abc; })cc";
+  auto AST = clang::tooling::buildASTFromCode(code);
+  auto matches =
+  match(traverse(TK_AsIs,
+ varDecl(hasName("abc"), hasTypeLoc(typeLoc().bind("tl",
+AST->getASTContext());
+  EXPECT_EQ(matches.size(), 1u);
+
+  const auto  = *matches[0].getNodeAs("tl");
+  DynTypedNode Node = DynTypedNode::create(tl);
+  EXPECT_TRUE(Node == Node);
+  EXPECT_FALSE(Node < Node);
+}
+
+TEST(DynTypedNode, PointerTypeLoc) {
+  std::string code = R"cc(void example() { int *abc; })cc";
+  auto AST = clang::tooling::buildASTFromCode(code);
+  auto matches =
+  match(traverse(TK_AsIs, varDecl(hasName("abc"),
+  hasTypeLoc(typeLoc().bind("ptl",
+AST->getASTContext());
+  EXPECT_EQ(matches.size(), 1u);
+
+  const auto  = *matches[0].getNodeAs("ptl");
+  DynTypedNode TypeLocNode = DynTypedNode::create(tl);
+  EXPECT_TRUE(TypeLocNode == TypeLocNode);
+  EXPECT_FALSE(TypeLocNode < TypeLocNode);
+
+  const auto  = *matches[0].getNodeAs("ptl");
+  EXPECT_EQ(, );
+  DynTypedNode PointerTypeLocNode = DynTypedNode::create(ptl);
+  EXPECT_TRUE(PointerTypeLocNode == PointerTypeLocNode);
+  EXPECT_FALSE(PointerTypeLocNode < PointerTypeLocNode);
+}
+
 } // namespace
 }  // namespace clang
Index: clang/lib/AST/ASTTypeTraits.cpp
===
--- clang/lib/AST/ASTTypeTraits.cpp
+++ clang/lib/AST/ASTTypeTraits.cpp
@@ -18,6 +18,7 @@
 #include "clang/AST/DeclCXX.h"
 #include "clang/AST/NestedNameSpecifier.h"
 #include "clang/AST/OpenMPClause.h"
+#include "clang/AST/TypeLoc.h"
 
 using namespace clang;
 
@@ -28,6 +29,8 @@
 {NKI_None, "TemplateName"},
 {NKI_None, "NestedNameSpecifierLoc"},
 {NKI_None, "QualType"},
+#define TYPELOC(CLASS, PARENT) {NKI_##PARENT, #CLASS "TypeLoc"},
+#include "clang/AST/TypeLocNodes.def"
 {NKI_None, "TypeLoc"},
 {NKI_None, "CXXBaseSpecifier"},
 {NKI_None, "CXXCtorInitializer"},
@@ -127,6 +130,17 @@
   llvm_unreachable("invalid type kind");
  }
 
+ ASTNodeKind ASTNodeKind::getFromNode(const TypeLoc ) {
+   switch (T.getTypeLocClass()) {
+#define ABSTRACT_TYPELOC(CLASS, PARENT)
+#define TYPELOC(CLASS, PARENT) \
+  case TypeLoc::CLASS: \
+return ASTNodeKind(NKI_##CLASS##TypeLoc);
+#include "clang/AST/TypeLocNodes.def"
+   }
+   llvm_unreachable("invalid typeloc kind");
+ }
+
 ASTNodeKind ASTNodeKind::getFromNode(const OMPClause ) {
   switch (C.getClauseKind()) {
 #define GEN_CLANG_CLAUSE_CLASS
Index: clang/include/clang/AST/ASTTypeTraits.h
===
--- clang/include/clang/AST/ASTTypeTraits.h
+++ clang/include/clang/AST/ASTTypeTraits.h
@@ -63,6 +63,7 @@
   static ASTNodeKind getFromNode(const Decl );
   static ASTNodeKind getFromNode(const Stmt );
   static ASTNodeKind getFromNode(const Type );
+  static ASTNodeKind getFromNode(const TypeLoc );
   static ASTNodeKind getFromNode(const OMPClause );
   static ASTNodeKind getFromNode(const Attr );
   /// \}
@@ -133,6 +134,8 @@
 NKI_TemplateName,
 NKI_NestedNameSpecifierLoc,
 NKI_QualType,
+#define TYPELOC(CLASS, PARENT) NKI_##CLASS##TypeLoc,
+#include "clang/AST/TypeLocNodes.def"
 NKI_TypeLoc,
 NKI_LastKindWithoutPointerIdentity = NKI_TypeLoc,
 NKI_CXXBaseSpecifier,
@@ -198,6 +201,8 @@
 KIND_TO_KIND_ID(NestedNameSpecifier)
 KIND_TO_KIND_ID(NestedNameSpecifierLoc)
 KIND_TO_KIND_ID(QualType)
+#define TYPELOC(CLASS, PARENT) KIND_TO_KIND_ID(CLASS##TypeLoc)
+#include "clang/AST/TypeLocNodes.def"
 KIND_TO_KIND_ID(TypeLoc)
 KIND_TO_KIND_ID(Decl)
 KIND_TO_KIND_ID(Stmt)
@@ -304,7 +309,7 @@
   return getUnchecked().getAsOpaquePtr() <
  Other.getUnchecked().getAsOpaquePtr();
 
-if (ASTNodeKind::getFromNodeKind().isSame(NodeKind)) {
+if (ASTNodeKind::getFromNodeKind().isBaseOf(NodeKind)) {
   auto TLA = getUnchecked();
   auto TLB = Other.getUnchecked();
   return std::make_pair(TLA.getType().getAsOpaquePtr(),
@@ -336,7 +341,7 @@
 if (ASTNodeKind::getFromNodeKind().isSame(NodeKind))
   return getUnchecked() == Other.getUnchecked();
 
-if 

[PATCH] D110586: Update `DynTypedNode` to support the conversion of `TypeLoc`s.

2021-10-04 Thread James King via Phabricator via cfe-commits
jcking1034 updated this revision to Diff 376939.
jcking1034 added a comment.

Include additional expectation in unit test


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D110586

Files:
  clang/include/clang/AST/ASTTypeTraits.h
  clang/lib/AST/ASTTypeTraits.cpp
  clang/unittests/AST/ASTTypeTraitsTest.cpp

Index: clang/unittests/AST/ASTTypeTraitsTest.cpp
===
--- clang/unittests/AST/ASTTypeTraitsTest.cpp
+++ clang/unittests/AST/ASTTypeTraitsTest.cpp
@@ -199,5 +199,41 @@
   EXPECT_FALSE(Node < Node);
 }
 
+TEST(DynTypedNode, TypeLoc) {
+  std::string code = R"cc(void example() { int abc; })cc";
+  auto AST = clang::tooling::buildASTFromCode(code);
+  auto matches =
+  match(traverse(TK_AsIs,
+ varDecl(hasName("abc"), hasTypeLoc(typeLoc().bind("tl",
+AST->getASTContext());
+  EXPECT_EQ(matches.size(), 1u);
+
+  const auto  = *matches[0].getNodeAs("tl");
+  DynTypedNode Node = DynTypedNode::create(tl);
+  EXPECT_TRUE(Node == Node);
+  EXPECT_FALSE(Node < Node);
+}
+
+TEST(DynTypedNode, PointerTypeLoc) {
+  std::string code = R"cc(void example() { int* abc; })cc";
+  auto AST = clang::tooling::buildASTFromCode(code);
+  auto matches =
+  match(traverse(TK_AsIs, varDecl(hasName("abc"),
+  hasTypeLoc(typeLoc().bind("ptl",
+AST->getASTContext());
+  EXPECT_EQ(matches.size(), 1u);
+
+  const auto  = *matches[0].getNodeAs("ptl");
+  DynTypedNode TypeLocNode = DynTypedNode::create(tl);
+  EXPECT_TRUE(TypeLocNode == TypeLocNode);
+  EXPECT_FALSE(TypeLocNode < TypeLocNode);
+
+  const auto  = *matches[0].getNodeAs("ptl");
+  EXPECT_EQ(, );
+  DynTypedNode PointerTypeLocNode = DynTypedNode::create(ptl);
+  EXPECT_TRUE(PointerTypeLocNode == PointerTypeLocNode);
+  EXPECT_FALSE(PointerTypeLocNode < PointerTypeLocNode);
+}
+
 } // namespace
 }  // namespace clang
Index: clang/lib/AST/ASTTypeTraits.cpp
===
--- clang/lib/AST/ASTTypeTraits.cpp
+++ clang/lib/AST/ASTTypeTraits.cpp
@@ -18,6 +18,7 @@
 #include "clang/AST/DeclCXX.h"
 #include "clang/AST/NestedNameSpecifier.h"
 #include "clang/AST/OpenMPClause.h"
+#include "clang/AST/TypeLoc.h"
 
 using namespace clang;
 
@@ -28,6 +29,8 @@
 {NKI_None, "TemplateName"},
 {NKI_None, "NestedNameSpecifierLoc"},
 {NKI_None, "QualType"},
+#define TYPELOC(CLASS, PARENT) {NKI_##PARENT, #CLASS "TypeLoc"},
+#include "clang/AST/TypeLocNodes.def"
 {NKI_None, "TypeLoc"},
 {NKI_None, "CXXBaseSpecifier"},
 {NKI_None, "CXXCtorInitializer"},
@@ -127,6 +130,17 @@
   llvm_unreachable("invalid type kind");
  }
 
+ ASTNodeKind ASTNodeKind::getFromNode(const TypeLoc ) {
+   switch (T.getTypeLocClass()) {
+#define ABSTRACT_TYPELOC(CLASS, PARENT)
+#define TYPELOC(CLASS, PARENT) \
+  case TypeLoc::CLASS: \
+return ASTNodeKind(NKI_##CLASS##TypeLoc);
+#include "clang/AST/TypeLocNodes.def"
+   }
+   llvm_unreachable("invalid typeloc kind");
+ }
+
 ASTNodeKind ASTNodeKind::getFromNode(const OMPClause ) {
   switch (C.getClauseKind()) {
 #define GEN_CLANG_CLAUSE_CLASS
Index: clang/include/clang/AST/ASTTypeTraits.h
===
--- clang/include/clang/AST/ASTTypeTraits.h
+++ clang/include/clang/AST/ASTTypeTraits.h
@@ -63,6 +63,7 @@
   static ASTNodeKind getFromNode(const Decl );
   static ASTNodeKind getFromNode(const Stmt );
   static ASTNodeKind getFromNode(const Type );
+  static ASTNodeKind getFromNode(const TypeLoc );
   static ASTNodeKind getFromNode(const OMPClause );
   static ASTNodeKind getFromNode(const Attr );
   /// \}
@@ -133,6 +134,8 @@
 NKI_TemplateName,
 NKI_NestedNameSpecifierLoc,
 NKI_QualType,
+#define TYPELOC(CLASS, PARENT) NKI_##CLASS##TypeLoc,
+#include "clang/AST/TypeLocNodes.def"
 NKI_TypeLoc,
 NKI_LastKindWithoutPointerIdentity = NKI_TypeLoc,
 NKI_CXXBaseSpecifier,
@@ -198,6 +201,8 @@
 KIND_TO_KIND_ID(NestedNameSpecifier)
 KIND_TO_KIND_ID(NestedNameSpecifierLoc)
 KIND_TO_KIND_ID(QualType)
+#define TYPELOC(CLASS, PARENT) KIND_TO_KIND_ID(CLASS##TypeLoc)
+#include "clang/AST/TypeLocNodes.def"
 KIND_TO_KIND_ID(TypeLoc)
 KIND_TO_KIND_ID(Decl)
 KIND_TO_KIND_ID(Stmt)
@@ -304,7 +309,7 @@
   return getUnchecked().getAsOpaquePtr() <
  Other.getUnchecked().getAsOpaquePtr();
 
-if (ASTNodeKind::getFromNodeKind().isSame(NodeKind)) {
+if (ASTNodeKind::getFromNodeKind().isBaseOf(NodeKind)) {
   auto TLA = getUnchecked();
   auto TLB = Other.getUnchecked();
   return std::make_pair(TLA.getType().getAsOpaquePtr(),
@@ -336,7 +341,7 @@
 if (ASTNodeKind::getFromNodeKind().isSame(NodeKind))
   return getUnchecked() == Other.getUnchecked();
 
-if 

[PATCH] D110586: Update `DynTypedNode` to support the conversion of `TypeLoc`s.

2021-10-04 Thread James King via Phabricator via cfe-commits
jcking1034 marked an inline comment as not done.
jcking1034 added inline comments.



Comment at: clang/unittests/AST/ASTTypeTraitsTest.cpp:212
+  DynTypedNode Node = DynTypedNode::create(tl);
+  EXPECT_TRUE(Node == Node);
+  EXPECT_FALSE(Node < Node);

sbenza wrote:
> I don't know what we are trying to check with this self equivalence.
> Did you mean `Node == tl`?
These two `EXPECT`s are meant to ensure that the overloaded equality and 
less-than operators do function correctly when handling nodes of the `TypeLoc` 
family. In both cases, there is behavior specifically for these nodes, and I've 
made minor updates to both (changing `isSame` to `isBaseOf`). Additionally, 
this may give a little more confidence that template specialization functioned 
correctly. I will note that the `QualType` test performs a similar set of 
checks, presumably for similar reasoning.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D110586

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


[PATCH] D110586: Update `DynTypedNode` to support the conversion of `TypeLoc`s.

2021-10-04 Thread James King via Phabricator via cfe-commits
jcking1034 updated this revision to Diff 376901.
jcking1034 marked an inline comment as done.
jcking1034 added a comment.

Update unit test to better exercise `getNodeAs`


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D110586

Files:
  clang/include/clang/AST/ASTTypeTraits.h
  clang/lib/AST/ASTTypeTraits.cpp
  clang/unittests/AST/ASTTypeTraitsTest.cpp

Index: clang/unittests/AST/ASTTypeTraitsTest.cpp
===
--- clang/unittests/AST/ASTTypeTraitsTest.cpp
+++ clang/unittests/AST/ASTTypeTraitsTest.cpp
@@ -199,5 +199,40 @@
   EXPECT_FALSE(Node < Node);
 }
 
+TEST(DynTypedNode, TypeLoc) {
+  std::string code = R"cc(void example() { int abc; })cc";
+  auto AST = clang::tooling::buildASTFromCode(code);
+  auto matches =
+  match(traverse(TK_AsIs,
+ varDecl(hasName("abc"), hasTypeLoc(typeLoc().bind("tl",
+AST->getASTContext());
+  EXPECT_EQ(matches.size(), 1u);
+
+  const auto  = *matches[0].getNodeAs("tl");
+  DynTypedNode Node = DynTypedNode::create(tl);
+  EXPECT_TRUE(Node == Node);
+  EXPECT_FALSE(Node < Node);
+}
+
+TEST(DynTypedNode, PointerTypeLoc) {
+  std::string code = R"cc(void example() { int* abc; })cc";
+  auto AST = clang::tooling::buildASTFromCode(code);
+  auto matches =
+  match(traverse(TK_AsIs, varDecl(hasName("abc"),
+  hasTypeLoc(typeLoc().bind("ptl",
+AST->getASTContext());
+  EXPECT_EQ(matches.size(), 1u);
+
+  const auto  = *matches[0].getNodeAs("ptl");
+  DynTypedNode TypeLocNode = DynTypedNode::create(tl);
+  EXPECT_TRUE(TypeLocNode == TypeLocNode);
+  EXPECT_FALSE(TypeLocNode < TypeLocNode);
+
+  const auto  = *matches[0].getNodeAs("ptl");
+  DynTypedNode PointerTypeLocNode = DynTypedNode::create(ptl);
+  EXPECT_TRUE(PointerTypeLocNode == PointerTypeLocNode);
+  EXPECT_FALSE(PointerTypeLocNode < PointerTypeLocNode);
+}
+
 } // namespace
 }  // namespace clang
Index: clang/lib/AST/ASTTypeTraits.cpp
===
--- clang/lib/AST/ASTTypeTraits.cpp
+++ clang/lib/AST/ASTTypeTraits.cpp
@@ -18,6 +18,7 @@
 #include "clang/AST/DeclCXX.h"
 #include "clang/AST/NestedNameSpecifier.h"
 #include "clang/AST/OpenMPClause.h"
+#include "clang/AST/TypeLoc.h"
 
 using namespace clang;
 
@@ -28,6 +29,8 @@
 {NKI_None, "TemplateName"},
 {NKI_None, "NestedNameSpecifierLoc"},
 {NKI_None, "QualType"},
+#define TYPELOC(CLASS, PARENT) {NKI_##PARENT, #CLASS "TypeLoc"},
+#include "clang/AST/TypeLocNodes.def"
 {NKI_None, "TypeLoc"},
 {NKI_None, "CXXBaseSpecifier"},
 {NKI_None, "CXXCtorInitializer"},
@@ -127,6 +130,17 @@
   llvm_unreachable("invalid type kind");
  }
 
+ ASTNodeKind ASTNodeKind::getFromNode(const TypeLoc ) {
+   switch (T.getTypeLocClass()) {
+#define ABSTRACT_TYPELOC(CLASS, PARENT)
+#define TYPELOC(CLASS, PARENT) \
+  case TypeLoc::CLASS: \
+return ASTNodeKind(NKI_##CLASS##TypeLoc);
+#include "clang/AST/TypeLocNodes.def"
+   }
+   llvm_unreachable("invalid typeloc kind");
+ }
+
 ASTNodeKind ASTNodeKind::getFromNode(const OMPClause ) {
   switch (C.getClauseKind()) {
 #define GEN_CLANG_CLAUSE_CLASS
Index: clang/include/clang/AST/ASTTypeTraits.h
===
--- clang/include/clang/AST/ASTTypeTraits.h
+++ clang/include/clang/AST/ASTTypeTraits.h
@@ -63,6 +63,7 @@
   static ASTNodeKind getFromNode(const Decl );
   static ASTNodeKind getFromNode(const Stmt );
   static ASTNodeKind getFromNode(const Type );
+  static ASTNodeKind getFromNode(const TypeLoc );
   static ASTNodeKind getFromNode(const OMPClause );
   static ASTNodeKind getFromNode(const Attr );
   /// \}
@@ -133,6 +134,8 @@
 NKI_TemplateName,
 NKI_NestedNameSpecifierLoc,
 NKI_QualType,
+#define TYPELOC(CLASS, PARENT) NKI_##CLASS##TypeLoc,
+#include "clang/AST/TypeLocNodes.def"
 NKI_TypeLoc,
 NKI_LastKindWithoutPointerIdentity = NKI_TypeLoc,
 NKI_CXXBaseSpecifier,
@@ -198,6 +201,8 @@
 KIND_TO_KIND_ID(NestedNameSpecifier)
 KIND_TO_KIND_ID(NestedNameSpecifierLoc)
 KIND_TO_KIND_ID(QualType)
+#define TYPELOC(CLASS, PARENT) KIND_TO_KIND_ID(CLASS##TypeLoc)
+#include "clang/AST/TypeLocNodes.def"
 KIND_TO_KIND_ID(TypeLoc)
 KIND_TO_KIND_ID(Decl)
 KIND_TO_KIND_ID(Stmt)
@@ -304,7 +309,7 @@
   return getUnchecked().getAsOpaquePtr() <
  Other.getUnchecked().getAsOpaquePtr();
 
-if (ASTNodeKind::getFromNodeKind().isSame(NodeKind)) {
+if (ASTNodeKind::getFromNodeKind().isBaseOf(NodeKind)) {
   auto TLA = getUnchecked();
   auto TLB = Other.getUnchecked();
   return std::make_pair(TLA.getType().getAsOpaquePtr(),
@@ -336,7 +341,7 @@
 if (ASTNodeKind::getFromNodeKind().isSame(NodeKind))
   return getUnchecked() == 

[PATCH] D110586: Update `DynTypedNode` to support the conversion of `TypeLoc`s.

2021-10-01 Thread James King via Phabricator via cfe-commits
jcking1034 updated this revision to Diff 376610.
jcking1034 added a comment.

Clean up unit tests.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D110586

Files:
  clang/include/clang/AST/ASTTypeTraits.h
  clang/lib/AST/ASTTypeTraits.cpp
  clang/unittests/AST/ASTTypeTraitsTest.cpp

Index: clang/unittests/AST/ASTTypeTraitsTest.cpp
===
--- clang/unittests/AST/ASTTypeTraitsTest.cpp
+++ clang/unittests/AST/ASTTypeTraitsTest.cpp
@@ -199,5 +199,34 @@
   EXPECT_FALSE(Node < Node);
 }
 
+TEST(DynTypedNode, TypeLoc) {
+  std::string code = R"cc(void example() { int abc; })cc";
+  auto AST = clang::tooling::buildASTFromCode(code);
+  auto matches =
+  match(traverse(TK_AsIs,
+ varDecl(hasName("abc"), hasTypeLoc(typeLoc().bind("tl",
+AST->getASTContext());
+  EXPECT_EQ(matches.size(), 1u);
+  const auto  = *matches[0].getNodeAs("tl");
+  DynTypedNode Node = DynTypedNode::create(tl);
+  EXPECT_TRUE(Node == Node);
+  EXPECT_FALSE(Node < Node);
+}
+
+TEST(DynTypedNode, PointerTypeLoc) {
+  std::string code = R"cc(void example() { int* abc; })cc";
+  auto AST = clang::tooling::buildASTFromCode(code);
+  auto matches =
+  match(traverse(TK_AsIs, varDecl(hasName("abc"),
+  hasTypeLoc(typeLoc().bind("ptl",
+AST->getASTContext());
+  EXPECT_EQ(matches.size(), 1u);
+  const auto ptl =
+  matches[0].getNodeAs("ptl")->castAs();
+  DynTypedNode Node = DynTypedNode::create(ptl);
+  EXPECT_TRUE(Node == Node);
+  EXPECT_FALSE(Node < Node);
+}
+
 } // namespace
 }  // namespace clang
Index: clang/lib/AST/ASTTypeTraits.cpp
===
--- clang/lib/AST/ASTTypeTraits.cpp
+++ clang/lib/AST/ASTTypeTraits.cpp
@@ -18,6 +18,7 @@
 #include "clang/AST/DeclCXX.h"
 #include "clang/AST/NestedNameSpecifier.h"
 #include "clang/AST/OpenMPClause.h"
+#include "clang/AST/TypeLoc.h"
 
 using namespace clang;
 
@@ -28,6 +29,8 @@
 {NKI_None, "TemplateName"},
 {NKI_None, "NestedNameSpecifierLoc"},
 {NKI_None, "QualType"},
+#define TYPELOC(CLASS, PARENT) {NKI_##PARENT, #CLASS "TypeLoc"},
+#include "clang/AST/TypeLocNodes.def"
 {NKI_None, "TypeLoc"},
 {NKI_None, "CXXBaseSpecifier"},
 {NKI_None, "CXXCtorInitializer"},
@@ -127,6 +130,17 @@
   llvm_unreachable("invalid type kind");
  }
 
+ ASTNodeKind ASTNodeKind::getFromNode(const TypeLoc ) {
+   switch (T.getTypeLocClass()) {
+#define ABSTRACT_TYPELOC(CLASS, PARENT)
+#define TYPELOC(CLASS, PARENT) \
+  case TypeLoc::CLASS: \
+return ASTNodeKind(NKI_##CLASS##TypeLoc);
+#include "clang/AST/TypeLocNodes.def"
+   }
+   llvm_unreachable("invalid typeloc kind");
+ }
+
 ASTNodeKind ASTNodeKind::getFromNode(const OMPClause ) {
   switch (C.getClauseKind()) {
 #define GEN_CLANG_CLAUSE_CLASS
Index: clang/include/clang/AST/ASTTypeTraits.h
===
--- clang/include/clang/AST/ASTTypeTraits.h
+++ clang/include/clang/AST/ASTTypeTraits.h
@@ -63,6 +63,7 @@
   static ASTNodeKind getFromNode(const Decl );
   static ASTNodeKind getFromNode(const Stmt );
   static ASTNodeKind getFromNode(const Type );
+  static ASTNodeKind getFromNode(const TypeLoc );
   static ASTNodeKind getFromNode(const OMPClause );
   static ASTNodeKind getFromNode(const Attr );
   /// \}
@@ -133,6 +134,8 @@
 NKI_TemplateName,
 NKI_NestedNameSpecifierLoc,
 NKI_QualType,
+#define TYPELOC(CLASS, PARENT) NKI_##CLASS##TypeLoc,
+#include "clang/AST/TypeLocNodes.def"
 NKI_TypeLoc,
 NKI_LastKindWithoutPointerIdentity = NKI_TypeLoc,
 NKI_CXXBaseSpecifier,
@@ -198,6 +201,8 @@
 KIND_TO_KIND_ID(NestedNameSpecifier)
 KIND_TO_KIND_ID(NestedNameSpecifierLoc)
 KIND_TO_KIND_ID(QualType)
+#define TYPELOC(CLASS, PARENT) KIND_TO_KIND_ID(CLASS##TypeLoc)
+#include "clang/AST/TypeLocNodes.def"
 KIND_TO_KIND_ID(TypeLoc)
 KIND_TO_KIND_ID(Decl)
 KIND_TO_KIND_ID(Stmt)
@@ -304,7 +309,7 @@
   return getUnchecked().getAsOpaquePtr() <
  Other.getUnchecked().getAsOpaquePtr();
 
-if (ASTNodeKind::getFromNodeKind().isSame(NodeKind)) {
+if (ASTNodeKind::getFromNodeKind().isBaseOf(NodeKind)) {
   auto TLA = getUnchecked();
   auto TLB = Other.getUnchecked();
   return std::make_pair(TLA.getType().getAsOpaquePtr(),
@@ -336,7 +341,7 @@
 if (ASTNodeKind::getFromNodeKind().isSame(NodeKind))
   return getUnchecked() == Other.getUnchecked();
 
-if (ASTNodeKind::getFromNodeKind().isSame(NodeKind))
+if (ASTNodeKind::getFromNodeKind().isBaseOf(NodeKind))
   return getUnchecked() == Other.getUnchecked();
 
 if (ASTNodeKind::getFromNodeKind().isSame(NodeKind))
@@ -365,7 +370,7 @@
 }
 static unsigned getHashValue(const 

[PATCH] D110586: Update `DynTypedNode` to support the conversion of `TypeLoc`s.

2021-10-01 Thread James King via Phabricator via cfe-commits
jcking1034 updated this revision to Diff 376573.
jcking1034 marked an inline comment as done.
jcking1034 added a comment.

Fix typing for `create` and add unit tests.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D110586

Files:
  clang/include/clang/AST/ASTTypeTraits.h
  clang/lib/AST/ASTTypeTraits.cpp
  clang/unittests/AST/ASTTypeTraitsTest.cpp

Index: clang/unittests/AST/ASTTypeTraitsTest.cpp
===
--- clang/unittests/AST/ASTTypeTraitsTest.cpp
+++ clang/unittests/AST/ASTTypeTraitsTest.cpp
@@ -199,5 +199,34 @@
   EXPECT_FALSE(Node < Node);
 }
 
+TEST(DynTypedNode, TypeLoc) {
+  std::string code = R"cc(void example() { int abc; })cc";
+  auto AST = clang::tooling::buildASTFromCode(code);
+  auto  = AST->getASTContext();
+  auto matches = match(traverse(TK_AsIs, typeLoc().bind("tl")), context);
+  for (auto  : matches) {
+const auto  = *nodes.getNodeAs("tl");
+DynTypedNode Node = DynTypedNode::create(tl);
+EXPECT_TRUE(Node == Node);
+EXPECT_FALSE(Node < Node);
+  }
+}
+
+TEST(DynTypedNode, PointerTypeLoc) {
+  std::string code = R"cc(void example() { int* abc; })cc";
+  auto AST = clang::tooling::buildASTFromCode(code);
+  auto  = AST->getASTContext();
+  auto matches =
+  match(traverse(TK_AsIs, varDecl(hasName("abc"),
+  hasTypeLoc(typeLoc().bind("ptl",
+context);
+  for (auto  : matches) {
+const auto ptl = nodes.getNodeAs("ptl")->castAs();
+DynTypedNode Node = DynTypedNode::create(ptl);
+EXPECT_TRUE(Node == Node);
+EXPECT_FALSE(Node < Node);
+  }
+}
+
 } // namespace
 }  // namespace clang
Index: clang/lib/AST/ASTTypeTraits.cpp
===
--- clang/lib/AST/ASTTypeTraits.cpp
+++ clang/lib/AST/ASTTypeTraits.cpp
@@ -18,6 +18,7 @@
 #include "clang/AST/DeclCXX.h"
 #include "clang/AST/NestedNameSpecifier.h"
 #include "clang/AST/OpenMPClause.h"
+#include "clang/AST/TypeLoc.h"
 
 using namespace clang;
 
@@ -28,6 +29,8 @@
 {NKI_None, "TemplateName"},
 {NKI_None, "NestedNameSpecifierLoc"},
 {NKI_None, "QualType"},
+#define TYPELOC(CLASS, PARENT) {NKI_##PARENT, #CLASS "TypeLoc"},
+#include "clang/AST/TypeLocNodes.def"
 {NKI_None, "TypeLoc"},
 {NKI_None, "CXXBaseSpecifier"},
 {NKI_None, "CXXCtorInitializer"},
@@ -127,6 +130,17 @@
   llvm_unreachable("invalid type kind");
  }
 
+ ASTNodeKind ASTNodeKind::getFromNode(const TypeLoc ) {
+   switch (T.getTypeLocClass()) {
+#define ABSTRACT_TYPELOC(CLASS, PARENT)
+#define TYPELOC(CLASS, PARENT) \
+  case TypeLoc::CLASS: \
+return ASTNodeKind(NKI_##CLASS##TypeLoc);
+#include "clang/AST/TypeLocNodes.def"
+   }
+   llvm_unreachable("invalid typeloc kind");
+ }
+
 ASTNodeKind ASTNodeKind::getFromNode(const OMPClause ) {
   switch (C.getClauseKind()) {
 #define GEN_CLANG_CLAUSE_CLASS
Index: clang/include/clang/AST/ASTTypeTraits.h
===
--- clang/include/clang/AST/ASTTypeTraits.h
+++ clang/include/clang/AST/ASTTypeTraits.h
@@ -63,6 +63,7 @@
   static ASTNodeKind getFromNode(const Decl );
   static ASTNodeKind getFromNode(const Stmt );
   static ASTNodeKind getFromNode(const Type );
+  static ASTNodeKind getFromNode(const TypeLoc );
   static ASTNodeKind getFromNode(const OMPClause );
   static ASTNodeKind getFromNode(const Attr );
   /// \}
@@ -133,6 +134,8 @@
 NKI_TemplateName,
 NKI_NestedNameSpecifierLoc,
 NKI_QualType,
+#define TYPELOC(CLASS, PARENT) NKI_##CLASS##TypeLoc,
+#include "clang/AST/TypeLocNodes.def"
 NKI_TypeLoc,
 NKI_LastKindWithoutPointerIdentity = NKI_TypeLoc,
 NKI_CXXBaseSpecifier,
@@ -198,6 +201,8 @@
 KIND_TO_KIND_ID(NestedNameSpecifier)
 KIND_TO_KIND_ID(NestedNameSpecifierLoc)
 KIND_TO_KIND_ID(QualType)
+#define TYPELOC(CLASS, PARENT) KIND_TO_KIND_ID(CLASS##TypeLoc)
+#include "clang/AST/TypeLocNodes.def"
 KIND_TO_KIND_ID(TypeLoc)
 KIND_TO_KIND_ID(Decl)
 KIND_TO_KIND_ID(Stmt)
@@ -304,7 +309,7 @@
   return getUnchecked().getAsOpaquePtr() <
  Other.getUnchecked().getAsOpaquePtr();
 
-if (ASTNodeKind::getFromNodeKind().isSame(NodeKind)) {
+if (ASTNodeKind::getFromNodeKind().isBaseOf(NodeKind)) {
   auto TLA = getUnchecked();
   auto TLB = Other.getUnchecked();
   return std::make_pair(TLA.getType().getAsOpaquePtr(),
@@ -336,7 +341,7 @@
 if (ASTNodeKind::getFromNodeKind().isSame(NodeKind))
   return getUnchecked() == Other.getUnchecked();
 
-if (ASTNodeKind::getFromNodeKind().isSame(NodeKind))
+if (ASTNodeKind::getFromNodeKind().isBaseOf(NodeKind))
   return getUnchecked() == Other.getUnchecked();
 
 if (ASTNodeKind::getFromNodeKind().isSame(NodeKind))
@@ -365,7 +370,7 @@
 }
 static 

[PATCH] D110586: Update `DynTypedNode` to support the conversion of `TypeLoc`s.

2021-09-30 Thread James King via Phabricator via cfe-commits
jcking1034 marked an inline comment as done.
jcking1034 added inline comments.



Comment at: clang/include/clang/AST/ASTTypeTraits.h:472
+  assert(ASTNodeKind::getFromNodeKind().isBaseOf(NodeKind));
+  return *static_cast(reinterpret_cast(Storage));
+}

sbenza wrote:
> The create/get don't seem to match.
> We are constructing a `BaseT` object in `create()`, so this `static_cast` to 
> a derived type is UB?
> That memory does not contain a `T`.
> 
> If we instead construct a `T` in `create()`, we should be able to read it as 
> a `BaseT*` (assuming `is_pointer_interconvertible_base_of` is true)
Done, constructing a `T` instead of a `BaseT` seems to work!


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D110586

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


[PATCH] D110586: Update `DynTypedNode` to support the conversion of `TypeLoc`s.

2021-09-30 Thread James King via Phabricator via cfe-commits
jcking1034 updated this revision to Diff 376389.
jcking1034 added a comment.

Construct an object of the derived type, instead of the base type.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D110586

Files:
  clang/include/clang/AST/ASTTypeTraits.h
  clang/lib/AST/ASTTypeTraits.cpp

Index: clang/lib/AST/ASTTypeTraits.cpp
===
--- clang/lib/AST/ASTTypeTraits.cpp
+++ clang/lib/AST/ASTTypeTraits.cpp
@@ -18,6 +18,7 @@
 #include "clang/AST/DeclCXX.h"
 #include "clang/AST/NestedNameSpecifier.h"
 #include "clang/AST/OpenMPClause.h"
+#include "clang/AST/TypeLoc.h"
 
 using namespace clang;
 
@@ -28,6 +29,8 @@
 {NKI_None, "TemplateName"},
 {NKI_None, "NestedNameSpecifierLoc"},
 {NKI_None, "QualType"},
+#define TYPELOC(CLASS, PARENT) {NKI_##PARENT, #CLASS "TypeLoc"},
+#include "clang/AST/TypeLocNodes.def"
 {NKI_None, "TypeLoc"},
 {NKI_None, "CXXBaseSpecifier"},
 {NKI_None, "CXXCtorInitializer"},
@@ -127,6 +130,17 @@
   llvm_unreachable("invalid type kind");
  }
 
+ ASTNodeKind ASTNodeKind::getFromNode(const TypeLoc ) {
+   switch (T.getTypeLocClass()) {
+#define ABSTRACT_TYPELOC(CLASS, PARENT)
+#define TYPELOC(CLASS, PARENT) \
+  case TypeLoc::CLASS: \
+return ASTNodeKind(NKI_##CLASS##TypeLoc);
+#include "clang/AST/TypeLocNodes.def"
+   }
+   llvm_unreachable("invalid typeloc kind");
+ }
+
 ASTNodeKind ASTNodeKind::getFromNode(const OMPClause ) {
   switch (C.getClauseKind()) {
 #define GEN_CLANG_CLAUSE_CLASS
Index: clang/include/clang/AST/ASTTypeTraits.h
===
--- clang/include/clang/AST/ASTTypeTraits.h
+++ clang/include/clang/AST/ASTTypeTraits.h
@@ -63,6 +63,7 @@
   static ASTNodeKind getFromNode(const Decl );
   static ASTNodeKind getFromNode(const Stmt );
   static ASTNodeKind getFromNode(const Type );
+  static ASTNodeKind getFromNode(const TypeLoc );
   static ASTNodeKind getFromNode(const OMPClause );
   static ASTNodeKind getFromNode(const Attr );
   /// \}
@@ -133,6 +134,8 @@
 NKI_TemplateName,
 NKI_NestedNameSpecifierLoc,
 NKI_QualType,
+#define TYPELOC(CLASS, PARENT) NKI_##CLASS##TypeLoc,
+#include "clang/AST/TypeLocNodes.def"
 NKI_TypeLoc,
 NKI_LastKindWithoutPointerIdentity = NKI_TypeLoc,
 NKI_CXXBaseSpecifier,
@@ -198,6 +201,8 @@
 KIND_TO_KIND_ID(NestedNameSpecifier)
 KIND_TO_KIND_ID(NestedNameSpecifierLoc)
 KIND_TO_KIND_ID(QualType)
+#define TYPELOC(CLASS, PARENT) KIND_TO_KIND_ID(CLASS##TypeLoc)
+#include "clang/AST/TypeLocNodes.def"
 KIND_TO_KIND_ID(TypeLoc)
 KIND_TO_KIND_ID(Decl)
 KIND_TO_KIND_ID(Stmt)
@@ -304,7 +309,7 @@
   return getUnchecked().getAsOpaquePtr() <
  Other.getUnchecked().getAsOpaquePtr();
 
-if (ASTNodeKind::getFromNodeKind().isSame(NodeKind)) {
+if (ASTNodeKind::getFromNodeKind().isBaseOf(NodeKind)) {
   auto TLA = getUnchecked();
   auto TLB = Other.getUnchecked();
   return std::make_pair(TLA.getType().getAsOpaquePtr(),
@@ -336,7 +341,7 @@
 if (ASTNodeKind::getFromNodeKind().isSame(NodeKind))
   return getUnchecked() == Other.getUnchecked();
 
-if (ASTNodeKind::getFromNodeKind().isSame(NodeKind))
+if (ASTNodeKind::getFromNodeKind().isBaseOf(NodeKind))
   return getUnchecked() == Other.getUnchecked();
 
 if (ASTNodeKind::getFromNodeKind().isSame(NodeKind))
@@ -365,7 +370,7 @@
 }
 static unsigned getHashValue(const DynTypedNode ) {
   // FIXME: Add hashing support for the remaining types.
-  if (ASTNodeKind::getFromNodeKind().isSame(Val.NodeKind)) {
+  if (ASTNodeKind::getFromNodeKind().isBaseOf(Val.NodeKind)) {
 auto TL = Val.getUnchecked();
 return llvm::hash_combine(TL.getType().getAsOpaquePtr(),
   TL.getOpaqueData());
@@ -455,6 +460,29 @@
 }
   };
 
+  /// Converter that stores nodes by value. It must be possible to dynamically
+  /// cast the stored node within a type hierarchy without breaking (especially
+  /// through slicing).
+  template >
+  struct DynCastValueConverter {
+static const T *get(ASTNodeKind NodeKind, const void *Storage) {
+  if (ASTNodeKind::getFromNodeKind().isBaseOf(NodeKind))
+return (NodeKind, Storage);
+  return nullptr;
+}
+static const T (ASTNodeKind NodeKind, const void *Storage) {
+  assert(ASTNodeKind::getFromNodeKind().isBaseOf(NodeKind));
+  return *static_cast(reinterpret_cast(Storage));
+}
+static DynTypedNode create(const BaseT ) {
+  DynTypedNode Result;
+  Result.NodeKind = ASTNodeKind::getFromNode(Node);
+  new () T(Node);
+  return Result;
+}
+  };
+
   ASTNodeKind NodeKind;
 
   /// Stores the data of the node.
@@ -525,9 +553,10 @@
 struct DynTypedNode::BaseConverter : public 

[PATCH] D110586: Update `DynTypedNode` to support the conversion of `TypeLoc`s.

2021-09-30 Thread James King via Phabricator via cfe-commits
jcking1034 updated this revision to Diff 376302.
jcking1034 added a comment.

Restore original formatting on unchanged lines.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D110586

Files:
  clang/include/clang/AST/ASTTypeTraits.h
  clang/lib/AST/ASTTypeTraits.cpp

Index: clang/lib/AST/ASTTypeTraits.cpp
===
--- clang/lib/AST/ASTTypeTraits.cpp
+++ clang/lib/AST/ASTTypeTraits.cpp
@@ -18,6 +18,7 @@
 #include "clang/AST/DeclCXX.h"
 #include "clang/AST/NestedNameSpecifier.h"
 #include "clang/AST/OpenMPClause.h"
+#include "clang/AST/TypeLoc.h"
 
 using namespace clang;
 
@@ -28,6 +29,8 @@
 {NKI_None, "TemplateName"},
 {NKI_None, "NestedNameSpecifierLoc"},
 {NKI_None, "QualType"},
+#define TYPELOC(CLASS, PARENT) {NKI_##PARENT, #CLASS "TypeLoc"},
+#include "clang/AST/TypeLocNodes.def"
 {NKI_None, "TypeLoc"},
 {NKI_None, "CXXBaseSpecifier"},
 {NKI_None, "CXXCtorInitializer"},
@@ -127,6 +130,17 @@
   llvm_unreachable("invalid type kind");
  }
 
+ ASTNodeKind ASTNodeKind::getFromNode(const TypeLoc ) {
+   switch (T.getTypeLocClass()) {
+#define ABSTRACT_TYPELOC(CLASS, PARENT)
+#define TYPELOC(CLASS, PARENT) \
+  case TypeLoc::CLASS: \
+return ASTNodeKind(NKI_##CLASS##TypeLoc);
+#include "clang/AST/TypeLocNodes.def"
+   }
+   llvm_unreachable("invalid typeloc kind");
+ }
+
 ASTNodeKind ASTNodeKind::getFromNode(const OMPClause ) {
   switch (C.getClauseKind()) {
 #define GEN_CLANG_CLAUSE_CLASS
Index: clang/include/clang/AST/ASTTypeTraits.h
===
--- clang/include/clang/AST/ASTTypeTraits.h
+++ clang/include/clang/AST/ASTTypeTraits.h
@@ -63,6 +63,7 @@
   static ASTNodeKind getFromNode(const Decl );
   static ASTNodeKind getFromNode(const Stmt );
   static ASTNodeKind getFromNode(const Type );
+  static ASTNodeKind getFromNode(const TypeLoc );
   static ASTNodeKind getFromNode(const OMPClause );
   static ASTNodeKind getFromNode(const Attr );
   /// \}
@@ -133,6 +134,8 @@
 NKI_TemplateName,
 NKI_NestedNameSpecifierLoc,
 NKI_QualType,
+#define TYPELOC(CLASS, PARENT) NKI_##CLASS##TypeLoc,
+#include "clang/AST/TypeLocNodes.def"
 NKI_TypeLoc,
 NKI_LastKindWithoutPointerIdentity = NKI_TypeLoc,
 NKI_CXXBaseSpecifier,
@@ -198,6 +201,8 @@
 KIND_TO_KIND_ID(NestedNameSpecifier)
 KIND_TO_KIND_ID(NestedNameSpecifierLoc)
 KIND_TO_KIND_ID(QualType)
+#define TYPELOC(CLASS, PARENT) KIND_TO_KIND_ID(CLASS##TypeLoc)
+#include "clang/AST/TypeLocNodes.def"
 KIND_TO_KIND_ID(TypeLoc)
 KIND_TO_KIND_ID(Decl)
 KIND_TO_KIND_ID(Stmt)
@@ -304,7 +309,7 @@
   return getUnchecked().getAsOpaquePtr() <
  Other.getUnchecked().getAsOpaquePtr();
 
-if (ASTNodeKind::getFromNodeKind().isSame(NodeKind)) {
+if (ASTNodeKind::getFromNodeKind().isBaseOf(NodeKind)) {
   auto TLA = getUnchecked();
   auto TLB = Other.getUnchecked();
   return std::make_pair(TLA.getType().getAsOpaquePtr(),
@@ -336,7 +341,7 @@
 if (ASTNodeKind::getFromNodeKind().isSame(NodeKind))
   return getUnchecked() == Other.getUnchecked();
 
-if (ASTNodeKind::getFromNodeKind().isSame(NodeKind))
+if (ASTNodeKind::getFromNodeKind().isBaseOf(NodeKind))
   return getUnchecked() == Other.getUnchecked();
 
 if (ASTNodeKind::getFromNodeKind().isSame(NodeKind))
@@ -365,7 +370,7 @@
 }
 static unsigned getHashValue(const DynTypedNode ) {
   // FIXME: Add hashing support for the remaining types.
-  if (ASTNodeKind::getFromNodeKind().isSame(Val.NodeKind)) {
+  if (ASTNodeKind::getFromNodeKind().isBaseOf(Val.NodeKind)) {
 auto TL = Val.getUnchecked();
 return llvm::hash_combine(TL.getType().getAsOpaquePtr(),
   TL.getOpaqueData());
@@ -455,6 +460,29 @@
 }
   };
 
+  /// Converter that stores nodes by value. It must be possible to dynamically
+  /// cast the stored node within a type hierarchy without breaking (especially
+  /// through slicing).
+  template >
+  struct DynCastValueConverter {
+static const T *get(ASTNodeKind NodeKind, const void *Storage) {
+  if (ASTNodeKind::getFromNodeKind().isBaseOf(NodeKind))
+return (NodeKind, Storage);
+  return nullptr;
+}
+static const T (ASTNodeKind NodeKind, const void *Storage) {
+  assert(ASTNodeKind::getFromNodeKind().isBaseOf(NodeKind));
+  return *static_cast(reinterpret_cast(Storage));
+}
+static DynTypedNode create(const BaseT ) {
+  DynTypedNode Result;
+  Result.NodeKind = ASTNodeKind::getFromNode(Node);
+  new () BaseT(Node);
+  return Result;
+}
+  };
+
   ASTNodeKind NodeKind;
 
   /// Stores the data of the node.
@@ -525,9 +553,10 @@
 struct DynTypedNode::BaseConverter : public ValueConverter {};
 

[PATCH] D110586: Update `DynTypedNode` to support the conversion of TypeLocs.

2021-09-27 Thread James King via Phabricator via cfe-commits
jcking1034 created this revision.
jcking1034 added reviewers: ymandel, tdl-g, sbenza.
jcking1034 requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

This provides better support for TypeLocs to allow TypeLoc-related
Matchers to feature stricter typing and to avoid relying on the dynamic
casting of TypeLocs in matchers.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D110586

Files:
  clang/include/clang/AST/ASTTypeTraits.h
  clang/lib/AST/ASTTypeTraits.cpp

Index: clang/lib/AST/ASTTypeTraits.cpp
===
--- clang/lib/AST/ASTTypeTraits.cpp
+++ clang/lib/AST/ASTTypeTraits.cpp
@@ -18,6 +18,7 @@
 #include "clang/AST/DeclCXX.h"
 #include "clang/AST/NestedNameSpecifier.h"
 #include "clang/AST/OpenMPClause.h"
+#include "clang/AST/TypeLoc.h"
 
 using namespace clang;
 
@@ -28,6 +29,8 @@
 {NKI_None, "TemplateName"},
 {NKI_None, "NestedNameSpecifierLoc"},
 {NKI_None, "QualType"},
+#define TYPELOC(CLASS, PARENT) {NKI_##PARENT, #CLASS "TypeLoc"},
+#include "clang/AST/TypeLocNodes.def"
 {NKI_None, "TypeLoc"},
 {NKI_None, "CXXBaseSpecifier"},
 {NKI_None, "CXXCtorInitializer"},
@@ -127,6 +130,17 @@
   llvm_unreachable("invalid type kind");
  }
 
+ ASTNodeKind ASTNodeKind::getFromNode(const TypeLoc ) {
+   switch (T.getTypeLocClass()) {
+#define ABSTRACT_TYPELOC(CLASS, PARENT)
+#define TYPELOC(CLASS, PARENT) \
+  case TypeLoc::CLASS: \
+return ASTNodeKind(NKI_##CLASS##TypeLoc);
+#include "clang/AST/TypeLocNodes.def"
+   }
+   llvm_unreachable("invalid typeloc kind");
+ }
+
 ASTNodeKind ASTNodeKind::getFromNode(const OMPClause ) {
   switch (C.getClauseKind()) {
 #define GEN_CLANG_CLAUSE_CLASS
Index: clang/include/clang/AST/ASTTypeTraits.h
===
--- clang/include/clang/AST/ASTTypeTraits.h
+++ clang/include/clang/AST/ASTTypeTraits.h
@@ -53,8 +53,7 @@
   ASTNodeKind() : KindId(NKI_None) {}
 
   /// Construct an identifier for T.
-  template 
-  static ASTNodeKind getFromNodeKind() {
+  template  static ASTNodeKind getFromNodeKind() {
 return ASTNodeKind(KindToKindId::Id);
   }
 
@@ -63,6 +62,7 @@
   static ASTNodeKind getFromNode(const Decl );
   static ASTNodeKind getFromNode(const Stmt );
   static ASTNodeKind getFromNode(const Type );
+  static ASTNodeKind getFromNode(const TypeLoc );
   static ASTNodeKind getFromNode(const OMPClause );
   static ASTNodeKind getFromNode(const Attr );
   /// \}
@@ -133,6 +133,8 @@
 NKI_TemplateName,
 NKI_NestedNameSpecifierLoc,
 NKI_QualType,
+#define TYPELOC(CLASS, PARENT) NKI_##CLASS##TypeLoc,
+#include "clang/AST/TypeLocNodes.def"
 NKI_TypeLoc,
 NKI_LastKindWithoutPointerIdentity = NKI_TypeLoc,
 NKI_CXXBaseSpecifier,
@@ -172,8 +174,7 @@
   template  struct KindToKindId {
 static const NodeKindId Id = NKI_None;
   };
-  template 
-  struct KindToKindId : KindToKindId {};
+  template  struct KindToKindId : KindToKindId {};
 
   /// Per kind info.
   struct KindInfo {
@@ -198,6 +199,8 @@
 KIND_TO_KIND_ID(NestedNameSpecifier)
 KIND_TO_KIND_ID(NestedNameSpecifierLoc)
 KIND_TO_KIND_ID(QualType)
+#define TYPELOC(CLASS, PARENT) KIND_TO_KIND_ID(CLASS##TypeLoc)
+#include "clang/AST/TypeLocNodes.def"
 KIND_TO_KIND_ID(TypeLoc)
 KIND_TO_KIND_ID(Decl)
 KIND_TO_KIND_ID(Stmt)
@@ -238,8 +241,7 @@
 class DynTypedNode {
 public:
   /// Creates a \c DynTypedNode from \c Node.
-  template 
-  static DynTypedNode create(const T ) {
+  template  static DynTypedNode create(const T ) {
 return BaseConverter::create(Node);
   }
 
@@ -262,8 +264,7 @@
   /// Retrieve the stored node as type \c T.
   ///
   /// Similar to \c get(), but asserts that the type is what we are expecting.
-  template 
-  const T () const {
+  template  const T () const {
 return BaseConverter::getUnchecked(NodeKind, );
   }
 
@@ -304,7 +305,7 @@
   return getUnchecked().getAsOpaquePtr() <
  Other.getUnchecked().getAsOpaquePtr();
 
-if (ASTNodeKind::getFromNodeKind().isSame(NodeKind)) {
+if (ASTNodeKind::getFromNodeKind().isBaseOf(NodeKind)) {
   auto TLA = getUnchecked();
   auto TLB = Other.getUnchecked();
   return std::make_pair(TLA.getType().getAsOpaquePtr(),
@@ -336,7 +337,7 @@
 if (ASTNodeKind::getFromNodeKind().isSame(NodeKind))
   return getUnchecked() == Other.getUnchecked();
 
-if (ASTNodeKind::getFromNodeKind().isSame(NodeKind))
+if (ASTNodeKind::getFromNodeKind().isBaseOf(NodeKind))
   return getUnchecked() == Other.getUnchecked();
 
 if (ASTNodeKind::getFromNodeKind().isSame(NodeKind))
@@ -365,7 +366,7 @@
 }
 static unsigned getHashValue(const DynTypedNode ) {
   // FIXME: Add hashing support for the remaining types.
-  if (ASTNodeKind::getFromNodeKind().isSame(Val.NodeKind)) {
+  if