CXCursor_TypeRef = 43,
CXCursor_CXXBaseSpecifier = 44,
/**
- * \brief A reference to a class template, function template, or template
- * template parameter.
+ * \brief A reference to a class template, function template, template
+ * template parameter, or class template partial specialization.
*/
CXCursor_TemplateRef = 45,
/**
* \brief A reference to a namespace or namespace alias.
*/
CXCursor_NamespaceRef = 46,
- CXCursor_LastRef = CXCursor_NamespaceRef,
+ /**
+ * A reference to a member of a struct, union, or class that occurs in some
+ * non-expression context, e.g., a designated initializer.
+ */
+ CXCursor_MemberRef = 47,
+ CXCursor_LastRef = CXCursor_MemberRef,
/* Error conditions */
CXCursor_FirstInvalid = 70,
Pattern->AddChunk(CodeCompletionString::CK_RightParen);
Results.AddResult(CodeCompletionResult(Pattern,
SawLastInitializer? CCP_NextInitializer
- : CCP_MemberDeclaration));
+ : CCP_MemberDeclaration,
+ CXCursor_MemberRef));
SawLastInitializer = false;
}
Results.ExitScope();
Z::Z() : ::X<int>(0), Virt(), b(), c() { }
// RUN: c-index-test -code-completion-at=%s:18:10 %s | FileCheck -check-prefix=CHECK-CC1 %s
-// CHECK-CC1: NotImplemented:{TypedText a}{LeftParen (}{Placeholder args}{RightParen )} (20)
-// CHECK-CC1: NotImplemented:{TypedText b}{LeftParen (}{Placeholder args}{RightParen )} (20)
-// CHECK-CC1: NotImplemented:{TypedText c}{LeftParen (}{Placeholder args}{RightParen )} (20)
+// CHECK-CC1: MemberRef:{TypedText a}{LeftParen (}{Placeholder args}{RightParen )} (20)
+// CHECK-CC1: MemberRef:{TypedText b}{LeftParen (}{Placeholder args}{RightParen )} (20)
+// CHECK-CC1: MemberRef:{TypedText c}{LeftParen (}{Placeholder args}{RightParen )} (20)
// CHECK-CC1: NotImplemented:{TypedText Virt}{LeftParen (}{Placeholder args}{RightParen )} (20)
// CHECK-CC1: NotImplemented:{TypedText X<int>}{LeftParen (}{Placeholder args}{RightParen )} (7)
// CHECK-CC1: NotImplemented:{TypedText Y}{LeftParen (}{Placeholder args}{RightParen )} (20)
// RUN: c-index-test -code-completion-at=%s:18:23 %s | FileCheck -check-prefix=CHECK-CC2 %s
-// CHECK-CC2: NotImplemented:{TypedText a}{LeftParen (}{Placeholder args}{RightParen )} (20)
-// CHECK-CC2: NotImplemented:{TypedText b}{LeftParen (}{Placeholder args}{RightParen )} (20)
-// CHECK-CC2: NotImplemented:{TypedText c}{LeftParen (}{Placeholder args}{RightParen )} (20)
+// CHECK-CC2: MemberRef:{TypedText a}{LeftParen (}{Placeholder args}{RightParen )} (20)
+// CHECK-CC2: MemberRef:{TypedText b}{LeftParen (}{Placeholder args}{RightParen )} (20)
+// CHECK-CC2: MemberRef:{TypedText c}{LeftParen (}{Placeholder args}{RightParen )} (20)
// CHECK-CC2: NotImplemented:{TypedText Virt}{LeftParen (}{Placeholder args}{RightParen )} (20)
// CHECK-CC2: NotImplemented:{TypedText Y}{LeftParen (}{Placeholder args}{RightParen )} (7)
// RUN: c-index-test -code-completion-at=%s:18:36 %s | FileCheck -check-prefix=CHECK-CC3 %s
-// CHECK-CC3: NotImplemented:{TypedText a}{LeftParen (}{Placeholder args}{RightParen )} (20)
-// CHECK-CC3-NOT: NotImplemented:{TypedText b}{LeftParen (}{Placeholder args}{RightParen )}
-// CHECK-CC3: NotImplemented:{TypedText c}{LeftParen (}{Placeholder args}{RightParen )} (7)
+// CHECK-CC3: MemberRef:{TypedText a}{LeftParen (}{Placeholder args}{RightParen )} (20)
+// CHECK-CC3-NOT: MemberRef:{TypedText b}{LeftParen (}{Placeholder args}{RightParen )}
+// CHECK-CC3: MemberRef:{TypedText c}{LeftParen (}{Placeholder args}{RightParen )} (7)
// CHECK-CC3-NOT: NotImplemented:{TypedText Virt}{LeftParen (}{Placeholder args}{RightParen )}
// CHECK-CC3: NotImplemented:{TypedText Y}{LeftParen (}{Placeholder args}{RightParen )} (20)
(void)__has_nothrow_assign(type);
}
+struct Base {
+ Base(int);
+};
+
+struct Derived : public Base {
+ Derived(int x);
+ int member;
+};
+
+Derived::Derived(int x)
+ : member(x), Base(x) {
+}
+
// RUN: c-index-test -test-load-source all %s | FileCheck %s
// CHECK: load-stmts.cpp:1:13: TypedefDecl=T:1:13 (Definition) Extent=[1:13 - 1:14]
// CHECK: load-stmts.cpp:2:8: StructDecl=X:2:8 (Definition) Extent=[2:1 - 2:23]
// CHECK: load-stmts.cpp:90:17: DeclRefExpr=y:88:44 Extent=[90:17 - 90:18]
// CHECK: load-stmts.cpp:91:9: UnexposedExpr= Extent=[91:9 - 91:35]
// CHECK: load-stmts.cpp:91:30: TypeRef=type:89:13 Extent=[91:30 - 91:34]
+// CHECK: load-stmts.cpp:103:10: CXXConstructor=Derived:103:10 (Definition)
+// CHECK: load-stmts.cpp:103:1: TypeRef=struct Derived:98:8 Extent=[103:1 - 103:
+// FIXME: Missing TypeRef for constructor name.
+// CHECK: load-stmts.cpp:103:22: ParmDecl=x:103:22 (Definition)
+// CHECK: load-stmts.cpp:104:5: MemberRef=member:100:7 Extent=[104:5 - 104:11]
+// CHECK: load-stmts.cpp:104:12: DeclRefExpr=x:103:22 Extent=[104:12 - 104:13]
+// CHECK: load-stmts.cpp:104:16: TypeRef=struct Base:94:8 Extent=[104:16 - 104:2
+// CHECK: load-stmts.cpp:104:16: CallExpr= Extent=[104:16 - 104:22]
+// CHECK: load-stmts.cpp:104:21: DeclRefExpr=x:103:22 Extent=[104:21 - 104:22]
#include "clang/Lex/Lexer.h"
#include "clang/Lex/PreprocessingRecord.h"
#include "clang/Lex/Preprocessor.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/CrashRecoveryContext.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Timer.h"
return false;
}
+/// \brief Compare two base or member initializers based on their source order.
+static int CompareCXXBaseOrMemberInitializers(const void* Xp, const void *Yp) {
+ CXXBaseOrMemberInitializer const * const *X
+ = static_cast<CXXBaseOrMemberInitializer const * const *>(Xp);
+ CXXBaseOrMemberInitializer const * const *Y
+ = static_cast<CXXBaseOrMemberInitializer const * const *>(Yp);
+
+ if ((*X)->getSourceOrder() < (*Y)->getSourceOrder())
+ return -1;
+ else if ((*X)->getSourceOrder() > (*Y)->getSourceOrder())
+ return 1;
+ else
+ return 0;
+}
+
bool CursorVisitor::VisitFunctionDecl(FunctionDecl *ND) {
if (TypeSourceInfo *TSInfo = ND->getTypeSourceInfo()) {
// Visit the function declaration's syntactic components in the order
// FIXME: Attributes?
}
- if (ND->isThisDeclarationADefinition() &&
- Visit(MakeCXCursor(ND->getBody(), StmtParent, TU)))
- return true;
+ if (ND->isThisDeclarationADefinition()) {
+ if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(ND)) {
+ // Find the initializers that were written in the source.
+ llvm::SmallVector<CXXBaseOrMemberInitializer *, 4> WrittenInits;
+ for (CXXConstructorDecl::init_iterator I = Constructor->init_begin(),
+ IEnd = Constructor->init_end();
+ I != IEnd; ++I) {
+ if (!(*I)->isWritten())
+ continue;
+
+ WrittenInits.push_back(*I);
+ }
+
+ // Sort the initializers in source order
+ llvm::array_pod_sort(WrittenInits.begin(), WrittenInits.end(),
+ &CompareCXXBaseOrMemberInitializers);
+
+ // Visit the initializers in source order
+ for (unsigned I = 0, N = WrittenInits.size(); I != N; ++I) {
+ CXXBaseOrMemberInitializer *Init = WrittenInits[I];
+ if (Init->isMemberInitializer()) {
+ if (Visit(MakeCursorMemberRef(Init->getMember(),
+ Init->getMemberLocation(), TU)))
+ return true;
+ } else if (TypeSourceInfo *BaseInfo = Init->getBaseClassInfo()) {
+ if (Visit(BaseInfo->getTypeLoc()))
+ return true;
+ }
+
+ // Visit the initializer value.
+ if (Expr *Initializer = Init->getInit())
+ if (Visit(MakeCXCursor(Initializer, ND, TU)))
+ return true;
+ }
+ }
+
+ if (Visit(MakeCXCursor(ND->getBody(), StmtParent, TU)))
+ return true;
+ }
return false;
}
return createCXString(NS->getNameAsString());
}
+ case CXCursor_MemberRef: {
+ FieldDecl *Field = getCursorMemberRef(C).first;
+ assert(Field && "Missing member decl");
+
+ return createCXString(Field->getNameAsString());
+ }
+
default:
return createCXString("<not implemented>");
}
return createCXString("TemplateRef");
case CXCursor_NamespaceRef:
return createCXString("NamespaceRef");
+ case CXCursor_MemberRef:
+ return createCXString("MemberRef");
case CXCursor_UnexposedExpr:
return createCXString("UnexposedExpr");
case CXCursor_BlockExpr:
return cxloc::translateSourceLocation(P.first->getASTContext(), P.second);
}
+ case CXCursor_MemberRef: {
+ std::pair<FieldDecl *, SourceLocation> P = getCursorMemberRef(C);
+ return cxloc::translateSourceLocation(P.first->getASTContext(), P.second);
+ }
+
case CXCursor_CXXBaseSpecifier: {
// FIXME: Figure out what location to return for a CXXBaseSpecifier.
return clang_getNullLocation();
case CXCursor_NamespaceRef:
return getCursorNamespaceRef(C).second;
-
+
+ case CXCursor_MemberRef:
+ return getCursorMemberRef(C).second;
+
case CXCursor_CXXBaseSpecifier:
// FIXME: Figure out what source range to use for a CXBaseSpecifier.
return SourceRange();
case CXCursor_NamespaceRef:
return MakeCXCursor(getCursorNamespaceRef(C).first, CXXUnit);
+ case CXCursor_MemberRef:
+ return MakeCXCursor(getCursorMemberRef(C).first, CXXUnit);
+
case CXCursor_CXXBaseSpecifier: {
CXXBaseSpecifier *B = cxcursor::getCursorCXXBaseSpecifier(C);
return clang_getTypeDeclaration(cxtype::MakeCXType(B->getType(),
reinterpret_cast<uintptr_t>(C.data[1])));
}
+CXCursor cxcursor::MakeCursorMemberRef(FieldDecl *Field, SourceLocation Loc,
+ ASTUnit *TU) {
+
+ assert(Field && TU && "Invalid arguments!");
+ void *RawLoc = reinterpret_cast<void *>(Loc.getRawEncoding());
+ CXCursor C = { CXCursor_MemberRef, { Field, RawLoc, TU } };
+ return C;
+}
+
+std::pair<FieldDecl *, SourceLocation>
+cxcursor::getCursorMemberRef(CXCursor C) {
+ assert(C.kind == CXCursor_MemberRef);
+ return std::make_pair(static_cast<FieldDecl *>(C.data[0]),
+ SourceLocation::getFromRawEncoding(
+ reinterpret_cast<uintptr_t>(C.data[1])));
+}
+
CXCursor cxcursor::MakeCursorCXXBaseSpecifier(CXXBaseSpecifier *B, ASTUnit *TU){
CXCursor C = { CXCursor_CXXBaseSpecifier, { B, 0, TU } };
return C;
class CXXBaseSpecifier;
class Decl;
class Expr;
+class FieldDecl;
class MacroDefinition;
class MacroInstantiation;
class NamedDecl;
/// it references and the location where the reference occurred.
std::pair<NamedDecl *, SourceLocation> getCursorNamespaceRef(CXCursor C);
+/// \brief Create a reference to a field at the given location.
+CXCursor MakeCursorMemberRef(FieldDecl *Field, SourceLocation Loc,
+ ASTUnit *TU);
+
+/// \brief Unpack a MemberRef cursor into the field it references and the
+/// location where the reference occurred.
+std::pair<FieldDecl *, SourceLocation> getCursorMemberRef(CXCursor C);
+
/// \brief Create a CXX base specifier cursor.
CXCursor MakeCursorCXXBaseSpecifier(CXXBaseSpecifier *B, ASTUnit *TU);