]> granicus.if.org Git - clang/commitdiff
Add a couple of helper methods in the SourceManager API, isAtStartOfMacroInstantiatio...
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>
Sat, 28 May 2011 03:56:11 +0000 (03:56 +0000)
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>
Sat, 28 May 2011 03:56:11 +0000 (03:56 +0000)
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

include/clang/Basic/SourceManager.h
lib/Basic/SourceManager.cpp

index c121bbb34f3416d9fb7a68d3d707a2cf239a7c4f..df5074cb42e69f2207b3e0a3eff5c6a68d6e2fbf 100644 (file)
@@ -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
   //===--------------------------------------------------------------------===//
index ae7de2d3c95fbf8fc05cbee29961be0a5821f2b4..2de8ab7528abfef9818626ad81620787331c3b28 100644 (file)
@@ -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<SourceLocation, SourceLocation>
+    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<SourceLocation, SourceLocation>
+    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.
 //===----------------------------------------------------------------------===//