On Thu, Mar 12, 2015 at 12:52 PM, Manuel Klimek <[email protected]> wrote: > I think d0k fixed that in 232054.
Yup, appears so! :-) ~Aaron > > 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 >> > 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 >> > [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
