123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374 |
- //===- CXSourceLocation.cpp - CXSourceLocations APIs ------------*- C++ -*-===//
- //
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- // See https://llvm.org/LICENSE.txt for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- //
- //===----------------------------------------------------------------------===//
- //
- // This file defines routines for manipulating CXSourceLocations.
- //
- //===----------------------------------------------------------------------===//
- #include "CXSourceLocation.h"
- #include "CIndexer.h"
- #include "CLog.h"
- #include "CXLoadedDiagnostic.h"
- #include "CXString.h"
- #include "CXTranslationUnit.h"
- #include "clang/Basic/FileManager.h"
- #include "clang/Frontend/ASTUnit.h"
- #include "llvm/Support/Compiler.h"
- #include "llvm/Support/Format.h"
- using namespace clang;
- using namespace clang::cxindex;
- //===----------------------------------------------------------------------===//
- // Internal predicates on CXSourceLocations.
- //===----------------------------------------------------------------------===//
- static bool isASTUnitSourceLocation(const CXSourceLocation &L) {
- // If the lowest bit is clear then the first ptr_data entry is a SourceManager
- // pointer, or the CXSourceLocation is a null location.
- return ((uintptr_t)L.ptr_data[0] & 0x1) == 0;
- }
- //===----------------------------------------------------------------------===//
- // Basic construction and comparison of CXSourceLocations and CXSourceRanges.
- //===----------------------------------------------------------------------===//
- CXSourceLocation clang_getNullLocation() {
- CXSourceLocation Result = { { nullptr, nullptr }, 0 };
- return Result;
- }
- unsigned clang_equalLocations(CXSourceLocation loc1, CXSourceLocation loc2) {
- return (loc1.ptr_data[0] == loc2.ptr_data[0] &&
- loc1.ptr_data[1] == loc2.ptr_data[1] &&
- loc1.int_data == loc2.int_data);
- }
- CXSourceRange clang_getNullRange() {
- CXSourceRange Result = { { nullptr, nullptr }, 0, 0 };
- return Result;
- }
- CXSourceRange clang_getRange(CXSourceLocation begin, CXSourceLocation end) {
- if (!isASTUnitSourceLocation(begin)) {
- if (isASTUnitSourceLocation(end))
- return clang_getNullRange();
- CXSourceRange Result = { { begin.ptr_data[0], end.ptr_data[0] }, 0, 0 };
- return Result;
- }
-
- if (begin.ptr_data[0] != end.ptr_data[0] ||
- begin.ptr_data[1] != end.ptr_data[1])
- return clang_getNullRange();
-
- CXSourceRange Result = { { begin.ptr_data[0], begin.ptr_data[1] },
- begin.int_data, end.int_data };
- return Result;
- }
- unsigned clang_equalRanges(CXSourceRange range1, CXSourceRange range2) {
- return range1.ptr_data[0] == range2.ptr_data[0]
- && range1.ptr_data[1] == range2.ptr_data[1]
- && range1.begin_int_data == range2.begin_int_data
- && range1.end_int_data == range2.end_int_data;
- }
- int clang_Range_isNull(CXSourceRange range) {
- return clang_equalRanges(range, clang_getNullRange());
- }
-
-
- CXSourceLocation clang_getRangeStart(CXSourceRange range) {
- // Special decoding for CXSourceLocations for CXLoadedDiagnostics.
- if ((uintptr_t)range.ptr_data[0] & 0x1) {
- CXSourceLocation Result = { { range.ptr_data[0], nullptr }, 0 };
- return Result;
- }
-
- CXSourceLocation Result = { { range.ptr_data[0], range.ptr_data[1] },
- range.begin_int_data };
- return Result;
- }
- CXSourceLocation clang_getRangeEnd(CXSourceRange range) {
- // Special decoding for CXSourceLocations for CXLoadedDiagnostics.
- if ((uintptr_t)range.ptr_data[0] & 0x1) {
- CXSourceLocation Result = { { range.ptr_data[1], nullptr }, 0 };
- return Result;
- }
- CXSourceLocation Result = { { range.ptr_data[0], range.ptr_data[1] },
- range.end_int_data };
- return Result;
- }
- //===----------------------------------------------------------------------===//
- // Getting CXSourceLocations and CXSourceRanges from a translation unit.
- //===----------------------------------------------------------------------===//
- CXSourceLocation clang_getLocation(CXTranslationUnit TU,
- CXFile file,
- unsigned line,
- unsigned column) {
- if (cxtu::isNotUsableTU(TU)) {
- LOG_BAD_TU(TU);
- return clang_getNullLocation();
- }
- if (!file)
- return clang_getNullLocation();
- if (line == 0 || column == 0)
- return clang_getNullLocation();
-
- LogRef Log = Logger::make(__func__);
- ASTUnit *CXXUnit = cxtu::getASTUnit(TU);
- ASTUnit::ConcurrencyCheck Check(*CXXUnit);
- const FileEntry *File = static_cast<const FileEntry *>(file);
- SourceLocation SLoc = CXXUnit->getLocation(File, line, column);
- if (SLoc.isInvalid()) {
- if (Log)
- *Log << llvm::format("(\"%s\", %d, %d) = invalid",
- File->getName().str().c_str(), line, column);
- return clang_getNullLocation();
- }
-
- CXSourceLocation CXLoc =
- cxloc::translateSourceLocation(CXXUnit->getASTContext(), SLoc);
- if (Log)
- *Log << llvm::format("(\"%s\", %d, %d) = ", File->getName().str().c_str(),
- line, column)
- << CXLoc;
- return CXLoc;
- }
-
- CXSourceLocation clang_getLocationForOffset(CXTranslationUnit TU,
- CXFile file,
- unsigned offset) {
- if (cxtu::isNotUsableTU(TU)) {
- LOG_BAD_TU(TU);
- return clang_getNullLocation();
- }
- if (!file)
- return clang_getNullLocation();
- ASTUnit *CXXUnit = cxtu::getASTUnit(TU);
- SourceLocation SLoc
- = CXXUnit->getLocation(static_cast<const FileEntry *>(file), offset);
- if (SLoc.isInvalid())
- return clang_getNullLocation();
-
- return cxloc::translateSourceLocation(CXXUnit->getASTContext(), SLoc);
- }
- //===----------------------------------------------------------------------===//
- // Routines for expanding and manipulating CXSourceLocations, regardless
- // of their origin.
- //===----------------------------------------------------------------------===//
- static void createNullLocation(CXFile *file, unsigned *line,
- unsigned *column, unsigned *offset) {
- if (file)
- *file = nullptr;
- if (line)
- *line = 0;
- if (column)
- *column = 0;
- if (offset)
- *offset = 0;
- }
- static void createNullLocation(CXString *filename, unsigned *line,
- unsigned *column, unsigned *offset = nullptr) {
- if (filename)
- *filename = cxstring::createEmpty();
- if (line)
- *line = 0;
- if (column)
- *column = 0;
- if (offset)
- *offset = 0;
- }
- int clang_Location_isInSystemHeader(CXSourceLocation location) {
- const SourceLocation Loc =
- SourceLocation::getFromRawEncoding(location.int_data);
- if (Loc.isInvalid())
- return 0;
- const SourceManager &SM =
- *static_cast<const SourceManager*>(location.ptr_data[0]);
- return SM.isInSystemHeader(Loc);
- }
- int clang_Location_isFromMainFile(CXSourceLocation location) {
- const SourceLocation Loc =
- SourceLocation::getFromRawEncoding(location.int_data);
- if (Loc.isInvalid())
- return 0;
- const SourceManager &SM =
- *static_cast<const SourceManager*>(location.ptr_data[0]);
- return SM.isWrittenInMainFile(Loc);
- }
- void clang_getExpansionLocation(CXSourceLocation location,
- CXFile *file,
- unsigned *line,
- unsigned *column,
- unsigned *offset) {
- if (!isASTUnitSourceLocation(location)) {
- CXLoadedDiagnostic::decodeLocation(location, file, line, column, offset);
- return;
- }
- SourceLocation Loc = SourceLocation::getFromRawEncoding(location.int_data);
- if (!location.ptr_data[0] || Loc.isInvalid()) {
- createNullLocation(file, line, column, offset);
- return;
- }
- const SourceManager &SM =
- *static_cast<const SourceManager*>(location.ptr_data[0]);
- SourceLocation ExpansionLoc = SM.getExpansionLoc(Loc);
-
- // Check that the FileID is invalid on the expansion location.
- // This can manifest in invalid code.
- FileID fileID = SM.getFileID(ExpansionLoc);
- bool Invalid = false;
- const SrcMgr::SLocEntry &sloc = SM.getSLocEntry(fileID, &Invalid);
- if (Invalid || !sloc.isFile()) {
- createNullLocation(file, line, column, offset);
- return;
- }
-
- if (file)
- *file = const_cast<FileEntry *>(SM.getFileEntryForSLocEntry(sloc));
- if (line)
- *line = SM.getExpansionLineNumber(ExpansionLoc);
- if (column)
- *column = SM.getExpansionColumnNumber(ExpansionLoc);
- if (offset)
- *offset = SM.getDecomposedLoc(ExpansionLoc).second;
- }
- void clang_getPresumedLocation(CXSourceLocation location,
- CXString *filename,
- unsigned *line,
- unsigned *column) {
- if (!isASTUnitSourceLocation(location)) {
- // Other SourceLocation implementations do not support presumed locations
- // at this time.
- createNullLocation(filename, line, column);
- return;
- }
- SourceLocation Loc = SourceLocation::getFromRawEncoding(location.int_data);
- if (!location.ptr_data[0] || Loc.isInvalid()) {
- createNullLocation(filename, line, column);
- return;
- }
- const SourceManager &SM =
- *static_cast<const SourceManager *>(location.ptr_data[0]);
- PresumedLoc PreLoc = SM.getPresumedLoc(Loc);
- if (PreLoc.isInvalid()) {
- createNullLocation(filename, line, column);
- return;
- }
- if (filename) *filename = cxstring::createRef(PreLoc.getFilename());
- if (line) *line = PreLoc.getLine();
- if (column) *column = PreLoc.getColumn();
- }
- void clang_getInstantiationLocation(CXSourceLocation location,
- CXFile *file,
- unsigned *line,
- unsigned *column,
- unsigned *offset) {
- // Redirect to new API.
- clang_getExpansionLocation(location, file, line, column, offset);
- }
- void clang_getSpellingLocation(CXSourceLocation location,
- CXFile *file,
- unsigned *line,
- unsigned *column,
- unsigned *offset) {
- if (!isASTUnitSourceLocation(location)) {
- CXLoadedDiagnostic::decodeLocation(location, file, line,
- column, offset);
- return;
- }
-
- SourceLocation Loc = SourceLocation::getFromRawEncoding(location.int_data);
-
- if (!location.ptr_data[0] || Loc.isInvalid())
- return createNullLocation(file, line, column, offset);
-
- const SourceManager &SM =
- *static_cast<const SourceManager*>(location.ptr_data[0]);
- // FIXME: This should call SourceManager::getSpellingLoc().
- SourceLocation SpellLoc = SM.getFileLoc(Loc);
- std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(SpellLoc);
- FileID FID = LocInfo.first;
- unsigned FileOffset = LocInfo.second;
-
- if (FID.isInvalid())
- return createNullLocation(file, line, column, offset);
-
- if (file)
- *file = const_cast<FileEntry *>(SM.getFileEntryForID(FID));
- if (line)
- *line = SM.getLineNumber(FID, FileOffset);
- if (column)
- *column = SM.getColumnNumber(FID, FileOffset);
- if (offset)
- *offset = FileOffset;
- }
- void clang_getFileLocation(CXSourceLocation location,
- CXFile *file,
- unsigned *line,
- unsigned *column,
- unsigned *offset) {
- if (!isASTUnitSourceLocation(location)) {
- CXLoadedDiagnostic::decodeLocation(location, file, line,
- column, offset);
- return;
- }
- SourceLocation Loc = SourceLocation::getFromRawEncoding(location.int_data);
- if (!location.ptr_data[0] || Loc.isInvalid())
- return createNullLocation(file, line, column, offset);
- const SourceManager &SM =
- *static_cast<const SourceManager*>(location.ptr_data[0]);
- SourceLocation FileLoc = SM.getFileLoc(Loc);
- std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(FileLoc);
- FileID FID = LocInfo.first;
- unsigned FileOffset = LocInfo.second;
- if (FID.isInvalid())
- return createNullLocation(file, line, column, offset);
- if (file)
- *file = const_cast<FileEntry *>(SM.getFileEntryForID(FID));
- if (line)
- *line = SM.getLineNumber(FID, FileOffset);
- if (column)
- *column = SM.getColumnNumber(FID, FileOffset);
- if (offset)
- *offset = FileOffset;
- }
|