I think d0k fixed that in 232054. On Thu, Mar 12, 2015 at 5:39 PM Aaron Ballman <[email protected]> wrote:
> On Thu, Mar 12, 2015 at 11:48 AM, Manuel Klimek <[email protected]> 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 > > [email protected] > > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits >
_______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
