[cfe-commits] r148551 - in /cfe/trunk: lib/Lex/Lexer.cpp unittests/Lex/LexerTest.cpp

Argyrios Kyrtzidis akyrtzi at gmail.com
Fri Jan 20 08:52:43 PST 2012


Author: akirtzidis
Date: Fri Jan 20 10:52:43 2012
New Revision: 148551

URL: http://llvm.org/viewvc/llvm-project?rev=148551&view=rev
Log:
Enhance Lexer::makeFileCharRange to check for ranges inside a macro argument
expansion, in which case it returns a file range in the location where the
argument was spelled.

Modified:
    cfe/trunk/lib/Lex/Lexer.cpp
    cfe/trunk/unittests/Lex/LexerTest.cpp

Modified: cfe/trunk/lib/Lex/Lexer.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/Lexer.cpp?rev=148551&r1=148550&r2=148551&view=diff
==============================================================================
--- cfe/trunk/lib/Lex/Lexer.cpp (original)
+++ cfe/trunk/lib/Lex/Lexer.cpp Fri Jan 20 10:52:43 2012
@@ -30,6 +30,7 @@
 #include "clang/Lex/CodeCompletionHandler.h"
 #include "clang/Basic/SourceManager.h"
 #include "llvm/ADT/StringSwitch.h"
+#include "llvm/ADT/STLExtras.h"
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/MemoryBuffer.h"
 #include <cstring>
@@ -792,6 +793,30 @@
   return isAtEndOfMacroExpansion(expansionLoc, SM, LangOpts, MacroEnd);
 }
 
+static CharSourceRange makeRangeFromFileLocs(SourceLocation Begin,
+                                             SourceLocation End,
+                                             const SourceManager &SM,
+                                             const LangOptions &LangOpts) {
+  assert(Begin.isFileID() && End.isFileID());
+  End = Lexer::getLocForEndOfToken(End, 0, SM,LangOpts);
+  if (End.isInvalid())
+    return CharSourceRange();
+
+  // Break down the source locations.
+  FileID FID;
+  unsigned BeginOffs;
+  llvm::tie(FID, BeginOffs) = SM.getDecomposedLoc(Begin);
+  if (FID.isInvalid())
+    return CharSourceRange();
+
+  unsigned EndOffs;
+  if (!SM.isInFileID(End, FID, &EndOffs) ||
+      BeginOffs > EndOffs)
+    return CharSourceRange();
+
+  return CharSourceRange::getCharRange(Begin, End);
+}
+
 /// \brief Accepts a token source range and returns a character range with
 /// file locations.
 /// Returns a null range if a part of the range resides inside a macro
@@ -800,28 +825,53 @@
                                          const SourceManager &SM,
                                          const LangOptions &LangOpts) {
   SourceLocation Begin = TokenRange.getBegin();
-  if (Begin.isInvalid())
+  SourceLocation End = TokenRange.getEnd();
+  if (Begin.isInvalid() || End.isInvalid())
     return CharSourceRange();
 
-  if (Begin.isMacroID())
+  if (Begin.isFileID() && End.isFileID())
+    return makeRangeFromFileLocs(Begin, End, SM, LangOpts);
+
+  if (Begin.isMacroID() && End.isFileID()) {
     if (!isAtStartOfMacroExpansion(Begin, SM, LangOpts, &Begin))
       return CharSourceRange();
+    return makeRangeFromFileLocs(Begin, End, SM, LangOpts);
+  }
 
-  SourceLocation End = getLocForEndOfToken(TokenRange.getEnd(), 0, SM,LangOpts);
-  if (End.isInvalid())
-    return CharSourceRange();
+  if (Begin.isFileID() && End.isMacroID()) {
+    if (!isAtEndOfMacroExpansion(End, SM, LangOpts, &End))
+      return CharSourceRange();
+    return makeRangeFromFileLocs(Begin, End, SM, LangOpts);
+  }
 
-  // Break down the source locations.
-  std::pair<FileID, unsigned> beginInfo = SM.getDecomposedLoc(Begin);
-  if (beginInfo.first.isInvalid())
+  assert(Begin.isMacroID() && End.isMacroID());
+  SourceLocation MacroBegin, MacroEnd;
+  if (isAtStartOfMacroExpansion(Begin, SM, LangOpts, &MacroBegin) &&
+      isAtEndOfMacroExpansion(End, SM, LangOpts, &MacroEnd))
+    return makeRangeFromFileLocs(MacroBegin, MacroEnd, SM, LangOpts);
+
+  FileID FID;
+  unsigned BeginOffs;
+  llvm::tie(FID, BeginOffs) = SM.getDecomposedLoc(Begin);
+  if (FID.isInvalid())
     return CharSourceRange();
 
   unsigned EndOffs;
-  if (!SM.isInFileID(End, beginInfo.first, &EndOffs) ||
-      beginInfo.second > EndOffs)
+  if (!SM.isInFileID(End, FID, &EndOffs) ||
+      BeginOffs > EndOffs)
     return CharSourceRange();
 
-  return CharSourceRange::getCharRange(Begin, End);
+  const SrcMgr::SLocEntry *E = &SM.getSLocEntry(FID);
+  const SrcMgr::ExpansionInfo &Expansion = E->getExpansion();
+  if (Expansion.isMacroArgExpansion() &&
+      Expansion.getSpellingLoc().isFileID()) {
+    SourceLocation SpellLoc = Expansion.getSpellingLoc();
+    return makeRangeFromFileLocs(SpellLoc.getLocWithOffset(BeginOffs),
+                                 SpellLoc.getLocWithOffset(EndOffs),
+                                 SM, LangOpts);
+  }
+
+  return CharSourceRange();
 }
 
 StringRef Lexer::getSourceText(CharSourceRange Range,

Modified: cfe/trunk/unittests/Lex/LexerTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Lex/LexerTest.cpp?rev=148551&r1=148550&r2=148551&view=diff
==============================================================================
--- cfe/trunk/unittests/Lex/LexerTest.cpp (original)
+++ cfe/trunk/unittests/Lex/LexerTest.cpp Fri Jan 20 10:52:43 2012
@@ -58,7 +58,8 @@
 TEST_F(LexerTest, LexAPI) {
   const char *source =
     "#define M(x) [x]\n"
-    "M(foo)";
+    "#define N(x) x\n"
+    "M(foo) N([bar])";
   MemoryBuffer *buf = MemoryBuffer::getMemBuffer(source);
   SourceMgr.createMainFileIDForMemBuffer(buf);
 
@@ -82,10 +83,13 @@
   }
 
   // Make sure we got the tokens that we expected.
-  ASSERT_EQ(3U, toks.size());
+  ASSERT_EQ(6U, toks.size());
   ASSERT_EQ(tok::l_square, toks[0].getKind());
   ASSERT_EQ(tok::identifier, toks[1].getKind());
   ASSERT_EQ(tok::r_square, toks[2].getKind());
+  ASSERT_EQ(tok::l_square, toks[3].getKind());
+  ASSERT_EQ(tok::identifier, toks[4].getKind());
+  ASSERT_EQ(tok::r_square, toks[5].getKind());
   
   SourceLocation lsqrLoc = toks[0].getLocation();
   SourceLocation idLoc = toks[1].getLocation();
@@ -119,6 +123,34 @@
                   CharSourceRange::getTokenRange(SourceRange(lsqrLoc, rsqrLoc)),
                   SourceMgr, LangOpts);
   EXPECT_EQ(text, "M(foo)");
+
+  SourceLocation macroLsqrLoc = toks[3].getLocation();
+  SourceLocation macroIdLoc = toks[4].getLocation();
+  SourceLocation macroRsqrLoc = toks[5].getLocation();
+  SourceLocation fileLsqrLoc = SourceMgr.getSpellingLoc(macroLsqrLoc);
+  SourceLocation fileIdLoc = SourceMgr.getSpellingLoc(macroIdLoc);
+  SourceLocation fileRsqrLoc = SourceMgr.getSpellingLoc(macroRsqrLoc);
+
+  range = Lexer::makeFileCharRange(SourceRange(macroLsqrLoc, macroIdLoc),
+                                   SourceMgr, LangOpts);
+  EXPECT_EQ(SourceRange(fileLsqrLoc, fileIdLoc.getLocWithOffset(3)),
+            range.getAsRange());
+
+  range = Lexer::makeFileCharRange(SourceRange(macroIdLoc, macroRsqrLoc),
+                                   SourceMgr, LangOpts);
+  EXPECT_EQ(SourceRange(fileIdLoc, fileRsqrLoc.getLocWithOffset(1)),
+            range.getAsRange());
+
+  macroPair = SourceMgr.getExpansionRange(macroLsqrLoc);
+  range = Lexer::makeFileCharRange(SourceRange(macroLsqrLoc, macroRsqrLoc),
+                                   SourceMgr, LangOpts);
+  EXPECT_EQ(SourceRange(macroPair.first, macroPair.second.getLocWithOffset(1)),
+            range.getAsRange());
+
+  text = Lexer::getSourceText(
+          CharSourceRange::getTokenRange(SourceRange(macroLsqrLoc, macroIdLoc)),
+          SourceMgr, LangOpts);
+  EXPECT_EQ(text, "[bar");
 }
 
 } // anonymous namespace





More information about the cfe-commits mailing list