diff --git a/include/clang/Lex/Preprocessor.h b/include/clang/Lex/Preprocessor.h index 6589f84c93138422b7e6c3549c3f77559ff4ad93..0dd9477e922d114a7096838ecc87942b1e4f49a4 100644 --- a/include/clang/Lex/Preprocessor.h +++ b/include/clang/Lex/Preprocessor.h @@ -131,6 +131,9 @@ class Preprocessor : public RefCountedBase<Preprocessor> { /// \brief Whether we have already loaded macros from the external source. mutable bool ReadMacrosFromExternalSource : 1; + /// \brief True if pragmas are enabled. + bool PragmasEnabled : 1; + /// \brief True if we are pre-expanding macro arguments. bool InMacroArgPreExpansion; @@ -416,6 +419,9 @@ public: bool getCommentRetentionState() const { return KeepComments; } + void setPragmasEnabled(bool Enabled) { PragmasEnabled = Enabled; } + bool getPragmasEnabled() const { return PragmasEnabled; } + void SetSuppressIncludeNotFoundError(bool Suppress) { SuppressIncludeNotFoundError = Suppress; } diff --git a/lib/Lex/Pragma.cpp b/lib/Lex/Pragma.cpp index e2a192b01f287c38eed37aff7fe8942724335595..d678ce5d7fbeaa3f67982c3786d0a32af37c3ffd 100644 --- a/lib/Lex/Pragma.cpp +++ b/lib/Lex/Pragma.cpp @@ -103,6 +103,9 @@ void PragmaNamespace::HandlePragma(Preprocessor &PP, /// HandlePragmaDirective - The "#pragma" directive has been parsed. Lex the /// rest of the pragma, passing it to the registered pragma handlers. void Preprocessor::HandlePragmaDirective(unsigned Introducer) { + if (!PragmasEnabled) + return; + ++NumPragma; // Invoke the first level of pragma handlers which reads the namespace id. diff --git a/lib/Lex/Preprocessor.cpp b/lib/Lex/Preprocessor.cpp index 4be59c65f77a515f180b1481b1444936f4873a62..b420c6cd1d289db0bcc4da98466a5fe9f48de356 100644 --- a/lib/Lex/Preprocessor.cpp +++ b/lib/Lex/Preprocessor.cpp @@ -90,7 +90,8 @@ Preprocessor::Preprocessor(DiagnosticsEngine &diags, LangOptions &opts, InMacroArgs = false; InMacroArgPreExpansion = false; NumCachedTokenLexers = 0; - + PragmasEnabled = true; + CachedLexPos = 0; // We haven't read anything from the external source. diff --git a/lib/Rewrite/HTMLRewrite.cpp b/lib/Rewrite/HTMLRewrite.cpp index dc39dde7ff1f9b7ab33e54ac6fde27fcd23cb012..e2da26fc80c5fd96ab71c841a56d6360a29baa8a 100644 --- a/lib/Rewrite/HTMLRewrite.cpp +++ b/lib/Rewrite/HTMLRewrite.cpp @@ -495,6 +495,11 @@ void html::HighlightMacros(Rewriter &R, FileID FID, const Preprocessor& PP) { // Inform the preprocessor that we don't want comments. TmpPP.SetCommentRetentionState(false, false); + // We don't want pragmas either. Although we filtered out #pragma, removing + // _Pragma and __pragma is much harder. + bool PragmasPreviouslyEnabled = TmpPP.getPragmasEnabled(); + TmpPP.setPragmasEnabled(false); + // Enter the tokens we just lexed. This will cause them to be macro expanded // but won't enter sub-files (because we removed #'s). TmpPP.EnterTokenStream(&TokenStream[0], TokenStream.size(), false, false); @@ -571,6 +576,7 @@ void html::HighlightMacros(Rewriter &R, FileID FID, const Preprocessor& PP) { "<span class='macro'>", Expansion.c_str()); } - // Restore diagnostics object back to its own thing. + // Restore the preprocessor's old state. TmpPP.setDiagnostics(*OldDiags); + TmpPP.setPragmasEnabled(PragmasPreviouslyEnabled); } diff --git a/test/Misc/emit-html.c b/test/Misc/emit-html.c index 48c8b61b38de2aaa2e5c0089db77fb4a93476f2b..ec07a60a60668361bfcfde00fd7f177433a17208 100644 --- a/test/Misc/emit-html.c +++ b/test/Misc/emit-html.c @@ -16,3 +16,11 @@ int main(int argc, char **argv) { FOR_ALL_FILES(f) { } #endif +// <rdar://problem/11625964> +// -emit-html filters out # directives, but not _Pragma (or MS __pragma) +// Diagnostic push/pop is stateful, so re-lexing a file can cause problems +// if these pragmas are interpreted normally. +_Pragma("clang diagnostic push") +_Pragma("clang diagnostic ignored \"-Wformat-extra-args\"") +_Pragma("clang diagnostic pop") +