Skip to content

Commit 30709b0

Browse files
committed
Implement a new type of FileID: FileIDInfo::MacroExpansion. For tokens that
came from a macro expansion, this allows us to keep track of both where the character data came from and where the logical position of the token is (at the expansion site). This implements Preprocessor/indent_macro.c, and reduces the number of cpp iostream -E diffs vs GCC from 2589 to 2297. llvm-svn: 38557
1 parent 5f4b1ff commit 30709b0

File tree

4 files changed

+85
-22
lines changed

4 files changed

+85
-22
lines changed

clang/Basic/SourceManager.cpp

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,16 @@ unsigned SourceManager::createFileID(const InfoRec *File,
110110
return Result;
111111
}
112112

113+
/// createFileIDForMacroExp - Return a new FileID for a macro expansion at
114+
/// SourcePos, where the macro token character came from PhysicalFileID.
115+
///
116+
unsigned SourceManager::createFileIDForMacroExp(SourceLocation SourcePos,
117+
unsigned PhysicalFileID) {
118+
FileIDs.push_back(FileIDInfo::getMacroExpansion(SourcePos, PhysicalFileID));
119+
return FileIDs.size();
120+
}
121+
122+
113123
/// getCharacterData - Return a pointer to the start of the specified location
114124
/// in the appropriate SourceBuffer. This returns null if it cannot be
115125
/// computed (e.g. invalid SourceLocation).
@@ -126,9 +136,16 @@ const char *SourceManager::getCharacterData(SourceLocation SL) const {
126136
unsigned SourceManager::getColumnNumber(SourceLocation IncludePos) const {
127137
unsigned FileID = IncludePos.getFileID();
128138
if (FileID == 0) return 0;
129-
FileInfo *FileInfo = getFileInfo(FileID);
139+
140+
// If this is a macro, we need to get the instantiation location.
141+
const SrcMgr::FileIDInfo *FIDInfo = getFIDInfo(FileID);
142+
if (FIDInfo->IDType == SrcMgr::FileIDInfo::MacroExpansion) {
143+
IncludePos = FIDInfo->IncludeLoc;
144+
FileID = IncludePos.getFileID();
145+
}
146+
130147
unsigned FilePos = getFilePos(IncludePos);
131-
const SourceBuffer *Buffer = FileInfo->Buffer;
148+
const SourceBuffer *Buffer = getBuffer(FileID);
132149
const char *Buf = Buffer->getBufferStart();
133150

134151
unsigned LineStart = FilePos;
@@ -211,6 +228,19 @@ void SourceManager::PrintStats() const {
211228
std::cerr << FileInfos.size() << " files mapped, " << MemBufferInfos.size()
212229
<< " mem buffers mapped, " << FileIDs.size()
213230
<< " file ID's allocated.\n";
231+
unsigned NumBuffers = 0, NumMacros = 0;
232+
for (unsigned i = 0, e = FileIDs.size(); i != e; ++i) {
233+
if (FileIDs[i].IDType == FileIDInfo::NormalBuffer)
234+
++NumBuffers;
235+
else if (FileIDs[i].IDType == FileIDInfo::MacroExpansion)
236+
++NumMacros;
237+
else
238+
assert(0 && "Unknown FileID!");
239+
}
240+
std::cerr << " " << NumBuffers << " normal buffer FileID's, "
241+
<< NumMacros << " macro expansion FileID's.\n";
242+
243+
214244

215245
unsigned NumLineNumsComputed = 0;
216246
unsigned NumFileBytesMapped = 0;

clang/Lex/MacroExpander.cpp

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "clang/Lex/MacroExpander.h"
1515
#include "clang/Lex/MacroInfo.h"
1616
#include "clang/Lex/Preprocessor.h"
17+
#include "clang/Basic/SourceManager.h"
1718
using namespace llvm;
1819
using namespace clang;
1920

@@ -24,9 +25,6 @@ MacroExpander::MacroExpander(LexerToken &Tok, Preprocessor &pp)
2425
HasLeadingSpace(Tok.hasLeadingSpace()) {
2526
}
2627

27-
28-
29-
3028
/// Lex - Lex and return a token from this macro stream.
3129
///
3230
void MacroExpander::Lex(LexerToken &Tok) {
@@ -38,6 +36,18 @@ void MacroExpander::Lex(LexerToken &Tok) {
3836
Tok = Macro.getReplacementToken(CurToken++);
3937
//Tok.SetLocation(InstantiateLoc);
4038

39+
// The token's current location indicate where the token was lexed from. We
40+
// need this information to compute the spelling of the token, but any
41+
// diagnostics for the expanded token should appear as if they came from
42+
// InstantiateLoc. Pull this information together into a new SourceLocation
43+
// that captures all of this.
44+
unsigned CharFilePos = Tok.getLocation().getRawFilePos();
45+
unsigned CharFileID = Tok.getLocation().getFileID();
46+
47+
unsigned InstantiationFileID =
48+
PP.getSourceManager().createFileIDForMacroExp(InstantiateLoc, CharFileID);
49+
Tok.SetLocation(SourceLocation(InstantiationFileID, CharFilePos));
50+
4151
// If this is the first token, set the lexical properties of the token to
4252
// match the lexical properties of the macro identifier.
4353
if (CurToken == 1) {

clang/Lex/Preprocessor.cpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -349,8 +349,6 @@ void Preprocessor::EnterSourceFile(unsigned FileID,
349349
void Preprocessor::EnterMacro(LexerToken &Tok) {
350350
IdentifierTokenInfo *Identifier = Tok.getIdentifierInfo();
351351
MacroInfo &MI = *Identifier->getMacroInfo();
352-
SourceLocation ExpandLoc = Tok.getLocation();
353-
//unsigned MacroID = SourceMgr.getMacroID(Identifier, ExpandLoc);
354352
if (CurLexer) {
355353
IncludeStack.push_back(IncludeStackInfo(CurLexer, CurNextDirLookup));
356354
CurLexer = 0;
@@ -367,7 +365,6 @@ void Preprocessor::EnterMacro(LexerToken &Tok) {
367365
// Mark the macro as currently disabled, so that it is not recursively
368366
// expanded.
369367
MI.DisableMacro();
370-
371368
CurMacroExpander = new MacroExpander(Tok, *this);
372369
}
373370

clang/include/clang/Basic/SourceManager.h

Lines changed: 40 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,9 @@ namespace SrcMgr {
6767
/// the SourceLocation's offset from the start of the buffer.
6868
/// 2. Macro Expansions. These indicate that the logical location is
6969
/// totally different than the physical location. The logical source
70-
/// location is specified with an explicit SourceLocation object.
70+
/// location is specified by the IncludeLoc. The physical location is
71+
/// the FilePos of the token's SourceLocation combined with the FileID
72+
/// from MacroTokenFileID.
7173
///
7274
struct FileIDInfo {
7375
enum FileIDType {
@@ -76,7 +78,7 @@ namespace SrcMgr {
7678
};
7779

7880
/// The type of this FileID.
79-
FileIDType IDType : 2;
81+
FileIDType IDType;
8082

8183
/// IncludeLoc - The location of the #include that brought in this file.
8284
/// This SourceLocation object has a FileId of 0 for the main file.
@@ -96,9 +98,9 @@ namespace SrcMgr {
9698
const InfoRec *Info;
9799
} NormalBuffer;
98100

99-
/// MacroTokenLoc - This is the raw encoding of a SourceLocation which
100-
/// indicates the physical location of the macro token.
101-
unsigned MacroTokenLoc;
101+
/// MacroTokenFileID - This is the File ID that contains the characters
102+
/// that make up the expanded token.
103+
unsigned MacroTokenFileID;
102104
} u;
103105

104106
/// getNormalBuffer - Return a FileIDInfo object for a normal buffer
@@ -114,13 +116,14 @@ namespace SrcMgr {
114116
}
115117

116118
/// getMacroExpansion - Return a FileID for a macro expansion. IL specifies
117-
/// the instantiation location,
119+
/// the instantiation location, and MacroFID specifies the FileID that the
120+
/// token's characters come from.
118121
static FileIDInfo getMacroExpansion(SourceLocation IL,
119-
SourceLocation TokenLoc) {
122+
unsigned MacroFID) {
120123
FileIDInfo X;
121124
X.IDType = MacroExpansion;
122125
X.IncludeLoc = IL;
123-
X.u.MacroTokenLoc = TokenLoc.getRawEncoding();
126+
X.u.MacroTokenFileID = MacroFID;
124127
return X;
125128
}
126129

@@ -172,10 +175,15 @@ class SourceManager {
172175
return createFileID(createMemBufferInfoRec(Buffer), SourceLocation());
173176
}
174177

178+
/// createFileIDForMacroExp - Return a new FileID for a macro expansion at
179+
/// SourcePos, where the macro token character came from PhysicalFileID.
180+
///
181+
unsigned createFileIDForMacroExp(SourceLocation SourcePos,
182+
unsigned PhysicalFileID);
175183

176184
/// getBuffer - Return the buffer for the specified FileID.
177185
///
178-
const SourceBuffer *getBuffer(unsigned FileID) {
186+
const SourceBuffer *getBuffer(unsigned FileID) const {
179187
return getFileInfo(FileID)->Buffer;
180188
}
181189

@@ -187,12 +195,18 @@ class SourceManager {
187195
}
188196

189197
/// getFilePos - This (efficient) method returns the offset from the start of
190-
/// the file that the specified SourceLocation represents.
198+
/// the file that the specified SourceLocation represents. This returns the
199+
/// location of the physical character data, not the logical file position.
191200
unsigned getFilePos(SourceLocation IncludePos) const {
192-
assert(IncludePos.getFileID()-1 < FileIDs.size() && "Invalid FileID!");
201+
const SrcMgr::FileIDInfo *FIDInfo = getFIDInfo(IncludePos.getFileID());
202+
203+
// For Macros, the physical loc is specified by the MacroTokenFileID.
204+
if (FIDInfo->IDType == SrcMgr::FileIDInfo::MacroExpansion)
205+
FIDInfo = &FileIDs[FIDInfo->u.MacroTokenFileID-1];
206+
193207
// If this file has been split up into chunks, factor in the chunk number
194208
// that the FileID references.
195-
unsigned ChunkNo=FileIDs[IncludePos.getFileID()-1].getNormalBufferChunkNo();
209+
unsigned ChunkNo = FIDInfo->getNormalBufferChunkNo();
196210
return IncludePos.getRawFilePos() +
197211
(ChunkNo << SourceLocation::FilePosBits);
198212
}
@@ -237,9 +251,21 @@ class SourceManager {
237251
/// buffer. This does no caching.
238252
const SrcMgr::InfoRec *createMemBufferInfoRec(const SourceBuffer *Buffer);
239253

240-
const SrcMgr::InfoRec *getInfoRec(unsigned FileID) const {
254+
const SrcMgr::FileIDInfo *getFIDInfo(unsigned FileID) const {
241255
assert(FileID-1 < FileIDs.size() && "Invalid FileID!");
242-
return FileIDs[FileID-1].getNormalBufferInfo();
256+
return &FileIDs[FileID-1];
257+
}
258+
259+
/// Return the InfoRec structure for the specified FileID. This is always the
260+
/// physical reference for the ID.
261+
const SrcMgr::InfoRec *getInfoRec(unsigned FileID) const {
262+
const SrcMgr::FileIDInfo *FIDInfo = getFIDInfo(FileID);
263+
264+
// For Macros, the physical loc is specified by the MacroTokenFileID.
265+
if (FIDInfo->IDType == SrcMgr::FileIDInfo::MacroExpansion)
266+
FIDInfo = &FileIDs[FIDInfo->u.MacroTokenFileID-1];
267+
268+
return FIDInfo->getNormalBufferInfo();
243269
}
244270

245271
SrcMgr::FileInfo *getFileInfo(unsigned FileID) const {

0 commit comments

Comments
 (0)