Author: george.karpenkov Date: Mon Jul 16 13:22:12 2018 New Revision: 337209
URL: http://llvm.org/viewvc/llvm-project?rev=337209&view=rev Log: [ASTMatchers] Introduce Objective-C matchers `hasReceiver` and `isInstanceMessage` for ObjCMessageExpr Differential Revision: https://reviews.llvm.org/D49333 Modified: cfe/trunk/docs/LibASTMatchersReference.html cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp cfe/trunk/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp Modified: cfe/trunk/docs/LibASTMatchersReference.html URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/docs/LibASTMatchersReference.html?rev=337209&r1=337208&r2=337209&view=diff ============================================================================== --- cfe/trunk/docs/LibASTMatchersReference.html (original) +++ cfe/trunk/docs/LibASTMatchersReference.html Mon Jul 16 13:22:12 2018 @@ -3268,6 +3268,19 @@ represent an error condition in the tree </pre></td></tr> +<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1ObjCMessageExpr.html">ObjCMessageExpr</a>></td><td class="name" onclick="toggle('isInstanceMessage0')"><a name="isInstanceMessage0Anchor">isInstanceMessage</a></td><td></td></tr> +<tr><td colspan="4" class="doc" id="isInstanceMessage0"><pre>Returns true when the Objective-C message is sent to an instance. + +Example +matcher = objcMessagaeExpr(isInstanceMessage()) +matches + NSString *x = @"hello"; + [x containsString:@"h"] +but not + [NSString stringWithFormat:@"format"] +</pre></td></tr> + + <tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1ObjCMessageExpr.html">ObjCMessageExpr</a>></td><td class="name" onclick="toggle('matchesSelector0')"><a name="matchesSelector0Anchor">matchesSelector</a></td><td>std::string RegExp</td></tr> <tr><td colspan="4" class="doc" id="matchesSelector0"><pre>Matches ObjC selectors whose name contains a substring matched by the given RegExp. @@ -5875,6 +5888,18 @@ Example matches y in x(y) </pre></td></tr> +<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1ObjCMessageExpr.html">ObjCMessageExpr</a>></td><td class="name" onclick="toggle('hasReceiver0')"><a name="hasReceiver0Anchor">hasReceiver</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>> InnerMatcher</td></tr> +<tr><td colspan="4" class="doc" id="hasReceiver0"><pre>Matches if the Objective-C message is sent to an instance, +and the inner matcher matches on that instance. + +For example the method call in + NSString *x = @"hello"; + [x containsString:@"h"] +is matched by +objcMessageExpr(hasReceiver(declRefExpr(to(varDecl(hasName("x")))))) +</pre></td></tr> + + <tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1ObjCMessageExpr.html">ObjCMessageExpr</a>></td><td class="name" onclick="toggle('hasReceiverType0')"><a name="hasReceiverType0Anchor">hasReceiverType</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>> InnerMatcher</td></tr> <tr><td colspan="4" class="doc" id="hasReceiverType0"><pre>Matches on the receiver of an ObjectiveC Message expression. Modified: cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h?rev=337209&r1=337208&r2=337209&view=diff ============================================================================== --- cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h (original) +++ cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h Mon Jul 16 13:22:12 2018 @@ -2736,6 +2736,41 @@ AST_MATCHER_P(ObjCMessageExpr, hasReceiv return InnerMatcher.matches(TypeDecl, Finder, Builder); } +/// Returns true when the Objective-C message is sent to an instance. +/// +/// Example +/// matcher = objcMessagaeExpr(isInstanceMessage()) +/// matches +/// \code +/// NSString *x = @"hello"; +/// [x containsString:@"h"]; +/// \endcode +/// but not +/// \code +/// [NSString stringWithFormat:@"format"]; +/// \endcode +AST_MATCHER(ObjCMessageExpr, isInstanceMessage) { + return Node.isInstanceMessage(); +} + +/// Matches if the Objective-C message is sent to an instance, +/// and the inner matcher matches on that instance. +/// +/// For example the method call in +/// \code +/// NSString *x = @"hello"; +/// [x containsString:@"h"]; +/// \endcode +/// is matched by +/// objcMessageExpr(hasReceiver(declRefExpr(to(varDecl(hasName("x")))))) +AST_MATCHER_P(ObjCMessageExpr, hasReceiver, internal::Matcher<Expr>, + InnerMatcher) { + const Expr *ReceiverNode = Node.getInstanceReceiver(); + return (ReceiverNode != nullptr && + InnerMatcher.matches(*ReceiverNode->IgnoreParenImpCasts(), Finder, + Builder)); +} + /// Matches when BaseName == Selector.getAsString() /// /// matcher = objCMessageExpr(hasSelector("loadHTMLString:baseURL:")); Modified: cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp?rev=337209&r1=337208&r2=337209&view=diff ============================================================================== --- cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp (original) +++ cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp Mon Jul 16 13:22:12 2018 @@ -283,6 +283,7 @@ RegistryMaps::RegistryMaps() { REGISTER_MATCHER(hasParent); REGISTER_MATCHER(hasQualifier); REGISTER_MATCHER(hasRangeInit); + REGISTER_MATCHER(hasReceiver); REGISTER_MATCHER(hasReceiverType); REGISTER_MATCHER(hasReplacementType); REGISTER_MATCHER(hasReturnValue); @@ -349,6 +350,7 @@ RegistryMaps::RegistryMaps() { REGISTER_MATCHER(isImplicit); REGISTER_MATCHER(isExpansionInFileMatching); REGISTER_MATCHER(isExpansionInMainFile); + REGISTER_MATCHER(isInstanceMessage); REGISTER_MATCHER(isInstantiated); REGISTER_MATCHER(isExpansionInSystemHeader); REGISTER_MATCHER(isInteger); Modified: cfe/trunk/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp?rev=337209&r1=337208&r2=337209&view=diff ============================================================================== --- cfe/trunk/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp (original) +++ cfe/trunk/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp Mon Jul 16 13:22:12 2018 @@ -422,6 +422,35 @@ TEST(Matcher, AnyArgument) { EXPECT_TRUE(matches("void x(long) { int y; x(y); }", ImplicitCastedArgument)); } +TEST(Matcher, HasReceiver) { + EXPECT_TRUE(matchesObjC( + "@interface NSString @end" + "void f(NSString *x) {" + "[x containsString]" + "}", + objcMessageExpr(hasReceiver(declRefExpr(to(varDecl(hasName("x")))))))); + + EXPECT_FALSE(matchesObjC( + "@interface NSString +(NSString *) stringWithFormat; @end" + "void f() { [NSString stringWithFormat]; }", + objcMessageExpr(hasReceiver(declRefExpr(to(varDecl(hasName("x")))))))); +} + +TEST(Matcher, isInstanceMessage) { + EXPECT_TRUE(matchesObjC( + "@interface NSString @end" + "void f(NSString *x) {" + "[x containsString]" + "}", + objcMessageExpr(isInstanceMessage()))); + + EXPECT_FALSE(matchesObjC( + "@interface NSString +(NSString *) stringWithFormat; @end" + "void f() { [NSString stringWithFormat]; }", + objcMessageExpr(isInstanceMessage()))); + +} + TEST(ForEachArgumentWithParam, ReportsNoFalsePositives) { StatementMatcher ArgumentY = declRefExpr(to(varDecl(hasName("y")))).bind("arg"); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits