diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Lex')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Lex/HeaderSearch.cpp | 47 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Lex/Lexer.cpp | 199 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Lex/LiteralSupport.cpp | 20 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Lex/MacroArgs.cpp | 26 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Lex/MacroInfo.cpp | 23 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Lex/ModuleMap.cpp | 582 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Lex/PPCaching.cpp | 30 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Lex/PPDirectives.cpp | 395 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Lex/PPExpressions.cpp | 84 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Lex/PPLexerChange.cpp | 181 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Lex/PPMacroExpansion.cpp | 18 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Lex/Pragma.cpp | 306 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Lex/PreprocessingRecord.cpp | 3 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Lex/Preprocessor.cpp | 48 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Lex/ScratchBuffer.cpp | 8 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Lex/TokenLexer.cpp | 42 |
16 files changed, 1365 insertions, 647 deletions
diff --git a/contrib/llvm/tools/clang/lib/Lex/HeaderSearch.cpp b/contrib/llvm/tools/clang/lib/Lex/HeaderSearch.cpp index c667f4b..1ebcc0a 100644 --- a/contrib/llvm/tools/clang/lib/Lex/HeaderSearch.cpp +++ b/contrib/llvm/tools/clang/lib/Lex/HeaderSearch.cpp @@ -172,8 +172,10 @@ std::string HeaderSearch::getModuleFileName(StringRef ModuleName, // // To avoid false-negatives, we form as canonical a path as we can, and map // to lower-case in case we're on a case-insensitive file system. - auto *Dir = - FileMgr.getDirectory(llvm::sys::path::parent_path(ModuleMapPath)); + std::string Parent = llvm::sys::path::parent_path(ModuleMapPath); + if (Parent.empty()) + Parent = "."; + auto *Dir = FileMgr.getDirectory(Parent); if (!Dir) return std::string(); auto DirName = FileMgr.getCanonicalName(Dir); @@ -622,7 +624,10 @@ const FileEntry *HeaderSearch::LookupFile( ArrayRef<std::pair<const FileEntry *, const DirectoryEntry *>> Includers, SmallVectorImpl<char> *SearchPath, SmallVectorImpl<char> *RelativePath, Module *RequestingModule, ModuleMap::KnownHeader *SuggestedModule, - bool SkipCache, bool BuildSystemModule) { + bool *IsMapped, bool SkipCache, bool BuildSystemModule) { + if (IsMapped) + *IsMapped = false; + if (SuggestedModule) *SuggestedModule = ModuleMap::KnownHeader(); @@ -752,8 +757,11 @@ const FileEntry *HeaderSearch::LookupFile( if (!SkipCache && CacheLookup.StartIdx == i+1) { // Skip querying potentially lots of directories for this lookup. i = CacheLookup.HitIdx; - if (CacheLookup.MappedName) + if (CacheLookup.MappedName) { Filename = CacheLookup.MappedName; + if (IsMapped) + *IsMapped = true; + } } else { // Otherwise, this is the first query, or the previous query didn't match // our search start. We will fill in our found location below, so prime the @@ -774,6 +782,8 @@ const FileEntry *HeaderSearch::LookupFile( if (HasBeenMapped) { CacheLookup.MappedName = copyString(Filename, LookupFileCache.getAllocator()); + if (IsMapped) + *IsMapped = true; } if (!FE) continue; @@ -837,7 +847,7 @@ const FileEntry *HeaderSearch::LookupFile( const FileEntry *FE = LookupFile(ScratchFilename, IncludeLoc, /*isAngled=*/true, FromDir, CurDir, Includers.front(), SearchPath, RelativePath, - RequestingModule, SuggestedModule); + RequestingModule, SuggestedModule, IsMapped); if (checkMSVCHeaderSearch(Diags, MSFE, FE, IncludeLoc)) { if (SuggestedModule) @@ -1104,6 +1114,8 @@ bool HeaderSearch::ShouldEnterIncludeFile(Preprocessor &PP, auto TryEnterImported = [&](void) -> bool { if (!ModulesEnabled) return false; + // Ensure FileInfo bits are up to date. + ModMap.resolveHeaderDirectives(File); // Modules with builtins are special; multiple modules use builtins as // modular headers, example: // @@ -1315,14 +1327,28 @@ static const FileEntry *getPrivateModuleMap(const FileEntry *File, return FileMgr.getFile(PrivateFilename); } -bool HeaderSearch::loadModuleMapFile(const FileEntry *File, bool IsSystem) { +bool HeaderSearch::loadModuleMapFile(const FileEntry *File, bool IsSystem, + FileID ID, unsigned *Offset, + StringRef OriginalModuleMapFile) { // Find the directory for the module. For frameworks, that may require going // up from the 'Modules' directory. const DirectoryEntry *Dir = nullptr; if (getHeaderSearchOpts().ModuleMapFileHomeIsCwd) Dir = FileMgr.getDirectory("."); else { - Dir = File->getDir(); + if (!OriginalModuleMapFile.empty()) { + // We're building a preprocessed module map. Find or invent the directory + // that it originally occupied. + Dir = FileMgr.getDirectory( + llvm::sys::path::parent_path(OriginalModuleMapFile)); + if (!Dir) { + auto *FakeFile = FileMgr.getVirtualFile(OriginalModuleMapFile, 0, 0); + Dir = FakeFile->getDir(); + } + } else { + Dir = File->getDir(); + } + StringRef DirName(Dir->getName()); if (llvm::sys::path::filename(DirName) == "Modules") { DirName = llvm::sys::path::parent_path(DirName); @@ -1334,7 +1360,7 @@ bool HeaderSearch::loadModuleMapFile(const FileEntry *File, bool IsSystem) { } } - switch (loadModuleMapFileImpl(File, IsSystem, Dir)) { + switch (loadModuleMapFileImpl(File, IsSystem, Dir, ID, Offset)) { case LMM_AlreadyLoaded: case LMM_NewlyLoaded: return false; @@ -1347,7 +1373,8 @@ bool HeaderSearch::loadModuleMapFile(const FileEntry *File, bool IsSystem) { HeaderSearch::LoadModuleMapResult HeaderSearch::loadModuleMapFileImpl(const FileEntry *File, bool IsSystem, - const DirectoryEntry *Dir) { + const DirectoryEntry *Dir, FileID ID, + unsigned *Offset) { assert(File && "expected FileEntry"); // Check whether we've already loaded this module map, and mark it as being @@ -1356,7 +1383,7 @@ HeaderSearch::loadModuleMapFileImpl(const FileEntry *File, bool IsSystem, if (!AddResult.second) return AddResult.first->second ? LMM_AlreadyLoaded : LMM_InvalidModuleMap; - if (ModMap.parseModuleMapFile(File, IsSystem, Dir)) { + if (ModMap.parseModuleMapFile(File, IsSystem, Dir, ID, Offset)) { LoadedModuleMaps[File] = false; return LMM_InvalidModuleMap; } diff --git a/contrib/llvm/tools/clang/lib/Lex/Lexer.cpp b/contrib/llvm/tools/clang/lib/Lex/Lexer.cpp index 6025a66..61bcef8 100644 --- a/contrib/llvm/tools/clang/lib/Lex/Lexer.cpp +++ b/contrib/llvm/tools/clang/lib/Lex/Lexer.cpp @@ -19,6 +19,7 @@ #include "clang/Lex/LexDiagnostic.h" #include "clang/Lex/LiteralSupport.h" #include "clang/Lex/Preprocessor.h" +#include "clang/Lex/PreprocessorOptions.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/Support/Compiler.h" @@ -43,6 +44,8 @@ using namespace clang; /// isObjCAtKeyword - Return true if we have an ObjC keyword identifier. bool Token::isObjCAtKeyword(tok::ObjCKeywordKind objcKey) const { + if (isAnnotation()) + return false; if (IdentifierInfo *II = getIdentifierInfo()) return II->getObjCKeywordID() == objcKey; return false; @@ -50,6 +53,8 @@ bool Token::isObjCAtKeyword(tok::ObjCKeywordKind objcKey) const { /// getObjCKeywordID - Return the ObjC keyword kind. tok::ObjCKeywordKind Token::getObjCKeywordID() const { + if (isAnnotation()) + return tok::objc_not_keyword; IdentifierInfo *specId = getIdentifierInfo(); return specId ? specId->getObjCKeywordID() : tok::objc_not_keyword; } @@ -452,6 +457,29 @@ bool Lexer::getRawToken(SourceLocation Loc, Token &Result, return false; } +/// Returns the pointer that points to the beginning of line that contains +/// the given offset, or null if the offset if invalid. +static const char *findBeginningOfLine(StringRef Buffer, unsigned Offset) { + const char *BufStart = Buffer.data(); + if (Offset >= Buffer.size()) + return nullptr; + const char *StrData = BufStart + Offset; + + if (StrData[0] == '\n' || StrData[0] == '\r') + return StrData; + + const char *LexStart = StrData; + while (LexStart != BufStart) { + if (LexStart[0] == '\n' || LexStart[0] == '\r') { + ++LexStart; + break; + } + + --LexStart; + } + return LexStart; +} + static SourceLocation getBeginningOfFileToken(SourceLocation Loc, const SourceManager &SM, const LangOptions &LangOpts) { @@ -467,27 +495,15 @@ static SourceLocation getBeginningOfFileToken(SourceLocation Loc, // Back up from the current location until we hit the beginning of a line // (or the buffer). We'll relex from that point. - const char *BufStart = Buffer.data(); - if (LocInfo.second >= Buffer.size()) - return Loc; - - const char *StrData = BufStart+LocInfo.second; - if (StrData[0] == '\n' || StrData[0] == '\r') + const char *StrData = Buffer.data() + LocInfo.second; + const char *LexStart = findBeginningOfLine(Buffer, LocInfo.second); + if (!LexStart || LexStart == StrData) return Loc; - - const char *LexStart = StrData; - while (LexStart != BufStart) { - if (LexStart[0] == '\n' || LexStart[0] == '\r') { - ++LexStart; - break; - } - - --LexStart; - } // Create a lexer starting at the beginning of this token. SourceLocation LexerStartLoc = Loc.getLocWithOffset(-LocInfo.second); - Lexer TheLexer(LexerStartLoc, LangOpts, BufStart, LexStart, Buffer.end()); + Lexer TheLexer(LexerStartLoc, LangOpts, Buffer.data(), LexStart, + Buffer.end()); TheLexer.SetCommentRetentionState(true); // Lex tokens until we find the token that contains the source location. @@ -535,8 +551,6 @@ namespace { enum PreambleDirectiveKind { PDK_Skipped, - PDK_StartIf, - PDK_EndIf, PDK_Unknown }; @@ -559,8 +573,6 @@ std::pair<unsigned, bool> Lexer::ComputePreamble(StringRef Buffer, bool InPreprocessorDirective = false; Token TheTok; - Token IfStartTok; - unsigned IfCount = 0; SourceLocation ActiveCommentLoc; unsigned MaxLineOffset = 0; @@ -643,33 +655,18 @@ std::pair<unsigned, bool> Lexer::ComputePreamble(StringRef Buffer, .Case("sccs", PDK_Skipped) .Case("assert", PDK_Skipped) .Case("unassert", PDK_Skipped) - .Case("if", PDK_StartIf) - .Case("ifdef", PDK_StartIf) - .Case("ifndef", PDK_StartIf) + .Case("if", PDK_Skipped) + .Case("ifdef", PDK_Skipped) + .Case("ifndef", PDK_Skipped) .Case("elif", PDK_Skipped) .Case("else", PDK_Skipped) - .Case("endif", PDK_EndIf) + .Case("endif", PDK_Skipped) .Default(PDK_Unknown); switch (PDK) { case PDK_Skipped: continue; - case PDK_StartIf: - if (IfCount == 0) - IfStartTok = HashTok; - - ++IfCount; - continue; - - case PDK_EndIf: - // Mismatched #endif. The preamble ends here. - if (IfCount == 0) - break; - - --IfCount; - continue; - case PDK_Unknown: // We don't know what this directive is; stop at the '#'. break; @@ -690,16 +687,13 @@ std::pair<unsigned, bool> Lexer::ComputePreamble(StringRef Buffer, } while (true); SourceLocation End; - if (IfCount) - End = IfStartTok.getLocation(); - else if (ActiveCommentLoc.isValid()) + if (ActiveCommentLoc.isValid()) End = ActiveCommentLoc; // don't truncate a decl comment. else End = TheTok.getLocation(); return std::make_pair(End.getRawEncoding() - StartLoc.getRawEncoding(), - IfCount? IfStartTok.isAtStartOfLine() - : TheTok.isAtStartOfLine()); + TheTok.isAtStartOfLine()); } /// AdvanceToTokenCharacter - Given a location that specifies the start of a @@ -1038,6 +1032,27 @@ bool Lexer::isIdentifierBodyChar(char c, const LangOptions &LangOpts) { return isIdentifierBody(c, LangOpts.DollarIdents); } +StringRef Lexer::getIndentationForLine(SourceLocation Loc, + const SourceManager &SM) { + if (Loc.isInvalid() || Loc.isMacroID()) + return ""; + std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(Loc); + if (LocInfo.first.isInvalid()) + return ""; + bool Invalid = false; + StringRef Buffer = SM.getBufferData(LocInfo.first, &Invalid); + if (Invalid) + return ""; + const char *Line = findBeginningOfLine(Buffer, LocInfo.second); + if (!Line) + return ""; + StringRef Rest = Buffer.substr(Line - Buffer.data()); + size_t NumWhitespaceChars = Rest.find_first_not_of(" \t"); + return NumWhitespaceChars == StringRef::npos + ? "" + : Rest.take_front(NumWhitespaceChars); +} + //===----------------------------------------------------------------------===// // Diagnostics forwarding code. //===----------------------------------------------------------------------===// @@ -1171,6 +1186,8 @@ const char *Lexer::SkipEscapedNewLines(const char *P) { // If not a trigraph for escape, bail out. if (P[1] != '?' || P[2] != '/') return P; + // FIXME: Take LangOpts into account; the language might not + // support trigraphs. AfterEscape = P+3; } else { return P; @@ -1282,12 +1299,6 @@ Slash: Size += EscapedNewLineSize; Ptr += EscapedNewLineSize; - // If the char that we finally got was a \n, then we must have had - // something like \<newline><newline>. We don't want to consume the - // second newline. - if (*Ptr == '\n' || *Ptr == '\r' || *Ptr == '\0') - return ' '; - // Use slow version to accumulate a correct size field. return getCharAndSizeSlow(Ptr, Size, Tok); } @@ -1338,12 +1349,6 @@ Slash: Size += EscapedNewLineSize; Ptr += EscapedNewLineSize; - // If the char that we finally got was a \n, then we must have had - // something like \<newline><newline>. We don't want to consume the - // second newline. - if (*Ptr == '\n' || *Ptr == '\r' || *Ptr == '\0') - return ' '; - // Use slow version to accumulate a correct size field. return getCharAndSizeSlowNoWarn(Ptr, Size, LangOpts); } @@ -2070,8 +2075,11 @@ bool Lexer::SkipLineComment(Token &Result, const char *CurPtr, // Scan over the body of the comment. The common case, when scanning, is that // the comment contains normal ascii characters with nothing interesting in // them. As such, optimize for this case with the inner loop. + // + // This loop terminates with CurPtr pointing at the newline (or end of buffer) + // character that ends the line comment. char C; - do { + while (true) { C = *CurPtr; // Skip over characters in the fast loop. while (C != 0 && // Potentially EOF. @@ -2088,10 +2096,12 @@ bool Lexer::SkipLineComment(Token &Result, const char *CurPtr, HasSpace = true; } - if (*EscapePtr == '\\') // Escaped newline. + if (*EscapePtr == '\\') + // Escaped newline. CurPtr = EscapePtr; else if (EscapePtr[0] == '/' && EscapePtr[-1] == '?' && - EscapePtr[-2] == '?') // Trigraph-escaped newline. + EscapePtr[-2] == '?' && LangOpts.Trigraphs) + // Trigraph-escaped newline. CurPtr = EscapePtr-2; else break; // This is a newline, we're done. @@ -2140,9 +2150,9 @@ bool Lexer::SkipLineComment(Token &Result, const char *CurPtr, } } - if (CurPtr == BufferEnd+1) { - --CurPtr; - break; + if (C == '\r' || C == '\n' || CurPtr == BufferEnd + 1) { + --CurPtr; + break; } if (C == '\0' && isCodeCompletionPoint(CurPtr-1)) { @@ -2150,8 +2160,7 @@ bool Lexer::SkipLineComment(Token &Result, const char *CurPtr, cutOffLexing(); return false; } - - } while (C != '\n' && C != '\r'); + } // Found but did not consume the newline. Notify comment handlers about the // comment unless we're in a #if 0 block. @@ -2490,6 +2499,7 @@ void Lexer::ReadToEndOfLine(SmallVectorImpl<char> *Result) { break; } // FALL THROUGH. + LLVM_FALLTHROUGH; case '\r': case '\n': // Okay, we found the end of the line. First, back up past the \0, \r, \n. @@ -2540,6 +2550,11 @@ bool Lexer::LexEndOfFile(Token &Result, const char *CurPtr) { return true; } + if (PP->isRecordingPreamble() && PP->isInPrimaryFile()) { + PP->setRecordedPreambleConditionalStack(ConditionalStack); + ConditionalStack.clear(); + } + // Issue diagnostics for unterminated #if and missing newline. // If we are in a #if directive, emit an error. @@ -2722,6 +2737,37 @@ bool Lexer::HandleEndOfConflictMarker(const char *CurPtr) { return false; } +static const char *findPlaceholderEnd(const char *CurPtr, + const char *BufferEnd) { + if (CurPtr == BufferEnd) + return nullptr; + BufferEnd -= 1; // Scan until the second last character. + for (; CurPtr != BufferEnd; ++CurPtr) { + if (CurPtr[0] == '#' && CurPtr[1] == '>') + return CurPtr + 2; + } + return nullptr; +} + +bool Lexer::lexEditorPlaceholder(Token &Result, const char *CurPtr) { + assert(CurPtr[-1] == '<' && CurPtr[0] == '#' && "Not a placeholder!"); + if (!PP || !PP->getPreprocessorOpts().LexEditorPlaceholders || LexingRawMode) + return false; + const char *End = findPlaceholderEnd(CurPtr + 1, BufferEnd); + if (!End) + return false; + const char *Start = CurPtr - 1; + if (!LangOpts.AllowEditorPlaceholders) + Diag(Start, diag::err_placeholder_in_source); + Result.startToken(); + FormTokenWithChars(Result, End, tok::raw_identifier); + Result.setRawIdentifierData(Start); + PP->LookUpIdentifierInfo(Result); + Result.setFlag(Token::IsEditorPlaceholder); + BufferPtr = End; + return true; +} + bool Lexer::isCodeCompletionPoint(const char *CurPtr) const { if (PP && PP->isCodeCompletionEnabled()) { SourceLocation Loc = FileLoc.getLocWithOffset(CurPtr-BufferStart); @@ -3203,6 +3249,7 @@ LexNextToken: return LexCharConstant(Result, ConsumeChar(CurPtr, SizeTmp, Result), tok::wide_char_constant); // FALL THROUGH, treating L like the start of an identifier. + LLVM_FALLTHROUGH; // C99 6.4.2: Identifiers. case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': @@ -3479,6 +3526,8 @@ LexNextToken: } else if (LangOpts.Digraphs && Char == '%') { // '<%' -> '{' CurPtr = ConsumeChar(CurPtr, SizeTmp, Result); Kind = tok::l_brace; + } else if (Char == '#' && lexEditorPlaceholder(Result, CurPtr)) { + return true; } else { Kind = tok::less; } @@ -3603,17 +3652,19 @@ LexNextToken: // UCNs (C99 6.4.3, C++11 [lex.charset]p2) case '\\': - if (uint32_t CodePoint = tryReadUCN(CurPtr, BufferPtr, &Result)) { - if (CheckUnicodeWhitespace(Result, CodePoint, CurPtr)) { - if (SkipWhitespace(Result, CurPtr, TokAtPhysicalStartOfLine)) - return true; // KeepWhitespaceMode + if (!LangOpts.AsmPreprocessor) { + if (uint32_t CodePoint = tryReadUCN(CurPtr, BufferPtr, &Result)) { + if (CheckUnicodeWhitespace(Result, CodePoint, CurPtr)) { + if (SkipWhitespace(Result, CurPtr, TokAtPhysicalStartOfLine)) + return true; // KeepWhitespaceMode + + // We only saw whitespace, so just try again with this lexer. + // (We manually eliminate the tail call to avoid recursion.) + goto LexNextToken; + } - // We only saw whitespace, so just try again with this lexer. - // (We manually eliminate the tail call to avoid recursion.) - goto LexNextToken; + return LexUnicode(Result, CodePoint, CurPtr); } - - return LexUnicode(Result, CodePoint, CurPtr); } Kind = tok::unknown; diff --git a/contrib/llvm/tools/clang/lib/Lex/LiteralSupport.cpp b/contrib/llvm/tools/clang/lib/Lex/LiteralSupport.cpp index fbfd3fe..a598a46 100644 --- a/contrib/llvm/tools/clang/lib/Lex/LiteralSupport.cpp +++ b/contrib/llvm/tools/clang/lib/Lex/LiteralSupport.cpp @@ -456,10 +456,17 @@ 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; + LLVM_FALLTHROUGH; + case 3: + *--ResultBuf = (UTF8)((UcnVal | byteMark) & byteMask); UcnVal >>= 6; + LLVM_FALLTHROUGH; + case 2: + *--ResultBuf = (UTF8)((UcnVal | byteMark) & byteMask); UcnVal >>= 6; + LLVM_FALLTHROUGH; + case 1: + *--ResultBuf = (UTF8) (UcnVal | firstByteMark[bytesToWrite]); } // Update the buffer. ResultBuf += bytesToWrite; @@ -563,7 +570,6 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling, // Parse the suffix. At this point we can classify whether we have an FP or // integer constant. bool isFPConstant = isFloatingLiteral(); - const char *ImaginarySuffixLoc = nullptr; // Loop over all of the characters of the suffix. If we see something bad, // we break out of the loop. @@ -660,7 +666,6 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling, case 'J': if (isImaginary) break; // Cannot be repeated. isImaginary = true; - ImaginarySuffixLoc = s; continue; // Success. } // If we reached here, there was an error or a ud-suffix. @@ -694,8 +699,7 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling, } if (isImaginary) { - PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, - ImaginarySuffixLoc - ThisTokBegin), + PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, SuffixBegin - ThisTokBegin), diag::ext_imaginary_constant); } } diff --git a/contrib/llvm/tools/clang/lib/Lex/MacroArgs.cpp b/contrib/llvm/tools/clang/lib/Lex/MacroArgs.cpp index 1c1979d..f791d8d 100644 --- a/contrib/llvm/tools/clang/lib/Lex/MacroArgs.cpp +++ b/contrib/llvm/tools/clang/lib/Lex/MacroArgs.cpp @@ -44,20 +44,22 @@ MacroArgs *MacroArgs::create(const MacroInfo *MI, // Otherwise, use the best fit. ClosestMatch = (*Entry)->NumUnexpArgTokens; } - + MacroArgs *Result; if (!ResultEnt) { // Allocate memory for a MacroArgs object with the lexer tokens at the end. - Result = (MacroArgs*)malloc(sizeof(MacroArgs) + - UnexpArgTokens.size() * sizeof(Token)); + Result = (MacroArgs *)malloc(sizeof(MacroArgs) + + UnexpArgTokens.size() * sizeof(Token)); // Construct the MacroArgs object. - new (Result) MacroArgs(UnexpArgTokens.size(), VarargsElided); + new (Result) + MacroArgs(UnexpArgTokens.size(), VarargsElided, MI->getNumParams()); } else { Result = *ResultEnt; // Unlink this node from the preprocessors singly linked list. *ResultEnt = Result->ArgCache; Result->NumUnexpArgTokens = UnexpArgTokens.size(); Result->VarargsElided = VarargsElided; + Result->NumMacroArgs = MI->getNumParams(); } // Copy the actual unexpanded tokens to immediately after the result ptr. @@ -146,11 +148,11 @@ bool MacroArgs::ArgNeedsPreexpansion(const Token *ArgTok, const std::vector<Token> & MacroArgs::getPreExpArgument(unsigned Arg, const MacroInfo *MI, Preprocessor &PP) { - assert(Arg < MI->getNumArgs() && "Invalid argument number!"); + assert(Arg < MI->getNumParams() && "Invalid argument number!"); // If we have already computed this, return it. - if (PreExpArgTokens.size() < MI->getNumArgs()) - PreExpArgTokens.resize(MI->getNumArgs()); + if (PreExpArgTokens.size() < MI->getNumParams()) + PreExpArgTokens.resize(MI->getNumParams()); std::vector<Token> &Result = PreExpArgTokens[Arg]; if (!Result.empty()) return Result; @@ -298,12 +300,10 @@ const Token &MacroArgs::getStringifiedArgument(unsigned ArgNo, Preprocessor &PP, SourceLocation ExpansionLocStart, SourceLocation ExpansionLocEnd) { - assert(ArgNo < NumUnexpArgTokens && "Invalid argument number!"); - if (StringifiedArgs.empty()) { - StringifiedArgs.resize(getNumArguments()); - memset((void*)&StringifiedArgs[0], 0, - sizeof(StringifiedArgs[0])*getNumArguments()); - } + assert(ArgNo < getNumMacroArguments() && "Invalid argument number!"); + if (StringifiedArgs.empty()) + StringifiedArgs.resize(getNumMacroArguments(), {}); + if (StringifiedArgs[ArgNo].isNot(tok::string_literal)) StringifiedArgs[ArgNo] = StringifyArgument(getUnexpArgument(ArgNo), PP, /*Charify=*/false, diff --git a/contrib/llvm/tools/clang/lib/Lex/MacroInfo.cpp b/contrib/llvm/tools/clang/lib/Lex/MacroInfo.cpp index 924613d..6dc7841 100644 --- a/contrib/llvm/tools/clang/lib/Lex/MacroInfo.cpp +++ b/contrib/llvm/tools/clang/lib/Lex/MacroInfo.cpp @@ -17,8 +17,8 @@ using namespace clang; MacroInfo::MacroInfo(SourceLocation DefLoc) : Location(DefLoc), - ArgumentList(nullptr), - NumArguments(0), + ParameterList(nullptr), + NumParameters(0), IsDefinitionLengthCached(false), IsFunctionLike(false), IsC99Varargs(false), @@ -29,11 +29,10 @@ MacroInfo::MacroInfo(SourceLocation DefLoc) IsUsed(false), IsAllowRedefinitionsWithoutWarning(false), IsWarnIfUnused(false), - FromASTFile(false), UsedForHeaderGuard(false) { } -unsigned MacroInfo::getDefinitionLengthSlow(SourceManager &SM) const { +unsigned MacroInfo::getDefinitionLengthSlow(const SourceManager &SM) const { assert(!IsDefinitionLengthCached); IsDefinitionLengthCached = true; @@ -75,7 +74,7 @@ bool MacroInfo::isIdenticalTo(const MacroInfo &Other, Preprocessor &PP, // Check # tokens in replacement, number of args, and various flags all match. if (ReplacementTokens.size() != Other.ReplacementTokens.size() || - getNumArgs() != Other.getNumArgs() || + getNumParams() != Other.getNumParams() || isFunctionLike() != Other.isFunctionLike() || isC99Varargs() != Other.isC99Varargs() || isGNUVarargs() != Other.isGNUVarargs()) @@ -83,7 +82,8 @@ bool MacroInfo::isIdenticalTo(const MacroInfo &Other, Preprocessor &PP, if (Lexically) { // Check arguments. - for (arg_iterator I = arg_begin(), OI = Other.arg_begin(), E = arg_end(); + for (param_iterator I = param_begin(), OI = Other.param_begin(), + E = param_end(); I != E; ++I, ++OI) if (*I != *OI) return false; } @@ -110,10 +110,10 @@ bool MacroInfo::isIdenticalTo(const MacroInfo &Other, Preprocessor &PP, return false; // With syntactic equivalence the parameter names can be different as long // as they are used in the same place. - int AArgNum = getArgumentNum(A.getIdentifierInfo()); + int AArgNum = getParameterNum(A.getIdentifierInfo()); if (AArgNum == -1) return false; - if (AArgNum != Other.getArgumentNum(B.getIdentifierInfo())) + if (AArgNum != Other.getParameterNum(B.getIdentifierInfo())) return false; continue; } @@ -137,18 +137,17 @@ LLVM_DUMP_METHOD void MacroInfo::dump() const { if (IsAllowRedefinitionsWithoutWarning) Out << " allow_redefinitions_without_warning"; if (IsWarnIfUnused) Out << " warn_if_unused"; - if (FromASTFile) Out << " imported"; if (UsedForHeaderGuard) Out << " header_guard"; Out << "\n #define <macro>"; if (IsFunctionLike) { Out << "("; - for (unsigned I = 0; I != NumArguments; ++I) { + for (unsigned I = 0; I != NumParameters; ++I) { if (I) Out << ", "; - Out << ArgumentList[I]->getName(); + Out << ParameterList[I]->getName(); } if (IsC99Varargs || IsGNUVarargs) { - if (NumArguments && IsC99Varargs) Out << ", "; + if (NumParameters && IsC99Varargs) Out << ", "; Out << "..."; } Out << ")"; diff --git a/contrib/llvm/tools/clang/lib/Lex/ModuleMap.cpp b/contrib/llvm/tools/clang/lib/Lex/ModuleMap.cpp index 1488f62..40f78ce 100644 --- a/contrib/llvm/tools/clang/lib/Lex/ModuleMap.cpp +++ b/contrib/llvm/tools/clang/lib/Lex/ModuleMap.cpp @@ -36,6 +36,37 @@ #endif using namespace clang; +Module::HeaderKind ModuleMap::headerRoleToKind(ModuleHeaderRole Role) { + switch ((int)Role) { + default: llvm_unreachable("unknown header role"); + case NormalHeader: + return Module::HK_Normal; + case PrivateHeader: + return Module::HK_Private; + case TextualHeader: + return Module::HK_Textual; + case PrivateHeader | TextualHeader: + return Module::HK_PrivateTextual; + } +} + +ModuleMap::ModuleHeaderRole +ModuleMap::headerKindToRole(Module::HeaderKind Kind) { + switch ((int)Kind) { + case Module::HK_Normal: + return NormalHeader; + case Module::HK_Private: + return PrivateHeader; + case Module::HK_Textual: + return TextualHeader; + case Module::HK_PrivateTextual: + return ModuleHeaderRole(PrivateHeader | TextualHeader); + case Module::HK_Excluded: + llvm_unreachable("unexpected header kind"); + } + llvm_unreachable("unknown header kind"); +} + Module::ExportDecl ModuleMap::resolveExport(Module *Mod, const Module::UnresolvedExportDecl &Unresolved, @@ -84,6 +115,143 @@ Module *ModuleMap::resolveModuleId(const ModuleId &Id, Module *Mod, return Context; } +/// \brief Append to \p Paths the set of paths needed to get to the +/// subframework in which the given module lives. +static void appendSubframeworkPaths(Module *Mod, + SmallVectorImpl<char> &Path) { + // Collect the framework names from the given module to the top-level module. + SmallVector<StringRef, 2> Paths; + for (; Mod; Mod = Mod->Parent) { + if (Mod->IsFramework) + Paths.push_back(Mod->Name); + } + + if (Paths.empty()) + return; + + // Add Frameworks/Name.framework for each subframework. + for (unsigned I = Paths.size() - 1; I != 0; --I) + llvm::sys::path::append(Path, "Frameworks", Paths[I-1] + ".framework"); +} + +const FileEntry * +ModuleMap::findHeader(Module *M, + const Module::UnresolvedHeaderDirective &Header, + SmallVectorImpl<char> &RelativePathName) { + auto GetFile = [&](StringRef Filename) -> const FileEntry * { + auto *File = SourceMgr.getFileManager().getFile(Filename); + if (!File || + (Header.Size && File->getSize() != *Header.Size) || + (Header.ModTime && File->getModificationTime() != *Header.ModTime)) + return nullptr; + return File; + }; + + if (llvm::sys::path::is_absolute(Header.FileName)) { + RelativePathName.clear(); + RelativePathName.append(Header.FileName.begin(), Header.FileName.end()); + return GetFile(Header.FileName); + } + + // Search for the header file within the module's home directory. + auto *Directory = M->Directory; + SmallString<128> FullPathName(Directory->getName()); + unsigned FullPathLength = FullPathName.size(); + + if (M->isPartOfFramework()) { + appendSubframeworkPaths(M, RelativePathName); + unsigned RelativePathLength = RelativePathName.size(); + + // Check whether this file is in the public headers. + llvm::sys::path::append(RelativePathName, "Headers", Header.FileName); + llvm::sys::path::append(FullPathName, RelativePathName); + if (auto *File = GetFile(FullPathName)) + return File; + + // Check whether this file is in the private headers. + // Ideally, private modules in the form 'FrameworkName.Private' should + // be defined as 'module FrameworkName.Private', and not as + // 'framework module FrameworkName.Private', since a 'Private.Framework' + // does not usually exist. However, since both are currently widely used + // for private modules, make sure we find the right path in both cases. + if (M->IsFramework && M->Name == "Private") + RelativePathName.clear(); + else + RelativePathName.resize(RelativePathLength); + FullPathName.resize(FullPathLength); + llvm::sys::path::append(RelativePathName, "PrivateHeaders", + Header.FileName); + llvm::sys::path::append(FullPathName, RelativePathName); + return GetFile(FullPathName); + } + + // Lookup for normal headers. + llvm::sys::path::append(RelativePathName, Header.FileName); + llvm::sys::path::append(FullPathName, RelativePathName); + return GetFile(FullPathName); +} + +void ModuleMap::resolveHeader(Module *Mod, + const Module::UnresolvedHeaderDirective &Header) { + SmallString<128> RelativePathName; + if (const FileEntry *File = findHeader(Mod, Header, RelativePathName)) { + if (Header.IsUmbrella) { + const DirectoryEntry *UmbrellaDir = File->getDir(); + if (Module *UmbrellaMod = UmbrellaDirs[UmbrellaDir]) + Diags.Report(Header.FileNameLoc, diag::err_mmap_umbrella_clash) + << UmbrellaMod->getFullModuleName(); + else + // Record this umbrella header. + setUmbrellaHeader(Mod, File, RelativePathName.str()); + } else { + Module::Header H = {RelativePathName.str(), File}; + if (Header.Kind == Module::HK_Excluded) + excludeHeader(Mod, H); + else + addHeader(Mod, H, headerKindToRole(Header.Kind)); + } + } else if (Header.HasBuiltinHeader && !Header.Size && !Header.ModTime) { + // There's a builtin header but no corresponding on-disk header. Assume + // this was supposed to modularize the builtin header alone. + } else if (Header.Kind == Module::HK_Excluded) { + // Ignore missing excluded header files. They're optional anyway. + } else { + // If we find a module that has a missing header, we mark this module as + // unavailable and store the header directive for displaying diagnostics. + Mod->MissingHeaders.push_back(Header); + // A missing header with stat information doesn't make the module + // unavailable; this keeps our behavior consistent as headers are lazily + // resolved. (Such a module still can't be built though, except from + // preprocessed source.) + if (!Header.Size && !Header.ModTime) + Mod->markUnavailable(); + } +} + +bool ModuleMap::resolveAsBuiltinHeader( + Module *Mod, const Module::UnresolvedHeaderDirective &Header) { + if (Header.Kind == Module::HK_Excluded || + llvm::sys::path::is_absolute(Header.FileName) || + Mod->isPartOfFramework() || !Mod->IsSystem || Header.IsUmbrella || + !BuiltinIncludeDir || BuiltinIncludeDir == Mod->Directory || + !isBuiltinHeader(Header.FileName)) + return false; + + // This is a system module with a top-level header. This header + // may have a counterpart (or replacement) in the set of headers + // supplied by Clang. Find that builtin header. + SmallString<128> Path; + llvm::sys::path::append(Path, BuiltinIncludeDir->getName(), Header.FileName); + auto *File = SourceMgr.getFileManager().getFile(Path); + if (!File) + return false; + + auto Role = headerKindToRole(Header.Kind); + Module::Header H = {Path.str(), File}; + addHeader(Mod, H, Role); + return true; +} + ModuleMap::ModuleMap(SourceManager &SourceMgr, DiagnosticsEngine &Diags, const LangOptions &LangOpts, const TargetInfo *Target, HeaderSearch &HeaderInfo) @@ -162,6 +330,7 @@ bool ModuleMap::isBuiltinHeader(StringRef FileName) { ModuleMap::HeadersMap::iterator ModuleMap::findKnownHeader(const FileEntry *File) { + resolveHeaderDirectives(File); HeadersMap::iterator Known = Headers.find(File); if (HeaderInfo.getHeaderSearchOpts().ImplicitModuleMaps && Known == Headers.end() && File->getDir() == BuiltinIncludeDir && @@ -244,8 +413,10 @@ void ModuleMap::diagnoseHeaderInclusion(Module *RequestingModule, if (getTopLevelOrNull(RequestingModule) != getTopLevelOrNull(SourceModule)) return; - if (RequestingModule) + if (RequestingModule) { resolveUses(RequestingModule, /*Complain=*/false); + resolveHeaderDirectives(RequestingModule); + } bool Excluded = false; Module *Private = nullptr; @@ -427,6 +598,7 @@ ModuleMap::findOrCreateModuleForHeaderInUmbrellaDir(const FileEntry *File) { ArrayRef<ModuleMap::KnownHeader> ModuleMap::findAllModulesForHeader(const FileEntry *File) const { + resolveHeaderDirectives(File); auto It = Headers.find(File); if (It == Headers.end()) return None; @@ -440,6 +612,7 @@ bool ModuleMap::isHeaderInUnavailableModule(const FileEntry *Header) const { bool ModuleMap::isHeaderUnavailableInModule(const FileEntry *Header, const Module *RequestingModule) const { + resolveHeaderDirectives(Header); HeadersMap::const_iterator Known = Headers.find(Header); if (Known != Headers.end()) { for (SmallVectorImpl<KnownHeader>::const_iterator @@ -554,16 +727,17 @@ Module *ModuleMap::lookupModuleQualified(StringRef Name, Module *Context) const{ return Context->findSubmodule(Name); } -std::pair<Module *, bool> -ModuleMap::findOrCreateModule(StringRef Name, Module *Parent, bool IsFramework, - bool IsExplicit) { +std::pair<Module *, bool> ModuleMap::findOrCreateModule(StringRef Name, + Module *Parent, + bool IsFramework, + bool IsExplicit) { // Try to find an existing module with this name. if (Module *Sub = lookupModuleQualified(Name, Parent)) return std::make_pair(Sub, false); // Create a new module with this name. - Module *Result = new Module(Name, SourceLocation(), Parent, - IsFramework, IsExplicit, NumCreatedModules++); + Module *Result = new Module(Name, SourceLocation(), Parent, IsFramework, + IsExplicit, NumCreatedModules++); if (!Parent) { if (LangOpts.CurrentModule == Name) SourceModule = Result; @@ -580,6 +754,7 @@ Module *ModuleMap::createModuleForInterfaceUnit(SourceLocation Loc, auto *Result = new Module(Name, Loc, nullptr, /*IsFramework*/ false, /*IsExplicit*/ false, NumCreatedModules++); + Result->Kind = Module::ModuleInterfaceUnit; Modules[Name] = SourceModule = Result; // Mark the main source file as being within the newly-created module so that @@ -810,18 +985,63 @@ void ModuleMap::setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir, UmbrellaDirs[UmbrellaDir] = Mod; } -static Module::HeaderKind headerRoleToKind(ModuleMap::ModuleHeaderRole Role) { - switch ((int)Role) { - default: llvm_unreachable("unknown header role"); - case ModuleMap::NormalHeader: - return Module::HK_Normal; - case ModuleMap::PrivateHeader: - return Module::HK_Private; - case ModuleMap::TextualHeader: - return Module::HK_Textual; - case ModuleMap::PrivateHeader | ModuleMap::TextualHeader: - return Module::HK_PrivateTextual; +void ModuleMap::addUnresolvedHeader(Module *Mod, + Module::UnresolvedHeaderDirective Header) { + // If there is a builtin counterpart to this file, add it now so it can + // wrap the system header. + if (resolveAsBuiltinHeader(Mod, Header)) { + // If we have both a builtin and system version of the file, the + // builtin version may want to inject macros into the system header, so + // force the system header to be treated as a textual header in this + // case. + Header.Kind = headerRoleToKind(ModuleMap::ModuleHeaderRole( + headerKindToRole(Header.Kind) | ModuleMap::TextualHeader)); + Header.HasBuiltinHeader = true; + } + + // If possible, don't stat the header until we need to. This requires the + // user to have provided us with some stat information about the file. + // FIXME: Add support for lazily stat'ing umbrella headers and excluded + // headers. + if ((Header.Size || Header.ModTime) && !Header.IsUmbrella && + Header.Kind != Module::HK_Excluded) { + // We expect more variation in mtime than size, so if we're given both, + // use the mtime as the key. + if (Header.ModTime) + LazyHeadersByModTime[*Header.ModTime].push_back(Mod); + else + LazyHeadersBySize[*Header.Size].push_back(Mod); + Mod->UnresolvedHeaders.push_back(Header); + return; } + + // We don't have stat information or can't defer looking this file up. + // Perform the lookup now. + resolveHeader(Mod, Header); +} + +void ModuleMap::resolveHeaderDirectives(const FileEntry *File) const { + auto BySize = LazyHeadersBySize.find(File->getSize()); + if (BySize != LazyHeadersBySize.end()) { + for (auto *M : BySize->second) + resolveHeaderDirectives(M); + LazyHeadersBySize.erase(BySize); + } + + auto ByModTime = LazyHeadersByModTime.find(File->getModificationTime()); + if (ByModTime != LazyHeadersByModTime.end()) { + for (auto *M : ByModTime->second) + resolveHeaderDirectives(M); + LazyHeadersByModTime.erase(ByModTime); + } +} + +void ModuleMap::resolveHeaderDirectives(Module *Mod) const { + for (auto &Header : Mod->UnresolvedHeaders) + // This operation is logically const; we're just changing how we represent + // the header information for this file. + const_cast<ModuleMap*>(this)->resolveHeader(Mod, Header); + Mod->UnresolvedHeaders.clear(); } void ModuleMap::addHeader(Module *Mod, Module::Header Header, @@ -948,39 +1168,6 @@ bool ModuleMap::resolveConflicts(Module *Mod, bool Complain) { return !Mod->UnresolvedConflicts.empty(); } -Module *ModuleMap::inferModuleFromLocation(FullSourceLoc Loc) { - if (Loc.isInvalid()) - return nullptr; - - if (UmbrellaDirs.empty() && Headers.empty()) - return nullptr; - - // Use the expansion location to determine which module we're in. - FullSourceLoc ExpansionLoc = Loc.getExpansionLoc(); - if (!ExpansionLoc.isFileID()) - return nullptr; - - const SourceManager &SrcMgr = Loc.getManager(); - FileID ExpansionFileID = ExpansionLoc.getFileID(); - - while (const FileEntry *ExpansionFile - = SrcMgr.getFileEntryForID(ExpansionFileID)) { - // Find the module that owns this header (if any). - if (Module *Mod = findModuleForHeader(ExpansionFile).getModule()) - return Mod; - - // No module owns this header, so look up the inclusion chain to see if - // any included header has an associated module. - SourceLocation IncludeLoc = SrcMgr.getIncludeLoc(ExpansionFileID); - if (IncludeLoc.isInvalid()) - return nullptr; - - ExpansionFileID = SrcMgr.getFileID(IncludeLoc); - } - - return nullptr; -} - //----------------------------------------------------------------------------// // Module map file parser //----------------------------------------------------------------------------// @@ -1010,6 +1197,7 @@ namespace clang { RequiresKeyword, Star, StringLiteral, + IntegerLiteral, TextualKeyword, LBrace, RBrace, @@ -1019,7 +1207,12 @@ namespace clang { unsigned Location; unsigned StringLength; - const char *StringData; + union { + // If Kind != IntegerLiteral. + const char *StringData; + // If Kind == IntegerLiteral. + uint64_t IntegerValue; + }; void clear() { Kind = EndOfFile; @@ -1033,9 +1226,14 @@ namespace clang { SourceLocation getLocation() const { return SourceLocation::getFromRawEncoding(Location); } + + uint64_t getInteger() const { + return Kind == IntegerLiteral ? IntegerValue : 0; + } StringRef getString() const { - return StringRef(StringData, StringLength); + return Kind == IntegerLiteral ? StringRef() + : StringRef(StringData, StringLength); } }; @@ -1057,9 +1255,6 @@ namespace clang { /// be resolved relative to. const DirectoryEntry *Directory; - /// \brief The directory containing Clang-supplied headers. - const DirectoryEntry *BuiltinIncludeDir; - /// \brief Whether this module map is in a system header directory. bool IsSystem; @@ -1118,26 +1313,27 @@ namespace clang { ModuleMap &Map, const FileEntry *ModuleMapFile, const DirectoryEntry *Directory, - const DirectoryEntry *BuiltinIncludeDir, bool IsSystem) : L(L), SourceMgr(SourceMgr), Target(Target), Diags(Diags), Map(Map), ModuleMapFile(ModuleMapFile), Directory(Directory), - BuiltinIncludeDir(BuiltinIncludeDir), IsSystem(IsSystem), - HadError(false), ActiveModule(nullptr) + IsSystem(IsSystem), HadError(false), ActiveModule(nullptr) { Tok.clear(); consumeToken(); } bool parseModuleMapFile(); + + bool terminatedByDirective() { return false; } + SourceLocation getLocation() { return Tok.getLocation(); } }; } SourceLocation ModuleMapParser::consumeToken() { -retry: SourceLocation Result = Tok.getLocation(); + +retry: Tok.clear(); - Token LToken; L.LexFromRawLexer(LToken); Tok.Location = LToken.getLocation().getRawEncoding(); @@ -1227,12 +1423,50 @@ retry: Tok.StringLength = Length; break; } + + case tok::numeric_constant: { + // We don't support any suffixes or other complications. + SmallString<32> SpellingBuffer; + SpellingBuffer.resize(LToken.getLength() + 1); + const char *Start = SpellingBuffer.data(); + unsigned Length = + Lexer::getSpelling(LToken, Start, SourceMgr, L.getLangOpts()); + uint64_t Value; + if (StringRef(Start, Length).getAsInteger(0, Value)) { + Diags.Report(Tok.getLocation(), diag::err_mmap_unknown_token); + HadError = true; + goto retry; + } + + Tok.Kind = MMToken::IntegerLiteral; + Tok.IntegerValue = Value; + break; + } case tok::comment: goto retry; - + + case tok::hash: + // A module map can be terminated prematurely by + // #pragma clang module contents + // When building the module, we'll treat the rest of the file as the + // contents of the module. + { + auto NextIsIdent = [&](StringRef Str) -> bool { + L.LexFromRawLexer(LToken); + return !LToken.isAtStartOfLine() && LToken.is(tok::raw_identifier) && + LToken.getRawIdentifier() == Str; + }; + if (NextIsIdent("pragma") && NextIsIdent("clang") && + NextIsIdent("module") && NextIsIdent("contents")) { + Tok.Kind = MMToken::EndOfFile; + break; + } + } + LLVM_FALLTHROUGH; + default: - Diags.Report(LToken.getLocation(), diag::err_mmap_unknown_token); + Diags.Report(Tok.getLocation(), diag::err_mmap_unknown_token); HadError = true; goto retry; } @@ -1461,7 +1695,19 @@ void ModuleMapParser::parseModuleDecl() { // Determine whether this (sub)module has already been defined. if (Module *Existing = Map.lookupModuleQualified(ModuleName, ActiveModule)) { - if (Existing->DefinitionLoc.isInvalid() && !ActiveModule) { + // We might see a (re)definition of a module that we already have a + // definition for in two cases: + // - If we loaded one definition from an AST file and we've just found a + // corresponding definition in a module map file, or + bool LoadedFromASTFile = Existing->DefinitionLoc.isInvalid(); + // - If we're building a (preprocessed) module and we've just loaded the + // module map file from which it was created. + bool ParsedAsMainInput = + Map.LangOpts.getCompilingModule() == LangOptions::CMK_ModuleMap && + Map.LangOpts.CurrentModule == ModuleName && + SourceMgr.getDecomposedLoc(ModuleNameLoc).first != + SourceMgr.getDecomposedLoc(Existing->DefinitionLoc).first; + if (!ActiveModule && (LoadedFromASTFile || ParsedAsMainInput)) { // Skip the module definition. skipUntil(MMToken::RBrace); if (Tok.is(MMToken::RBrace)) @@ -1680,7 +1926,8 @@ void ModuleMapParser::parseExternModuleDecl() { File, /*IsSystem=*/false, Map.HeaderInfo.getHeaderSearchOpts().ModuleMapFileHomeIsCwd ? Directory - : File->getDir(), ExternLoc); + : File->getDir(), + FileID(), nullptr, ExternLoc); } /// Whether to add the requirement \p Feature to the module \p M. @@ -1768,25 +2015,6 @@ void ModuleMapParser::parseRequiresDecl() { } while (true); } -/// \brief Append to \p Paths the set of paths needed to get to the -/// subframework in which the given module lives. -static void appendSubframeworkPaths(Module *Mod, - SmallVectorImpl<char> &Path) { - // Collect the framework names from the given module to the top-level module. - SmallVector<StringRef, 2> Paths; - for (; Mod; Mod = Mod->Parent) { - if (Mod->IsFramework) - Paths.push_back(Mod->Name); - } - - if (Paths.empty()) - return; - - // Add Frameworks/Name.framework for each subframework. - for (unsigned I = Paths.size() - 1; I != 0; --I) - llvm::sys::path::append(Path, "Frameworks", Paths[I-1] + ".framework"); -} - /// \brief Parse a header declaration. /// /// header-declaration: @@ -1839,119 +2067,75 @@ void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken, Module::UnresolvedHeaderDirective Header; Header.FileName = Tok.getString(); Header.FileNameLoc = consumeToken(); - + Header.IsUmbrella = LeadingToken == MMToken::UmbrellaKeyword; + Header.Kind = + (LeadingToken == MMToken::ExcludeKeyword ? Module::HK_Excluded + : Map.headerRoleToKind(Role)); + // Check whether we already have an umbrella. - if (LeadingToken == MMToken::UmbrellaKeyword && ActiveModule->Umbrella) { + if (Header.IsUmbrella && ActiveModule->Umbrella) { Diags.Report(Header.FileNameLoc, diag::err_mmap_umbrella_clash) << ActiveModule->getFullModuleName(); HadError = true; return; } - // Look for this file. - const FileEntry *File = nullptr; - const FileEntry *BuiltinFile = nullptr; - SmallString<128> RelativePathName; - if (llvm::sys::path::is_absolute(Header.FileName)) { - RelativePathName = Header.FileName; - File = SourceMgr.getFileManager().getFile(RelativePathName); - } else { - // Search for the header file within the search directory. - SmallString<128> FullPathName(Directory->getName()); - unsigned FullPathLength = FullPathName.size(); - - if (ActiveModule->isPartOfFramework()) { - appendSubframeworkPaths(ActiveModule, RelativePathName); - - // Check whether this file is in the public headers. - llvm::sys::path::append(RelativePathName, "Headers", Header.FileName); - llvm::sys::path::append(FullPathName, RelativePathName); - File = SourceMgr.getFileManager().getFile(FullPathName); - - if (!File) { - // Check whether this file is in the private headers. - // FIXME: Should we retain the subframework paths here? - RelativePathName.clear(); - FullPathName.resize(FullPathLength); - llvm::sys::path::append(RelativePathName, "PrivateHeaders", - Header.FileName); - llvm::sys::path::append(FullPathName, RelativePathName); - File = SourceMgr.getFileManager().getFile(FullPathName); - } - } else { - // Lookup for normal headers. - llvm::sys::path::append(RelativePathName, Header.FileName); - llvm::sys::path::append(FullPathName, RelativePathName); - File = SourceMgr.getFileManager().getFile(FullPathName); - - // If this is a system module with a top-level header, this header - // may have a counterpart (or replacement) in the set of headers - // supplied by Clang. Find that builtin header. - if (ActiveModule->IsSystem && LeadingToken != MMToken::UmbrellaKeyword && - BuiltinIncludeDir && BuiltinIncludeDir != Directory && - ModuleMap::isBuiltinHeader(Header.FileName)) { - SmallString<128> BuiltinPathName(BuiltinIncludeDir->getName()); - llvm::sys::path::append(BuiltinPathName, Header.FileName); - BuiltinFile = SourceMgr.getFileManager().getFile(BuiltinPathName); - - // If Clang supplies this header but the underlying system does not, - // just silently swap in our builtin version. Otherwise, we'll end - // up adding both (later). - if (BuiltinFile && !File) { - File = BuiltinFile; - RelativePathName = BuiltinPathName; - BuiltinFile = nullptr; + // If we were given stat information, parse it so we can skip looking for + // the file. + if (Tok.is(MMToken::LBrace)) { + SourceLocation LBraceLoc = consumeToken(); + + while (!Tok.is(MMToken::RBrace) && !Tok.is(MMToken::EndOfFile)) { + enum Attribute { Size, ModTime, Unknown }; + StringRef Str = Tok.getString(); + SourceLocation Loc = consumeToken(); + switch (llvm::StringSwitch<Attribute>(Str) + .Case("size", Size) + .Case("mtime", ModTime) + .Default(Unknown)) { + case Size: + if (Header.Size) + Diags.Report(Loc, diag::err_mmap_duplicate_header_attribute) << Str; + if (!Tok.is(MMToken::IntegerLiteral)) { + Diags.Report(Tok.getLocation(), + diag::err_mmap_invalid_header_attribute_value) << Str; + skipUntil(MMToken::RBrace); + break; } - } - } - } + Header.Size = Tok.getInteger(); + consumeToken(); + break; - // 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 (LeadingToken == MMToken::UmbrellaKeyword) { - const DirectoryEntry *UmbrellaDir = File->getDir(); - if (Module *UmbrellaModule = Map.UmbrellaDirs[UmbrellaDir]) { - Diags.Report(LeadingLoc, diag::err_mmap_umbrella_clash) - << UmbrellaModule->getFullModuleName(); - HadError = true; - } else { - // Record this umbrella header. - Map.setUmbrellaHeader(ActiveModule, File, RelativePathName.str()); - } - } else if (LeadingToken == MMToken::ExcludeKeyword) { - Module::Header H = {RelativePathName.str(), File}; - Map.excludeHeader(ActiveModule, H); - } else { - // If there is a builtin counterpart to this file, add it now so it can - // wrap the system header. - if (BuiltinFile) { - // FIXME: Taking the name from the FileEntry is unstable and can give - // different results depending on how we've previously named that file - // in this build. - Module::Header H = { BuiltinFile->getName(), BuiltinFile }; - Map.addHeader(ActiveModule, H, Role); - - // If we have both a builtin and system version of the file, the - // builtin version may want to inject macros into the system header, so - // force the system header to be treated as a textual header in this - // case. - Role = ModuleMap::ModuleHeaderRole(Role | ModuleMap::TextualHeader); - } + case ModTime: + if (Header.ModTime) + Diags.Report(Loc, diag::err_mmap_duplicate_header_attribute) << Str; + if (!Tok.is(MMToken::IntegerLiteral)) { + Diags.Report(Tok.getLocation(), + diag::err_mmap_invalid_header_attribute_value) << Str; + skipUntil(MMToken::RBrace); + break; + } + Header.ModTime = Tok.getInteger(); + consumeToken(); + break; - // Record this header. - Module::Header H = { RelativePathName.str(), File }; - Map.addHeader(ActiveModule, H, Role); + case Unknown: + Diags.Report(Loc, diag::err_mmap_expected_header_attribute); + skipUntil(MMToken::RBrace); + break; + } } - } else if (LeadingToken != MMToken::ExcludeKeyword) { - // Ignore excluded header files. They're optional anyway. - // If we find a module that has a missing header, we mark this module as - // unavailable and store the header directive for displaying diagnostics. - Header.IsUmbrella = LeadingToken == MMToken::UmbrellaKeyword; - ActiveModule->markUnavailable(); - ActiveModule->MissingHeaders.push_back(Header); + if (Tok.is(MMToken::RBrace)) + consumeToken(); + else { + Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace); + Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match); + HadError = true; + } } + + Map.addUnresolvedHeader(ActiveModule, std::move(Header)); } static int compareModuleHeaders(const Module::Header *A, @@ -1995,9 +2179,8 @@ void ModuleMapParser::parseUmbrellaDirDecl(SourceLocation UmbrellaLoc) { } if (!Dir) { - Diags.Report(DirNameLoc, diag::err_mmap_umbrella_dir_not_found) + Diags.Report(DirNameLoc, diag::warn_mmap_umbrella_dir_not_found) << DirName; - HadError = true; return; } @@ -2503,6 +2686,7 @@ bool ModuleMapParser::parseModuleMapFile() { case MMToken::RequiresKeyword: case MMToken::Star: case MMToken::StringLiteral: + case MMToken::IntegerLiteral: case MMToken::TextualKeyword: case MMToken::UmbrellaKeyword: case MMToken::UseKeyword: @@ -2515,28 +2699,46 @@ bool ModuleMapParser::parseModuleMapFile() { } bool ModuleMap::parseModuleMapFile(const FileEntry *File, bool IsSystem, - const DirectoryEntry *Dir, + const DirectoryEntry *Dir, FileID ID, + unsigned *Offset, SourceLocation ExternModuleLoc) { + assert(Target && "Missing target information"); llvm::DenseMap<const FileEntry *, bool>::iterator Known = ParsedModuleMap.find(File); if (Known != ParsedModuleMap.end()) return Known->second; + // If the module map file wasn't already entered, do so now. + if (ID.isInvalid()) { + auto FileCharacter = + IsSystem ? SrcMgr::C_System_ModuleMap : SrcMgr::C_User_ModuleMap; + ID = SourceMgr.createFileID(File, ExternModuleLoc, FileCharacter); + } + assert(Target && "Missing target information"); - auto FileCharacter = IsSystem ? SrcMgr::C_System : SrcMgr::C_User; - FileID ID = SourceMgr.createFileID(File, ExternModuleLoc, FileCharacter); const llvm::MemoryBuffer *Buffer = SourceMgr.getBuffer(ID); if (!Buffer) return ParsedModuleMap[File] = true; + assert((!Offset || *Offset <= Buffer->getBufferSize()) && + "invalid buffer offset"); // Parse this module map file. - Lexer L(ID, SourceMgr.getBuffer(ID), SourceMgr, MMapLangOpts); + Lexer L(SourceMgr.getLocForStartOfFile(ID), MMapLangOpts, + Buffer->getBufferStart(), + Buffer->getBufferStart() + (Offset ? *Offset : 0), + Buffer->getBufferEnd()); SourceLocation Start = L.getSourceLocation(); ModuleMapParser Parser(L, SourceMgr, Target, Diags, *this, File, Dir, - BuiltinIncludeDir, IsSystem); + IsSystem); bool Result = Parser.parseModuleMapFile(); ParsedModuleMap[File] = Result; + if (Offset) { + auto Loc = SourceMgr.getDecomposedLoc(Parser.getLocation()); + assert(Loc.first == ID && "stopped in a different file?"); + *Offset = Loc.second; + } + // Notify callbacks that we parsed it. for (const auto &Cb : Callbacks) Cb->moduleMapFileRead(Start, *File, IsSystem); diff --git a/contrib/llvm/tools/clang/lib/Lex/PPCaching.cpp b/contrib/llvm/tools/clang/lib/Lex/PPCaching.cpp index 45bdce3..f5e8cdc 100644 --- a/contrib/llvm/tools/clang/lib/Lex/PPCaching.cpp +++ b/contrib/llvm/tools/clang/lib/Lex/PPCaching.cpp @@ -35,6 +35,29 @@ void Preprocessor::CommitBacktrackedTokens() { BacktrackPositions.pop_back(); } +Preprocessor::CachedTokensRange Preprocessor::LastCachedTokenRange() { + assert(isBacktrackEnabled()); + auto PrevCachedLexPos = BacktrackPositions.back(); + return CachedTokensRange{PrevCachedLexPos, CachedLexPos}; +} + +void Preprocessor::EraseCachedTokens(CachedTokensRange TokenRange) { + assert(TokenRange.Begin <= TokenRange.End); + if (CachedLexPos == TokenRange.Begin && TokenRange.Begin != TokenRange.End) { + // We have backtracked to the start of the token range as we want to consume + // them again. Erase the tokens only after consuming then. + assert(!CachedTokenRangeToErase); + CachedTokenRangeToErase = TokenRange; + return; + } + // The cached tokens were committed, so they should be erased now. + assert(TokenRange.End == CachedLexPos); + CachedTokens.erase(CachedTokens.begin() + TokenRange.Begin, + CachedTokens.begin() + TokenRange.End); + CachedLexPos = TokenRange.Begin; + ExitCachingLexMode(); +} + // Make Preprocessor re-lex the tokens that were lexed since // EnableBacktrackAtThisPos() was previously called. void Preprocessor::Backtrack() { @@ -51,6 +74,13 @@ void Preprocessor::CachingLex(Token &Result) { if (CachedLexPos < CachedTokens.size()) { Result = CachedTokens[CachedLexPos++]; + // Erase the some of the cached tokens after they are consumed when + // asked to do so. + if (CachedTokenRangeToErase && + CachedTokenRangeToErase->End == CachedLexPos) { + EraseCachedTokens(*CachedTokenRangeToErase); + CachedTokenRangeToErase = None; + } return; } diff --git a/contrib/llvm/tools/clang/lib/Lex/PPDirectives.cpp b/contrib/llvm/tools/clang/lib/Lex/PPDirectives.cpp index 322c580..b2450f5 100644 --- a/contrib/llvm/tools/clang/lib/Lex/PPDirectives.cpp +++ b/contrib/llvm/tools/clang/lib/Lex/PPDirectives.cpp @@ -30,6 +30,7 @@ #include "clang/Lex/PPCallbacks.h" #include "clang/Lex/Pragma.h" #include "clang/Lex/Preprocessor.h" +#include "clang/Lex/PreprocessorOptions.h" #include "clang/Lex/PTHLexer.h" #include "clang/Lex/Token.h" #include "llvm/ADT/ArrayRef.h" @@ -54,35 +55,12 @@ using namespace clang; // Utility Methods for Preprocessor Directive Handling. //===----------------------------------------------------------------------===// -MacroInfo *Preprocessor::AllocateMacroInfo() { - MacroInfoChain *MIChain = BP.Allocate<MacroInfoChain>(); - MIChain->Next = MIChainHead; +MacroInfo *Preprocessor::AllocateMacroInfo(SourceLocation L) { + auto *MIChain = new (BP) MacroInfoChain{L, MIChainHead}; MIChainHead = MIChain; return &MIChain->MI; } -MacroInfo *Preprocessor::AllocateMacroInfo(SourceLocation L) { - MacroInfo *MI = AllocateMacroInfo(); - new (MI) MacroInfo(L); - return MI; -} - -MacroInfo *Preprocessor::AllocateDeserializedMacroInfo(SourceLocation L, - unsigned SubModuleID) { - static_assert(alignof(MacroInfo) >= sizeof(SubModuleID), - "alignment for MacroInfo is less than the ID"); - DeserializedMacroInfoChain *MIChain = - BP.Allocate<DeserializedMacroInfoChain>(); - MIChain->Next = DeserialMIChainHead; - DeserialMIChainHead = MIChain; - - MacroInfo *MI = &MIChain->MI; - new (MI) MacroInfo(L); - MI->FromASTFile = true; - MI->setOwningModuleID(SubModuleID); - return MI; -} - DefMacroDirective *Preprocessor::AllocateDefMacroDirective(MacroInfo *MI, SourceLocation Loc) { return new (BP) DefMacroDirective(MI, Loc); @@ -242,26 +220,18 @@ bool Preprocessor::CheckMacroName(Token &MacroNameTok, MacroUse isDefineUndef, return Diag(MacroNameTok, diag::err_pp_missing_macro_name); IdentifierInfo *II = MacroNameTok.getIdentifierInfo(); - if (!II) { - bool Invalid = false; - std::string Spelling = getSpelling(MacroNameTok, &Invalid); - if (Invalid) - return Diag(MacroNameTok, diag::err_pp_macro_not_identifier); - II = getIdentifierInfo(Spelling); - - if (!II->isCPlusPlusOperatorKeyword()) - return Diag(MacroNameTok, diag::err_pp_macro_not_identifier); + if (!II) + return Diag(MacroNameTok, diag::err_pp_macro_not_identifier); + if (II->isCPlusPlusOperatorKeyword()) { // C++ 2.5p2: Alternative tokens behave the same as its primary token // except for their spellings. Diag(MacroNameTok, getLangOpts().MicrosoftExt ? diag::ext_pp_operator_used_as_macro_name : diag::err_pp_operator_used_as_macro_name) << II << MacroNameTok.getKind(); - // Allow #defining |and| and friends for Microsoft compatibility or // recovery when legacy C headers are included in C++. - MacroNameTok.setIdentifierInfo(II); } if ((isDefineUndef != MU_Other) && II->getPPKeywordID() == tok::pp_defined) { @@ -560,7 +530,7 @@ void Preprocessor::SkipExcludedConditionalBlock(SourceLocation IfTokenLoc, assert(CurPPLexer->LexingRawMode && "We have to be skipping here!"); CurPPLexer->LexingRawMode = false; IdentifierInfo *IfNDefMacro = nullptr; - const bool CondValue = EvaluateDirectiveExpression(IfNDefMacro); + const bool CondValue = EvaluateDirectiveExpression(IfNDefMacro).Conditional; CurPPLexer->LexingRawMode = true; if (Callbacks) { const SourceLocation CondEnd = CurPPLexer->getSourceLocation(); @@ -657,7 +627,7 @@ void Preprocessor::PTHSkipExcludedConditionalBlock() { // Evaluate the condition of the #elif. IdentifierInfo *IfNDefMacro = nullptr; CurPTHLexer->ParsingPreprocessorDirective = true; - bool ShouldEnter = EvaluateDirectiveExpression(IfNDefMacro); + bool ShouldEnter = EvaluateDirectiveExpression(IfNDefMacro).Conditional; CurPTHLexer->ParsingPreprocessorDirective = false; // If this condition is true, enter it! @@ -690,24 +660,17 @@ Module *Preprocessor::getModuleForLocation(SourceLocation Loc) { : HeaderInfo.lookupModule(getLangOpts().CurrentModule); } -Module *Preprocessor::getModuleContainingLocation(SourceLocation Loc) { - return HeaderInfo.getModuleMap().inferModuleFromLocation( - FullSourceLoc(Loc, SourceMgr)); -} - const FileEntry * Preprocessor::getModuleHeaderToIncludeForDiagnostics(SourceLocation IncLoc, + Module *M, SourceLocation Loc) { + assert(M && "no module to include"); + // If we have a module import syntax, we shouldn't include a header to // make a particular module visible. if (getLangOpts().ObjC2) return nullptr; - // Figure out which module we'd want to import. - Module *M = getModuleContainingLocation(Loc); - if (!M) - return nullptr; - Module *TopM = M->getTopLevelModule(); Module *IncM = getModuleForLocation(IncLoc); @@ -719,6 +682,8 @@ Preprocessor::getModuleHeaderToIncludeForDiagnostics(SourceLocation IncLoc, while (!Loc.isInvalid() && !SM.isInMainFile(Loc)) { auto ID = SM.getFileID(SM.getExpansionLoc(Loc)); auto *FE = SM.getFileEntryForID(ID); + if (!FE) + break; bool InTextualHeader = false; for (auto Header : HeaderInfo.getModuleMap().findAllModulesForHeader(FE)) { @@ -752,16 +717,11 @@ Preprocessor::getModuleHeaderToIncludeForDiagnostics(SourceLocation IncLoc, } const FileEntry *Preprocessor::LookupFile( - SourceLocation FilenameLoc, - StringRef Filename, - bool isAngled, - const DirectoryLookup *FromDir, - const FileEntry *FromFile, - const DirectoryLookup *&CurDir, - SmallVectorImpl<char> *SearchPath, + SourceLocation FilenameLoc, StringRef Filename, bool isAngled, + const DirectoryLookup *FromDir, const FileEntry *FromFile, + const DirectoryLookup *&CurDir, SmallVectorImpl<char> *SearchPath, SmallVectorImpl<char> *RelativePath, - ModuleMap::KnownHeader *SuggestedModule, - bool SkipCache) { + ModuleMap::KnownHeader *SuggestedModule, bool *IsMapped, bool SkipCache) { Module *RequestingModule = getModuleForLocation(FilenameLoc); bool RequestingModuleIsModuleInterface = !SourceMgr.isInMainFile(FilenameLoc); @@ -819,7 +779,7 @@ const FileEntry *Preprocessor::LookupFile( while (const FileEntry *FE = HeaderInfo.LookupFile( Filename, FilenameLoc, isAngled, TmpFromDir, TmpCurDir, Includers, SearchPath, RelativePath, RequestingModule, - SuggestedModule, SkipCache)) { + SuggestedModule, /*IsMapped=*/nullptr, SkipCache)) { // Keep looking as if this file did a #include_next. TmpFromDir = TmpCurDir; ++TmpFromDir; @@ -835,7 +795,7 @@ const FileEntry *Preprocessor::LookupFile( // Do a standard file entry lookup. const FileEntry *FE = HeaderInfo.LookupFile( Filename, FilenameLoc, isAngled, FromDir, CurDir, Includers, SearchPath, - RelativePath, RequestingModule, SuggestedModule, SkipCache, + RelativePath, RequestingModule, SuggestedModule, IsMapped, SkipCache, BuildSystemModule); if (FE) { if (SuggestedModule && !LangOpts.AsmPreprocessor) @@ -1206,18 +1166,26 @@ void Preprocessor::HandleLineDirective() { CheckEndOfDirective("line", true); } - SourceMgr.AddLineNote(DigitTok.getLocation(), LineNo, FilenameID); + // Take the file kind of the file containing the #line directive. #line + // directives are often used for generated sources from the same codebase, so + // the new file should generally be classified the same way as the current + // file. This is visible in GCC's pre-processed output, which rewrites #line + // to GNU line markers. + SrcMgr::CharacteristicKind FileKind = + SourceMgr.getFileCharacteristic(DigitTok.getLocation()); + + SourceMgr.AddLineNote(DigitTok.getLocation(), LineNo, FilenameID, false, + false, FileKind); if (Callbacks) Callbacks->FileChanged(CurPPLexer->getSourceLocation(), - PPCallbacks::RenameFile, - SrcMgr::C_User); + PPCallbacks::RenameFile, FileKind); } /// ReadLineMarkerFlags - Parse and validate any flags at the end of a GNU line /// marker directive. static bool ReadLineMarkerFlags(bool &IsFileEntry, bool &IsFileExit, - bool &IsSystemHeader, bool &IsExternCHeader, + SrcMgr::CharacteristicKind &FileKind, Preprocessor &PP) { unsigned FlagVal; Token FlagTok; @@ -1268,7 +1236,7 @@ static bool ReadLineMarkerFlags(bool &IsFileEntry, bool &IsFileExit, return true; } - IsSystemHeader = true; + FileKind = SrcMgr::C_System; PP.Lex(FlagTok); if (FlagTok.is(tok::eod)) return false; @@ -1282,7 +1250,7 @@ static bool ReadLineMarkerFlags(bool &IsFileEntry, bool &IsFileExit, return true; } - IsExternCHeader = true; + FileKind = SrcMgr::C_ExternCSystem; PP.Lex(FlagTok); if (FlagTok.is(tok::eod)) return false; @@ -1312,14 +1280,15 @@ void Preprocessor::HandleDigitDirective(Token &DigitTok) { Lex(StrTok); bool IsFileEntry = false, IsFileExit = false; - bool IsSystemHeader = false, IsExternCHeader = false; int FilenameID = -1; + SrcMgr::CharacteristicKind FileKind = SrcMgr::C_User; // If the StrTok is "eod", then it wasn't present. Otherwise, it must be a // string followed by eod. - if (StrTok.is(tok::eod)) - ; // ok - else if (StrTok.isNot(tok::string_literal)) { + if (StrTok.is(tok::eod)) { + // Treat this like "#line NN", which doesn't change file characteristics. + FileKind = SourceMgr.getFileCharacteristic(DigitTok.getLocation()); + } else if (StrTok.isNot(tok::string_literal)) { Diag(StrTok, diag::err_pp_linemarker_invalid_filename); return DiscardUntilEndOfDirective(); } else if (StrTok.hasUDSuffix()) { @@ -1338,15 +1307,13 @@ void Preprocessor::HandleDigitDirective(Token &DigitTok) { FilenameID = SourceMgr.getLineTableFilenameID(Literal.GetString()); // If a filename was present, read any flags that are present. - if (ReadLineMarkerFlags(IsFileEntry, IsFileExit, - IsSystemHeader, IsExternCHeader, *this)) + if (ReadLineMarkerFlags(IsFileEntry, IsFileExit, FileKind, *this)) return; } // Create a line note with this information. - SourceMgr.AddLineNote(DigitTok.getLocation(), LineNo, FilenameID, - IsFileEntry, IsFileExit, - IsSystemHeader, IsExternCHeader); + SourceMgr.AddLineNote(DigitTok.getLocation(), LineNo, FilenameID, IsFileEntry, + IsFileExit, FileKind); // If the preprocessor has callbacks installed, notify them of the #line // change. This is used so that the line marker comes out in -E mode for @@ -1357,11 +1324,6 @@ void Preprocessor::HandleDigitDirective(Token &DigitTok) { Reason = PPCallbacks::EnterFile; else if (IsFileExit) Reason = PPCallbacks::ExitFile; - SrcMgr::CharacteristicKind FileKind = SrcMgr::C_User; - if (IsExternCHeader) - FileKind = SrcMgr::C_ExternCSystem; - else if (IsSystemHeader) - FileKind = SrcMgr::C_System; Callbacks->FileChanged(CurPPLexer->getSourceLocation(), Reason, FileKind); } @@ -1593,18 +1555,18 @@ bool Preprocessor::ConcatenateIncludeName(SmallString<128> &FilenameBuffer, } /// \brief Push a token onto the token stream containing an annotation. -static void EnterAnnotationToken(Preprocessor &PP, - SourceLocation Begin, SourceLocation End, - tok::TokenKind Kind, void *AnnotationVal) { +void Preprocessor::EnterAnnotationToken(SourceRange Range, + tok::TokenKind Kind, + void *AnnotationVal) { // FIXME: Produce this as the current token directly, rather than // allocating a new token for it. auto Tok = llvm::make_unique<Token[]>(1); Tok[0].startToken(); Tok[0].setKind(Kind); - Tok[0].setLocation(Begin); - Tok[0].setAnnotationEndLoc(End); + Tok[0].setLocation(Range.getBegin()); + Tok[0].setAnnotationEndLoc(Range.getEnd()); Tok[0].setAnnotationValue(AnnotationVal); - PP.EnterTokenStream(std::move(Tok), 1, true); + EnterTokenStream(std::move(Tok), 1, true); } /// \brief Produce a diagnostic informing the user that a #include or similar @@ -1685,6 +1647,26 @@ static bool trySimplifyPath(SmallVectorImpl<StringRef> &Components, return SuggestReplacement; } +bool Preprocessor::checkModuleIsAvailable(const LangOptions &LangOpts, + const TargetInfo &TargetInfo, + DiagnosticsEngine &Diags, Module *M) { + Module::Requirement Requirement; + Module::UnresolvedHeaderDirective MissingHeader; + if (M->isAvailable(LangOpts, TargetInfo, Requirement, MissingHeader)) + return false; + + if (MissingHeader.FileNameLoc.isValid()) { + Diags.Report(MissingHeader.FileNameLoc, diag::err_module_header_missing) + << MissingHeader.IsUmbrella << MissingHeader.FileName; + } else { + // FIXME: Track the location at which the requirement was specified, and + // use it here. + Diags.Report(M->DefinitionLoc, diag::err_module_unavailable) + << M->getFullModuleName() << Requirement.second << Requirement.first; + } + return true; +} + /// HandleIncludeDirective - The "\#include" tokens have just been read, read /// the file to be included from the lexer, then include it! This is a common /// routine with functionality shared between \#include, \#include_next and @@ -1783,6 +1765,7 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc, } // Search include directories. + bool IsMapped = false; const DirectoryLookup *CurDir; SmallString<1024> SearchPath; SmallString<1024> RelativePath; @@ -1801,7 +1784,7 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc, FilenameLoc, LangOpts.MSVCCompat ? NormalizedPath.c_str() : Filename, isAngled, LookupFrom, LookupFromFile, CurDir, Callbacks ? &SearchPath : nullptr, Callbacks ? &RelativePath : nullptr, - &SuggestedModule); + &SuggestedModule, &IsMapped); if (!File) { if (Callbacks) { @@ -1818,7 +1801,7 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc, FilenameLoc, LangOpts.MSVCCompat ? NormalizedPath.c_str() : Filename, isAngled, LookupFrom, LookupFromFile, CurDir, nullptr, nullptr, - &SuggestedModule, /*SkipCache*/ true); + &SuggestedModule, &IsMapped, /*SkipCache*/ true); } } } @@ -1833,8 +1816,7 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc, LangOpts.MSVCCompat ? NormalizedPath.c_str() : Filename, false, LookupFrom, LookupFromFile, CurDir, Callbacks ? &SearchPath : nullptr, - Callbacks ? &RelativePath : nullptr, - &SuggestedModule); + Callbacks ? &RelativePath : nullptr, &SuggestedModule, &IsMapped); if (File) { SourceRange Range(FilenameTok.getLocation(), CharEnd); Diag(FilenameTok, diag::err_pp_file_not_found_not_fatal) << @@ -1856,33 +1838,24 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc, // we've imported or already built. bool ShouldEnter = true; + if (PPOpts->SingleFileParseMode) + ShouldEnter = false; + // Determine whether we should try to import the module for this #include, if // there is one. Don't do so if precompiled module support is disabled or we // are processing this module textually (because we're building the module). - if (File && SuggestedModule && getLangOpts().Modules && + if (ShouldEnter && File && SuggestedModule && getLangOpts().Modules && SuggestedModule.getModule()->getTopLevelModuleName() != getLangOpts().CurrentModule) { // If this include corresponds to a module but that module is // unavailable, diagnose the situation and bail out. // FIXME: Remove this; loadModule does the same check (but produces // slightly worse diagnostics). - if (!SuggestedModule.getModule()->isAvailable()) { - Module::Requirement Requirement; - Module::UnresolvedHeaderDirective MissingHeader; - Module *M = SuggestedModule.getModule(); - // Identify the cause. - (void)M->isAvailable(getLangOpts(), getTargetInfo(), Requirement, - MissingHeader); - if (MissingHeader.FileNameLoc.isValid()) { - Diag(MissingHeader.FileNameLoc, diag::err_module_header_missing) - << MissingHeader.IsUmbrella << MissingHeader.FileName; - } else { - Diag(M->DefinitionLoc, diag::err_module_unavailable) - << M->getFullModuleName() << Requirement.second << Requirement.first; - } + if (checkModuleIsAvailable(getLangOpts(), getTargetInfo(), getDiagnostics(), + SuggestedModule.getModule())) { Diag(FilenameTok.getLocation(), diag::note_implicit_top_level_module_import_here) - << M->getTopLevelModuleName(); + << SuggestedModule.getModule()->getTopLevelModuleName(); return; } @@ -1939,6 +1912,25 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc, } } + // The #included file will be considered to be a system header if either it is + // in a system include directory, or if the #includer is a system include + // header. + SrcMgr::CharacteristicKind FileCharacter = + SourceMgr.getFileCharacteristic(FilenameTok.getLocation()); + if (File) + FileCharacter = std::max(HeaderInfo.getFileDirFlavor(File), FileCharacter); + + // Ask HeaderInfo if we should enter this #include file. If not, #including + // this file will have no effect. + bool SkipHeader = false; + if (ShouldEnter && File && + !HeaderInfo.ShouldEnterIncludeFile(*this, File, isImport, + getLangOpts().Modules, + SuggestedModule.getModule())) { + ShouldEnter = false; + SkipHeader = true; + } + if (Callbacks) { // Notify the callback object that we've seen an inclusion directive. Callbacks->InclusionDirective( @@ -1946,25 +1938,20 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc, LangOpts.MSVCCompat ? NormalizedPath.c_str() : Filename, isAngled, FilenameRange, File, SearchPath, RelativePath, ShouldEnter ? nullptr : SuggestedModule.getModule()); + if (SkipHeader && !SuggestedModule.getModule()) + Callbacks->FileSkipped(*File, FilenameTok, FileCharacter); } if (!File) return; - // The #included file will be considered to be a system header if either it is - // in a system include directory, or if the #includer is a system include - // header. - SrcMgr::CharacteristicKind FileCharacter = - std::max(HeaderInfo.getFileDirFlavor(File), - SourceMgr.getFileCharacteristic(FilenameTok.getLocation())); - // FIXME: If we have a suggested module, and we've already visited this file, // don't bother entering it again. We know it has no further effect. // Issue a diagnostic if the name of the file on disk has a different case // than the one we're about to open. const bool CheckIncludePathPortability = - File && !File->tryGetRealPathName().empty(); + !IsMapped && File && !File->tryGetRealPathName().empty(); if (CheckIncludePathPortability) { StringRef Name = LangOpts.MSVCCompat ? NormalizedPath.str() : Filename; @@ -1976,37 +1963,27 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc, SmallString<128> Path; Path.reserve(Name.size()+2); Path.push_back(isAngled ? '<' : '"'); + bool isLeadingSeparator = llvm::sys::path::is_absolute(Name); for (auto Component : Components) { - Path.append(Component); + if (isLeadingSeparator) + isLeadingSeparator = false; + else + Path.append(Component); // Append the separator the user used, or the close quote Path.push_back( Path.size() <= Filename.size() ? Filename[Path.size()-1] : (isAngled ? '>' : '"')); } - auto Replacement = Path.str().str(); // For user files and known standard headers, by default we issue a diagnostic. // For other system headers, we don't. They can be controlled separately. auto DiagId = (FileCharacter == SrcMgr::C_User || warnByDefaultOnWrongCase(Name)) ? diag::pp_nonportable_path : diag::pp_nonportable_system_path; SourceRange Range(FilenameTok.getLocation(), CharEnd); - Diag(FilenameTok, DiagId) << Replacement << - FixItHint::CreateReplacement(Range, Replacement); + Diag(FilenameTok, DiagId) << Path << + FixItHint::CreateReplacement(Range, Path); } } - // Ask HeaderInfo if we should enter this #include file. If not, #including - // this file will have no effect. - bool SkipHeader = false; - if (ShouldEnter && - !HeaderInfo.ShouldEnterIncludeFile(*this, File, isImport, - getLangOpts().Modules, - SuggestedModule.getModule())) { - ShouldEnter = false; - SkipHeader = true; - if (Callbacks) - Callbacks->FileSkipped(*File, FilenameTok, FileCharacter); - } - // If we don't need to enter the file, stop now. if (!ShouldEnter) { // If this is a module import, make it visible if needed. @@ -2023,7 +2000,8 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc, if (IncludeTok.getIdentifierInfo()->getPPKeywordID() != tok::pp___include_macros) - EnterAnnotationToken(*this, HashLoc, End, tok::annot_module_include, M); + EnterAnnotationToken(SourceRange(HashLoc, End), + tok::annot_module_include, M); } return; } @@ -2050,18 +2028,18 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc, M->getTopLevelModuleName() == getLangOpts().CurrentModule) return; - assert(!CurSubmodule && "should not have marked this as a module yet"); - CurSubmodule = M; + assert(!CurLexerSubmodule && "should not have marked this as a module yet"); + CurLexerSubmodule = M; // Let the macro handling code know that any future macros are within // the new submodule. - EnterSubmodule(M, HashLoc); + EnterSubmodule(M, HashLoc, /*ForPragma*/false); // Let the parser know that any future declarations are within the new // submodule. // FIXME: There's no point doing this if we're handling a #__include_macros // directive. - EnterAnnotationToken(*this, HashLoc, End, tok::annot_module_begin, M); + EnterAnnotationToken(SourceRange(HashLoc, End), tok::annot_module_begin, M); } } @@ -2083,7 +2061,7 @@ void Preprocessor::HandleIncludeNextDirective(SourceLocation HashLoc, } else if (isInPrimaryFile()) { Lookup = nullptr; Diag(IncludeNextTok, diag::pp_include_next_in_primary); - } else if (CurSubmodule) { + } else if (CurLexerSubmodule) { // Start looking up in the directory *after* the one in which the current // file would be found, if any. assert(CurPPLexer && "#include_next directive in macro?"); @@ -2157,11 +2135,11 @@ void Preprocessor::HandleIncludeMacrosDirective(SourceLocation HashLoc, // Preprocessor Macro Directive Handling. //===----------------------------------------------------------------------===// -/// ReadMacroDefinitionArgList - The ( starting an argument list of a macro +/// ReadMacroParameterList - The ( starting an argument list of a macro /// definition has just been read. Lex the rest of the arguments and the /// closing ), updating MI with what we learn. Return true if an error occurs /// parsing the arg list. -bool Preprocessor::ReadMacroDefinitionArgList(MacroInfo *MI, Token &Tok) { +bool Preprocessor::ReadMacroParameterList(MacroInfo *MI, Token &Tok) { SmallVector<IdentifierInfo*, 32> Arguments; while (true) { @@ -2195,7 +2173,7 @@ bool Preprocessor::ReadMacroDefinitionArgList(MacroInfo *MI, Token &Tok) { // Add the __VA_ARGS__ identifier as an argument. Arguments.push_back(Ident__VA_ARGS__); MI->setIsC99Varargs(); - MI->setArgumentList(Arguments, BP); + MI->setParameterList(Arguments, BP); return false; case tok::eod: // #define X( Diag(Tok, diag::err_pp_missing_rparen_in_macro_def); @@ -2229,7 +2207,7 @@ bool Preprocessor::ReadMacroDefinitionArgList(MacroInfo *MI, Token &Tok) { Diag(Tok, diag::err_pp_expected_comma_in_arg_list); return true; case tok::r_paren: // #define X(A) - MI->setArgumentList(Arguments, BP); + MI->setParameterList(Arguments, BP); return false; case tok::comma: // #define X(A, break; @@ -2245,7 +2223,7 @@ bool Preprocessor::ReadMacroDefinitionArgList(MacroInfo *MI, Token &Tok) { } MI->setIsGNUVarargs(); - MI->setArgumentList(Arguments, BP); + MI->setParameterList(Arguments, BP); return false; } } @@ -2294,28 +2272,20 @@ static bool isConfigurationPattern(Token &MacroName, MacroInfo *MI, MI->getNumTokens() == 0; } -/// HandleDefineDirective - Implements \#define. This consumes the entire macro -/// line then lets the caller lex the next real token. -void Preprocessor::HandleDefineDirective(Token &DefineTok, - bool ImmediatelyAfterHeaderGuard) { - ++NumDefined; - - Token MacroNameTok; - bool MacroShadowsKeyword; - ReadMacroName(MacroNameTok, MU_Define, &MacroShadowsKeyword); +// ReadOptionalMacroParameterListAndBody - This consumes all (i.e. the +// entire line) of the macro's tokens and adds them to MacroInfo, and while +// doing so performs certain validity checks including (but not limited to): +// - # (stringization) is followed by a macro parameter +// +// Returns a nullptr if an invalid sequence of tokens is encountered or returns +// a pointer to a MacroInfo object. - // Error reading macro name? If so, diagnostic already issued. - if (MacroNameTok.is(tok::eod)) - return; +MacroInfo *Preprocessor::ReadOptionalMacroParameterListAndBody( + const Token &MacroNameTok, const bool ImmediatelyAfterHeaderGuard) { Token LastTok = MacroNameTok; - - // If we are supposed to keep comments in #defines, reenable comment saving - // mode. - if (CurLexer) CurLexer->SetCommentRetentionState(KeepMacroComments); - // Create the new macro. - MacroInfo *MI = AllocateMacroInfo(MacroNameTok.getLocation()); + MacroInfo *const MI = AllocateMacroInfo(MacroNameTok.getLocation()); Token Tok; LexUnexpandedToken(Tok); @@ -2337,11 +2307,11 @@ void Preprocessor::HandleDefineDirective(Token &DefineTok, } else if (Tok.is(tok::l_paren)) { // This is a function-like macro definition. Read the argument list. MI->setIsFunctionLike(); - if (ReadMacroDefinitionArgList(MI, LastTok)) { + if (ReadMacroParameterList(MI, LastTok)) { // Throw away the rest of the line. if (CurPPLexer->ParsingPreprocessorDirective) DiscardUntilEndOfDirective(); - return; + return nullptr; } // If this is a definition of a variadic C99 function-like macro, not using @@ -2448,7 +2418,7 @@ void Preprocessor::HandleDefineDirective(Token &DefineTok, // Check for a valid macro arg identifier. if (Tok.getIdentifierInfo() == nullptr || - MI->getArgumentNum(Tok.getIdentifierInfo()) == -1) { + MI->getParameterNum(Tok.getIdentifierInfo()) == -1) { // If this is assembler-with-cpp mode, we accept random gibberish after // the '#' because '#' is often a comment character. However, change @@ -2464,7 +2434,7 @@ void Preprocessor::HandleDefineDirective(Token &DefineTok, // Disable __VA_ARGS__ again. Ident__VA_ARGS__->setIsPoisoned(true); - return; + return nullptr; } } @@ -2477,15 +2447,39 @@ void Preprocessor::HandleDefineDirective(Token &DefineTok, LexUnexpandedToken(Tok); } } + MI->setDefinitionEndLoc(LastTok.getLocation()); + // Disable __VA_ARGS__ again. + Ident__VA_ARGS__->setIsPoisoned(true); + + return MI; +} +/// HandleDefineDirective - Implements \#define. This consumes the entire macro +/// line then lets the caller lex the next real token. +void Preprocessor::HandleDefineDirective( + Token &DefineTok, const bool ImmediatelyAfterHeaderGuard) { + ++NumDefined; + + Token MacroNameTok; + bool MacroShadowsKeyword; + ReadMacroName(MacroNameTok, MU_Define, &MacroShadowsKeyword); + + // Error reading macro name? If so, diagnostic already issued. + if (MacroNameTok.is(tok::eod)) + return; + + // If we are supposed to keep comments in #defines, reenable comment saving + // mode. + if (CurLexer) CurLexer->SetCommentRetentionState(KeepMacroComments); + + MacroInfo *const MI = ReadOptionalMacroParameterListAndBody( + MacroNameTok, ImmediatelyAfterHeaderGuard); + + if (!MI) return; if (MacroShadowsKeyword && !isConfigurationPattern(MacroNameTok, MI, getLangOpts())) { Diag(MacroNameTok, diag::warn_pp_macro_hides_keyword); - } - - // Disable __VA_ARGS__ again. - Ident__VA_ARGS__->setIsPoisoned(true); - + } // Check that there is no paste (##) operator at the beginning or end of the // replacement list. unsigned NumTokens = MI->getNumTokens(); @@ -2500,7 +2494,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 issue diagnostics if they are not. @@ -2589,25 +2583,26 @@ void Preprocessor::HandleUndefDirective() { // Okay, we have a valid identifier to undef. auto *II = MacroNameTok.getIdentifierInfo(); auto MD = getMacroDefinition(II); + UndefMacroDirective *Undef = nullptr; + + // If the macro is not defined, this is a noop undef. + if (const MacroInfo *MI = MD.getMacroInfo()) { + if (!MI->isUsed() && MI->isWarnIfUnused()) + Diag(MI->getDefinitionLoc(), diag::pp_macro_not_used); + + if (MI->isWarnIfUnused()) + WarnUnusedMacroLocs.erase(MI->getDefinitionLoc()); + + Undef = AllocateUndefMacroDirective(MacroNameTok.getLocation()); + } // If the callbacks want to know, tell them about the macro #undef. // Note: no matter if the macro was defined or not. if (Callbacks) - Callbacks->MacroUndefined(MacroNameTok, MD); - - // If the macro is not defined, this is a noop undef, just return. - const MacroInfo *MI = MD.getMacroInfo(); - if (!MI) - return; + Callbacks->MacroUndefined(MacroNameTok, MD, Undef); - if (!MI->isUsed() && MI->isWarnIfUnused()) - Diag(MI->getDefinitionLoc(), diag::pp_macro_not_used); - - if (MI->isWarnIfUnused()) - WarnUnusedMacroLocs.erase(MI->getDefinitionLoc()); - - appendMacroDirective(MacroNameTok.getIdentifierInfo(), - AllocateUndefMacroDirective(MacroNameTok.getLocation())); + if (Undef) + appendMacroDirective(II, Undef); } //===----------------------------------------------------------------------===// @@ -2667,7 +2662,13 @@ void Preprocessor::HandleIfdefDirective(Token &Result, bool isIfndef, } // Should we include the stuff contained by this directive? - if (!MI == isIfndef) { + if (PPOpts->SingleFileParseMode && !MI) { + // In 'single-file-parse mode' undefined identifiers trigger parsing of all + // the directive blocks. + CurPPLexer->pushConditionalLevel(DirectiveTok.getLocation(), + /*wasskip*/false, /*foundnonskip*/false, + /*foundelse*/false); + } else if (!MI == isIfndef) { // Yes, remember that we are inside a conditional, then lex the next token. CurPPLexer->pushConditionalLevel(DirectiveTok.getLocation(), /*wasskip*/false, /*foundnonskip*/true, @@ -2689,7 +2690,8 @@ void Preprocessor::HandleIfDirective(Token &IfToken, // Parse and evaluate the conditional expression. IdentifierInfo *IfNDefMacro = nullptr; const SourceLocation ConditionalBegin = CurPPLexer->getSourceLocation(); - const bool ConditionalTrue = EvaluateDirectiveExpression(IfNDefMacro); + const DirectiveEvalResult DER = EvaluateDirectiveExpression(IfNDefMacro); + const bool ConditionalTrue = DER.Conditional; const SourceLocation ConditionalEnd = CurPPLexer->getSourceLocation(); // If this condition is equivalent to #ifndef X, and if this is the first @@ -2708,7 +2710,12 @@ void Preprocessor::HandleIfDirective(Token &IfToken, (ConditionalTrue ? PPCallbacks::CVK_True : PPCallbacks::CVK_False)); // Should we include the stuff contained by this directive? - if (ConditionalTrue) { + if (PPOpts->SingleFileParseMode && DER.IncludedUndefinedIds) { + // In 'single-file-parse mode' undefined identifiers trigger parsing of all + // the directive blocks. + CurPPLexer->pushConditionalLevel(IfToken.getLocation(), /*wasskip*/false, + /*foundnonskip*/false, /*foundelse*/false); + } else if (ConditionalTrue) { // Yes, remember that we are inside a conditional, then lex the next token. CurPPLexer->pushConditionalLevel(IfToken.getLocation(), /*wasskip*/false, /*foundnonskip*/true, /*foundelse*/false); @@ -2769,6 +2776,14 @@ void Preprocessor::HandleElseDirective(Token &Result) { if (Callbacks) Callbacks->Else(Result.getLocation(), CI.IfLoc); + if (PPOpts->SingleFileParseMode && !CI.FoundNonSkip) { + // In 'single-file-parse mode' undefined identifiers trigger parsing of all + // the directive blocks. + CurPPLexer->pushConditionalLevel(CI.IfLoc, /*wasskip*/false, + /*foundnonskip*/false, /*foundelse*/true); + return; + } + // Finally, skip the rest of the contents of this block. SkipExcludedConditionalBlock(CI.IfLoc, /*Foundnonskip*/true, /*FoundElse*/true, Result.getLocation()); @@ -2804,6 +2819,14 @@ void Preprocessor::HandleElifDirective(Token &ElifToken) { SourceRange(ConditionalBegin, ConditionalEnd), PPCallbacks::CVK_NotEvaluated, CI.IfLoc); + if (PPOpts->SingleFileParseMode && !CI.FoundNonSkip) { + // In 'single-file-parse mode' undefined identifiers trigger parsing of all + // the directive blocks. + CurPPLexer->pushConditionalLevel(ElifToken.getLocation(), /*wasskip*/false, + /*foundnonskip*/false, /*foundelse*/false); + return; + } + // Finally, skip the rest of the contents of this block. SkipExcludedConditionalBlock(CI.IfLoc, /*Foundnonskip*/true, /*FoundElse*/CI.FoundElse, diff --git a/contrib/llvm/tools/clang/lib/Lex/PPExpressions.cpp b/contrib/llvm/tools/clang/lib/Lex/PPExpressions.cpp index 862a471..d843182 100644 --- a/contrib/llvm/tools/clang/lib/Lex/PPExpressions.cpp +++ b/contrib/llvm/tools/clang/lib/Lex/PPExpressions.cpp @@ -73,6 +73,7 @@ public: static bool EvaluateDirectiveSubExpr(PPValue &LHS, unsigned MinPrec, Token &PeekTok, bool ValueLive, + bool &IncludedUndefinedIds, Preprocessor &PP); /// DefinedTracker - This struct is used while parsing expressions to keep track @@ -93,6 +94,7 @@ struct DefinedTracker { /// TheMacro - When the state is DefinedMacro or NotDefinedMacro, this /// indicates the macro that was checked. IdentifierInfo *TheMacro; + bool IncludedUndefinedIds = false; }; /// EvaluateDefined - Process a 'defined(sym)' expression. @@ -128,6 +130,7 @@ static bool EvaluateDefined(PPValue &Result, Token &PeekTok, DefinedTracker &DT, MacroDefinition Macro = PP.getMacroDefinition(II); Result.Val = !!Macro; Result.Val.setIsUnsigned(false); // Result is signed intmax_t. + DT.IncludedUndefinedIds = !Macro; // If there is a macro, mark it used. if (Result.Val != 0 && ValueLive) @@ -234,33 +237,32 @@ static bool EvaluateValue(PPValue &Result, Token &PeekTok, DefinedTracker &DT, PP.setCodeCompletionReached(); PP.LexNonComment(PeekTok); } - - // If this token's spelling is a pp-identifier, check to see if it is - // 'defined' or if it is a macro. Note that we check here because many - // keywords are pp-identifiers, so we can't check the kind. - if (IdentifierInfo *II = PeekTok.getIdentifierInfo()) { - // Handle "defined X" and "defined(X)". - if (II->isStr("defined")) - return EvaluateDefined(Result, PeekTok, DT, ValueLive, PP); - - // If this identifier isn't 'defined' or one of the special - // 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 && - 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. - Result.setIdentifier(II); - Result.setRange(PeekTok.getLocation()); - PP.LexNonComment(PeekTok); - return false; - } switch (PeekTok.getKind()) { - default: // Non-value token. + default: + // If this token's spelling is a pp-identifier, check to see if it is + // 'defined' or if it is a macro. Note that we check here because many + // keywords are pp-identifiers, so we can't check the kind. + if (IdentifierInfo *II = PeekTok.getIdentifierInfo()) { + // Handle "defined X" and "defined(X)". + if (II->isStr("defined")) + return EvaluateDefined(Result, PeekTok, DT, ValueLive, PP); + + if (!II->isCPlusPlusOperatorKeyword()) { + // If this identifier isn't 'defined' or one of the special + // preprocessor keywords and it wasn't macro expanded, it turns + // into a simple 0 + if (ValueLive) + PP.Diag(PeekTok, diag::warn_pp_undef_identifier) << II; + Result.Val = 0; + Result.Val.setIsUnsigned(false); // "0" is signed intmax_t 0. + Result.setIdentifier(II); + Result.setRange(PeekTok.getLocation()); + DT.IncludedUndefinedIds = true; + PP.LexNonComment(PeekTok); + return false; + } + } PP.Diag(PeekTok, diag::err_pp_expr_bad_token_start_expr); return true; case tok::eod: @@ -400,7 +402,8 @@ static bool EvaluateValue(PPValue &Result, Token &PeekTok, DefinedTracker &DT, // Just use DT unmodified as our result. } else { // Otherwise, we have something like (x+y), and we consumed '(x'. - if (EvaluateDirectiveSubExpr(Result, 1, PeekTok, ValueLive, PP)) + if (EvaluateDirectiveSubExpr(Result, 1, PeekTok, ValueLive, + DT.IncludedUndefinedIds, PP)) return true; if (PeekTok.isNot(tok::r_paren)) { @@ -475,6 +478,14 @@ static bool EvaluateValue(PPValue &Result, Token &PeekTok, DefinedTracker &DT, DT.State = DefinedTracker::DefinedMacro; return false; } + case tok::kw_true: + case tok::kw_false: + Result.Val = PeekTok.getKind() == tok::kw_true; + Result.Val.setIsUnsigned(false); // "0" is signed intmax_t 0. + Result.setIdentifier(PeekTok.getIdentifierInfo()); + Result.setRange(PeekTok.getLocation()); + PP.LexNonComment(PeekTok); + return false; // FIXME: Handle #assert } @@ -532,6 +543,7 @@ static void diagnoseUnexpectedOperator(Preprocessor &PP, PPValue &LHS, /// evaluation, such as division by zero warnings. static bool EvaluateDirectiveSubExpr(PPValue &LHS, unsigned MinPrec, Token &PeekTok, bool ValueLive, + bool &IncludedUndefinedIds, Preprocessor &PP) { unsigned PeekPrec = getPrecedence(PeekTok.getKind()); // If this token isn't valid, report the error. @@ -571,6 +583,7 @@ static bool EvaluateDirectiveSubExpr(PPValue &LHS, unsigned MinPrec, // Parse the RHS of the operator. DefinedTracker DT; if (EvaluateValue(RHS, PeekTok, DT, RHSIsLive, PP)) return true; + IncludedUndefinedIds = DT.IncludedUndefinedIds; // Remember the precedence of this operator and get the precedence of the // operator immediately to the right of the RHS. @@ -601,7 +614,8 @@ static bool EvaluateDirectiveSubExpr(PPValue &LHS, unsigned MinPrec, RHSPrec = ThisPrec+1; if (PeekPrec >= RHSPrec) { - if (EvaluateDirectiveSubExpr(RHS, RHSPrec, PeekTok, RHSIsLive, PP)) + if (EvaluateDirectiveSubExpr(RHS, RHSPrec, PeekTok, RHSIsLive, + IncludedUndefinedIds, PP)) return true; PeekPrec = getPrecedence(PeekTok.getKind()); } @@ -769,7 +783,8 @@ static bool EvaluateDirectiveSubExpr(PPValue &LHS, unsigned MinPrec, // Parse anything after the : with the same precedence as ?. We allow // things of equal precedence because ?: is right associative. if (EvaluateDirectiveSubExpr(AfterColonVal, ThisPrec, - PeekTok, AfterColonLive, PP)) + PeekTok, AfterColonLive, + IncludedUndefinedIds, PP)) return true; // Now that we have the condition, the LHS and the RHS of the :, evaluate. @@ -806,7 +821,8 @@ static bool EvaluateDirectiveSubExpr(PPValue &LHS, unsigned MinPrec, /// EvaluateDirectiveExpression - Evaluate an integer constant expression that /// may occur after a #if or #elif directive. If the expression is equivalent /// to "!defined(X)" return X in IfNDefMacro. -bool Preprocessor::EvaluateDirectiveExpression(IdentifierInfo *&IfNDefMacro) { +Preprocessor::DirectiveEvalResult +Preprocessor::EvaluateDirectiveExpression(IdentifierInfo *&IfNDefMacro) { SaveAndRestore<bool> PPDir(ParsingIfOrElifDirective, true); // Save the current state of 'DisableMacroExpansion' and reset it to false. If // 'DisableMacroExpansion' is true, then we must be in a macro argument list @@ -833,7 +849,7 @@ bool Preprocessor::EvaluateDirectiveExpression(IdentifierInfo *&IfNDefMacro) { // Restore 'DisableMacroExpansion'. DisableMacroExpansion = DisableMacroExpansionAtStartOfDirective; - return false; + return {false, DT.IncludedUndefinedIds}; } // If we are at the end of the expression after just parsing a value, there @@ -847,20 +863,20 @@ bool Preprocessor::EvaluateDirectiveExpression(IdentifierInfo *&IfNDefMacro) { // Restore 'DisableMacroExpansion'. DisableMacroExpansion = DisableMacroExpansionAtStartOfDirective; - return ResVal.Val != 0; + return {ResVal.Val != 0, DT.IncludedUndefinedIds}; } // Otherwise, we must have a binary operator (e.g. "#if 1 < 2"), so parse the // operator and the stuff after it. if (EvaluateDirectiveSubExpr(ResVal, getPrecedence(tok::question), - Tok, true, *this)) { + Tok, true, DT.IncludedUndefinedIds, *this)) { // Parse error, skip the rest of the macro line. if (Tok.isNot(tok::eod)) DiscardUntilEndOfDirective(); // Restore 'DisableMacroExpansion'. DisableMacroExpansion = DisableMacroExpansionAtStartOfDirective; - return false; + return {false, DT.IncludedUndefinedIds}; } // If we aren't at the tok::eod token, something bad happened, like an extra @@ -872,5 +888,5 @@ bool Preprocessor::EvaluateDirectiveExpression(IdentifierInfo *&IfNDefMacro) { // Restore 'DisableMacroExpansion'. DisableMacroExpansion = DisableMacroExpansionAtStartOfDirective; - return ResVal.Val != 0; + return {ResVal.Val != 0, DT.IncludedUndefinedIds}; } diff --git a/contrib/llvm/tools/clang/lib/Lex/PPLexerChange.cpp b/contrib/llvm/tools/clang/lib/Lex/PPLexerChange.cpp index 4db17c3..36d7028 100644 --- a/contrib/llvm/tools/clang/lib/Lex/PPLexerChange.cpp +++ b/contrib/llvm/tools/clang/lib/Lex/PPLexerChange.cpp @@ -117,7 +117,7 @@ void Preprocessor::EnterSourceFileWithLexer(Lexer *TheLexer, CurLexer.reset(TheLexer); CurPPLexer = TheLexer; CurDirLookup = CurDir; - CurSubmodule = nullptr; + CurLexerSubmodule = nullptr; if (CurLexerKind != CLK_LexAfterModuleImport) CurLexerKind = CLK_Lexer; @@ -142,7 +142,7 @@ void Preprocessor::EnterSourceFileWithPTH(PTHLexer *PL, CurDirLookup = CurDir; CurPTHLexer.reset(PL); CurPPLexer = CurPTHLexer.get(); - CurSubmodule = nullptr; + CurLexerSubmodule = nullptr; if (CurLexerKind != CLK_LexAfterModuleImport) CurLexerKind = CLK_PTHLexer; @@ -287,6 +287,48 @@ const char *Preprocessor::getCurLexerEndPos() { return EndPos; } +static void collectAllSubModulesWithUmbrellaHeader( + const Module &Mod, SmallVectorImpl<const Module *> &SubMods) { + if (Mod.getUmbrellaHeader()) + SubMods.push_back(&Mod); + for (auto *M : Mod.submodules()) + collectAllSubModulesWithUmbrellaHeader(*M, SubMods); +} + +void Preprocessor::diagnoseMissingHeaderInUmbrellaDir(const Module &Mod) { + assert(Mod.getUmbrellaHeader() && "Module must use umbrella header"); + SourceLocation StartLoc = + SourceMgr.getLocForStartOfFile(SourceMgr.getMainFileID()); + if (getDiagnostics().isIgnored(diag::warn_uncovered_module_header, StartLoc)) + return; + + ModuleMap &ModMap = getHeaderSearchInfo().getModuleMap(); + const DirectoryEntry *Dir = Mod.getUmbrellaDir().Entry; + vfs::FileSystem &FS = *FileMgr.getVirtualFileSystem(); + std::error_code EC; + for (vfs::recursive_directory_iterator Entry(FS, Dir->getName(), EC), End; + Entry != End && !EC; Entry.increment(EC)) { + using llvm::StringSwitch; + + // Check whether this entry has an extension typically associated with + // headers. + if (!StringSwitch<bool>(llvm::sys::path::extension(Entry->getName())) + .Cases(".h", ".H", ".hh", ".hpp", true) + .Default(false)) + continue; + + if (const FileEntry *Header = getFileManager().getFile(Entry->getName())) + if (!getSourceManager().hasFileInfo(Header)) { + if (!ModMap.isHeaderInUnavailableModule(Header)) { + // Find the relative path that would access this header. + SmallString<128> RelativePath; + computeRelativePath(FileMgr, Dir, Header, RelativePath); + Diag(StartLoc, diag::warn_uncovered_module_header) + << Mod.getFullModuleName() << RelativePath; + } + } + } +} /// HandleEndOfFile - This callback is invoked when the lexer hits the end of /// the current file. This either returns the EOF token or pops a level off @@ -295,6 +337,26 @@ bool Preprocessor::HandleEndOfFile(Token &Result, bool isEndOfMacro) { assert(!CurTokenLexer && "Ending a file when currently in a macro!"); + // If we have an unclosed module region from a pragma at the end of a + // module, complain and close it now. + // FIXME: This is not correct if we are building a module from PTH. + const bool LeavingSubmodule = CurLexer && CurLexerSubmodule; + if ((LeavingSubmodule || IncludeMacroStack.empty()) && + !BuildingSubmoduleStack.empty() && + BuildingSubmoduleStack.back().IsPragma) { + Diag(BuildingSubmoduleStack.back().ImportLoc, + diag::err_pp_module_begin_without_module_end); + Module *M = LeaveSubmodule(/*ForPragma*/true); + + Result.startToken(); + const char *EndPos = getCurLexerEndPos(); + CurLexer->BufferPtr = EndPos; + CurLexer->FormTokenWithChars(Result, EndPos, tok::annot_module_end); + Result.setAnnotationEndLoc(Result.getLocation()); + Result.setAnnotationValue(M); + return true; + } + // See if this file had a controlling macro. if (CurPPLexer) { // Not ending a macro, ignore it. if (const IdentifierInfo *ControllingMacro = @@ -303,9 +365,8 @@ bool Preprocessor::HandleEndOfFile(Token &Result, bool isEndOfMacro) { if (const FileEntry *FE = CurPPLexer->getFileEntry()) { HeaderInfo.SetFileControllingMacro(FE, ControllingMacro); if (MacroInfo *MI = - getMacroInfo(const_cast<IdentifierInfo*>(ControllingMacro))) { - MI->UsedForHeaderGuard = true; - } + getMacroInfo(const_cast<IdentifierInfo*>(ControllingMacro))) + MI->setUsedForHeaderGuard(true); if (const IdentifierInfo *DefinedMacro = CurPPLexer->MIOpt.GetDefinedMacro()) { if (!isMacroDefined(ControllingMacro) && @@ -397,22 +458,27 @@ bool Preprocessor::HandleEndOfFile(Token &Result, bool isEndOfMacro) { SourceMgr.setNumCreatedFIDsForFileID(CurPPLexer->getFileID(), NumFIDs); } + bool ExitedFromPredefinesFile = false; FileID ExitedFID; - if (Callbacks && !isEndOfMacro && CurPPLexer) + if (!isEndOfMacro && CurPPLexer) { ExitedFID = CurPPLexer->getFileID(); - bool LeavingSubmodule = CurSubmodule && CurLexer; + assert(PredefinesFileID.isValid() && + "HandleEndOfFile is called before PredefinesFileId is set"); + ExitedFromPredefinesFile = (PredefinesFileID == ExitedFID); + } + if (LeavingSubmodule) { + // We're done with this submodule. + Module *M = LeaveSubmodule(/*ForPragma*/false); + // Notify the parser that we've left the module. const char *EndPos = getCurLexerEndPos(); Result.startToken(); CurLexer->BufferPtr = EndPos; CurLexer->FormTokenWithChars(Result, EndPos, tok::annot_module_end); Result.setAnnotationEndLoc(Result.getLocation()); - Result.setAnnotationValue(CurSubmodule); - - // We're done with this submodule. - LeaveSubmodule(); + Result.setAnnotationValue(M); } // We're done with the #included file. @@ -429,6 +495,11 @@ bool Preprocessor::HandleEndOfFile(Token &Result, bool isEndOfMacro) { PPCallbacks::ExitFile, FileType, ExitedFID); } + // Restore conditional stack from the preamble right after exiting from the + // predefines file. + if (ExitedFromPredefinesFile) + replayPreambleConditionalStack(); + // Client should lex another token unless we generated an EOM. return LeavingSubmodule; } @@ -474,44 +545,14 @@ bool Preprocessor::HandleEndOfFile(Token &Result, bool isEndOfMacro) { } // If we are building a module that has an umbrella header, make sure that - // each of the headers within the directory covered by the umbrella header - // was actually included by the umbrella header. + // each of the headers within the directory, including all submodules, is + // covered by the umbrella header was actually included by the umbrella + // header. if (Module *Mod = getCurrentModule()) { - if (Mod->getUmbrellaHeader()) { - SourceLocation StartLoc - = SourceMgr.getLocForStartOfFile(SourceMgr.getMainFileID()); - - if (!getDiagnostics().isIgnored(diag::warn_uncovered_module_header, - StartLoc)) { - ModuleMap &ModMap = getHeaderSearchInfo().getModuleMap(); - const DirectoryEntry *Dir = Mod->getUmbrellaDir().Entry; - vfs::FileSystem &FS = *FileMgr.getVirtualFileSystem(); - std::error_code EC; - for (vfs::recursive_directory_iterator Entry(FS, Dir->getName(), EC), End; - Entry != End && !EC; Entry.increment(EC)) { - using llvm::StringSwitch; - - // Check whether this entry has an extension typically associated with - // headers. - if (!StringSwitch<bool>(llvm::sys::path::extension(Entry->getName())) - .Cases(".h", ".H", ".hh", ".hpp", true) - .Default(false)) - continue; - - if (const FileEntry *Header = - getFileManager().getFile(Entry->getName())) - if (!getSourceManager().hasFileInfo(Header)) { - if (!ModMap.isHeaderInUnavailableModule(Header)) { - // Find the relative path that would access this header. - SmallString<128> RelativePath; - computeRelativePath(FileMgr, Dir, Header, RelativePath); - Diag(StartLoc, diag::warn_uncovered_module_header) - << Mod->getFullModuleName() << RelativePath; - } - } - } - } - } + llvm::SmallVector<const Module *, 4> AllMods; + collectAllSubModulesWithUmbrellaHeader(*Mod, AllMods); + for (auto *M : AllMods) + diagnoseMissingHeaderInUmbrellaDir(*M); } return true; @@ -617,11 +658,13 @@ void Preprocessor::HandleMicrosoftCommentPaste(Token &Tok) { assert(!FoundLexer && "Lexer should return EOD before EOF in PP mode"); } -void Preprocessor::EnterSubmodule(Module *M, SourceLocation ImportLoc) { +void Preprocessor::EnterSubmodule(Module *M, SourceLocation ImportLoc, + bool ForPragma) { if (!getLangOpts().ModulesLocalVisibility) { // Just track that we entered this submodule. - BuildingSubmoduleStack.push_back(BuildingSubmoduleInfo( - M, ImportLoc, CurSubmoduleState, PendingModuleMacroNames.size())); + BuildingSubmoduleStack.push_back( + BuildingSubmoduleInfo(M, ImportLoc, ForPragma, CurSubmoduleState, + PendingModuleMacroNames.size())); return; } @@ -662,8 +705,9 @@ void Preprocessor::EnterSubmodule(Module *M, SourceLocation ImportLoc) { } // Track that we entered this module. - BuildingSubmoduleStack.push_back(BuildingSubmoduleInfo( - M, ImportLoc, CurSubmoduleState, PendingModuleMacroNames.size())); + BuildingSubmoduleStack.push_back( + BuildingSubmoduleInfo(M, ImportLoc, ForPragma, CurSubmoduleState, + PendingModuleMacroNames.size())); // Switch to this submodule as the current submodule. CurSubmoduleState = &State; @@ -686,13 +730,19 @@ bool Preprocessor::needModuleMacros() const { return getLangOpts().isCompilingModule(); } -void Preprocessor::LeaveSubmodule() { +Module *Preprocessor::LeaveSubmodule(bool ForPragma) { + if (BuildingSubmoduleStack.empty() || + BuildingSubmoduleStack.back().IsPragma != ForPragma) { + assert(ForPragma && "non-pragma module enter/leave mismatch"); + return nullptr; + } + auto &Info = BuildingSubmoduleStack.back(); Module *LeavingMod = Info.M; SourceLocation ImportLoc = Info.ImportLoc; - if (!needModuleMacros() || + if (!needModuleMacros() || (!getLangOpts().ModulesLocalVisibility && LeavingMod->getTopLevelModuleName() != getLangOpts().CurrentModule)) { // If we don't need module macros, or this is not a module for which we @@ -700,7 +750,7 @@ void Preprocessor::LeaveSubmodule() { // of pending names for the surrounding submodule. BuildingSubmoduleStack.pop_back(); makeModuleVisible(LeavingMod, ImportLoc); - return; + return LeavingMod; } // Create ModuleMacros for any macros defined in this submodule. @@ -738,17 +788,6 @@ void Preprocessor::LeaveSubmodule() { for (auto *MD = Macro.getLatest(); MD != OldMD; MD = MD->getPrevious()) { assert(MD && "broken macro directive chain"); - // Stop on macros defined in other submodules of this module that we - // #included along the way. There's no point doing this if we're - // tracking local submodule visibility, since there can be no such - // directives in our list. - if (!getLangOpts().ModulesLocalVisibility) { - Module *Mod = getModuleContainingLocation(MD->getLocation()); - if (Mod != LeavingMod && - Mod->getTopLevelModule() == LeavingMod->getTopLevelModule()) - break; - } - if (auto *VisMD = dyn_cast<VisibilityMacroDirective>(MD)) { // The latest visibility directive for a name in a submodule affects // all the directives that come before it. @@ -770,6 +809,13 @@ void Preprocessor::LeaveSubmodule() { if (Def || !Macro.getOverriddenMacros().empty()) addModuleMacro(LeavingMod, II, Def, Macro.getOverriddenMacros(), IsNew); + + if (!getLangOpts().ModulesLocalVisibility) { + // This macro is exposed to the rest of this compilation as a + // ModuleMacro; we don't need to track its MacroDirective any more. + Macro.setLatest(nullptr); + Macro.setOverriddenMacros(*this, {}); + } break; } } @@ -789,4 +835,5 @@ void Preprocessor::LeaveSubmodule() { // A nested #include makes the included submodule visible. makeModuleVisible(LeavingMod, ImportLoc); + return LeavingMod; } diff --git a/contrib/llvm/tools/clang/lib/Lex/PPMacroExpansion.cpp b/contrib/llvm/tools/clang/lib/Lex/PPMacroExpansion.cpp index de166c7..3f8ede2 100644 --- a/contrib/llvm/tools/clang/lib/Lex/PPMacroExpansion.cpp +++ b/contrib/llvm/tools/clang/lib/Lex/PPMacroExpansion.cpp @@ -412,7 +412,7 @@ static bool isTrivialSingleTokenExpansion(const MacroInfo *MI, // If this is a function-like macro invocation, it's safe to trivially expand // as long as the identifier is not a macro argument. - return std::find(MI->arg_begin(), MI->arg_end(), II) == MI->arg_end(); + return std::find(MI->param_begin(), MI->param_end(), II) == MI->param_end(); } /// isNextPPTokenLParen - Determine whether the next preprocessor token to be @@ -492,7 +492,7 @@ bool Preprocessor::HandleMacroExpandedIdentifier(Token &Identifier, // Preprocessor directives used inside macro arguments are not portable, and // this enables the warning. InMacroArgs = true; - Args = ReadFunctionLikeMacroArgs(Identifier, MI, ExpansionEnd); + Args = ReadMacroCallArgumentList(Identifier, MI, ExpansionEnd); // Finished parsing args. InMacroArgs = false; @@ -745,11 +745,11 @@ static bool GenerateNewArgTokens(Preprocessor &PP, /// token is the '(' of the macro, this method is invoked to read all of the /// actual arguments specified for the macro invocation. This returns null on /// error. -MacroArgs *Preprocessor::ReadFunctionLikeMacroArgs(Token &MacroName, +MacroArgs *Preprocessor::ReadMacroCallArgumentList(Token &MacroName, MacroInfo *MI, SourceLocation &MacroEnd) { // The number of fixed arguments to parse. - unsigned NumFixedArgsLeft = MI->getNumArgs(); + unsigned NumFixedArgsLeft = MI->getNumParams(); bool isVariadic = MI->isVariadic(); // Outer loop, while there are more arguments, keep reading them. @@ -889,7 +889,7 @@ MacroArgs *Preprocessor::ReadFunctionLikeMacroArgs(Token &MacroName, // Okay, we either found the r_paren. Check to see if we parsed too few // arguments. - unsigned MinArgsExpected = MI->getNumArgs(); + unsigned MinArgsExpected = MI->getNumParams(); // If this is not a variadic macro, and too many args were specified, emit // an error. @@ -1125,6 +1125,7 @@ static bool HasFeature(const Preprocessor &PP, StringRef Feature) { .Case("attribute_overloadable", true) .Case("attribute_unavailable_with_message", true) .Case("attribute_unused_on_fields", true) + .Case("attribute_diagnose_if_objc", true) .Case("blocks", LangOpts.Blocks) .Case("c_thread_safety_attributes", true) .Case("cxx_exceptions", LangOpts.CXXExceptions) @@ -1314,6 +1315,8 @@ static bool HasExtension(const Preprocessor &PP, StringRef Extension) { .Case("cxx_binary_literals", true) .Case("cxx_init_captures", LangOpts.CPlusPlus11) .Case("cxx_variable_templates", LangOpts.CPlusPlus) + // Miscellaneous language extensions + .Case("overloadable_unmarked", true) .Default(false); } @@ -1422,7 +1425,7 @@ static bool EvaluateHasIncludeCommon(Token &Tok, const DirectoryLookup *CurDir; const FileEntry *File = PP.LookupFile(FilenameLoc, Filename, isAngled, LookupFrom, LookupFromFile, - CurDir, nullptr, nullptr, nullptr); + CurDir, nullptr, nullptr, nullptr, nullptr); // Get the result value. A result of true means the file exists. return File != nullptr; @@ -1453,7 +1456,7 @@ static bool EvaluateHasIncludeNext(Token &Tok, } else if (PP.isInPrimaryFile()) { Lookup = nullptr; PP.Diag(Tok, diag::pp_include_next_in_primary); - } else if (PP.getCurrentSubmodule()) { + } else if (PP.getCurrentLexerSubmodule()) { // Start looking up in the directory *after* the one in which the current // file would be found, if any. assert(PP.getCurrentLexer() && "#include_next directive in macro?"); @@ -1746,6 +1749,7 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) { return llvm::StringSwitch<bool>(II->getName()) .Case("__make_integer_seq", LangOpts.CPlusPlus) .Case("__type_pack_element", LangOpts.CPlusPlus) + .Case("__builtin_available", true) .Default(false); } }); diff --git a/contrib/llvm/tools/clang/lib/Lex/Pragma.cpp b/contrib/llvm/tools/clang/lib/Lex/Pragma.cpp index 100da51..bf2363a 100644 --- a/contrib/llvm/tools/clang/lib/Lex/Pragma.cpp +++ b/contrib/llvm/tools/clang/lib/Lex/Pragma.cpp @@ -20,6 +20,7 @@ #include "clang/Basic/TokenKinds.h" #include "clang/Lex/HeaderSearch.h" #include "clang/Lex/LexDiagnostic.h" +#include "clang/Lex/LiteralSupport.h" #include "clang/Lex/MacroInfo.h" #include "clang/Lex/PPCallbacks.h" #include "clang/Lex/Preprocessor.h" @@ -160,12 +161,23 @@ public: ~LexingFor_PragmaRAII() { if (InMacroArgPreExpansion) { + // When committing/backtracking the cached pragma tokens in a macro + // argument pre-expansion we want to ensure that either the tokens which + // have been committed will be removed from the cache or that the tokens + // over which we just backtracked won't remain in the cache after they're + // consumed and that the caching will stop after consuming them. + // Otherwise the caching will interfere with the way macro expansion + // works, because we will continue to cache tokens after consuming the + // backtracked tokens, which shouldn't happen when we're dealing with + // macro argument pre-expansion. + auto CachedTokenRange = PP.LastCachedTokenRange(); if (Failed) { PP.CommitBacktrackedTokens(); } else { PP.Backtrack(); OutTok = PragmaTok; } + PP.EraseCachedTokens(CachedTokenRange); } } @@ -464,9 +476,9 @@ void Preprocessor::HandlePragmaSystemHeader(Token &SysHeaderTok) { // Emit a line marker. This will change any source locations from this point // forward to realize they are in a system header. // Create a line note with this information. - SourceMgr.AddLineNote(SysHeaderTok.getLocation(), PLoc.getLine()+1, + SourceMgr.AddLineNote(SysHeaderTok.getLocation(), PLoc.getLine() + 1, FilenameID, /*IsEntry=*/false, /*IsExit=*/false, - /*IsSystem=*/true, /*IsExternC=*/false); + SrcMgr::C_System); } /// HandlePragmaDependency - Handle \#pragma GCC dependency "foo" blah. @@ -497,7 +509,7 @@ void Preprocessor::HandlePragmaDependency(Token &DependencyTok) { const DirectoryLookup *CurDir; const FileEntry *File = LookupFile(FilenameTok.getLocation(), Filename, isAngled, nullptr, - nullptr, CurDir, nullptr, nullptr, nullptr); + nullptr, CurDir, nullptr, nullptr, nullptr, nullptr); if (!File) { if (!SuppressIncludeNotFoundError) Diag(FilenameTok, diag::err_pp_file_not_found) << Filename; @@ -743,6 +755,125 @@ void Preprocessor::HandlePragmaIncludeAlias(Token &Tok) { getHeaderSearchInfo().AddIncludeAlias(OriginalSource, ReplaceFileName); } +// Lex a component of a module name: either an identifier or a string literal; +// for components that can be expressed both ways, the two forms are equivalent. +static bool LexModuleNameComponent( + Preprocessor &PP, Token &Tok, + std::pair<IdentifierInfo *, SourceLocation> &ModuleNameComponent, + bool First) { + PP.LexUnexpandedToken(Tok); + if (Tok.is(tok::string_literal) && !Tok.hasUDSuffix()) { + StringLiteralParser Literal(Tok, PP); + if (Literal.hadError) + return true; + ModuleNameComponent = std::make_pair( + PP.getIdentifierInfo(Literal.GetString()), Tok.getLocation()); + } else if (!Tok.isAnnotation() && Tok.getIdentifierInfo()) { + ModuleNameComponent = + std::make_pair(Tok.getIdentifierInfo(), Tok.getLocation()); + } else { + PP.Diag(Tok.getLocation(), diag::err_pp_expected_module_name) << First; + return true; + } + return false; +} + +static bool LexModuleName( + Preprocessor &PP, Token &Tok, + llvm::SmallVectorImpl<std::pair<IdentifierInfo *, SourceLocation>> + &ModuleName) { + while (true) { + std::pair<IdentifierInfo*, SourceLocation> NameComponent; + if (LexModuleNameComponent(PP, Tok, NameComponent, ModuleName.empty())) + return true; + ModuleName.push_back(NameComponent); + + PP.LexUnexpandedToken(Tok); + if (Tok.isNot(tok::period)) + return false; + } +} + +void Preprocessor::HandlePragmaModuleBuild(Token &Tok) { + SourceLocation Loc = Tok.getLocation(); + + std::pair<IdentifierInfo *, SourceLocation> ModuleNameLoc; + if (LexModuleNameComponent(*this, Tok, ModuleNameLoc, true)) + return; + IdentifierInfo *ModuleName = ModuleNameLoc.first; + + LexUnexpandedToken(Tok); + if (Tok.isNot(tok::eod)) { + Diag(Tok, diag::ext_pp_extra_tokens_at_eol) << "pragma"; + DiscardUntilEndOfDirective(); + } + + if (CurPTHLexer) { + // FIXME: Support this somehow? + Diag(Loc, diag::err_pp_module_build_pth); + return; + } + + CurLexer->LexingRawMode = true; + + auto TryConsumeIdentifier = [&](StringRef Ident) -> bool { + if (Tok.getKind() != tok::raw_identifier || + Tok.getRawIdentifier() != Ident) + return false; + CurLexer->Lex(Tok); + return true; + }; + + // Scan forward looking for the end of the module. + const char *Start = CurLexer->getBufferLocation(); + const char *End = nullptr; + unsigned NestingLevel = 1; + while (true) { + End = CurLexer->getBufferLocation(); + CurLexer->Lex(Tok); + + if (Tok.is(tok::eof)) { + Diag(Loc, diag::err_pp_module_build_missing_end); + break; + } + + if (Tok.isNot(tok::hash) || !Tok.isAtStartOfLine()) { + // Token was part of module; keep going. + continue; + } + + // We hit something directive-shaped; check to see if this is the end + // of the module build. + CurLexer->ParsingPreprocessorDirective = true; + CurLexer->Lex(Tok); + if (TryConsumeIdentifier("pragma") && TryConsumeIdentifier("clang") && + TryConsumeIdentifier("module")) { + if (TryConsumeIdentifier("build")) + // #pragma clang module build -> entering a nested module build. + ++NestingLevel; + else if (TryConsumeIdentifier("endbuild")) { + // #pragma clang module endbuild -> leaving a module build. + if (--NestingLevel == 0) + break; + } + // We should either be looking at the EOD or more of the current directive + // preceding the EOD. Either way we can ignore this token and keep going. + assert(Tok.getKind() != tok::eof && "missing EOD before EOF"); + } + } + + CurLexer->LexingRawMode = false; + + // Load the extracted text as a preprocessed module. + assert(CurLexer->getBuffer().begin() <= Start && + Start <= CurLexer->getBuffer().end() && + CurLexer->getBuffer().begin() <= End && + End <= CurLexer->getBuffer().end() && + "module source range not contained within same file buffer"); + TheModuleLoader.loadModuleFromSource(Loc, ModuleName->getName(), + StringRef(Start, End - Start)); +} + /// AddPragmaHandler - Add the specified pragma handler to the preprocessor. /// If 'Namespace' is non-null, then it is a token required to exist on the /// pragma line before the pragma string starts, e.g. "STDC" or "GCC". @@ -978,9 +1109,9 @@ struct PragmaDebugHandler : public PragmaHandler { #ifdef _MSC_VER #pragma warning(disable : 4717) #endif - static void DebugOverflowStack() { - void (*volatile Self)() = DebugOverflowStack; - Self(); + static void DebugOverflowStack(void (*P)() = nullptr) { + void (*volatile Self)(void(*P)()) = DebugOverflowStack; + Self(reinterpret_cast<void(*)()>(Self)); } #ifdef _MSC_VER #pragma warning(default : 4717) @@ -1290,6 +1421,160 @@ public: } }; +/// Handle the clang \#pragma module import extension. The syntax is: +/// \code +/// #pragma clang module import some.module.name +/// \endcode +struct PragmaModuleImportHandler : public PragmaHandler { + PragmaModuleImportHandler() : PragmaHandler("import") {} + + void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &Tok) override { + SourceLocation ImportLoc = Tok.getLocation(); + + // Read the module name. + llvm::SmallVector<std::pair<IdentifierInfo *, SourceLocation>, 8> + ModuleName; + if (LexModuleName(PP, Tok, ModuleName)) + return; + + if (Tok.isNot(tok::eod)) + PP.Diag(Tok, diag::ext_pp_extra_tokens_at_eol) << "pragma"; + + // If we have a non-empty module path, load the named module. + Module *Imported = + PP.getModuleLoader().loadModule(ImportLoc, ModuleName, Module::Hidden, + /*IsIncludeDirective=*/false); + if (!Imported) + return; + + PP.makeModuleVisible(Imported, ImportLoc); + PP.EnterAnnotationToken(SourceRange(ImportLoc, ModuleName.back().second), + tok::annot_module_include, Imported); + if (auto *CB = PP.getPPCallbacks()) + CB->moduleImport(ImportLoc, ModuleName, Imported); + } +}; + +/// Handle the clang \#pragma module begin extension. The syntax is: +/// \code +/// #pragma clang module begin some.module.name +/// ... +/// #pragma clang module end +/// \endcode +struct PragmaModuleBeginHandler : public PragmaHandler { + PragmaModuleBeginHandler() : PragmaHandler("begin") {} + + void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &Tok) override { + SourceLocation BeginLoc = Tok.getLocation(); + + // Read the module name. + llvm::SmallVector<std::pair<IdentifierInfo *, SourceLocation>, 8> + ModuleName; + if (LexModuleName(PP, Tok, ModuleName)) + return; + + if (Tok.isNot(tok::eod)) + PP.Diag(Tok, diag::ext_pp_extra_tokens_at_eol) << "pragma"; + + // We can only enter submodules of the current module. + StringRef Current = PP.getLangOpts().CurrentModule; + if (ModuleName.front().first->getName() != Current) { + PP.Diag(ModuleName.front().second, diag::err_pp_module_begin_wrong_module) + << ModuleName.front().first << (ModuleName.size() > 1) + << Current.empty() << Current; + return; + } + + // Find the module we're entering. We require that a module map for it + // be loaded or implicitly loadable. + // FIXME: We could create the submodule here. We'd need to know whether + // it's supposed to be explicit, but not much else. + Module *M = PP.getHeaderSearchInfo().lookupModule(Current); + if (!M) { + PP.Diag(ModuleName.front().second, + diag::err_pp_module_begin_no_module_map) << Current; + return; + } + for (unsigned I = 1; I != ModuleName.size(); ++I) { + auto *NewM = M->findSubmodule(ModuleName[I].first->getName()); + if (!NewM) { + PP.Diag(ModuleName[I].second, diag::err_pp_module_begin_no_submodule) + << M->getFullModuleName() << ModuleName[I].first; + return; + } + M = NewM; + } + + // If the module isn't available, it doesn't make sense to enter it. + if (Preprocessor::checkModuleIsAvailable( + PP.getLangOpts(), PP.getTargetInfo(), PP.getDiagnostics(), M)) { + PP.Diag(BeginLoc, diag::note_pp_module_begin_here) + << M->getTopLevelModuleName(); + return; + } + + // Enter the scope of the submodule. + PP.EnterSubmodule(M, BeginLoc, /*ForPragma*/true); + PP.EnterAnnotationToken(SourceRange(BeginLoc, ModuleName.back().second), + tok::annot_module_begin, M); + } +}; + +/// Handle the clang \#pragma module end extension. +struct PragmaModuleEndHandler : public PragmaHandler { + PragmaModuleEndHandler() : PragmaHandler("end") {} + + void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &Tok) override { + SourceLocation Loc = Tok.getLocation(); + + PP.LexUnexpandedToken(Tok); + if (Tok.isNot(tok::eod)) + PP.Diag(Tok, diag::ext_pp_extra_tokens_at_eol) << "pragma"; + + Module *M = PP.LeaveSubmodule(/*ForPragma*/true); + if (M) + PP.EnterAnnotationToken(SourceRange(Loc), tok::annot_module_end, M); + else + PP.Diag(Loc, diag::err_pp_module_end_without_module_begin); + } +}; + +/// Handle the clang \#pragma module build extension. +struct PragmaModuleBuildHandler : public PragmaHandler { + PragmaModuleBuildHandler() : PragmaHandler("build") {} + + void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &Tok) override { + PP.HandlePragmaModuleBuild(Tok); + } +}; + +/// Handle the clang \#pragma module load extension. +struct PragmaModuleLoadHandler : public PragmaHandler { + PragmaModuleLoadHandler() : PragmaHandler("load") {} + + void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &Tok) override { + SourceLocation Loc = Tok.getLocation(); + + // Read the module name. + llvm::SmallVector<std::pair<IdentifierInfo *, SourceLocation>, 8> + ModuleName; + if (LexModuleName(PP, Tok, ModuleName)) + return; + + if (Tok.isNot(tok::eod)) + PP.Diag(Tok, diag::ext_pp_extra_tokens_at_eol) << "pragma"; + + // Load the module, don't make it visible. + PP.getModuleLoader().loadModule(Loc, ModuleName, Module::Hidden, + /*IsIncludeDirective=*/false); + } +}; + /// PragmaPushMacroHandler - "\#pragma push_macro" saves the value of the /// macro on the top of the stack. struct PragmaPushMacroHandler : public PragmaHandler { @@ -1513,6 +1798,15 @@ void Preprocessor::RegisterBuiltinPragmas() { AddPragmaHandler("clang", new PragmaARCCFCodeAuditedHandler()); AddPragmaHandler("clang", new PragmaAssumeNonNullHandler()); + // #pragma clang module ... + auto *ModuleHandler = new PragmaNamespace("module"); + AddPragmaHandler("clang", ModuleHandler); + ModuleHandler->AddPragma(new PragmaModuleImportHandler()); + ModuleHandler->AddPragma(new PragmaModuleBeginHandler()); + ModuleHandler->AddPragma(new PragmaModuleEndHandler()); + ModuleHandler->AddPragma(new PragmaModuleBuildHandler()); + ModuleHandler->AddPragma(new PragmaModuleLoadHandler()); + AddPragmaHandler("STDC", new PragmaSTDC_FENV_ACCESSHandler()); AddPragmaHandler("STDC", new PragmaSTDC_CX_LIMITED_RANGEHandler()); AddPragmaHandler("STDC", new PragmaSTDC_UnknownHandler()); diff --git a/contrib/llvm/tools/clang/lib/Lex/PreprocessingRecord.cpp b/contrib/llvm/tools/clang/lib/Lex/PreprocessingRecord.cpp index 13e15f3..03c4cbe 100644 --- a/contrib/llvm/tools/clang/lib/Lex/PreprocessingRecord.cpp +++ b/contrib/llvm/tools/clang/lib/Lex/PreprocessingRecord.cpp @@ -422,7 +422,8 @@ void PreprocessingRecord::MacroDefined(const Token &Id, } void PreprocessingRecord::MacroUndefined(const Token &Id, - const MacroDefinition &MD) { + const MacroDefinition &MD, + const MacroDirective *Undef) { MD.forAllDefinitions([&](MacroInfo *MI) { MacroDefinitions.erase(MI); }); } diff --git a/contrib/llvm/tools/clang/lib/Lex/Preprocessor.cpp b/contrib/llvm/tools/clang/lib/Lex/Preprocessor.cpp index 91319be..7979be7 100644 --- a/contrib/llvm/tools/clang/lib/Lex/Preprocessor.cpp +++ b/contrib/llvm/tools/clang/lib/Lex/Preprocessor.cpp @@ -70,25 +70,25 @@ ExternalPreprocessorSource::~ExternalPreprocessorSource() { } Preprocessor::Preprocessor(std::shared_ptr<PreprocessorOptions> PPOpts, DiagnosticsEngine &diags, LangOptions &opts, - SourceManager &SM, HeaderSearch &Headers, - ModuleLoader &TheModuleLoader, + SourceManager &SM, MemoryBufferCache &PCMCache, + HeaderSearch &Headers, ModuleLoader &TheModuleLoader, IdentifierInfoLookup *IILookup, bool OwnsHeaders, TranslationUnitKind TUKind) : PPOpts(std::move(PPOpts)), Diags(&diags), LangOpts(opts), Target(nullptr), AuxTarget(nullptr), FileMgr(Headers.getFileMgr()), SourceMgr(SM), - ScratchBuf(new ScratchBuffer(SourceMgr)), HeaderInfo(Headers), - TheModuleLoader(TheModuleLoader), ExternalSource(nullptr), - Identifiers(opts, IILookup), + PCMCache(PCMCache), ScratchBuf(new ScratchBuffer(SourceMgr)), + HeaderInfo(Headers), TheModuleLoader(TheModuleLoader), + ExternalSource(nullptr), Identifiers(opts, IILookup), PragmaHandlers(new PragmaNamespace(StringRef())), IncrementalProcessing(false), TUKind(TUKind), CodeComplete(nullptr), CodeCompletionFile(nullptr), CodeCompletionOffset(0), LastTokenWasAt(false), ModuleImportExpectsIdentifier(false), CodeCompletionReached(false), CodeCompletionII(nullptr), MainFileDir(nullptr), SkipMainFilePreamble(0, true), CurPPLexer(nullptr), - CurDirLookup(nullptr), CurLexerKind(CLK_Lexer), CurSubmodule(nullptr), - Callbacks(nullptr), CurSubmoduleState(&NullSubmoduleState), - MacroArgCache(nullptr), Record(nullptr), MIChainHead(nullptr), - DeserialMIChainHead(nullptr) { + CurDirLookup(nullptr), CurLexerKind(CLK_Lexer), + CurLexerSubmodule(nullptr), Callbacks(nullptr), + CurSubmoduleState(&NullSubmoduleState), MacroArgCache(nullptr), + Record(nullptr), MIChainHead(nullptr) { OwnsHeaderSearch = OwnsHeaders; CounterValue = 0; // __COUNTER__ starts at 0. @@ -150,6 +150,9 @@ Preprocessor::Preprocessor(std::shared_ptr<PreprocessorOptions> PPOpts, Ident_GetExceptionInfo = Ident_GetExceptionCode = nullptr; Ident_AbnormalTermination = nullptr; } + + if (this->PPOpts->GeneratePreamble) + PreambleConditionalStack.startRecording(); } Preprocessor::~Preprocessor() { @@ -169,11 +172,6 @@ Preprocessor::~Preprocessor() { std::fill(TokenLexerCache, TokenLexerCache + NumCachedTokenLexers, nullptr); CurTokenLexer.reset(); - while (DeserializedMacroInfoChain *I = DeserialMIChainHead) { - DeserialMIChainHead = I->Next; - I->~DeserializedMacroInfoChain(); - } - // Free any cached MacroArgs. for (MacroArgs *ArgList = MacroArgCache; ArgList;) ArgList = ArgList->deallocate(); @@ -539,6 +537,16 @@ void Preprocessor::EnterMainSourceFile() { EnterSourceFile(FID, nullptr, SourceLocation()); } +void Preprocessor::replayPreambleConditionalStack() { + // Restore the conditional stack from the preamble, if there is one. + if (PreambleConditionalStack.isReplaying()) { + assert(CurPPLexer && + "CurPPLexer is null when calling replayPreambleConditionalStack."); + CurPPLexer->setConditionalLevels(PreambleConditionalStack.getStack()); + PreambleConditionalStack.doneReplaying(); + } +} + void Preprocessor::EndSourceFile() { // Notify the client that we reached the end of the source file. if (Callbacks) @@ -576,7 +584,11 @@ IdentifierInfo *Preprocessor::LookUpIdentifierInfo(Token &Identifier) const { // Update the token info (identifier info and appropriate token kind). Identifier.setIdentifierInfo(II); - Identifier.setKind(II->getTokenID()); + if (getLangOpts().MSVCCompat && II->isCPlusPlusOperatorKeyword() && + getSourceManager().isInSystemHeader(Identifier.getLocation())) + Identifier.setKind(clang::tok::identifier); + else + Identifier.setKind(II->getTokenID()); return II; } @@ -702,12 +714,6 @@ bool Preprocessor::HandleIdentifier(Token &Identifier) { II.setIsFutureCompatKeyword(false); } - // C++ 2.11p2: If this is an alternative representation of a C++ operator, - // then we act as if it is the actual operator and not the textual - // representation of it. - if (II.isCPlusPlusOperatorKeyword()) - Identifier.setIdentifierInfo(nullptr); - // If this is an extension token, diagnose its use. // We avoid diagnosing tokens that originate from macro definitions. // FIXME: This warning is disabled in cases where it shouldn't be, diff --git a/contrib/llvm/tools/clang/lib/Lex/ScratchBuffer.cpp b/contrib/llvm/tools/clang/lib/Lex/ScratchBuffer.cpp index cd8a27e..e0f3966 100644 --- a/contrib/llvm/tools/clang/lib/Lex/ScratchBuffer.cpp +++ b/contrib/llvm/tools/clang/lib/Lex/ScratchBuffer.cpp @@ -35,6 +35,14 @@ SourceLocation ScratchBuffer::getToken(const char *Buf, unsigned Len, const char *&DestPtr) { if (BytesUsed+Len+2 > ScratchBufSize) AllocScratchBuffer(Len+2); + else { + // Clear out the source line cache if it's already been computed. + // FIXME: Allow this to be incrementally extended. + auto *ContentCache = const_cast<SrcMgr::ContentCache *>( + SourceMgr.getSLocEntry(SourceMgr.getFileID(BufferStartLoc)) + .getFile().getContentCache()); + ContentCache->SourceLineCache = nullptr; + } // Prefix the token with a \n, so that it looks like it is the first thing on // its own virtual line in caret diagnostics. diff --git a/contrib/llvm/tools/clang/lib/Lex/TokenLexer.cpp b/contrib/llvm/tools/clang/lib/Lex/TokenLexer.cpp index a53c801..c2e49ba 100644 --- a/contrib/llvm/tools/clang/lib/Lex/TokenLexer.cpp +++ b/contrib/llvm/tools/clang/lib/Lex/TokenLexer.cpp @@ -67,7 +67,7 @@ void TokenLexer::Init(Token &Tok, SourceLocation ELEnd, MacroInfo *MI, // If this is a function-like macro, expand the arguments and change // Tokens to point to the expanded tokens. - if (Macro->isFunctionLike() && Macro->getNumArgs()) + if (Macro->isFunctionLike() && Macro->getNumParams()) ExpandFunctionArguments(); // Mark the macro as currently disabled, so that it is not recursively @@ -122,7 +122,7 @@ bool TokenLexer::MaybeRemoveCommaBeforeVaArgs( SmallVectorImpl<Token> &ResultToks, bool HasPasteOperator, MacroInfo *Macro, unsigned MacroArgNo, Preprocessor &PP) { // Is the macro argument __VA_ARGS__? - if (!Macro->isVariadic() || MacroArgNo != Macro->getNumArgs()-1) + if (!Macro->isVariadic() || MacroArgNo != Macro->getNumParams()-1) return false; // In Microsoft-compatibility mode, a comma is removed in the expansion @@ -137,7 +137,7 @@ bool TokenLexer::MaybeRemoveCommaBeforeVaArgs( // 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) + && Macro->getNumParams() < 2) return false; // Is a comma available to be removed? @@ -183,11 +183,17 @@ void TokenLexer::ExpandFunctionArguments() { // preprocessor already verified that the following token is a macro name // when the #define was parsed. const Token &CurTok = Tokens[i]; + // We don't want a space for the next token after a paste + // operator. In valid code, the token will get smooshed onto the + // preceding one anyway. In assembler-with-cpp mode, invalid + // pastes are allowed through: in this case, we do not want the + // extra whitespace to be added. For example, we want ". ## foo" + // -> ".foo" not ". foo". if (i != 0 && !Tokens[i-1].is(tok::hashhash) && CurTok.hasLeadingSpace()) NextTokGetsSpace = true; if (CurTok.isOneOf(tok::hash, tok::hashat)) { - int ArgNo = Macro->getArgumentNum(Tokens[i+1].getIdentifierInfo()); + int ArgNo = Macro->getParameterNum(Tokens[i+1].getIdentifierInfo()); assert(ArgNo != -1 && "Token following # is not an argument?"); SourceLocation ExpansionLocStart = @@ -231,7 +237,7 @@ void TokenLexer::ExpandFunctionArguments() { // Otherwise, if this is not an argument token, just add the token to the // output buffer. IdentifierInfo *II = CurTok.getIdentifierInfo(); - int ArgNo = II ? Macro->getArgumentNum(II) : -1; + int ArgNo = II ? Macro->getParameterNum(II) : -1; if (ArgNo == -1) { // This isn't an argument, just add it. ResultToks.push_back(CurTok); @@ -317,14 +323,16 @@ void TokenLexer::ExpandFunctionArguments() { const Token *ArgToks = ActualArgs->getUnexpArgument(ArgNo); unsigned NumToks = MacroArgs::getArgLength(ArgToks); if (NumToks) { // Not an empty argument? + bool VaArgsPseudoPaste = false; // If this is the GNU ", ## __VA_ARGS__" extension, and we just learned // that __VA_ARGS__ expands to multiple tokens, avoid a pasting error when // the expander trys to paste ',' with the first token of the __VA_ARGS__ // expansion. if (NonEmptyPasteBefore && ResultToks.size() >= 2 && ResultToks[ResultToks.size()-2].is(tok::comma) && - (unsigned)ArgNo == Macro->getNumArgs()-1 && + (unsigned)ArgNo == Macro->getNumParams()-1 && Macro->isVariadic()) { + VaArgsPseudoPaste = true; // Remove the paste operator, report use of the extension. PP.Diag(ResultToks.pop_back_val().getLocation(), diag::ext_paste_comma); } @@ -344,18 +352,16 @@ void TokenLexer::ExpandFunctionArguments() { ResultToks.end()-NumToks, ResultToks.end()); } - // If this token (the macro argument) was supposed to get leading - // whitespace, transfer this information onto the first token of the - // expansion. - // - // Do not do this if the paste operator occurs before the macro argument, - // as in "A ## MACROARG". In valid code, the first token will get - // smooshed onto the preceding one anyway (forming AMACROARG). In - // assembler-with-cpp mode, invalid pastes are allowed through: in this - // case, we do not want the extra whitespace to be added. For example, - // we want ". ## foo" -> ".foo" not ". foo". - if (NextTokGetsSpace) - ResultToks[ResultToks.size()-NumToks].setFlag(Token::LeadingSpace); + // Transfer the leading whitespace information from the token + // (the macro argument) onto the first token of the + // expansion. Note that we don't do this for the GNU + // pseudo-paste extension ", ## __VA_ARGS__". + if (!VaArgsPseudoPaste) { + ResultToks[ResultToks.size() - NumToks].setFlagValue(Token::StartOfLine, + false); + ResultToks[ResultToks.size() - NumToks].setFlagValue( + Token::LeadingSpace, NextTokGetsSpace); + } NextTokGetsSpace = false; continue; |