[cfe-commits] r141802 - in /cfe/trunk: docs/LanguageExtensions.html include/clang/Basic/DiagnosticGroups.td include/clang/Basic/DiagnosticIDs.h include/clang/Basic/DiagnosticLexKinds.td include/clang/Lex/Preprocessor.h lib/Lex/PPMacroExpansion.cpp

Ted Kremenek kremenek at apple.com
Wed Oct 12 12:46:30 PDT 2011


Author: kremenek
Date: Wed Oct 12 14:46:30 2011
New Revision: 141802

URL: http://llvm.org/viewvc/llvm-project?rev=141802&view=rev
Log:
Implement built-in macro '__has_warning', which allows one to query if a warning flag is valid.  Fixes <rdar://problem/10263428>.

Modified:
    cfe/trunk/docs/LanguageExtensions.html
    cfe/trunk/include/clang/Basic/DiagnosticGroups.td
    cfe/trunk/include/clang/Basic/DiagnosticIDs.h
    cfe/trunk/include/clang/Basic/DiagnosticLexKinds.td
    cfe/trunk/include/clang/Lex/Preprocessor.h
    cfe/trunk/lib/Lex/PPMacroExpansion.cpp

Modified: cfe/trunk/docs/LanguageExtensions.html
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/docs/LanguageExtensions.html?rev=141802&r1=141801&r2=141802&view=diff
==============================================================================
--- cfe/trunk/docs/LanguageExtensions.html (original)
+++ cfe/trunk/docs/LanguageExtensions.html Wed Oct 12 14:46:30 2011
@@ -300,6 +300,23 @@
 file.  A warning will also be issued if an absolute path
 is used in the file argument.</p>
 
+
+<!-- ======================================================================= -->
+<h3><a name="__has_warning">__has_warning</a></h3>
+<!-- ======================================================================= -->
+
+<p>This function-like macro takes a string literal that represents a command
+  line option for a warning and returns true if that is a valid warning
+  option.</p>
+  
+<blockquote>
+<pre>
+#if __has_warning("-Wformat")
+...
+#endif
+</pre>
+</blockquote>
+
 <!-- ======================================================================= -->
 <h2 id="builtinmacros">Builtin Macros</h2>
 <!-- ======================================================================= -->

Modified: cfe/trunk/include/clang/Basic/DiagnosticGroups.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticGroups.td?rev=141802&r1=141801&r2=141802&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticGroups.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticGroups.td Wed Oct 12 14:46:30 2011
@@ -73,6 +73,7 @@
 def : DiagGroup<"invalid-pch">;
 def LiteralRange : DiagGroup<"literal-range">;
 def LocalTypeTemplateArgs : DiagGroup<"local-type-template-args">;
+def MalformedWarningCheck : DiagGroup<"malformed-warning-check">;
 def Main : DiagGroup<"main">;
 def MissingBraces : DiagGroup<"missing-braces">;
 def MissingDeclarations: DiagGroup<"missing-declarations">;

Modified: cfe/trunk/include/clang/Basic/DiagnosticIDs.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticIDs.h?rev=141802&r1=141801&r2=141802&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticIDs.h (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticIDs.h Wed Oct 12 14:46:30 2011
@@ -251,7 +251,6 @@
   static diag_iterator diags_begin();
   static diag_iterator diags_end();
 
-private:
   /// \brief Get the set of all diagnostic IDs in the group with the given name.
   ///
   /// \param Diags [out] - On return, the diagnostics in the group.
@@ -259,6 +258,7 @@
   bool getDiagnosticsInGroup(StringRef Group,
                              llvm::SmallVectorImpl<diag::kind> &Diags) const;
 
+private:
   /// \brief Get the set of all diagnostic IDs in the given group.
   ///
   /// \param Diags [out] - On return, the diagnostics in the group.

Modified: cfe/trunk/include/clang/Basic/DiagnosticLexKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticLexKinds.td?rev=141802&r1=141801&r2=141802&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticLexKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticLexKinds.td Wed Oct 12 14:46:30 2011
@@ -242,6 +242,13 @@
 def err_feature_check_malformed : Error<
   "builtin feature check macro requires a parenthesized identifier">;
 
+def err_warning_check_malformed : Error<
+  "builtin warning check macro requires a parenthesized string">,
+  InGroup<MalformedWarningCheck>;
+def warn_has_warning_invalid_option :
+   ExtWarn<"__has_warning expected option name (e.g. \"-Wundef\")">,
+   InGroup<MalformedWarningCheck>;
+
 def err__Pragma_malformed : Error<
   "_Pragma takes a parenthesized string literal">;
 def err_pragma_comment_malformed : Error<

Modified: cfe/trunk/include/clang/Lex/Preprocessor.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Lex/Preprocessor.h?rev=141802&r1=141801&r2=141802&view=diff
==============================================================================
--- cfe/trunk/include/clang/Lex/Preprocessor.h (original)
+++ cfe/trunk/include/clang/Lex/Preprocessor.h Wed Oct 12 14:46:30 2011
@@ -93,6 +93,7 @@
   IdentifierInfo *Ident__has_attribute;            // __has_attribute
   IdentifierInfo *Ident__has_include;              // __has_include
   IdentifierInfo *Ident__has_include_next;         // __has_include_next
+  IdentifierInfo *Ident__has_warning;              // __has_warning
 
   SourceLocation DATELoc, TIMELoc;
   unsigned CounterValue;  // Next __COUNTER__ value.

Modified: cfe/trunk/lib/Lex/PPMacroExpansion.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/PPMacroExpansion.cpp?rev=141802&r1=141801&r2=141802&view=diff
==============================================================================
--- cfe/trunk/lib/Lex/PPMacroExpansion.cpp (original)
+++ cfe/trunk/lib/Lex/PPMacroExpansion.cpp Wed Oct 12 14:46:30 2011
@@ -21,6 +21,7 @@
 #include "clang/Lex/LexDiagnostic.h"
 #include "clang/Lex/CodeCompletionHandler.h"
 #include "clang/Lex/ExternalPreprocessorSource.h"
+#include "clang/Lex/LiteralSupport.h"
 #include "llvm/ADT/StringSwitch.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/Config/config.h"
@@ -92,6 +93,7 @@
   Ident__has_attribute    = RegisterBuiltinMacro(*this, "__has_attribute");
   Ident__has_include      = RegisterBuiltinMacro(*this, "__has_include");
   Ident__has_include_next = RegisterBuiltinMacro(*this, "__has_include_next");
+  Ident__has_warning      = RegisterBuiltinMacro(*this, "__has_warning");
 
   // Microsoft Extensions.
   if (Features.MicrosoftExt) 
@@ -1016,6 +1018,73 @@
       Value = EvaluateHasIncludeNext(Tok, II, *this);
     OS << (int)Value;
     Tok.setKind(tok::numeric_constant);
+  } else if (II == Ident__has_warning) {
+    // The argument should be a parenthesized string literal.
+    // The argument to these builtins should be a parenthesized identifier.
+    SourceLocation StartLoc = Tok.getLocation();    
+    bool IsValid = false;
+    bool Value = false;
+    // Read the '('.
+    Lex(Tok);
+    do {
+      if (Tok.is(tok::l_paren)) {      
+        // Read the string.
+        Lex(Tok);
+      
+        // We need at least one string literal.
+        if (!Tok.is(tok::string_literal)) {
+          StartLoc = Tok.getLocation();
+          IsValid = false;
+          // Eat tokens until ')'.
+          do Lex(Tok); while (!(Tok.is(tok::r_paren) || Tok.is(tok::eod)));
+          break;
+        }
+        
+        // String concatenation allows multiple strings, which can even come
+        // from macro expansion.
+        SmallVector<Token, 4> StrToks;
+        while (Tok.is(tok::string_literal)) {
+          StrToks.push_back(Tok);
+          LexUnexpandedToken(Tok);
+        }
+        
+        // Is the end a ')'?
+        if (!(IsValid = Tok.is(tok::r_paren)))
+          break;
+        
+        // Concatenate and parse the strings.
+        StringLiteralParser Literal(&StrToks[0], StrToks.size(), *this);
+        assert(Literal.isAscii() && "Didn't allow wide strings in");
+        if (Literal.hadError)
+          break;
+        if (Literal.Pascal) {
+          Diag(Tok, diag::warn_pragma_diagnostic_invalid);
+          break;
+        }
+        
+        StringRef WarningName(Literal.GetString());
+        
+        if (WarningName.size() < 3 || WarningName[0] != '-' ||
+            WarningName[1] != 'W') {
+          Diag(StrToks[0].getLocation(), diag::warn_has_warning_invalid_option);
+          break;
+        }
+        
+        // Finally, check if the warning flags maps to a diagnostic group.
+        // We construct a SmallVector here to talk to getDiagnosticIDs().
+        // Although we don't use the result, this isn't a hot path, and not
+        // worth special casing.
+        llvm::SmallVector<diag::kind, 10> Diags;
+        Value = !getDiagnostics().getDiagnosticIDs()->
+          getDiagnosticsInGroup(WarningName.substr(2), Diags);
+      }
+    } while (false);
+    
+    if (!IsValid)
+      Diag(StartLoc, diag::err_warning_check_malformed);
+
+    OS << (int)Value;
+    Tok.setKind(tok::numeric_constant);
   } else {
     llvm_unreachable("Unknown identifier!");
   }





More information about the cfe-commits mailing list