[llvm-commits] [PATCH] Compatibility with GCC 4.6 #pragma GCC diagnostics

Louis Gerbarg lgerbarg at gmail.com
Mon Aug 16 18:12:36 PDT 2010


GCC 4.6 has apparently added support for #pragma push/pop (see this
thread for more details
<http://gcc.gnu.org/ml/gcc-patches/2010-06/msg01163.html>), using the
exact same identifier and semantics as the existing implementation in
clang. This patch removes the special clang mode in the diagnostic
handler, which lets the GCC pragmas fall through to the existing code.
Overall it is a simplification of the existing code. This patch also
includes modified test cases to handle altered semantics of the GCC
mode behaviour.

Passed tests with TOT under Darwin 10.6.3 x86-64. I think this should
be good, but let me know if any fixes are needed.

Louis

---
 include/clang/Basic/DiagnosticLexKinds.td |   10 ++----
 lib/Lex/Pragma.cpp                        |   45 +++++++++--------------------
 test/Preprocessor/pragma_diagnostic.c     |    3 +-
 test/Preprocessor/pushable-diagnostics.c  |    2 +-
 4 files changed, 19 insertions(+), 41 deletions(-)

diff --git a/include/clang/Basic/DiagnosticLexKinds.td
b/include/clang/Basic/DiagnosticLexKinds.td
index 9b06fa8..76c211e 100644
--- a/include/clang/Basic/DiagnosticLexKinds.td
+++ b/include/clang/Basic/DiagnosticLexKinds.td
@@ -244,15 +244,11 @@ def ext_stdc_pragma_syntax_eom :
 def warn_stdc_fenv_access_not_supported :
    Warning<"pragma STDC FENV_ACCESS ON is not supported, ignoring pragma">,
    InGroup<UnknownPragmas>;
-def warn_pragma_diagnostic_gcc_invalid :
-   ExtWarn<"pragma diagnostic expected 'error', 'warning', 'ignored', or"
-            " 'fatal'">,
-   InGroup<UnknownPragmas>;
-def warn_pragma_diagnostic_clang_invalid :
-   ExtWarn<"pragma diagnostic expected 'error', 'warning', 'ignored', 'fatal'"
+def warn_pragma_diagnostic_invalid :
+   ExtWarn<"pragma diagnostic expected 'error', 'warning', 'ignored', 'fatal',"
             " 'push', or 'pop'">,
    InGroup<UnknownPragmas>;
-def warn_pragma_diagnostic_clang_cannot_ppp :
+def warn_pragma_diagnostic_cannot_pop :
    ExtWarn<"pragma diagnostic pop could not pop, no matching push">,
    InGroup<UnknownPragmas>;
 def warn_pragma_diagnostic_invalid_option :
diff --git a/lib/Lex/Pragma.cpp b/lib/Lex/Pragma.cpp
index 783900d..a74ff33 100644
--- a/lib/Lex/Pragma.cpp
+++ b/lib/Lex/Pragma.cpp
@@ -588,7 +588,7 @@ struct PragmaDebugHandler : public PragmaHandler {
     Token Tok;
     PP.LexUnexpandedToken(Tok);
     if (Tok.isNot(tok::identifier)) {
-      PP.Diag(Tok, diag::warn_pragma_diagnostic_clang_invalid);
+      PP.Diag(Tok, diag::warn_pragma_diagnostic_invalid);
       return;
     }
     IdentifierInfo *II = Tok.getIdentifierInfo();
@@ -610,23 +610,14 @@ struct PragmaDebugHandler : public PragmaHandler {
 };

 /// PragmaDiagnosticHandler - e.g. '#pragma GCC diagnostic ignored "-Wformat"'
-/// Since clang's diagnostic supports extended functionality beyond GCC's
-/// the constructor takes a clangMode flag to tell it whether or not to allow
-/// clang's extended functionality, or whether to reject it.
 struct PragmaDiagnosticHandler : public PragmaHandler {
-private:
-  const bool ClangMode;
 public:
-  explicit PragmaDiagnosticHandler(const bool clangMode)
-    : PragmaHandler("diagnostic"), ClangMode(clangMode) {}
-
+  explicit PragmaDiagnosticHandler() : PragmaHandler("diagnostic") {}
   virtual void HandlePragma(Preprocessor &PP, Token &DiagToken) {
     Token Tok;
     PP.LexUnexpandedToken(Tok);
     if (Tok.isNot(tok::identifier)) {
-      unsigned Diag = ClangMode ? diag::warn_pragma_diagnostic_clang_invalid
-                                 : diag::warn_pragma_diagnostic_gcc_invalid;
-      PP.Diag(Tok, Diag);
+      PP.Diag(Tok, diag::warn_pragma_diagnostic_invalid);
       return;
     }
     IdentifierInfo *II = Tok.getIdentifierInfo();
@@ -640,22 +631,16 @@ public:
       Map = diag::MAP_IGNORE;
     else if (II->isStr("fatal"))
       Map = diag::MAP_FATAL;
-    else if (ClangMode) {
-      if (II->isStr("pop")) {
-        if (!PP.getDiagnostics().popMappings())
-          PP.Diag(Tok, diag::warn_pragma_diagnostic_clang_cannot_ppp);
-        return;
-      }
-
-      if (II->isStr("push")) {
-        PP.getDiagnostics().pushMappings();
-        return;
-      }
-
-      PP.Diag(Tok, diag::warn_pragma_diagnostic_clang_invalid);
+    else if (II->isStr("pop")) {
+      if (!PP.getDiagnostics().popMappings())
+        PP.Diag(Tok, diag::warn_pragma_diagnostic_cannot_pop);
+
+      return;
+    } else if (II->isStr("push")) {
+      PP.getDiagnostics().pushMappings();
       return;
     } else {
-      PP.Diag(Tok, diag::warn_pragma_diagnostic_gcc_invalid);
+      PP.Diag(Tok, diag::warn_pragma_diagnostic_invalid);
       return;
     }

@@ -687,9 +672,7 @@ public:
     if (Literal.hadError)
       return;
     if (Literal.Pascal) {
-      unsigned Diag = ClangMode ? diag::warn_pragma_diagnostic_clang_invalid
-                                 : diag::warn_pragma_diagnostic_gcc_invalid;
-      PP.Diag(Tok, Diag);
+      PP.Diag(Tok, diag::warn_pragma_diagnostic_invalid);
       return;
     }

@@ -812,13 +795,13 @@ void Preprocessor::RegisterBuiltinPragmas() {
   AddPragmaHandler("GCC", new PragmaPoisonHandler());
   AddPragmaHandler("GCC", new PragmaSystemHeaderHandler());
   AddPragmaHandler("GCC", new PragmaDependencyHandler());
-  AddPragmaHandler("GCC", new PragmaDiagnosticHandler(false));
+  AddPragmaHandler("GCC", new PragmaDiagnosticHandler());
   // #pragma clang ...
   AddPragmaHandler("clang", new PragmaPoisonHandler());
   AddPragmaHandler("clang", new PragmaSystemHeaderHandler());
   AddPragmaHandler("clang", new PragmaDebugHandler());
   AddPragmaHandler("clang", new PragmaDependencyHandler());
-  AddPragmaHandler("clang", new PragmaDiagnosticHandler(true));
+  AddPragmaHandler("clang", new PragmaDiagnosticHandler());

   AddPragmaHandler("STDC", new PragmaSTDC_FP_CONTRACTHandler());
   AddPragmaHandler("STDC", new PragmaSTDC_FENV_ACCESSHandler());
diff --git a/test/Preprocessor/pragma_diagnostic.c
b/test/Preprocessor/pragma_diagnostic.c
index d157406..818f02f 100644
--- a/test/Preprocessor/pragma_diagnostic.c
+++ b/test/Preprocessor/pragma_diagnostic.c
@@ -20,9 +20,8 @@
 #endif


-
 #define foo error
-#pragma GCC diagnostic foo "-Wundef"  // expected-warning {{pragma
diagnostic expected 'error', 'warning', 'ignored', or 'fatal'}}
+#pragma GCC diagnostic foo "-Wundef"  // expected-warning {{pragma
diagnostic expected 'error', 'warning', 'ignored', 'fatal', 'push', or
'pop'}}

 #pragma GCC diagnostic error 42  // expected-warning {{unexpected
token in pragma diagnostic}}

diff --git a/test/Preprocessor/pushable-diagnostics.c
b/test/Preprocessor/pushable-diagnostics.c
index 6c861a1..567a866 100644
--- a/test/Preprocessor/pushable-diagnostics.c
+++ b/test/Preprocessor/pushable-diagnostics.c
@@ -2,7 +2,7 @@

 #pragma clang diagnostic pop // expected-warning{{pragma diagnostic
pop could not pop, no matching push}}

-#pragma clang diagnostic puhs // expected-warning{{pragma diagnostic
expected 'error', 'warning', 'ignored', 'fatal' 'push', or 'pop'}}
+#pragma clang diagnostic puhs // expected-warning {{pragma diagnostic
expected 'error', 'warning', 'ignored', 'fatal', 'push', or 'pop'}}

 char a = 'df'; // expected-warning{{multi-character character constant}}

-- 
1.7.0



More information about the llvm-commits mailing list