diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Lex/Pragma.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Lex/Pragma.cpp | 267 |
1 files changed, 125 insertions, 142 deletions
diff --git a/contrib/llvm/tools/clang/lib/Lex/Pragma.cpp b/contrib/llvm/tools/clang/lib/Lex/Pragma.cpp index 95e8a8c..b2ae4c9 100644 --- a/contrib/llvm/tools/clang/lib/Lex/Pragma.cpp +++ b/contrib/llvm/tools/clang/lib/Lex/Pragma.cpp @@ -254,14 +254,15 @@ void Preprocessor::Handle_Pragma(Token &Tok) { "Invalid string token!"); // Remove escaped quotes and escapes. - for (unsigned i = 1, e = StrVal.size(); i < e-2; ++i) { - if (StrVal[i] == '\\' && - (StrVal[i+1] == '\\' || StrVal[i+1] == '"')) { + unsigned ResultPos = 1; + for (unsigned i = 1, e = StrVal.size() - 2; i != e; ++i) { + if (StrVal[i] != '\\' || + (StrVal[i + 1] != '\\' && StrVal[i + 1] != '"')) { // \\ -> '\' and \" -> '"'. - StrVal.erase(StrVal.begin()+i); - --e; + StrVal[ResultPos++] = StrVal[i]; } } + StrVal.erase(StrVal.begin() + ResultPos, StrVal.end() - 2); } // Remove the front quote, replacing it with a space, so that the pragma @@ -434,8 +435,9 @@ void Preprocessor::HandlePragmaSystemHeader(Token &SysHeaderTok) { // Emit a line marker. This will change any source locations from this point // forward to realize they are in a system header. // Create a line note with this information. - SourceMgr.AddLineNote(SysHeaderTok.getLocation(), PLoc.getLine(), FilenameID, - false, false, true, false); + SourceMgr.AddLineNote(SysHeaderTok.getLocation(), PLoc.getLine()+1, + FilenameID, /*IsEntry=*/false, /*IsExit=*/false, + /*IsSystem=*/true, /*IsExternC=*/false); } /// HandlePragmaDependency - Handle \#pragma GCC dependency "foo" blah. @@ -491,126 +493,7 @@ void Preprocessor::HandlePragmaDependency(Token &DependencyTok) { } } -/// \brief Handle the microsoft \#pragma comment extension. -/// -/// The syntax is: -/// \code -/// #pragma comment(linker, "foo") -/// \endcode -/// 'linker' is one of five identifiers: compiler, exestr, lib, linker, user. -/// "foo" is a string, which is fully macro expanded, and permits string -/// concatenation, embedded escape characters etc. See MSDN for more details. -void Preprocessor::HandlePragmaComment(Token &Tok) { - SourceLocation CommentLoc = Tok.getLocation(); - Lex(Tok); - if (Tok.isNot(tok::l_paren)) { - Diag(CommentLoc, diag::err_pragma_comment_malformed); - return; - } - - // Read the identifier. - Lex(Tok); - if (Tok.isNot(tok::identifier)) { - Diag(CommentLoc, diag::err_pragma_comment_malformed); - return; - } - - // Verify that this is one of the 5 whitelisted options. - // FIXME: warn that 'exestr' is deprecated. - const IdentifierInfo *II = Tok.getIdentifierInfo(); - if (!II->isStr("compiler") && !II->isStr("exestr") && !II->isStr("lib") && - !II->isStr("linker") && !II->isStr("user")) { - Diag(Tok.getLocation(), diag::err_pragma_comment_unknown_kind); - return; - } - - // Read the optional string if present. - Lex(Tok); - std::string ArgumentString; - if (Tok.is(tok::comma) && !LexStringLiteral(Tok, ArgumentString, - "pragma comment", - /*MacroExpansion=*/true)) - return; - - // FIXME: If the kind is "compiler" warn if the string is present (it is - // ignored). - // FIXME: 'lib' requires a comment string. - // FIXME: 'linker' requires a comment string, and has a specific list of - // things that are allowable. - - if (Tok.isNot(tok::r_paren)) { - Diag(Tok.getLocation(), diag::err_pragma_comment_malformed); - return; - } - Lex(Tok); // eat the r_paren. - - if (Tok.isNot(tok::eod)) { - Diag(Tok.getLocation(), diag::err_pragma_comment_malformed); - return; - } - - // If the pragma is lexically sound, notify any interested PPCallbacks. - if (Callbacks) - Callbacks->PragmaComment(CommentLoc, II, ArgumentString); -} - -/// HandlePragmaMessage - Handle the microsoft and gcc \#pragma message -/// extension. The syntax is: -/// \code -/// #pragma message(string) -/// \endcode -/// OR, in GCC mode: -/// \code -/// #pragma message string -/// \endcode -/// string 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); - bool ExpectClosingParen = false; - switch (Tok.getKind()) { - case tok::l_paren: - // We have a MSVC style pragma message. - ExpectClosingParen = true; - // Read the string. - Lex(Tok); - break; - case tok::string_literal: - // We have a GCC style pragma message, and we just read the string. - break; - default: - Diag(MessageLoc, diag::err_pragma_message_malformed); - return; - } - - std::string MessageString; - if (!FinishLexStringLiteral(Tok, MessageString, "pragma message", - /*MacroExpansion=*/true)) - return; - - if (ExpectClosingParen) { - 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::eod)) { - 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); -} - -/// ParsePragmaPushOrPopMacro - Handle parsing of pragma push_macro/pop_macro. +/// ParsePragmaPushOrPopMacro - Handle parsing of pragma push_macro/pop_macro. /// Return the IdentifierInfo* associated with the macro to push or pop. IdentifierInfo *Preprocessor::ParsePragmaPushOrPopMacro(Token &Tok) { // Remember the pragma token location. @@ -995,10 +878,40 @@ struct PragmaDebugHandler : public PragmaHandler { llvm::CrashRecoveryContext *CRC =llvm::CrashRecoveryContext::GetCurrent(); if (CRC) CRC->HandleCrash(); + } else if (II->isStr("captured")) { + HandleCaptured(PP); } else { PP.Diag(Tok, diag::warn_pragma_debug_unexpected_command) << II->getName(); } + + PPCallbacks *Callbacks = PP.getPPCallbacks(); + if (Callbacks) + Callbacks->PragmaDebug(Tok.getLocation(), II->getName()); + } + + void HandleCaptured(Preprocessor &PP) { + // Skip if emitting preprocessed output. + if (PP.isPreprocessedOutput()) + return; + + Token Tok; + PP.LexUnexpandedToken(Tok); + + if (Tok.isNot(tok::eod)) { + PP.Diag(Tok, diag::ext_pp_extra_tokens_at_eol) + << "pragma clang __debug captured"; + return; + } + + SourceLocation NameLoc = Tok.getLocation(); + Token *Toks = PP.getPreprocessorAllocator().Allocate<Token>(1); + Toks->startToken(); + Toks->setKind(tok::annot_pragma_captured); + Toks->setLocation(NameLoc); + + PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true, + /*OwnsTokens=*/false); } // Disable MSVC warning about runtime stack overflow. @@ -1086,15 +999,6 @@ public: } }; -/// PragmaCommentHandler - "\#pragma comment ...". -struct PragmaCommentHandler : public PragmaHandler { - PragmaCommentHandler() : PragmaHandler("comment") {} - virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, - Token &CommentTok) { - PP.HandlePragmaComment(CommentTok); - } -}; - /// PragmaIncludeAliasHandler - "\#pragma include_alias("...")". struct PragmaIncludeAliasHandler : public PragmaHandler { PragmaIncludeAliasHandler() : PragmaHandler("include_alias") {} @@ -1104,12 +1008,88 @@ struct PragmaIncludeAliasHandler : public PragmaHandler { } }; -/// PragmaMessageHandler - "\#pragma message("...")". +/// PragmaMessageHandler - Handle the microsoft and gcc \#pragma message +/// extension. The syntax is: +/// \code +/// #pragma message(string) +/// \endcode +/// OR, in GCC mode: +/// \code +/// #pragma message string +/// \endcode +/// string is a string, which is fully macro expanded, and permits string +/// concatenation, embedded escape characters, etc... See MSDN for more details. +/// Also handles \#pragma GCC warning and \#pragma GCC error which take the same +/// form as \#pragma message. struct PragmaMessageHandler : public PragmaHandler { - PragmaMessageHandler() : PragmaHandler("message") {} +private: + const PPCallbacks::PragmaMessageKind Kind; + const StringRef Namespace; + + static const char* PragmaKind(PPCallbacks::PragmaMessageKind Kind, + bool PragmaNameOnly = false) { + switch (Kind) { + case PPCallbacks::PMK_Message: + return PragmaNameOnly ? "message" : "pragma message"; + case PPCallbacks::PMK_Warning: + return PragmaNameOnly ? "warning" : "pragma warning"; + case PPCallbacks::PMK_Error: + return PragmaNameOnly ? "error" : "pragma error"; + } + llvm_unreachable("Unknown PragmaMessageKind!"); + } + +public: + PragmaMessageHandler(PPCallbacks::PragmaMessageKind Kind, + StringRef Namespace = StringRef()) + : PragmaHandler(PragmaKind(Kind, true)), Kind(Kind), Namespace(Namespace) {} + virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, - Token &CommentTok) { - PP.HandlePragmaMessage(CommentTok); + Token &Tok) { + SourceLocation MessageLoc = Tok.getLocation(); + PP.Lex(Tok); + bool ExpectClosingParen = false; + switch (Tok.getKind()) { + case tok::l_paren: + // We have a MSVC style pragma message. + ExpectClosingParen = true; + // Read the string. + PP.Lex(Tok); + break; + case tok::string_literal: + // We have a GCC style pragma message, and we just read the string. + break; + default: + PP.Diag(MessageLoc, diag::err_pragma_message_malformed) << Kind; + return; + } + + std::string MessageString; + if (!PP.FinishLexStringLiteral(Tok, MessageString, PragmaKind(Kind), + /*MacroExpansion=*/true)) + return; + + if (ExpectClosingParen) { + if (Tok.isNot(tok::r_paren)) { + PP.Diag(Tok.getLocation(), diag::err_pragma_message_malformed) << Kind; + return; + } + PP.Lex(Tok); // eat the r_paren. + } + + if (Tok.isNot(tok::eod)) { + PP.Diag(Tok.getLocation(), diag::err_pragma_message_malformed) << Kind; + return; + } + + // Output the message. + PP.Diag(MessageLoc, (Kind == PPCallbacks::PMK_Error) + ? diag::err_pragma_message + : diag::warn_pragma_message) << MessageString; + + // If the pragma is lexically sound, notify any interested PPCallbacks. + if (PPCallbacks *Callbacks = PP.getPPCallbacks()) + Callbacks->PragmaMessage(MessageLoc, Namespace, Kind, MessageString); } }; @@ -1257,13 +1237,17 @@ void Preprocessor::RegisterBuiltinPragmas() { AddPragmaHandler(new PragmaMarkHandler()); AddPragmaHandler(new PragmaPushMacroHandler()); AddPragmaHandler(new PragmaPopMacroHandler()); - AddPragmaHandler(new PragmaMessageHandler()); + AddPragmaHandler(new PragmaMessageHandler(PPCallbacks::PMK_Message)); // #pragma GCC ... AddPragmaHandler("GCC", new PragmaPoisonHandler()); AddPragmaHandler("GCC", new PragmaSystemHeaderHandler()); AddPragmaHandler("GCC", new PragmaDependencyHandler()); AddPragmaHandler("GCC", new PragmaDiagnosticHandler("GCC")); + AddPragmaHandler("GCC", new PragmaMessageHandler(PPCallbacks::PMK_Warning, + "GCC")); + AddPragmaHandler("GCC", new PragmaMessageHandler(PPCallbacks::PMK_Error, + "GCC")); // #pragma clang ... AddPragmaHandler("clang", new PragmaPoisonHandler()); AddPragmaHandler("clang", new PragmaSystemHeaderHandler()); @@ -1278,7 +1262,6 @@ void Preprocessor::RegisterBuiltinPragmas() { // MS extensions. if (LangOpts.MicrosoftExt) { - AddPragmaHandler(new PragmaCommentHandler()); AddPragmaHandler(new PragmaIncludeAliasHandler()); AddPragmaHandler(new PragmaRegionHandler("region")); AddPragmaHandler(new PragmaRegionHandler("endregion")); |