]> granicus.if.org Git - clang/commitdiff
Disable _Pragma during HTML macro rewriting to keep from crashing.
authorJordan Rose <jordan_rose@apple.com>
Fri, 8 Jun 2012 18:06:21 +0000 (18:06 +0000)
committerJordan Rose <jordan_rose@apple.com>
Fri, 8 Jun 2012 18:06:21 +0000 (18:06 +0000)
The preprocessor's handling of diagnostic push/pops is stateful, so
encountering pragmas during a re-parse causes problems. HTMLRewrite
already filters out normal # directives including #pragma, so it's
clear it's not expected to be interpreting pragmas in this mode.

This fix adds a flag to Preprocessor to explicitly disable pragmas.
The "right" fix might be to separate pragma lexing from pragma
parsing so that we can throw away pragmas like we do preprocessor
directives, but right now it's important to get the fix in.

Note that this has nothing to do with the "hack" of re-using the
input preprocessor in HTMLRewrite. Even if we someday copy the
preprocessor instead of re-using it, the copy would (and should) include
the diagnostic level tables and have the same problems.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@158214 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Lex/Preprocessor.h
lib/Lex/Pragma.cpp
lib/Lex/Preprocessor.cpp
lib/Rewrite/HTMLRewrite.cpp
test/Misc/emit-html.c

index 6589f84c93138422b7e6c3549c3f77559ff4ad93..0dd9477e922d114a7096838ecc87942b1e4f49a4 100644 (file)
@@ -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;
   }
index e2a192b01f287c38eed37aff7fe8942724335595..d678ce5d7fbeaa3f67982c3786d0a32af37c3ffd 100644 (file)
@@ -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.
index 4be59c65f77a515f180b1481b1444936f4873a62..b420c6cd1d289db0bcc4da98466a5fe9f48de356 100644 (file)
@@ -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.
index dc39dde7ff1f9b7ab33e54ac6fde27fcd23cb012..e2da26fc80c5fd96ab71c841a56d6360a29baa8a 100644 (file)
@@ -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);
 }
index 48c8b61b38de2aaa2e5c0089db77fb4a93476f2b..ec07a60a60668361bfcfde00fd7f177433a17208 100644 (file)
@@ -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")
+