From: Etienne Bergeron Date: Fri, 13 May 2016 19:36:55 +0000 (+0000) Subject: Add an AST matcher for CastExpr kind X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=3bb611ddc858cb8c25dbd9e849bcc78c3f4b0203;p=clang Add an AST matcher for CastExpr kind Summary: This AST matcher will match a given CastExpr kind. It's an narrowing matcher on CastExpr. Reviewers: klimek, alexfh, sbenza, aaron.ballman Subscribers: Prazek, jroelofs, aaron.ballman, klimek, cfe-commits Differential Revision: http://reviews.llvm.org/D19871 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@269460 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/docs/LibASTMatchersReference.html b/docs/LibASTMatchersReference.html index 2d4b8c1999..c0b1253ba9 100644 --- a/docs/LibASTMatchersReference.html +++ b/docs/LibASTMatchersReference.html @@ -2159,6 +2159,15 @@ Example matches f(0, 0) (matcher = callExpr(argumentCountIs(2))) +Matcher<CastExpr>hasCastKindCastKind Kind +
Matches casts that has a given cast kind.
+
+Example: matches the implicit cast around 0
+(matcher = castExpr(hasCastKind(CK_NullToPointer)))
+  int *p = 0;
+
+ + Matcher<CharacterLiteral>equalsValueT Value
Matches literals that are equal to the given value.
 
diff --git a/include/clang/ASTMatchers/ASTMatchers.h b/include/clang/ASTMatchers/ASTMatchers.h
index 74206b9a5c..26ac4fd9e7 100644
--- a/include/clang/ASTMatchers/ASTMatchers.h
+++ b/include/clang/ASTMatchers/ASTMatchers.h
@@ -3551,6 +3551,17 @@ AST_POLYMORPHIC_MATCHER_P(hasSourceExpression,
           InnerMatcher.matches(*SubExpression, Finder, Builder));
 }
 
+/// \brief Matches casts that has a given cast kind.
+///
+/// Example: matches the implicit cast around \c 0
+/// (matcher = castExpr(hasCastKind(CK_NullToPointer)))
+/// \code
+///   int *p = 0;
+/// \endcode
+AST_MATCHER_P(CastExpr, hasCastKind, CastKind, Kind) {
+  return Node.getCastKind() == Kind;
+}
+
 /// \brief Matches casts whose destination type matches a given matcher.
 ///
 /// (Note: Clang's AST refers to other conversions as "casts" too, and calls
diff --git a/lib/ASTMatchers/Dynamic/Marshallers.h b/lib/ASTMatchers/Dynamic/Marshallers.h
index f28abb06f9..7b1a307026 100644
--- a/lib/ASTMatchers/Dynamic/Marshallers.h
+++ b/lib/ASTMatchers/Dynamic/Marshallers.h
@@ -96,6 +96,28 @@ public:
   }
 };
 
+template <> struct ArgTypeTraits {
+private:
+  static clang::CastKind getCastKind(llvm::StringRef AttrKind) {
+    return llvm::StringSwitch(AttrKind)
+#define CAST_OPERATION(Name) .Case( #Name, CK_##Name)
+#include "clang/AST/OperationKinds.def"
+        .Default(CK_Invalid);
+  }
+
+public:
+  static bool is(const VariantValue &Value) {
+    return Value.isString() &&  
+        getCastKind(Value.getString()) != CK_Invalid;
+  }
+  static clang::CastKind get(const VariantValue &Value) {
+    return getCastKind(Value.getString());
+  }
+  static ArgKind getKind() {
+    return ArgKind(ArgKind::AK_String);
+  }
+};
+
 /// \brief Matcher descriptor interface.
 ///
 /// Provides a \c create() method that constructs the matcher from the provided
diff --git a/lib/ASTMatchers/Dynamic/Registry.cpp b/lib/ASTMatchers/Dynamic/Registry.cpp
index e43960241d..ee271e4053 100644
--- a/lib/ASTMatchers/Dynamic/Registry.cpp
+++ b/lib/ASTMatchers/Dynamic/Registry.cpp
@@ -210,6 +210,7 @@ RegistryMaps::RegistryMaps() {
   REGISTER_MATCHER(hasBody);
   REGISTER_MATCHER(hasCanonicalType);
   REGISTER_MATCHER(hasCaseConstant);
+  REGISTER_MATCHER(hasCastKind);
   REGISTER_MATCHER(hasCondition);
   REGISTER_MATCHER(hasConditionVariableStatement);
   REGISTER_MATCHER(hasDecayedType);
diff --git a/unittests/ASTMatchers/ASTMatchersTest.cpp b/unittests/ASTMatchers/ASTMatchersTest.cpp
index 34eca9977a..0db16d692f 100644
--- a/unittests/ASTMatchers/ASTMatchersTest.cpp
+++ b/unittests/ASTMatchers/ASTMatchersTest.cpp
@@ -3485,6 +3485,15 @@ TEST(CastExpression, DoesNotMatchNonCasts) {
   EXPECT_TRUE(notMatches("int i = 0;", castExpr()));
 }
 
+TEST(CastExpression, HasCastKind) {
+  EXPECT_TRUE(matches("char *p = 0;",
+              castExpr(hasCastKind(CK_NullToPointer))));
+  EXPECT_TRUE(notMatches("char *p = 0;",
+              castExpr(hasCastKind(CK_DerivedToBase))));
+  EXPECT_TRUE(matches("char *p = 0;",
+              implicitCastExpr(hasCastKind(CK_NullToPointer))));
+}
+
 TEST(ReinterpretCast, MatchesSimpleCase) {
   EXPECT_TRUE(matches("char* p = reinterpret_cast(&p);",
                       cxxReinterpretCastExpr()));