r232051 - Add support for a few Objective-C matchers.
Manuel Klimek
klimek at google.com
Thu Mar 12 09:52:54 PDT 2015
I think d0k fixed that in 232054.
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 stringByEvaluatingJavaScriptFr
> omString: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
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20150312/8694bbc4/attachment.html>
More information about the cfe-commits
mailing list