Index: docs/LibASTMatchersReference.html =================================================================== --- docs/LibASTMatchersReference.html +++ docs/LibASTMatchersReference.html @@ -410,7 +410,7 @@ Given typedef int X; - using Y = int; + using Y = int; typeAliasDecl() matches "using Y = int", but not "typedef int X" @@ -421,7 +421,7 @@ Given typedef int X; - using Y = int; + using Y = int; typedefDecl() matches "typedef int X", but not "using Y = int" @@ -432,7 +432,7 @@ Given typedef int X; - using Y = int; + using Y = int; typedefNameDecl() matches "typedef int X" and "using Y = int" @@ -2156,6 +2156,15 @@ +
Matches casts that has a given cast kind. + +Example: matches the implicit cast around 0 +(matcher = castExpr(hasCastKind(CK_NullToPointer))) + int *p = 0; +
Matches literals that are equal to the given value.
Index: include/clang/ASTMatchers/ASTMatchers.h
===================================================================
--- include/clang/ASTMatchers/ASTMatchers.h
+++ include/clang/ASTMatchers/ASTMatchers.h
@@ -3548,6 +3548,17 @@
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
Index: lib/ASTMatchers/Dynamic/Marshallers.h
===================================================================
--- lib/ASTMatchers/Dynamic/Marshallers.h
+++ lib/ASTMatchers/Dynamic/Marshallers.h
@@ -96,6 +96,85 @@
}
};
+template <> struct ArgTypeTraits {
+private:
+ static clang::CastKind getCastKind(llvm::StringRef AttrKind) {
+ return llvm::StringSwitch(AttrKind)
+ .Case("CK_Dependent", CK_Dependent)
+ .Case("CK_BitCast", CK_BitCast)
+ .Case("CK_LValueBitCast", CK_LValueBitCast)
+ .Case("CK_LValueToRValue", CK_LValueToRValue)
+ .Case("CK_NoOp", CK_NoOp)
+ .Case("CK_BaseToDerived", CK_BaseToDerived)
+ .Case("CK_DerivedToBase", CK_DerivedToBase)
+ .Case("CK_UncheckedDerivedToBase", CK_UncheckedDerivedToBase)
+ .Case("CK_Dynamic", CK_Dynamic)
+ .Case("CK_ToUnion", CK_ToUnion)
+ .Case("CK_ArrayToPointerDecay", CK_ArrayToPointerDecay)
+ .Case("CK_FunctionToPointerDecay", CK_FunctionToPointerDecay)
+ .Case("CK_NullToMemberPointer", CK_NullToMemberPointer)
+ .Case("CK_NullToPointer", CK_NullToPointer)
+ .Case("CK_BaseToDerivedMemberPointer", CK_BaseToDerivedMemberPointer)
+ .Case("CK_DerivedToBaseMemberPointer", CK_DerivedToBaseMemberPointer)
+ .Case("CK_ReinterpretMemberPointer", CK_ReinterpretMemberPointer)
+ .Case("CK_UserDefinedConversion", CK_UserDefinedConversion)
+ .Case("CK_ConstructorConversion", CK_ConstructorConversion)
+ .Case("CK_IntegralToPointer", CK_IntegralToPointer)
+ .Case("CK_PointerToIntegral", CK_PointerToIntegral)
+ .Case("CK_PointerToBoolean", CK_PointerToBoolean)
+ .Case("CK_ToVoid", CK_ToVoid)
+ .Case("CK_VectorSplat", CK_VectorSplat)
+ .Case("CK_IntegralCast", CK_IntegralCast)
+ .Case("CK_BooleanToSignedIntegral", CK_BooleanToSignedIntegral)
+ .Case("CK_IntegralToBoolean", CK_IntegralToBoolean)
+ .Case("CK_IntegralToFloating", CK_IntegralToFloating)
+ .Case("CK_FloatingToIntegral", CK_FloatingToIntegral)
+ .Case("CK_FloatingCast", CK_FloatingCast)
+ .Case("CK_FloatingToBoolean", CK_FloatingToBoolean)
+ .Case("CK_MemberPointerToBoolean", CK_MemberPointerToBoolean)
+ .Case("CK_CPointerToObjCPointerCast", CK_CPointerToObjCPointerCast)
+ .Case("CK_BlockPointerToObjCPointerCast",
+ CK_BlockPointerToObjCPointerCast)
+ .Case("CK_AnyPointerToBlockPointerCast", CK_AnyPointerToBlockPointerCast)
+ .Case("CK_ObjCObjectLValueCast", CK_ObjCObjectLValueCast)
+ .Case("CK_FloatingRealToComplex", CK_FloatingRealToComplex)
+ .Case("CK_FloatingComplexToReal", CK_FloatingComplexToReal)
+ .Case("CK_FloatingComplexToBoolean", CK_FloatingComplexToBoolean)
+ .Case("CK_FloatingComplexCast", CK_FloatingComplexCast)
+ .Case("CK_FloatingComplexToIntegralComplex",
+ CK_FloatingComplexToIntegralComplex)
+ .Case("CK_IntegralRealToComplex", CK_IntegralRealToComplex)
+ .Case("CK_IntegralComplexToReal", CK_IntegralComplexToReal)
+ .Case("CK_IntegralComplexToBoolean", CK_IntegralComplexToBoolean)
+ .Case("CK_IntegralComplexCast", CK_IntegralComplexCast)
+ .Case("CK_IntegralComplexToFloatingComplex",
+ CK_IntegralComplexToFloatingComplex)
+ .Case("CK_ARCConsumeObject", CK_ARCConsumeObject)
+ .Case("CK_ARCProduceObject", CK_ARCProduceObject)
+ .Case("CK_ARCReclaimReturnedObject", CK_ARCReclaimReturnedObject)
+ .Case("CK_ARCExtendBlockObject", CK_ARCExtendBlockObject)
+ .Case("CK_AtomicToNonAtomic", CK_AtomicToNonAtomic)
+ .Case("CK_NonAtomicToAtomic", CK_NonAtomicToAtomic)
+ .Case("CK_CopyAndAutoreleaseBlockObject",
+ CK_CopyAndAutoreleaseBlockObject)
+ .Case("CK_BuiltinFnToFnPtr", CK_BuiltinFnToFnPtr)
+ .Case("CK_ZeroToOCLEvent", CK_ZeroToOCLEvent)
+ .Case("CK_AddressSpaceConversion", CK_AddressSpaceConversion)
+ .Default(clang::CastKind(-1));
+ }
+public:
+ static bool is(const VariantValue &Value) {
+ return Value.isString() &&
+ getCastKind(Value.getString()) != clang::CastKind(-1);
+ }
+ 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
Index: lib/ASTMatchers/Dynamic/Registry.cpp
===================================================================
--- lib/ASTMatchers/Dynamic/Registry.cpp
+++ lib/ASTMatchers/Dynamic/Registry.cpp
@@ -209,6 +209,7 @@
REGISTER_MATCHER(hasBody);
REGISTER_MATCHER(hasCanonicalType);
REGISTER_MATCHER(hasCaseConstant);
+ REGISTER_MATCHER(hasCastKind);
REGISTER_MATCHER(hasCondition);
REGISTER_MATCHER(hasConditionVariableStatement);
REGISTER_MATCHER(hasDecayedType);
Index: unittests/ASTMatchers/ASTMatchersTest.cpp
===================================================================
--- unittests/ASTMatchers/ASTMatchersTest.cpp
+++ unittests/ASTMatchers/ASTMatchersTest.cpp
@@ -3475,6 +3475,13 @@
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))));
+}
+
TEST(ReinterpretCast, MatchesSimpleCase) {
EXPECT_TRUE(matches("char* p = reinterpret_cast(&p);",
cxxReinterpretCastExpr()));