Implement support for #pragma message, patch by Michael Spencer!
llvm-svn: 106950
This commit is contained in:
parent
04775f8413
commit
30c924b3e8
|
@ -225,6 +225,9 @@ def err__Pragma_malformed : Error<
|
|||
"_Pragma takes a parenthesized string literal">;
|
||||
def err_pragma_comment_malformed : Error<
|
||||
"pragma comment requires parenthesized identifier and optional string">;
|
||||
def err_pragma_message_malformed : Error<
|
||||
"pragma message requires parenthesized string">;
|
||||
def warn_pragma_message : Warning<"%0">;
|
||||
def warn_pragma_ignored : Warning<"unknown pragma ignored">,
|
||||
InGroup<UnknownPragmas>, DefaultIgnore;
|
||||
def ext_stdc_pragma_ignored : ExtWarn<"unknown pragma in STDC namespace">,
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
#include "clang/Lex/DirectoryLookup.h"
|
||||
#include "clang/Basic/SourceLocation.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include <string>
|
||||
|
||||
namespace clang {
|
||||
|
@ -70,6 +71,12 @@ public:
|
|||
const std::string &Str) {
|
||||
}
|
||||
|
||||
/// PragmaMessage - This callback is invoked when a #pragma message directive
|
||||
/// is read.
|
||||
///
|
||||
virtual void PragmaMessage(SourceLocation Loc, llvm::StringRef Str) {
|
||||
}
|
||||
|
||||
/// MacroExpands - This is called by
|
||||
/// Preprocessor::HandleMacroExpandedIdentifier when a macro invocation is
|
||||
/// found.
|
||||
|
@ -127,6 +134,11 @@ public:
|
|||
Second->PragmaComment(Loc, Kind, Str);
|
||||
}
|
||||
|
||||
virtual void PragmaMessage(SourceLocation Loc, llvm::StringRef Str) {
|
||||
First->PragmaMessage(Loc, Str);
|
||||
Second->PragmaMessage(Loc, Str);
|
||||
}
|
||||
|
||||
virtual void MacroExpands(const Token &Id, const MacroInfo* MI) {
|
||||
First->MacroExpands(Id, MI);
|
||||
Second->MacroExpands(Id, MI);
|
||||
|
|
|
@ -918,6 +918,7 @@ public:
|
|||
void HandlePragmaSystemHeader(Token &SysHeaderTok);
|
||||
void HandlePragmaDependency(Token &DependencyTok);
|
||||
void HandlePragmaComment(Token &CommentTok);
|
||||
void HandlePragmaMessage(Token &MessageTok);
|
||||
// Return true and store the first token only if any CommentHandler
|
||||
// has inserted some tokens and getCommentRetentionState() is false.
|
||||
bool HandleComment(Token &Token, SourceRange Comment);
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "clang/Lex/TokenConcatenation.h"
|
||||
#include "llvm/ADT/SmallString.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/Config/config.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include <cstdio>
|
||||
|
@ -117,7 +118,7 @@ public:
|
|||
virtual void Ident(SourceLocation Loc, const std::string &str);
|
||||
virtual void PragmaComment(SourceLocation Loc, const IdentifierInfo *Kind,
|
||||
const std::string &Str);
|
||||
|
||||
virtual void PragmaMessage(SourceLocation Loc, llvm::StringRef Str);
|
||||
|
||||
bool HandleFirstTokOnLine(Token &Tok);
|
||||
bool MoveToLine(SourceLocation Loc) {
|
||||
|
@ -306,6 +307,29 @@ void PrintPPOutputPPCallbacks::PragmaComment(SourceLocation Loc,
|
|||
EmittedTokensOnThisLine = true;
|
||||
}
|
||||
|
||||
void PrintPPOutputPPCallbacks::PragmaMessage(SourceLocation Loc,
|
||||
llvm::StringRef Str) {
|
||||
MoveToLine(Loc);
|
||||
OS << "#pragma message(";
|
||||
|
||||
OS << '"';
|
||||
|
||||
for (unsigned i = 0, e = Str.size(); i != e; ++i) {
|
||||
unsigned char Char = Str[i];
|
||||
if (isprint(Char) && Char != '\\' && Char != '"')
|
||||
OS << (char)Char;
|
||||
else // Output anything hard as an octal escape.
|
||||
OS << '\\'
|
||||
<< (char)('0'+ ((Char >> 6) & 7))
|
||||
<< (char)('0'+ ((Char >> 3) & 7))
|
||||
<< (char)('0'+ ((Char >> 0) & 7));
|
||||
}
|
||||
OS << '"';
|
||||
|
||||
OS << ')';
|
||||
EmittedTokensOnThisLine = true;
|
||||
}
|
||||
|
||||
|
||||
/// HandleFirstTokOnLine - When emitting a preprocessed file in -E mode, this
|
||||
/// is called for the first token on each new line. If this really is the start
|
||||
|
|
|
@ -419,7 +419,68 @@ void Preprocessor::HandlePragmaComment(Token &Tok) {
|
|||
Callbacks->PragmaComment(CommentLoc, II, ArgumentString);
|
||||
}
|
||||
|
||||
/// HandlePragmaMessage - Handle the microsoft #pragma message extension. The
|
||||
/// syntax is:
|
||||
/// #pragma message(messagestring)
|
||||
/// messagestring is a string, which is fully macro expanded, and permits string
|
||||
/// concatenation, embedded escape characters etc. See MSDN for more details.
|
||||
void Preprocessor::HandlePragmaMessage(Token &Tok) {
|
||||
SourceLocation MessageLoc = Tok.getLocation();
|
||||
Lex(Tok);
|
||||
if (Tok.isNot(tok::l_paren)) {
|
||||
Diag(MessageLoc, diag::err_pragma_message_malformed);
|
||||
return;
|
||||
}
|
||||
|
||||
// Read the string.
|
||||
Lex(Tok);
|
||||
|
||||
|
||||
// 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"
|
||||
llvm::SmallVector<Token, 4> StrToks;
|
||||
while (Tok.is(tok::string_literal)) {
|
||||
StrToks.push_back(Tok);
|
||||
Lex(Tok);
|
||||
}
|
||||
|
||||
// Concatenate and parse the strings.
|
||||
StringLiteralParser Literal(&StrToks[0], StrToks.size(), *this);
|
||||
assert(!Literal.AnyWide && "Didn't allow wide strings in");
|
||||
if (Literal.hadError)
|
||||
return;
|
||||
if (Literal.Pascal) {
|
||||
Diag(StrToks[0].getLocation(), diag::err_pragma_message_malformed);
|
||||
return;
|
||||
}
|
||||
|
||||
llvm::StringRef MessageString(Literal.GetString(), Literal.GetStringLength());
|
||||
|
||||
if (Tok.isNot(tok::r_paren)) {
|
||||
Diag(Tok.getLocation(), diag::err_pragma_message_malformed);
|
||||
return;
|
||||
}
|
||||
Lex(Tok); // eat the r_paren.
|
||||
|
||||
if (Tok.isNot(tok::eom)) {
|
||||
Diag(Tok.getLocation(), diag::err_pragma_message_malformed);
|
||||
return;
|
||||
}
|
||||
|
||||
// Output the message.
|
||||
Diag(MessageLoc, diag::warn_pragma_message) << MessageString;
|
||||
|
||||
// If the pragma is lexically sound, notify any interested PPCallbacks.
|
||||
if (Callbacks)
|
||||
Callbacks->PragmaMessage(MessageLoc, MessageString);
|
||||
}
|
||||
|
||||
|
||||
/// AddPragmaHandler - Add the specified pragma handler to the preprocessor.
|
||||
|
@ -632,6 +693,14 @@ struct PragmaCommentHandler : public PragmaHandler {
|
|||
}
|
||||
};
|
||||
|
||||
/// PragmaMessageHandler - "#pragma message("...")".
|
||||
struct PragmaMessageHandler : public PragmaHandler {
|
||||
PragmaMessageHandler(const IdentifierInfo *ID) : PragmaHandler(ID) {}
|
||||
virtual void HandlePragma(Preprocessor &PP, Token &CommentTok) {
|
||||
PP.HandlePragmaMessage(CommentTok);
|
||||
}
|
||||
};
|
||||
|
||||
// Pragma STDC implementations.
|
||||
|
||||
enum STDCSetting {
|
||||
|
@ -743,6 +812,8 @@ void Preprocessor::RegisterBuiltinPragmas() {
|
|||
AddPragmaHandler("STDC", new PragmaSTDC_UnknownHandler());
|
||||
|
||||
// MS extensions.
|
||||
if (Features.Microsoft)
|
||||
if (Features.Microsoft) {
|
||||
AddPragmaHandler(0, new PragmaCommentHandler(getIdentifierInfo("comment")));
|
||||
AddPragmaHandler(0, new PragmaMessageHandler(getIdentifierInfo("message")));
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue