SilensAngelusNex updated this revision to Diff 342790.
SilensAngelusNex retitled this revision from "Make `hasTypeLoc` matcher support 
nodes of type `CXXFunctionalCastExpr` and `CXXTemporaryObjectExpr`." to "Make 
`hasTypeLoc` matcher support more node types.".
SilensAngelusNex added a comment.

Added support for node types in groups #1 and #3.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D101572

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

Index: clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
===================================================================
--- clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
+++ clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
@@ -11,6 +11,7 @@
 #include "clang/ASTMatchers/ASTMatchFinder.h"
 #include "clang/ASTMatchers/ASTMatchers.h"
 #include "clang/Tooling/Tooling.h"
+#include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/Triple.h"
 #include "llvm/Support/Host.h"
 #include "gtest/gtest.h"
@@ -375,15 +376,104 @@
                       typedefNameDecl(hasType(asString("foo")), hasName("bar"))));
 }
 
-TEST(HasTypeLoc, MatchesDeclaratorDecls) {
+TEST(HasTypeLoc, MatchesBlockDecl) {
+  EXPECT_TRUE(matchesConditionally(
+      "auto x = ^int (int a, int b) { return a + b; };",
+      blockDecl(hasTypeLoc(loc(asString("int (int, int)")))), true,
+      {"-fblocks"}));
+}
+
+TEST(HasTypeLoc, MatchesCXXBaseSpecifierAndCtorInitializer) {
+  llvm::StringRef code = R"cpp(
+  class Foo {};
+  class Bar : public Foo {
+    Bar() : Foo() {}
+  };
+  )cpp";
+
+  EXPECT_TRUE(matches(
+      code, cxxRecordDecl(hasAnyBase(hasTypeLoc(loc(asString("class Foo")))))));
+  EXPECT_TRUE(matches(
+      code, cxxCtorInitializer(hasTypeLoc(loc(asString("class Foo"))))));
+}
+
+TEST(HasTypeLoc, MatchesCXXFunctionalCastExpr) {
+  EXPECT_TRUE(matches("auto x = int(3);",
+                      cxxFunctionalCastExpr(hasTypeLoc(loc(asString("int"))))));
+}
+
+TEST(HasTypeLoc, MatchesCXXNewExpr) {
+  EXPECT_TRUE(matches("auto* x = new int(3);",
+                      cxxNewExpr(hasTypeLoc(loc(asString("int"))))));
+  EXPECT_TRUE(matches("class Foo{}; auto* x = new Foo();",
+                      cxxNewExpr(hasTypeLoc(loc(asString("class Foo"))))));
+}
+
+TEST(HasTypeLoc, MatchesCXXTemporaryObjectExpr) {
+  EXPECT_TRUE(
+      matches("struct Foo { Foo(int, int); }; auto x = Foo(1, 2);",
+              cxxTemporaryObjectExpr(hasTypeLoc(loc(asString("struct Foo"))))));
+}
+
+TEST(HasTypeLoc, MatchesCXXUnresolvedConstructExpr) {
+  EXPECT_TRUE(
+      matches("template <typename T> T make() { return T(); }",
+              cxxUnresolvedConstructExpr(hasTypeLoc(loc(asString("T"))))));
+}
+
+TEST(HasTypeLoc, MatchesClassTemplateSpecializationDecl) {
+  EXPECT_TRUE(matches(
+      "template <typename T> class Foo; template <> class Foo<int> {};",
+      classTemplateSpecializationDecl(hasTypeLoc(loc(asString("Foo<int>"))))));
+}
+
+TEST(HasTypeLoc, MatchesCompoundLiteralExpr) {
+  EXPECT_TRUE(
+      matches("int* x = (int [2]) { 0, 1 };",
+              compoundLiteralExpr(hasTypeLoc(loc(asString("int [2]"))))));
+}
+
+TEST(HasTypeLoc, MatchesDeclaratorDecl) {
   EXPECT_TRUE(matches("int x;",
                       varDecl(hasName("x"), hasTypeLoc(loc(asString("int"))))));
+  EXPECT_TRUE(matches("int x(3);",
+                      varDecl(hasName("x"), hasTypeLoc(loc(asString("int"))))));
+  EXPECT_TRUE(
+      matches("struct Foo { Foo(int, int); }; Foo x(1, 2);",
+              varDecl(hasName("x"), hasTypeLoc(loc(asString("struct Foo"))))));
 
   // Make sure we don't crash on implicit constructors.
   EXPECT_TRUE(notMatches("class X {}; X x;",
                          declaratorDecl(hasTypeLoc(loc(asString("int"))))));
 }
 
+TEST(HasTypeLoc, MatchesExplicitCastExpr) {
+  EXPECT_TRUE(matches("auto x = (int) 3;",
+                      explicitCastExpr(hasTypeLoc(loc(asString("int"))))));
+  EXPECT_TRUE(matches("auto x = static_cast<int>(3);",
+                      explicitCastExpr(hasTypeLoc(loc(asString("int"))))));
+}
+
+TEST(HasTypeLoc, MatchesObjCPropertyDecl) {
+  EXPECT_TRUE(matchesObjC(R"objc(
+      @interface Foo
+      @property int enabled;
+      @end
+    )objc",
+                          objcPropertyDecl(hasTypeLoc(loc(asString("int"))))));
+}
+
+TEST(HasTypeLoc, MatchesTemplateArgumentLoc) {
+  EXPECT_TRUE(matches("template <typename T> class Foo {}; Foo<int> x;",
+                      templateArgumentLoc(hasTypeLoc(loc(asString("int"))))));
+}
+
+TEST(HasTypeLoc, MatchesTypedefNameDecl) {
+  EXPECT_TRUE(matches("typedef int X;",
+                      typedefNameDecl(hasTypeLoc(loc(asString("int"))))));
+  EXPECT_TRUE(matches("using X = int;",
+                      typedefNameDecl(hasTypeLoc(loc(asString("int"))))));
+}
 
 TEST(Callee, MatchesDeclarations) {
   StatementMatcher CallMethodX = callExpr(callee(cxxMethodDecl(hasName("x"))));
Index: clang/include/clang/ASTMatchers/ASTMatchersInternal.h
===================================================================
--- clang/include/clang/ASTMatchers/ASTMatchersInternal.h
+++ clang/include/clang/ASTMatchers/ASTMatchersInternal.h
@@ -135,6 +135,47 @@
   return Node.getType();
 }
 
+template <typename... T> struct disjunction;
+template <typename T> struct disjunction<T> : public T {};
+template <typename Head, typename... Tail> struct disjunction<Head, Tail...> {
+  using type =
+      typename std::conditional<Head::value, Head, disjunction<Tail...>>::type;
+  static constexpr bool value = type::value;
+};
+
+template <typename... Expected> struct is_one_of {
+  template <typename T>
+  static constexpr bool value =
+      disjunction<std::is_base_of<Expected, T>...>::value;
+};
+
+/// Unifies obtaining a `TypeSourceInfo` from different node types.
+template <typename T,
+          std::enable_if_t<is_one_of<
+              CXXBaseSpecifier, CXXCtorInitializer, CXXTemporaryObjectExpr,
+              CXXUnresolvedConstructExpr, CompoundLiteralExpr, DeclaratorDecl,
+              ObjCPropertyDecl, TemplateArgumentLoc, TypedefNameDecl>::value<T>>
+              * = nullptr>
+inline TypeSourceInfo *GetTypeSourceInfo(const T &Node) {
+  return Node.getTypeSourceInfo();
+}
+template <typename T,
+          std::enable_if_t<is_one_of<CXXFunctionalCastExpr,
+                                     ExplicitCastExpr>::value<T>> * = nullptr>
+inline TypeSourceInfo *GetTypeSourceInfo(const T &Node) {
+  return Node.getTypeInfoAsWritten();
+}
+inline TypeSourceInfo *GetTypeSourceInfo(const BlockDecl &Node) {
+  return Node.getSignatureAsWritten();
+}
+inline TypeSourceInfo *GetTypeSourceInfo(const CXXNewExpr &Node) {
+  return Node.getAllocatedTypeSourceInfo();
+}
+inline TypeSourceInfo *
+GetTypeSourceInfo(const ClassTemplateSpecializationDecl &Node) {
+  return Node.getTypeAsWritten();
+}
+
 /// Unifies obtaining the FunctionProtoType pointer from both
 /// FunctionProtoType and FunctionDecl nodes..
 inline const FunctionProtoType *
Index: clang/include/clang/ASTMatchers/ASTMatchers.h
===================================================================
--- clang/include/clang/ASTMatchers/ASTMatchers.h
+++ clang/include/clang/ASTMatchers/ASTMatchers.h
@@ -3896,20 +3896,42 @@
   return false;
 }
 
-/// Matches if the type location of the declarator decl's type matches
-/// the inner matcher.
+/// Matches if the type location of a node matches the inner matcher.
 ///
-/// Given
+/// Examples:
 /// \code
 ///   int x;
 /// \endcode
 /// declaratorDecl(hasTypeLoc(loc(asString("int"))))
 ///   matches int x
-AST_MATCHER_P(DeclaratorDecl, hasTypeLoc, internal::Matcher<TypeLoc>, Inner) {
-  if (!Node.getTypeSourceInfo())
+///
+/// \code
+/// auto x = int(3);
+/// \code
+/// cxxTemporaryObjectExpr(hasTypeLoc(loc(asString("int"))))
+///   matches int(3)
+///
+/// \code
+/// struct Foo { Foo(int, int); };
+/// auto x = Foo(1, 2);
+/// \code
+/// cxxFunctionalCastExpr(hasTypeLoc(loc(asString("struct Foo"))))
+///   matches Foo(1, 2)
+AST_POLYMORPHIC_MATCHER_P(
+    hasTypeLoc,
+    AST_POLYMORPHIC_SUPPORTED_TYPES(
+        BlockDecl, CXXBaseSpecifier, CXXCtorInitializer, CXXFunctionalCastExpr,
+        CXXNewExpr, CXXTemporaryObjectExpr, CXXUnresolvedConstructExpr,
+        ClassTemplateSpecializationDecl, CompoundLiteralExpr, DeclaratorDecl,
+        ExplicitCastExpr, ObjCPropertyDecl, TemplateArgumentLoc,
+        TypedefNameDecl),
+    internal::Matcher<TypeLoc>, Inner) {
+  TypeSourceInfo *source = internal::GetTypeSourceInfo(Node);
+  if (source == nullptr) {
     // This happens for example for implicit destructors.
     return false;
-  return Inner.matches(Node.getTypeSourceInfo()->getTypeLoc(), Finder, Builder);
+  }
+  return Inner.matches(source->getTypeLoc(), Finder, Builder);
 }
 
 /// Matches if the matched type is represented by the given string.
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to