[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 ¤tMappings = 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