summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJordan Rose <jordan_rose@apple.com>2012-06-08 18:06:21 +0000
committerJordan Rose <jordan_rose@apple.com>2012-06-08 18:06:21 +0000
commitde1a29277e122a72085ad7f3f5cd76baec010970 (patch)
tree46bbfdb3673cf8889b67fc9bc7f9c52de3b6202f
parent3d464d8068c33e86bbf99498541d7ef6583c15a2 (diff)
downloadbcm5719-llvm-de1a29277e122a72085ad7f3f5cd76baec010970.tar.gz
bcm5719-llvm-de1a29277e122a72085ad7f3f5cd76baec010970.zip
Disable _Pragma during HTML macro rewriting to keep from crashing.
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. llvm-svn: 158214
-rw-r--r--clang/include/clang/Lex/Preprocessor.h6
-rw-r--r--clang/lib/Lex/Pragma.cpp3
-rw-r--r--clang/lib/Lex/Preprocessor.cpp3
-rw-r--r--clang/lib/Rewrite/HTMLRewrite.cpp8
-rw-r--r--clang/test/Misc/emit-html.c8
5 files changed, 26 insertions, 2 deletions
diff --git a/clang/include/clang/Lex/Preprocessor.h b/clang/include/clang/Lex/Preprocessor.h
index 6589f84c931..0dd9477e922 100644
--- a/clang/include/clang/Lex/Preprocessor.h
+++ b/clang/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/clang/lib/Lex/Pragma.cpp b/clang/lib/Lex/Pragma.cpp
index e2a192b01f2..d678ce5d7fb 100644
--- a/clang/lib/Lex/Pragma.cpp
+++ b/clang/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/clang/lib/Lex/Preprocessor.cpp b/clang/lib/Lex/Preprocessor.cpp
index 4be59c65f77..b420c6cd1d2 100644
--- a/clang/lib/Lex/Preprocessor.cpp
+++ b/clang/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/clang/lib/Rewrite/HTMLRewrite.cpp b/clang/lib/Rewrite/HTMLRewrite.cpp
index dc39dde7ff1..e2da26fc80c 100644
--- a/clang/lib/Rewrite/HTMLRewrite.cpp
+++ b/clang/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/clang/test/Misc/emit-html.c b/clang/test/Misc/emit-html.c
index 48c8b61b38d..ec07a60a606 100644
--- a/clang/test/Misc/emit-html.c
+++ b/clang/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")
+
OpenPOWER on IntegriCloud