CXCursor_Namespace = 22,
/** \brief A linkage specification, e.g. 'extern "C"'. */
CXCursor_LinkageSpec = 23,
-
+ /** \brief A C++ constructor. */
+ CXCursor_Constructor = 24,
+ /** \brief A C++ destructor. */
+ CXCursor_Destructor = 25,
+ /** \brief A C++ conversion function. */
+ CXCursor_ConversionFunction = 26,
CXCursor_FirstDecl = CXCursor_UnexposedDecl,
- CXCursor_LastDecl = CXCursor_LinkageSpec,
+ CXCursor_LastDecl = CXCursor_ConversionFunction,
/* References */
CXCursor_FirstRef = 40, /* Decl references */
--- /dev/null
+// Test is line- and column-sensitive; see below.
+
+struct X {
+ X(int value);
+ X(const X& x);
+ ~X();
+ operator X*();
+};
+
+// RUN: c-index-test -test-load-source all %s | FileCheck %s
+// CHECK: load-classes.cpp:3:8: StructDecl=X:3:8 (Definition) Extent=[3:1 - 8:2]
+// CHECK: load-classes.cpp:4:3: CXXConstructor=X:4:3 Extent=[4:3 - 4:15]
+// FIXME: missing TypeRef in the constructor name
+// CHECK: load-classes.cpp:4:9: ParmDecl=value:4:9 (Definition) Extent=[4:5 - 4:14]
+// CHECK: load-classes.cpp:5:3: CXXConstructor=X:5:3 Extent=[5:3 - 5:16]
+// FIXME: missing TypeRef in the constructor name
+// CHECK: load-classes.cpp:5:14: ParmDecl=x:5:14 (Definition) Extent=[5:11 - 5:15]
+// CHECK: load-classes.cpp:5:11: TypeRef=struct X:3:8 Extent=[5:11 - 5:12]
+// CHECK: load-classes.cpp:6:3: CXXDestructor=~X:6:3 Extent=[6:3 - 6:7]
+// FIXME: missing TypeRef in the destructor name
+// CHECK: load-classes.cpp:7:3: CXXConversion=operator struct X *:7:3 Extent=[7:3 - 7:16]
+// CHECK: load-classes.cpp:7:12: TypeRef=struct X:3:8 Extent=[7:12 - 7:13]
bool VisitLinkageSpecDecl(LinkageSpecDecl *D);
bool VisitNamespaceDecl(NamespaceDecl *D);
+ // Name visitor
+ bool VisitDeclarationNameInfo(DeclarationNameInfo Name);
+
// Type visitors
- // FIXME: QualifiedTypeLoc doesn't provide any location information
+ bool VisitQualifiedTypeLoc(QualifiedTypeLoc TL);
bool VisitBuiltinTypeLoc(BuiltinTypeLoc TL);
bool VisitTypedefTypeLoc(TypedefTypeLoc TL);
bool VisitUnresolvedUsingTypeLoc(UnresolvedUsingTypeLoc TL);
bool VisitMemberPointerTypeLoc(MemberPointerTypeLoc TL);
bool VisitLValueReferenceTypeLoc(LValueReferenceTypeLoc TL);
bool VisitRValueReferenceTypeLoc(RValueReferenceTypeLoc TL);
- bool VisitFunctionTypeLoc(FunctionTypeLoc TL);
+ bool VisitFunctionTypeLoc(FunctionTypeLoc TL, bool SkipResultType = false);
bool VisitArrayTypeLoc(ArrayTypeLoc TL);
// FIXME: Implement for TemplateSpecializationTypeLoc
// FIXME: Implement visitors here when the unimplemented TypeLocs get
}
bool CursorVisitor::VisitFunctionDecl(FunctionDecl *ND) {
- if (VisitDeclaratorDecl(ND))
- return true;
-
+ if (TypeSourceInfo *TSInfo = ND->getTypeSourceInfo()) {
+ // Visit the function declaration's syntactic components in the order
+ // written. This requires a bit of work.
+ TypeLoc TL = TSInfo->getTypeLoc();
+ FunctionTypeLoc *FTL = dyn_cast<FunctionTypeLoc>(&TL);
+
+ // If we have a function declared directly (without the use of a typedef),
+ // visit just the return type. Otherwise, just visit the function's type
+ // now.
+ if ((FTL && !isa<CXXConversionDecl>(ND) && Visit(FTL->getResultLoc())) ||
+ (!FTL && Visit(TL)))
+ return true;
+
+ // FIXME: Visit the nested-name-specifier, if present.
+
+ // Visit the declaration name.
+ if (VisitDeclarationNameInfo(ND->getNameInfo()))
+ return true;
+
+ // FIXME: Visit explicitly-specified template arguments!
+
+ // Visit the function parameters, if we have a function type.
+ if (FTL && VisitFunctionTypeLoc(*FTL, true))
+ return true;
+
+ // FIXME: Attributes?
+ }
+
if (ND->isThisDeclarationADefinition() &&
Visit(MakeCXCursor(ND->getBody(), StmtParent, TU)))
return true;
return VisitDeclContext(D);
}
+bool CursorVisitor::VisitDeclarationNameInfo(DeclarationNameInfo Name) {
+ switch (Name.getName().getNameKind()) {
+ case clang::DeclarationName::Identifier:
+ case clang::DeclarationName::CXXLiteralOperatorName:
+ case clang::DeclarationName::CXXOperatorName:
+ case clang::DeclarationName::CXXUsingDirective:
+ return false;
+
+ case clang::DeclarationName::CXXConstructorName:
+ case clang::DeclarationName::CXXDestructorName:
+ case clang::DeclarationName::CXXConversionFunctionName:
+ if (TypeSourceInfo *TSInfo = Name.getNamedTypeInfo())
+ return Visit(TSInfo->getTypeLoc());
+ return false;
+
+ case clang::DeclarationName::ObjCZeroArgSelector:
+ case clang::DeclarationName::ObjCOneArgSelector:
+ case clang::DeclarationName::ObjCMultiArgSelector:
+ // FIXME: Per-identifier location info?
+ return false;
+ }
+
+ return false;
+}
+
bool CursorVisitor::VisitLinkageSpecDecl(LinkageSpecDecl *D) {
return VisitDeclContext(D);
}
+bool CursorVisitor::VisitQualifiedTypeLoc(QualifiedTypeLoc TL) {
+ return Visit(TL.getUnqualifiedLoc());
+}
+
bool CursorVisitor::VisitBuiltinTypeLoc(BuiltinTypeLoc TL) {
ASTContext &Context = TU->getASTContext();
return Visit(TL.getPointeeLoc());
}
-bool CursorVisitor::VisitFunctionTypeLoc(FunctionTypeLoc TL) {
- if (Visit(TL.getResultLoc()))
+bool CursorVisitor::VisitFunctionTypeLoc(FunctionTypeLoc TL,
+ bool SkipResultType) {
+ if (!SkipResultType && Visit(TL.getResultLoc()))
return true;
for (unsigned I = 0, N = TL.getNumArgs(); I != N; ++I)
return createCXString("LinkageSpec");
case CXCursor_CXXBaseSpecifier:
return createCXString("C++ base class specifier");
+ case CXCursor_Constructor:
+ return createCXString("CXXConstructor");
+ case CXCursor_Destructor:
+ return createCXString("CXXDestructor");
+ case CXCursor_ConversionFunction:
+ return createCXString("CXXConversion");
}
llvm_unreachable("Unhandled CXCursorKind");