From: Argyrios Kyrtzidis Date: Sat, 28 May 2011 03:56:11 +0000 (+0000) Subject: Add a couple of helper methods in the SourceManager API, isAtStartOfMacroInstantiatio... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=469244a322dd5d35cee1d02d70a2edbc12ac5ce7;p=clang Add a couple of helper methods in the SourceManager API, isAtStartOfMacroInstantiation/isAtEndOfMacroInstantiation useful only for source locations that point at a macro token. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@132247 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/SourceManager.h b/include/clang/Basic/SourceManager.h index c121bbb34f..df5074cb42 100644 --- a/include/clang/Basic/SourceManager.h +++ b/include/clang/Basic/SourceManager.h @@ -831,6 +831,14 @@ public: return getFileCharacteristic(Loc) == SrcMgr::C_ExternCSystem; } + /// \brief Returns true if the given MacroID location points at the first + /// token of the macro instantiation. + bool isAtStartOfMacroInstantiation(SourceLocation Loc) const; + + /// \brief Returns true if the given MacroID location points at the last + /// token of the macro instantiation. + bool isAtEndOfMacroInstantiation(SourceLocation Loc) const; + //===--------------------------------------------------------------------===// // Line Table Manipulation Routines //===--------------------------------------------------------------------===// diff --git a/lib/Basic/SourceManager.cpp b/lib/Basic/SourceManager.cpp index ae7de2d3c9..2de8ab7528 100644 --- a/lib/Basic/SourceManager.cpp +++ b/lib/Basic/SourceManager.cpp @@ -1213,6 +1213,73 @@ PresumedLoc SourceManager::getPresumedLoc(SourceLocation Loc) const { return PresumedLoc(Filename, LineNo, ColNo, IncludeLoc); } +/// \brief Returns true if the given MacroID location points at the first +/// token of the macro instantiation. +bool SourceManager::isAtStartOfMacroInstantiation(SourceLocation loc) const { + assert(loc.isValid() && loc.isMacroID() && "Expected a valid macro loc"); + + unsigned FID = getFileID(loc).ID; + assert(FID > 1); + std::pair + instRange = getImmediateInstantiationRange(loc); + + bool invalid = false; + const SrcMgr::SLocEntry &Entry = getSLocEntry(FID-1, &invalid); + if (invalid) + return false; + + // If the FileID immediately before it is a file then this is the first token + // in the macro. + if (Entry.isFile()) + return true; + + // If the FileID immediately before it (which is a macro token) is the + // immediate instantiated macro, check this macro token's location. + if (getFileID(instRange.second).ID == FID-1) + return isAtStartOfMacroInstantiation(instRange.first); + + // If the FileID immediately before it (which is a macro token) came from a + // different instantiation, then this is the first token in the macro. + if (getInstantiationLoc(Entry.getInstantiation().getInstantiationLocStart()) + != getInstantiationLoc(loc)) + return true; + + // It is inside the macro or the last token in the macro. + return false; +} + +/// \brief Returns true if the given MacroID location points at the last +/// token of the macro instantiation. +bool SourceManager::isAtEndOfMacroInstantiation(SourceLocation loc) const { + assert(loc.isValid() && loc.isMacroID() && "Expected a valid macro loc"); + + unsigned FID = getFileID(loc).ID; + assert(FID > 1); + std::pair + instRange = getInstantiationRange(loc); + + // If there's no FileID after it, it is the last token in the macro. + if (FID+1 == sloc_entry_size()) + return true; + + bool invalid = false; + const SrcMgr::SLocEntry &Entry = getSLocEntry(FID+1, &invalid); + if (invalid) + return false; + + // If the FileID immediately after it is a file or a macro token which + // came from a different instantiation, then this is the last token in the + // macro. + if (Entry.isFile()) + return true; + if (getInstantiationLoc(Entry.getInstantiation().getInstantiationLocStart()) + != instRange.first) + return true; + + // It is inside the macro or the first token in the macro. + return false; +} + //===----------------------------------------------------------------------===// // Other miscellaneous methods. //===----------------------------------------------------------------------===//