Fix bugs in SourceManager::computeMacroArgsCache() and add a unit test for it.

llvm-svn: 147057
This commit is contained in:
Argyrios Kyrtzidis 2011-12-21 16:56:35 +00:00
parent 2403797eec
commit e841c901de
3 changed files with 99 additions and 5 deletions

View File

@ -300,6 +300,11 @@ namespace SrcMgr {
SourceLocation::getFromRawEncoding(ExpansionLocEnd).isInvalid();
}
bool isFunctionMacroExpansion() const {
return getExpansionLocStart().isValid() &&
getExpansionLocStart() != getExpansionLocEnd();
}
/// create - Return a ExpansionInfo for an expansion. Start and End specify
/// the expansion range (where the macro is expanded), and SpellingLoc
/// specifies the spelling location (where the characters from the token

View File

@ -1585,14 +1585,31 @@ void SourceManager::computeMacroArgsCache(MacroArgsMap *&CachePtr,
continue;
}
if (!Entry.getExpansion().isMacroArgExpansion())
const ExpansionInfo &ExpInfo = Entry.getExpansion();
if (ExpInfo.getExpansionLocStart().isFileID()) {
if (!isInFileID(ExpInfo.getExpansionLocStart(), FID))
return; // No more files/macros that may be "contained" in this file.
}
if (!ExpInfo.isMacroArgExpansion())
continue;
SourceLocation SpellLoc =
getSpellingLoc(Entry.getExpansion().getSpellingLoc());
SourceLocation SpellLoc = ExpInfo.getSpellingLoc();
while (!SpellLoc.isFileID()) {
std::pair<FileID, unsigned> LocInfo = getDecomposedLoc(SpellLoc);
const ExpansionInfo &Info = getSLocEntry(LocInfo.first).getExpansion();
if (!Info.isMacroArgExpansion())
break;
SpellLoc = Info.getSpellingLoc().getLocWithOffset(LocInfo.second);
}
if (!SpellLoc.isFileID())
continue;
unsigned BeginOffs;
if (!isInFileID(SpellLoc, FID, &BeginOffs))
return; // No more files/macros that may be "contained" in this file.
continue;
unsigned EndOffs = BeginOffs + getFileIDSize(FileID::get(ID));
// Add a new chunk for this macro argument. A previous macro argument chunk

View File

@ -16,6 +16,7 @@
#include "clang/Lex/ModuleLoader.h"
#include "clang/Lex/HeaderSearch.h"
#include "clang/Lex/Preprocessor.h"
#include "llvm/Config/config.h"
#include "gtest/gtest.h"
@ -105,4 +106,75 @@ TEST_F(SourceManagerTest, isBeforeInTranslationUnit) {
EXPECT_TRUE(SourceMgr.isBeforeInTranslationUnit(idLoc, macroExpEndLoc));
}
#if defined(LLVM_ON_UNIX)
TEST_F(SourceManagerTest, getMacroArgExpandedLocation) {
const char *header =
"#define FM(x,y) x\n";
const char *main =
"#include \"/test-header.h\"\n"
"#define VAL 0\n"
"FM(VAL,0)\n"
"FM(0,VAL)\n"
"FM(FM(0,VAL),0)\n"
"#define CONCAT(X, Y) X##Y\n"
"CONCAT(1,1)\n";
MemoryBuffer *headerBuf = MemoryBuffer::getMemBuffer(header);
MemoryBuffer *mainBuf = MemoryBuffer::getMemBuffer(main);
FileID mainFileID = SourceMgr.createMainFileIDForMemBuffer(mainBuf);
const FileEntry *headerFile = FileMgr.getVirtualFile("/test-header.h",
headerBuf->getBufferSize(), 0);
SourceMgr.overrideFileContents(headerFile, headerBuf);
VoidModuleLoader ModLoader;
HeaderSearch HeaderInfo(FileMgr, Diags);
Preprocessor PP(Diags, LangOpts,
Target.getPtr(),
SourceMgr, HeaderInfo, ModLoader,
/*IILookup =*/ 0,
/*OwnsHeaderSearch =*/false,
/*DelayInitialization =*/ false);
PP.EnterMainSourceFile();
std::vector<Token> toks;
while (1) {
Token tok;
PP.Lex(tok);
if (tok.is(tok::eof))
break;
toks.push_back(tok);
}
// Make sure we got the tokens that we expected.
ASSERT_EQ(4U, toks.size());
ASSERT_EQ(tok::numeric_constant, toks[0].getKind());
ASSERT_EQ(tok::numeric_constant, toks[1].getKind());
ASSERT_EQ(tok::numeric_constant, toks[2].getKind());
ASSERT_EQ(tok::numeric_constant, toks[3].getKind());
SourceLocation defLoc = SourceMgr.translateLineCol(mainFileID, 2, 13);
SourceLocation loc1 = SourceMgr.translateLineCol(mainFileID, 3, 8);
SourceLocation loc2 = SourceMgr.translateLineCol(mainFileID, 4, 4);
SourceLocation loc3 = SourceMgr.translateLineCol(mainFileID, 5, 7);
SourceLocation defLoc2 = SourceMgr.translateLineCol(mainFileID, 6, 22);
defLoc = SourceMgr.getMacroArgExpandedLocation(defLoc);
loc1 = SourceMgr.getMacroArgExpandedLocation(loc1);
loc2 = SourceMgr.getMacroArgExpandedLocation(loc2);
loc3 = SourceMgr.getMacroArgExpandedLocation(loc3);
defLoc2 = SourceMgr.getMacroArgExpandedLocation(defLoc2);
EXPECT_TRUE(defLoc.isFileID());
EXPECT_TRUE(loc1.isFileID());
EXPECT_TRUE(SourceMgr.isMacroArgExpansion(loc2));
EXPECT_TRUE(SourceMgr.isMacroArgExpansion(loc3));
EXPECT_EQ(loc2, toks[1].getLocation());
EXPECT_EQ(loc3, toks[2].getLocation());
EXPECT_TRUE(defLoc2.isFileID());
}
#endif
} // anonymous namespace