├── Example.cpp ├── Makefile └── test.m /Example.cpp: -------------------------------------------------------------------------------- 1 | #include "clang/Driver/Options.h" 2 | #include "clang/AST/AST.h" 3 | #include "clang/AST/ASTContext.h" 4 | #include "clang/AST/ASTConsumer.h" 5 | #include "clang/AST/RecursiveASTVisitor.h" 6 | #include "clang/Frontend/ASTConsumers.h" 7 | #include "clang/Frontend/FrontendActions.h" 8 | #include "clang/Frontend/CompilerInstance.h" 9 | #include "clang/Tooling/CommonOptionsParser.h" 10 | #include "clang/Tooling/Tooling.h" 11 | 12 | using namespace std; 13 | using namespace clang; 14 | using namespace clang::driver; 15 | using namespace clang::tooling; 16 | using namespace llvm; 17 | 18 | class ExampleVisitor : public RecursiveASTVisitor { 19 | private: 20 | ASTContext *astContext; // used for getting additional AST info 21 | 22 | public: 23 | explicit ExampleVisitor(CompilerInstance *CI) 24 | : astContext(&(CI->getASTContext())) // initialize private members 25 | { 26 | } 27 | 28 | virtual bool VisitObjCMessageExpr(ObjCMessageExpr *E) { 29 | if (E->getReceiverKind() == ObjCMessageExpr::Class) { 30 | QualType ReceiverType = E->getClassReceiver(); 31 | Selector Sel = E->getSelector(); 32 | string TypeName = ReceiverType.getAsString(); 33 | string SelName = Sel.getAsString(); 34 | if (TypeName == "Observer" && SelName == "observerWithTarget:action:") { 35 | Expr *Receiver = E->getArg(0)->IgnoreParenCasts(); 36 | ObjCSelectorExpr* SelExpr = cast(E->getArg(1)->IgnoreParenCasts()); 37 | Selector Sel = SelExpr->getSelector(); 38 | if (const ObjCObjectPointerType *OT = Receiver->getType()->getAs()) { 39 | ObjCInterfaceDecl *decl = OT->getInterfaceDecl(); 40 | if (! decl->lookupInstanceMethod(Sel)) { 41 | errs() << "Warning: class " << TypeName << " does not implement selector " << Sel.getAsString() << "\n"; 42 | SourceLocation Loc = E->getExprLoc(); 43 | PresumedLoc PLoc = astContext->getSourceManager().getPresumedLoc(Loc); 44 | errs() << "in " << PLoc.getFilename() << " <" << PLoc.getLine() << ":" << PLoc.getColumn() << ">\n"; 45 | } 46 | } 47 | } 48 | } 49 | return true; 50 | } 51 | }; 52 | 53 | 54 | 55 | class ExampleASTConsumer : public ASTConsumer { 56 | private: 57 | ExampleVisitor *visitor; // doesn't have to be private 58 | 59 | public: 60 | // override the constructor in order to pass CI 61 | explicit ExampleASTConsumer(CompilerInstance *CI) 62 | : visitor(new ExampleVisitor(CI)) // initialize the visitor 63 | { } 64 | 65 | // override this to call our ExampleVisitor on the entire source file 66 | virtual void HandleTranslationUnit(ASTContext &Context) { 67 | /* we can use ASTContext to get the TranslationUnitDecl, which is 68 | a single Decl that collectively represents the entire source file */ 69 | visitor->TraverseDecl(Context.getTranslationUnitDecl()); 70 | } 71 | 72 | }; 73 | 74 | 75 | 76 | class ExampleFrontendAction : public ASTFrontendAction { 77 | public: 78 | virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, StringRef file) { 79 | return new ExampleASTConsumer(&CI); // pass CI pointer to ASTConsumer 80 | } 81 | }; 82 | 83 | 84 | 85 | int main(int argc, const char **argv) { 86 | // parse the command-line args passed to your code 87 | CommonOptionsParser op(argc, argv); 88 | // create a new Clang Tool instance (a LibTooling environment) 89 | ClangTool Tool(op.getCompilations(), op.getSourcePathList()); 90 | 91 | // run the Clang Tool, creating a new FrontendAction (explained below) 92 | int result = Tool.run(newFrontendActionFactory()); 93 | return result; 94 | } 95 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CLANG_LEVEL := ../.. 2 | 3 | TOOLNAME = example #the name of your tool's executable 4 | 5 | SOURCES := Example.cpp #the Clang source files you want to compile 6 | 7 | include $(CLANG_LEVEL)/../../Makefile.config 8 | 9 | LINK_COMPONENTS := $(TARGETS_TO_BUILD) asmparser bitreader support mc option 10 | 11 | USEDLIBS = clangFrontend.a clangSerialization.a clangDriver.a \ 12 | clangTooling.a clangParse.a clangSema.a \ 13 | clangAnalysis.a clangRewriteFrontend.a clangRewriteCore.a \ 14 | clangEdit.a clangAST.a clangLex.a clangBasic.a 15 | 16 | include $(CLANG_LEVEL)/Makefile 17 | -------------------------------------------------------------------------------- /test.m: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @interface NSString (MyAdditions) 4 | - (NSUInteger)lengthh; 5 | @end 6 | 7 | @interface Observer 8 | + (instancetype)observerWithTarget:(id)target action:(SEL)selector; 9 | @end 10 | 11 | @interface Test : NSObject 12 | @property (nonatomic,strong) id keyValueObserver; 13 | @end 14 | 15 | @implementation Test 16 | 17 | - (void)test 18 | { 19 | NSString* string = @""; 20 | self.keyValueObserver = [Observer observerWithTarget:string action:@selector(lengthh)]; 21 | } 22 | @end 23 | 24 | void do_math(int *x) { 25 | *x += 5; 26 | } 27 | 28 | int main(void) { 29 | int result = -1, val = 4; 30 | do_math(&val); 31 | return result; 32 | } 33 | --------------------------------------------------------------------------------