From: Jordan Rose Date: Fri, 15 Jun 2012 23:33:51 +0000 (+0000) Subject: [-E] Emit a rewritten _Pragma on its own line. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=0cdd1fe3ec29b5cbff9a728966ace5c5b5d614f7;p=clang [-E] Emit a rewritten _Pragma on its own line. 1. Teach Lexer that pragma lexers are like macro expansions at EOF. 2. Treat pragmas like #define/#undef when printing. 3. If we just printed a directive, add a newline before any more tokens. (4. Miscellaneous cleanup in PrintPreprocessedOutput.cpp) PR10594 and (two separate related problems) git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@158571 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Frontend/PrintPreprocessedOutput.cpp b/lib/Frontend/PrintPreprocessedOutput.cpp index 9e1587c8fa..7e0bc6bb2d 100644 --- a/lib/Frontend/PrintPreprocessedOutput.cpp +++ b/lib/Frontend/PrintPreprocessedOutput.cpp @@ -87,7 +87,7 @@ private: unsigned CurLine; bool EmittedTokensOnThisLine; - bool EmittedMacroOnThisLine; + bool EmittedDirectiveOnThisLine; SrcMgr::CharacteristicKind FileType; SmallString<512> CurFilename; bool Initialized; @@ -103,7 +103,7 @@ public: CurLine = 0; CurFilename += ""; EmittedTokensOnThisLine = false; - EmittedMacroOnThisLine = false; + EmittedDirectiveOnThisLine = false; FileType = SrcMgr::C_User; Initialized = false; @@ -111,10 +111,15 @@ public: UseLineDirective = PP.getLangOpts().MicrosoftExt; } - void SetEmittedTokensOnThisLine() { EmittedTokensOnThisLine = true; } + void setEmittedTokensOnThisLine() { EmittedTokensOnThisLine = true; } bool hasEmittedTokensOnThisLine() const { return EmittedTokensOnThisLine; } - bool StartNewLineIfNeeded(); + void setEmittedDirectiveOnThisLine() { EmittedDirectiveOnThisLine = true; } + bool hasEmittedDirectiveOnThisLine() const { + return EmittedDirectiveOnThisLine; + } + + bool startNewLineIfNeeded(bool ShouldUpdateCurrentLine = true); virtual void FileChanged(SourceLocation Loc, FileChangeReason Reason, SrcMgr::CharacteristicKind FileType, @@ -158,11 +163,7 @@ public: void PrintPPOutputPPCallbacks::WriteLineInfo(unsigned LineNo, const char *Extra, unsigned ExtraLen) { - if (EmittedTokensOnThisLine || EmittedMacroOnThisLine) { - OS << '\n'; - EmittedTokensOnThisLine = false; - EmittedMacroOnThisLine = false; - } + startNewLineIfNeeded(/*ShouldUpdateCurrentLine=*/false); // Emit #line directives or GNU line markers depending on what mode we're in. if (UseLineDirective) { @@ -207,23 +208,21 @@ bool PrintPPOutputPPCallbacks::MoveToLine(unsigned LineNo) { } else { // Okay, we're in -P mode, which turns off line markers. However, we still // need to emit a newline between tokens on different lines. - if (EmittedTokensOnThisLine || EmittedMacroOnThisLine) { - OS << '\n'; - EmittedTokensOnThisLine = false; - EmittedMacroOnThisLine = false; - } + startNewLineIfNeeded(/*ShouldUpdateCurrentLine=*/false); } CurLine = LineNo; return true; } -bool PrintPPOutputPPCallbacks::StartNewLineIfNeeded() { - if (EmittedTokensOnThisLine || EmittedMacroOnThisLine) { +bool +PrintPPOutputPPCallbacks::startNewLineIfNeeded(bool ShouldUpdateCurrentLine) { + if (EmittedTokensOnThisLine || EmittedDirectiveOnThisLine) { OS << '\n'; EmittedTokensOnThisLine = false; - EmittedMacroOnThisLine = false; - ++CurLine; + EmittedDirectiveOnThisLine = false; + if (ShouldUpdateCurrentLine) + ++CurLine; return true; } @@ -307,7 +306,7 @@ void PrintPPOutputPPCallbacks::MacroDefined(const Token &MacroNameTok, MoveToLine(MI->getDefinitionLoc()); PrintMacroDefinition(*MacroNameTok.getIdentifierInfo(), *MI, PP, OS); - EmittedMacroOnThisLine = true; + setEmittedDirectiveOnThisLine(); } void PrintPPOutputPPCallbacks::MacroUndefined(const Token &MacroNameTok, @@ -317,12 +316,13 @@ void PrintPPOutputPPCallbacks::MacroUndefined(const Token &MacroNameTok, MoveToLine(MacroNameTok.getLocation()); OS << "#undef " << MacroNameTok.getIdentifierInfo()->getName(); - EmittedMacroOnThisLine = true; + setEmittedDirectiveOnThisLine(); } void PrintPPOutputPPCallbacks::PragmaComment(SourceLocation Loc, const IdentifierInfo *Kind, const std::string &Str) { + startNewLineIfNeeded(); MoveToLine(Loc); OS << "#pragma comment(" << Kind->getName(); @@ -343,11 +343,12 @@ void PrintPPOutputPPCallbacks::PragmaComment(SourceLocation Loc, } OS << ')'; - EmittedTokensOnThisLine = true; + setEmittedDirectiveOnThisLine(); } void PrintPPOutputPPCallbacks::PragmaMessage(SourceLocation Loc, StringRef Str) { + startNewLineIfNeeded(); MoveToLine(Loc); OS << "#pragma message("; @@ -366,26 +367,29 @@ void PrintPPOutputPPCallbacks::PragmaMessage(SourceLocation Loc, OS << '"'; OS << ')'; - EmittedTokensOnThisLine = true; + setEmittedDirectiveOnThisLine(); } void PrintPPOutputPPCallbacks:: PragmaDiagnosticPush(SourceLocation Loc, StringRef Namespace) { + startNewLineIfNeeded(); MoveToLine(Loc); OS << "#pragma " << Namespace << " diagnostic push"; - EmittedTokensOnThisLine = true; + setEmittedDirectiveOnThisLine(); } void PrintPPOutputPPCallbacks:: PragmaDiagnosticPop(SourceLocation Loc, StringRef Namespace) { + startNewLineIfNeeded(); MoveToLine(Loc); OS << "#pragma " << Namespace << " diagnostic pop"; - EmittedTokensOnThisLine = true; + setEmittedDirectiveOnThisLine(); } void PrintPPOutputPPCallbacks:: PragmaDiagnostic(SourceLocation Loc, StringRef Namespace, diag::Mapping Map, StringRef Str) { + startNewLineIfNeeded(); MoveToLine(Loc); OS << "#pragma " << Namespace << " diagnostic "; switch (Map) { @@ -403,7 +407,7 @@ PragmaDiagnostic(SourceLocation Loc, StringRef Namespace, break; } OS << " \"" << Str << '"'; - EmittedTokensOnThisLine = true; + setEmittedDirectiveOnThisLine(); } /// HandleFirstTokOnLine - When emitting a preprocessed file in -E mode, this @@ -471,10 +475,9 @@ struct UnknownPragmaHandler : public PragmaHandler { Token &PragmaTok) { // Figure out what line we went to and insert the appropriate number of // newline characters. - Callbacks->StartNewLineIfNeeded(); + Callbacks->startNewLineIfNeeded(); Callbacks->MoveToLine(PragmaTok.getLocation()); Callbacks->OS.write(Prefix, strlen(Prefix)); - Callbacks->SetEmittedTokensOnThisLine(); // Read and print all of the pragma tokens. while (PragmaTok.isNot(tok::eod)) { if (PragmaTok.hasLeadingSpace()) @@ -483,7 +486,7 @@ struct UnknownPragmaHandler : public PragmaHandler { Callbacks->OS.write(&TokSpell[0], TokSpell.size()); PP.LexUnexpandedToken(PragmaTok); } - Callbacks->StartNewLineIfNeeded(); + Callbacks->setEmittedDirectiveOnThisLine(); } }; } // end anonymous namespace @@ -497,6 +500,10 @@ static void PrintPreprocessedTokens(Preprocessor &PP, Token &Tok, PrevPrevTok.startToken(); PrevTok.startToken(); while (1) { + if (Callbacks->hasEmittedDirectiveOnThisLine()) { + Callbacks->startNewLineIfNeeded(); + Callbacks->MoveToLine(Tok.getLocation()); + } // If this token is at the start of a line, emit newlines if needed. if (Tok.isAtStartOfLine() && Callbacks->HandleFirstTokOnLine(Tok)) { @@ -533,7 +540,7 @@ static void PrintPreprocessedTokens(Preprocessor &PP, Token &Tok, if (Tok.getKind() == tok::comment) Callbacks->HandleNewlinesInToken(&S[0], S.size()); } - Callbacks->SetEmittedTokensOnThisLine(); + Callbacks->setEmittedTokensOnThisLine(); if (Tok.is(tok::eof)) break; diff --git a/lib/Lex/Lexer.cpp b/lib/Lex/Lexer.cpp index 69d21f8ad6..4ebe1579d0 100644 --- a/lib/Lex/Lexer.cpp +++ b/lib/Lex/Lexer.cpp @@ -2402,7 +2402,7 @@ bool Lexer::LexEndOfFile(Token &Result, const char *CurPtr) { BufferPtr = CurPtr; // Finally, let the preprocessor handle this. - return PP->HandleEndOfFile(Result); + return PP->HandleEndOfFile(Result, isPragmaLexer()); } /// isNextPPTokenLParen - Return 1 if the next unexpanded token lexed from diff --git a/test/Lexer/pragma-operators.cpp b/test/Lexer/pragma-operators.cpp index d1645adbc2..a76e0b2f97 100644 --- a/test/Lexer/pragma-operators.cpp +++ b/test/Lexer/pragma-operators.cpp @@ -9,7 +9,6 @@ // CHECK: #line // CHECK: #pragma warning(push) // CHECK: int foo() { return 0; } } -// CHECK: #line // CHECK: #pragma warning(pop) #define A(X) extern "C" { __pragma(warning(push)) \ int X() { return 0; } \ diff --git a/test/Preprocessor/_Pragma-location.c b/test/Preprocessor/_Pragma-location.c index 8b68d6ca1f..5031ee4edc 100644 --- a/test/Preprocessor/_Pragma-location.c +++ b/test/Preprocessor/_Pragma-location.c @@ -1,4 +1,47 @@ -// RUN: %clang_cc1 %s -E | not grep 'scratch space' +// RUN: %clang_cc1 %s -fms-extensions -E | FileCheck %s +// We use -fms-extensions to test both _Pragma and __pragma. -#define push _Pragma ("pack(push)") -push +// A long time ago the pragma lexer's buffer showed through in -E output. +// CHECK-NOT: scratch space + +#define push_p _Pragma ("pack(push)") +push_p +// CHECK: #pragma pack(push) + +push_p _Pragma("pack(push)") __pragma(pack(push)) +// CHECK: #pragma pack(push) +// CHECK-NEXT: #line 11 "{{.*}}_Pragma-location.c" +// CHECK-NEXT: #pragma pack(push) +// CHECK-NEXT: #line 11 "{{.*}}_Pragma-location.c" +// CHECK-NEXT: #pragma pack(push) + + +#define __PRAGMA_PUSH_NO_EXTRA_ARG_WARNINGS _Pragma("clang diagnostic push") \ +_Pragma("clang diagnostic ignored \"-Wformat-extra-args\"") +#define __PRAGMA_POP_NO_EXTRA_ARG_WARNINGS _Pragma("clang diagnostic pop") + +void test () { + 1;_Pragma("clang diagnostic push") \ + _Pragma("clang diagnostic ignored \"-Wformat-extra-args\"") + _Pragma("clang diagnostic pop") + + 2;__PRAGMA_PUSH_NO_EXTRA_ARG_WARNINGS + 3;__PRAGMA_POP_NO_EXTRA_ARG_WARNINGS +} + +// CHECK: void test () { +// CHECK-NEXT: 1; +// CHECK-NEXT: #line 24 "{{.*}}_Pragma-location.c" +// CHECK-NEXT: #pragma clang diagnostic push +// CHECK-NEXT: #pragma clang diagnostic ignored "-Wformat-extra-args" +// CHECK-NEXT: #pragma clang diagnostic pop + +// CHECK: 2; +// CHECK-NEXT: #line 28 "{{.*}}_Pragma-location.c" +// CHECK-NEXT: #pragma clang diagnostic push +// CHECK-NEXT: #line 28 "{{.*}}_Pragma-location.c" +// CHECK-NEXT: #pragma clang diagnostic ignored "-Wformat-extra-args" +// CHECK-NEXT: 3; +// CHECK-NEXT: #line 29 "{{.*}}_Pragma-location.c" +// CHECK-NEXT: #pragma clang diagnostic pop +// CHECK-NEXT: } diff --git a/test/Preprocessor/comment_save.c b/test/Preprocessor/comment_save.c index 996c14ca97..1100ea29bb 100644 --- a/test/Preprocessor/comment_save.c +++ b/test/Preprocessor/comment_save.c @@ -10,3 +10,13 @@ #endif /* baz */ // CHECK: /* baz */ + +_Pragma("unknown") // after unknown pragma +// CHECK: #pragma unknown +// CHECK-NEXT: # +// CHECK-NEXT: // after unknown pragma + +_Pragma("comment(\"abc\")") // after known pragma +// CHECK: #pragma comment("abc") +// CHECK-NEXT: # +// CHECK-NEXT: // after known pragma