Added clang_getCursorReferenceNameRange to libclang to to retrieve parts of
a cursor reference, from Erik Verbruggen!
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@135920 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp
index df93049..7f8f759 100644
--- a/tools/libclang/CIndex.cpp
+++ b/tools/libclang/CIndex.cpp
@@ -4253,6 +4253,94 @@
*endColumn = SM.getSpellingColumnNumber(Body->getRBracLoc());
}
+namespace {
+typedef llvm::SmallVector<SourceRange, 4> RefNamePieces;
+RefNamePieces buildPieces(unsigned NameFlags, bool IsMemberRefExpr,
+ const DeclarationNameInfo &NI,
+ const SourceRange &QLoc,
+ const ExplicitTemplateArgumentList *TemplateArgs = 0){
+ const bool WantQualifier = NameFlags & CXNameRange_WantQualifier;
+ const bool WantTemplateArgs = NameFlags & CXNameRange_WantTemplateArgs;
+ const bool WantSinglePiece = NameFlags & CXNameRange_WantSinglePiece;
+
+ const DeclarationName::NameKind Kind = NI.getName().getNameKind();
+
+ RefNamePieces Pieces;
+
+ if (WantQualifier && QLoc.isValid())
+ Pieces.push_back(QLoc);
+
+ if (Kind != DeclarationName::CXXOperatorName || IsMemberRefExpr)
+ Pieces.push_back(NI.getLoc());
+
+ if (WantTemplateArgs && TemplateArgs)
+ Pieces.push_back(SourceRange(TemplateArgs->LAngleLoc,
+ TemplateArgs->RAngleLoc));
+
+ if (Kind == DeclarationName::CXXOperatorName) {
+ Pieces.push_back(SourceLocation::getFromRawEncoding(
+ NI.getInfo().CXXOperatorName.BeginOpNameLoc));
+ Pieces.push_back(SourceLocation::getFromRawEncoding(
+ NI.getInfo().CXXOperatorName.EndOpNameLoc));
+ }
+
+ if (WantSinglePiece) {
+ SourceRange R(Pieces.front().getBegin(), Pieces.back().getEnd());
+ Pieces.clear();
+ Pieces.push_back(R);
+ }
+
+ return Pieces;
+}
+}
+
+CXSourceRange clang_getCursorReferenceNameRange(CXCursor C, unsigned NameFlags,
+ unsigned PieceIndex) {
+ RefNamePieces Pieces;
+
+ switch (C.kind) {
+ case CXCursor_MemberRefExpr:
+ if (MemberExpr *E = dyn_cast<MemberExpr>(getCursorExpr(C)))
+ Pieces = buildPieces(NameFlags, true, E->getMemberNameInfo(),
+ E->getQualifierLoc().getSourceRange());
+ break;
+
+ case CXCursor_DeclRefExpr:
+ if (DeclRefExpr *E = dyn_cast<DeclRefExpr>(getCursorExpr(C)))
+ Pieces = buildPieces(NameFlags, false, E->getNameInfo(),
+ E->getQualifierLoc().getSourceRange(),
+ E->getExplicitTemplateArgsOpt());
+ break;
+
+ case CXCursor_CallExpr:
+ if (CXXOperatorCallExpr *OCE =
+ dyn_cast<CXXOperatorCallExpr>(getCursorExpr(C))) {
+ Expr *Callee = OCE->getCallee();
+ if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Callee))
+ Callee = ICE->getSubExpr();
+
+ if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Callee))
+ Pieces = buildPieces(NameFlags, false, DRE->getNameInfo(),
+ DRE->getQualifierLoc().getSourceRange());
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ if (Pieces.empty()) {
+ if (PieceIndex == 0)
+ return clang_getCursorExtent(C);
+ } else if (PieceIndex < Pieces.size()) {
+ SourceRange R = Pieces[PieceIndex];
+ if (R.isValid())
+ return cxloc::translateSourceRange(getCursorContext(C), R);
+ }
+
+ return clang_getNullRange();
+}
+
void clang_enableStackTraces(void) {
llvm::sys::PrintStackTraceOnErrorSignal();
}