Skip to content

Commit 0c885f5

Browse files
committed
Improve #line emission in -E mode to include file entry/exits. This is
still pretty hacky because it doesn't compute the 3/4 markers correctly. llvm-svn: 38561
1 parent 9a13bde commit 0c885f5

File tree

3 files changed

+106
-19
lines changed

3 files changed

+106
-19
lines changed

clang/Driver/clang.cpp

+72-14
Original file line numberDiff line numberDiff line change
@@ -588,24 +588,76 @@ static void ReadPrologFiles(Preprocessor &PP, std::vector<char> &Buf) {
588588
// Preprocessed output mode.
589589
//===----------------------------------------------------------------------===//
590590

591+
static unsigned EModeCurLine;
592+
static std::string EModeCurFilename;
593+
static Preprocessor *EModePP;
594+
static bool EmodeEmittedTokensOnThisLine;
595+
596+
static void MoveToLine(unsigned LineNo) {
597+
// If this line is "close enough" to the original line, just print newlines,
598+
// otherwise print a #line directive.
599+
if (LineNo-EModeCurLine < 8) {
600+
for (; EModeCurLine != LineNo; ++EModeCurLine)
601+
std::cout << "\n";
602+
} else {
603+
if (EmodeEmittedTokensOnThisLine) {
604+
std::cout << "\n";
605+
EmodeEmittedTokensOnThisLine = false;
606+
}
607+
608+
std::cout << "# " << LineNo << " " << EModeCurFilename;
609+
610+
// FIXME: calculate system file right.
611+
std::cout << " 3";
612+
613+
std::cout << "\n";
614+
EModeCurLine = LineNo;
615+
}
616+
}
617+
618+
/// HandleFileChange - Whenever the preprocessor enters or exits a #include file
619+
/// it invokes this handler. Update our conception of the current
620+
static void HandleFileChange(SourceLocation Loc, bool EnteringFile) {
621+
SourceManager &SourceMgr = EModePP->getSourceManager();
622+
623+
// If we are entering a new #include, make sure to skip ahead to the line the
624+
// #include directive was at.
625+
if (EnteringFile) {
626+
SourceLocation IncludeLoc = SourceMgr.getIncludeLoc(Loc.getFileID());
627+
MoveToLine(SourceMgr.getLineNumber(IncludeLoc));
628+
}
629+
630+
EModeCurLine = SourceMgr.getLineNumber(Loc);
631+
// FIXME: escape filename right.
632+
EModeCurFilename = '"' + SourceMgr.getSourceName(Loc) + '"';
633+
634+
if (EmodeEmittedTokensOnThisLine) {
635+
std::cout << "\n";
636+
EmodeEmittedTokensOnThisLine = false;
637+
}
638+
std::cout << "# " << EModeCurLine << " " << EModeCurFilename;
639+
if (EnteringFile)
640+
std::cout << " 1";
641+
else
642+
std::cout << " 2";
643+
644+
// FIXME: calculate system file right.
645+
std::cout << " 3";
646+
647+
std::cout << "\n";
648+
}
649+
650+
591651
/// HandleFirstTokOnLine - When emitting a preprocessed file in -E mode, this
592652
/// is called for the first token on each new line.
593-
static void HandleFirstTokOnLine(LexerToken &Tok, Preprocessor &PP,
594-
unsigned &CurLine) {
653+
static void HandleFirstTokOnLine(LexerToken &Tok, Preprocessor &PP) {
595654
// Figure out what line we went to and insert the appropriate number of
596655
// newline characters.
597656
unsigned LineNo = PP.getSourceManager().getLineNumber(Tok.getLocation());
598657

599-
// If this line is "close enough" to the original line, just print newlines,
600-
// otherwise print a #line directive.
601-
if (LineNo-CurLine < 8) {
602-
for (; CurLine != LineNo; ++CurLine)
603-
std::cout << "\n";
604-
} else {
605-
// FIXME: filename too.
606-
std::cout << "\n# " << LineNo << "\n";
607-
CurLine = LineNo;
608-
}
658+
// Move to the specified line.
659+
MoveToLine(LineNo);
660+
609661

610662
// Print out space characters so that the first token on a line is
611663
// indented for easy reading.
@@ -630,7 +682,12 @@ static void HandleFirstTokOnLine(LexerToken &Tok, Preprocessor &PP,
630682
void DoPrintPreprocessedInput(Preprocessor &PP) {
631683
LexerToken Tok;
632684
char Buffer[256];
633-
unsigned CurLine = 1;
685+
EModeCurLine = 0;
686+
EModeCurFilename = "\"<uninit>\"";
687+
PP.setFileChangeHandler(HandleFileChange);
688+
EModePP = &PP;
689+
EmodeEmittedTokensOnThisLine = false;
690+
634691
do {
635692
PP.Lex(Tok);
636693

@@ -640,7 +697,7 @@ void DoPrintPreprocessedInput(Preprocessor &PP) {
640697
// FIXME: For some tests, this fails just because there is no col# info from
641698
// macro expansions!
642699
if (Tok.isAtStartOfLine()) {
643-
HandleFirstTokOnLine(Tok, PP, CurLine);
700+
HandleFirstTokOnLine(Tok, PP);
644701
} else if (Tok.hasLeadingSpace()) {
645702
std::cout << ' ';
646703
}
@@ -652,6 +709,7 @@ void DoPrintPreprocessedInput(Preprocessor &PP) {
652709
} else {
653710
std::cout << PP.getSpelling(Tok);
654711
}
712+
EmodeEmittedTokensOnThisLine = true;
655713
} while (Tok.getKind() != tok::eof);
656714
std::cout << "\n";
657715
}

clang/Lex/Preprocessor.cpp

+16-3
Original file line numberDiff line numberDiff line change
@@ -55,10 +55,13 @@ Preprocessor::Preprocessor(Diagnostic &diags, const LangOptions &opts,
5555
NumEnteredSourceFiles = NumMacroExpanded = NumFastMacroExpanded = 0;
5656
MaxIncludeStackDepth = MaxMacroStackDepth = 0;
5757
NumSkipped = 0;
58-
58+
5959
// Macro expansion is enabled.
6060
DisableMacroExpansion = false;
6161
SkippingContents = false;
62+
63+
// There is no file-change handler yet.
64+
FileChangeHandler = 0;
6265
}
6366

6467
Preprocessor::~Preprocessor() {
@@ -342,6 +345,10 @@ void Preprocessor::EnterSourceFile(unsigned FileID,
342345

343346
CurLexer = new Lexer(Buffer, FileID, *this);
344347
CurNextDirLookup = NextDir;
348+
349+
// Notify the client, if desired, that we are in a new source file.
350+
if (FileChangeHandler)
351+
FileChangeHandler(CurLexer->getSourceLocation(CurLexer->BufferStart), true);
345352
}
346353

347354
/// EnterMacro - Add a Macro to the top of the include stack and start lexing
@@ -464,7 +471,7 @@ void Preprocessor::HandleIdentifier(LexerToken &Identifier) {
464471
/// HandleEndOfFile - This callback is invoked when the lexer hits the end of
465472
/// the current file. This either returns the EOF token or pops a level off
466473
/// the include stack and keeps going.
467-
void Preprocessor::HandleEndOfFile(LexerToken &Result) {
474+
void Preprocessor::HandleEndOfFile(LexerToken &Result, bool isEndOfMacro) {
468475
assert(!CurMacroExpander &&
469476
"Ending a file when currently in a macro!");
470477

@@ -488,6 +495,12 @@ void Preprocessor::HandleEndOfFile(LexerToken &Result) {
488495
CurLexer = IncludeStack.back().TheLexer;
489496
CurNextDirLookup = IncludeStack.back().TheDirLookup;
490497
IncludeStack.pop_back();
498+
499+
// Notify the client, if desired, that we are in a new source file.
500+
if (FileChangeHandler && !isEndOfMacro)
501+
FileChangeHandler(CurLexer->getSourceLocation(CurLexer->BufferPtr),
502+
false);
503+
491504
return Lex(Result);
492505
}
493506

@@ -519,7 +532,7 @@ void Preprocessor::HandleEndOfMacro(LexerToken &Result) {
519532
} else {
520533
CurMacroExpander = 0;
521534
// Handle this like a #include file being popped off the stack.
522-
return HandleEndOfFile(Result);
535+
return HandleEndOfFile(Result, true);
523536
}
524537
}
525538

clang/include/clang/Lex/Preprocessor.h

+18-2
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,13 @@ class Preprocessor {
8787
std::vector<DirectoryLookup> SearchDirs;
8888
unsigned SystemDirIdx;
8989
bool NoCurDirSearch;
90+
91+
/// FileChangeHandler - This callback is invoked whenever a source file is
92+
/// entered or exited. The SourceLocation indicates the new location, and
93+
/// EnteringFile indicates whether this is because we are entering a new
94+
/// #include'd file (when true) or whether we're exiting one because we ran
95+
/// off the end (when false).
96+
void (*FileChangeHandler)(SourceLocation Loc, bool EnteringFile);
9097

9198
enum {
9299
/// MaxIncludeStackDepth - Maximum depth of #includes.
@@ -103,7 +110,6 @@ class Preprocessor {
103110

104111
/// CurLexer - This is the current top of the stack that we're lexing from if
105112
/// not expanding a macro. One of CurLexer and CurMacroExpander must be null.
106-
///
107113
Lexer *CurLexer;
108114

109115
/// CurDirLookup - The next DirectoryLookup structure to search for a file if
@@ -185,6 +191,16 @@ class Preprocessor {
185191
NoCurDirSearch = noCurDirSearch;
186192
}
187193

194+
/// setFileChangeHandler - Set the callback invoked whenever a source file is
195+
/// entered or exited. The SourceLocation indicates the new location, and
196+
/// EnteringFile indicates whether this is because we are entering a new
197+
/// #include'd file (when true) or whether we're exiting one because we ran
198+
/// off the end (when false).
199+
void setFileChangeHandler(void (*Handler)(SourceLocation, bool)) {
200+
FileChangeHandler = Handler;
201+
}
202+
203+
188204
/// getIdentifierInfo - Return information about the specified preprocessor
189205
/// identifier token. The version of this method that takes two character
190206
/// pointers is preferred unless the identifier is already available as a
@@ -302,7 +318,7 @@ class Preprocessor {
302318
/// HandleEndOfFile - This callback is invoked when the lexer hits the end of
303319
/// the current file. This either returns the EOF token or pops a level off
304320
/// the include stack and keeps going.
305-
void HandleEndOfFile(LexerToken &Result);
321+
void HandleEndOfFile(LexerToken &Result, bool isEndOfMacro = false);
306322

307323
/// HandleEndOfMacro - This callback is invoked when the lexer hits the end of
308324
/// the current macro line.

0 commit comments

Comments
 (0)