def err_expected_colon_after_setter_name : Error<
"method name referenced in property setter attribute "
"must end with ':'">;
+def err_expected_string_literal : Error<"expected string literal">;
def err_invalid_string_udl : Error<
"string literal with user-defined suffix cannot be used here">;
def err_invalid_character_udl : Error<
"label at end of compound statement: expected statement">;
def err_address_of_label_outside_fn : Error<
"use of address-of-label extension outside of a function body">;
-def err_expected_string_literal : Error<"expected string literal">;
def err_asm_operand_wide_string_literal : Error<
"cannot use %select{unicode|wide}0 string literal in 'asm'">;
def err_expected_selector_for_method : Error<
void LexAfterModuleImport(Token &Result);
+ /// \brief Lex a string literal, which may be the concatenation of multiple
+ /// string literals and may even come from macro expansion.
+ /// \returns true on success, false if a error diagnostic has been generated.
+ bool LexStringLiteral(Token &Result, std::string &String,
+ bool AllowMacroExpansion) {
+ if (AllowMacroExpansion)
+ Lex(Result);
+ else
+ LexUnexpandedToken(Result);
+ return FinishLexStringLiteral(Result, String, AllowMacroExpansion);
+ }
+
+ /// \brief Complete the lexing of a string literal where the first token has
+ /// already been lexed (see LexStringLiteral).
+ bool FinishLexStringLiteral(Token &Result, std::string &String,
+ bool AllowMacroExpansion);
+
/// LexNonComment - Lex a token. If it's a comment, keep lexing until we get
/// something not a comment. This is useful in -E -C mode where comments
/// would foul up preprocessor directive handling.
#include "clang/Lex/LexDiagnostic.h"
#include "clang/Lex/CodeCompletionHandler.h"
#include "clang/Lex/ExternalPreprocessorSource.h"
-#include "clang/Lex/LiteralSupport.h"
+#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Config/llvm-config.h"
bool IsValid = false;
bool Value = false;
// Read the '('.
- Lex(Tok);
+ LexUnexpandedToken(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 ')'.
- while (Tok.isNot(tok::r_paren)
- && Tok.isNot(tok::eod)
- && Tok.isNot(tok::eof))
- Lex(Tok);
- break;
- }
-
- // String concatenation allows multiple strings, which can even come
- // from macro expansion.
- SmallVector<Token, 4> StrToks;
- while (Tok.is(tok::string_literal)) {
- // Complain about, and drop, any ud-suffix.
- if (Tok.hasUDSuffix())
- Diag(Tok, diag::err_invalid_string_udl);
- StrToks.push_back(Tok);
+ if (Tok.isNot(tok::l_paren)) {
+ Diag(StartLoc, diag::err_warning_check_malformed);
+ break;
+ }
+
+ LexUnexpandedToken(Tok);
+ std::string WarningName;
+ SourceLocation StrStartLoc = Tok.getLocation();
+ if (!FinishLexStringLiteral(Tok, WarningName, /*MacroExpansion=*/false)) {
+ // Eat tokens until ')'.
+ while (Tok.isNot(tok::r_paren)
+ && Tok.isNot(tok::eod)
+ && Tok.isNot(tok::eof))
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);
+ break;
}
+
+ // Is the end a ')'?
+ if (!(IsValid = Tok.is(tok::r_paren))) {
+ Diag(StartLoc, diag::err_warning_check_malformed);
+ break;
+ }
+
+ if (WarningName.size() < 3 || WarningName[0] != '-' ||
+ WarningName[1] != 'W') {
+ Diag(StrStartLoc, 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;
if (IsValid)
// Read the optional string if present.
Lex(Tok);
std::string ArgumentString;
- if (Tok.is(tok::comma)) {
- Lex(Tok); // eat the comma.
-
- // We need at least one string.
- if (Tok.isNot(tok::string_literal)) {
- Diag(Tok.getLocation(), diag::err_pragma_comment_malformed);
- return;
- }
-
- // String concatenation allows multiple strings, which can even come from
- // macro expansion.
- // "foo " "bar" "Baz"
- SmallVector<Token, 4> StrToks;
- while (Tok.is(tok::string_literal)) {
- if (Tok.hasUDSuffix())
- Diag(Tok, diag::err_invalid_string_udl);
- StrToks.push_back(Tok);
- Lex(Tok);
- }
-
- // Concatenate and parse the strings.
- StringLiteralParser Literal(&StrToks[0], StrToks.size(), *this);
- assert(Literal.isAscii() && "Didn't allow wide strings in");
- if (Literal.hadError)
- return;
- if (Literal.Pascal) {
- Diag(StrToks[0].getLocation(), diag::err_pragma_comment_malformed);
- return;
- }
-
- ArgumentString = Literal.GetString();
- }
+ if (Tok.is(tok::comma) && !LexStringLiteral(Tok, ArgumentString,
+ /*MacroExpansion=*/true))
+ return;
// FIXME: If the kind is "compiler" warn if the string is present (it is
// ignored).
return;
}
- // We need at least one string.
- if (Tok.isNot(tok::string_literal)) {
- Diag(Tok.getLocation(), diag::err_pragma_message_malformed);
- return;
- }
-
- // String concatenation allows multiple strings, which can even come from
- // macro expansion.
- // "foo " "bar" "Baz"
- SmallVector<Token, 4> StrToks;
- while (Tok.is(tok::string_literal)) {
- if (Tok.hasUDSuffix())
- Diag(Tok, diag::err_invalid_string_udl);
- StrToks.push_back(Tok);
- Lex(Tok);
- }
-
- // Concatenate and parse the strings.
- StringLiteralParser Literal(&StrToks[0], StrToks.size(), *this);
- assert(Literal.isAscii() && "Didn't allow wide strings in");
- if (Literal.hadError)
- return;
- if (Literal.Pascal) {
- Diag(StrToks[0].getLocation(), diag::err_pragma_message_malformed);
+ std::string MessageString;
+ if (!FinishLexStringLiteral(Tok, MessageString, /*MacroExpansion=*/true))
return;
- }
-
- StringRef MessageString(Literal.GetString());
if (ExpectClosingParen) {
if (Tok.isNot(tok::r_paren)) {
}
PP.LexUnexpandedToken(Tok);
+ SourceLocation StringLoc = Tok.getLocation();
- // We need at least one string.
- if (Tok.isNot(tok::string_literal)) {
- PP.Diag(Tok.getLocation(), diag::warn_pragma_diagnostic_invalid_token);
+ std::string WarningName;
+ if (!PP.FinishLexStringLiteral(Tok, WarningName, /*MacroExpansion=*/false))
return;
- }
-
- // String concatenation allows multiple strings, which can even come from
- // macro expansion.
- // "foo " "bar" "Baz"
- SmallVector<Token, 4> StrToks;
- while (Tok.is(tok::string_literal)) {
- StrToks.push_back(Tok);
- PP.LexUnexpandedToken(Tok);
- }
if (Tok.isNot(tok::eod)) {
PP.Diag(Tok.getLocation(), diag::warn_pragma_diagnostic_invalid_token);
return;
}
- // Concatenate and parse the strings.
- StringLiteralParser Literal(&StrToks[0], StrToks.size(), PP);
- assert(Literal.isAscii() && "Didn't allow wide strings in");
- if (Literal.hadError)
- return;
- if (Literal.Pascal) {
- PP.Diag(Tok, diag::warn_pragma_diagnostic_invalid);
- return;
- }
-
- StringRef WarningName(Literal.GetString());
-
if (WarningName.size() < 3 || WarningName[0] != '-' ||
WarningName[1] != 'W') {
- PP.Diag(StrToks[0].getLocation(),
- diag::warn_pragma_diagnostic_invalid_option);
+ PP.Diag(StringLoc, diag::warn_pragma_diagnostic_invalid_option);
return;
}
if (PP.getDiagnostics().setDiagnosticGroupMapping(WarningName.substr(2),
Map, DiagLoc))
- PP.Diag(StrToks[0].getLocation(),
- diag::warn_pragma_diagnostic_unknown_warning) << WarningName;
+ PP.Diag(StringLoc, diag::warn_pragma_diagnostic_unknown_warning)
+ << WarningName;
else if (Callbacks)
Callbacks->PragmaDiagnostic(DiagLoc, Namespace, Map, WarningName);
}
#include "clang/Lex/LexDiagnostic.h"
#include "clang/Lex/CodeCompletionHandler.h"
#include "clang/Lex/ModuleLoader.h"
+#include "clang/Lex/LiteralSupport.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/TargetInfo.h"
}
}
+bool Preprocessor::FinishLexStringLiteral(Token &Result, std::string &String,
+ bool AllowMacroExpansion) {
+ // We need at least one string literal.
+ if (Result.isNot(tok::string_literal)) {
+ Diag(Result, diag::err_expected_string_literal);
+ return false;
+ }
+
+ // Lex string literal tokens, optionally with macro expansion.
+ SmallVector<Token, 4> StrToks;
+ do {
+ StrToks.push_back(Result);
+
+ if (Result.hasUDSuffix())
+ Diag(Result, diag::err_invalid_string_udl);
+
+ if (AllowMacroExpansion)
+ Lex(Result);
+ else
+ LexUnexpandedToken(Result);
+ } while (Result.is(tok::string_literal));
+
+ // Concatenate and parse the strings.
+ StringLiteralParser Literal(&StrToks[0], StrToks.size(), *this);
+ assert(Literal.isAscii() && "Didn't allow wide strings in");
+
+ if (Literal.hadError)
+ return false;
+
+ if (Literal.Pascal) {
+ Diag(StrToks[0].getLocation(), diag::err_expected_string_literal);
+ return false;
+ }
+
+ String = Literal.GetString();
+ return true;
+}
+
void Preprocessor::addCommentHandler(CommentHandler *Handler) {
assert(Handler && "NULL comment handler");
assert(std::find(CommentHandlers.begin(), CommentHandlers.end(), Handler) ==
// RUN: %clang_cc1 -verify %s
// These must be the last lines in this test.
-// expected-error@+1{{requires a parenthesized string}} expected-error@+1 2{{expected}}
+// expected-error@+1{{expected string literal}} expected-error@+1 2{{expected}}
int i = __has_warning(
// RUN: %clang_cc1 -verify %s
// These must be the last lines in this test.
-// expected-error@+1{{requires a parenthesized string}} expected-error@+1{{expected}}
+// expected-error@+1{{expected string literal}} expected-error@+1{{expected}}
int i = __has_warning();
#define foo error
#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}}
+#pragma GCC diagnostic error 42 // expected-error {{expected string literal}}
#pragma GCC diagnostic error "-Wundef" 42 // expected-warning {{unexpected token in pragma diagnostic}}
#pragma GCC diagnostic error "invalid-name" // expected-warning {{pragma diagnostic expected option name (e.g. "-Wundef")}}
#pragma comment( user, "Compiled on " __DATE__ " at " __TIME__ )
#pragma comment(foo) // expected-error {{unknown kind of pragma comment}}
-#pragma comment(compiler,) // expected-error {{pragma comment requires}}
+#pragma comment(compiler,) // expected-error {{expected string literal}}
#define foo compiler
#pragma comment(foo) // macro expand kind.
#pragma comment(foo) x // expected-error {{pragma comment requires}}
#warning Should have -Wparentheses
#endif
-// expected-error@+2 {{builtin warning check macro requires a parenthesized string}}
+// expected-error@+2 {{expected string literal}}
// expected-error@+1 {{expected value in expression}}
#if __has_warning(-Wfoo)
#endif
#else
#warning Not a valid warning flag
#endif
+
+// expected-error@+2 {{builtin warning check macro requires a parenthesized string}}
+// expected-error@+1 {{invalid token}}
+#if __has_warning "not valid"
+#endif
+
+// Macro expansion does not occur in the parameter to __has_warning
+// (as is also expected behaviour for ordinary macros), so the
+// following should not expand:
+
+#define MY_ALIAS "-Wparentheses"
+
+// expected-error@+1 2{{expected}}
+#if __has_warning(MY_ALIAS)
+#error Alias expansion not allowed
+#endif
+
+// But deferring should expand:
+#define HAS_WARNING(X) __has_warning(X)
+
+#if !HAS_WARNING(MY_ALIAS)
+#error Expansion should have occurred
+#endif