diff options
author | Douglas Gregor <dgregor@apple.com> | 2010-09-13 22:52:57 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2010-09-13 22:52:57 +0000 |
commit | 16a2bdd6b011e4522463ae162625712f1764cb1c (patch) | |
tree | f60b6dc514026a6dc27ab1f9460cb6e891cc118c /clang/tools/libclang | |
parent | 59c97b50ae56b69d42cdecd94818ef0c1e317393 (diff) | |
download | bcm5719-llvm-16a2bdd6b011e4522463ae162625712f1764cb1c.tar.gz bcm5719-llvm-16a2bdd6b011e4522463ae162625712f1764cb1c.zip |
Introduce a new kind of cursor into libclang, which covers a reference
to an "overloaded" set of declarations. This cursor kind works for
unresolved references to functions/templates (e.g., a call within a
template), using declarations, and Objective-C class and protocol
forward declarations.
llvm-svn: 113805
Diffstat (limited to 'clang/tools/libclang')
-rw-r--r-- | clang/tools/libclang/CIndex.cpp | 176 | ||||
-rw-r--r-- | clang/tools/libclang/CXCursor.cpp | 48 | ||||
-rw-r--r-- | clang/tools/libclang/CXCursor.h | 27 | ||||
-rw-r--r-- | clang/tools/libclang/libclang.darwin.exports | 2 | ||||
-rw-r--r-- | clang/tools/libclang/libclang.exports | 2 |
5 files changed, 202 insertions, 53 deletions
diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp index 73e5ce06dd8..b699a98e128 100644 --- a/clang/tools/libclang/CIndex.cpp +++ b/clang/tools/libclang/CIndex.cpp @@ -1015,10 +1015,9 @@ bool CursorVisitor::VisitUsingDecl(UsingDecl *D) { if (VisitNestedNameSpecifier(Qualifier, D->getNestedNameRange())) return true; - // FIXME: Provide a multi-reference of some kind for all of the declarations - // that the using declaration refers to. We don't have this kind of cursor - // yet. - + if (Visit(MakeCursorOverloadedDeclRef(D, D->getLocation(), TU))) + return true; + return VisitDeclarationNameInfo(D->getNameInfo()); } @@ -1141,8 +1140,10 @@ bool CursorVisitor::VisitTemplateName(TemplateName Name, SourceLocation Loc) { return Visit(MakeCursorTemplateRef(Name.getAsTemplateDecl(), Loc, TU)); case TemplateName::OverloadedTemplate: - // FIXME: We need a way to return multiple lookup results in a single - // cursor. + // Visit the overloaded template set. + if (Visit(MakeCursorOverloadedDeclRef(Name, Loc, TU))) + return true; + return false; case TemplateName::DependentTemplate: @@ -1272,7 +1273,7 @@ bool CursorVisitor::VisitTagTypeLoc(TagTypeLoc TL) { } bool CursorVisitor::VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) { - // FIXME: We can't visit the template template parameter, but there's + // FIXME: We can't visit the template type parameter, because there's // no context information with which we can match up the depth/index in the // type to the appropriate return false; @@ -1792,7 +1793,11 @@ bool CursorVisitor::VisitOverloadExpr(OverloadExpr *E) { // Visit the declaration name. if (VisitDeclarationNameInfo(E->getNameInfo())) return true; - + + // Visit the overloaded declaration reference. + if (Visit(MakeCursorOverloadedDeclRef(E, TU))) + return true; + // Visit the explicitly-specified template arguments. if (const ExplicitTemplateArgumentList *ArgList = E->getOptionalExplicitTemplateArgs()) { @@ -1804,8 +1809,6 @@ bool CursorVisitor::VisitOverloadExpr(OverloadExpr *E) { } } - // FIXME: We don't have a way to visit all of the declarations referenced - // here. return false; } @@ -2618,6 +2621,22 @@ CXString clang_getCursorSpelling(CXCursor C) { return createCXString(Label->getID()->getName()); } + case CXCursor_OverloadedDeclRef: { + OverloadedDeclRefStorage Storage = getCursorOverloadedDeclRef(C).first; + if (Decl *D = Storage.dyn_cast<Decl *>()) { + if (NamedDecl *ND = dyn_cast<NamedDecl>(D)) + return createCXString(ND->getNameAsString()); + return createCXString(""); + } + if (OverloadExpr *E = Storage.dyn_cast<OverloadExpr *>()) + return createCXString(E->getName().getAsString()); + OverloadedTemplateStorage *Ovl + = Storage.get<OverloadedTemplateStorage*>(); + if (Ovl->size() == 0) + return createCXString(""); + return createCXString((*Ovl->begin())->getNameAsString()); + } + default: return createCXString("<not implemented>"); } @@ -2712,6 +2731,8 @@ CXString clang_getCursorKindSpelling(enum CXCursorKind Kind) { return createCXString("MemberRef"); case CXCursor_LabelRef: return createCXString("LabelRef"); + case CXCursor_OverloadedDeclRef: + return createCXString("OverloadedDeclRef"); case CXCursor_UnexposedExpr: return createCXString("UnexposedExpr"); case CXCursor_BlockExpr: @@ -2931,6 +2952,10 @@ CXSourceLocation clang_getCursorLocation(CXCursor C) { return cxloc::translateSourceLocation(getCursorContext(C), P.second); } + case CXCursor_OverloadedDeclRef: + return cxloc::translateSourceLocation(getCursorContext(C), + getCursorOverloadedDeclRef(C).second); + default: // FIXME: Need a way to enumerate all non-reference cases. llvm_unreachable("Missed a reference kind"); @@ -3004,6 +3029,9 @@ static SourceRange getRawCursorExtent(CXCursor C) { case CXCursor_LabelRef: return getCursorLabelRef(C).second; + case CXCursor_OverloadedDeclRef: + return getCursorOverloadedDeclRef(C).second; + default: // FIXME: Need a way to enumerate all non-reference cases. llvm_unreachable("Missed a reference kind"); @@ -3046,13 +3074,28 @@ CXCursor clang_getCursorReferenced(CXCursor C) { return clang_getNullCursor(); ASTUnit *CXXUnit = getCursorASTUnit(C); - if (clang_isDeclaration(C.kind)) + if (clang_isDeclaration(C.kind)) { + Decl *D = getCursorDecl(C); + if (UsingDecl *Using = dyn_cast<UsingDecl>(D)) + return MakeCursorOverloadedDeclRef(Using, D->getLocation(), CXXUnit); + if (ObjCClassDecl *Classes = dyn_cast<ObjCClassDecl>(D)) + return MakeCursorOverloadedDeclRef(Classes, D->getLocation(), CXXUnit); + if (ObjCForwardProtocolDecl *Protocols + = dyn_cast<ObjCForwardProtocolDecl>(D)) + return MakeCursorOverloadedDeclRef(Protocols, D->getLocation(), CXXUnit); + return C; - + } + if (clang_isExpression(C.kind)) { - Decl *D = getDeclFromExpr(getCursorExpr(C)); + Expr *E = getCursorExpr(C); + Decl *D = getDeclFromExpr(E); if (D) return MakeCXCursor(D, CXXUnit); + + if (OverloadExpr *Ovl = dyn_cast_or_null<OverloadExpr>(E)) + return MakeCursorOverloadedDeclRef(Ovl, CXXUnit); + return clang_getNullCursor(); } @@ -3108,6 +3151,9 @@ CXCursor clang_getCursorReferenced(CXCursor C) { CXXUnit->getASTContext().getTranslationUnitDecl(), CXXUnit); + case CXCursor_OverloadedDeclRef: + return C; + default: // We would prefer to enumerate all non-reference cursor kinds here. llvm_unreachable("Unhandled reference cursor kind"); @@ -3223,23 +3269,9 @@ CXCursor clang_getCursorDefinition(CXCursor C) { return clang_getNullCursor(); } - case Decl::Using: { - UsingDecl *Using = cast<UsingDecl>(D); - CXCursor Def = clang_getNullCursor(); - for (UsingDecl::shadow_iterator S = Using->shadow_begin(), - SEnd = Using->shadow_end(); - S != SEnd; ++S) { - if (Def != clang_getNullCursor()) { - // FIXME: We have no way to return multiple results. - return clang_getNullCursor(); - } - - Def = clang_getCursorDefinition(MakeCXCursor((*S)->getTargetDecl(), - CXXUnit)); - } - - return Def; - } + case Decl::Using: + return MakeCursorOverloadedDeclRef(cast<UsingDecl>(D), + D->getLocation(), CXXUnit); case Decl::UsingShadow: return clang_getCursorDefinition( @@ -3303,29 +3335,13 @@ CXCursor clang_getCursorDefinition(CXCursor C) { return clang_getNullCursor(); - case Decl::ObjCForwardProtocol: { - ObjCForwardProtocolDecl *Forward = cast<ObjCForwardProtocolDecl>(D); - if (Forward->protocol_size() == 1) - return clang_getCursorDefinition( - MakeCXCursor(*Forward->protocol_begin(), - CXXUnit)); - - // FIXME: Cannot return multiple definitions. - return clang_getNullCursor(); - } - - case Decl::ObjCClass: { - ObjCClassDecl *Class = cast<ObjCClassDecl>(D); - if (Class->size() == 1) { - ObjCInterfaceDecl *IFace = Class->begin()->getInterface(); - if (!IFace->isForwardDecl()) - return MakeCXCursor(IFace, CXXUnit); - return clang_getNullCursor(); - } + case Decl::ObjCForwardProtocol: + return MakeCursorOverloadedDeclRef(cast<ObjCForwardProtocolDecl>(D), + D->getLocation(), CXXUnit); - // FIXME: Cannot return multiple definitions. - return clang_getNullCursor(); - } + case Decl::ObjCClass: + return MakeCursorOverloadedDeclRef(cast<ObjCClassDecl>(D), D->getLocation(), + CXXUnit); case Decl::Friend: if (NamedDecl *Friend = cast<FriendDecl>(D)->getFriendDecl()) @@ -3348,6 +3364,62 @@ unsigned clang_isCursorDefinition(CXCursor C) { return clang_getCursorDefinition(C) == C; } +unsigned clang_getNumOverloadedDecls(CXCursor C) { + if (!C.kind == CXCursor_OverloadedDeclRef) + return 0; + + OverloadedDeclRefStorage Storage = getCursorOverloadedDeclRef(C).first; + if (OverloadExpr *E = Storage.dyn_cast<OverloadExpr *>()) + return E->getNumDecls(); + + if (OverloadedTemplateStorage *S + = Storage.dyn_cast<OverloadedTemplateStorage*>()) + return S->size(); + + Decl *D = Storage.get<Decl*>(); + if (UsingDecl *Using = dyn_cast<UsingDecl>(D)) + return Using->getNumShadowDecls(); + if (ObjCClassDecl *Classes = dyn_cast<ObjCClassDecl>(D)) + return Classes->size(); + if (ObjCForwardProtocolDecl *Protocols =dyn_cast<ObjCForwardProtocolDecl>(D)) + return Protocols->protocol_size(); + + return 0; +} + +CXCursor clang_getOverloadedDecl(CXCursor cursor, unsigned index) { + if (!cursor.kind == CXCursor_OverloadedDeclRef) + return clang_getNullCursor(); + + if (index >= clang_getNumOverloadedDecls(cursor)) + return clang_getNullCursor(); + + ASTUnit *Unit = getCursorASTUnit(cursor); + OverloadedDeclRefStorage Storage = getCursorOverloadedDeclRef(cursor).first; + if (OverloadExpr *E = Storage.dyn_cast<OverloadExpr *>()) + return MakeCXCursor(E->decls_begin()[index], Unit); + + if (OverloadedTemplateStorage *S + = Storage.dyn_cast<OverloadedTemplateStorage*>()) + return MakeCXCursor(S->begin()[index], Unit); + + Decl *D = Storage.get<Decl*>(); + if (UsingDecl *Using = dyn_cast<UsingDecl>(D)) { + // FIXME: This is, unfortunately, linear time. + UsingDecl::shadow_iterator Pos = Using->shadow_begin(); + std::advance(Pos, index); + return MakeCXCursor(cast<UsingShadowDecl>(*Pos)->getTargetDecl(), Unit); + } + + if (ObjCClassDecl *Classes = dyn_cast<ObjCClassDecl>(D)) + return MakeCXCursor(Classes->begin()[index].getInterface(), Unit); + + if (ObjCForwardProtocolDecl *Protocols = dyn_cast<ObjCForwardProtocolDecl>(D)) + return MakeCXCursor(Protocols->protocol_begin()[index], Unit); + + return clang_getNullCursor(); +} + void clang_getDefinitionSpellingAndExtent(CXCursor C, const char **startBuf, const char **endBuf, diff --git a/clang/tools/libclang/CXCursor.cpp b/clang/tools/libclang/CXCursor.cpp index e8c14d25928..0db477498ad 100644 --- a/clang/tools/libclang/CXCursor.cpp +++ b/clang/tools/libclang/CXCursor.cpp @@ -19,9 +19,11 @@ #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/Expr.h" +#include "clang/AST/ExprCXX.h" #include "llvm/Support/ErrorHandling.h" using namespace clang; +using namespace cxcursor; CXCursor cxcursor::MakeCXCursorInvalid(CXCursorKind K) { assert(K >= CXCursor_FirstInvalid && K <= CXCursor_LastInvalid); @@ -379,6 +381,52 @@ cxcursor::getCursorLabelRef(CXCursor C) { reinterpret_cast<uintptr_t>(C.data[1]))); } +CXCursor cxcursor::MakeCursorOverloadedDeclRef(OverloadExpr *E, + ASTUnit *TU) { + assert(E && TU && "Invalid arguments!"); + OverloadedDeclRefStorage Storage(E); + void *RawLoc = reinterpret_cast<void *>(E->getNameLoc().getRawEncoding()); + CXCursor C = { + CXCursor_OverloadedDeclRef, + { Storage.getOpaqueValue(), RawLoc, TU } + }; + return C; +} + +CXCursor cxcursor::MakeCursorOverloadedDeclRef(Decl *D, + SourceLocation Loc, + ASTUnit *TU) { + assert(D && TU && "Invalid arguments!"); + void *RawLoc = reinterpret_cast<void *>(Loc.getRawEncoding()); + OverloadedDeclRefStorage Storage(D); + CXCursor C = { + CXCursor_OverloadedDeclRef, + { Storage.getOpaqueValue(), RawLoc, TU } + }; + return C; +} + +CXCursor cxcursor::MakeCursorOverloadedDeclRef(TemplateName Name, + SourceLocation Loc, + ASTUnit *TU) { + assert(Name.getAsOverloadedTemplate() && TU && "Invalid arguments!"); + void *RawLoc = reinterpret_cast<void *>(Loc.getRawEncoding()); + OverloadedDeclRefStorage Storage(Name.getAsOverloadedTemplate()); + CXCursor C = { + CXCursor_OverloadedDeclRef, + { Storage.getOpaqueValue(), RawLoc, TU } + }; + return C; +} + +std::pair<cxcursor::OverloadedDeclRefStorage, SourceLocation> +cxcursor::getCursorOverloadedDeclRef(CXCursor C) { + assert(C.kind == CXCursor_OverloadedDeclRef); + return std::make_pair(OverloadedDeclRefStorage::getFromOpaqueValue(C.data[0]), + SourceLocation::getFromRawEncoding( + reinterpret_cast<uintptr_t>(C.data[1]))); +} + Decl *cxcursor::getCursorDecl(CXCursor Cursor) { return (Decl *)Cursor.data[0]; } diff --git a/clang/tools/libclang/CXCursor.h b/clang/tools/libclang/CXCursor.h index 743b38b9c4d..4a29dd0f1c1 100644 --- a/clang/tools/libclang/CXCursor.h +++ b/clang/tools/libclang/CXCursor.h @@ -16,6 +16,7 @@ #include "clang-c/Index.h" #include "clang/Basic/SourceLocation.h" +#include "llvm/ADT/PointerUnion.h" #include <utility> namespace clang { @@ -33,10 +34,13 @@ class MacroInstantiation; class NamedDecl; class ObjCInterfaceDecl; class ObjCProtocolDecl; +class OverloadedTemplateStorage; +class OverloadExpr; class Stmt; class TemplateDecl; +class TemplateName; class TypeDecl; - + namespace cxcursor { CXCursor MakeCXCursor(const clang::Attr *A, clang::Decl *Parent, ASTUnit *TU); @@ -135,6 +139,27 @@ CXCursor MakeCursorLabelRef(LabelStmt *Label, SourceLocation Loc, ASTUnit *TU); /// \brief Unpack a label reference into the label statement it refers to and /// the location of the reference. std::pair<LabelStmt *, SourceLocation> getCursorLabelRef(CXCursor C); + +/// \brief Create a overloaded declaration reference cursor for an expression. +CXCursor MakeCursorOverloadedDeclRef(OverloadExpr *E, ASTUnit *TU); + +/// \brief Create a overloaded declaration reference cursor for a declaration. +CXCursor MakeCursorOverloadedDeclRef(Decl *D, SourceLocation Location, + ASTUnit *TU); + +/// \brief Create a overloaded declaration reference cursor for a template name. +CXCursor MakeCursorOverloadedDeclRef(TemplateName Template, + SourceLocation Location, ASTUnit *TU); + +/// \brief Internal storage for an overloaded declaration reference cursor; +typedef llvm::PointerUnion3<OverloadExpr *, Decl *, + OverloadedTemplateStorage *> + OverloadedDeclRefStorage; + +/// \brief Unpack an overloaded declaration reference into an expression, +/// declaration, or template name along with the source location. +std::pair<OverloadedDeclRefStorage, SourceLocation> + getCursorOverloadedDeclRef(CXCursor C); Decl *getCursorDecl(CXCursor Cursor); Expr *getCursorExpr(CXCursor Cursor); diff --git a/clang/tools/libclang/libclang.darwin.exports b/clang/tools/libclang/libclang.darwin.exports index d1b45a24867..6b30da4d2bb 100644 --- a/clang/tools/libclang/libclang.darwin.exports +++ b/clang/tools/libclang/libclang.darwin.exports @@ -73,6 +73,8 @@ _clang_getNullLocation _clang_getNullRange _clang_getNumCompletionChunks _clang_getNumDiagnostics +_clang_getNumOverloadedDecls +_clang_getOverloadedDecl _clang_getPointeeType _clang_getRange _clang_getRangeEnd diff --git a/clang/tools/libclang/libclang.exports b/clang/tools/libclang/libclang.exports index 0ea6993b218..798ec322183 100644 --- a/clang/tools/libclang/libclang.exports +++ b/clang/tools/libclang/libclang.exports @@ -73,6 +73,8 @@ clang_getNullLocation clang_getNullRange clang_getNumCompletionChunks clang_getNumDiagnostics +clang_getNumOverloadedDecls +clang_getOverloadedDecl clang_getPointeeType clang_getRange clang_getRangeEnd |