From: Daniel Dunbar Date: Sun, 14 Feb 2010 01:47:29 +0000 (+0000) Subject: CIndex: Stop hiding magic end bit in CXSourceRange locations where clients can't X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=76dd3c2ff274772dc5771cb73f856d14aaf5ee2f;p=clang CIndex: Stop hiding magic end bit in CXSourceRange locations where clients can't see it. Instead, translate the locations up-front when we create a CXSourceRange. - This is part of a move to make CXSourceRange a pure half-open range, which is a more natural API for clients to deal with. More cleanups to follow. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@96144 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/tools/CIndex/CIndex.cpp b/tools/CIndex/CIndex.cpp index 8d887eb32e..a8f9caec85 100644 --- a/tools/CIndex/CIndex.cpp +++ b/tools/CIndex/CIndex.cpp @@ -146,6 +146,51 @@ static RangeComparisonResult RangeCompare(SourceManager &SM, return RangeOverlap; } +/// \brief Translate a Clang source range into a CIndex source range. +/// +/// Clang internally represents ranges where the end location points to the +/// start of the token at the end. However, for external clients it is more +/// useful to have a CXSourceRange be a proper half-open interval. This routine +/// does the appropriate translation. +CXSourceRange cxloc::translateSourceRange(const SourceManager &SM, + const LangOptions &LangOpts, + SourceRange R) { + // 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. + + // We want the last character in this location, so we will adjust the + // instantiation location accordingly. + + // If the location is from a macro instantiation, get the end of the + // instantiation range. + SourceLocation EndLoc = R.getEnd(); + SourceLocation InstLoc = SM.getInstantiationLoc(EndLoc); + if (EndLoc.isMacroID()) + InstLoc = SM.getInstantiationRange(EndLoc).second; + + // Measure the length token we're pointing at, so we can adjust the physical + // location in the file to point at the last character. + // + // FIXME: This won't cope with trigraphs or escaped newlines well. For that, + // we actually need a preprocessor, which isn't currently available + // here. Eventually, we'll switch the pointer data of + // CXSourceLocation/CXSourceRange to a translation unit (CXXUnit), so that the + // preprocessor will be available here. At that point, we can use + // Preprocessor::getLocForEndOfToken(). + if (InstLoc.isValid()) { + unsigned Length = Lexer::MeasureTokenLength(InstLoc, SM, LangOpts); + // FIXME: Temporarily represent as closed range to preserve API + // compatibility. + if (Length) --Length; + EndLoc = EndLoc.getFileLocWithOffset(Length); + } + + CXSourceRange Result = { { (void *)&SM, (void *)&LangOpts }, + R.getBegin().getRawEncoding(), + EndLoc.getRawEncoding() }; + return Result; +} //===----------------------------------------------------------------------===// // Cursor visitor. @@ -1195,35 +1240,8 @@ void clang_getInstantiationLocation(CXSourceLocation location, return; } - // 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. const SourceManager &SM = *Ptr.getPointer(); SourceLocation InstLoc = SM.getInstantiationLoc(Loc); - - if (Ptr.getInt()) { - // We want the last character in this location, so we will adjust - // the instantiation location accordingly. - - // If the location is from a macro instantiation, get the end of - // the instantiation range. - if (Loc.isMacroID()) - InstLoc = SM.getInstantiationRange(Loc).second; - - // Measure the length token we're pointing at, so we can adjust - // the physical location in the file to point at the last - // character. - // FIXME: This won't cope with trigraphs or escaped newlines - // well. For that, we actually need a preprocessor, which isn't - // currently available here. Eventually, we'll switch the pointer - // data of CXSourceLocation/CXSourceRange to a translation unit - // (CXXUnit), so that the preprocessor will be available here. At - // that point, we can use Preprocessor::getLocForEndOfToken(). - unsigned Length = Lexer::MeasureTokenLength(InstLoc, SM, - *static_cast(location.ptr_data[1])); - if (Length > 0) - InstLoc = InstLoc.getFileLocWithOffset(Length - 1); - } if (file) *file = (void *)SM.getFileEntryForID(SM.getFileID(InstLoc)); diff --git a/tools/CIndex/CXSourceLocation.h b/tools/CIndex/CXSourceLocation.h index e1dc7ed966..95b774b24c 100644 --- a/tools/CIndex/CXSourceLocation.h +++ b/tools/CIndex/CXSourceLocation.h @@ -1,4 +1,4 @@ -//===- CXSourceLocation.h - Routines for manipulating CXSourceLocations ---===// +//===- CXSourceLocation.h - CXSourceLocations Utilities ---------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -49,14 +49,14 @@ static inline CXSourceLocation translateSourceLocation(ASTContext &Context, } /// \brief Translate a Clang source range into a CIndex source range. -static inline CXSourceRange translateSourceRange(const SourceManager &SM, - const LangOptions &LangOpts, - SourceRange R) { - CXSourceRange Result = { { (void *)&SM, (void *)&LangOpts }, - R.getBegin().getRawEncoding(), - R.getEnd().getRawEncoding() }; - return Result; -} +/// +/// Clang internally represents ranges where the end location points to the +/// start of the token at the end. However, for external clients it is more +/// useful to have a CXSourceRange be a proper half-open interval. This routine +/// does the appropriate translation. +CXSourceRange translateSourceRange(const SourceManager &SM, + const LangOptions &LangOpts, + SourceRange R); /// \brief Translate a Clang source range into a CIndex source range. static inline CXSourceRange translateSourceRange(ASTContext &Context,