Change clang_getDeclExtent() to have the endpoint point to the last character in the last token.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@92869 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/tools/CIndex/CIndex.cpp b/tools/CIndex/CIndex.cpp
index e6b3d60..2c3f737 100644
--- a/tools/CIndex/CIndex.cpp
+++ b/tools/CIndex/CIndex.cpp
@@ -16,6 +16,7 @@
#include "clang/AST/DeclVisitor.h"
#include "clang/AST/StmtVisitor.h"
+#include "clang/Lex/Lexer.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/System/Program.h"
@@ -627,19 +628,53 @@
CXDeclExtent clang_getDeclExtent(CXDecl AnonDecl) {
assert(AnonDecl && "Passed null CXDecl");
NamedDecl *ND = static_cast<NamedDecl *>(AnonDecl);
- SourceManager &SourceMgr = ND->getASTContext().getSourceManager();
+ SourceManager &SM = ND->getASTContext().getSourceManager();
SourceRange R = ND->getSourceRange();
- CXDeclExtent extent;
+ SourceLocation Begin = SM.getInstantiationLoc(R.getBegin());
+ SourceLocation End = SM.getInstantiationLoc(R.getEnd());
+
+ if (!Begin.isValid()) {
+ CXDeclExtent extent = { { 0, 0 }, { 0, 0 } };
+ return extent;
+ }
- SourceLocation L = SourceMgr.getSpellingLoc(R.getBegin());
- extent.begin.line = SourceMgr.getSpellingLineNumber(L);
- extent.begin.column = SourceMgr.getSpellingColumnNumber(L);
+ // FIXME: This is largely copy-paste from
+ ///TextDiagnosticPrinter::HighlightRange. When it is clear that this is
+ // what we want the two routines should be refactored.
- L = SourceMgr.getSpellingLoc(R.getEnd());
- extent.end.line = SourceMgr.getSpellingLineNumber(L);
- extent.end.column = SourceMgr.getSpellingColumnNumber(L);
+ // If the End location and the start location are the same and are a macro
+ // location, then the range was something that came from a macro expansion
+ // or _Pragma. If this is an object-like macro, the best we can do is to
+ // get the range. If this is a function-like macro, we'd also like to
+ // get the arguments.
+ if (Begin == End && R.getEnd().isMacroID())
+ End = SM.getInstantiationRange(R.getEnd()).second;
+
+ assert(SM.getFileID(Begin) == SM.getFileID(End));
+ unsigned StartLineNo = SM.getInstantiationLineNumber(Begin);
+ unsigned EndLineNo = SM.getInstantiationLineNumber(End);
+ // Compute the column number of the start. Keep the column based at 1.
+ unsigned StartColNo = SM.getInstantiationColumnNumber(Begin);
+
+ // Compute the column number of the end.
+ unsigned EndColNo = SM.getInstantiationColumnNumber(End);
+ if (EndColNo) {
+ // Offset the end column by 1 so that we point to the last character
+ // in the last token.
+ --EndColNo;
+
+ // Add in the length of the token, so that we cover multi-char tokens.
+ ASTContext &Ctx = ND->getTranslationUnitDecl()->getASTContext();
+ const LangOptions &LOpts = Ctx.getLangOptions();
+
+ EndColNo += Lexer::MeasureTokenLength(End, SM, LOpts);
+ }
+
+ // Package up the line/column data and return to the caller.
+ CXDeclExtent extent = { { StartLineNo, StartColNo },
+ { EndLineNo, EndColNo } };
return extent;
}