[cfe-commits] r75431 - in /cfe/trunk: include/clang/Basic/Diagnostic.h include/clang/Basic/DiagnosticLexKinds.td lib/Basic/Diagnostic.cpp lib/Lex/Pragma.cpp test/Preprocessor/pushable-diagnostics.c

Chris Lattner sabre at nondot.org
Sun Jul 12 14:18:46 PDT 2009


Author: lattner
Date: Sun Jul 12 16:18:45 2009
New Revision: 75431

URL: http://llvm.org/viewvc/llvm-project?rev=75431&view=rev
Log:
add push/pop semantics for diagnostics.  Patch by Louis Gerbarg!

Added:
    cfe/trunk/test/Preprocessor/pushable-diagnostics.c
Modified:
    cfe/trunk/include/clang/Basic/Diagnostic.h
    cfe/trunk/include/clang/Basic/DiagnosticLexKinds.td
    cfe/trunk/lib/Basic/Diagnostic.cpp
    cfe/trunk/lib/Lex/Pragma.cpp

Modified: cfe/trunk/include/clang/Basic/Diagnostic.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Diagnostic.h?rev=75431&r1=75430&r2=75431&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/Diagnostic.h (original)
+++ cfe/trunk/include/clang/Basic/Diagnostic.h Sun Jul 12 16:18:45 2009
@@ -16,6 +16,7 @@
 
 #include "clang/Basic/SourceLocation.h"
 #include <string>
+#include <vector>
 #include <cassert>
 
 namespace llvm {
@@ -172,8 +173,10 @@
   /// when the mapping was established as a user mapping.  If the high bit is
   /// clear, then the low bits are set to the default value, and should be
   /// mapped with -pedantic, -Werror, etc.
-  mutable unsigned char DiagMappings[diag::DIAG_UPPER_LIMIT/2];
-  
+
+  typedef std::vector<unsigned char> DiagMappings;
+  mutable std::vector<DiagMappings> DiagMappingsStack;
+
   /// ErrorOccurred / FatalErrorOccurred - This is set to true when an error or
   /// fatal error is emitted, and is sticky.
   bool ErrorOccurred;
@@ -212,6 +215,17 @@
   DiagnosticClient *getClient() { return Client; };
   const DiagnosticClient *getClient() const { return Client; };
     
+
+  /// pushMappings - Copies the current DiagMappings and pushes the new copy 
+  /// onto the top of the stack.
+  void pushMappings();
+
+  /// popMappings - Pops the current DiagMappings off the top of the stack
+  /// causing the new top of the stack to be the active mappings. Returns
+  /// true if the pop happens, false if there is only one DiagMapping on the
+  /// stack.
+  bool popMappings();
+
   void setClient(DiagnosticClient* client) { Client = client; }
 
   /// setIgnoreAllWarnings - When set to true, any unmapped warnings are
@@ -343,13 +357,14 @@
   /// specified builtin diagnostic.  This returns the high bit encoding, or zero
   /// if the field is completely uninitialized.
   unsigned getDiagnosticMappingInfo(diag::kind Diag) const {
-    return (diag::Mapping)((DiagMappings[Diag/2] >> (Diag & 1)*4) & 15);
+    const DiagMappings &currentMappings = DiagMappingsStack.back();
+    return (diag::Mapping)((currentMappings[Diag/2] >> (Diag & 1)*4) & 15);
   }
   
   void setDiagnosticMappingInternal(unsigned DiagId, unsigned Map,
                                     bool isUser) const {
     if (isUser) Map |= 8;  // Set the high bit for user mappings.
-    unsigned char &Slot = DiagMappings[DiagId/2];
+    unsigned char &Slot = DiagMappingsStack.back()[DiagId/2];
     unsigned Shift = (DiagId & 1)*4;
     Slot &= ~(15 << Shift);
     Slot |= Map << Shift;

Modified: cfe/trunk/include/clang/Basic/DiagnosticLexKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticLexKinds.td?rev=75431&r1=75430&r2=75431&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticLexKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticLexKinds.td Sun Jul 12 16:18:45 2009
@@ -226,10 +226,17 @@
 def warn_stdc_fenv_access_not_supported :
    Warning<"pragma STDC FENV_ACCESS ON is not supported, ignoring pragma">,
    InGroup<UnknownPragmas>;
-def warn_pragma_diagnostic_invalid :
+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'"
+            " 'push', or 'pop'">,
+   InGroup<UnknownPragmas>;
+def warn_pragma_diagnostic_clang_cannot_ppp :
+   ExtWarn<"pragma diagnostic pop could not pop, no matching push">,
+   InGroup<UnknownPragmas>;
 def warn_pragma_diagnostic_invalid_option :
    ExtWarn<"pragma diagnostic expected option name (e.g. \"-Wundef\")">,
    InGroup<UnknownPragmas>;

Modified: cfe/trunk/lib/Basic/Diagnostic.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/Diagnostic.cpp?rev=75431&r1=75430&r2=75431&view=diff

==============================================================================
--- cfe/trunk/lib/Basic/Diagnostic.cpp (original)
+++ cfe/trunk/lib/Basic/Diagnostic.cpp Sun Jul 12 16:18:45 2009
@@ -201,6 +201,7 @@
   ErrorOccurred = false;
   FatalErrorOccurred = false;
   NumDiagnostics = 0;
+
   NumErrors = 0;
   CustomDiagInfo = 0;
   CurDiagID = ~0U;
@@ -210,13 +211,27 @@
   ArgToStringCookie = 0;
   
   // Set all mappings to 'unset'.
-  memset(DiagMappings, 0, sizeof(DiagMappings));
+  DiagMappings BlankDiags(diag::DIAG_UPPER_LIMIT/2, 0);
+  DiagMappingsStack.push_back(BlankDiags);
 }
 
 Diagnostic::~Diagnostic() {
   delete CustomDiagInfo;
 }
 
+
+void Diagnostic::pushMappings() {
+  DiagMappingsStack.push_back(DiagMappingsStack.back());
+}
+
+bool Diagnostic::popMappings() {
+  if (DiagMappingsStack.size() == 1)
+    return false;
+
+  DiagMappingsStack.pop_back();
+  return true;
+}
+
 /// getCustomDiagID - Return an ID for a diagnostic with the specified message
 /// and level.  If this is the first request for this diagnosic, it is
 /// registered and created, otherwise the existing ID is returned.

Modified: cfe/trunk/lib/Lex/Pragma.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/Pragma.cpp?rev=75431&r1=75430&r2=75431&view=diff

==============================================================================
--- cfe/trunk/lib/Lex/Pragma.cpp (original)
+++ cfe/trunk/lib/Lex/Pragma.cpp Sun Jul 12 16:18:45 2009
@@ -518,13 +518,23 @@
 };
   
 /// 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 {
-  PragmaDiagnosticHandler(const IdentifierInfo *ID) : PragmaHandler(ID) {}
+private:
+  const bool ClangMode;
+public:
+  PragmaDiagnosticHandler(const IdentifierInfo *ID,
+                          const bool clangMode) : PragmaHandler(ID),
+                                                  ClangMode(clangMode) {}
   virtual void HandlePragma(Preprocessor &PP, Token &DiagToken) {
     Token Tok;
     PP.LexUnexpandedToken(Tok);
     if (Tok.isNot(tok::identifier)) {
-      PP.Diag(Tok, diag::warn_pragma_diagnostic_invalid);
+      unsigned Diag = ClangMode ? diag::warn_pragma_diagnostic_clang_invalid
+                                 : diag::warn_pragma_diagnostic_gcc_invalid;
+      PP.Diag(Tok, Diag);
       return;
     }
     IdentifierInfo *II = Tok.getIdentifierInfo();
@@ -538,8 +548,22 @@
       Map = diag::MAP_IGNORE;
     else if (II->isStr("fatal"))
       Map = diag::MAP_FATAL;
-    else {
-      PP.Diag(Tok, diag::warn_pragma_diagnostic_invalid);
+    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);
+      return;
+    } else {
+      PP.Diag(Tok, diag::warn_pragma_diagnostic_gcc_invalid);
       return;
     }
     
@@ -571,10 +595,12 @@
     if (Literal.hadError)
       return;
     if (Literal.Pascal) {
-      PP.Diag(StrToks[0].getLocation(), diag::warn_pragma_diagnostic_invalid);
+      unsigned Diag = ClangMode ? diag::warn_pragma_diagnostic_clang_invalid
+                                 : diag::warn_pragma_diagnostic_gcc_invalid;
+      PP.Diag(Tok, Diag);
       return;
     }
-    
+
     std::string WarningName(Literal.GetString(),
                             Literal.GetString()+Literal.GetStringLength());
 
@@ -689,7 +715,8 @@
   AddPragmaHandler("GCC", new PragmaDependencyHandler(
                                           getIdentifierInfo("dependency")));
   AddPragmaHandler("GCC", new PragmaDiagnosticHandler(
-                                              getIdentifierInfo("diagnostic")));
+                                              getIdentifierInfo("diagnostic"),
+                                              false));
   // #pragma clang ...
   AddPragmaHandler("clang", new PragmaPoisonHandler(
                                           getIdentifierInfo("poison")));
@@ -698,7 +725,8 @@
   AddPragmaHandler("clang", new PragmaDependencyHandler(
                                           getIdentifierInfo("dependency")));
   AddPragmaHandler("clang", new PragmaDiagnosticHandler(
-                                          getIdentifierInfo("diagnostic")));
+                                          getIdentifierInfo("diagnostic"),
+                                          true));
 
   AddPragmaHandler("STDC", new PragmaSTDC_FP_CONTRACTHandler(
                                              getIdentifierInfo("FP_CONTRACT")));

Added: cfe/trunk/test/Preprocessor/pushable-diagnostics.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Preprocessor/pushable-diagnostics.c?rev=75431&view=auto

==============================================================================
--- cfe/trunk/test/Preprocessor/pushable-diagnostics.c (added)
+++ cfe/trunk/test/Preprocessor/pushable-diagnostics.c Sun Jul 12 16:18:45 2009
@@ -0,0 +1,17 @@
+// RUN: clang-cc -fsyntax-only -verify -pedantic %s
+
+#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'}}
+
+char a = 'df'; // expected-warning{{multi-character character constant}}
+
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wmultichar"
+
+char b = 'df'; // no warning.
+#pragma clang diagnostic pop
+
+char c = 'df';  // expected-warning{{multi-character character constant}}
+
+#pragma clang diagnostic pop // expected-warning{{pragma diagnostic pop could not pop, no matching push}}





More information about the cfe-commits mailing list