diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Lex')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Lex/HeaderMap.cpp | 2 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Lex/HeaderSearch.cpp | 47 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Lex/Lexer.cpp | 75 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Lex/LiteralSupport.cpp | 263 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Lex/MacroArgs.cpp | 2 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Lex/MacroInfo.cpp | 90 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Lex/ModuleMap.cpp | 524 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Lex/PPDirectives.cpp | 56 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Lex/PPExpressions.cpp | 20 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Lex/PPLexerChange.cpp | 6 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Lex/PPMacroExpansion.cpp | 333 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Lex/PTHLexer.cpp | 11 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Lex/Pragma.cpp | 22 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Lex/PreprocessingRecord.cpp | 56 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Lex/Preprocessor.cpp | 66 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Lex/TokenLexer.cpp | 88 |
16 files changed, 1203 insertions, 458 deletions
diff --git a/contrib/llvm/tools/clang/lib/Lex/HeaderMap.cpp b/contrib/llvm/tools/clang/lib/Lex/HeaderMap.cpp index bbfc1df..7dc0491 100644 --- a/contrib/llvm/tools/clang/lib/Lex/HeaderMap.cpp +++ b/contrib/llvm/tools/clang/lib/Lex/HeaderMap.cpp @@ -144,7 +144,7 @@ HMapBucket HeaderMap::getBucket(unsigned BucketNo) const { sizeof(HMapHeader)); const HMapBucket *BucketPtr = BucketArray+BucketNo; - if ((char*)(BucketPtr+1) > FileBuffer->getBufferEnd()) { + if ((const char*)(BucketPtr+1) > FileBuffer->getBufferEnd()) { Result.Prefix = 0; Result.Suffix = 0; return Result; // Invalid buffer, corrupt hmap. diff --git a/contrib/llvm/tools/clang/lib/Lex/HeaderSearch.cpp b/contrib/llvm/tools/clang/lib/Lex/HeaderSearch.cpp index bb3a673..67000b68 100644 --- a/contrib/llvm/tools/clang/lib/Lex/HeaderSearch.cpp +++ b/contrib/llvm/tools/clang/lib/Lex/HeaderSearch.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "clang/Lex/HeaderSearch.h" +#include "clang/Lex/HeaderSearchOptions.h" #include "clang/Lex/HeaderMap.h" #include "clang/Lex/Lexer.h" #include "clang/Basic/Diagnostic.h" @@ -38,10 +39,11 @@ HeaderFileInfo::getControllingMacro(ExternalIdentifierLookup *External) { ExternalHeaderFileInfoSource::~ExternalHeaderFileInfoSource() {} -HeaderSearch::HeaderSearch(FileManager &FM, DiagnosticsEngine &Diags, +HeaderSearch::HeaderSearch(llvm::IntrusiveRefCntPtr<HeaderSearchOptions> HSOpts, + FileManager &FM, DiagnosticsEngine &Diags, const LangOptions &LangOpts, const TargetInfo *Target) - : FileMgr(FM), Diags(Diags), FrameworkMap(64), + : HSOpts(HSOpts), FileMgr(FM), FrameworkMap(64), ModMap(FileMgr, *Diags.getClient(), LangOpts, Target) { AngledDirIdx = 0; @@ -905,7 +907,20 @@ Module *HeaderSearch::loadFrameworkModule(StringRef Name, SubmodulePath.push_back(Name); // Walk the directory structure to find any enclosing frameworks. +#ifdef LLVM_ON_UNIX + // Note: as an egregious but useful hack we use the real path here, because + // frameworks moving from top-level frameworks to embedded frameworks tend + // to be symlinked from the top-level location to the embedded location, + // and we need to resolve lookups as if we had found the embedded location. + char RealDirName[PATH_MAX]; + StringRef DirName; + if (realpath(Dir->getName(), RealDirName)) + DirName = RealDirName; + else + DirName = Dir->getName(); +#else StringRef DirName = Dir->getName(); +#endif do { // Get the parent directory name. DirName = llvm::sys::path::parent_path(DirName); @@ -924,7 +939,33 @@ Module *HeaderSearch::loadFrameworkModule(StringRef Name, TopFrameworkDir = Dir; } } while (true); - + + // Determine whether we're allowed to infer a module map. + bool canInfer = false; + if (llvm::sys::path::has_parent_path(TopFrameworkDir->getName())) { + // Figure out the parent path. + StringRef Parent = llvm::sys::path::parent_path(TopFrameworkDir->getName()); + if (const DirectoryEntry *ParentDir = FileMgr.getDirectory(Parent)) { + // If there's a module map file in the parent directory, it can + // explicitly allow us to infer framework modules. + switch (loadModuleMapFile(ParentDir)) { + case LMM_AlreadyLoaded: + case LMM_NewlyLoaded: { + StringRef Name = llvm::sys::path::stem(TopFrameworkDir->getName()); + canInfer = ModMap.canInferFrameworkModule(ParentDir, Name, IsSystem); + break; + } + case LMM_InvalidModuleMap: + case LMM_NoDirectory: + break; + } + } + } + + // If we're not allowed to infer a module map, we're done. + if (!canInfer) + return 0; + // Try to infer a module map from the top-level framework directory. Module *Result = ModMap.inferFrameworkModule(SubmodulePath.back(), TopFrameworkDir, diff --git a/contrib/llvm/tools/clang/lib/Lex/Lexer.cpp b/contrib/llvm/tools/clang/lib/Lex/Lexer.cpp index 5212dd8..a5ba7db 100644 --- a/contrib/llvm/tools/clang/lib/Lex/Lexer.cpp +++ b/contrib/llvm/tools/clang/lib/Lex/Lexer.cpp @@ -513,10 +513,13 @@ Lexer::ComputePreamble(const llvm::MemoryBuffer *Buffer, // "fake" file source location at offset 1 so that the lexer will track our // position within the file. const unsigned StartOffset = 1; - SourceLocation StartLoc = SourceLocation::getFromRawEncoding(StartOffset); - Lexer TheLexer(StartLoc, LangOpts, Buffer->getBufferStart(), + SourceLocation FileLoc = SourceLocation::getFromRawEncoding(StartOffset); + Lexer TheLexer(FileLoc, LangOpts, Buffer->getBufferStart(), Buffer->getBufferStart(), Buffer->getBufferEnd()); - + + // StartLoc will differ from FileLoc if there is a BOM that was skipped. + SourceLocation StartLoc = TheLexer.getSourceLocation(); + bool InPreprocessorDirective = false; Token TheTok; Token IfStartTok; @@ -1534,7 +1537,7 @@ FinishIdentifier: /// isHexaLiteral - Return true if Start points to a hex constant. /// in microsoft mode (where this is supposed to be several different tokens). -static bool isHexaLiteral(const char *Start, const LangOptions &LangOpts) { +bool Lexer::isHexaLiteral(const char *Start, const LangOptions &LangOpts) { unsigned Size; char C1 = Lexer::getCharAndSizeNoWarn(Start, Size, LangOpts); if (C1 != '0') @@ -1813,17 +1816,18 @@ void Lexer::LexCharConstant(Token &Result, const char *CurPtr, while (C != '\'') { // Skip escaped characters. - if (C == '\\') { - // Skip the escaped character. - // FIXME: UCN's - getAndAdvanceChar(CurPtr, Result); - } else if (C == '\n' || C == '\r' || // Newline. - (C == 0 && CurPtr-1 == BufferEnd)) { // End of file. + if (C == '\\') + C = getAndAdvanceChar(CurPtr, Result); + + if (C == '\n' || C == '\r' || // Newline. + (C == 0 && CurPtr-1 == BufferEnd)) { // End of file. if (!isLexingRawMode() && !LangOpts.AsmPreprocessor) Diag(BufferPtr, diag::ext_unterminated_char); FormTokenWithChars(Result, CurPtr-1, tok::unknown); return; - } else if (C == 0) { + } + + if (C == 0) { if (isCodeCompletionPoint(CurPtr-1)) { PP->CodeCompleteNaturalLanguage(); FormTokenWithChars(Result, CurPtr-1, tok::unknown); @@ -1895,21 +1899,21 @@ bool Lexer::SkipWhitespace(Token &Result, const char *CurPtr) { return false; } -// SkipBCPLComment - We have just read the // characters from input. Skip until -// we find the newline character thats terminate the comment. Then update -/// BufferPtr and return. +/// We have just read the // characters from input. Skip until we find the +/// newline character thats terminate the comment. Then update BufferPtr and +/// return. /// /// If we're in KeepCommentMode or any CommentHandler has inserted /// some tokens, this will store the first token and return true. -bool Lexer::SkipBCPLComment(Token &Result, const char *CurPtr) { - // If BCPL comments aren't explicitly enabled for this language, emit an +bool Lexer::SkipLineComment(Token &Result, const char *CurPtr) { + // If Line comments aren't explicitly enabled for this language, emit an // extension warning. - if (!LangOpts.BCPLComment && !isLexingRawMode()) { - Diag(BufferPtr, diag::ext_bcpl_comment); + if (!LangOpts.LineComment && !isLexingRawMode()) { + Diag(BufferPtr, diag::ext_line_comment); // Mark them enabled so we only emit one warning for this translation // unit. - LangOpts.BCPLComment = true; + LangOpts.LineComment = true; } // Scan over the body of the comment. The common case, when scanning, is that @@ -1973,7 +1977,7 @@ bool Lexer::SkipBCPLComment(Token &Result, const char *CurPtr) { } if (!isLexingRawMode()) - Diag(OldPtr-1, diag::ext_multi_line_bcpl_comment); + Diag(OldPtr-1, diag::ext_multi_line_line_comment); break; } } @@ -2002,7 +2006,7 @@ bool Lexer::SkipBCPLComment(Token &Result, const char *CurPtr) { // If we are returning comments as tokens, return this comment as a token. if (inKeepCommentMode()) - return SaveBCPLComment(Result, CurPtr); + return SaveLineComment(Result, CurPtr); // If we are inside a preprocessor directive and we see the end of line, // return immediately, so that the lexer can return this as an EOD token. @@ -2026,9 +2030,9 @@ bool Lexer::SkipBCPLComment(Token &Result, const char *CurPtr) { return false; } -/// SaveBCPLComment - If in save-comment mode, package up this BCPL comment in -/// an appropriate way and return it. -bool Lexer::SaveBCPLComment(Token &Result, const char *CurPtr) { +/// If in save-comment mode, package up this Line comment in an appropriate +/// way and return it. +bool Lexer::SaveLineComment(Token &Result, const char *CurPtr) { // If we're not in a preprocessor directive, just return the // comment // directly. FormTokenWithChars(Result, CurPtr, tok::comment); @@ -2036,19 +2040,19 @@ bool Lexer::SaveBCPLComment(Token &Result, const char *CurPtr) { if (!ParsingPreprocessorDirective || LexingRawMode) return true; - // If this BCPL-style comment is in a macro definition, transmogrify it into + // If this Line-style comment is in a macro definition, transmogrify it into // a C-style block comment. bool Invalid = false; std::string Spelling = PP->getSpelling(Result, &Invalid); if (Invalid) return true; - assert(Spelling[0] == '/' && Spelling[1] == '/' && "Not bcpl comment?"); + assert(Spelling[0] == '/' && Spelling[1] == '/' && "Not line comment?"); Spelling[1] = '*'; // Change prefix to "/*". Spelling += "*/"; // add suffix. Result.setKind(tok::comment); - PP->CreateString(&Spelling[0], Spelling.size(), Result, + PP->CreateString(Spelling, Result, Result.getLocation(), Result.getLocation()); return true; } @@ -2179,7 +2183,8 @@ bool Lexer::SkipBlockComment(Token &Result, const char *CurPtr) { #ifdef __SSE2__ __m128i Slashes = _mm_set1_epi8('/'); while (CurPtr+16 <= BufferEnd) { - int cmp = _mm_movemask_epi8(_mm_cmpeq_epi8(*(__m128i*)CurPtr, Slashes)); + int cmp = _mm_movemask_epi8(_mm_cmpeq_epi8(*(const __m128i*)CurPtr, + Slashes)); if (cmp != 0) { // Adjust the pointer to point directly after the first slash. It's // not necessary to set C here, it will be overwritten at the end of @@ -2669,8 +2674,8 @@ LexNextToken: // If the next token is obviously a // or /* */ comment, skip it efficiently // too (without going through the big switch stmt). if (CurPtr[0] == '/' && CurPtr[1] == '/' && !inKeepCommentMode() && - LangOpts.BCPLComment && !LangOpts.TraditionalCPP) { - if (SkipBCPLComment(Result, CurPtr+2)) + LangOpts.LineComment && !LangOpts.TraditionalCPP) { + if (SkipLineComment(Result, CurPtr+2)) return; // There is a token to return. goto SkipIgnoredUnits; } else if (CurPtr[0] == '/' && CurPtr[1] == '*' && !inKeepCommentMode()) { @@ -2955,19 +2960,19 @@ LexNextToken: case '/': // 6.4.9: Comments Char = getCharAndSize(CurPtr, SizeTmp); - if (Char == '/') { // BCPL comment. - // Even if BCPL comments are disabled (e.g. in C89 mode), we generally + if (Char == '/') { // Line comment. + // Even if Line comments are disabled (e.g. in C89 mode), we generally // want to lex this as a comment. There is one problem with this though, // that in one particular corner case, this can change the behavior of the // resultant program. For example, In "foo //**/ bar", C89 would lex - // this as "foo / bar" and langauges with BCPL comments would lex it as + // this as "foo / bar" and langauges with Line comments would lex it as // "foo". Check to see if the character after the second slash is a '*'. // If so, we will lex that as a "/" instead of the start of a comment. // However, we never do this in -traditional-cpp mode. - if ((LangOpts.BCPLComment || + if ((LangOpts.LineComment || getCharAndSize(CurPtr+SizeTmp, SizeTmp2) != '*') && !LangOpts.TraditionalCPP) { - if (SkipBCPLComment(Result, ConsumeChar(CurPtr, SizeTmp, Result))) + if (SkipLineComment(Result, ConsumeChar(CurPtr, SizeTmp, Result))) return; // There is a token to return. // It is common for the tokens immediately after a // comment to be diff --git a/contrib/llvm/tools/clang/lib/Lex/LiteralSupport.cpp b/contrib/llvm/tools/clang/lib/Lex/LiteralSupport.cpp index 9e3c778..e30612e 100644 --- a/contrib/llvm/tools/clang/lib/Lex/LiteralSupport.cpp +++ b/contrib/llvm/tools/clang/lib/Lex/LiteralSupport.cpp @@ -49,12 +49,46 @@ static unsigned getCharWidth(tok::TokenKind kind, const TargetInfo &Target) { } } +static CharSourceRange MakeCharSourceRange(const LangOptions &Features, + FullSourceLoc TokLoc, + const char *TokBegin, + const char *TokRangeBegin, + const char *TokRangeEnd) { + SourceLocation Begin = + Lexer::AdvanceToTokenCharacter(TokLoc, TokRangeBegin - TokBegin, + TokLoc.getManager(), Features); + SourceLocation End = + Lexer::AdvanceToTokenCharacter(Begin, TokRangeEnd - TokRangeBegin, + TokLoc.getManager(), Features); + return CharSourceRange::getCharRange(Begin, End); +} + +/// \brief Produce a diagnostic highlighting some portion of a literal. +/// +/// Emits the diagnostic \p DiagID, highlighting the range of characters from +/// \p TokRangeBegin (inclusive) to \p TokRangeEnd (exclusive), which must be +/// a substring of a spelling buffer for the token beginning at \p TokBegin. +static DiagnosticBuilder Diag(DiagnosticsEngine *Diags, + const LangOptions &Features, FullSourceLoc TokLoc, + const char *TokBegin, const char *TokRangeBegin, + const char *TokRangeEnd, unsigned DiagID) { + SourceLocation Begin = + Lexer::AdvanceToTokenCharacter(TokLoc, TokRangeBegin - TokBegin, + TokLoc.getManager(), Features); + return Diags->Report(Begin, DiagID) << + MakeCharSourceRange(Features, TokLoc, TokBegin, TokRangeBegin, TokRangeEnd); +} + /// ProcessCharEscape - Parse a standard C escape sequence, which can occur in /// either a character or a string literal. -static unsigned ProcessCharEscape(const char *&ThisTokBuf, +static unsigned ProcessCharEscape(const char *ThisTokBegin, + const char *&ThisTokBuf, const char *ThisTokEnd, bool &HadError, FullSourceLoc Loc, unsigned CharWidth, - DiagnosticsEngine *Diags) { + DiagnosticsEngine *Diags, + const LangOptions &Features) { + const char *EscapeBegin = ThisTokBuf; + // Skip the '\' char. ++ThisTokBuf; @@ -75,12 +109,14 @@ static unsigned ProcessCharEscape(const char *&ThisTokBuf, break; case 'e': if (Diags) - Diags->Report(Loc, diag::ext_nonstandard_escape) << "e"; + Diag(Diags, Features, Loc, ThisTokBegin, EscapeBegin, ThisTokBuf, + diag::ext_nonstandard_escape) << "e"; ResultChar = 27; break; case 'E': if (Diags) - Diags->Report(Loc, diag::ext_nonstandard_escape) << "E"; + Diag(Diags, Features, Loc, ThisTokBegin, EscapeBegin, ThisTokBuf, + diag::ext_nonstandard_escape) << "E"; ResultChar = 27; break; case 'f': @@ -102,7 +138,8 @@ static unsigned ProcessCharEscape(const char *&ThisTokBuf, ResultChar = 0; if (ThisTokBuf == ThisTokEnd || !isxdigit(*ThisTokBuf)) { if (Diags) - Diags->Report(Loc, diag::err_hex_escape_no_digits); + Diag(Diags, Features, Loc, ThisTokBegin, EscapeBegin, ThisTokBuf, + diag::err_hex_escape_no_digits); HadError = 1; break; } @@ -126,7 +163,8 @@ static unsigned ProcessCharEscape(const char *&ThisTokBuf, // Check for overflow. if (Overflow && Diags) // Too many digits to fit in - Diags->Report(Loc, diag::warn_hex_escape_too_large); + Diag(Diags, Features, Loc, ThisTokBegin, EscapeBegin, ThisTokBuf, + diag::warn_hex_escape_too_large); break; } case '0': case '1': case '2': case '3': @@ -148,7 +186,8 @@ static unsigned ProcessCharEscape(const char *&ThisTokBuf, // Check for overflow. Reject '\777', but not L'\777'. if (CharWidth != 32 && (ResultChar >> CharWidth) != 0) { if (Diags) - Diags->Report(Loc, diag::warn_octal_escape_too_large); + Diag(Diags, Features, Loc, ThisTokBegin, EscapeBegin, ThisTokBuf, + diag::warn_octal_escape_too_large); ResultChar &= ~0U >> (32-CharWidth); } break; @@ -158,19 +197,22 @@ static unsigned ProcessCharEscape(const char *&ThisTokBuf, case '(': case '{': case '[': case '%': // GCC accepts these as extensions. We warn about them as such though. if (Diags) - Diags->Report(Loc, diag::ext_nonstandard_escape) - << std::string()+(char)ResultChar; + Diag(Diags, Features, Loc, ThisTokBegin, EscapeBegin, ThisTokBuf, + diag::ext_nonstandard_escape) + << std::string(1, ResultChar); break; default: if (Diags == 0) break; - + if (isgraph(ResultChar)) - Diags->Report(Loc, diag::ext_unknown_escape) - << std::string()+(char)ResultChar; + Diag(Diags, Features, Loc, ThisTokBegin, EscapeBegin, ThisTokBuf, + diag::ext_unknown_escape) + << std::string(1, ResultChar); else - Diags->Report(Loc, diag::ext_unknown_escape) - << "x"+llvm::utohexstr(ResultChar); + Diag(Diags, Features, Loc, ThisTokBegin, EscapeBegin, ThisTokBuf, + diag::ext_unknown_escape) + << "x" + llvm::utohexstr(ResultChar); break; } @@ -185,9 +227,6 @@ static bool ProcessUCNEscape(const char *ThisTokBegin, const char *&ThisTokBuf, FullSourceLoc Loc, DiagnosticsEngine *Diags, const LangOptions &Features, bool in_char_string_literal = false) { - if (!Features.CPlusPlus && !Features.C99 && Diags) - Diags->Report(Loc, diag::warn_ucn_not_valid_in_c89); - const char *UcnBegin = ThisTokBuf; // Skip the '\u' char's. @@ -195,7 +234,8 @@ static bool ProcessUCNEscape(const char *ThisTokBegin, const char *&ThisTokBuf, if (ThisTokBuf == ThisTokEnd || !isxdigit(*ThisTokBuf)) { if (Diags) - Diags->Report(Loc, diag::err_ucn_escape_no_digits); + Diag(Diags, Features, Loc, ThisTokBegin, UcnBegin, ThisTokBuf, + diag::err_ucn_escape_no_digits); return false; } UcnLen = (ThisTokBuf[-1] == 'u' ? 4 : 8); @@ -208,12 +248,9 @@ static bool ProcessUCNEscape(const char *ThisTokBegin, const char *&ThisTokBuf, } // If we didn't consume the proper number of digits, there is a problem. if (UcnLenSave) { - if (Diags) { - SourceLocation L = - Lexer::AdvanceToTokenCharacter(Loc, UcnBegin - ThisTokBegin, - Loc.getManager(), Features); - Diags->Report(L, diag::err_ucn_escape_incomplete); - } + if (Diags) + Diag(Diags, Features, Loc, ThisTokBegin, UcnBegin, ThisTokBuf, + diag::err_ucn_escape_incomplete); return false; } @@ -221,7 +258,8 @@ static bool ProcessUCNEscape(const char *ThisTokBegin, const char *&ThisTokBuf, if ((0xD800 <= UcnVal && UcnVal <= 0xDFFF) || // surrogate codepoints UcnVal > 0x10FFFF) { // maximum legal UTF32 value if (Diags) - Diags->Report(Loc, diag::err_ucn_escape_invalid); + Diag(Diags, Features, Loc, ThisTokBegin, UcnBegin, ThisTokBuf, + diag::err_ucn_escape_invalid); return false; } @@ -231,22 +269,25 @@ static bool ProcessUCNEscape(const char *ThisTokBegin, const char *&ThisTokBuf, (UcnVal != 0x24 && UcnVal != 0x40 && UcnVal != 0x60)) { // $, @, ` bool IsError = (!Features.CPlusPlus0x || !in_char_string_literal); if (Diags) { - SourceLocation UcnBeginLoc = - Lexer::AdvanceToTokenCharacter(Loc, UcnBegin - ThisTokBegin, - Loc.getManager(), Features); char BasicSCSChar = UcnVal; if (UcnVal >= 0x20 && UcnVal < 0x7f) - Diags->Report(UcnBeginLoc, IsError ? diag::err_ucn_escape_basic_scs : - diag::warn_cxx98_compat_literal_ucn_escape_basic_scs) - << StringRef(&BasicSCSChar, 1); + Diag(Diags, Features, Loc, ThisTokBegin, UcnBegin, ThisTokBuf, + IsError ? diag::err_ucn_escape_basic_scs : + diag::warn_cxx98_compat_literal_ucn_escape_basic_scs) + << StringRef(&BasicSCSChar, 1); else - Diags->Report(UcnBeginLoc, IsError ? diag::err_ucn_control_character : - diag::warn_cxx98_compat_literal_ucn_control_character); + Diag(Diags, Features, Loc, ThisTokBegin, UcnBegin, ThisTokBuf, + IsError ? diag::err_ucn_control_character : + diag::warn_cxx98_compat_literal_ucn_control_character); } if (IsError) return false; } + if (!Features.CPlusPlus && !Features.C99 && Diags) + Diag(Diags, Features, Loc, ThisTokBegin, UcnBegin, ThisTokBuf, + diag::warn_ucn_not_valid_in_c89); + return true; } @@ -365,10 +406,10 @@ static void EncodeUCNEscape(const char *ThisTokBegin, const char *&ThisTokBuf, // Finally, we write the bytes into ResultBuf. ResultBuf += bytesToWrite; switch (bytesToWrite) { // note: everything falls through. - case 4: *--ResultBuf = (UTF8)((UcnVal | byteMark) & byteMask); UcnVal >>= 6; - case 3: *--ResultBuf = (UTF8)((UcnVal | byteMark) & byteMask); UcnVal >>= 6; - case 2: *--ResultBuf = (UTF8)((UcnVal | byteMark) & byteMask); UcnVal >>= 6; - case 1: *--ResultBuf = (UTF8) (UcnVal | firstByteMark[bytesToWrite]); + case 4: *--ResultBuf = (UTF8)((UcnVal | byteMark) & byteMask); UcnVal >>= 6; + case 3: *--ResultBuf = (UTF8)((UcnVal | byteMark) & byteMask); UcnVal >>= 6; + case 2: *--ResultBuf = (UTF8)((UcnVal | byteMark) & byteMask); UcnVal >>= 6; + case 1: *--ResultBuf = (UTF8) (UcnVal | firstByteMark[bytesToWrite]); } // Update the buffer. ResultBuf += bytesToWrite; @@ -417,19 +458,19 @@ static void EncodeUCNEscape(const char *ThisTokBegin, const char *&ThisTokBuf, /// floating-constant: [C99 6.4.4.2] /// TODO: add rules... /// -NumericLiteralParser:: -NumericLiteralParser(const char *begin, const char *end, - SourceLocation TokLoc, Preprocessor &pp) - : PP(pp), ThisTokBegin(begin), ThisTokEnd(end) { +NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling, + SourceLocation TokLoc, + Preprocessor &PP) + : PP(PP), ThisTokBegin(TokSpelling.begin()), ThisTokEnd(TokSpelling.end()) { // This routine assumes that the range begin/end matches the regex for integer // and FP constants (specifically, the 'pp-number' regex), and assumes that // the byte at "*end" is both valid and not part of the regex. Because of // this, it doesn't have to check for 'overscan' in various places. - assert(!isalnum(*end) && *end != '.' && *end != '_' && + assert(!isalnum(*ThisTokEnd) && *ThisTokEnd != '.' && *ThisTokEnd != '_' && "Lexer didn't maximally munch?"); - s = DigitsBegin = begin; + s = DigitsBegin = ThisTokBegin; saw_exponent = false; saw_period = false; saw_ud_suffix = false; @@ -451,7 +492,7 @@ NumericLiteralParser(const char *begin, const char *end, if (s == ThisTokEnd) { // Done. } else if (isxdigit(*s) && !(*s == 'e' || *s == 'E')) { - PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, s-begin), + PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, s - ThisTokBegin), diag::err_invalid_decimal_digit) << StringRef(s, 1); hadError = true; return; @@ -469,7 +510,7 @@ NumericLiteralParser(const char *begin, const char *end, if (first_non_digit != s) { s = first_non_digit; } else { - PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, Exponent-begin), + PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, Exponent - ThisTokBegin), diag::err_exponent_has_no_digits); hadError = true; return; @@ -565,7 +606,7 @@ NumericLiteralParser(const char *begin, const char *end, case 'j': case 'J': if (isImaginary) break; // Cannot be repeated. - PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, s-begin), + PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, s - ThisTokBegin), diag::ext_imaginary_constant); isImaginary = true; continue; // Success. @@ -583,7 +624,7 @@ NumericLiteralParser(const char *begin, const char *end, } // Report an error if there are any. - PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, SuffixBegin-begin), + PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, SuffixBegin - ThisTokBegin), isFPConstant ? diag::err_invalid_suffix_float_constant : diag::err_invalid_suffix_integer_constant) << StringRef(SuffixBegin, ThisTokEnd-SuffixBegin); @@ -619,7 +660,7 @@ void NumericLiteralParser::ParseNumberStartingWithZero(SourceLocation TokLoc) { } if (noSignificand) { - PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, s-ThisTokBegin), \ + PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, s - ThisTokBegin), diag::err_hexconstant_requires_digits); hadError = true; return; @@ -722,6 +763,20 @@ void NumericLiteralParser::ParseNumberStartingWithZero(SourceLocation TokLoc) { } } +static bool alwaysFitsInto64Bits(unsigned Radix, unsigned NumDigits) { + switch (Radix) { + case 2: + return NumDigits <= 64; + case 8: + return NumDigits <= 64 / 3; // Digits are groups of 3 bits. + case 10: + return NumDigits <= 19; // floor(log10(2^64)) + case 16: + return NumDigits <= 64 / 4; // Digits are groups of 4 bits. + default: + llvm_unreachable("impossible Radix"); + } +} /// GetIntegerValue - Convert this numeric literal value to an APInt that /// matches Val's input width. If there is an overflow, set Val to the low bits @@ -733,13 +788,11 @@ bool NumericLiteralParser::GetIntegerValue(llvm::APInt &Val) { // integer. This avoids the expensive overflow checking below, and // handles the common cases that matter (small decimal integers and // hex/octal values which don't overflow). - unsigned MaxBitsPerDigit = 1; - while ((1U << MaxBitsPerDigit) < radix) - MaxBitsPerDigit += 1; - if ((SuffixBegin - DigitsBegin) * MaxBitsPerDigit <= 64) { + const unsigned NumDigits = SuffixBegin - DigitsBegin; + if (alwaysFitsInto64Bits(radix, NumDigits)) { uint64_t N = 0; - for (s = DigitsBegin; s != SuffixBegin; ++s) - N = N*radix + HexDigitValue(*s); + for (const char *Ptr = DigitsBegin; Ptr != SuffixBegin; ++Ptr) + N = N * radix + HexDigitValue(*Ptr); // This will truncate the value to Val's input width. Simply check // for overflow by comparing. @@ -748,15 +801,15 @@ bool NumericLiteralParser::GetIntegerValue(llvm::APInt &Val) { } Val = 0; - s = DigitsBegin; + const char *Ptr = DigitsBegin; llvm::APInt RadixVal(Val.getBitWidth(), radix); llvm::APInt CharVal(Val.getBitWidth(), 0); llvm::APInt OldVal = Val; bool OverflowOccurred = false; - while (s < SuffixBegin) { - unsigned C = HexDigitValue(*s++); + while (Ptr < SuffixBegin) { + unsigned C = HexDigitValue(*Ptr++); // If this letter is out of bound for this radix, reject it. assert(C < radix && "NumericLiteralParser ctor should have rejected this"); @@ -943,7 +996,7 @@ CharLiteralParser::CharLiteralParser(const char *begin, const char *end, HadError = true; } else if (*buffer_begin > largest_character_for_kind) { HadError = true; - PP.Diag(Loc,diag::err_character_too_large); + PP.Diag(Loc, diag::err_character_too_large); } ++buffer_begin; @@ -951,9 +1004,9 @@ CharLiteralParser::CharLiteralParser(const char *begin, const char *end, } unsigned CharWidth = getCharWidth(Kind, PP.getTargetInfo()); uint64_t result = - ProcessCharEscape(begin, end, HadError, - FullSourceLoc(Loc,PP.getSourceManager()), - CharWidth, &PP.getDiagnostics()); + ProcessCharEscape(TokBegin, begin, end, HadError, + FullSourceLoc(Loc,PP.getSourceManager()), + CharWidth, &PP.getDiagnostics(), PP.getLangOpts()); *buffer_begin++ = result; } @@ -1110,7 +1163,7 @@ void StringLiteralParser::init(const Token *StringToks, unsigned NumStringToks){ Kind = StringToks[i].getKind(); } else { if (Diags) - Diags->Report(FullSourceLoc(StringToks[i].getLocation(), SM), + Diags->Report(StringToks[i].getLocation(), diag::err_unsupported_string_concat); hadError = true; } @@ -1218,9 +1271,9 @@ void StringLiteralParser::init(const Token *StringToks, unsigned NumStringToks){ assert(ThisTokEnd >= ThisTokBuf && "malformed raw string literal"); // Copy the string over - if (CopyStringFragment(StringRef(ThisTokBuf, ThisTokEnd - ThisTokBuf))) - if (DiagnoseBadString(StringToks[i])) - hadError = true; + if (CopyStringFragment(StringToks[i], ThisTokBegin, + StringRef(ThisTokBuf, ThisTokEnd - ThisTokBuf))) + hadError = true; } else { if (ThisTokBuf[0] != '"') { // The file may have come from PCH and then changed after loading the @@ -1251,9 +1304,9 @@ void StringLiteralParser::init(const Token *StringToks, unsigned NumStringToks){ } while (ThisTokBuf != ThisTokEnd && ThisTokBuf[0] != '\\'); // Copy the character span over. - if (CopyStringFragment(StringRef(InStart, ThisTokBuf - InStart))) - if (DiagnoseBadString(StringToks[i])) - hadError = true; + if (CopyStringFragment(StringToks[i], ThisTokBegin, + StringRef(InStart, ThisTokBuf - InStart))) + hadError = true; continue; } // Is this a Universal Character Name escape? @@ -1266,9 +1319,9 @@ void StringLiteralParser::init(const Token *StringToks, unsigned NumStringToks){ } // Otherwise, this is a non-UCN escape character. Process it. unsigned ResultChar = - ProcessCharEscape(ThisTokBuf, ThisTokEnd, hadError, + ProcessCharEscape(ThisTokBegin, ThisTokBuf, ThisTokEnd, hadError, FullSourceLoc(StringToks[i].getLocation(), SM), - CharByteWidth*8, Diags); + CharByteWidth*8, Diags, Features); if (CharByteWidth == 4) { // FIXME: Make the type of the result buffer correct instead of @@ -1308,8 +1361,8 @@ void StringLiteralParser::init(const Token *StringToks, unsigned NumStringToks){ // Verify that pascal strings aren't too large. if (GetStringLength() > 256) { - if (Diags) - Diags->Report(FullSourceLoc(StringToks[0].getLocation(), SM), + if (Diags) + Diags->Report(StringToks[0].getLocation(), diag::err_pascal_string_too_long) << SourceRange(StringToks[0].getLocation(), StringToks[NumStringToks-1].getLocation()); @@ -1319,9 +1372,9 @@ void StringLiteralParser::init(const Token *StringToks, unsigned NumStringToks){ } else if (Diags) { // Complain if this string literal has too many characters. unsigned MaxChars = Features.CPlusPlus? 65536 : Features.C99 ? 4095 : 509; - + if (GetNumStringChars() > MaxChars) - Diags->Report(FullSourceLoc(StringToks[0].getLocation(), SM), + Diags->Report(StringToks[0].getLocation(), diag::ext_string_too_long) << GetNumStringChars() << MaxChars << (Features.CPlusPlus ? 2 : Features.C99 ? 1 : 0) @@ -1330,21 +1383,61 @@ void StringLiteralParser::init(const Token *StringToks, unsigned NumStringToks){ } } -/// copyStringFragment - This function copies from Start to End into ResultPtr. -/// Performs widening for multi-byte characters. -bool StringLiteralParser::CopyStringFragment(StringRef Fragment) { - return !ConvertUTF8toWide(CharByteWidth, Fragment, ResultPtr); +static const char *resyncUTF8(const char *Err, const char *End) { + if (Err == End) + return End; + End = Err + std::min<unsigned>(getNumBytesForUTF8(*Err), End-Err); + while (++Err != End && (*Err & 0xC0) == 0x80) + ; + return Err; } -bool StringLiteralParser::DiagnoseBadString(const Token &Tok) { +/// \brief This function copies from Fragment, which is a sequence of bytes +/// within Tok's contents (which begin at TokBegin) into ResultPtr. +/// Performs widening for multi-byte characters. +bool StringLiteralParser::CopyStringFragment(const Token &Tok, + const char *TokBegin, + StringRef Fragment) { + const UTF8 *ErrorPtrTmp; + if (ConvertUTF8toWide(CharByteWidth, Fragment, ResultPtr, ErrorPtrTmp)) + return false; + // If we see bad encoding for unprefixed string literals, warn and // simply copy the byte values, for compatibility with gcc and older // versions of clang. bool NoErrorOnBadEncoding = isAscii(); - unsigned Msg = NoErrorOnBadEncoding ? diag::warn_bad_string_encoding : - diag::err_bad_string_encoding; - if (Diags) - Diags->Report(FullSourceLoc(Tok.getLocation(), SM), Msg); + if (NoErrorOnBadEncoding) { + memcpy(ResultPtr, Fragment.data(), Fragment.size()); + ResultPtr += Fragment.size(); + } + + if (Diags) { + const char *ErrorPtr = reinterpret_cast<const char *>(ErrorPtrTmp); + + FullSourceLoc SourceLoc(Tok.getLocation(), SM); + const DiagnosticBuilder &Builder = + Diag(Diags, Features, SourceLoc, TokBegin, + ErrorPtr, resyncUTF8(ErrorPtr, Fragment.end()), + NoErrorOnBadEncoding ? diag::warn_bad_string_encoding + : diag::err_bad_string_encoding); + + const char *NextStart = resyncUTF8(ErrorPtr, Fragment.end()); + StringRef NextFragment(NextStart, Fragment.end()-NextStart); + + // Decode into a dummy buffer. + SmallString<512> Dummy; + Dummy.reserve(Fragment.size() * CharByteWidth); + char *Ptr = Dummy.data(); + + while (!Builder.hasMaxRanges() && + !ConvertUTF8toWide(CharByteWidth, NextFragment, Ptr, ErrorPtrTmp)) { + const char *ErrorPtr = reinterpret_cast<const char *>(ErrorPtrTmp); + NextStart = resyncUTF8(ErrorPtr, Fragment.end()); + Builder << MakeCharSourceRange(Features, SourceLoc, TokBegin, + ErrorPtr, NextStart); + NextFragment = StringRef(NextStart, Fragment.end()-NextStart); + } + } return !NoErrorOnBadEncoding; } @@ -1422,9 +1515,9 @@ unsigned StringLiteralParser::getOffsetOfStringByte(const Token &Tok, } ByteNo -= Len; } else { - ProcessCharEscape(SpellingPtr, SpellingEnd, HadError, + ProcessCharEscape(SpellingStart, SpellingPtr, SpellingEnd, HadError, FullSourceLoc(Tok.getLocation(), SM), - CharByteWidth*8, Diags); + CharByteWidth*8, Diags, Features); --ByteNo; } assert(!HadError && "This method isn't valid on erroneous strings"); diff --git a/contrib/llvm/tools/clang/lib/Lex/MacroArgs.cpp b/contrib/llvm/tools/clang/lib/Lex/MacroArgs.cpp index e2b251a..ed8873d 100644 --- a/contrib/llvm/tools/clang/lib/Lex/MacroArgs.cpp +++ b/contrib/llvm/tools/clang/lib/Lex/MacroArgs.cpp @@ -291,7 +291,7 @@ Token MacroArgs::StringifyArgument(const Token *ArgToks, } } - PP.CreateString(&Result[0], Result.size(), Tok, + PP.CreateString(Result, Tok, ExpansionLocStart, ExpansionLocEnd); return Tok; } diff --git a/contrib/llvm/tools/clang/lib/Lex/MacroInfo.cpp b/contrib/llvm/tools/clang/lib/Lex/MacroInfo.cpp index 3d0c9a1..904f04e 100644 --- a/contrib/llvm/tools/clang/lib/Lex/MacroInfo.cpp +++ b/contrib/llvm/tools/clang/lib/Lex/MacroInfo.cpp @@ -15,47 +15,65 @@ #include "clang/Lex/Preprocessor.h" using namespace clang; -MacroInfo::MacroInfo(SourceLocation DefLoc) : Location(DefLoc) { - IsFunctionLike = false; - IsC99Varargs = false; - IsGNUVarargs = false; - IsBuiltinMacro = false; - IsFromAST = false; - ChangedAfterLoad = false; - IsDisabled = false; - IsUsed = false; - IsAllowRedefinitionsWithoutWarning = false; - IsWarnIfUnused = false; - IsDefinitionLengthCached = false; - IsPublic = true; - - ArgumentList = 0; - NumArguments = 0; +MacroInfo::MacroInfo(SourceLocation DefLoc) + : Location(DefLoc), + PreviousDefinition(0), + ArgumentList(0), + NumArguments(0), + IsDefinitionLengthCached(false), + IsFunctionLike(false), + IsC99Varargs(false), + IsGNUVarargs(false), + IsBuiltinMacro(false), + IsFromAST(false), + ChangedAfterLoad(false), + IsDisabled(false), + IsUsed(false), + IsAllowRedefinitionsWithoutWarning(false), + IsWarnIfUnused(false), + IsPublic(true), + IsHidden(false), + IsAmbiguous(false) { } -MacroInfo::MacroInfo(const MacroInfo &MI, llvm::BumpPtrAllocator &PPAllocator) { - Location = MI.Location; - EndLocation = MI.EndLocation; - ReplacementTokens = MI.ReplacementTokens; - IsFunctionLike = MI.IsFunctionLike; - IsC99Varargs = MI.IsC99Varargs; - IsGNUVarargs = MI.IsGNUVarargs; - IsBuiltinMacro = MI.IsBuiltinMacro; - IsFromAST = MI.IsFromAST; - ChangedAfterLoad = MI.ChangedAfterLoad; - IsDisabled = MI.IsDisabled; - IsUsed = MI.IsUsed; - IsAllowRedefinitionsWithoutWarning = MI.IsAllowRedefinitionsWithoutWarning; - IsWarnIfUnused = MI.IsWarnIfUnused; - IsDefinitionLengthCached = MI.IsDefinitionLengthCached; - DefinitionLength = MI.DefinitionLength; - IsPublic = MI.IsPublic; - - ArgumentList = 0; - NumArguments = 0; +MacroInfo::MacroInfo(const MacroInfo &MI, llvm::BumpPtrAllocator &PPAllocator) + : Location(MI.Location), + EndLocation(MI.EndLocation), + UndefLocation(MI.UndefLocation), + PreviousDefinition(0), + ArgumentList(0), + NumArguments(0), + ReplacementTokens(MI.ReplacementTokens), + DefinitionLength(MI.DefinitionLength), + IsDefinitionLengthCached(MI.IsDefinitionLengthCached), + IsFunctionLike(MI.IsFunctionLike), + IsC99Varargs(MI.IsC99Varargs), + IsGNUVarargs(MI.IsGNUVarargs), + IsBuiltinMacro(MI.IsBuiltinMacro), + IsFromAST(MI.IsFromAST), + ChangedAfterLoad(MI.ChangedAfterLoad), + IsDisabled(MI.IsDisabled), + IsUsed(MI.IsUsed), + IsAllowRedefinitionsWithoutWarning(MI.IsAllowRedefinitionsWithoutWarning), + IsWarnIfUnused(MI.IsWarnIfUnused), + IsPublic(MI.IsPublic), + IsHidden(MI.IsHidden), + IsAmbiguous(MI.IsAmbiguous) { setArgumentList(MI.ArgumentList, MI.NumArguments, PPAllocator); } +const MacroInfo *MacroInfo::findDefinitionAtLoc(SourceLocation L, + SourceManager &SM) const { + assert(L.isValid() && "SourceLocation is invalid."); + for (const MacroInfo *MI = this; MI; MI = MI->PreviousDefinition) { + if (MI->Location.isInvalid() || // For macros defined on the command line. + SM.isBeforeInTranslationUnit(MI->Location, L)) + return (MI->UndefLocation.isInvalid() || + SM.isBeforeInTranslationUnit(L, MI->UndefLocation)) ? MI : NULL; + } + return NULL; +} + unsigned MacroInfo::getDefinitionLengthSlow(SourceManager &SM) const { assert(!IsDefinitionLengthCached); IsDefinitionLengthCached = true; diff --git a/contrib/llvm/tools/clang/lib/Lex/ModuleMap.cpp b/contrib/llvm/tools/clang/lib/Lex/ModuleMap.cpp index 5304311..8a936fa 100644 --- a/contrib/llvm/tools/clang/lib/Lex/ModuleMap.cpp +++ b/contrib/llvm/tools/clang/lib/Lex/ModuleMap.cpp @@ -16,6 +16,7 @@ #include "clang/Lex/LiteralSupport.h" #include "clang/Lex/LexDiagnostic.h" #include "clang/Basic/Diagnostic.h" +#include "clang/Basic/DiagnosticOptions.h" #include "clang/Basic/FileManager.h" #include "clang/Basic/TargetInfo.h" #include "clang/Basic/TargetOptions.h" @@ -26,6 +27,7 @@ #include "llvm/Support/raw_ostream.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSwitch.h" +#include <stdlib.h> using namespace clang; Module::ExportDecl @@ -75,7 +77,7 @@ ModuleMap::ModuleMap(FileManager &FileMgr, const DiagnosticConsumer &DC, { IntrusiveRefCntPtr<DiagnosticIDs> DiagIDs(new DiagnosticIDs); Diags = IntrusiveRefCntPtr<DiagnosticsEngine>( - new DiagnosticsEngine(DiagIDs)); + new DiagnosticsEngine(DiagIDs, new DiagnosticOptions)); Diags->setClient(DC.clone(*Diags), /*ShouldOwnClient=*/true); SourceMgr = new SourceManager(*Diags, FileMgr); } @@ -96,16 +98,62 @@ void ModuleMap::setTarget(const TargetInfo &Target) { this->Target = &Target; } +/// \brief "Sanitize" a filename so that it can be used as an identifier. +static StringRef sanitizeFilenameAsIdentifier(StringRef Name, + SmallVectorImpl<char> &Buffer) { + if (Name.empty()) + return Name; + + // Check whether the filename is already an identifier; this is the common + // case. + bool isIdentifier = true; + for (unsigned I = 0, N = Name.size(); I != N; ++I) { + if (isalpha(Name[I]) || Name[I] == '_' || (isdigit(Name[I]) && I > 0)) + continue; + + isIdentifier = false; + break; + } + + if (!isIdentifier) { + // If we don't already have something with the form of an identifier, + // create a buffer with the sanitized name. + Buffer.clear(); + if (isdigit(Name[0])) + Buffer.push_back('_'); + Buffer.reserve(Buffer.size() + Name.size()); + for (unsigned I = 0, N = Name.size(); I != N; ++I) { + if (isalnum(Name[I]) || isspace(Name[I])) + Buffer.push_back(Name[I]); + else + Buffer.push_back('_'); + } + + Name = StringRef(Buffer.data(), Buffer.size()); + } + + while (llvm::StringSwitch<bool>(Name) +#define KEYWORD(Keyword,Conditions) .Case(#Keyword, true) +#define ALIAS(Keyword, AliasOf, Conditions) .Case(Keyword, true) +#include "clang/Basic/TokenKinds.def" + .Default(false)) { + if (Name.data() != Buffer.data()) + Buffer.append(Name.begin(), Name.end()); + Buffer.push_back('_'); + Name = StringRef(Buffer.data(), Buffer.size()); + } + + return Name; +} + Module *ModuleMap::findModuleForHeader(const FileEntry *File) { - llvm::DenseMap<const FileEntry *, Module *>::iterator Known - = Headers.find(File); + HeadersMap::iterator Known = Headers.find(File); if (Known != Headers.end()) { - // If a header corresponds to an unavailable module, don't report - // that it maps to anything. - if (!Known->second->isAvailable()) + // If a header is not available, don't report that it maps to anything. + if (!Known->second.isAvailable()) return 0; - return Known->second; + return Known->second.getModule(); } const DirectoryEntry *Dir = File->getDir(); @@ -134,7 +182,10 @@ Module *ModuleMap::findModuleForHeader(const FileEntry *File) { for (unsigned I = SkippedDirs.size(); I != 0; --I) { // Find or create the module that corresponds to this directory name. - StringRef Name = llvm::sys::path::stem(SkippedDirs[I-1]->getName()); + SmallString<32> NameBuf; + StringRef Name = sanitizeFilenameAsIdentifier( + llvm::sys::path::stem(SkippedDirs[I-1]->getName()), + NameBuf); Result = findOrCreateModule(Name, Result, /*IsFramework=*/false, Explicit).first; @@ -148,9 +199,12 @@ Module *ModuleMap::findModuleForHeader(const FileEntry *File) { } // Infer a submodule with the same name as this header file. - StringRef Name = llvm::sys::path::stem(File->getName()); + SmallString<32> NameBuf; + StringRef Name = sanitizeFilenameAsIdentifier( + llvm::sys::path::stem(File->getName()), NameBuf); Result = findOrCreateModule(Name, Result, /*IsFramework=*/false, Explicit).first; + Result->TopHeaders.insert(File); // If inferred submodules export everything they import, add a // wildcard to the set of exports. @@ -163,7 +217,7 @@ Module *ModuleMap::findModuleForHeader(const FileEntry *File) { UmbrellaDirs[SkippedDirs[I]] = Result; } - Headers[File] = Result; + Headers[File] = KnownHeader(Result, /*Excluded=*/false); // If a header corresponds to an unavailable module, don't report // that it maps to anything. @@ -188,10 +242,9 @@ Module *ModuleMap::findModuleForHeader(const FileEntry *File) { } bool ModuleMap::isHeaderInUnavailableModule(const FileEntry *Header) { - llvm::DenseMap<const FileEntry *, Module *>::iterator Known - = Headers.find(Header); + HeadersMap::iterator Known = Headers.find(Header); if (Known != Headers.end()) - return !Known->second->isAvailable(); + return !Known->second.isAvailable(); const DirectoryEntry *Dir = Header->getDir(); llvm::SmallVector<const DirectoryEntry *, 2> SkippedDirs; @@ -216,7 +269,10 @@ bool ModuleMap::isHeaderInUnavailableModule(const FileEntry *Header) { if (UmbrellaModule->InferSubmodules) { for (unsigned I = SkippedDirs.size(); I != 0; --I) { // Find or create the module that corresponds to this directory name. - StringRef Name = llvm::sys::path::stem(SkippedDirs[I-1]->getName()); + SmallString<32> NameBuf; + StringRef Name = sanitizeFilenameAsIdentifier( + llvm::sys::path::stem(SkippedDirs[I-1]->getName()), + NameBuf); Found = lookupModuleQualified(Name, Found); if (!Found) return false; @@ -225,7 +281,10 @@ bool ModuleMap::isHeaderInUnavailableModule(const FileEntry *Header) { } // Infer a submodule with the same name as this header file. - StringRef Name = llvm::sys::path::stem(Header->getName()); + SmallString<32> NameBuf; + StringRef Name = sanitizeFilenameAsIdentifier( + llvm::sys::path::stem(Header->getName()), + NameBuf); Found = lookupModuleQualified(Name, Found); if (!Found) return false; @@ -287,8 +346,32 @@ ModuleMap::findOrCreateModule(StringRef Name, Module *Parent, bool IsFramework, return std::make_pair(Result, true); } +bool ModuleMap::canInferFrameworkModule(const DirectoryEntry *ParentDir, + StringRef Name, bool &IsSystem) { + // Check whether we have already looked into the parent directory + // for a module map. + llvm::DenseMap<const DirectoryEntry *, InferredDirectory>::iterator + inferred = InferredDirectories.find(ParentDir); + if (inferred == InferredDirectories.end()) + return false; + + if (!inferred->second.InferModules) + return false; + + // We're allowed to infer for this directory, but make sure it's okay + // to infer this particular module. + bool canInfer = std::find(inferred->second.ExcludedModules.begin(), + inferred->second.ExcludedModules.end(), + Name) == inferred->second.ExcludedModules.end(); + + if (canInfer && inferred->second.InferSystemModules) + IsSystem = true; + + return canInfer; +} + Module * -ModuleMap::inferFrameworkModule(StringRef ModuleName, +ModuleMap::inferFrameworkModule(StringRef ModuleName, const DirectoryEntry *FrameworkDir, bool IsSystem, Module *Parent) { @@ -297,7 +380,54 @@ ModuleMap::inferFrameworkModule(StringRef ModuleName, return Mod; FileManager &FileMgr = SourceMgr->getFileManager(); - + + // If the framework has a parent path from which we're allowed to infer + // a framework module, do so. + if (!Parent) { + bool canInfer = false; + if (llvm::sys::path::has_parent_path(FrameworkDir->getName())) { + // Figure out the parent path. + StringRef Parent = llvm::sys::path::parent_path(FrameworkDir->getName()); + if (const DirectoryEntry *ParentDir = FileMgr.getDirectory(Parent)) { + // Check whether we have already looked into the parent directory + // for a module map. + llvm::DenseMap<const DirectoryEntry *, InferredDirectory>::iterator + inferred = InferredDirectories.find(ParentDir); + if (inferred == InferredDirectories.end()) { + // We haven't looked here before. Load a module map, if there is + // one. + SmallString<128> ModMapPath = Parent; + llvm::sys::path::append(ModMapPath, "module.map"); + if (const FileEntry *ModMapFile = FileMgr.getFile(ModMapPath)) { + parseModuleMapFile(ModMapFile); + inferred = InferredDirectories.find(ParentDir); + } + + if (inferred == InferredDirectories.end()) + inferred = InferredDirectories.insert( + std::make_pair(ParentDir, InferredDirectory())).first; + } + + if (inferred->second.InferModules) { + // We're allowed to infer for this directory, but make sure it's okay + // to infer this particular module. + StringRef Name = llvm::sys::path::filename(FrameworkDir->getName()); + canInfer = std::find(inferred->second.ExcludedModules.begin(), + inferred->second.ExcludedModules.end(), + Name) == inferred->second.ExcludedModules.end(); + + if (inferred->second.InferSystemModules) + IsSystem = true; + } + } + } + + // If we're not allowed to infer a framework module, don't. + if (!canInfer) + return 0; + } + + // Look for an umbrella header. SmallString<128> UmbrellaName = StringRef(FrameworkDir->getName()); llvm::sys::path::append(UmbrellaName, "Headers"); @@ -320,7 +450,7 @@ ModuleMap::inferFrameworkModule(StringRef ModuleName, // umbrella header "umbrella-header-name" Result->Umbrella = UmbrellaHeader; - Headers[UmbrellaHeader] = Result; + Headers[UmbrellaHeader] = KnownHeader(Result, /*Excluded=*/false); UmbrellaDirs[UmbrellaHeader->getDir()] = Result; // export * @@ -343,12 +473,42 @@ ModuleMap::inferFrameworkModule(StringRef ModuleName, Dir != DirEnd && !EC; Dir.increment(EC)) { if (!StringRef(Dir->path()).endswith(".framework")) continue; - + if (const DirectoryEntry *SubframeworkDir = FileMgr.getDirectory(Dir->path())) { + // Note: as an egregious but useful hack, we use the real path here and + // check whether it is actually a subdirectory of the parent directory. + // This will not be the case if the 'subframework' is actually a symlink + // out to a top-level framework. +#ifdef LLVM_ON_UNIX + char RealSubframeworkDirName[PATH_MAX]; + if (realpath(Dir->path().c_str(), RealSubframeworkDirName)) { + StringRef SubframeworkDirName = RealSubframeworkDirName; + + bool FoundParent = false; + do { + // Get the parent directory name. + SubframeworkDirName + = llvm::sys::path::parent_path(SubframeworkDirName); + if (SubframeworkDirName.empty()) + break; + + if (FileMgr.getDirectory(SubframeworkDirName) == FrameworkDir) { + FoundParent = true; + break; + } + } while (true); + + if (!FoundParent) + continue; + } +#endif + // FIXME: Do we want to warn about subframeworks without umbrella headers? - inferFrameworkModule(llvm::sys::path::stem(Dir->path()), SubframeworkDir, - IsSystem, Result); + SmallString<32> NameBuf; + inferFrameworkModule(sanitizeFilenameAsIdentifier( + llvm::sys::path::stem(Dir->path()), NameBuf), + SubframeworkDir, IsSystem, Result); } } @@ -356,7 +516,7 @@ ModuleMap::inferFrameworkModule(StringRef ModuleName, } void ModuleMap::setUmbrellaHeader(Module *Mod, const FileEntry *UmbrellaHeader){ - Headers[UmbrellaHeader] = Mod; + Headers[UmbrellaHeader] = KnownHeader(Mod, /*Excluded=*/false); Mod->Umbrella = UmbrellaHeader; UmbrellaDirs[UmbrellaHeader->getDir()] = Mod; } @@ -366,9 +526,13 @@ void ModuleMap::setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir) { UmbrellaDirs[UmbrellaDir] = Mod; } -void ModuleMap::addHeader(Module *Mod, const FileEntry *Header) { - Mod->Headers.push_back(Header); - Headers[Header] = Mod; +void ModuleMap::addHeader(Module *Mod, const FileEntry *Header, + bool Excluded) { + if (Excluded) + Mod->ExcludedHeaders.push_back(Header); + else + Mod->Headers.push_back(Header); + Headers[Header] = KnownHeader(Mod, Excluded); } const FileEntry * @@ -388,12 +552,10 @@ void ModuleMap::dump() { M->getValue()->print(llvm::errs(), 2); llvm::errs() << "Headers:"; - for (llvm::DenseMap<const FileEntry *, Module *>::iterator - H = Headers.begin(), - HEnd = Headers.end(); + for (HeadersMap::iterator H = Headers.begin(), HEnd = Headers.end(); H != HEnd; ++H) { llvm::errs() << " \"" << H->first->getName() << "\" -> " - << H->second->getFullModuleName() << "\n"; + << H->second.getModule()->getFullModuleName() << "\n"; } } @@ -454,6 +616,7 @@ namespace clang { EndOfFile, HeaderKeyword, Identifier, + ExcludeKeyword, ExplicitKeyword, ExportKeyword, FrameworkKeyword, @@ -490,10 +653,24 @@ namespace clang { return StringRef(StringData, StringLength); } }; + + /// \brief The set of attributes that can be attached to a module. + struct Attributes { + Attributes() : IsSystem() { } + + /// \brief Whether this is a system module. + unsigned IsSystem : 1; + }; + class ModuleMapParser { Lexer &L; SourceManager &SourceMgr; + + /// \brief Default target information, used only for string literal + /// parsing. + const TargetInfo *Target; + DiagnosticsEngine &Diags; ModuleMap ⤅ @@ -505,11 +682,7 @@ namespace clang { /// \brief Whether an error occurred. bool HadError; - - /// \brief Default target information, used only for string literal - /// parsing. - OwningPtr<TargetInfo> Target; - + /// \brief Stores string data for the various string literals referenced /// during parsing. llvm::BumpPtrAllocator StringData; @@ -532,27 +705,25 @@ namespace clang { bool parseModuleId(ModuleId &Id); void parseModuleDecl(); void parseRequiresDecl(); - void parseHeaderDecl(SourceLocation UmbrellaLoc); + void parseHeaderDecl(SourceLocation UmbrellaLoc, SourceLocation ExcludeLoc); void parseUmbrellaDirDecl(SourceLocation UmbrellaLoc); void parseExportDecl(); - void parseInferredSubmoduleDecl(bool Explicit); - + void parseInferredModuleDecl(bool Framework, bool Explicit); + bool parseOptionalAttributes(Attributes &Attrs); + const DirectoryEntry *getOverriddenHeaderSearchDir(); public: explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr, + const TargetInfo *Target, DiagnosticsEngine &Diags, ModuleMap &Map, const DirectoryEntry *Directory, const DirectoryEntry *BuiltinIncludeDir) - : L(L), SourceMgr(SourceMgr), Diags(Diags), Map(Map), + : L(L), SourceMgr(SourceMgr), Target(Target), Diags(Diags), Map(Map), Directory(Directory), BuiltinIncludeDir(BuiltinIncludeDir), HadError(false), ActiveModule(0) { - TargetOptions TargetOpts; - TargetOpts.Triple = llvm::sys::getDefaultTargetTriple(); - Target.reset(TargetInfo::CreateTargetInfo(Diags, TargetOpts)); - Tok.clear(); consumeToken(); } @@ -575,6 +746,7 @@ retry: Tok.StringLength = LToken.getLength(); Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(Tok.getString()) .Case("header", MMToken::HeaderKeyword) + .Case("exclude", MMToken::ExcludeKeyword) .Case("explicit", MMToken::ExplicitKeyword) .Case("export", MMToken::ExportKeyword) .Case("framework", MMToken::FrameworkKeyword) @@ -743,13 +915,6 @@ namespace { /// 'explicit'[opt] 'framework'[opt] 'module' module-id attributes[opt] /// { module-member* } /// -/// attributes: -/// attribute attributes -/// attribute -/// -/// attribute: -/// [ identifier ] -/// /// module-member: /// requires-declaration /// header-declaration @@ -791,7 +956,7 @@ void ModuleMapParser::parseModuleDecl() { // If we have a wildcard for the module name, this is an inferred submodule. // Parse it. if (Tok.is(MMToken::Star)) - return parseInferredSubmoduleDecl(Explicit); + return parseInferredModuleDecl(Framework, Explicit); // Parse the module name. ModuleId Id; @@ -799,7 +964,7 @@ void ModuleMapParser::parseModuleDecl() { HadError = true; return; } - + if (ActiveModule) { if (Id.size() > 1) { Diags.Report(Id.front().second, diag::err_mmap_nested_submodule_id) @@ -842,47 +1007,8 @@ void ModuleMapParser::parseModuleDecl() { SourceLocation ModuleNameLoc = Id.back().second; // Parse the optional attribute list. - bool IsSystem = false; - while (Tok.is(MMToken::LSquare)) { - // Consume the '['. - SourceLocation LSquareLoc = consumeToken(); - - // Check whether we have an attribute name here. - if (!Tok.is(MMToken::Identifier)) { - Diags.Report(Tok.getLocation(), diag::err_mmap_expected_attribute); - skipUntil(MMToken::RSquare); - if (Tok.is(MMToken::RSquare)) - consumeToken(); - continue; - } - - // Decode the attribute name. - AttributeKind Attribute - = llvm::StringSwitch<AttributeKind>(Tok.getString()) - .Case("system", AT_system) - .Default(AT_unknown); - switch (Attribute) { - case AT_unknown: - Diags.Report(Tok.getLocation(), diag::warn_mmap_unknown_attribute) - << Tok.getString(); - break; - - case AT_system: - IsSystem = true; - break; - } - consumeToken(); - - // Consume the ']'. - if (!Tok.is(MMToken::RSquare)) { - Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rsquare); - Diags.Report(LSquareLoc, diag::note_mmap_lsquare_match); - skipUntil(MMToken::RSquare); - } - - if (Tok.is(MMToken::RSquare)) - consumeToken(); - } + Attributes Attrs; + parseOptionalAttributes(Attrs); // Parse the opening brace. if (!Tok.is(MMToken::LBrace)) { @@ -925,7 +1051,7 @@ void ModuleMapParser::parseModuleDecl() { ActiveModule = Map.findOrCreateModule(ModuleName, ActiveModule, Framework, Explicit).first; ActiveModule->DefinitionLoc = ModuleNameLoc; - if (IsSystem) + if (Attrs.IsSystem) ActiveModule->IsSystem = true; bool Done = false; @@ -953,14 +1079,25 @@ void ModuleMapParser::parseModuleDecl() { case MMToken::UmbrellaKeyword: { SourceLocation UmbrellaLoc = consumeToken(); if (Tok.is(MMToken::HeaderKeyword)) - parseHeaderDecl(UmbrellaLoc); + parseHeaderDecl(UmbrellaLoc, SourceLocation()); else parseUmbrellaDirDecl(UmbrellaLoc); break; } + case MMToken::ExcludeKeyword: { + SourceLocation ExcludeLoc = consumeToken(); + if (Tok.is(MMToken::HeaderKeyword)) { + parseHeaderDecl(SourceLocation(), ExcludeLoc); + } else { + Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header) + << "exclude"; + } + break; + } + case MMToken::HeaderKeyword: - parseHeaderDecl(SourceLocation()); + parseHeaderDecl(SourceLocation(), SourceLocation()); break; default: @@ -1062,12 +1199,15 @@ static bool isBuiltinHeader(StringRef FileName) { /// /// header-declaration: /// 'umbrella'[opt] 'header' string-literal -void ModuleMapParser::parseHeaderDecl(SourceLocation UmbrellaLoc) { +/// 'exclude'[opt] 'header' string-literal +void ModuleMapParser::parseHeaderDecl(SourceLocation UmbrellaLoc, + SourceLocation ExcludeLoc) { assert(Tok.is(MMToken::HeaderKeyword)); consumeToken(); bool Umbrella = UmbrellaLoc.isValid(); - + bool Exclude = ExcludeLoc.isValid(); + assert(!(Umbrella && Exclude) && "Cannot have both 'umbrella' and 'exclude'"); // Parse the header name. if (!Tok.is(MMToken::StringLiteral)) { Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header) @@ -1145,15 +1285,15 @@ void ModuleMapParser::parseHeaderDecl(SourceLocation UmbrellaLoc) { // FIXME: We shouldn't be eagerly stat'ing every file named in a module map. // Come up with a lazy way to do this. if (File) { - if (const Module *OwningModule = Map.Headers[File]) { + if (ModuleMap::KnownHeader OwningModule = Map.Headers[File]) { Diags.Report(FileNameLoc, diag::err_mmap_header_conflict) - << FileName << OwningModule->getFullModuleName(); + << FileName << OwningModule.getModule()->getFullModuleName(); HadError = true; } else if (Umbrella) { const DirectoryEntry *UmbrellaDir = File->getDir(); - if ((OwningModule = Map.UmbrellaDirs[UmbrellaDir])) { + if (Module *UmbrellaModule = Map.UmbrellaDirs[UmbrellaDir]) { Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash) - << OwningModule->getFullModuleName(); + << UmbrellaModule->getFullModuleName(); HadError = true; } else { // Record this umbrella header. @@ -1161,11 +1301,11 @@ void ModuleMapParser::parseHeaderDecl(SourceLocation UmbrellaLoc) { } } else { // Record this header. - Map.addHeader(ActiveModule, File); + Map.addHeader(ActiveModule, File, Exclude); // If there is a builtin counterpart to this file, add it now. if (BuiltinFile) - Map.addHeader(ActiveModule, BuiltinFile); + Map.addHeader(ActiveModule, BuiltinFile, Exclude); } } else { Diags.Report(FileNameLoc, diag::err_mmap_header_not_found) @@ -1274,32 +1414,52 @@ void ModuleMapParser::parseExportDecl() { ActiveModule->UnresolvedExports.push_back(Unresolved); } -void ModuleMapParser::parseInferredSubmoduleDecl(bool Explicit) { +/// \brief Parse an inferried module declaration (wildcard modules). +/// +/// module-declaration: +/// 'explicit'[opt] 'framework'[opt] 'module' * attributes[opt] +/// { inferred-module-member* } +/// +/// inferred-module-member: +/// 'export' '*' +/// 'exclude' identifier +void ModuleMapParser::parseInferredModuleDecl(bool Framework, bool Explicit) { assert(Tok.is(MMToken::Star)); SourceLocation StarLoc = consumeToken(); bool Failed = false; - + // Inferred modules must be submodules. - if (!ActiveModule) { + if (!ActiveModule && !Framework) { Diags.Report(StarLoc, diag::err_mmap_top_level_inferred_submodule); Failed = true; } - - // Inferred modules must have umbrella directories. - if (!Failed && !ActiveModule->getUmbrellaDir()) { - Diags.Report(StarLoc, diag::err_mmap_inferred_no_umbrella); - Failed = true; - } - - // Check for redefinition of an inferred module. - if (!Failed && ActiveModule->InferSubmodules) { - Diags.Report(StarLoc, diag::err_mmap_inferred_redef); - if (ActiveModule->InferredSubmoduleLoc.isValid()) - Diags.Report(ActiveModule->InferredSubmoduleLoc, - diag::note_mmap_prev_definition); - Failed = true; + + if (ActiveModule) { + // Inferred modules must have umbrella directories. + if (!Failed && !ActiveModule->getUmbrellaDir()) { + Diags.Report(StarLoc, diag::err_mmap_inferred_no_umbrella); + Failed = true; + } + + // Check for redefinition of an inferred module. + if (!Failed && ActiveModule->InferSubmodules) { + Diags.Report(StarLoc, diag::err_mmap_inferred_redef); + if (ActiveModule->InferredSubmoduleLoc.isValid()) + Diags.Report(ActiveModule->InferredSubmoduleLoc, + diag::note_mmap_prev_definition); + Failed = true; + } + + // Check for the 'framework' keyword, which is not permitted here. + if (Framework) { + Diags.Report(StarLoc, diag::err_mmap_inferred_framework_submodule); + Framework = false; + } + } else if (Explicit) { + Diags.Report(StarLoc, diag::err_mmap_explicit_inferred_framework); + Explicit = false; } - + // If there were any problems with this inferred submodule, skip its body. if (Failed) { if (Tok.is(MMToken::LBrace)) { @@ -1311,12 +1471,22 @@ void ModuleMapParser::parseInferredSubmoduleDecl(bool Explicit) { HadError = true; return; } - - // Note that we have an inferred submodule. - ActiveModule->InferSubmodules = true; - ActiveModule->InferredSubmoduleLoc = StarLoc; - ActiveModule->InferExplicitSubmodules = Explicit; - + + // Parse optional attributes. + Attributes Attrs; + parseOptionalAttributes(Attrs); + + if (ActiveModule) { + // Note that we have an inferred submodule. + ActiveModule->InferSubmodules = true; + ActiveModule->InferredSubmoduleLoc = StarLoc; + ActiveModule->InferExplicitSubmodules = Explicit; + } else { + // We'll be inferring framework modules for this directory. + Map.InferredDirectories[Directory].InferModules = true; + Map.InferredDirectories[Directory].InferSystemModules = Attrs.IsSystem; + } + // Parse the opening brace. if (!Tok.is(MMToken::LBrace)) { Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace_wildcard); @@ -1333,8 +1503,35 @@ void ModuleMapParser::parseInferredSubmoduleDecl(bool Explicit) { case MMToken::RBrace: Done = true; break; - - case MMToken::ExportKeyword: { + + case MMToken::ExcludeKeyword: { + if (ActiveModule) { + Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member) + << (ActiveModule != 0); + consumeToken(); + break; + } + + consumeToken(); + if (!Tok.is(MMToken::Identifier)) { + Diags.Report(Tok.getLocation(), diag::err_mmap_missing_exclude_name); + break; + } + + Map.InferredDirectories[Directory].ExcludedModules + .push_back(Tok.getString()); + consumeToken(); + break; + } + + case MMToken::ExportKeyword: + if (!ActiveModule) { + Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member) + << (ActiveModule != 0); + consumeToken(); + break; + } + consumeToken(); if (Tok.is(MMToken::Star)) ActiveModule->InferExportWildcard = true; @@ -1343,14 +1540,14 @@ void ModuleMapParser::parseInferredSubmoduleDecl(bool Explicit) { diag::err_mmap_expected_export_wildcard); consumeToken(); break; - } - + case MMToken::ExplicitKeyword: case MMToken::ModuleKeyword: case MMToken::HeaderKeyword: case MMToken::UmbrellaKeyword: default: - Diags.Report(Tok.getLocation(), diag::err_mmap_expected_wildcard_member); + Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member) + << (ActiveModule != 0); consumeToken(); break; } @@ -1365,6 +1562,66 @@ void ModuleMapParser::parseInferredSubmoduleDecl(bool Explicit) { } } +/// \brief Parse optional attributes. +/// +/// attributes: +/// attribute attributes +/// attribute +/// +/// attribute: +/// [ identifier ] +/// +/// \param Attrs Will be filled in with the parsed attributes. +/// +/// \returns true if an error occurred, false otherwise. +bool ModuleMapParser::parseOptionalAttributes(Attributes &Attrs) { + bool HadError = false; + + while (Tok.is(MMToken::LSquare)) { + // Consume the '['. + SourceLocation LSquareLoc = consumeToken(); + + // Check whether we have an attribute name here. + if (!Tok.is(MMToken::Identifier)) { + Diags.Report(Tok.getLocation(), diag::err_mmap_expected_attribute); + skipUntil(MMToken::RSquare); + if (Tok.is(MMToken::RSquare)) + consumeToken(); + HadError = true; + } + + // Decode the attribute name. + AttributeKind Attribute + = llvm::StringSwitch<AttributeKind>(Tok.getString()) + .Case("system", AT_system) + .Default(AT_unknown); + switch (Attribute) { + case AT_unknown: + Diags.Report(Tok.getLocation(), diag::warn_mmap_unknown_attribute) + << Tok.getString(); + break; + + case AT_system: + Attrs.IsSystem = true; + break; + } + consumeToken(); + + // Consume the ']'. + if (!Tok.is(MMToken::RSquare)) { + Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rsquare); + Diags.Report(LSquareLoc, diag::note_mmap_lsquare_match); + skipUntil(MMToken::RSquare); + HadError = true; + } + + if (Tok.is(MMToken::RSquare)) + consumeToken(); + } + + return HadError; +} + /// \brief If there is a specific header search directory due the presence /// of an umbrella directory, retrieve that directory. Otherwise, returns null. const DirectoryEntry *ModuleMapParser::getOverriddenHeaderSearchDir() { @@ -1398,6 +1655,7 @@ bool ModuleMapParser::parseModuleMapFile() { break; case MMToken::Comma: + case MMToken::ExcludeKeyword: case MMToken::ExportKeyword: case MMToken::HeaderKeyword: case MMToken::Identifier: @@ -1428,7 +1686,7 @@ bool ModuleMap::parseModuleMapFile(const FileEntry *File) { // Parse this module map file. Lexer L(ID, SourceMgr->getBuffer(ID), *SourceMgr, MMapLangOpts); Diags->getClient()->BeginSourceFile(MMapLangOpts); - ModuleMapParser Parser(L, *SourceMgr, *Diags, *this, File->getDir(), + ModuleMapParser Parser(L, *SourceMgr, Target, *Diags, *this, File->getDir(), BuiltinIncludeDir); bool Result = Parser.parseModuleMapFile(); Diags->getClient()->EndSourceFile(); diff --git a/contrib/llvm/tools/clang/lib/Lex/PPDirectives.cpp b/contrib/llvm/tools/clang/lib/Lex/PPDirectives.cpp index 74b9cbc..b7c1846 100644 --- a/contrib/llvm/tools/clang/lib/Lex/PPDirectives.cpp +++ b/contrib/llvm/tools/clang/lib/Lex/PPDirectives.cpp @@ -1296,7 +1296,7 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc, case tok::string_literal: Filename = getSpelling(FilenameTok, FilenameBuffer); End = FilenameTok.getLocation(); - CharEnd = End.getLocWithOffset(Filename.size()); + CharEnd = End.getLocWithOffset(FilenameTok.getLength()); break; case tok::less: @@ -1306,7 +1306,7 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc, if (ConcatenateIncludeName(FilenameBuffer, End)) return; // Found <eod> but no ">"? Diagnostic already emitted. Filename = FilenameBuffer.str(); - CharEnd = getLocForEndOfToken(End); + CharEnd = End.getLocWithOffset(1); break; default: Diag(FilenameTok.getLocation(), diag::err_pp_expects_filename); @@ -1314,6 +1314,8 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc, return; } + CharSourceRange FilenameRange + = CharSourceRange::getCharRange(FilenameTok.getLocation(), CharEnd); StringRef OriginalFilename = Filename; bool isAngled = GetIncludeFilenameSpelling(FilenameTok.getLocation(), Filename); @@ -1384,9 +1386,13 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc, } } - // Notify the callback object that we've seen an inclusion directive. - Callbacks->InclusionDirective(HashLoc, IncludeTok, Filename, isAngled, File, - End, SearchPath, RelativePath); + if (!SuggestedModule) { + // Notify the callback object that we've seen an inclusion directive. + Callbacks->InclusionDirective(HashLoc, IncludeTok, Filename, isAngled, + FilenameRange, File, + SearchPath, RelativePath, + /*ImportedModule=*/0); + } } if (File == 0) { @@ -1480,10 +1486,28 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc, Module *Imported = TheModuleLoader.loadModule(IncludeTok.getLocation(), Path, Visibility, /*IsIncludeDirective=*/true); + assert((Imported == 0 || Imported == SuggestedModule) && + "the imported module is different than the suggested one"); // If this header isn't part of the module we're building, we're done. - if (!BuildingImportedModule && Imported) + if (!BuildingImportedModule && Imported) { + if (Callbacks) { + Callbacks->InclusionDirective(HashLoc, IncludeTok, Filename, isAngled, + FilenameRange, File, + SearchPath, RelativePath, Imported); + } return; + } + } + + if (Callbacks && SuggestedModule) { + // We didn't notify the callback object that we've seen an inclusion + // directive before. Now that we are parsing the include normally and not + // turning it to a module import, notify the callback object. + Callbacks->InclusionDirective(HashLoc, IncludeTok, Filename, isAngled, + FilenameRange, File, + SearchPath, RelativePath, + /*ImportedModule=*/0); } // The #included file will be considered to be a system header if either it is @@ -1849,7 +1873,7 @@ void Preprocessor::HandleDefineDirective(Token &DefineTok) { MI->setDefinitionEndLoc(LastTok.getLocation()); // Finally, if this identifier already had a macro defined for it, verify that - // the macro bodies are identical and free the old definition. + // the macro bodies are identical, and issue diagnostics if they are not. if (MacroInfo *OtherMI = getMacroInfo(MacroNameTok.getIdentifierInfo())) { // It is very common for system headers to have tons of macro redefinitions // and for warnings to be disabled in system headers. If this is the case, @@ -1870,7 +1894,6 @@ void Preprocessor::HandleDefineDirective(Token &DefineTok) { } if (OtherMI->isWarnIfUnused()) WarnUnusedMacroLocs.erase(OtherMI->getDefinitionLoc()); - ReleaseMacroInfo(OtherMI); } setMacroInfo(MacroNameTok.getIdentifierInfo(), MI); @@ -1921,9 +1944,20 @@ void Preprocessor::HandleUndefDirective(Token &UndefTok) { if (MI->isWarnIfUnused()) WarnUnusedMacroLocs.erase(MI->getDefinitionLoc()); - // Free macro definition. - ReleaseMacroInfo(MI); - setMacroInfo(MacroNameTok.getIdentifierInfo(), 0); + UndefineMacro(MacroNameTok.getIdentifierInfo(), MI, + MacroNameTok.getLocation()); +} + +void Preprocessor::UndefineMacro(IdentifierInfo *II, MacroInfo *MI, + SourceLocation UndefLoc) { + MI->setUndefLoc(UndefLoc); + if (MI->isFromAST()) { + MI->setChangedAfterLoad(); + if (Listener) + Listener->UndefinedMacro(MI); + } + + clearMacroInfo(II); } diff --git a/contrib/llvm/tools/clang/lib/Lex/PPExpressions.cpp b/contrib/llvm/tools/clang/lib/Lex/PPExpressions.cpp index 7cac63e..d5a88db 100644 --- a/contrib/llvm/tools/clang/lib/Lex/PPExpressions.cpp +++ b/contrib/llvm/tools/clang/lib/Lex/PPExpressions.cpp @@ -178,7 +178,9 @@ static bool EvaluateValue(PPValue &Result, Token &PeekTok, DefinedTracker &DT, // preprocessor keywords and it wasn't macro expanded, it turns // into a simple 0, unless it is the C++ keyword "true", in which case it // turns into "1". - if (ValueLive) + if (ValueLive && + II->getTokenID() != tok::kw_true && + II->getTokenID() != tok::kw_false) PP.Diag(PeekTok, diag::warn_pp_undef_identifier) << II; Result.Val = II->getTokenID() == tok::kw_true; Result.Val.setIsUnsigned(false); // "0" is signed intmax_t 0. @@ -204,8 +206,7 @@ static bool EvaluateValue(PPValue &Result, Token &PeekTok, DefinedTracker &DT, if (NumberInvalid) return true; // a diagnostic was already reported - NumericLiteralParser Literal(Spelling.begin(), Spelling.end(), - PeekTok.getLocation(), PP); + NumericLiteralParser Literal(Spelling, PeekTok.getLocation(), PP); if (Literal.hadError) return true; // a diagnostic was already reported. @@ -219,10 +220,15 @@ static bool EvaluateValue(PPValue &Result, Token &PeekTok, DefinedTracker &DT, if (Literal.hasUDSuffix()) PP.Diag(PeekTok, diag::err_pp_invalid_udl) << /*integer*/1; - // long long is a C99 feature. - if (!PP.getLangOpts().C99 && Literal.isLongLong) - PP.Diag(PeekTok, PP.getLangOpts().CPlusPlus0x ? - diag::warn_cxx98_compat_longlong : diag::ext_longlong); + // 'long long' is a C99 or C++11 feature. + if (!PP.getLangOpts().C99 && Literal.isLongLong) { + if (PP.getLangOpts().CPlusPlus) + PP.Diag(PeekTok, + PP.getLangOpts().CPlusPlus0x ? + diag::warn_cxx98_compat_longlong : diag::ext_cxx11_longlong); + else + PP.Diag(PeekTok, diag::ext_c99_longlong); + } // Parse the integer literal into Result. if (Literal.GetIntegerValue(Result.Val)) { diff --git a/contrib/llvm/tools/clang/lib/Lex/PPLexerChange.cpp b/contrib/llvm/tools/clang/lib/Lex/PPLexerChange.cpp index e824320..d827f58 100644 --- a/contrib/llvm/tools/clang/lib/Lex/PPLexerChange.cpp +++ b/contrib/llvm/tools/clang/lib/Lex/PPLexerChange.cpp @@ -157,15 +157,15 @@ void Preprocessor::EnterSourceFileWithPTH(PTHLexer *PL, /// EnterMacro - Add a Macro to the top of the include stack and start lexing /// tokens from it instead of the current buffer. void Preprocessor::EnterMacro(Token &Tok, SourceLocation ILEnd, - MacroArgs *Args) { + MacroInfo *Macro, MacroArgs *Args) { PushIncludeMacroStack(); CurDirLookup = 0; if (NumCachedTokenLexers == 0) { - CurTokenLexer.reset(new TokenLexer(Tok, ILEnd, Args, *this)); + CurTokenLexer.reset(new TokenLexer(Tok, ILEnd, Macro, Args, *this)); } else { CurTokenLexer.reset(TokenLexerCache[--NumCachedTokenLexers]); - CurTokenLexer->Init(Tok, ILEnd, Args); + CurTokenLexer->Init(Tok, ILEnd, Macro, Args); } if (CurLexerKind != CLK_LexAfterModuleImport) CurLexerKind = CLK_TokenLexer; diff --git a/contrib/llvm/tools/clang/lib/Lex/PPMacroExpansion.cpp b/contrib/llvm/tools/clang/lib/Lex/PPMacroExpansion.cpp index ebdb644..eee4342 100644 --- a/contrib/llvm/tools/clang/lib/Lex/PPMacroExpansion.cpp +++ b/contrib/llvm/tools/clang/lib/Lex/PPMacroExpansion.cpp @@ -27,39 +27,138 @@ #include "llvm/Config/llvm-config.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/Format.h" #include <cstdio> #include <ctime> using namespace clang; -MacroInfo *Preprocessor::getInfoForMacro(IdentifierInfo *II) const { - assert(II->hasMacroDefinition() && "Identifier is not a macro!"); - - llvm::DenseMap<IdentifierInfo*, MacroInfo*>::const_iterator Pos - = Macros.find(II); - if (Pos == Macros.end()) { - // Load this macro from the external source. - getExternalSource()->LoadMacroDefinition(II); - Pos = Macros.find(II); - } +MacroInfo *Preprocessor::getMacroInfoHistory(IdentifierInfo *II) const { + assert(II->hadMacroDefinition() && "Identifier has not been not a macro!"); + + macro_iterator Pos = Macros.find(II); assert(Pos != Macros.end() && "Identifier macro info is missing!"); return Pos->second; } /// setMacroInfo - Specify a macro for this identifier. /// -void Preprocessor::setMacroInfo(IdentifierInfo *II, MacroInfo *MI, - bool LoadedFromAST) { - if (MI) { - Macros[II] = MI; - II->setHasMacroDefinition(true); - if (II->isFromAST() && !LoadedFromAST) - II->setChangedSinceDeserialization(); - } else if (II->hasMacroDefinition()) { - Macros.erase(II); - II->setHasMacroDefinition(false); - if (II->isFromAST() && !LoadedFromAST) - II->setChangedSinceDeserialization(); +void Preprocessor::setMacroInfo(IdentifierInfo *II, MacroInfo *MI) { + assert(MI && "MacroInfo should be non-zero!"); + assert(MI->getUndefLoc().isInvalid() && + "Undefined macros cannot be registered"); + + MacroInfo *&StoredMI = Macros[II]; + MI->setPreviousDefinition(StoredMI); + StoredMI = MI; + II->setHasMacroDefinition(MI->getUndefLoc().isInvalid()); + if (II->isFromAST()) + II->setChangedSinceDeserialization(); +} + +void Preprocessor::addLoadedMacroInfo(IdentifierInfo *II, MacroInfo *MI, + MacroInfo *Hint) { + assert(MI && "Missing macro?"); + assert(MI->isFromAST() && "Macro is not from an AST?"); + assert(!MI->getPreviousDefinition() && "Macro already in chain?"); + + MacroInfo *&StoredMI = Macros[II]; + + // Easy case: this is the first macro definition for this macro. + if (!StoredMI) { + StoredMI = MI; + + if (MI->isDefined()) + II->setHasMacroDefinition(true); + return; + } + + // If this macro is a definition and this identifier has been neither + // defined nor undef'd in the current translation unit, add this macro + // to the end of the chain of definitions. + if (MI->isDefined() && StoredMI->isFromAST()) { + // Simple case: if this is the first actual definition, just put it at + // th beginning. + if (!StoredMI->isDefined()) { + MI->setPreviousDefinition(StoredMI); + StoredMI = MI; + + II->setHasMacroDefinition(true); + return; + } + + // Find the end of the definition chain. + MacroInfo *Prev; + MacroInfo *PrevPrev = StoredMI; + bool Ambiguous = StoredMI->isAmbiguous(); + bool MatchedOther = false; + do { + Prev = PrevPrev; + + // If the macros are not identical, we have an ambiguity. + if (!Prev->isIdenticalTo(*MI, *this)) { + if (!Ambiguous) { + Ambiguous = true; + StoredMI->setAmbiguous(true); + } + } else { + MatchedOther = true; + } + } while ((PrevPrev = Prev->getPreviousDefinition()) && + PrevPrev->isDefined()); + + // If there are ambiguous definitions, and we didn't match any other + // definition, then mark us as ambiguous. + if (Ambiguous && !MatchedOther) + MI->setAmbiguous(true); + + // Wire this macro information into the chain. + MI->setPreviousDefinition(Prev->getPreviousDefinition()); + Prev->setPreviousDefinition(MI); + return; + } + + // The macro is not a definition; put it at the end of the list. + MacroInfo *Prev = Hint? Hint : StoredMI; + while (Prev->getPreviousDefinition()) + Prev = Prev->getPreviousDefinition(); + Prev->setPreviousDefinition(MI); +} + +void Preprocessor::makeLoadedMacroInfoVisible(IdentifierInfo *II, + MacroInfo *MI) { + assert(MI->isFromAST() && "Macro must be from the AST"); + + MacroInfo *&StoredMI = Macros[II]; + if (StoredMI == MI) { + // Easy case: this is the first macro anyway. + II->setHasMacroDefinition(MI->isDefined()); + return; } + + // Go find the macro and pull it out of the list. + // FIXME: Yes, this is O(N), and making a pile of macros visible or hidden + // would be quadratic, but it's extremely rare. + MacroInfo *Prev = StoredMI; + while (Prev->getPreviousDefinition() != MI) + Prev = Prev->getPreviousDefinition(); + Prev->setPreviousDefinition(MI->getPreviousDefinition()); + MI->setPreviousDefinition(0); + + // Add the macro back to the list. + addLoadedMacroInfo(II, MI); + + II->setHasMacroDefinition(StoredMI->isDefined()); + if (II->isFromAST()) + II->setChangedSinceDeserialization(); +} + +/// \brief Undefine a macro for this identifier. +void Preprocessor::clearMacroInfo(IdentifierInfo *II) { + assert(II->hasMacroDefinition() && "Macro is not defined!"); + assert(Macros[II]->getUndefLoc().isValid() && "Macro is still defined!"); + II->setHasMacroDefinition(false); + if (II->isFromAST()) + II->setChangedSinceDeserialization(); } /// RegisterBuiltinMacro - Register the specified identifier in the identifier @@ -100,6 +199,20 @@ void Preprocessor::RegisterBuiltinMacros() { Ident__has_include_next = RegisterBuiltinMacro(*this, "__has_include_next"); Ident__has_warning = RegisterBuiltinMacro(*this, "__has_warning"); + // Modules. + if (LangOpts.Modules) { + Ident__building_module = RegisterBuiltinMacro(*this, "__building_module"); + + // __MODULE__ + if (!LangOpts.CurrentModule.empty()) + Ident__MODULE__ = RegisterBuiltinMacro(*this, "__MODULE__"); + else + Ident__MODULE__ = 0; + } else { + Ident__building_module = 0; + Ident__MODULE__ = 0; + } + // Microsoft Extensions. if (LangOpts.MicrosoftExt) Ident__pragma = RegisterBuiltinMacro(*this, "__pragma"); @@ -263,7 +376,23 @@ bool Preprocessor::HandleMacroExpandedIdentifier(Token &Identifier, } } } - + + // If the macro definition is ambiguous, complain. + if (MI->isAmbiguous()) { + Diag(Identifier, diag::warn_pp_ambiguous_macro) + << Identifier.getIdentifierInfo(); + Diag(MI->getDefinitionLoc(), diag::note_pp_ambiguous_macro_chosen) + << Identifier.getIdentifierInfo(); + for (MacroInfo *PrevMI = MI->getPreviousDefinition(); + PrevMI && PrevMI->isDefined(); + PrevMI = PrevMI->getPreviousDefinition()) { + if (PrevMI->isAmbiguous()) { + Diag(PrevMI->getDefinitionLoc(), diag::note_pp_ambiguous_macro_other) + << Identifier.getIdentifierInfo(); + } + } + } + // If we started lexing a macro, enter the macro expansion body. // If this macro expands to no tokens, don't bother to push it onto the @@ -337,7 +466,7 @@ bool Preprocessor::HandleMacroExpandedIdentifier(Token &Identifier, } // Start expanding the macro. - EnterMacro(Identifier, ExpansionEnd, Args); + EnterMacro(Identifier, ExpansionEnd, MI, Args); // Now that the macro is at the top of the include stack, ask the // preprocessor to read the next token from it. @@ -581,27 +710,27 @@ static void ComputeDATE_TIME(SourceLocation &DATELoc, SourceLocation &TIMELoc, "Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec" }; - char TmpBuffer[32]; -#ifdef LLVM_ON_WIN32 - sprintf(TmpBuffer, "\"%s %2d %4d\"", Months[TM->tm_mon], TM->tm_mday, - TM->tm_year+1900); -#else - snprintf(TmpBuffer, sizeof(TmpBuffer), "\"%s %2d %4d\"", Months[TM->tm_mon], TM->tm_mday, - TM->tm_year+1900); -#endif - - Token TmpTok; - TmpTok.startToken(); - PP.CreateString(TmpBuffer, strlen(TmpBuffer), TmpTok); - DATELoc = TmpTok.getLocation(); - -#ifdef LLVM_ON_WIN32 - sprintf(TmpBuffer, "\"%02d:%02d:%02d\"", TM->tm_hour, TM->tm_min, TM->tm_sec); -#else - snprintf(TmpBuffer, sizeof(TmpBuffer), "\"%02d:%02d:%02d\"", TM->tm_hour, TM->tm_min, TM->tm_sec); -#endif - PP.CreateString(TmpBuffer, strlen(TmpBuffer), TmpTok); - TIMELoc = TmpTok.getLocation(); + { + SmallString<32> TmpBuffer; + llvm::raw_svector_ostream TmpStream(TmpBuffer); + TmpStream << llvm::format("\"%s %2d %4d\"", Months[TM->tm_mon], + TM->tm_mday, TM->tm_year + 1900); + Token TmpTok; + TmpTok.startToken(); + PP.CreateString(TmpStream.str(), TmpTok); + DATELoc = TmpTok.getLocation(); + } + + { + SmallString<32> TmpBuffer; + llvm::raw_svector_ostream TmpStream(TmpBuffer); + TmpStream << llvm::format("\"%02d:%02d:%02d\"", + TM->tm_hour, TM->tm_min, TM->tm_sec); + Token TmpTok; + TmpTok.startToken(); + PP.CreateString(TmpStream.str(), TmpTok); + TIMELoc = TmpTok.getLocation(); + } } @@ -616,7 +745,7 @@ static bool HasFeature(const Preprocessor &PP, const IdentifierInfo *II) { Feature = Feature.substr(2, Feature.size() - 4); return llvm::StringSwitch<bool>(Feature) - .Case("address_sanitizer", LangOpts.AddressSanitizer) + .Case("address_sanitizer", LangOpts.SanitizeAddress) .Case("attribute_analyzer_noreturn", true) .Case("attribute_availability", true) .Case("attribute_availability_with_message", true) @@ -641,8 +770,7 @@ static bool HasFeature(const Preprocessor &PP, const IdentifierInfo *II) { // Objective-C features .Case("objc_arr", LangOpts.ObjCAutoRefCount) // FIXME: REMOVE? .Case("objc_arc", LangOpts.ObjCAutoRefCount) - .Case("objc_arc_weak", LangOpts.ObjCAutoRefCount && - LangOpts.ObjCRuntimeHasWeak) + .Case("objc_arc_weak", LangOpts.ObjCARCWeak) .Case("objc_default_synthesize_properties", LangOpts.ObjC2) .Case("objc_fixed_enum", LangOpts.ObjC2) .Case("objc_instancetype", LangOpts.ObjC2) @@ -716,22 +844,12 @@ static bool HasFeature(const Preprocessor &PP, const IdentifierInfo *II) { // "struct __is_empty" parsing hack hasn't been needed in this // translation unit. If it has, __is_empty reverts to a normal // identifier and __has_feature(is_empty) evaluates false. - .Case("is_empty", - LangOpts.CPlusPlus && - PP.getIdentifierInfo("__is_empty")->getTokenID() - != tok::identifier) + .Case("is_empty", LangOpts.CPlusPlus) .Case("is_enum", LangOpts.CPlusPlus) .Case("is_final", LangOpts.CPlusPlus) .Case("is_literal", LangOpts.CPlusPlus) .Case("is_standard_layout", LangOpts.CPlusPlus) - // __is_pod is available only if the horrible - // "struct __is_pod" parsing hack hasn't been needed in this - // translation unit. If it has, __is_pod reverts to a normal - // identifier and __has_feature(is_pod) evaluates false. - .Case("is_pod", - LangOpts.CPlusPlus && - PP.getIdentifierInfo("__is_pod")->getTokenID() - != tok::identifier) + .Case("is_pod", LangOpts.CPlusPlus) .Case("is_polymorphic", LangOpts.CPlusPlus) .Case("is_trivial", LangOpts.CPlusPlus) .Case("is_trivially_assignable", LangOpts.CPlusPlus) @@ -807,22 +925,30 @@ static bool HasAttribute(const IdentifierInfo *II) { static bool EvaluateHasIncludeCommon(Token &Tok, IdentifierInfo *II, Preprocessor &PP, const DirectoryLookup *LookupFrom) { - SourceLocation LParenLoc; + // Save the location of the current token. If a '(' is later found, use + // that location. If no, use the end of this location instead. + SourceLocation LParenLoc = Tok.getLocation(); // Get '('. PP.LexNonComment(Tok); // Ensure we have a '('. if (Tok.isNot(tok::l_paren)) { - PP.Diag(Tok.getLocation(), diag::err_pp_missing_lparen) << II->getName(); - return false; - } - - // Save '(' location for possible missing ')' message. - LParenLoc = Tok.getLocation(); + // No '(', use end of last token. + LParenLoc = PP.getLocForEndOfToken(LParenLoc); + PP.Diag(LParenLoc, diag::err_pp_missing_lparen) << II->getName(); + // If the next token looks like a filename or the start of one, + // assume it is and process it as such. + if (!Tok.is(tok::angle_string_literal) && !Tok.is(tok::string_literal) && + !Tok.is(tok::less)) + return false; + } else { + // Save '(' location for possible missing ')' message. + LParenLoc = Tok.getLocation(); - // Get the file name. - PP.getCurrentLexer()->LexIncludeFilename(Tok); + // Get the file name. + PP.getCurrentLexer()->LexIncludeFilename(Tok); + } // Reserve a buffer to get the spelling. SmallString<128> FilenameBuffer; @@ -847,8 +973,11 @@ static bool EvaluateHasIncludeCommon(Token &Tok, // This could be a <foo/bar.h> file coming from a macro expansion. In this // case, glue the tokens together into FilenameBuffer and interpret those. FilenameBuffer.push_back('<'); - if (PP.ConcatenateIncludeName(FilenameBuffer, EndLoc)) + if (PP.ConcatenateIncludeName(FilenameBuffer, EndLoc)) { + // Let the caller know a <eod> was found by changing the Token kind. + Tok.setKind(tok::eod); return false; // Found <eod> but no ">"? Diagnostic already emitted. + } Filename = FilenameBuffer.str(); break; default: @@ -856,12 +985,15 @@ static bool EvaluateHasIncludeCommon(Token &Tok, return false; } + SourceLocation FilenameLoc = Tok.getLocation(); + // Get ')'. PP.LexNonComment(Tok); // Ensure we have a trailing ). if (Tok.isNot(tok::r_paren)) { - PP.Diag(Tok.getLocation(), diag::err_pp_missing_rparen) << II->getName(); + PP.Diag(PP.getLocForEndOfToken(FilenameLoc), diag::err_pp_missing_rparen) + << II->getName(); PP.Diag(LParenLoc, diag::note_matching) << "("; return false; } @@ -909,6 +1041,47 @@ static bool EvaluateHasIncludeNext(Token &Tok, return EvaluateHasIncludeCommon(Tok, II, PP, Lookup); } +/// \brief Process __building_module(identifier) expression. +/// \returns true if we are building the named module, false otherwise. +static bool EvaluateBuildingModule(Token &Tok, + IdentifierInfo *II, Preprocessor &PP) { + // Get '('. + PP.LexNonComment(Tok); + + // Ensure we have a '('. + if (Tok.isNot(tok::l_paren)) { + PP.Diag(Tok.getLocation(), diag::err_pp_missing_lparen) << II->getName(); + return false; + } + + // Save '(' location for possible missing ')' message. + SourceLocation LParenLoc = Tok.getLocation(); + + // Get the module name. + PP.LexNonComment(Tok); + + // Ensure that we have an identifier. + if (Tok.isNot(tok::identifier)) { + PP.Diag(Tok.getLocation(), diag::err_expected_id_building_module); + return false; + } + + bool Result + = Tok.getIdentifierInfo()->getName() == PP.getLangOpts().CurrentModule; + + // Get ')'. + PP.LexNonComment(Tok); + + // Ensure we have a trailing ). + if (Tok.isNot(tok::r_paren)) { + PP.Diag(Tok.getLocation(), diag::err_pp_missing_rparen) << II->getName(); + PP.Diag(LParenLoc, diag::note_matching) << "("; + return false; + } + + return Result; +} + /// ExpandBuiltinMacro - If an identifier token is read that is to be expanded /// as a builtin macro, handle it and return the next token as 'Tok'. void Preprocessor::ExpandBuiltinMacro(Token &Tok) { @@ -1093,7 +1266,8 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) { else Value = EvaluateHasIncludeNext(Tok, II, *this); OS << (int)Value; - Tok.setKind(tok::numeric_constant); + if (Tok.is(tok::r_paren)) + 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. @@ -1164,11 +1338,22 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) { OS << (int)Value; Tok.setKind(tok::numeric_constant); + } else if (II == Ident__building_module) { + // The argument to this builtin should be an identifier. The + // builtin evaluates to 1 when that identifier names the module we are + // currently building. + OS << (int)EvaluateBuildingModule(Tok, II, *this); + Tok.setKind(tok::numeric_constant); + } else if (II == Ident__MODULE__) { + // The current module as an identifier. + OS << getLangOpts().CurrentModule; + IdentifierInfo *ModuleII = getIdentifierInfo(getLangOpts().CurrentModule); + Tok.setIdentifierInfo(ModuleII); + Tok.setKind(ModuleII->getTokenID()); } else { llvm_unreachable("Unknown identifier!"); } - CreateString(OS.str().data(), OS.str().size(), Tok, - Tok.getLocation(), Tok.getLocation()); + CreateString(OS.str(), Tok, Tok.getLocation(), Tok.getLocation()); } void Preprocessor::markMacroAsUsed(MacroInfo *MI) { diff --git a/contrib/llvm/tools/clang/lib/Lex/PTHLexer.cpp b/contrib/llvm/tools/clang/lib/Lex/PTHLexer.cpp index 67738e9..b167172 100644 --- a/contrib/llvm/tools/clang/lib/Lex/PTHLexer.cpp +++ b/contrib/llvm/tools/clang/lib/Lex/PTHLexer.cpp @@ -198,12 +198,11 @@ bool PTHLexer::SkipBlock() { assert(LastHashTokPtr && "No known '#' token."); const unsigned char* HashEntryI = 0; - uint32_t Offset; uint32_t TableIdx; do { // Read the token offset from the side-table. - Offset = ReadLE32(CurPPCondPtr); + uint32_t Offset = ReadLE32(CurPPCondPtr); // Read the target table index from the side-table. TableIdx = ReadLE32(CurPPCondPtr); @@ -223,13 +222,11 @@ bool PTHLexer::SkipBlock() { PPCond + TableIdx*(sizeof(uint32_t)*2); assert(NextPPCondPtr >= CurPPCondPtr); // Read where we should jump to. - uint32_t TmpOffset = ReadLE32(NextPPCondPtr); - const unsigned char* HashEntryJ = TokBuf + TmpOffset; + const unsigned char* HashEntryJ = TokBuf + ReadLE32(NextPPCondPtr); if (HashEntryJ <= LastHashTokPtr) { // Jump directly to the next entry in the side table. HashEntryI = HashEntryJ; - Offset = TmpOffset; TableIdx = ReadLE32(NextPPCondPtr); CurPPCondPtr = NextPPCondPtr; } @@ -448,8 +445,8 @@ PTHManager *PTHManager::Create(const std::string &file, // Get the buffer ranges and check if there are at least three 32-bit // words at the end of the file. - const unsigned char *BufBeg = (unsigned char*)File->getBufferStart(); - const unsigned char *BufEnd = (unsigned char*)File->getBufferEnd(); + const unsigned char *BufBeg = (const unsigned char*)File->getBufferStart(); + const unsigned char *BufEnd = (const unsigned char*)File->getBufferEnd(); // Check the prologue of the file. if ((BufEnd - BufBeg) < (signed)(sizeof("cfe-pth") + 4 + 4) || diff --git a/contrib/llvm/tools/clang/lib/Lex/Pragma.cpp b/contrib/llvm/tools/clang/lib/Lex/Pragma.cpp index c9cc4ad..e7e6c37 100644 --- a/contrib/llvm/tools/clang/lib/Lex/Pragma.cpp +++ b/contrib/llvm/tools/clang/lib/Lex/Pragma.cpp @@ -43,7 +43,6 @@ void EmptyPragmaHandler::HandlePragma(Preprocessor &PP, // PragmaNamespace Implementation. //===----------------------------------------------------------------------===// - PragmaNamespace::~PragmaNamespace() { for (llvm::StringMap<PragmaHandler*>::iterator I = Handlers.begin(), E = Handlers.end(); I != E; ++I) @@ -251,7 +250,7 @@ void Preprocessor::Handle_Pragma(Token &Tok) { // where we can lex it. Token TmpTok; TmpTok.startToken(); - CreateString(&StrVal[0], StrVal.size(), TmpTok); + CreateString(StrVal, TmpTok); SourceLocation TokLoc = TmpTok.getLocation(); // Make and enter a lexer object so that we lex and expand the tokens just @@ -683,7 +682,7 @@ IdentifierInfo *Preprocessor::ParsePragmaPushOrPopMacro(Token &Tok) { Token MacroTok; MacroTok.startToken(); MacroTok.setKind(tok::raw_identifier); - CreateString(&StrVal[1], StrVal.size() - 2, MacroTok); + CreateString(StringRef(&StrVal[1], StrVal.size() - 2), MacroTok); // Get the IdentifierInfo of MacroToPushTok. return LookUpIdentifierInfo(MacroTok); @@ -733,19 +732,22 @@ void Preprocessor::HandlePragmaPopMacro(Token &PopMacroTok) { llvm::DenseMap<IdentifierInfo*, std::vector<MacroInfo*> >::iterator iter = PragmaPushMacroInfo.find(IdentInfo); if (iter != PragmaPushMacroInfo.end()) { - // Release the MacroInfo currently associated with IdentInfo. - MacroInfo *CurrentMI = getMacroInfo(IdentInfo); - if (CurrentMI) { + // Forget the MacroInfo currently associated with IdentInfo. + if (MacroInfo *CurrentMI = getMacroInfo(IdentInfo)) { if (CurrentMI->isWarnIfUnused()) WarnUnusedMacroLocs.erase(CurrentMI->getDefinitionLoc()); - ReleaseMacroInfo(CurrentMI); + UndefineMacro(IdentInfo, CurrentMI, MessageLoc); } // Get the MacroInfo we want to reinstall. MacroInfo *MacroToReInstall = iter->second.back(); - // Reinstall the previously pushed macro. - setMacroInfo(IdentInfo, MacroToReInstall); + if (MacroToReInstall) { + // Reinstall the previously pushed macro. + setMacroInfo(IdentInfo, MacroToReInstall); + } else if (IdentInfo->hasMacroDefinition()) { + clearMacroInfo(IdentInfo); + } // Pop PragmaPushMacroInfo stack. iter->second.pop_back(); @@ -1009,7 +1011,7 @@ struct PragmaDebugHandler : public PragmaHandler { if (II->isStr("assert")) { llvm_unreachable("This is an assertion!"); } else if (II->isStr("crash")) { - *(volatile int*) 0x11 = 0; + LLVM_BUILTIN_TRAP; } else if (II->isStr("parser_crash")) { Token Crasher; Crasher.setKind(tok::annot_pragma_parser_crash); diff --git a/contrib/llvm/tools/clang/lib/Lex/PreprocessingRecord.cpp b/contrib/llvm/tools/clang/lib/Lex/PreprocessingRecord.cpp index dfdeba3..01f3665e 100644 --- a/contrib/llvm/tools/clang/lib/Lex/PreprocessingRecord.cpp +++ b/contrib/llvm/tools/clang/lib/Lex/PreprocessingRecord.cpp @@ -25,10 +25,11 @@ ExternalPreprocessingRecordSource::~ExternalPreprocessingRecordSource() { } InclusionDirective::InclusionDirective(PreprocessingRecord &PPRec, InclusionKind Kind, StringRef FileName, - bool InQuotes, const FileEntry *File, + bool InQuotes, bool ImportedModule, + const FileEntry *File, SourceRange Range) : PreprocessingDirective(InclusionDirectiveKind, Range), - InQuotes(InQuotes), Kind(Kind), File(File) + InQuotes(InQuotes), Kind(Kind), ImportedModule(ImportedModule), File(File) { char *Memory = (char*)PPRec.Allocate(FileName.size() + 1, llvm::alignOf<char>()); @@ -59,8 +60,7 @@ PreprocessingRecord::getPreprocessedEntitiesInRange(SourceRange Range) { iterator(this, CachedRangeQuery.Result.second)); } - std::pair<PPEntityID, PPEntityID> - Res = getPreprocessedEntitiesInRangeSlow(Range); + std::pair<int, int> Res = getPreprocessedEntitiesInRangeSlow(Range); CachedRangeQuery.Range = Range; CachedRangeQuery.Result = Res; @@ -95,12 +95,12 @@ bool PreprocessingRecord::isEntityInFileID(iterator PPEI, FileID FID) { if (FID.isInvalid()) return false; - PPEntityID PPID = PPEI.Position; - if (PPID < 0) { - assert(unsigned(-PPID-1) < LoadedPreprocessedEntities.size() && + int Pos = PPEI.Position; + if (Pos < 0) { + assert(unsigned(-Pos-1) < LoadedPreprocessedEntities.size() && "Out-of bounds loaded preprocessed entity"); assert(ExternalSource && "No external source to load from"); - unsigned LoadedIndex = LoadedPreprocessedEntities.size()+PPID; + unsigned LoadedIndex = LoadedPreprocessedEntities.size()+Pos; if (PreprocessedEntity *PPE = LoadedPreprocessedEntities[LoadedIndex]) return isPreprocessedEntityIfInFileID(PPE, FID, SourceMgr); @@ -118,15 +118,15 @@ bool PreprocessingRecord::isEntityInFileID(iterator PPEI, FileID FID) { FID, SourceMgr); } - assert(unsigned(PPID) < PreprocessedEntities.size() && + assert(unsigned(Pos) < PreprocessedEntities.size() && "Out-of bounds local preprocessed entity"); - return isPreprocessedEntityIfInFileID(PreprocessedEntities[PPID], + return isPreprocessedEntityIfInFileID(PreprocessedEntities[Pos], FID, SourceMgr); } /// \brief Returns a pair of [Begin, End) iterators of preprocessed entities /// that source range \arg R encompasses. -std::pair<PreprocessingRecord::PPEntityID, PreprocessingRecord::PPEntityID> +std::pair<int, int> PreprocessingRecord::getPreprocessedEntitiesInRangeSlow(SourceRange Range) { assert(Range.isValid()); assert(!SourceMgr.isBeforeInTranslationUnit(Range.getEnd(),Range.getBegin())); @@ -319,14 +319,19 @@ void PreprocessingRecord::RegisterMacroDefinition(MacroInfo *Macro, /// \brief Retrieve the preprocessed entity at the given ID. PreprocessedEntity *PreprocessingRecord::getPreprocessedEntity(PPEntityID PPID){ - if (PPID < 0) { - assert(unsigned(-PPID-1) < LoadedPreprocessedEntities.size() && + if (PPID.ID < 0) { + unsigned Index = -PPID.ID - 1; + assert(Index < LoadedPreprocessedEntities.size() && "Out-of bounds loaded preprocessed entity"); - return getLoadedPreprocessedEntity(LoadedPreprocessedEntities.size()+PPID); + return getLoadedPreprocessedEntity(Index); } - assert(unsigned(PPID) < PreprocessedEntities.size() && + + if (PPID.ID == 0) + return 0; + unsigned Index = PPID.ID - 1; + assert(Index < PreprocessedEntities.size() && "Out-of bounds local preprocessed entity"); - return PreprocessedEntities[PPID]; + return PreprocessedEntities[Index]; } /// \brief Retrieve the loaded preprocessed entity at the given index. @@ -389,10 +394,11 @@ void PreprocessingRecord::InclusionDirective( const clang::Token &IncludeTok, StringRef FileName, bool IsAngled, + CharSourceRange FilenameRange, const FileEntry *File, - clang::SourceLocation EndLoc, StringRef SearchPath, - StringRef RelativePath) { + StringRef RelativePath, + const Module *Imported) { InclusionDirective::InclusionKind Kind = InclusionDirective::Include; switch (IncludeTok.getIdentifierInfo()->getPPKeywordID()) { @@ -415,9 +421,19 @@ void PreprocessingRecord::InclusionDirective( default: llvm_unreachable("Unknown include directive kind"); } - + + SourceLocation EndLoc; + if (!IsAngled) { + EndLoc = FilenameRange.getBegin(); + } else { + EndLoc = FilenameRange.getEnd(); + if (FilenameRange.isCharRange()) + EndLoc = EndLoc.getLocWithOffset(-1); // the InclusionDirective expects + // a token range. + } clang::InclusionDirective *ID - = new (*this) clang::InclusionDirective(*this, Kind, FileName, !IsAngled, + = new (*this) clang::InclusionDirective(*this, Kind, FileName, !IsAngled, + (bool)Imported, File, SourceRange(HashLoc, EndLoc)); addPreprocessedEntity(ID); } diff --git a/contrib/llvm/tools/clang/lib/Lex/Preprocessor.cpp b/contrib/llvm/tools/clang/lib/Lex/Preprocessor.cpp index 614530c..3b070ce 100644 --- a/contrib/llvm/tools/clang/lib/Lex/Preprocessor.cpp +++ b/contrib/llvm/tools/clang/lib/Lex/Preprocessor.cpp @@ -26,6 +26,7 @@ //===----------------------------------------------------------------------===// #include "clang/Lex/Preprocessor.h" +#include "clang/Lex/PreprocessorOptions.h" #include "MacroArgs.h" #include "clang/Lex/ExternalPreprocessorSource.h" #include "clang/Lex/HeaderSearch.h" @@ -49,21 +50,25 @@ using namespace clang; //===----------------------------------------------------------------------===// ExternalPreprocessorSource::~ExternalPreprocessorSource() { } -Preprocessor::Preprocessor(DiagnosticsEngine &diags, LangOptions &opts, +PPMutationListener::~PPMutationListener() { } + +Preprocessor::Preprocessor(llvm::IntrusiveRefCntPtr<PreprocessorOptions> PPOpts, + DiagnosticsEngine &diags, LangOptions &opts, const TargetInfo *target, SourceManager &SM, HeaderSearch &Headers, ModuleLoader &TheModuleLoader, IdentifierInfoLookup* IILookup, bool OwnsHeaders, bool DelayInitialization, bool IncrProcessing) - : Diags(&diags), LangOpts(opts), Target(target),FileMgr(Headers.getFileMgr()), + : PPOpts(PPOpts), Diags(&diags), LangOpts(opts), Target(target), + FileMgr(Headers.getFileMgr()), SourceMgr(SM), HeaderInfo(Headers), TheModuleLoader(TheModuleLoader), ExternalSource(0), Identifiers(opts, IILookup), IncrementalProcessing(IncrProcessing), CodeComplete(0), CodeCompletionFile(0), CodeCompletionOffset(0), CodeCompletionReached(0), SkipMainFilePreamble(0, true), CurPPLexer(0), - CurDirLookup(0), CurLexerKind(CLK_Lexer), Callbacks(0), MacroArgCache(0), - Record(0), MIChainHead(0), MICache(0) + CurDirLookup(0), CurLexerKind(CLK_Lexer), Callbacks(0), Listener(0), + MacroArgCache(0), Record(0), MIChainHead(0), MICache(0) { OwnsHeaderSearch = OwnsHeaders; @@ -285,6 +290,39 @@ Preprocessor::macro_end(bool IncludeExternalMacros) const { return Macros.end(); } +/// \brief Compares macro tokens with a specified token value sequence. +static bool MacroDefinitionEquals(const MacroInfo *MI, + llvm::ArrayRef<TokenValue> Tokens) { + return Tokens.size() == MI->getNumTokens() && + std::equal(Tokens.begin(), Tokens.end(), MI->tokens_begin()); +} + +StringRef Preprocessor::getLastMacroWithSpelling( + SourceLocation Loc, + ArrayRef<TokenValue> Tokens) const { + SourceLocation BestLocation; + StringRef BestSpelling; + for (Preprocessor::macro_iterator I = macro_begin(), E = macro_end(); + I != E; ++I) { + if (!I->second->isObjectLike()) + continue; + const MacroInfo *MI = I->second->findDefinitionAtLoc(Loc, SourceMgr); + if (!MI) + continue; + if (!MacroDefinitionEquals(MI, Tokens)) + continue; + SourceLocation Location = I->second->getDefinitionLoc(); + // Choose the macro defined latest. + if (BestLocation.isInvalid() || + (Location.isValid() && + SourceMgr.isBeforeInTranslationUnit(BestLocation, Location))) { + BestLocation = Location; + BestSpelling = I->first->getName(); + } + } + return BestSpelling; +} + void Preprocessor::recomputeCurLexerKind() { if (CurLexer) CurLexerKind = CLK_Lexer; @@ -378,17 +416,17 @@ StringRef Preprocessor::getSpelling(const Token &Tok, /// CreateString - Plop the specified string into a scratch buffer and return a /// location for it. If specified, the source location provides a source /// location for the token. -void Preprocessor::CreateString(const char *Buf, unsigned Len, Token &Tok, +void Preprocessor::CreateString(StringRef Str, Token &Tok, SourceLocation ExpansionLocStart, SourceLocation ExpansionLocEnd) { - Tok.setLength(Len); + Tok.setLength(Str.size()); const char *DestPtr; - SourceLocation Loc = ScratchBuf->getToken(Buf, Len, DestPtr); + SourceLocation Loc = ScratchBuf->getToken(Str.data(), Str.size(), DestPtr); if (ExpansionLocStart.isValid()) Loc = SourceMgr.createExpansionLoc(Loc, ExpansionLocStart, - ExpansionLocEnd, Len); + ExpansionLocEnd, Str.size()); Tok.setLocation(Loc); // If this is a raw identifier or a literal token, set the pointer data. @@ -641,10 +679,14 @@ void Preprocessor::LexAfterModuleImport(Token &Result) { } // If we have a non-empty module path, load the named module. - if (!ModuleImportPath.empty()) - (void)TheModuleLoader.loadModule(ModuleImportLoc, ModuleImportPath, - Module::MacrosVisible, - /*IsIncludeDirective=*/false); + if (!ModuleImportPath.empty()) { + Module *Imported = TheModuleLoader.loadModule(ModuleImportLoc, + ModuleImportPath, + Module::MacrosVisible, + /*IsIncludeDirective=*/false); + if (Callbacks) + Callbacks->moduleImport(ModuleImportLoc, ModuleImportPath, Imported); + } } void Preprocessor::addCommentHandler(CommentHandler *Handler) { diff --git a/contrib/llvm/tools/clang/lib/Lex/TokenLexer.cpp b/contrib/llvm/tools/clang/lib/Lex/TokenLexer.cpp index ade40da..59b7478 100644 --- a/contrib/llvm/tools/clang/lib/Lex/TokenLexer.cpp +++ b/contrib/llvm/tools/clang/lib/Lex/TokenLexer.cpp @@ -23,12 +23,13 @@ using namespace clang; /// Create a TokenLexer for the specified macro with the specified actual /// arguments. Note that this ctor takes ownership of the ActualArgs pointer. -void TokenLexer::Init(Token &Tok, SourceLocation ELEnd, MacroArgs *Actuals) { +void TokenLexer::Init(Token &Tok, SourceLocation ELEnd, MacroInfo *MI, + MacroArgs *Actuals) { // If the client is reusing a TokenLexer, make sure to free any memory // associated with it. destroy(); - Macro = PP.getMacroInfo(Tok.getIdentifierInfo()); + Macro = MI; ActualArgs = Actuals; CurToken = 0; @@ -118,6 +119,55 @@ void TokenLexer::destroy() { if (ActualArgs) ActualArgs->destroy(PP); } +/// Remove comma ahead of __VA_ARGS__, if present, according to compiler dialect +/// settings. Returns true if the comma is removed. +static bool MaybeRemoveCommaBeforeVaArgs(SmallVector<Token, 128> &ResultToks, + bool &NextTokGetsSpace, + bool HasPasteOperator, + MacroInfo *Macro, unsigned MacroArgNo, + Preprocessor &PP) { + // Is the macro argument __VA_ARGS__? + if (!Macro->isVariadic() || MacroArgNo != Macro->getNumArgs()-1) + return false; + + // In Microsoft-compatibility mode, a comma is removed in the expansion + // of " ... , __VA_ARGS__ " if __VA_ARGS__ is empty. This extension is + // not supported by gcc. + if (!HasPasteOperator && !PP.getLangOpts().MicrosoftMode) + return false; + + // GCC removes the comma in the expansion of " ... , ## __VA_ARGS__ " if + // __VA_ARGS__ is empty, but not in strict C99 mode where there are no + // named arguments, where it remains. In all other modes, including C99 + // with GNU extensions, it is removed regardless of named arguments. + // Microsoft also appears to support this extension, unofficially. + if (PP.getLangOpts().C99 && !PP.getLangOpts().GNUMode + && Macro->getNumArgs() < 2) + return false; + + // Is a comma available to be removed? + if (ResultToks.empty() || !ResultToks.back().is(tok::comma)) + return false; + + // Issue an extension diagnostic for the paste operator. + if (HasPasteOperator) + PP.Diag(ResultToks.back().getLocation(), diag::ext_paste_comma); + + // Remove the comma. + ResultToks.pop_back(); + + // If the comma was right after another paste (e.g. "X##,##__VA_ARGS__"), + // then removal of the comma should produce a placemarker token (in C99 + // terms) which we model by popping off the previous ##, giving us a plain + // "X" when __VA_ARGS__ is empty. + if (!ResultToks.empty() && ResultToks.back().is(tok::hashhash)) + ResultToks.pop_back(); + + // Never add a space, even if the comma, ##, or arg had a space. + NextTokGetsSpace = false; + return true; +} + /// Expand the arguments of a function-like macro so that we can quickly /// return preexpanded tokens from Tokens. void TokenLexer::ExpandFunctionArguments() { @@ -198,6 +248,14 @@ void TokenLexer::ExpandFunctionArguments() { !ResultToks.empty() && ResultToks.back().is(tok::hashhash); bool PasteAfter = i+1 != e && Tokens[i+1].is(tok::hashhash); + // In Microsoft mode, remove the comma before __VA_ARGS__ to ensure there + // are no trailing commas if __VA_ARGS__ is empty. + if (!PasteBefore && ActualArgs->isVarargsElidedUse() && + MaybeRemoveCommaBeforeVaArgs(ResultToks, NextTokGetsSpace, + /*HasPasteOperator=*/false, + Macro, ArgNo, PP)) + continue; + // If it is not the LHS/RHS of a ## operator, we must pre-expand the // argument and substitute the expanded tokens into the result. This is // C99 6.10.3.1p1. @@ -320,23 +378,13 @@ void TokenLexer::ExpandFunctionArguments() { // If this is the __VA_ARGS__ token, and if the argument wasn't provided, // and if the macro had at least one real argument, and if the token before - // the ## was a comma, remove the comma. - if ((unsigned)ArgNo == Macro->getNumArgs()-1 && // is __VA_ARGS__ - ActualArgs->isVarargsElidedUse() && // Argument elided. - !ResultToks.empty() && ResultToks.back().is(tok::comma)) { - // Never add a space, even if the comma, ##, or arg had a space. - NextTokGetsSpace = false; - // Remove the paste operator, report use of the extension. - PP.Diag(ResultToks.back().getLocation(), diag::ext_paste_comma); - ResultToks.pop_back(); - - // If the comma was right after another paste (e.g. "X##,##__VA_ARGS__"), - // then removal of the comma should produce a placemarker token (in C99 - // terms) which we model by popping off the previous ##, giving us a plain - // "X" when __VA_ARGS__ is empty. - if (!ResultToks.empty() && ResultToks.back().is(tok::hashhash)) - ResultToks.pop_back(); - } + // the ## was a comma, remove the comma. This is a GCC extension which is + // disabled when using -std=c99. + if (ActualArgs->isVarargsElidedUse()) + MaybeRemoveCommaBeforeVaArgs(ResultToks, NextTokGetsSpace, + /*HasPasteOperator=*/true, + Macro, ArgNo, PP); + continue; } @@ -494,7 +542,7 @@ bool TokenLexer::PasteTokens(Token &Tok) { // Claim that the tmp token is a string_literal so that we can get the // character pointer back from CreateString in getLiteralData(). ResultTokTmp.setKind(tok::string_literal); - PP.CreateString(&Buffer[0], Buffer.size(), ResultTokTmp); + PP.CreateString(Buffer, ResultTokTmp); SourceLocation ResultTokLoc = ResultTokTmp.getLocation(); ResultTokStrPtr = ResultTokTmp.getLiteralData(); |