[cfe-commits] r77551 - in /cfe/trunk: include/clang/Index/Analyzer.h lib/Index/Analyzer.cpp test/Index/objc-decls.m test/Index/objc-message.m test/Index/objc.h test/Index/t1.m test/Index/t2.m tools/index-test/index-test.cpp
Argiris Kirtzidis
akyrtzi at gmail.com
Wed Jul 29 17:03:55 PDT 2009
Author: akirtzidis
Date: Wed Jul 29 19:03:55 2009
New Revision: 77551
URL: http://llvm.org/viewvc/llvm-project?rev=77551&view=rev
Log:
Add support for ObjC message expressions, in the Analyzer:
-Accept an ObjC method and find all message expressions that this method may respond to.
-Accept an ObjC message expression and find all methods that may respond to it.
Added:
cfe/trunk/test/Index/objc-decls.m
cfe/trunk/test/Index/objc-message.m
cfe/trunk/test/Index/objc.h
cfe/trunk/test/Index/t1.m
cfe/trunk/test/Index/t2.m
Modified:
cfe/trunk/include/clang/Index/Analyzer.h
cfe/trunk/lib/Index/Analyzer.cpp
cfe/trunk/tools/index-test/index-test.cpp
Modified: cfe/trunk/include/clang/Index/Analyzer.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Index/Analyzer.h?rev=77551&r1=77550&r2=77551&view=diff
==============================================================================
--- cfe/trunk/include/clang/Index/Analyzer.h (original)
+++ cfe/trunk/include/clang/Index/Analyzer.h Wed Jul 29 19:03:55 2009
@@ -16,6 +16,7 @@
namespace clang {
class Decl;
+ class ObjCMessageExpr;
namespace idx {
class Program;
@@ -42,6 +43,10 @@
/// \brief Find all TULocations for references of the given Decl and pass
/// them to Handler.
void FindReferences(Decl *D, TULocationHandler &Handler);
+
+ /// \brief Find methods that may respond to the given message and pass them
+ /// to Handler.
+ void FindObjCMethods(ObjCMessageExpr *MsgE, TULocationHandler &Handler);
};
} // namespace idx
Modified: cfe/trunk/lib/Index/Analyzer.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Index/Analyzer.cpp?rev=77551&r1=77550&r2=77551&view=diff
==============================================================================
--- cfe/trunk/lib/Index/Analyzer.cpp (original)
+++ cfe/trunk/lib/Index/Analyzer.cpp Wed Jul 29 19:03:55 2009
@@ -16,9 +16,13 @@
#include "clang/Index/TranslationUnit.h"
#include "clang/Index/Handlers.h"
#include "clang/Index/ASTLocation.h"
+#include "clang/Index/GlobalSelector.h"
#include "clang/Index/DeclReferenceMap.h"
+#include "clang/Index/SelectorMap.h"
#include "clang/Index/IndexProvider.h"
-#include "clang/AST/Decl.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/ExprObjC.h"
+#include "llvm/ADT/SmallSet.h"
#include "llvm/Support/Compiler.h"
using namespace clang;
using namespace idx;
@@ -73,7 +77,321 @@
DeclReferenceMap &RefMap = TU->getDeclReferenceMap();
for (DeclReferenceMap::astlocation_iterator
I = RefMap.refs_begin(ND), E = RefMap.refs_end(ND); I != E; ++I)
- TULocHandler.Handle(TULocation(TU, ASTLocation(*I)));
+ TULocHandler.Handle(TULocation(TU, *I));
+ }
+};
+
+//===----------------------------------------------------------------------===//
+// RefSelectorAnalyzer Implementation
+//===----------------------------------------------------------------------===//
+
+/// \brief Accepts an ObjC method and finds all message expressions that this
+/// method may respond to.
+class VISIBILITY_HIDDEN RefSelectorAnalyzer : public TranslationUnitHandler {
+ Program &Prog;
+ TULocationHandler &TULocHandler;
+
+ // The original ObjCInterface associated with the method.
+ Entity IFaceEnt;
+ GlobalSelector GlobSel;
+ bool IsInstanceMethod;
+
+ /// \brief Super classes of the ObjCInterface.
+ typedef llvm::SmallSet<Entity, 16> EntitiesSetTy;
+ EntitiesSetTy HierarchyEntities;
+
+public:
+ RefSelectorAnalyzer(ObjCMethodDecl *MD,
+ Program &prog, TULocationHandler &handler)
+ : Prog(prog), TULocHandler(handler) {
+ assert(MD);
+
+ // FIXME: Protocol methods.
+ assert(!isa<ObjCProtocolDecl>(MD->getDeclContext()) &&
+ "Protocol methods not supported yet");
+
+ ObjCInterfaceDecl *IFD = MD->getClassInterface();
+ assert(IFD);
+ IFaceEnt = Entity::get(IFD, Prog);
+ GlobSel = GlobalSelector::get(MD->getSelector(), Prog);
+ IsInstanceMethod = MD->isInstanceMethod();
+
+ for (ObjCInterfaceDecl *Cls = IFD->getSuperClass();
+ Cls; Cls = Cls->getSuperClass())
+ HierarchyEntities.insert(Entity::get(Cls, Prog));
+ }
+
+ virtual void Handle(TranslationUnit *TU) {
+ assert(TU && "Passed null translation unit");
+
+ ASTContext &Ctx = TU->getASTContext();
+ // Null means it doesn't exist in this translation unit.
+ ObjCInterfaceDecl *IFace =
+ cast_or_null<ObjCInterfaceDecl>(IFaceEnt.getDecl(Ctx));
+ Selector Sel = GlobSel.getSelector(Ctx);
+
+ SelectorMap &SelMap = TU->getSelectorMap();
+ for (SelectorMap::astlocation_iterator
+ I = SelMap.refs_begin(Sel), E = SelMap.refs_end(Sel); I != E; ++I) {
+ if (ValidReference(*I, IFace))
+ TULocHandler.Handle(TULocation(TU, *I));
+ }
+ }
+
+ /// \brief Determines whether the given message expression is likely to end
+ /// up at the given interface decl.
+ ///
+ /// It returns true "eagerly", meaning it will return false only if it can
+ /// "prove" statically that the interface cannot accept this message.
+ bool ValidReference(ASTLocation ASTLoc, ObjCInterfaceDecl *IFace) {
+ assert(ASTLoc.isValid());
+ assert(ASTLoc.isStmt());
+
+ // FIXME: Finding @selector references should be through another Analyzer
+ // method, like FindSelectors.
+ if (isa<ObjCSelectorExpr>(ASTLoc.getStmt()))
+ return false;
+
+ ObjCInterfaceDecl *MsgD = 0;
+ ObjCMessageExpr *Msg = cast<ObjCMessageExpr>(ASTLoc.getStmt());
+
+ if (Msg->getReceiver()) {
+ const ObjCObjectPointerType *OPT =
+ Msg->getReceiver()->getType()->getAsObjCInterfacePointerType();
+
+ // Can be anything! Accept it as a possibility..
+ if (!OPT || OPT->isObjCIdType() || OPT->isObjCQualifiedIdType())
+ return true;
+
+ // Expecting class method.
+ if (OPT->isObjCClassType() || OPT->isObjCQualifiedClassType())
+ return !IsInstanceMethod;
+
+ MsgD = OPT->getInterfaceDecl();
+ assert(MsgD);
+
+ // Should be an instance method.
+ if (!IsInstanceMethod)
+ return false;
+
+ } else {
+ // Expecting class method.
+ if (IsInstanceMethod)
+ return false;
+
+ MsgD = Msg->getClassInfo().first;
+ // FIXME: Case when we only have an identifier.
+ assert(MsgD && "Identifier only");
+ }
+
+ assert(MsgD);
+
+ // Same interface ? We have a winner!
+ if (MsgD == IFace)
+ return true;
+
+ // If the message interface is a superclass of the original interface,
+ // accept this message as a possibility.
+ if (HierarchyEntities.count(Entity::get(MsgD, Prog)))
+ return true;
+
+ // If the message interface is a subclass of the original interface, accept
+ // the message unless there is a subclass in the hierarchy that will
+ // "steal" the message (thus the message "will go" to the subclass and not
+ /// the original interface).
+ if (IFace) {
+ Selector Sel = Msg->getSelector();
+ for (ObjCInterfaceDecl *Cls = MsgD; Cls; Cls = Cls->getSuperClass()) {
+ if (Cls == IFace)
+ return true;
+ if (Cls->getMethod(Sel, IsInstanceMethod))
+ return false;
+ }
+ }
+
+ // The interfaces are unrelated, don't accept the message.
+ return false;
+ }
+};
+
+//===----------------------------------------------------------------------===//
+// MessageAnalyzer Implementation
+//===----------------------------------------------------------------------===//
+
+/// \brief Accepts an ObjC message expression and finds all methods that may
+/// respond to it.
+class VISIBILITY_HIDDEN MessageAnalyzer : public TranslationUnitHandler {
+ Program &Prog;
+ TULocationHandler &TULocHandler;
+
+ // The ObjCInterface associated with the message. Can be null/invalid.
+ Entity MsgIFaceEnt;
+ GlobalSelector GlobSel;
+ bool CanBeInstanceMethod;
+ bool CanBeClassMethod;
+
+ /// \brief Super classes of the ObjCInterface.
+ typedef llvm::SmallSet<Entity, 16> EntitiesSetTy;
+ EntitiesSetTy HierarchyEntities;
+
+ /// \brief The interface in the message interface hierarchy that "intercepts"
+ /// the selector.
+ Entity ReceiverIFaceEnt;
+
+public:
+ MessageAnalyzer(ObjCMessageExpr *Msg,
+ Program &prog, TULocationHandler &handler)
+ : Prog(prog), TULocHandler(handler),
+ CanBeInstanceMethod(false),
+ CanBeClassMethod(false) {
+
+ assert(Msg);
+
+ ObjCInterfaceDecl *MsgD = 0;
+
+ while (true) {
+ if (Msg->getReceiver() == 0) {
+ CanBeClassMethod = true;
+ MsgD = Msg->getClassInfo().first;
+ // FIXME: Case when we only have an identifier.
+ assert(MsgD && "Identifier only");
+ break;
+ }
+
+ const ObjCObjectPointerType *OPT =
+ Msg->getReceiver()->getType()->getAsObjCInterfacePointerType();
+
+ if (!OPT || OPT->isObjCIdType() || OPT->isObjCQualifiedIdType()) {
+ CanBeInstanceMethod = CanBeClassMethod = true;
+ break;
+ }
+
+ if (OPT->isObjCClassType() || OPT->isObjCQualifiedClassType()) {
+ CanBeClassMethod = true;
+ break;
+ }
+
+ MsgD = OPT->getInterfaceDecl();
+ assert(MsgD);
+ CanBeInstanceMethod = true;
+ break;
+ }
+
+ assert(CanBeInstanceMethod || CanBeClassMethod);
+
+ Selector sel = Msg->getSelector();
+ assert(!sel.isNull());
+
+ MsgIFaceEnt = Entity::get(MsgD, Prog);
+ GlobSel = GlobalSelector::get(sel, Prog);
+
+ if (MsgD) {
+ for (ObjCInterfaceDecl *Cls = MsgD->getSuperClass();
+ Cls; Cls = Cls->getSuperClass())
+ HierarchyEntities.insert(Entity::get(Cls, Prog));
+
+ // Find the interface in the hierarchy that "receives" the message.
+ for (ObjCInterfaceDecl *Cls = MsgD; Cls; Cls = Cls->getSuperClass()) {
+ bool isReceiver = false;
+
+ ObjCInterfaceDecl::lookup_const_iterator Meth, MethEnd;
+ for (llvm::tie(Meth, MethEnd) = Cls->lookup(sel);
+ Meth != MethEnd; ++Meth) {
+ if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(*Meth))
+ if ((MD->isInstanceMethod() && CanBeInstanceMethod) ||
+ (MD->isClassMethod() && CanBeClassMethod)) {
+ isReceiver = true;
+ break;
+ }
+ }
+
+ if (isReceiver) {
+ ReceiverIFaceEnt = Entity::get(Cls, Prog);
+ break;
+ }
+ }
+ }
+ }
+
+ virtual void Handle(TranslationUnit *TU) {
+ assert(TU && "Passed null translation unit");
+ ASTContext &Ctx = TU->getASTContext();
+
+ // Null means it doesn't exist in this translation unit or there was no
+ // interface that was determined to receive the original message.
+ ObjCInterfaceDecl *ReceiverIFace =
+ cast_or_null<ObjCInterfaceDecl>(ReceiverIFaceEnt.getDecl(Ctx));
+
+ // No subclass for the original receiver interface, so it remains the
+ // receiver.
+ if (ReceiverIFaceEnt.isValid() && ReceiverIFace == 0)
+ return;
+
+ // Null means it doesn't exist in this translation unit or there was no
+ // interface associated with the message in the first place.
+ ObjCInterfaceDecl *MsgIFace =
+ cast_or_null<ObjCInterfaceDecl>(MsgIFaceEnt.getDecl(Ctx));
+
+ Selector Sel = GlobSel.getSelector(Ctx);
+ SelectorMap &SelMap = TU->getSelectorMap();
+ for (SelectorMap::method_iterator
+ I = SelMap.methods_begin(Sel), E = SelMap.methods_end(Sel);
+ I != E; ++I) {
+ ObjCMethodDecl *D = *I;
+ if (ValidMethod(D, MsgIFace, ReceiverIFace)) {
+ for (ObjCMethodDecl::redecl_iterator
+ RI = D->redecls_begin(), RE = D->redecls_end(); RI != RE; ++RI)
+ TULocHandler.Handle(TULocation(TU, ASTLocation(*RI)));
+ }
+ }
+ }
+
+ /// \brief Determines whether the given method is likely to accept the
+ /// original message.
+ ///
+ /// It returns true "eagerly", meaning it will return false only if it can
+ /// "prove" statically that the method cannot accept the original message.
+ bool ValidMethod(ObjCMethodDecl *D, ObjCInterfaceDecl *MsgIFace,
+ ObjCInterfaceDecl *ReceiverIFace) {
+ assert(D);
+
+ // FIXME: Protocol methods ?
+ if (isa<ObjCProtocolDecl>(D->getDeclContext()))
+ return false;
+
+ // No specific interface associated with the message. Can be anything.
+ if (MsgIFaceEnt.isInvalid())
+ return true;
+
+ if (!CanBeInstanceMethod && D->isInstanceMethod() ||
+ !CanBeClassMethod && D->isClassMethod())
+ return false;
+
+ ObjCInterfaceDecl *IFace = D->getClassInterface();
+ assert(IFace);
+
+ // If the original message interface is the same or a superclass of the
+ // given interface, accept the method as a possibility.
+ if (MsgIFace && MsgIFace->isSuperClassOf(IFace))
+ return true;
+
+ if (ReceiverIFace) {
+ // The given interface, "overrides" the receiver.
+ if (ReceiverIFace->isSuperClassOf(IFace))
+ return true;
+ } else {
+ // No receiver was found for the original message.
+ assert(ReceiverIFaceEnt.isInvalid());
+
+ // If the original message interface is a subclass of the given interface,
+ // accept the message.
+ if (HierarchyEntities.count(Entity::get(IFace, Prog)))
+ return true;
+ }
+
+ // The interfaces are unrelated, or the receiver interface wasn't
+ // "overriden".
+ return false;
}
};
@@ -95,6 +413,13 @@
void Analyzer::FindReferences(Decl *D, TULocationHandler &Handler) {
assert(D && "Passed null declaration");
+ if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
+ RefSelectorAnalyzer RSA(MD, Prog, Handler);
+ GlobalSelector Sel = GlobalSelector::get(MD->getSelector(), Prog);
+ Idxer.GetTranslationUnitsFor(Sel, RSA);
+ return;
+ }
+
Entity Ent = Entity::get(D, Prog);
if (Ent.isInvalid())
return;
@@ -102,3 +427,13 @@
RefEntityAnalyzer REA(Ent, Handler);
Idxer.GetTranslationUnitsFor(Ent, REA);
}
+
+/// \brief Find methods that may respond to the given message and pass them
+/// to Handler.
+void Analyzer::FindObjCMethods(ObjCMessageExpr *Msg,
+ TULocationHandler &Handler) {
+ assert(Msg);
+ MessageAnalyzer MsgAnalyz(Msg, Prog, Handler);
+ GlobalSelector GlobSel = GlobalSelector::get(Msg->getSelector(), Prog);
+ Idxer.GetTranslationUnitsFor(GlobSel, MsgAnalyz);
+}
Added: cfe/trunk/test/Index/objc-decls.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/objc-decls.m?rev=77551&view=auto
==============================================================================
--- cfe/trunk/test/Index/objc-decls.m (added)
+++ cfe/trunk/test/Index/objc-decls.m Wed Jul 29 19:03:55 2009
@@ -0,0 +1,16 @@
+// RUN: clang-cc -emit-pch %S/t1.m -o %t1.m.ast &&
+// RUN: clang-cc -emit-pch %S/t2.m -o %t2.m.ast &&
+
+// RUN: index-test %t1.m.ast %t2.m.ast -point-at %S/t1.m:12:12 -print-decls > %t &&
+// RUN: cat %t | count 2 &&
+// RUN: grep 'objc.h:2:9,' %t | count 2 &&
+
+// RUN: index-test %t1.m.ast %t2.m.ast -point-at %S/objc.h:5:13 -print-decls > %t &&
+// RUN: cat %t | count 3 &&
+// RUN: grep 'objc.h:5:1,' %t | count 2 &&
+// RUN: grep 't1.m:15:1,' %t | count 1 &&
+
+// RUN: index-test %t1.m.ast %t2.m.ast -point-at %S/objc.h:10:13 -print-decls > %t &&
+// RUN: cat %t | count 3 &&
+// RUN: grep 'objc.h:10:1,' %t | count 2 &&
+// RUN: grep 't2.m:11:1,' %t | count 1
Added: cfe/trunk/test/Index/objc-message.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/objc-message.m?rev=77551&view=auto
==============================================================================
--- cfe/trunk/test/Index/objc-message.m (added)
+++ cfe/trunk/test/Index/objc-message.m Wed Jul 29 19:03:55 2009
@@ -0,0 +1,38 @@
+// RUN: clang-cc -emit-pch %S/t1.m -o %t1.m.ast &&
+// RUN: clang-cc -emit-pch %S/t2.m -o %t2.m.ast &&
+
+// RUN: index-test %t1.m.ast %t2.m.ast -point-at %S/objc.h:5:13 -print-refs > %t &&
+// RUN: cat %t | count 1 &&
+// RUN: grep 't1.m:6:3,' %t &&
+
+// RUN: index-test %t1.m.ast %t2.m.ast -point-at %S/objc.h:6:13 -print-refs > %t &&
+// RUN: cat %t | count 2 &&
+// RUN: grep 't1.m:7:3,' %t &&
+// RUN: grep 't2.m:7:3,' %t &&
+
+// RUN: index-test %t1.m.ast %t2.m.ast -point-at %S/objc.h:10:13 -print-refs > %t &&
+// RUN: cat %t | count 2 &&
+// RUN: grep 't1.m:6:3,' %t &&
+// RUN: grep 't2.m:6:3,' %t &&
+
+// RUN: index-test %t1.m.ast %t2.m.ast -point-at %S/t1.m:6:15 -print-decls > %t &&
+// RUN: cat %t | count 6 &&
+// RUN: grep 'objc.h:5:1,' %t | count 2 &&
+// RUN: grep 'objc.h:10:1,' %t | count 2 &&
+// RUN: grep 't1.m:15:1,' %t &&
+// RUN: grep 't2.m:11:1,' %t &&
+
+// RUN: index-test %t1.m.ast %t2.m.ast -point-at %S/t1.m:7:15 -print-decls > %t &&
+// RUN: cat %t | count 3 &&
+// RUN: grep 'objc.h:6:1,' %t | count 2 &&
+// RUN: grep 't1.m:18:1,' %t &&
+
+// RUN: index-test %t2.m.ast %t1.m.ast -point-at %S/t2.m:6:15 -print-decls > %t &&
+// RUN: cat %t | count 3 &&
+// RUN: grep 'objc.h:10:1,' %t | count 2 &&
+// RUN: grep 't2.m:11:1,' %t &&
+
+// RUN: index-test %t2.m.ast %t1.m.ast -point-at %S/t2.m:7:15 -print-decls > %t &&
+// RUN: cat %t | count 3 &&
+// RUN: grep 'objc.h:6:1,' %t | count 2 &&
+// RUN: grep 't1.m:18:1,' %t
Added: cfe/trunk/test/Index/objc.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/objc.h?rev=77551&view=auto
==============================================================================
--- cfe/trunk/test/Index/objc.h (added)
+++ cfe/trunk/test/Index/objc.h Wed Jul 29 19:03:55 2009
@@ -0,0 +1,11 @@
+ at interface Base {
+ int my_var;
+}
+-(int) my_var;
+-(void) my_method: (int)param;
++(void) my_method: (int)param;
+ at end
+
+ at interface Sub : Base
+-(void) my_method: (int)param;
+ at end
Added: cfe/trunk/test/Index/t1.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/t1.m?rev=77551&view=auto
==============================================================================
--- cfe/trunk/test/Index/t1.m (added)
+++ cfe/trunk/test/Index/t1.m Wed Jul 29 19:03:55 2009
@@ -0,0 +1,23 @@
+#include "objc.h"
+
+static void foo() {
+ Base *base;
+ int x = [base my_var];
+ [base my_method:x];
+ [Base my_method:x];
+}
+
+ at implementation Base
+-(int) my_var {
+ return my_var;
+}
+
+-(void) my_method: (int)param {
+}
+
++(void) my_method: (int)param {
+}
+ at end
+
+// Suppress 'no run line' failure.
+// RUN: true
Added: cfe/trunk/test/Index/t2.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/t2.m?rev=77551&view=auto
==============================================================================
--- cfe/trunk/test/Index/t2.m (added)
+++ cfe/trunk/test/Index/t2.m Wed Jul 29 19:03:55 2009
@@ -0,0 +1,16 @@
+#include "objc.h"
+
+static void foo() {
+ Sub *sub;
+ int x = [sub my_var];
+ [sub my_method:x];
+ [Sub my_method:x];
+}
+
+ at implementation Sub
+-(void) my_method: (int)param {
+}
+ at end
+
+// Suppress 'no run line' failure.
+// RUN: true
Modified: cfe/trunk/tools/index-test/index-test.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/index-test/index-test.cpp?rev=77551&r1=77550&r2=77551&view=diff
==============================================================================
--- cfe/trunk/tools/index-test/index-test.cpp (original)
+++ cfe/trunk/tools/index-test/index-test.cpp Wed Jul 29 19:03:55 2009
@@ -44,8 +44,8 @@
#include "clang/Index/Utils.h"
#include "clang/Frontend/ASTUnit.h"
#include "clang/Frontend/CommandLineSourceLoc.h"
-#include "clang/AST/Decl.h"
-#include "clang/AST/Expr.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/ExprObjC.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/SourceManager.h"
#include "llvm/Support/CommandLine.h"
@@ -106,8 +106,48 @@
static bool HadErrors = false;
+static void ProcessObjCMessage(ObjCMessageExpr *Msg, Indexer &Idxer) {
+ llvm::raw_ostream &OS = llvm::outs();
+ typedef Storing<TULocationHandler> ResultsTy;
+ ResultsTy Results;
+
+ Analyzer Analyz(Idxer.getProgram(), Idxer);
+
+ switch (ProgAction) {
+ default: assert(0);
+ case PrintRefs:
+ llvm::errs() << "Error: Cannot -print-refs on a ObjC message expression\n";
+ HadErrors = true;
+ return;
+
+ case PrintDecls: {
+ Analyz.FindObjCMethods(Msg, Results);
+ for (ResultsTy::iterator
+ I = Results.begin(), E = Results.end(); I != E; ++I)
+ I->print(OS);
+ break;
+ }
+
+ case PrintDefs: {
+ Analyz.FindObjCMethods(Msg, Results);
+ for (ResultsTy::iterator
+ I = Results.begin(), E = Results.end(); I != E; ++I) {
+ const ObjCMethodDecl *D = cast<ObjCMethodDecl>(I->getDecl());
+ if (D->isThisDeclarationADefinition())
+ I->print(OS);
+ }
+ break;
+ }
+
+ }
+}
+
static void ProcessASTLocation(ASTLocation ASTLoc, Indexer &Idxer) {
assert(ASTLoc.isValid());
+
+ if (ObjCMessageExpr *Msg =
+ dyn_cast_or_null<ObjCMessageExpr>(ASTLoc.getStmt()))
+ return ProcessObjCMessage(Msg, Idxer);
Decl *D = ASTLoc.getReferencedDecl();
if (D == 0) {
@@ -140,7 +180,7 @@
break;
}
- case PrintDefs:{
+ case PrintDefs: {
Analyz.FindDeclarations(D, Results);
for (ResultsTy::iterator
I = Results.begin(), E = Results.end(); I != E; ++I) {
@@ -206,6 +246,10 @@
if (!PointAtLocation.empty()) {
const std::string &Filename = PointAtLocation[0].FileName;
const FileEntry *File = FileMgr.getFile(Filename);
+ if (File == 0) {
+ llvm::errs() << "File '" << Filename << "' does not exist\n";
+ return 1;
+ }
// Safety check. Using an out-of-date AST file will only lead to crashes
// or incorrect results.
@@ -218,10 +262,6 @@
return 1;
}
- if (File == 0) {
- llvm::errs() << "File '" << Filename << "' does not exist\n";
- return 1;
- }
unsigned Line = PointAtLocation[0].Line;
unsigned Col = PointAtLocation[0].Column;
More information about the cfe-commits
mailing list