r232051 - Add support for a few Objective-C matchers.

Aaron Ballman aaron at aaronballman.com
Thu Mar 12 09:54:42 PDT 2015


On Thu, Mar 12, 2015 at 12:52 PM, Manuel Klimek <klimek at google.com> wrote:
> I think d0k fixed that in 232054.

Yup, appears so! :-)

~Aaron

>
> On Thu, Mar 12, 2015 at 5:39 PM Aaron Ballman <aaron at aaronballman.com>
> wrote:
>>
>> On Thu, Mar 12, 2015 at 11:48 AM, Manuel Klimek <klimek at google.com> wrote:
>> > Author: klimek
>> > Date: Thu Mar 12 10:48:15 2015
>> > New Revision: 232051
>> >
>> > URL: http://llvm.org/viewvc/llvm-project?rev=232051&view=rev
>> > Log:
>> > Add support for a few Objective-C matchers.
>> >
>> > Add some matchers for Objective-C selectors and messages to
>> > ASTMatchers.h. Minor mods to ASTMatchersTest.h to allow test files with
>> > ".m" extension in addition to ".cpp".  New tests added to
>> > ASTMatchersTest.c.
>> >
>> > Patch by Dean Sutherland.
>>
>> When I commit this previously, I had to revert due to broken bots.
>>
>>
>> http://bb.pgr.jp/builders/ninja-clang-x64-mingw64-RA/builds/6352/steps/build/logs/stdio
>>
>> ~Aaron
>>
>> >
>> > Modified:
>> >     cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h
>> >     cfe/trunk/include/clang/ASTMatchers/ASTMatchersInternal.h
>> >     cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp
>> >     cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.cpp
>> >     cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.h
>> >
>> > Modified: cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h
>> > URL:
>> > http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h?rev=232051&r1=232050&r2=232051&view=diff
>> >
>> > ==============================================================================
>> > --- cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h (original)
>> > +++ cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h Thu Mar 12
>> > 10:48:15 2015
>> > @@ -47,6 +47,7 @@
>> >
>> >  #include "clang/AST/ASTContext.h"
>> >  #include "clang/AST/DeclFriend.h"
>> > +#include "clang/AST/DeclObjC.h"
>> >  #include "clang/AST/DeclTemplate.h"
>> >  #include "clang/ASTMatchers/ASTMatchersInternal.h"
>> >  #include "clang/ASTMatchers/ASTMatchersMacros.h"
>> > @@ -869,6 +870,20 @@ const internal::VariadicDynCastAllOfMatc
>> >    Stmt,
>> >    CXXMemberCallExpr> memberCallExpr;
>> >
>> > +/// \brief Matches ObjectiveC Message invocation expressions.
>> > +///
>> > +/// The innermost message send invokes the "alloc" class method on the
>> > +/// NSString class, while the outermost message send invokes the
>> > +/// "initWithString" instance method on the object returned from
>> > +/// NSString's "alloc". This matcher should match both message sends.
>> > +/// \code
>> > +///   [[NSString alloc] initWithString:@"Hello"]
>> > +/// \endcode
>> > +const internal::VariadicDynCastAllOfMatcher<
>> > +  Stmt,
>> > +  ObjCMessageExpr> objcMessageExpr;
>> > +
>> > +
>> >  /// \brief Matches expressions that introduce cleanups to be run at the
>> > end
>> >  /// of the sub-expression's evaluation.
>> >  ///
>> > @@ -2007,6 +2022,104 @@ AST_MATCHER_P(CXXMemberCallExpr, on, int
>> >            InnerMatcher.matches(*ExprNode, Finder, Builder));
>> >  }
>> >
>> > +
>> > +/// \brief Matches on the receiver of an ObjectiveC Message expression.
>> > +///
>> > +/// Example
>> > +/// matcher = objCMessageExpr(hasRecieverType(asString("UIWebView
>> > *")));
>> > +/// matches the [webView ...] message invocation.
>> > +/// \code
>> > +///   NSString *webViewJavaScript = ...
>> > +///   UIWebView *webView = ...
>> > +///   [webView
>> > stringByEvaluatingJavaScriptFromString:webViewJavascript];
>> > +/// \endcode
>> > +AST_MATCHER_P(ObjCMessageExpr, hasReceiverType,
>> > internal::Matcher<QualType>,
>> > +              InnerMatcher) {
>> > +  const QualType TypeDecl = Node.getReceiverType();
>> > +  return InnerMatcher.matches(TypeDecl, Finder, Builder);
>> > +}
>> > +
>> > +/// \brief Matches when BaseName == Selector.getAsString()
>> > +///
>> > +///  matcher = objCMessageExpr(hasSelector("loadHTMLString:baseURL:"));
>> > +///  matches the outer message expr in the code below, but NOT the
>> > message
>> > +///  invocation for self.bodyView.
>> > +/// \code
>> > +///     [self.bodyView loadHTMLString:html baseURL:NULL];
>> > +/// \endcode
>> > +  AST_MATCHER_P(ObjCMessageExpr, hasSelector, std::string, BaseName) {
>> > +  Selector Sel = Node.getSelector();
>> > +  return BaseName.compare(Sel.getAsString()) == 0;
>> > +}
>> > +
>> > +
>> > +/// \brief Matches ObjC selectors whose name contains
>> > +/// a substring matched by the given RegExp.
>> > +///  matcher =
>> > objCMessageExpr(matchesSelector("loadHTMLString\:baseURL?"));
>> > +///  matches the outer message expr in the code below, but NOT the
>> > message
>> > +///  invocation for self.bodyView.
>> > +/// \code
>> > +///     [self.bodyView loadHTMLString:html baseURL:NULL];
>> > +/// \endcode
>> > +AST_MATCHER_P(ObjCMessageExpr, matchesSelector, std::string, RegExp) {
>> > +  assert(!RegExp.empty());
>> > +  std::string SelectorString = Node.getSelector().getAsString();
>> > +  llvm::Regex RE(RegExp);
>> > +  return RE.match(SelectorString);
>> > +}
>> > +
>> > +/// \brief Matches when the selector is the empty selector
>> > +///
>> > +/// Matches only when the selector of the objCMessageExpr is NULL. This
>> > may
>> > +/// represent an error condition in the tree!
>> > +AST_MATCHER(ObjCMessageExpr, hasNullSelector) {
>> > +  return Node.getSelector().isNull();
>> > +}
>> > +
>> > +/// \brief Matches when the selector is a Unary Selector
>> > +///
>> > +///  matcher = objCMessageExpr(matchesSelector(hasUnarySelector());
>> > +///  matches self.bodyView in the code below, but NOT the outer message
>> > +///  invocation of "loadHTMLString:baseURL:".
>> > +/// \code
>> > +///     [self.bodyView loadHTMLString:html baseURL:NULL];
>> > +/// \endcode
>> > +AST_MATCHER(ObjCMessageExpr, hasUnarySelector) {
>> > +  return Node.getSelector().isUnarySelector();
>> > +}
>> > +
>> > +/// \brief Matches when the selector is a keyword selector
>> > +///
>> > +/// objCMessageExpr(hasKeywordSelector()) matches the generated
>> > setFrame
>> > +/// message expression in
>> > +///
>> > +/// \code
>> > +///   UIWebView *webView = ...;
>> > +///   CGRect bodyFrame = webView.frame;
>> > +///   bodyFrame.size.height = self.bodyContentHeight;
>> > +///   webView.frame = bodyFrame;
>> > +///   //     ^---- matches here
>> > +/// \endcode
>> > +
>> > +AST_MATCHER(ObjCMessageExpr, hasKeywordSelector) {
>> > +  return Node.getSelector().isKeywordSelector();
>> > +}
>> > +
>> > +/// \brief Matches when the selector has the specified number of
>> > arguments
>> > +///
>> > +///  matcher = objCMessageExpr(numSelectorArgs(1));
>> > +///  matches self.bodyView in the code below
>> > +///
>> > +///  matcher = objCMessageExpr(numSelectorArgs(2));
>> > +///  matches the invocation of "loadHTMLString:baseURL:" but not that
>> > +///  of self.bodyView
>> > +/// \code
>> > +///     [self.bodyView loadHTMLString:html baseURL:NULL];
>> > +/// \endcode
>> > +AST_MATCHER_P(ObjCMessageExpr, numSelectorArgs, unsigned, N) {
>> > +  return Node.getSelector().getNumArgs() == N;
>> > +}
>> > +
>> >  /// \brief Matches if the call expression's callee expression matches.
>> >  ///
>> >  /// Given
>> > @@ -2316,7 +2429,8 @@ AST_MATCHER(VarDecl, hasGlobalStorage) {
>> >  /// \endcode
>> >  AST_POLYMORPHIC_MATCHER_P(argumentCountIs,
>> >                            AST_POLYMORPHIC_SUPPORTED_TYPES(CallExpr,
>> > -
>> > CXXConstructExpr),
>> > +
>> > CXXConstructExpr,
>> > +
>> > ObjCMessageExpr),
>> >                            unsigned, N) {
>> >    return Node.getNumArgs() == N;
>> >  }
>> > @@ -2331,7 +2445,8 @@ AST_POLYMORPHIC_MATCHER_P(argumentCountI
>> >  /// \endcode
>> >  AST_POLYMORPHIC_MATCHER_P2(hasArgument,
>> >                             AST_POLYMORPHIC_SUPPORTED_TYPES(CallExpr,
>> > -
>> > CXXConstructExpr),
>> > +
>> > CXXConstructExpr,
>> > +
>> > ObjCMessageExpr),
>> >                             unsigned, N, internal::Matcher<Expr>,
>> > InnerMatcher) {
>> >    return (N < Node.getNumArgs() &&
>> >            InnerMatcher.matches(
>> >
>> > Modified: cfe/trunk/include/clang/ASTMatchers/ASTMatchersInternal.h
>> > URL:
>> > http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/ASTMatchers/ASTMatchersInternal.h?rev=232051&r1=232050&r2=232051&view=diff
>> >
>> > ==============================================================================
>> > --- cfe/trunk/include/clang/ASTMatchers/ASTMatchersInternal.h (original)
>> > +++ cfe/trunk/include/clang/ASTMatchers/ASTMatchersInternal.h Thu Mar 12
>> > 10:48:15 2015
>> > @@ -38,9 +38,12 @@
>> >  #include "clang/AST/ASTTypeTraits.h"
>> >  #include "clang/AST/Decl.h"
>> >  #include "clang/AST/DeclCXX.h"
>> > +#include "clang/AST/DeclObjC.h"
>> >  #include "clang/AST/ExprCXX.h"
>> > +#include "clang/AST/ExprObjC.h"
>> >  #include "clang/AST/Stmt.h"
>> >  #include "clang/AST/StmtCXX.h"
>> > +#include "clang/AST/StmtObjC.h"
>> >  #include "clang/AST/Type.h"
>> >  #include "llvm/ADT/Optional.h"
>> >  #include "llvm/ADT/VariadicFunction.h"
>> >
>> > Modified: cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp
>> > URL:
>> > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp?rev=232051&r1=232050&r2=232051&view=diff
>> >
>> > ==============================================================================
>> > --- cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp (original)
>> > +++ cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp Thu Mar 12 10:48:15
>> > 2015
>> > @@ -198,6 +198,7 @@ RegistryMaps::RegistryMaps() {
>> >    REGISTER_MATCHER(hasIncrement);
>> >    REGISTER_MATCHER(hasIndex);
>> >    REGISTER_MATCHER(hasInitializer);
>> > +  REGISTER_MATCHER(hasKeywordSelector);
>> >    REGISTER_MATCHER(hasLHS);
>> >    REGISTER_MATCHER(hasLocalQualifiers);
>> >    REGISTER_MATCHER(hasLocalStorage);
>> > @@ -205,6 +206,7 @@ RegistryMaps::RegistryMaps() {
>> >    REGISTER_MATCHER(hasLoopVariable);
>> >    REGISTER_MATCHER(hasMethod);
>> >    REGISTER_MATCHER(hasName);
>> > +  REGISTER_MATCHER(hasNullSelector);
>> >    REGISTER_MATCHER(hasObjectExpression);
>> >    REGISTER_MATCHER(hasOperatorName);
>> >    REGISTER_MATCHER(hasOverloadedOperatorName);
>> > @@ -212,7 +214,9 @@ RegistryMaps::RegistryMaps() {
>> >    REGISTER_MATCHER(hasParent);
>> >    REGISTER_MATCHER(hasQualifier);
>> >    REGISTER_MATCHER(hasRangeInit);
>> > +  REGISTER_MATCHER(hasReceiverType);
>> >    REGISTER_MATCHER(hasRHS);
>> > +  REGISTER_MATCHER(hasSelector);
>> >    REGISTER_MATCHER(hasSingleDecl);
>> >    REGISTER_MATCHER(hasSize);
>> >    REGISTER_MATCHER(hasSizeExpr);
>> > @@ -223,6 +227,7 @@ RegistryMaps::RegistryMaps() {
>> >    REGISTER_MATCHER(hasTrueExpression);
>> >    REGISTER_MATCHER(hasTypeLoc);
>> >    REGISTER_MATCHER(hasUnaryOperand);
>> > +  REGISTER_MATCHER(hasUnarySelector);
>> >    REGISTER_MATCHER(hasValueType);
>> >    REGISTER_MATCHER(ifStmt);
>> >    REGISTER_MATCHER(ignoringImpCasts);
>> > @@ -262,6 +267,7 @@ RegistryMaps::RegistryMaps() {
>> >    REGISTER_MATCHER(lambdaExpr);
>> >    REGISTER_MATCHER(lValueReferenceType);
>> >    REGISTER_MATCHER(matchesName);
>> > +  REGISTER_MATCHER(matchesSelector);
>> >    REGISTER_MATCHER(materializeTemporaryExpr);
>> >    REGISTER_MATCHER(member);
>> >    REGISTER_MATCHER(memberCallExpr);
>> > @@ -276,7 +282,9 @@ RegistryMaps::RegistryMaps() {
>> >    REGISTER_MATCHER(newExpr);
>> >    REGISTER_MATCHER(nullPtrLiteralExpr);
>> >    REGISTER_MATCHER(nullStmt);
>> > +  REGISTER_MATCHER(numSelectorArgs);
>> >    REGISTER_MATCHER(ofClass);
>> > +  REGISTER_MATCHER(objcMessageExpr);
>> >    REGISTER_MATCHER(on);
>> >    REGISTER_MATCHER(onImplicitObjectArgument);
>> >    REGISTER_MATCHER(operatorCallExpr);
>> >
>> > Modified: cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.cpp
>> > URL:
>> > http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.cpp?rev=232051&r1=232050&r2=232051&view=diff
>> >
>> > ==============================================================================
>> > --- cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.cpp (original)
>> > +++ cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.cpp Thu Mar 12
>> > 10:48:15 2015
>> > @@ -4714,5 +4714,50 @@ TEST(Matcher, IsExpansionInFileMatching)
>> >
>> >  #endif // LLVM_ON_WIN32
>> >
>> > +
>> > +TEST(ObjCMessageExprMatcher, SimpleExprs) {
>> > +  // don't find ObjCMessageExpr where none are present
>> > +  EXPECT_TRUE(notMatchesObjC("", objcMessageExpr(anything())));
>> > +
>> > +  std::string Objc1String =
>> > +  "@interface Str "
>> > +  " - (Str *)uppercaseString:(Str *)str;"
>> > +  "@end "
>> > +  "@interface foo "
>> > +  "- (void)meth:(Str *)text;"
>> > +  "@end "
>> > +  " "
>> > +  "@implementation foo "
>> > +  "- (void) meth:(Str *)text { "
>> > +  "  [self contents];"
>> > +  "  Str *up = [text uppercaseString];"
>> > +  "} "
>> > +  "@end ";
>> > +  EXPECT_TRUE(matchesObjC(
>> > +      Objc1String,
>> > +      objcMessageExpr(anything())));
>> > +  EXPECT_TRUE(matchesObjC(
>> > +      Objc1String,
>> > +      objcMessageExpr(hasSelector("contents"))));
>> > +  EXPECT_TRUE(matchesObjC(
>> > +      Objc1String,
>> > +      objcMessageExpr(matchesSelector("cont*"))));
>> > +  EXPECT_FALSE(matchesObjC(
>> > +      Objc1String,
>> > +      objcMessageExpr(matchesSelector("?cont*"))));
>> > +  EXPECT_TRUE(notMatchesObjC(
>> > +      Objc1String,
>> > +      objcMessageExpr(hasSelector("contents"), hasNullSelector())));
>> > +  EXPECT_TRUE(matchesObjC(
>> > +      Objc1String,
>> > +      objcMessageExpr(hasSelector("contents"), hasUnarySelector())));
>> > +  EXPECT_TRUE(matchesObjC(
>> > +      Objc1String,
>> > +      objcMessageExpr(matchesSelector("uppercase*"),
>> > +                      argumentCountIs(0)
>> > +                      )));
>> > +
>> > +}
>> > +
>> >  } // end namespace ast_matchers
>> >  } // end namespace clang
>> >
>> > Modified: cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.h
>> > URL:
>> > http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.h?rev=232051&r1=232050&r2=232051&view=diff
>> >
>> > ==============================================================================
>> > --- cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.h (original)
>> > +++ cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.h Thu Mar 12
>> > 10:48:15 2015
>> > @@ -62,7 +62,8 @@ template <typename T>
>> >  testing::AssertionResult matchesConditionally(
>> >      const std::string &Code, const T &AMatcher, bool ExpectMatch,
>> >      llvm::StringRef CompileArg,
>> > -    const FileContentMappings &VirtualMappedFiles =
>> > FileContentMappings()) {
>> > +    const FileContentMappings &VirtualMappedFiles =
>> > FileContentMappings(),
>> > +    const std::string &Filename = "input.cc") {
>> >    bool Found = false, DynamicFound = false;
>> >    MatchFinder Finder;
>> >    VerifyMatch VerifyFound(nullptr, &Found);
>> > @@ -78,7 +79,7 @@ testing::AssertionResult matchesConditio
>> >    // Some tests need rtti/exceptions on
>> >    Args.push_back("-frtti");
>> >    Args.push_back("-fexceptions");
>> > -  if (!runToolOnCodeWithArgs(Factory->create(), Code, Args, "input.cc",
>> > +  if (!runToolOnCodeWithArgs(Factory->create(), Code, Args, Filename,
>> >                               VirtualMappedFiles)) {
>> >      return testing::AssertionFailure() << "Parsing error in \"" << Code
>> > << "\"";
>> >    }
>> > @@ -109,6 +110,23 @@ testing::AssertionResult notMatches(cons
>> >    return matchesConditionally(Code, AMatcher, false, "-std=c++11");
>> >  }
>> >
>> > +template <typename T>
>> > +testing::AssertionResult matchesObjC(const std::string &Code,
>> > +                                     const T &AMatcher) {
>> > +  return matchesConditionally(
>> > +    Code, AMatcher, true,
>> > +    "", FileContentMappings(), "input.m");
>> > +}
>> > +
>> > +template <typename T>
>> > +testing::AssertionResult notMatchesObjC(const std::string &Code,
>> > +                                     const T &AMatcher) {
>> > +  return matchesConditionally(
>> > +    Code, AMatcher, false,
>> > +    "", FileContentMappings(), "input.m");
>> > +}
>> > +
>> > +
>> >  // Function based on matchesConditionally with "-x cuda" argument added
>> > and
>> >  // small CUDA header prepended to the code string.
>> >  template <typename T>
>> >
>> >
>> > _______________________________________________
>> > cfe-commits mailing list
>> > cfe-commits at cs.uiuc.edu
>> > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits



More information about the cfe-commits mailing list