summaryrefslogtreecommitdiffstats
path: root/tools/libclang/CXCursor.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tools/libclang/CXCursor.cpp')
-rw-r--r--tools/libclang/CXCursor.cpp244
1 files changed, 218 insertions, 26 deletions
diff --git a/tools/libclang/CXCursor.cpp b/tools/libclang/CXCursor.cpp
index a298759..2757af4 100644
--- a/tools/libclang/CXCursor.cpp
+++ b/tools/libclang/CXCursor.cpp
@@ -30,9 +30,9 @@
using namespace clang;
using namespace cxcursor;
-CXCursor cxcursor::MakeCXCursorInvalid(CXCursorKind K) {
+CXCursor cxcursor::MakeCXCursorInvalid(CXCursorKind K, CXTranslationUnit TU) {
assert(K >= CXCursor_FirstInvalid && K <= CXCursor_LastInvalid);
- CXCursor C = { K, 0, { 0, 0, 0 } };
+ CXCursor C = { K, 0, { 0, 0, TU } };
return C;
}
@@ -148,6 +148,10 @@ CXCursor cxcursor::MakeCXCursor(Stmt *S, Decl *Parent, CXTranslationUnit TU,
case Stmt::AsmStmtClass:
K = CXCursor_AsmStmt;
break;
+
+ case Stmt::MSAsmStmtClass:
+ K = CXCursor_MSAsmStmt;
+ break;
case Stmt::ObjCAtTryStmtClass:
K = CXCursor_ObjCAtTryStmt;
@@ -229,7 +233,7 @@ CXCursor cxcursor::MakeCXCursor(Stmt *S, Decl *Parent, CXTranslationUnit TU,
case Stmt::VAArgExprClass:
case Stmt::ObjCArrayLiteralClass:
case Stmt::ObjCDictionaryLiteralClass:
- case Stmt::ObjCNumericLiteralClass:
+ case Stmt::ObjCBoxedExprClass:
case Stmt::ObjCSubscriptRefExprClass:
K = CXCursor_UnexposedExpr;
break;
@@ -864,27 +868,10 @@ static inline void CollectOverriddenMethods(CXTranslationUnit TU,
/*MovedToSuper=*/false);
}
-void cxcursor::getOverriddenCursors(CXCursor cursor,
- SmallVectorImpl<CXCursor> &overridden) {
- assert(clang_isDeclaration(cursor.kind));
- Decl *D = getCursorDecl(cursor);
- if (!D)
- return;
-
- // Handle C++ member functions.
- CXTranslationUnit TU = getCursorTU(cursor);
- if (CXXMethodDecl *CXXMethod = dyn_cast<CXXMethodDecl>(D)) {
- for (CXXMethodDecl::method_iterator
- M = CXXMethod->begin_overridden_methods(),
- MEnd = CXXMethod->end_overridden_methods();
- M != MEnd; ++M)
- overridden.push_back(MakeCXCursor(const_cast<CXXMethodDecl*>(*M), TU));
- return;
- }
-
- ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(D);
- if (!Method)
- return;
+static void collectOverriddenMethodsSlow(CXTranslationUnit TU,
+ ObjCMethodDecl *Method,
+ SmallVectorImpl<CXCursor> &overridden) {
+ assert(Method->isOverriding());
if (ObjCProtocolDecl *
ProtD = dyn_cast<ObjCProtocolDecl>(Method->getDeclContext())) {
@@ -921,6 +908,83 @@ void cxcursor::getOverriddenCursors(CXCursor cursor,
}
}
+static void collectOnCategoriesAfterLocation(SourceLocation Loc,
+ ObjCInterfaceDecl *Class,
+ CXTranslationUnit TU,
+ ObjCMethodDecl *Method,
+ SmallVectorImpl<CXCursor> &Methods) {
+ if (!Class)
+ return;
+
+ SourceManager &SM = static_cast<ASTUnit *>(TU->TUData)->getSourceManager();
+ for (ObjCCategoryDecl *Category = Class->getCategoryList();
+ Category; Category = Category->getNextClassCategory())
+ if (SM.isBeforeInTranslationUnit(Loc, Category->getLocation()))
+ CollectOverriddenMethodsRecurse(TU, Category, Method, Methods, true);
+
+ collectOnCategoriesAfterLocation(Loc, Class->getSuperClass(), TU,
+ Method, Methods);
+}
+
+/// \brief Faster collection that is enabled when ObjCMethodDecl::isOverriding()
+/// returns false.
+/// You'd think that in that case there are no overrides but categories can
+/// "introduce" new overridden methods that are missed by Sema because the
+/// overrides lookup that it does for methods, inside implementations, will
+/// stop at the interface level (if there is a method there) and not look
+/// further in super classes.
+static void collectOverriddenMethodsFast(CXTranslationUnit TU,
+ ObjCMethodDecl *Method,
+ SmallVectorImpl<CXCursor> &Methods) {
+ assert(!Method->isOverriding());
+
+ ObjCContainerDecl *ContD = cast<ObjCContainerDecl>(Method->getDeclContext());
+ if (isa<ObjCInterfaceDecl>(ContD) || isa<ObjCProtocolDecl>(ContD))
+ return;
+ ObjCInterfaceDecl *Class = Method->getClassInterface();
+ if (!Class)
+ return;
+
+ collectOnCategoriesAfterLocation(Class->getLocation(), Class->getSuperClass(),
+ TU, Method, Methods);
+}
+
+void cxcursor::getOverriddenCursors(CXCursor cursor,
+ SmallVectorImpl<CXCursor> &overridden) {
+ assert(clang_isDeclaration(cursor.kind));
+ Decl *D = getCursorDecl(cursor);
+ if (!D)
+ return;
+
+ // Handle C++ member functions.
+ CXTranslationUnit TU = getCursorTU(cursor);
+ if (CXXMethodDecl *CXXMethod = dyn_cast<CXXMethodDecl>(D)) {
+ for (CXXMethodDecl::method_iterator
+ M = CXXMethod->begin_overridden_methods(),
+ MEnd = CXXMethod->end_overridden_methods();
+ M != MEnd; ++M)
+ overridden.push_back(MakeCXCursor(const_cast<CXXMethodDecl*>(*M), TU));
+ return;
+ }
+
+ ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(D);
+ if (!Method)
+ return;
+
+ if (Method->isRedeclaration()) {
+ Method = cast<ObjCContainerDecl>(Method->getDeclContext())->
+ getMethod(Method->getSelector(), Method->isInstanceMethod());
+ }
+
+ if (!Method->isOverriding()) {
+ collectOverriddenMethodsFast(TU, Method, overridden);
+ } else {
+ collectOverriddenMethodsSlow(TU, Method, overridden);
+ assert(!overridden.empty() &&
+ "ObjCMethodDecl's overriding bit is not as expected");
+ }
+}
+
std::pair<int, SourceLocation>
cxcursor::getSelectorIdentifierIndexAndLoc(CXCursor cursor) {
if (cursor.kind == CXCursor_ObjCMessageExpr) {
@@ -1134,7 +1198,8 @@ CXCompletionString clang_getCursorCompletionString(CXCursor cursor) {
= Result.CreateCodeCompletionString(unit->getASTContext(),
unit->getPreprocessor(),
unit->getCodeCompletionTUInfo().getAllocator(),
- unit->getCodeCompletionTUInfo());
+ unit->getCodeCompletionTUInfo(),
+ true);
return String;
}
}
@@ -1147,10 +1212,137 @@ CXCompletionString clang_getCursorCompletionString(CXCursor cursor) {
= Result.CreateCodeCompletionString(unit->getASTContext(),
unit->getPreprocessor(),
unit->getCodeCompletionTUInfo().getAllocator(),
- unit->getCodeCompletionTUInfo());
+ unit->getCodeCompletionTUInfo(),
+ false);
return String;
}
return NULL;
}
+} // end: extern C.
+
+namespace {
+ struct OverridenCursorsPool {
+ typedef llvm::SmallVector<CXCursor, 2> CursorVec;
+ std::vector<CursorVec*> AllCursors;
+ std::vector<CursorVec*> AvailableCursors;
+
+ ~OverridenCursorsPool() {
+ for (std::vector<CursorVec*>::iterator I = AllCursors.begin(),
+ E = AllCursors.end(); I != E; ++I) {
+ delete *I;
+ }
+ }
+ };
+}
+
+void *cxcursor::createOverridenCXCursorsPool() {
+ return new OverridenCursorsPool();
+}
+
+void cxcursor::disposeOverridenCXCursorsPool(void *pool) {
+ delete static_cast<OverridenCursorsPool*>(pool);
+}
+
+extern "C" {
+void clang_getOverriddenCursors(CXCursor cursor,
+ CXCursor **overridden,
+ unsigned *num_overridden) {
+ if (overridden)
+ *overridden = 0;
+ if (num_overridden)
+ *num_overridden = 0;
+
+ CXTranslationUnit TU = cxcursor::getCursorTU(cursor);
+
+ if (!overridden || !num_overridden || !TU)
+ return;
+
+ if (!clang_isDeclaration(cursor.kind))
+ return;
+
+ OverridenCursorsPool &pool =
+ *static_cast<OverridenCursorsPool*>(TU->OverridenCursorsPool);
+
+ OverridenCursorsPool::CursorVec *Vec = 0;
+ if (!pool.AvailableCursors.empty()) {
+ Vec = pool.AvailableCursors.back();
+ pool.AvailableCursors.pop_back();
+ }
+ else {
+ Vec = new OverridenCursorsPool::CursorVec();
+ pool.AllCursors.push_back(Vec);
+ }
+
+ // Clear out the vector, but don't free the memory contents. This
+ // reduces malloc() traffic.
+ Vec->clear();
+
+ // Use the first entry to contain a back reference to the vector.
+ // This is a complete hack.
+ CXCursor backRefCursor = MakeCXCursorInvalid(CXCursor_InvalidFile, TU);
+ backRefCursor.data[0] = Vec;
+ assert(cxcursor::getCursorTU(backRefCursor) == TU);
+ Vec->push_back(backRefCursor);
+
+ // Get the overriden cursors.
+ cxcursor::getOverriddenCursors(cursor, *Vec);
+
+ // Did we get any overriden cursors? If not, return Vec to the pool
+ // of available cursor vectors.
+ if (Vec->size() == 1) {
+ pool.AvailableCursors.push_back(Vec);
+ return;
+ }
+
+ // Now tell the caller about the overriden cursors.
+ assert(Vec->size() > 1);
+ *overridden = &((*Vec)[1]);
+ *num_overridden = Vec->size() - 1;
+}
+
+void clang_disposeOverriddenCursors(CXCursor *overridden) {
+ if (!overridden)
+ return;
+
+ // Use pointer arithmetic to get back the first faux entry
+ // which has a back-reference to the TU and the vector.
+ --overridden;
+ OverridenCursorsPool::CursorVec *Vec =
+ static_cast<OverridenCursorsPool::CursorVec*>(overridden->data[0]);
+ CXTranslationUnit TU = getCursorTU(*overridden);
+
+ assert(Vec && TU);
+
+ OverridenCursorsPool &pool =
+ *static_cast<OverridenCursorsPool*>(TU->OverridenCursorsPool);
+
+ pool.AvailableCursors.push_back(Vec);
+}
+
+int clang_Cursor_isDynamicCall(CXCursor C) {
+ const Expr *E = 0;
+ if (clang_isExpression(C.kind))
+ E = getCursorExpr(C);
+ if (!E)
+ return 0;
+
+ if (const ObjCMessageExpr *MsgE = dyn_cast<ObjCMessageExpr>(E))
+ return MsgE->getReceiverKind() == ObjCMessageExpr::Instance;
+
+ const MemberExpr *ME = 0;
+ if (isa<MemberExpr>(E))
+ ME = cast<MemberExpr>(E);
+ else if (const CallExpr *CE = dyn_cast<CallExpr>(E))
+ ME = dyn_cast_or_null<MemberExpr>(CE->getCallee());
+
+ if (ME) {
+ if (const CXXMethodDecl *
+ MD = dyn_cast_or_null<CXXMethodDecl>(ME->getMemberDecl()))
+ return MD->isVirtual() && !ME->hasQualifier();
+ }
+
+ return 0;
+}
+
} // end: extern "C"
OpenPOWER on IntegriCloud