diff options
author | Ted Kremenek <kremenek@apple.com> | 2011-10-12 19:46:30 +0000 |
---|---|---|
committer | Ted Kremenek <kremenek@apple.com> | 2011-10-12 19:46:30 +0000 |
commit | d768150ef57f617c8d9fef48f3c92e8f21698024 (patch) | |
tree | 6b32a6dcedf5b1225deb7a2fac21df3228fa1f55 /lib | |
parent | b3df1386680b3830d2f4d300d4d7eaba134135fc (diff) |
Implement built-in macro '__has_warning', which allows one to query if a warning flag is valid. Fixes <rdar://problem/10263428>.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@141802 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Lex/PPMacroExpansion.cpp | 69 |
1 files changed, 69 insertions, 0 deletions
diff --git a/lib/Lex/PPMacroExpansion.cpp b/lib/Lex/PPMacroExpansion.cpp index 5bdebf93b3..486ffbeb9c 100644 --- a/lib/Lex/PPMacroExpansion.cpp +++ b/lib/Lex/PPMacroExpansion.cpp @@ -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 @@ void Preprocessor::RegisterBuiltinMacros() { 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 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) { 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!"); } |