From 5f1803210b24b79c1a20f88aa8b0c62191e9d1cb Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Sun, 9 Dec 2007 21:11:08 +0000 Subject: [PATCH] The flags on tokens indicate whether they are the start of a *physical* line, not the start of a logical line. Be careful about this distinction, which affects when newlines are printed and when paste-avoidance happens, etc. This fixes PR1848, thanks to Neil for noticing this! git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@44743 91177308-0d34-0410-b5e6-96231b3b80d8 --- Driver/PrintPreprocessedOutput.cpp | 49 +++++++++++++++++++--------- test/Preprocessor/print_line_track.c | 15 +++++++++ 2 files changed, 48 insertions(+), 16 deletions(-) create mode 100644 test/Preprocessor/print_line_track.c diff --git a/Driver/PrintPreprocessedOutput.cpp b/Driver/PrintPreprocessedOutput.cpp index 9783754654..bdf6d04bc1 100644 --- a/Driver/PrintPreprocessedOutput.cpp +++ b/Driver/PrintPreprocessedOutput.cpp @@ -145,8 +145,8 @@ public: virtual void Ident(SourceLocation Loc, const std::string &str); - void HandleFirstTokOnLine(Token &Tok); - void MoveToLine(SourceLocation Loc); + bool HandleFirstTokOnLine(Token &Tok); + bool MoveToLine(SourceLocation Loc); bool AvoidConcat(const Token &PrevTok, const Token &Tok); }; } @@ -168,14 +168,21 @@ static char *UToStr(unsigned N, char *EndPtr) { /// MoveToLine - Move the output to the source line specified by the location /// object. We can do this by emitting some number of \n's, or be emitting a -/// #line directive. -void PrintPPOutputPPCallbacks::MoveToLine(SourceLocation Loc) { +/// #line directive. This returns false if already at the specified line, true +/// if some newlines were emitted. +bool PrintPPOutputPPCallbacks::MoveToLine(SourceLocation Loc) { if (DisableLineMarkers) { - if (EmittedTokensOnThisLine) { - OutputChar('\n'); - EmittedTokensOnThisLine = false; - } - return; + unsigned LineNo = PP.getSourceManager().getLogicalLineNumber(Loc); + if (LineNo == CurLine) return false; + + CurLine = LineNo; + + if (!EmittedTokensOnThisLine) + return true; + + OutputChar('\n'); + EmittedTokensOnThisLine = false; + return true; } unsigned LineNo = PP.getSourceManager().getLogicalLineNumber(Loc); @@ -185,6 +192,8 @@ void PrintPPOutputPPCallbacks::MoveToLine(SourceLocation Loc) { if (LineNo-CurLine < 8) { if (LineNo-CurLine == 1) OutputChar('\n'); + else if (LineNo == CurLine) + return false; // Phys line moved, but logical line didn't. else { const char *NewLines = "\n\n\n\n\n\n\n\n"; OutputString(NewLines, LineNo-CurLine); @@ -214,6 +223,7 @@ void PrintPPOutputPPCallbacks::MoveToLine(SourceLocation Loc) { OutputString(" 3 4", 4); OutputChar('\n'); } + return true; } @@ -223,8 +233,6 @@ void PrintPPOutputPPCallbacks::MoveToLine(SourceLocation Loc) { void PrintPPOutputPPCallbacks::FileChanged(SourceLocation Loc, FileChangeReason Reason, DirectoryLookup::DirType FileType) { - if (DisableLineMarkers) return; - // Unless we are exiting a #include, make sure to skip ahead to the line the // #include directive was at. SourceManager &SourceMgr = PP.getSourceManager(); @@ -240,6 +248,9 @@ void PrintPPOutputPPCallbacks::FileChanged(SourceLocation Loc, Loc = SourceMgr.getLogicalLoc(Loc); CurLine = SourceMgr.getLineNumber(Loc); + + if (DisableLineMarkers) return; + CurFilename.clear(); CurFilename += SourceMgr.getSourceName(Loc); Lexer::Stringify(CurFilename); @@ -291,11 +302,15 @@ void PrintPPOutputPPCallbacks::Ident(SourceLocation Loc, const std::string &S) { } /// HandleFirstTokOnLine - When emitting a preprocessed file in -E mode, this -/// is called for the first token on each new line. -void PrintPPOutputPPCallbacks::HandleFirstTokOnLine(Token &Tok) { +/// is called for the first token on each new line. If this really is the start +/// of a new logical line, handle it and return true, otherwise return false. +/// This may not be the start of a logical line because the "start of line" +/// marker is set for physical lines, not logical ones. +bool PrintPPOutputPPCallbacks::HandleFirstTokOnLine(Token &Tok) { // Figure out what line we went to and insert the appropriate number of // newline characters. - MoveToLine(Tok.getLocation()); + if (!MoveToLine(Tok.getLocation())) + return false; // Print out space characters so that the first token on a line is // indented for easy reading. @@ -314,6 +329,8 @@ void PrintPPOutputPPCallbacks::HandleFirstTokOnLine(Token &Tok) { // Otherwise, indent the appropriate number of spaces. for (; ColNo > 1; --ColNo) OutputChar(' '); + + return true; } namespace { @@ -547,8 +564,8 @@ void clang::DoPrintPreprocessedInput(unsigned MainFileID, Preprocessor &PP, while (1) { // If this token is at the start of a line, emit newlines if needed. - if (Tok.isAtStartOfLine()) { - Callbacks->HandleFirstTokOnLine(Tok); + if (Tok.isAtStartOfLine() && Callbacks->HandleFirstTokOnLine(Tok)) { + // done. } else if (Tok.hasLeadingSpace() || // If we haven't emitted a token on this line yet, PrevTok isn't // useful to look at and no concatenation could happen anyway. diff --git a/test/Preprocessor/print_line_track.c b/test/Preprocessor/print_line_track.c new file mode 100644 index 0000000000..4fbef7407c --- /dev/null +++ b/test/Preprocessor/print_line_track.c @@ -0,0 +1,15 @@ +/* RUN: clang -E %s | grep 'a 3' + * RUN: clang -E %s | grep 'b 14' + * RUN: clang -E -P %s | grep 'a 3' + * RUN: clang -E -P %s | grep 'b 14' + * PR1848 +*/ + +#define t(x) x + +t(a +3) + +t(b +__LINE__) + -- 2.40.0