*/
CXCursor_LabelRef = 48,
- CXCursor_LastRef = CXCursor_LabelRef,
+ /**
+ * \brief A reference to a set of overloaded functions or function templates
+ * that has not yet been resolved to a specific function or function template.
+ *
+ * An overloaded declaration reference cursor occurs in C++ templates where
+ * a dependent name refers to a function. For example:
+ *
+ * \code
+ * template<typename T> void swap(T&, T&);
+ *
+ * struct X { ... };
+ * void swap(X&, X&);
+ *
+ * template<typename T>
+ * void reverse(T* first, T* last) {
+ * while (first < last - 1) {
+ * swap(*first, *--last);
+ * ++first;
+ * }
+ * }
+ *
+ * struct Y { };
+ * void swap(Y&, Y&);
+ * \endcode
+ *
+ * Here, the identifier "swap" is associated with an overloaded declaration
+ * reference. In the template definition, "swap" refers to either of the two
+ * "swap" functions declared above, so both results will be available. At
+ * instantiation time, "swap" may also refer to other functions found via
+ * argument-dependent lookup (e.g., the "swap" function at the end of the
+ * example).
+ *
+ * The functions \c clang_getNumOverloadedDecls() and
+ * \c clang_getOverloadedDecl() can be used to retrieve the definitions
+ * referenced by this cursor.
+ */
+ CXCursor_OverloadedDeclRef = 49,
+
+ CXCursor_LastRef = CXCursor_OverloadedDeclRef,
/* Error conditions */
CXCursor_FirstInvalid = 70,
*/
CINDEX_LINKAGE enum CX_CXXAccessSpecifier clang_getCXXAccessSpecifier(CXCursor);
+/**
+ * \brief Determine the number of overloaded declarations referenced by a
+ * \c CXCursor_OverloadedDeclRef cursor.
+ *
+ * \param cursor The cursor whose overloaded declarations are being queried.
+ *
+ * \returns The number of overloaded declarations referenced by \c cursor. If it
+ * is not a \c CXCursor_OverloadedDeclRef cursor, returns 0.
+ */
+CINDEX_LINKAGE unsigned clang_getNumOverloadedDecls(CXCursor cursor);
+
+/**
+ * \brief Retrieve a cursor for one of the overloaded declarations referenced
+ * by a \c CXCursor_OverloadedDeclRef cursor.
+ *
+ * \param cursor The cursor whose overloaded declarations are being queried.
+ *
+ * \param index The zero-based index into the set of overloaded declarations in
+ * the cursor.
+ *
+ * \returns A cursor representing the declaration referenced by the given
+ * \c cursor at the specified \c index. If the cursor does not have an
+ * associated set of overloaded declarations, or if the index is out of bounds,
+ * returns \c clang_getNullCursor();
+ */
+CINDEX_LINKAGE CXCursor clang_getOverloadedDecl(CXCursor cursor,
+ unsigned index);
+
/**
* @}
*/
}
// CHECK-scan: [1:1 - 8:1] Invalid Cursor => NoDeclFound
-// CHECK-scan: [8:1 - 8:8] UnexposedDecl=:8:1
+// CHECK-scan: [8:1 - 8:8] UnexposedDecl=[10:12]
// CHECK-scan: [8:8 - 8:11] ObjCClassRef=Foo:10:12
// CHECK-scan: [8:11 - 10:1] Invalid Cursor => NoDeclFound
// CHECK-scan: [10:1 - 11:5] ObjCInterfaceDecl=Foo:10:12
}
// CHECK-scan: [1:1 - 8:1] Invalid Cursor => NoDeclFound
-// CHECK-scan: [8:1 - 8:8] UnexposedDecl=:8:1
+// CHECK-scan: [8:1 - 8:8] UnexposedDecl=[8:8]
// CHECK-scan: [8:8 - 8:11] ObjCClassRef=Foo:8:8
// CHECK-scan: [8:11 - 10:6] Invalid Cursor => NoDeclFound
// CHECK-scan: [10:6 - 10:15] FunctionDecl=function:10:6 (Definition)
Z4().getAs<Unsigned>();
}
+template<typename T> void swap(T&, T&);
+template<typename T, typename U> void swap(Y<T, U>&, Y<T, U>&);
+void swap(Z4&, Z4&);
+
+struct Z5 {
+ int f(int);
+ float f(float);
+};
+
+template<typename T>
+void unresolved_exprs(T &x) {
+ swap(x, x);
+ Z5 z5;
+ z5.f(x);
+ swap<T>(x, x);
+}
+
// RUN: c-index-test -test-load-source all %s | FileCheck -check-prefix=CHECK-LOAD %s
// CHECK-LOAD: index-templates.cpp:4:6: FunctionTemplate=f:4:6 Extent=[3:1 - 4:22]
// CHECK-LOAD: index-templates.cpp:3:19: TemplateTypeParameter=T:3:19 (Definition) Extent=[3:19 - 3:20]
// CHECK-LOAD: index-templates.cpp:55:8: MemberRefExpr=getAs:50:26 Extent=[55:3 - 55:23]
// CHECK-LOAD: index-templates.cpp:55:3: CallExpr= Extent=[55:3 - 55:7]
// CHECK-LOAD: index-templates.cpp:55:14: TypeRef=Unsigned:42:18 Extent=[55:14 - 55:22]
+// CHECK-LOAD: index-templates.cpp:68:6: FunctionTemplate=unresolved_exprs:68:6 (Definition)
+// CHECK-LOAD: index-templates.cpp:69:3: OverloadedDeclRef=swap[60:6, 59:39, 58:27]
+// CHECK-LOAD: index-templates.cpp:71:6: OverloadedDeclRef=f[63:7, 64:9]
+// CHECK-LOAD: index-templates.cpp:72:3: OverloadedDeclRef=swap[58:27, 59:39]
// RUN: c-index-test -test-load-source-usrs all %s | FileCheck -check-prefix=CHECK-USRS %s
// CHECK-USRS: index-templates.cpp c:@FT@>3#T#Nt0.0#t>2#T#Nt1.0f#>t0.22t0.0# Extent=[3:1 - 4:22]
// CHECK: load-namespaces.cpp:18:11: Namespace=std:18:11 (Definition) Extent=[18:11 - 20:2]
// CHECK: load-namespaces.cpp:19:7: FunctionDecl=g:19:7 Extent=[19:7 - 19:13]
// CHECK: load-namespaces.cpp:19:12: ParmDecl=:19:12 (Definition) Extent=[19:9 - 19:13]
-// CHECK: load-namespaces.cpp:22:12: UsingDeclaration=g:22:12 Extent=[22:1 - 22:13]
+// CHECK: load-namespaces.cpp:22:12: UsingDeclaration=g[10:8, 19:7] Extent=[22:1 - 22:13]
// CHECK: load-namespaces.cpp:22:7: NamespaceRef=std:18:11 Extent=[22:7 - 22:10]
// CHECK: load-namespaces.cpp:24:11: FunctionDecl=g:24:11 (Definition) Extent=[24:11 - 25:2]
// CHECK: load-namespaces.cpp:24:6: NamespaceRef=std:18:11 Extent=[24:6 - 24:9]
Referenced = clang_getCursorReferenced(Cursor);
if (!clang_equalCursors(Referenced, clang_getNullCursor())) {
- CXSourceLocation Loc = clang_getCursorLocation(Referenced);
- clang_getInstantiationLocation(Loc, 0, &line, &column, 0);
- printf(":%d:%d", line, column);
+ if (clang_getCursorKind(Referenced) == CXCursor_OverloadedDeclRef) {
+ unsigned I, N = clang_getNumOverloadedDecls(Referenced);
+ printf("[");
+ for (I = 0; I != N; ++I) {
+ CXCursor Ovl = clang_getOverloadedDecl(Referenced, I);
+ if (I)
+ printf(", ");
+
+ CXSourceLocation Loc = clang_getCursorLocation(Ovl);
+ clang_getInstantiationLocation(Loc, 0, &line, &column, 0);
+ printf("%d:%d", line, column);
+ }
+ printf("]");
+ } else {
+ CXSourceLocation Loc = clang_getCursorLocation(Referenced);
+ clang_getInstantiationLocation(Loc, 0, &line, &column, 0);
+ printf(":%d:%d", line, column);
+ }
}
if (clang_isCursorDefinition(Cursor))
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());
}
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:
}
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;
// 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()) {
}
}
- // FIXME: We don't have a way to visit all of the declarations referenced
- // here.
return false;
}
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>");
}
return createCXString("MemberRef");
case CXCursor_LabelRef:
return createCXString("LabelRef");
+ case CXCursor_OverloadedDeclRef:
+ return createCXString("OverloadedDeclRef");
case CXCursor_UnexposedExpr:
return createCXString("UnexposedExpr");
case CXCursor_BlockExpr:
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");
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");
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();
}
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");
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(
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())
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,
#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);
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];
}
#include "clang-c/Index.h"
#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/PointerUnion.h"
#include <utility>
namespace clang {
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);
/// \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);
_clang_getNullRange
_clang_getNumCompletionChunks
_clang_getNumDiagnostics
+_clang_getNumOverloadedDecls
+_clang_getOverloadedDecl
_clang_getPointeeType
_clang_getRange
_clang_getRangeEnd
clang_getNullRange
clang_getNumCompletionChunks
clang_getNumDiagnostics
+clang_getNumOverloadedDecls
+clang_getOverloadedDecl
clang_getPointeeType
clang_getRange
clang_getRangeEnd