diff options
author | dim <dim@FreeBSD.org> | 2013-04-08 18:45:10 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2013-04-08 18:45:10 +0000 |
commit | c72c57c9e9b69944e3e009cd5e209634839581d3 (patch) | |
tree | 4fc2f184c499d106f29a386c452b49e5197bf63d /lib/Lex/Pragma.cpp | |
parent | 5b20025c30d23d521e12c1f33ec8fa6b821952cd (diff) | |
download | FreeBSD-src-c72c57c9e9b69944e3e009cd5e209634839581d3.zip FreeBSD-src-c72c57c9e9b69944e3e009cd5e209634839581d3.tar.gz |
Vendor import of clang trunk r178860:
http://llvm.org/svn/llvm-project/cfe/trunk@178860
Diffstat (limited to 'lib/Lex/Pragma.cpp')
-rw-r--r-- | lib/Lex/Pragma.cpp | 220 |
1 files changed, 96 insertions, 124 deletions
diff --git a/lib/Lex/Pragma.cpp b/lib/Lex/Pragma.cpp index e7e6c37..95e8a8c 100644 --- a/lib/Lex/Pragma.cpp +++ b/lib/Lex/Pragma.cpp @@ -13,13 +13,13 @@ //===----------------------------------------------------------------------===// #include "clang/Lex/Pragma.h" +#include "clang/Basic/FileManager.h" +#include "clang/Basic/SourceManager.h" #include "clang/Lex/HeaderSearch.h" +#include "clang/Lex/LexDiagnostic.h" #include "clang/Lex/LiteralSupport.h" -#include "clang/Lex/Preprocessor.h" #include "clang/Lex/MacroInfo.h" -#include "clang/Lex/LexDiagnostic.h" -#include "clang/Basic/FileManager.h" -#include "clang/Basic/SourceManager.h" +#include "clang/Lex/Preprocessor.h" #include "llvm/Support/CrashRecoveryContext.h" #include "llvm/Support/ErrorHandling.h" #include <algorithm> @@ -184,7 +184,7 @@ void Preprocessor::Handle_Pragma(Token &Tok) { // Read the '"..."'. Lex(Tok); - if (Tok.isNot(tok::string_literal) && Tok.isNot(tok::wide_string_literal)) { + if (!tok::isStringLiteral(Tok.getKind())) { Diag(PragmaLoc, diag::err__Pragma_malformed); // Skip this token, and the ')', if present. if (Tok.isNot(tok::r_paren)) @@ -219,15 +219,50 @@ void Preprocessor::Handle_Pragma(Token &Tok) { SourceLocation RParenLoc = Tok.getLocation(); std::string StrVal = getSpelling(StrTok); - // The _Pragma is lexically sound. Destringize according to C99 6.10.9.1: - // "The string literal is destringized by deleting the L prefix, if present, + // The _Pragma is lexically sound. Destringize according to C11 6.10.9.1: + // "The string literal is destringized by deleting any encoding prefix, // deleting the leading and trailing double-quotes, replacing each escape // sequence \" by a double-quote, and replacing each escape sequence \\ by a // single backslash." - if (StrVal[0] == 'L') // Remove L prefix. + if (StrVal[0] == 'L' || StrVal[0] == 'U' || + (StrVal[0] == 'u' && StrVal[1] != '8')) StrVal.erase(StrVal.begin()); - assert(StrVal[0] == '"' && StrVal[StrVal.size()-1] == '"' && - "Invalid string token!"); + else if (StrVal[0] == 'u') + StrVal.erase(StrVal.begin(), StrVal.begin() + 2); + + if (StrVal[0] == 'R') { + // FIXME: C++11 does not specify how to handle raw-string-literals here. + // We strip off the 'R', the quotes, the d-char-sequences, and the parens. + assert(StrVal[1] == '"' && StrVal[StrVal.size() - 1] == '"' && + "Invalid raw string token!"); + + // Measure the length of the d-char-sequence. + unsigned NumDChars = 0; + while (StrVal[2 + NumDChars] != '(') { + assert(NumDChars < (StrVal.size() - 5) / 2 && + "Invalid raw string token!"); + ++NumDChars; + } + assert(StrVal[StrVal.size() - 2 - NumDChars] == ')'); + + // Remove 'R " d-char-sequence' and 'd-char-sequence "'. We'll replace the + // parens below. + StrVal.erase(0, 2 + NumDChars); + StrVal.erase(StrVal.size() - 1 - NumDChars); + } else { + assert(StrVal[0] == '"' && StrVal[StrVal.size()-1] == '"' && + "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] == '"')) { + // \\ -> '\' and \" -> '"'. + StrVal.erase(StrVal.begin()+i); + --e; + } + } + } // Remove the front quote, replacing it with a space, so that the pragma // contents appear to have a space before them. @@ -236,16 +271,6 @@ void Preprocessor::Handle_Pragma(Token &Tok) { // Replace the terminating quote with a \n. StrVal[StrVal.size()-1] = '\n'; - // Remove escaped quotes and escapes. - for (unsigned i = 0, e = StrVal.size(); i != e-1; ++i) { - if (StrVal[i] == '\\' && - (StrVal[i+1] == '\\' || StrVal[i+1] == '"')) { - // \\ -> '\' and \" -> '"'. - StrVal.erase(StrVal.begin()+i); - --e; - } - } - // Plop the string (including the newline and trailing null) into a buffer // where we can lex it. Token TmpTok; @@ -470,7 +495,7 @@ void Preprocessor::HandlePragmaDependency(Token &DependencyTok) { /// /// The syntax is: /// \code -/// \#pragma comment(linker, "foo") +/// #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 @@ -502,38 +527,10 @@ void Preprocessor::HandlePragmaComment(Token &Tok) { // 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, + "pragma comment", + /*MacroExpansion=*/true)) + return; // FIXME: If the kind is "compiler" warn if the string is present (it is // ignored). @@ -560,11 +557,11 @@ void Preprocessor::HandlePragmaComment(Token &Tok) { /// HandlePragmaMessage - Handle the microsoft and gcc \#pragma message /// extension. The syntax is: /// \code -/// \#pragma message(string) +/// #pragma message(string) /// \endcode /// OR, in GCC mode: /// \code -/// \#pragma message string +/// #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. @@ -587,34 +584,10 @@ void Preprocessor::HandlePragmaMessage(Token &Tok) { 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, "pragma message", + /*MacroExpansion=*/true)) return; - } - - StringRef MessageString(Literal.GetString()); if (ExpectClosingParen) { if (Tok.isNot(tok::r_paren)) { @@ -692,7 +665,7 @@ IdentifierInfo *Preprocessor::ParsePragmaPushOrPopMacro(Token &Tok) { /// /// The syntax is: /// \code -/// \#pragma push_macro("macro") +/// #pragma push_macro("macro") /// \endcode void Preprocessor::HandlePragmaPushMacro(Token &PushMacroTok) { // Parse the pragma directive and get the macro IdentifierInfo*. @@ -702,17 +675,13 @@ void Preprocessor::HandlePragmaPushMacro(Token &PushMacroTok) { // Get the MacroInfo associated with IdentInfo. MacroInfo *MI = getMacroInfo(IdentInfo); - MacroInfo *MacroCopyToPush = 0; if (MI) { - // Make a clone of MI. - MacroCopyToPush = CloneMacroInfo(*MI); - // Allow the original MacroInfo to be redefined later. MI->setIsAllowRedefinitionsWithoutWarning(true); } // Push the cloned MacroInfo so we can retrieve it later. - PragmaPushMacroInfo[IdentInfo].push_back(MacroCopyToPush); + PragmaPushMacroInfo[IdentInfo].push_back(MI); } /// \brief Handle \#pragma pop_macro. @@ -733,10 +702,11 @@ void Preprocessor::HandlePragmaPopMacro(Token &PopMacroTok) { PragmaPushMacroInfo.find(IdentInfo); if (iter != PragmaPushMacroInfo.end()) { // Forget the MacroInfo currently associated with IdentInfo. - if (MacroInfo *CurrentMI = getMacroInfo(IdentInfo)) { - if (CurrentMI->isWarnIfUnused()) - WarnUnusedMacroLocs.erase(CurrentMI->getDefinitionLoc()); - UndefineMacro(IdentInfo, CurrentMI, MessageLoc); + if (MacroDirective *CurrentMD = getMacroDirective(IdentInfo)) { + MacroInfo *MI = CurrentMD->getMacroInfo(); + if (MI->isWarnIfUnused()) + WarnUnusedMacroLocs.erase(MI->getDefinitionLoc()); + appendMacroDirective(IdentInfo, AllocateUndefMacroDirective(MessageLoc)); } // Get the MacroInfo we want to reinstall. @@ -744,9 +714,8 @@ void Preprocessor::HandlePragmaPopMacro(Token &PopMacroTok) { if (MacroToReInstall) { // Reinstall the previously pushed macro. - setMacroInfo(IdentInfo, MacroToReInstall); - } else if (IdentInfo->hasMacroDefinition()) { - clearMacroInfo(IdentInfo); + appendDefMacroDirective(IdentInfo, MacroToReInstall, MessageLoc, + /*isImported=*/false); } // Pop PragmaPushMacroInfo stack. @@ -1090,50 +1059,28 @@ public: } 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, "pragma diagnostic", + /*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); } @@ -1277,6 +1224,29 @@ struct PragmaARCCFCodeAuditedHandler : public PragmaHandler { } }; + /// \brief Handle "\#pragma region [...]" + /// + /// The syntax is + /// \code + /// #pragma region [optional name] + /// #pragma endregion [optional comment] + /// \endcode + /// + /// \note This is + /// <a href="http://msdn.microsoft.com/en-us/library/b6xkz944(v=vs.80).aspx">editor-only</a> + /// pragma, just skipped by compiler. + struct PragmaRegionHandler : public PragmaHandler { + PragmaRegionHandler(const char *pragma) : PragmaHandler(pragma) { } + + virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &NameTok) { + // #pragma region: endregion matches can be verified + // __pragma(region): no sense, but ignored by msvc + // _Pragma is not valid for MSVC, but there isn't any point + // to handle a _Pragma differently. + } + }; + } // end anonymous namespace @@ -1310,5 +1280,7 @@ void Preprocessor::RegisterBuiltinPragmas() { if (LangOpts.MicrosoftExt) { AddPragmaHandler(new PragmaCommentHandler()); AddPragmaHandler(new PragmaIncludeAliasHandler()); + AddPragmaHandler(new PragmaRegionHandler("region")); + AddPragmaHandler(new PragmaRegionHandler("endregion")); } } |