From: Douglas Gregor Date: Thu, 9 Sep 2010 22:45:38 +0000 (+0000) Subject: When we parse a pragma, keep track of how that pragma was originally X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=80c60f72848896f867f6b7e664e7060d9e78f019;p=clang When we parse a pragma, keep track of how that pragma was originally spelled (#pragma, _Pragma, __pragma). In -E mode, use that information to add appropriate newlines when translating _Pragma and __pragma into #pragma, like GCC does. Fixes . git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@113553 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Lex/Pragma.h b/include/clang/Lex/Pragma.h index c68555b2f9..8bd2236947 100644 --- a/include/clang/Lex/Pragma.h +++ b/include/clang/Lex/Pragma.h @@ -25,6 +25,28 @@ namespace clang { class IdentifierInfo; class PragmaNamespace; + /** + * \brief Describes how the pragma was introduced, e.g., with #pragma, + * _Pragma, or __pragma. + */ + enum PragmaIntroducerKind { + /** + * \brief The pragma was introduced via #pragma. + */ + PIK_HashPragma, + + /** + * \brief The pragma was introduced via the C99 _Pragma(string-literal). + */ + PIK__Pragma, + + /** + * \brief The pragma was introduced via the Microsoft + * __pragma(token-string). + */ + PIK___pragma + }; + /// PragmaHandler - Instances of this interface defined to handle the various /// pragmas that the language front-end uses. Each handler optionally has a /// name (e.g. "pack") and the HandlePragma method is invoked when a pragma with @@ -42,7 +64,8 @@ public: virtual ~PragmaHandler(); llvm::StringRef getName() const { return Name; } - virtual void HandlePragma(Preprocessor &PP, Token &FirstToken) = 0; + virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &FirstToken) = 0; /// getIfNamespace - If this is a namespace, return it. This is equivalent to /// using a dynamic_cast, but doesn't require RTTI. @@ -55,7 +78,8 @@ class EmptyPragmaHandler : public PragmaHandler { public: EmptyPragmaHandler(); - virtual void HandlePragma(Preprocessor &PP, Token &FirstToken); + virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &FirstToken); }; /// PragmaNamespace - This PragmaHandler subdivides the namespace of pragmas, @@ -90,7 +114,8 @@ public: return Handlers.empty(); } - virtual void HandlePragma(Preprocessor &PP, Token &FirstToken); + virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &FirstToken); virtual PragmaNamespace *getIfNamespace() { return this; } }; diff --git a/include/clang/Lex/Preprocessor.h b/include/clang/Lex/Preprocessor.h index 6b9b89ea5e..752cbed7b3 100644 --- a/include/clang/Lex/Preprocessor.h +++ b/include/clang/Lex/Preprocessor.h @@ -909,8 +909,8 @@ private: /// is not enclosed within a string literal. void HandleMicrosoft__pragma(Token &Tok); - void Handle_Pragma(const std::string &StrVal, SourceLocation PragmaLoc, - SourceLocation RParenLoc); + void Handle_Pragma(unsigned Introducer, const std::string &StrVal, + SourceLocation PragmaLoc, SourceLocation RParenLoc); /// EnterSourceFileWithLexer - Add a lexer to the top of the include stack and /// start lexing tokens from it instead of the current buffer. @@ -981,7 +981,7 @@ private: void HandleElifDirective(Token &Tok); // Pragmas. - void HandlePragmaDirective(); + void HandlePragmaDirective(unsigned Introducer); public: void HandlePragmaOnce(Token &OnceTok); void HandlePragmaMark(); diff --git a/lib/Frontend/PrintPreprocessedOutput.cpp b/lib/Frontend/PrintPreprocessedOutput.cpp index 5ae02f97bd..2159d3e80d 100644 --- a/lib/Frontend/PrintPreprocessedOutput.cpp +++ b/lib/Frontend/PrintPreprocessedOutput.cpp @@ -120,6 +120,8 @@ public: void SetEmittedTokensOnThisLine() { EmittedTokensOnThisLine = true; } bool hasEmittedTokensOnThisLine() const { return EmittedTokensOnThisLine; } + bool StartNewLineIfNeeded(); + virtual void FileChanged(SourceLocation Loc, FileChangeReason Reason, SrcMgr::CharacteristicKind FileType); virtual void Ident(SourceLocation Loc, const std::string &str); @@ -138,7 +140,7 @@ public: return ConcatInfo.AvoidConcat(PrevPrevTok, PrevTok, Tok); } void WriteLineInfo(unsigned LineNo, const char *Extra=0, unsigned ExtraLen=0); - + bool LineMarkersAreDisabled() const { return DisableLineMarkers; } void HandleNewlinesInToken(const char *TokStr, unsigned Len); /// MacroDefined - This hook is called whenever a macro definition is seen. @@ -213,6 +215,17 @@ bool PrintPPOutputPPCallbacks::MoveToLine(unsigned LineNo) { return true; } +bool PrintPPOutputPPCallbacks::StartNewLineIfNeeded() { + if (EmittedTokensOnThisLine || EmittedMacroOnThisLine) { + OS << '\n'; + EmittedTokensOnThisLine = false; + EmittedMacroOnThisLine = false; + ++CurLine; + return true; + } + + return false; +} /// FileChanged - Whenever the preprocessor enters or exits a #include file /// it invokes this handler. Update our conception of the current source @@ -438,12 +451,15 @@ struct UnknownPragmaHandler : public PragmaHandler { UnknownPragmaHandler(const char *prefix, PrintPPOutputPPCallbacks *callbacks) : Prefix(prefix), Callbacks(callbacks) {} - virtual void HandlePragma(Preprocessor &PP, Token &PragmaTok) { + virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &PragmaTok) { // Figure out what line we went to and insert the appropriate number of // newline characters. + if (Introducer == PIK__Pragma || Introducer == PIK___pragma) + 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::eom)) { if (PragmaTok.hasLeadingSpace()) @@ -452,7 +468,7 @@ struct UnknownPragmaHandler : public PragmaHandler { Callbacks->OS.write(&TokSpell[0], TokSpell.size()); PP.LexUnexpandedToken(PragmaTok); } - Callbacks->OS << '\n'; + Callbacks->StartNewLineIfNeeded(); } }; } // end anonymous namespace diff --git a/lib/Lex/PPDirectives.cpp b/lib/Lex/PPDirectives.cpp index 8da7def9ed..5e3b16e60d 100644 --- a/lib/Lex/PPDirectives.cpp +++ b/lib/Lex/PPDirectives.cpp @@ -17,6 +17,7 @@ #include "clang/Lex/MacroInfo.h" #include "clang/Lex/LexDiagnostic.h" #include "clang/Lex/CodeCompletionHandler.h" +#include "clang/Lex/Pragma.h" #include "clang/Basic/FileManager.h" #include "clang/Basic/SourceManager.h" #include "llvm/ADT/APInt.h" @@ -588,7 +589,7 @@ TryAgain: // C99 6.10.6 - Pragma Directive. case tok::pp_pragma: - return HandlePragmaDirective(); + return HandlePragmaDirective(PIK_HashPragma); // GNU Extensions. case tok::pp_import: diff --git a/lib/Lex/Pragma.cpp b/lib/Lex/Pragma.cpp index a7b289e137..3d6bc2aa83 100644 --- a/lib/Lex/Pragma.cpp +++ b/lib/Lex/Pragma.cpp @@ -35,7 +35,9 @@ PragmaHandler::~PragmaHandler() { EmptyPragmaHandler::EmptyPragmaHandler() {} -void EmptyPragmaHandler::HandlePragma(Preprocessor &PP, Token &FirstToken) {} +void EmptyPragmaHandler::HandlePragma(Preprocessor &PP, + PragmaIntroducerKind Introducer, + Token &FirstToken) {} //===----------------------------------------------------------------------===// // PragmaNamespace Implementation. @@ -73,7 +75,9 @@ void PragmaNamespace::RemovePragmaHandler(PragmaHandler *Handler) { Handlers.erase(Handler->getName()); } -void PragmaNamespace::HandlePragma(Preprocessor &PP, Token &Tok) { +void PragmaNamespace::HandlePragma(Preprocessor &PP, + PragmaIntroducerKind Introducer, + Token &Tok) { // Read the 'namespace' that the directive is in, e.g. STDC. Do not macro // expand it, the user can have a STDC #define, that should not affect this. PP.LexUnexpandedToken(Tok); @@ -89,7 +93,7 @@ void PragmaNamespace::HandlePragma(Preprocessor &PP, Token &Tok) { } // Otherwise, pass it down. - Handler->HandlePragma(PP, Tok); + Handler->HandlePragma(PP, Introducer, Tok); } //===----------------------------------------------------------------------===// @@ -98,12 +102,12 @@ void PragmaNamespace::HandlePragma(Preprocessor &PP, Token &Tok) { /// HandlePragmaDirective - The "#pragma" directive has been parsed. Lex the /// rest of the pragma, passing it to the registered pragma handlers. -void Preprocessor::HandlePragmaDirective() { +void Preprocessor::HandlePragmaDirective(unsigned Introducer) { ++NumPragma; // Invoke the first level of pragma handlers which reads the namespace id. Token Tok; - PragmaHandlers->HandlePragma(*this, Tok); + PragmaHandlers->HandlePragma(*this, PragmaIntroducerKind(Introducer), Tok); // If the pragma handler didn't read the rest of the line, consume it now. if (CurPPLexer && CurPPLexer->ParsingPreprocessorDirective) @@ -170,7 +174,7 @@ void Preprocessor::Handle_Pragma(Token &Tok) { } } - Handle_Pragma(StrVal, PragmaLoc, RParenLoc); + Handle_Pragma(PIK__Pragma, StrVal, PragmaLoc, RParenLoc); // Finally, return whatever came after the pragma directive. return Lex(Tok); @@ -216,13 +220,14 @@ void Preprocessor::HandleMicrosoft__pragma(Token &Tok) { SourceLocation RParenLoc = Tok.getLocation(); - Handle_Pragma(StrVal, PragmaLoc, RParenLoc); + Handle_Pragma(PIK___pragma, StrVal, PragmaLoc, RParenLoc); // Finally, return whatever came after the pragma directive. return Lex(Tok); } -void Preprocessor::Handle_Pragma(const std::string &StrVal, +void Preprocessor::Handle_Pragma(unsigned Introducer, + const std::string &StrVal, SourceLocation PragmaLoc, SourceLocation RParenLoc) { @@ -241,7 +246,7 @@ void Preprocessor::Handle_Pragma(const std::string &StrVal, EnterSourceFileWithLexer(TL, 0); // With everything set up, lex this as a #pragma directive. - HandlePragmaDirective(); + HandlePragmaDirective(Introducer); } @@ -704,7 +709,8 @@ namespace { /// PragmaOnceHandler - "#pragma once" marks the file as atomically included. struct PragmaOnceHandler : public PragmaHandler { PragmaOnceHandler() : PragmaHandler("once") {} - virtual void HandlePragma(Preprocessor &PP, Token &OnceTok) { + virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &OnceTok) { PP.CheckEndOfDirective("pragma once"); PP.HandlePragmaOnce(OnceTok); } @@ -714,7 +720,8 @@ struct PragmaOnceHandler : public PragmaHandler { /// rest of the line is not lexed. struct PragmaMarkHandler : public PragmaHandler { PragmaMarkHandler() : PragmaHandler("mark") {} - virtual void HandlePragma(Preprocessor &PP, Token &MarkTok) { + virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &MarkTok) { PP.HandlePragmaMark(); } }; @@ -722,7 +729,8 @@ struct PragmaMarkHandler : public PragmaHandler { /// PragmaPoisonHandler - "#pragma poison x" marks x as not usable. struct PragmaPoisonHandler : public PragmaHandler { PragmaPoisonHandler() : PragmaHandler("poison") {} - virtual void HandlePragma(Preprocessor &PP, Token &PoisonTok) { + virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &PoisonTok) { PP.HandlePragmaPoison(PoisonTok); } }; @@ -731,21 +739,24 @@ struct PragmaPoisonHandler : public PragmaHandler { /// as a system header, which silences warnings in it. struct PragmaSystemHeaderHandler : public PragmaHandler { PragmaSystemHeaderHandler() : PragmaHandler("system_header") {} - virtual void HandlePragma(Preprocessor &PP, Token &SHToken) { + virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &SHToken) { PP.HandlePragmaSystemHeader(SHToken); PP.CheckEndOfDirective("pragma"); } }; struct PragmaDependencyHandler : public PragmaHandler { PragmaDependencyHandler() : PragmaHandler("dependency") {} - virtual void HandlePragma(Preprocessor &PP, Token &DepToken) { + virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &DepToken) { PP.HandlePragmaDependency(DepToken); } }; struct PragmaDebugHandler : public PragmaHandler { PragmaDebugHandler() : PragmaHandler("__debug") {} - virtual void HandlePragma(Preprocessor &PP, Token &DepToken) { + virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &DepToken) { Token Tok; PP.LexUnexpandedToken(Tok); if (Tok.isNot(tok::identifier)) { @@ -783,7 +794,8 @@ struct PragmaDebugHandler : public PragmaHandler { struct PragmaDiagnosticHandler : public PragmaHandler { public: explicit PragmaDiagnosticHandler() : PragmaHandler("diagnostic") {} - virtual void HandlePragma(Preprocessor &PP, Token &DiagToken) { + virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &DiagToken) { Token Tok; PP.LexUnexpandedToken(Tok); if (Tok.isNot(tok::identifier)) { @@ -866,7 +878,8 @@ public: /// PragmaCommentHandler - "#pragma comment ...". struct PragmaCommentHandler : public PragmaHandler { PragmaCommentHandler() : PragmaHandler("comment") {} - virtual void HandlePragma(Preprocessor &PP, Token &CommentTok) { + virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &CommentTok) { PP.HandlePragmaComment(CommentTok); } }; @@ -874,7 +887,8 @@ struct PragmaCommentHandler : public PragmaHandler { /// PragmaMessageHandler - "#pragma message("...")". struct PragmaMessageHandler : public PragmaHandler { PragmaMessageHandler() : PragmaHandler("message") {} - virtual void HandlePragma(Preprocessor &PP, Token &CommentTok) { + virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &CommentTok) { PP.HandlePragmaMessage(CommentTok); } }; @@ -883,7 +897,8 @@ struct PragmaMessageHandler : public PragmaHandler { /// macro on the top of the stack. struct PragmaPushMacroHandler : public PragmaHandler { PragmaPushMacroHandler() : PragmaHandler("push_macro") {} - virtual void HandlePragma(Preprocessor &PP, Token &PushMacroTok) { + virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &PushMacroTok) { PP.HandlePragmaPushMacro(PushMacroTok); } }; @@ -893,7 +908,8 @@ struct PragmaPushMacroHandler : public PragmaHandler { /// macro to the value on the top of the stack. struct PragmaPopMacroHandler : public PragmaHandler { PragmaPopMacroHandler() : PragmaHandler("pop_macro") {} - virtual void HandlePragma(Preprocessor &PP, Token &PopMacroTok) { + virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &PopMacroTok) { PP.HandlePragmaPopMacro(PopMacroTok); } }; @@ -935,7 +951,8 @@ static STDCSetting LexOnOffSwitch(Preprocessor &PP) { /// PragmaSTDC_FP_CONTRACTHandler - "#pragma STDC FP_CONTRACT ...". struct PragmaSTDC_FP_CONTRACTHandler : public PragmaHandler { PragmaSTDC_FP_CONTRACTHandler() : PragmaHandler("FP_CONTRACT") {} - virtual void HandlePragma(Preprocessor &PP, Token &Tok) { + virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &Tok) { // We just ignore the setting of FP_CONTRACT. Since we don't do contractions // at all, our default is OFF and setting it to ON is an optimization hint // we can safely ignore. When we support -ffma or something, we would need @@ -947,7 +964,8 @@ struct PragmaSTDC_FP_CONTRACTHandler : public PragmaHandler { /// PragmaSTDC_FENV_ACCESSHandler - "#pragma STDC FENV_ACCESS ...". struct PragmaSTDC_FENV_ACCESSHandler : public PragmaHandler { PragmaSTDC_FENV_ACCESSHandler() : PragmaHandler("FENV_ACCESS") {} - virtual void HandlePragma(Preprocessor &PP, Token &Tok) { + virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &Tok) { if (LexOnOffSwitch(PP) == STDC_ON) PP.Diag(Tok, diag::warn_stdc_fenv_access_not_supported); } @@ -957,7 +975,8 @@ struct PragmaSTDC_FENV_ACCESSHandler : public PragmaHandler { struct PragmaSTDC_CX_LIMITED_RANGEHandler : public PragmaHandler { PragmaSTDC_CX_LIMITED_RANGEHandler() : PragmaHandler("CX_LIMITED_RANGE") {} - virtual void HandlePragma(Preprocessor &PP, Token &Tok) { + virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &Tok) { LexOnOffSwitch(PP); } }; @@ -965,7 +984,8 @@ struct PragmaSTDC_CX_LIMITED_RANGEHandler : public PragmaHandler { /// PragmaSTDC_UnknownHandler - "#pragma STDC ...". struct PragmaSTDC_UnknownHandler : public PragmaHandler { PragmaSTDC_UnknownHandler() {} - virtual void HandlePragma(Preprocessor &PP, Token &UnknownTok) { + virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &UnknownTok) { // C99 6.10.6p2, unknown forms are not allowed. PP.Diag(UnknownTok, diag::ext_stdc_pragma_ignored); } diff --git a/lib/Parse/ParsePragma.cpp b/lib/Parse/ParsePragma.cpp index ddba09ae0f..42c1c5f5a2 100644 --- a/lib/Parse/ParsePragma.cpp +++ b/lib/Parse/ParsePragma.cpp @@ -21,7 +21,9 @@ using namespace clang; // #pragma GCC visibility comes in two variants: // 'push' '(' [visibility] ')' // 'pop' -void PragmaGCCVisibilityHandler::HandlePragma(Preprocessor &PP, Token &VisTok) { +void PragmaGCCVisibilityHandler::HandlePragma(Preprocessor &PP, + PragmaIntroducerKind Introducer, + Token &VisTok) { SourceLocation VisLoc = VisTok.getLocation(); Token Tok; @@ -74,7 +76,9 @@ void PragmaGCCVisibilityHandler::HandlePragma(Preprocessor &PP, Token &VisTok) { // pack '(' [integer] ')' // pack '(' 'show' ')' // pack '(' ('push' | 'pop') [',' identifier] [, integer] ')' -void PragmaPackHandler::HandlePragma(Preprocessor &PP, Token &PackTok) { +void PragmaPackHandler::HandlePragma(Preprocessor &PP, + PragmaIntroducerKind Introducer, + Token &PackTok) { SourceLocation PackLoc = PackTok.getLocation(); Token Tok; @@ -222,16 +226,22 @@ static void ParseAlignPragma(Sema &Actions, Preprocessor &PP, Token &FirstTok, Actions.ActOnPragmaOptionsAlign(Kind, FirstTok.getLocation(), KindLoc); } -void PragmaAlignHandler::HandlePragma(Preprocessor &PP, Token &AlignTok) { +void PragmaAlignHandler::HandlePragma(Preprocessor &PP, + PragmaIntroducerKind Introducer, + Token &AlignTok) { ParseAlignPragma(Actions, PP, AlignTok, /*IsOptions=*/false); } -void PragmaOptionsHandler::HandlePragma(Preprocessor &PP, Token &OptionsTok) { +void PragmaOptionsHandler::HandlePragma(Preprocessor &PP, + PragmaIntroducerKind Introducer, + Token &OptionsTok) { ParseAlignPragma(Actions, PP, OptionsTok, /*IsOptions=*/true); } // #pragma unused(identifier) -void PragmaUnusedHandler::HandlePragma(Preprocessor &PP, Token &UnusedTok) { +void PragmaUnusedHandler::HandlePragma(Preprocessor &PP, + PragmaIntroducerKind Introducer, + Token &UnusedTok) { // FIXME: Should we be expanding macros here? My guess is no. SourceLocation UnusedLoc = UnusedTok.getLocation(); @@ -298,7 +308,9 @@ void PragmaUnusedHandler::HandlePragma(Preprocessor &PP, Token &UnusedTok) { // #pragma weak identifier // #pragma weak identifier '=' identifier -void PragmaWeakHandler::HandlePragma(Preprocessor &PP, Token &WeakTok) { +void PragmaWeakHandler::HandlePragma(Preprocessor &PP, + PragmaIntroducerKind Introducer, + Token &WeakTok) { // FIXME: Should we be expanding macros here? My guess is no. SourceLocation WeakLoc = WeakTok.getLocation(); diff --git a/lib/Parse/ParsePragma.h b/lib/Parse/ParsePragma.h index 0feaa9919e..9dfaceaead 100644 --- a/lib/Parse/ParsePragma.h +++ b/lib/Parse/ParsePragma.h @@ -25,7 +25,8 @@ class PragmaAlignHandler : public PragmaHandler { public: explicit PragmaAlignHandler(Sema &A) : PragmaHandler("align"), Actions(A) {} - virtual void HandlePragma(Preprocessor &PP, Token &FirstToken); + virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &FirstToken); }; class PragmaGCCVisibilityHandler : public PragmaHandler { @@ -34,7 +35,8 @@ public: explicit PragmaGCCVisibilityHandler(Sema &A) : PragmaHandler("visibility"), Actions(A) {} - virtual void HandlePragma(Preprocessor &PP, Token &FirstToken); + virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &FirstToken); }; class PragmaOptionsHandler : public PragmaHandler { @@ -43,7 +45,8 @@ public: explicit PragmaOptionsHandler(Sema &A) : PragmaHandler("options"), Actions(A) {} - virtual void HandlePragma(Preprocessor &PP, Token &FirstToken); + virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &FirstToken); }; class PragmaPackHandler : public PragmaHandler { @@ -52,7 +55,8 @@ public: explicit PragmaPackHandler(Sema &A) : PragmaHandler("pack"), Actions(A) {} - virtual void HandlePragma(Preprocessor &PP, Token &FirstToken); + virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &FirstToken); }; class PragmaUnusedHandler : public PragmaHandler { @@ -62,7 +66,8 @@ public: PragmaUnusedHandler(Sema &A, Parser& p) : PragmaHandler("unused"), Actions(A), parser(p) {} - virtual void HandlePragma(Preprocessor &PP, Token &FirstToken); + virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &FirstToken); }; class PragmaWeakHandler : public PragmaHandler { @@ -71,7 +76,8 @@ public: explicit PragmaWeakHandler(Sema &A) : PragmaHandler("weak"), Actions(A) {} - virtual void HandlePragma(Preprocessor &PP, Token &FirstToken); + virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &FirstToken); }; } // end namespace clang diff --git a/test/Lexer/pragma-operators.cpp b/test/Lexer/pragma-operators.cpp new file mode 100644 index 0000000000..af346e8c96 --- /dev/null +++ b/test/Lexer/pragma-operators.cpp @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -fms-extensions -E %s | FileCheck %s + +// Test that we properly expand the C99 _Pragma and Microsoft __pragma +// into #pragma directives, with newlines where needed. + +// CHECK: extern +// CHECK: #line +// CHECK: #pragma warning(push) +// CHECK: #line +// CHECK: ; void f0(); +// CHECK: #line +// CHECK: #pragma warning(pop) +// CHECK: #line +// CHECK: ; } +extern "C" { _Pragma("warning(push)"); void f0(); __pragma(warning(pop)); }