From 45b533945f0851ec234ca846e1af5ee1e4df0b6e Mon Sep 17 00:00:00 2001 From: Dimitry Andric Date: Wed, 30 Dec 2015 11:49:41 +0000 Subject: Vendor import of clang trunk r256633: https://llvm.org/svn/llvm-project/cfe/trunk@256633 --- lib/Lex/HeaderSearch.cpp | 296 ++++++++++++++++++++++------------------ lib/Lex/Lexer.cpp | 25 ++-- lib/Lex/LiteralSupport.cpp | 45 +++--- lib/Lex/MacroInfo.cpp | 14 +- lib/Lex/ModuleMap.cpp | 191 +++++++++++++++++++++----- lib/Lex/PPDirectives.cpp | 90 ++++++++---- lib/Lex/PPExpressions.cpp | 6 +- lib/Lex/PPLexerChange.cpp | 7 +- lib/Lex/PPMacroExpansion.cpp | 38 ++++-- lib/Lex/Pragma.cpp | 8 +- lib/Lex/PreprocessingRecord.cpp | 2 +- lib/Lex/Preprocessor.cpp | 37 ++--- lib/Lex/TokenLexer.cpp | 17 ++- 13 files changed, 508 insertions(+), 268 deletions(-) (limited to 'lib/Lex') diff --git a/lib/Lex/HeaderSearch.cpp b/lib/Lex/HeaderSearch.cpp index 983dc18b57af..8a686a7f3d74 100644 --- a/lib/Lex/HeaderSearch.cpp +++ b/lib/Lex/HeaderSearch.cpp @@ -127,11 +127,12 @@ std::string HeaderSearch::getModuleFileName(Module *Module) { std::string HeaderSearch::getModuleFileName(StringRef ModuleName, StringRef ModuleMapPath) { - // If we don't have a module cache path, we can't do anything. - if (ModuleCachePath.empty()) + // If we don't have a module cache path or aren't supposed to use one, we + // can't do anything. + if (getModuleCachePath().empty()) return std::string(); - SmallString<256> Result(ModuleCachePath); + SmallString<256> Result(getModuleCachePath()); llvm::sys::fs::make_absolute(Result); if (HSOpts->DisableModuleHash) { @@ -153,7 +154,7 @@ std::string HeaderSearch::getModuleFileName(StringRef ModuleName, llvm::hash_code Hash = llvm::hash_combine(DirName.lower(), FileName.lower(), - HSOpts->ModuleFormat); + HSOpts->ModuleFormat, HSOpts->UseDebugInfo); SmallString<128> HashStr; llvm::APInt(64, size_t(Hash)).toStringUnsigned(HashStr, /*Radix*/36); @@ -249,31 +250,22 @@ const char *DirectoryLookup::getName() const { return getHeaderMap()->getFileName(); } -static const FileEntry * -getFileAndSuggestModule(HeaderSearch &HS, StringRef FileName, - const DirectoryEntry *Dir, bool IsSystemHeaderDir, - ModuleMap::KnownHeader *SuggestedModule) { +const FileEntry *HeaderSearch::getFileAndSuggestModule( + StringRef FileName, const DirectoryEntry *Dir, bool IsSystemHeaderDir, + Module *RequestingModule, ModuleMap::KnownHeader *SuggestedModule) { // If we have a module map that might map this header, load it and // check whether we'll have a suggestion for a module. - HS.hasModuleMap(FileName, Dir, IsSystemHeaderDir); - if (SuggestedModule) { - const FileEntry *File = HS.getFileMgr().getFile(FileName, - /*OpenFile=*/false); - if (File) { - // If there is a module that corresponds to this header, suggest it. - *SuggestedModule = HS.findModuleForHeader(File); - - // FIXME: This appears to be a no-op. We loaded the module map for this - // directory at the start of this function. - if (!SuggestedModule->getModule() && - HS.hasModuleMap(FileName, Dir, IsSystemHeaderDir)) - *SuggestedModule = HS.findModuleForHeader(File); - } + const FileEntry *File = getFileMgr().getFile(FileName, /*OpenFile=*/true); + if (!File) + return nullptr; - return File; - } + // If there is a module that corresponds to this header, suggest it. + if (!findUsableModuleForHeader(File, Dir ? Dir : File->getDir(), + RequestingModule, SuggestedModule, + IsSystemHeaderDir)) + return nullptr; - return HS.getFileMgr().getFile(FileName, /*openFile=*/true); + return File; } /// LookupFile - Lookup the specified file in this search path, returning it @@ -283,6 +275,7 @@ const FileEntry *DirectoryLookup::LookupFile( HeaderSearch &HS, SmallVectorImpl *SearchPath, SmallVectorImpl *RelativePath, + Module *RequestingModule, ModuleMap::KnownHeader *SuggestedModule, bool &InUserSpecifiedSystemFramework, bool &HasBeenMapped, @@ -305,14 +298,15 @@ const FileEntry *DirectoryLookup::LookupFile( RelativePath->append(Filename.begin(), Filename.end()); } - return getFileAndSuggestModule(HS, TmpDir, getDir(), - isSystemHeaderDirectory(), - SuggestedModule); + return HS.getFileAndSuggestModule(TmpDir, getDir(), + isSystemHeaderDirectory(), + RequestingModule, SuggestedModule); } if (isFramework()) return DoFrameworkLookup(Filename, HS, SearchPath, RelativePath, - SuggestedModule, InUserSpecifiedSystemFramework); + RequestingModule, SuggestedModule, + InUserSpecifiedSystemFramework); assert(isHeaderMap() && "Unknown directory lookup"); const HeaderMap *HM = getHeaderMap(); @@ -404,13 +398,10 @@ getTopFrameworkDir(FileManager &FileMgr, StringRef DirName, /// DoFrameworkLookup - Do a lookup of the specified file in the current /// DirectoryLookup, which is a framework directory. const FileEntry *DirectoryLookup::DoFrameworkLookup( - StringRef Filename, - HeaderSearch &HS, - SmallVectorImpl *SearchPath, - SmallVectorImpl *RelativePath, + StringRef Filename, HeaderSearch &HS, SmallVectorImpl *SearchPath, + SmallVectorImpl *RelativePath, Module *RequestingModule, ModuleMap::KnownHeader *SuggestedModule, - bool &InUserSpecifiedSystemFramework) const -{ + bool &InUserSpecifiedSystemFramework) const { FileManager &FileMgr = HS.getFileMgr(); // Framework names must have a '/' in the filename. @@ -522,27 +513,15 @@ const FileEntry *DirectoryLookup::DoFrameworkLookup( break; } while (true); + bool IsSystem = getDirCharacteristic() != SrcMgr::C_User; if (FoundFramework) { - // Find the top-level framework based on this framework. - SmallVector SubmodulePath; - const DirectoryEntry *TopFrameworkDir - = ::getTopFrameworkDir(FileMgr, FrameworkPath, SubmodulePath); - - // Determine the name of the top-level framework. - StringRef ModuleName = llvm::sys::path::stem(TopFrameworkDir->getName()); - - // Load this framework module. If that succeeds, find the suggested module - // for this header, if any. - bool IsSystem = getDirCharacteristic() != SrcMgr::C_User; - HS.loadFrameworkModule(ModuleName, TopFrameworkDir, IsSystem); - - // FIXME: This can find a module not part of ModuleName, which is - // important so that we're consistent about whether this header - // corresponds to a module. Possibly we should lock down framework modules - // so that this is not possible. - *SuggestedModule = HS.findModuleForHeader(FE); + if (!HS.findUsableModuleForFrameworkHeader( + FE, FrameworkPath, RequestingModule, SuggestedModule, IsSystem)) + return nullptr; } else { - *SuggestedModule = HS.findModuleForHeader(FE); + if (!HS.findUsableModuleForHeader(FE, getDir(), RequestingModule, + SuggestedModule, IsSystem)) + return nullptr; } } return FE; @@ -588,7 +567,8 @@ const FileEntry *HeaderSearch::LookupFile( const DirectoryLookup *FromDir, const DirectoryLookup *&CurDir, ArrayRef> Includers, SmallVectorImpl *SearchPath, SmallVectorImpl *RelativePath, - ModuleMap::KnownHeader *SuggestedModule, bool SkipCache) { + Module *RequestingModule, ModuleMap::KnownHeader *SuggestedModule, + bool SkipCache) { if (SuggestedModule) *SuggestedModule = ModuleMap::KnownHeader(); @@ -606,13 +586,9 @@ const FileEntry *HeaderSearch::LookupFile( RelativePath->append(Filename.begin(), Filename.end()); } // Otherwise, just return the file. - const FileEntry *File = FileMgr.getFile(Filename, /*openFile=*/true); - if (File && SuggestedModule) { - // If there is a module that corresponds to this header, suggest it. - hasModuleMap(Filename, File->getDir(), /*SystemHeaderDir*/false); - *SuggestedModule = findModuleForHeader(File); - } - return File; + return getFileAndSuggestModule(Filename, nullptr, + /*IsSystemHeaderDir*/false, + RequestingModule, SuggestedModule); } // This is the header that MSVC's header search would have found. @@ -646,8 +622,8 @@ const FileEntry *HeaderSearch::LookupFile( bool IncluderIsSystemHeader = Includer && getFileInfo(Includer).DirInfo != SrcMgr::C_User; if (const FileEntry *FE = getFileAndSuggestModule( - *this, TmpDir, IncluderAndDir.second, - IncluderIsSystemHeader, SuggestedModule)) { + TmpDir, IncluderAndDir.second, IncluderIsSystemHeader, + RequestingModule, SuggestedModule)) { if (!Includer) { assert(First && "only first includer can have no file"); return FE; @@ -736,10 +712,10 @@ const FileEntry *HeaderSearch::LookupFile( for (; i != SearchDirs.size(); ++i) { bool InUserSpecifiedSystemFramework = false; bool HasBeenMapped = false; - const FileEntry *FE = - SearchDirs[i].LookupFile(Filename, *this, SearchPath, RelativePath, - SuggestedModule, InUserSpecifiedSystemFramework, - HasBeenMapped, MappedName); + const FileEntry *FE = SearchDirs[i].LookupFile( + Filename, *this, SearchPath, RelativePath, RequestingModule, + SuggestedModule, InUserSpecifiedSystemFramework, HasBeenMapped, + MappedName); if (HasBeenMapped) { CacheLookup.MappedName = copyString(Filename, LookupFileCache.getAllocator()); @@ -803,9 +779,10 @@ const FileEntry *HeaderSearch::LookupFile( ScratchFilename += '/'; ScratchFilename += Filename; - const FileEntry *FE = LookupFile( - ScratchFilename, IncludeLoc, /*isAngled=*/true, FromDir, CurDir, - Includers.front(), SearchPath, RelativePath, SuggestedModule); + const FileEntry *FE = + LookupFile(ScratchFilename, IncludeLoc, /*isAngled=*/true, FromDir, + CurDir, Includers.front(), SearchPath, RelativePath, + RequestingModule, SuggestedModule); if (checkMSVCHeaderSearch(Diags, MSFE, FE, IncludeLoc)) { if (SuggestedModule) @@ -841,6 +818,7 @@ LookupSubframeworkHeader(StringRef Filename, const FileEntry *ContextFileEnt, SmallVectorImpl *SearchPath, SmallVectorImpl *RelativePath, + Module *RequestingModule, ModuleMap::KnownHeader *SuggestedModule) { assert(ContextFileEnt && "No context file?"); @@ -932,24 +910,10 @@ LookupSubframeworkHeader(StringRef Filename, unsigned DirInfo = getFileInfo(ContextFileEnt).DirInfo; getFileInfo(FE).DirInfo = DirInfo; - // If we're supposed to suggest a module, look for one now. - if (SuggestedModule) { - // Find the top-level framework based on this framework. - FrameworkName.pop_back(); // remove the trailing '/' - SmallVector SubmodulePath; - const DirectoryEntry *TopFrameworkDir - = ::getTopFrameworkDir(FileMgr, FrameworkName, SubmodulePath); - - // Determine the name of the top-level framework. - StringRef ModuleName = llvm::sys::path::stem(TopFrameworkDir->getName()); - - // Load this framework module. If that succeeds, find the suggested module - // for this header, if any. - bool IsSystem = false; - if (loadFrameworkModule(ModuleName, TopFrameworkDir, IsSystem)) { - *SuggestedModule = findModuleForHeader(FE); - } - } + FrameworkName.pop_back(); // remove the trailing '/' + if (!findUsableModuleForFrameworkHeader(FE, FrameworkName, RequestingModule, + SuggestedModule, /*IsSystem*/ false)) + return nullptr; return FE; } @@ -962,77 +926,112 @@ LookupSubframeworkHeader(StringRef Filename, /// header file info (\p HFI) static void mergeHeaderFileInfo(HeaderFileInfo &HFI, const HeaderFileInfo &OtherHFI) { + assert(OtherHFI.External && "expected to merge external HFI"); + HFI.isImport |= OtherHFI.isImport; HFI.isPragmaOnce |= OtherHFI.isPragmaOnce; HFI.isModuleHeader |= OtherHFI.isModuleHeader; HFI.NumIncludes += OtherHFI.NumIncludes; - + if (!HFI.ControllingMacro && !HFI.ControllingMacroID) { HFI.ControllingMacro = OtherHFI.ControllingMacro; HFI.ControllingMacroID = OtherHFI.ControllingMacroID; } - - if (OtherHFI.External) { - HFI.DirInfo = OtherHFI.DirInfo; - HFI.External = OtherHFI.External; - HFI.IndexHeaderMapHeader = OtherHFI.IndexHeaderMapHeader; - } + + HFI.DirInfo = OtherHFI.DirInfo; + HFI.External = (!HFI.IsValid || HFI.External); + HFI.IsValid = true; + HFI.IndexHeaderMapHeader = OtherHFI.IndexHeaderMapHeader; if (HFI.Framework.empty()) HFI.Framework = OtherHFI.Framework; - - HFI.Resolved = true; } /// getFileInfo - Return the HeaderFileInfo structure for the specified /// FileEntry. HeaderFileInfo &HeaderSearch::getFileInfo(const FileEntry *FE) { if (FE->getUID() >= FileInfo.size()) - FileInfo.resize(FE->getUID()+1); - - HeaderFileInfo &HFI = FileInfo[FE->getUID()]; - if (ExternalSource && !HFI.Resolved) - mergeHeaderFileInfo(HFI, ExternalSource->GetHeaderFileInfo(FE)); - HFI.IsValid = 1; - return HFI; + FileInfo.resize(FE->getUID() + 1); + + HeaderFileInfo *HFI = &FileInfo[FE->getUID()]; + // FIXME: Use a generation count to check whether this is really up to date. + if (ExternalSource && !HFI->Resolved) { + HFI->Resolved = true; + auto ExternalHFI = ExternalSource->GetHeaderFileInfo(FE); + + HFI = &FileInfo[FE->getUID()]; + if (ExternalHFI.External) + mergeHeaderFileInfo(*HFI, ExternalHFI); + } + + HFI->IsValid = true; + // We have local information about this header file, so it's no longer + // strictly external. + HFI->External = false; + return *HFI; } -bool HeaderSearch::tryGetFileInfo(const FileEntry *FE, - HeaderFileInfo &Result) const { - if (FE->getUID() >= FileInfo.size()) - return false; - const HeaderFileInfo &HFI = FileInfo[FE->getUID()]; - if (HFI.IsValid) { - Result = HFI; - return true; +const HeaderFileInfo * +HeaderSearch::getExistingFileInfo(const FileEntry *FE, + bool WantExternal) const { + // If we have an external source, ensure we have the latest information. + // FIXME: Use a generation count to check whether this is really up to date. + HeaderFileInfo *HFI; + if (ExternalSource) { + if (FE->getUID() >= FileInfo.size()) { + if (!WantExternal) + return nullptr; + FileInfo.resize(FE->getUID() + 1); + } + + HFI = &FileInfo[FE->getUID()]; + if (!WantExternal && (!HFI->IsValid || HFI->External)) + return nullptr; + if (!HFI->Resolved) { + HFI->Resolved = true; + auto ExternalHFI = ExternalSource->GetHeaderFileInfo(FE); + + HFI = &FileInfo[FE->getUID()]; + if (ExternalHFI.External) + mergeHeaderFileInfo(*HFI, ExternalHFI); + } + } else if (FE->getUID() >= FileInfo.size()) { + return nullptr; + } else { + HFI = &FileInfo[FE->getUID()]; } - return false; + + if (!HFI->IsValid || (HFI->External && !WantExternal)) + return nullptr; + + return HFI; } bool HeaderSearch::isFileMultipleIncludeGuarded(const FileEntry *File) { // Check if we've ever seen this file as a header. - if (File->getUID() >= FileInfo.size()) - return false; - - // Resolve header file info from the external source, if needed. - HeaderFileInfo &HFI = FileInfo[File->getUID()]; - if (ExternalSource && !HFI.Resolved) - mergeHeaderFileInfo(HFI, ExternalSource->GetHeaderFileInfo(File)); - - return HFI.isPragmaOnce || HFI.isImport || - HFI.ControllingMacro || HFI.ControllingMacroID; + if (auto *HFI = getExistingFileInfo(File)) + return HFI->isPragmaOnce || HFI->isImport || HFI->ControllingMacro || + HFI->ControllingMacroID; + return false; } void HeaderSearch::MarkFileModuleHeader(const FileEntry *FE, ModuleMap::ModuleHeaderRole Role, bool isCompilingModuleHeader) { - if (FE->getUID() >= FileInfo.size()) - FileInfo.resize(FE->getUID()+1); + bool isModularHeader = !(Role & ModuleMap::TextualHeader); + + // Don't mark the file info as non-external if there's nothing to change. + if (!isCompilingModuleHeader) { + if (!isModularHeader) + return; + auto *HFI = getExistingFileInfo(FE); + if (HFI && HFI->isModuleHeader) + return; + } - HeaderFileInfo &HFI = FileInfo[FE->getUID()]; - HFI.isModuleHeader = true; + auto &HFI = getFileInfo(FE); + HFI.isModuleHeader |= isModularHeader; HFI.isCompilingModuleHeader |= isCompilingModuleHeader; - HFI.setHeaderRole(Role); } bool HeaderSearch::ShouldEnterIncludeFile(Preprocessor &PP, @@ -1142,11 +1141,48 @@ HeaderSearch::findModuleForHeader(const FileEntry *File) const { if (ExternalSource) { // Make sure the external source has handled header info about this file, // which includes whether the file is part of a module. - (void)getFileInfo(File); + (void)getExistingFileInfo(File); } return ModMap.findModuleForHeader(File); } +bool HeaderSearch::findUsableModuleForHeader( + const FileEntry *File, const DirectoryEntry *Root, Module *RequestingModule, + ModuleMap::KnownHeader *SuggestedModule, bool IsSystemHeaderDir) { + if (File && SuggestedModule) { + // If there is a module that corresponds to this header, suggest it. + hasModuleMap(File->getName(), Root, IsSystemHeaderDir); + *SuggestedModule = findModuleForHeader(File); + } + return true; +} + +bool HeaderSearch::findUsableModuleForFrameworkHeader( + const FileEntry *File, StringRef FrameworkName, Module *RequestingModule, + ModuleMap::KnownHeader *SuggestedModule, bool IsSystemFramework) { + // If we're supposed to suggest a module, look for one now. + if (SuggestedModule) { + // Find the top-level framework based on this framework. + SmallVector SubmodulePath; + const DirectoryEntry *TopFrameworkDir + = ::getTopFrameworkDir(FileMgr, FrameworkName, SubmodulePath); + + // Determine the name of the top-level framework. + StringRef ModuleName = llvm::sys::path::stem(TopFrameworkDir->getName()); + + // Load this framework module. If that succeeds, find the suggested module + // for this header, if any. + loadFrameworkModule(ModuleName, TopFrameworkDir, IsSystemFramework); + + // FIXME: This can find a module not part of ModuleName, which is + // important so that we're consistent about whether this header + // corresponds to a module. Possibly we should lock down framework modules + // so that this is not possible. + *SuggestedModule = findModuleForHeader(File); + } + return true; +} + static const FileEntry *getPrivateModuleMap(const FileEntry *File, FileManager &FileMgr) { StringRef Filename = llvm::sys::path::filename(File->getName()); diff --git a/lib/Lex/Lexer.cpp b/lib/Lex/Lexer.cpp index 4007914b6c08..27b0feb48270 100644 --- a/lib/Lex/Lexer.cpp +++ b/lib/Lex/Lexer.cpp @@ -235,7 +235,7 @@ static size_t getSpellingSlow(const Token &Tok, const char *BufPtr, size_t Length = 0; const char *BufEnd = BufPtr + Tok.getLength(); - if (Tok.is(tok::string_literal)) { + if (tok::isStringLiteral(Tok.getKind())) { // Munch the encoding-prefix and opening double-quote. while (BufPtr < BufEnd) { unsigned Size; @@ -1354,7 +1354,9 @@ void Lexer::SkipBytes(unsigned Bytes, bool StartOfLine) { } static bool isAllowedIDChar(uint32_t C, const LangOptions &LangOpts) { - if (LangOpts.CPlusPlus11 || LangOpts.C11) { + if (LangOpts.AsmPreprocessor) { + return false; + } else if (LangOpts.CPlusPlus11 || LangOpts.C11) { static const llvm::sys::UnicodeCharSet C11AllowedIDChars( C11AllowedIDCharRanges); return C11AllowedIDChars.contains(C); @@ -1371,7 +1373,9 @@ static bool isAllowedIDChar(uint32_t C, const LangOptions &LangOpts) { static bool isAllowedInitiallyIDChar(uint32_t C, const LangOptions &LangOpts) { assert(isAllowedIDChar(C, LangOpts)); - if (LangOpts.CPlusPlus11 || LangOpts.C11) { + if (LangOpts.AsmPreprocessor) { + return false; + } else if (LangOpts.CPlusPlus11 || LangOpts.C11) { static const llvm::sys::UnicodeCharSet C11DisallowedInitialIDChars( C11DisallowedInitialIDCharRanges); return !C11DisallowedInitialIDChars.contains(C); @@ -1732,7 +1736,7 @@ bool Lexer::LexStringLiteral(Token &Result, const char *CurPtr, if (C == '\n' || C == '\r' || // Newline. (C == 0 && CurPtr-1 == BufferEnd)) { // End of file. if (!isLexingRawMode() && !LangOpts.AsmPreprocessor) - Diag(BufferPtr, diag::ext_unterminated_string); + Diag(BufferPtr, diag::ext_unterminated_char_or_string) << 1; FormTokenWithChars(Result, CurPtr-1, tok::unknown); return true; } @@ -1756,7 +1760,7 @@ bool Lexer::LexStringLiteral(Token &Result, const char *CurPtr, // If a nul character existed in the string, warn about it. if (NulCharacter && !isLexingRawMode()) - Diag(NulCharacter, diag::null_in_string); + Diag(NulCharacter, diag::null_in_char_or_string) << 1; // Update the location of the token as well as the BufferPtr instance var. const char *TokStart = BufferPtr; @@ -1872,7 +1876,7 @@ bool Lexer::LexAngledStringLiteral(Token &Result, const char *CurPtr) { // If a nul character existed in the string, warn about it. if (NulCharacter && !isLexingRawMode()) - Diag(NulCharacter, diag::null_in_string); + Diag(NulCharacter, diag::null_in_char_or_string) << 1; // Update the location of token as well as BufferPtr. const char *TokStart = BufferPtr; @@ -1914,7 +1918,7 @@ bool Lexer::LexCharConstant(Token &Result, const char *CurPtr, if (C == '\n' || C == '\r' || // Newline. (C == 0 && CurPtr-1 == BufferEnd)) { // End of file. if (!isLexingRawMode() && !LangOpts.AsmPreprocessor) - Diag(BufferPtr, diag::ext_unterminated_char); + Diag(BufferPtr, diag::ext_unterminated_char_or_string) << 0; FormTokenWithChars(Result, CurPtr-1, tok::unknown); return true; } @@ -1938,7 +1942,7 @@ bool Lexer::LexCharConstant(Token &Result, const char *CurPtr, // If a nul character existed in the character, warn about it. if (NulCharacter && !isLexingRawMode()) - Diag(NulCharacter, diag::null_in_char); + Diag(NulCharacter, diag::null_in_char_or_string) << 0; // Update the location of token as well as BufferPtr. const char *TokStart = BufferPtr; @@ -2956,8 +2960,11 @@ LexNextToken: case 26: // DOS & CP/M EOF: "^Z". // If we're in Microsoft extensions mode, treat this as end of file. - if (LangOpts.MicrosoftExt) + if (LangOpts.MicrosoftExt) { + if (!isLexingRawMode()) + Diag(CurPtr-1, diag::ext_ctrl_z_eof_microsoft); return LexEndOfFile(Result, CurPtr-1); + } // If Microsoft extensions are disabled, this is just random garbage. Kind = tok::unknown; diff --git a/lib/Lex/LiteralSupport.cpp b/lib/Lex/LiteralSupport.cpp index aed91648799b..1e7858af8948 100644 --- a/lib/Lex/LiteralSupport.cpp +++ b/lib/Lex/LiteralSupport.cpp @@ -159,7 +159,7 @@ static unsigned ProcessCharEscape(const char *ThisTokBegin, // Check for overflow. if (Overflow && Diags) // Too many digits to fit in Diag(Diags, Features, Loc, ThisTokBegin, EscapeBegin, ThisTokBuf, - diag::err_hex_escape_too_large); + diag::err_escape_too_large) << 0; break; } case '0': case '1': case '2': case '3': @@ -182,7 +182,7 @@ static unsigned ProcessCharEscape(const char *ThisTokBegin, if (CharWidth != 32 && (ResultChar >> CharWidth) != 0) { if (Diags) Diag(Diags, Features, Loc, ThisTokBegin, EscapeBegin, ThisTokBuf, - diag::err_octal_escape_too_large); + diag::err_escape_too_large) << 1; ResultChar &= ~0U >> (32-CharWidth); } break; @@ -538,7 +538,7 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling, // Done. } else if (isHexDigit(*s) && !(*s == 'e' || *s == 'E')) { PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, s - ThisTokBegin), - diag::err_invalid_decimal_digit) << StringRef(s, 1); + diag::err_invalid_digit) << StringRef(s, 1) << 0; hadError = true; return; } else if (*s == '.') { @@ -613,7 +613,7 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling, break; if (!isFPConstant) { - // Allow i8, i16, i32, i64, and i128. + // Allow i8, i16, i32, and i64. switch (s[1]) { case '8': s += 2; // i8 suffix @@ -623,9 +623,6 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling, if (s[2] == '6') { s += 3; // i16 suffix MicrosoftInteger = 16; - } else if (s[2] == '2' && s[3] == '8') { - s += 4; // i128 suffix - MicrosoftInteger = 128; } break; case '3': @@ -683,9 +680,8 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling, // Report an error if there are any. PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, SuffixBegin - ThisTokBegin), - isFPConstant ? diag::err_invalid_suffix_float_constant : - diag::err_invalid_suffix_integer_constant) - << StringRef(SuffixBegin, ThisTokEnd-SuffixBegin); + diag::err_invalid_suffix_constant) + << StringRef(SuffixBegin, ThisTokEnd-SuffixBegin) << isFPConstant; hadError = true; return; } @@ -770,7 +766,7 @@ void NumericLiteralParser::ParseNumberStartingWithZero(SourceLocation TokLoc) { if (noSignificand) { PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, s - ThisTokBegin), - diag::err_hexconstant_requires_digits); + diag::err_hexconstant_requires) << 1; hadError = true; return; } @@ -797,7 +793,7 @@ void NumericLiteralParser::ParseNumberStartingWithZero(SourceLocation TokLoc) { PP.Diag(TokLoc, diag::ext_hexconstant_invalid); } else if (saw_period) { PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, s-ThisTokBegin), - diag::err_hexconstant_requires_exponent); + diag::err_hexconstant_requires) << 0; hadError = true; } return; @@ -821,7 +817,7 @@ void NumericLiteralParser::ParseNumberStartingWithZero(SourceLocation TokLoc) { // Done. } else if (isHexDigit(*s)) { PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, s-ThisTokBegin), - diag::err_invalid_binary_digit) << StringRef(s, 1); + diag::err_invalid_digit) << StringRef(s, 1) << 2; hadError = true; } // Other suffixes will be diagnosed by the caller. @@ -851,7 +847,7 @@ void NumericLiteralParser::ParseNumberStartingWithZero(SourceLocation TokLoc) { // the code is using an incorrect base. if (isHexDigit(*s) && *s != 'e' && *s != 'E') { PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, s-ThisTokBegin), - diag::err_invalid_octal_digit) << StringRef(s, 1); + diag::err_invalid_digit) << StringRef(s, 1) << 1; hadError = true; return; } @@ -1420,10 +1416,23 @@ void StringLiteralParser::init(ArrayRef StringToks){ ThisTokEnd -= ThisTokBuf - Prefix; assert(ThisTokEnd >= ThisTokBuf && "malformed raw string literal"); - // Copy the string over - if (CopyStringFragment(StringToks[i], ThisTokBegin, - StringRef(ThisTokBuf, ThisTokEnd - ThisTokBuf))) - hadError = true; + // C++14 [lex.string]p4: A source-file new-line in a raw string literal + // results in a new-line in the resulting execution string-literal. + StringRef RemainingTokenSpan(ThisTokBuf, ThisTokEnd - ThisTokBuf); + while (!RemainingTokenSpan.empty()) { + // Split the string literal on \r\n boundaries. + size_t CRLFPos = RemainingTokenSpan.find("\r\n"); + StringRef BeforeCRLF = RemainingTokenSpan.substr(0, CRLFPos); + StringRef AfterCRLF = RemainingTokenSpan.substr(CRLFPos); + + // Copy everything before the \r\n sequence into the string literal. + if (CopyStringFragment(StringToks[i], ThisTokBegin, BeforeCRLF)) + hadError = true; + + // Point into the \n inside the \r\n sequence and operate on the + // remaining portion of the literal. + RemainingTokenSpan = AfterCRLF.substr(1); + } } else { if (ThisTokBuf[0] != '"') { // The file may have come from PCH and then changed after loading the diff --git a/lib/Lex/MacroInfo.cpp b/lib/Lex/MacroInfo.cpp index 109b6c12b89b..0b4292fbeae5 100644 --- a/lib/Lex/MacroInfo.cpp +++ b/lib/Lex/MacroInfo.cpp @@ -154,16 +154,20 @@ void MacroInfo::dump() const { Out << ")"; } + bool First = true; for (const Token &Tok : ReplacementTokens) { - Out << " "; + // Leading space is semantically meaningful in a macro definition, + // so preserve it in the dump output. + if (First || Tok.hasLeadingSpace()) + Out << " "; + First = false; + if (const char *Punc = tok::getPunctuatorSpelling(Tok.getKind())) Out << Punc; - else if (const char *Kwd = tok::getKeywordSpelling(Tok.getKind())) - Out << Kwd; - else if (Tok.is(tok::identifier)) - Out << Tok.getIdentifierInfo()->getName(); else if (Tok.isLiteral() && Tok.getLiteralData()) Out << StringRef(Tok.getLiteralData(), Tok.getLength()); + else if (auto *II = Tok.getIdentifierInfo()) + Out << II->getName(); else Out << Tok.getName(); } diff --git a/lib/Lex/ModuleMap.cpp b/lib/Lex/ModuleMap.cpp index 96d3e4b8fe65..a7524028a229 100644 --- a/lib/Lex/ModuleMap.cpp +++ b/lib/Lex/ModuleMap.cpp @@ -231,11 +231,9 @@ static bool violatesPrivateInclude(Module *RequestingModule, assert((!IsPrivateRole || IsPrivate) && "inconsistent headers and roles"); } #endif - return IsPrivateRole && - // FIXME: Should we map RequestingModule to its top-level module here - // too? This check is redundant with the isSubModuleOf check in - // diagnoseHeaderInclusion. - RequestedModule->getTopLevelModule() != RequestingModule; + return IsPrivateRole && (!RequestingModule || + RequestedModule->getTopLevelModule() != + RequestingModule->getTopLevelModule()); } static Module *getTopLevelOrNull(Module *M) { @@ -261,11 +259,6 @@ void ModuleMap::diagnoseHeaderInclusion(Module *RequestingModule, HeadersMap::iterator Known = findKnownHeader(File); if (Known != Headers.end()) { for (const KnownHeader &Header : Known->second) { - // If 'File' is part of 'RequestingModule' we can definitely include it. - if (Header.getModule() && - Header.getModule()->isSubModuleOf(RequestingModule)) - return; - // Remember private headers for later printing of a diagnostic. if (violatesPrivateInclude(RequestingModule, File, Header.getRole(), Header.getModule())) { @@ -320,6 +313,10 @@ void ModuleMap::diagnoseHeaderInclusion(Module *RequestingModule, static bool isBetterKnownHeader(const ModuleMap::KnownHeader &New, const ModuleMap::KnownHeader &Old) { + // Prefer available modules. + if (New.getModule()->isAvailable() && !Old.getModule()->isAvailable()) + return true; + // Prefer a public header over a private header. if ((New.getRole() & ModuleMap::PrivateHeader) != (Old.getRole() & ModuleMap::PrivateHeader)) @@ -349,15 +346,19 @@ ModuleMap::KnownHeader ModuleMap::findModuleForHeader(const FileEntry *File) { // Prefer a header from the current module over all others. if (H.getModule()->getTopLevelModule() == CompilingModule) return MakeResult(H); - // Cannot use a module if it is unavailable. - if (!H.getModule()->isAvailable()) - continue; if (!Result || isBetterKnownHeader(H, Result)) Result = H; } return MakeResult(Result); } + return MakeResult(findOrCreateModuleForHeaderInUmbrellaDir(File)); +} + +ModuleMap::KnownHeader +ModuleMap::findOrCreateModuleForHeaderInUmbrellaDir(const FileEntry *File) { + assert(!Headers.count(File) && "already have a module for this header"); + SmallVector SkippedDirs; KnownHeader H = findHeaderInUmbrellaDirs(File, SkippedDirs); if (H) { @@ -418,19 +419,22 @@ ModuleMap::KnownHeader ModuleMap::findModuleForHeader(const FileEntry *File) { UmbrellaDirs[SkippedDirs[I]] = Result; } - Headers[File].push_back(KnownHeader(Result, NormalHeader)); - - // If a header corresponds to an unavailable module, don't report - // that it maps to anything. - if (!Result->isAvailable()) - return KnownHeader(); - - return MakeResult(Headers[File].back()); + KnownHeader Header(Result, NormalHeader); + Headers[File].push_back(Header); + return Header; } return KnownHeader(); } +ArrayRef +ModuleMap::findAllModulesForHeader(const FileEntry *File) const { + auto It = Headers.find(File); + if (It == Headers.end()) + return None; + return It->second; +} + bool ModuleMap::isHeaderInUnavailableModule(const FileEntry *Header) const { return isHeaderUnavailableInModule(Header, nullptr); } @@ -577,9 +581,18 @@ static void inferFrameworkLink(Module *Mod, const DirectoryEntry *FrameworkDir, SmallString<128> LibName; LibName += FrameworkDir->getName(); llvm::sys::path::append(LibName, Mod->Name); - if (FileMgr.getFile(LibName)) { - Mod->LinkLibraries.push_back(Module::LinkLibrary(Mod->Name, - /*IsFramework=*/true)); + + // The library name of a framework has more than one possible extension since + // the introduction of the text-based dynamic library format. We need to check + // for both before we give up. + static const char *frameworkExtensions[] = {"", ".tbd"}; + for (const auto *extension : frameworkExtensions) { + llvm::sys::path::replace_extension(LibName, extension); + if (FileMgr.getFile(LibName)) { + Mod->LinkLibraries.push_back(Module::LinkLibrary(Mod->Name, + /*IsFramework=*/true)); + return; + } } } @@ -785,15 +798,27 @@ static Module::HeaderKind headerRoleToKind(ModuleMap::ModuleHeaderRole Role) { } void ModuleMap::addHeader(Module *Mod, Module::Header Header, - ModuleHeaderRole Role) { - if (!(Role & TextualHeader)) { - bool isCompilingModuleHeader = Mod->getTopLevelModule() == CompilingModule; + ModuleHeaderRole Role, bool Imported) { + KnownHeader KH(Mod, Role); + + // Only add each header to the headers list once. + // FIXME: Should we diagnose if a header is listed twice in the + // same module definition? + auto &HeaderList = Headers[Header.Entry]; + for (auto H : HeaderList) + if (H == KH) + return; + + HeaderList.push_back(KH); + Mod->Headers[headerRoleToKind(Role)].push_back(std::move(Header)); + + bool isCompilingModuleHeader = Mod->getTopLevelModule() == CompilingModule; + if (!Imported || isCompilingModuleHeader) { + // When we import HeaderFileInfo, the external source is expected to + // set the isModuleHeader flag itself. HeaderInfo.MarkFileModuleHeader(Header.Entry, Role, isCompilingModuleHeader); } - Headers[Header.Entry].push_back(KnownHeader(Mod, Role)); - - Mod->Headers[headerRoleToKind(Role)].push_back(std::move(Header)); } void ModuleMap::excludeHeader(Module *Mod, Module::Header Header) { @@ -1015,7 +1040,17 @@ namespace clang { /// \brief The active module. Module *ActiveModule; - + + /// \brief Whether a module uses the 'requires excluded' hack to mark its + /// contents as 'textual'. + /// + /// On older Darwin SDK versions, 'requires excluded' is used to mark the + /// contents of the Darwin.C.excluded (assert.h) and Tcl.Private modules as + /// non-modular headers. For backwards compatibility, we continue to + /// support this idiom for just these modules, and map the headers to + /// 'textual' to match the original intent. + llvm::SmallPtrSet UsesRequiresExcludedHack; + /// \brief Consume the current token and return its location. SourceLocation consumeToken(); @@ -1570,6 +1605,38 @@ void ModuleMapParser::parseExternModuleDecl() { : File->getDir(), ExternLoc); } +/// Whether to add the requirement \p Feature to the module \p M. +/// +/// This preserves backwards compatibility for two hacks in the Darwin system +/// module map files: +/// +/// 1. The use of 'requires excluded' to make headers non-modular, which +/// should really be mapped to 'textual' now that we have this feature. We +/// drop the 'excluded' requirement, and set \p IsRequiresExcludedHack to +/// true. Later, this bit will be used to map all the headers inside this +/// module to 'textual'. +/// +/// This affects Darwin.C.excluded (for assert.h) and Tcl.Private. +/// +/// 2. Removes a bogus cplusplus requirement from IOKit.avc. This requirement +/// was never correct and causes issues now that we check it, so drop it. +static bool shouldAddRequirement(Module *M, StringRef Feature, + bool &IsRequiresExcludedHack) { + static const StringRef DarwinCExcluded[] = {"Darwin", "C", "excluded"}; + static const StringRef TclPrivate[] = {"Tcl", "Private"}; + static const StringRef IOKitAVC[] = {"IOKit", "avc"}; + + if (Feature == "excluded" && (M->fullModuleNameIs(DarwinCExcluded) || + M->fullModuleNameIs(TclPrivate))) { + IsRequiresExcludedHack = true; + return false; + } else if (Feature == "cplusplus" && M->fullModuleNameIs(IOKitAVC)) { + return false; + } + + return true; +} + /// \brief Parse a requires declaration. /// /// requires-declaration: @@ -1605,9 +1672,18 @@ void ModuleMapParser::parseRequiresDecl() { std::string Feature = Tok.getString(); consumeToken(); - // Add this feature. - ActiveModule->addRequirement(Feature, RequiredState, - Map.LangOpts, *Map.Target); + bool IsRequiresExcludedHack = false; + bool ShouldAddRequirement = + shouldAddRequirement(ActiveModule, Feature, IsRequiresExcludedHack); + + if (IsRequiresExcludedHack) + UsesRequiresExcludedHack.insert(ActiveModule); + + if (ShouldAddRequirement) { + // Add this feature. + ActiveModule->addRequirement(Feature, RequiredState, Map.LangOpts, + *Map.Target); + } if (!Tok.is(MMToken::Comma)) break; @@ -1657,9 +1733,16 @@ void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken, consumeToken(); } } + if (LeadingToken == MMToken::TextualKeyword) Role = ModuleMap::ModuleHeaderRole(Role | ModuleMap::TextualHeader); + if (UsesRequiresExcludedHack.count(ActiveModule)) { + // Mark this header 'textual' (see doc comment for + // Module::UsesRequiresExcludedHack). + Role = ModuleMap::ModuleHeaderRole(Role | ModuleMap::TextualHeader); + } + if (LeadingToken != MMToken::HeaderKeyword) { if (!Tok.is(MMToken::HeaderKeyword)) { Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header) @@ -1797,6 +1880,11 @@ void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken, } } +static int compareModuleHeaders(const Module::Header *A, + const Module::Header *B) { + return A->NameAsWritten.compare(B->NameAsWritten); +} + /// \brief Parse an umbrella directory declaration. /// /// umbrella-dir-declaration: @@ -1838,14 +1926,38 @@ void ModuleMapParser::parseUmbrellaDirDecl(SourceLocation UmbrellaLoc) { HadError = true; return; } - + + if (UsesRequiresExcludedHack.count(ActiveModule)) { + // Mark this header 'textual' (see doc comment for + // ModuleMapParser::UsesRequiresExcludedHack). Although iterating over the + // directory is relatively expensive, in practice this only applies to the + // uncommonly used Tcl module on Darwin platforms. + std::error_code EC; + SmallVector Headers; + for (llvm::sys::fs::recursive_directory_iterator I(Dir->getName(), EC), E; + I != E && !EC; I.increment(EC)) { + if (const FileEntry *FE = SourceMgr.getFileManager().getFile(I->path())) { + + Module::Header Header = {I->path(), FE}; + Headers.push_back(std::move(Header)); + } + } + + // Sort header paths so that the pcm doesn't depend on iteration order. + llvm::array_pod_sort(Headers.begin(), Headers.end(), compareModuleHeaders); + + for (auto &Header : Headers) + Map.addHeader(ActiveModule, std::move(Header), ModuleMap::TextualHeader); + return; + } + if (Module *OwningModule = Map.UmbrellaDirs[Dir]) { Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash) << OwningModule->getFullModuleName(); HadError = true; return; - } - + } + // Record this umbrella directory. Map.setUmbrellaDir(ActiveModule, Dir, DirName); } @@ -2335,9 +2447,14 @@ bool ModuleMap::parseModuleMapFile(const FileEntry *File, bool IsSystem, // Parse this module map file. Lexer L(ID, SourceMgr.getBuffer(ID), SourceMgr, MMapLangOpts); + SourceLocation Start = L.getSourceLocation(); ModuleMapParser Parser(L, SourceMgr, Target, Diags, *this, File, Dir, BuiltinIncludeDir, IsSystem); bool Result = Parser.parseModuleMapFile(); ParsedModuleMap[File] = Result; + + // Notify callbacks that we parsed it. + for (const auto &Cb : Callbacks) + Cb->moduleMapFileRead(Start, *File, IsSystem); return Result; } diff --git a/lib/Lex/PPDirectives.cpp b/lib/Lex/PPDirectives.cpp index ce64538de41b..c02a0cb8d302 100644 --- a/lib/Lex/PPDirectives.cpp +++ b/lib/Lex/PPDirectives.cpp @@ -611,6 +611,8 @@ const FileEntry *Preprocessor::LookupFile( SmallVectorImpl *RelativePath, ModuleMap::KnownHeader *SuggestedModule, bool SkipCache) { + Module *RequestingModule = getModuleForLocation(FilenameLoc); + // If the header lookup mechanism may be relative to the current inclusion // stack, record the parent #includes. SmallVector, 16> @@ -648,8 +650,7 @@ const FileEntry *Preprocessor::LookupFile( for (unsigned i = 0, e = IncludeMacroStack.size(); i != e; ++i) { IncludeStackInfo &ISEntry = IncludeMacroStack[e - i - 1]; if (IsFileLexer(ISEntry)) - if ((FileEnt = SourceMgr.getFileEntryForID( - ISEntry.ThePPLexer->getFileID()))) + if ((FileEnt = ISEntry.ThePPLexer->getFileEntry())) Includers.push_back(std::make_pair(FileEnt, FileEnt->getDir())); } } @@ -664,8 +665,8 @@ const FileEntry *Preprocessor::LookupFile( const DirectoryLookup *TmpFromDir = nullptr; while (const FileEntry *FE = HeaderInfo.LookupFile( Filename, FilenameLoc, isAngled, TmpFromDir, TmpCurDir, - Includers, SearchPath, RelativePath, SuggestedModule, - SkipCache)) { + Includers, SearchPath, RelativePath, RequestingModule, + SuggestedModule, SkipCache)) { // Keep looking as if this file did a #include_next. TmpFromDir = TmpCurDir; ++TmpFromDir; @@ -681,11 +682,11 @@ const FileEntry *Preprocessor::LookupFile( // Do a standard file entry lookup. const FileEntry *FE = HeaderInfo.LookupFile( Filename, FilenameLoc, isAngled, FromDir, CurDir, Includers, SearchPath, - RelativePath, SuggestedModule, SkipCache); + RelativePath, RequestingModule, SuggestedModule, SkipCache); if (FE) { if (SuggestedModule && !LangOpts.AsmPreprocessor) HeaderInfo.getModuleMap().diagnoseHeaderInclusion( - getModuleForLocation(FilenameLoc), FilenameLoc, Filename, FE); + RequestingModule, FilenameLoc, Filename, FE); return FE; } @@ -694,13 +695,14 @@ const FileEntry *Preprocessor::LookupFile( // to one of the headers on the #include stack. Walk the list of the current // headers on the #include stack and pass them to HeaderInfo. if (IsFileLexer()) { - if ((CurFileEnt = SourceMgr.getFileEntryForID(CurPPLexer->getFileID()))) { + if ((CurFileEnt = CurPPLexer->getFileEntry())) { if ((FE = HeaderInfo.LookupSubframeworkHeader(Filename, CurFileEnt, SearchPath, RelativePath, + RequestingModule, SuggestedModule))) { if (SuggestedModule && !LangOpts.AsmPreprocessor) HeaderInfo.getModuleMap().diagnoseHeaderInclusion( - getModuleForLocation(FilenameLoc), FilenameLoc, Filename, FE); + RequestingModule, FilenameLoc, Filename, FE); return FE; } } @@ -709,14 +711,13 @@ const FileEntry *Preprocessor::LookupFile( for (unsigned i = 0, e = IncludeMacroStack.size(); i != e; ++i) { IncludeStackInfo &ISEntry = IncludeMacroStack[e-i-1]; if (IsFileLexer(ISEntry)) { - if ((CurFileEnt = - SourceMgr.getFileEntryForID(ISEntry.ThePPLexer->getFileID()))) { + if ((CurFileEnt = ISEntry.ThePPLexer->getFileEntry())) { if ((FE = HeaderInfo.LookupSubframeworkHeader( Filename, CurFileEnt, SearchPath, RelativePath, - SuggestedModule))) { + RequestingModule, SuggestedModule))) { if (SuggestedModule && !LangOpts.AsmPreprocessor) HeaderInfo.getModuleMap().diagnoseHeaderInclusion( - getModuleForLocation(FilenameLoc), FilenameLoc, Filename, FE); + RequestingModule, FilenameLoc, Filename, FE); return FE; } } @@ -1674,6 +1675,29 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc, getLangOpts().CurrentModule && SuggestedModule.getModule()->getTopLevelModuleName() != getLangOpts().ImplementationOfModule) { + + // If this include corresponds to a module but that module is + // unavailable, diagnose the situation and bail out. + if (!SuggestedModule.getModule()->isAvailable()) { + clang::Module::Requirement Requirement; + clang::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; + } + Diag(FilenameTok.getLocation(), + diag::note_implicit_top_level_module_import_here) + << M->getTopLevelModuleName(); + return; + } + // Compute the module access path corresponding to this module. // FIXME: Should we have a second loadModule() overload to avoid this // extra lookup step? @@ -1776,7 +1800,7 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc, if (IncludePos.isMacroID()) IncludePos = SourceMgr.getExpansionRange(IncludePos).second; FileID FID = SourceMgr.createFileID(File, IncludePos, FileCharacter); - assert(!FID.isInvalid() && "Expected valid file ID"); + assert(FID.isValid() && "Expected valid file ID"); // If all is good, enter the new file! if (EnterSourceFile(FID, CurDir, FilenameTok.getLocation())) @@ -1925,7 +1949,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[0], Arguments.size(), BP); + MI->setArgumentList(Arguments, BP); return false; case tok::eod: // #define X( Diag(Tok, diag::err_pp_missing_rparen_in_macro_def); @@ -1959,7 +1983,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[0], Arguments.size(), BP); + MI->setArgumentList(Arguments, BP); return false; case tok::comma: // #define X(A, break; @@ -1975,7 +1999,7 @@ bool Preprocessor::ReadMacroDefinitionArgList(MacroInfo *MI, Token &Tok) { } MI->setIsGNUVarargs(); - MI->setArgumentList(&Arguments[0], Arguments.size(), BP); + MI->setArgumentList(Arguments, BP); return false; } } @@ -2019,13 +2043,9 @@ static bool isConfigurationPattern(Token &MacroName, MacroInfo *MI, } // #define inline - if (MacroName.isOneOf(tok::kw_extern, tok::kw_inline, tok::kw_static, - tok::kw_const) && - MI->getNumTokens() == 0) { - return true; - } - - return false; + return MacroName.isOneOf(tok::kw_extern, tok::kw_inline, tok::kw_static, + tok::kw_const) && + MI->getNumTokens() == 0; } /// HandleDefineDirective - Implements \#define. This consumes the entire macro @@ -2240,6 +2260,30 @@ void Preprocessor::HandleDefineDirective(Token &DefineTok, // 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. if (const MacroInfo *OtherMI=getMacroInfo(MacroNameTok.getIdentifierInfo())) { + // In Objective-C, ignore attempts to directly redefine the builtin + // definitions of the ownership qualifiers. It's still possible to + // #undef them. + auto isObjCProtectedMacro = [](const IdentifierInfo *II) -> bool { + return II->isStr("__strong") || + II->isStr("__weak") || + II->isStr("__unsafe_unretained") || + II->isStr("__autoreleasing"); + }; + if (getLangOpts().ObjC1 && + SourceMgr.getFileID(OtherMI->getDefinitionLoc()) + == getPredefinesFileID() && + isObjCProtectedMacro(MacroNameTok.getIdentifierInfo())) { + // Warn if it changes the tokens. + if ((!getDiagnostics().getSuppressSystemWarnings() || + !SourceMgr.isInSystemHeader(DefineTok.getLocation())) && + !MI->isIdenticalTo(*OtherMI, *this, + /*Syntactic=*/LangOpts.MicrosoftExt)) { + Diag(MI->getDefinitionLoc(), diag::warn_pp_objc_macro_redef_ignored); + } + assert(!OtherMI->isWarnIfUnused()); + return; + } + // It is very common for system headers to have tons of macro redefinitions // and for warnings to be disabled in system headers. If this is the case, // then don't bother calling MacroInfo::isIdenticalTo. diff --git a/lib/Lex/PPExpressions.cpp b/lib/Lex/PPExpressions.cpp index 44513023395d..c40598c06756 100644 --- a/lib/Lex/PPExpressions.cpp +++ b/lib/Lex/PPExpressions.cpp @@ -42,7 +42,7 @@ public: unsigned getBitWidth() const { return Val.getBitWidth(); } bool isUnsigned() const { return Val.isUnsigned(); } - const SourceRange &getRange() const { return Range; } + SourceRange getRange() const { return Range; } void setRange(SourceLocation L) { Range.setBegin(L); Range.setEnd(L); } void setRange(SourceLocation B, SourceLocation E) { @@ -549,12 +549,12 @@ static bool EvaluateDirectiveSubExpr(PPValue &LHS, unsigned MinPrec, // value was negative, warn about it. if (ValueLive && Res.isUnsigned()) { if (!LHS.isUnsigned() && LHS.Val.isNegative()) - PP.Diag(OpLoc, diag::warn_pp_convert_lhs_to_positive) + PP.Diag(OpLoc, diag::warn_pp_convert_to_positive) << 0 << LHS.Val.toString(10, true) + " to " + LHS.Val.toString(10, false) << LHS.getRange() << RHS.getRange(); if (!RHS.isUnsigned() && RHS.Val.isNegative()) - PP.Diag(OpLoc, diag::warn_pp_convert_rhs_to_positive) + PP.Diag(OpLoc, diag::warn_pp_convert_to_positive) << 1 << RHS.Val.toString(10, true) + " to " + RHS.Val.toString(10, false) << LHS.getRange() << RHS.getRange(); diff --git a/lib/Lex/PPLexerChange.cpp b/lib/Lex/PPLexerChange.cpp index c231e18eecc3..2f09841c5b5d 100644 --- a/lib/Lex/PPLexerChange.cpp +++ b/lib/Lex/PPLexerChange.cpp @@ -18,6 +18,7 @@ #include "clang/Lex/HeaderSearch.h" #include "clang/Lex/LexDiagnostic.h" #include "clang/Lex/MacroInfo.h" +#include "clang/Lex/PTHManager.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/MemoryBuffer.h" @@ -120,7 +121,7 @@ void Preprocessor::EnterSourceFileWithLexer(Lexer *TheLexer, CurSubmodule = nullptr; if (CurLexerKind != CLK_LexAfterModuleImport) CurLexerKind = CLK_Lexer; - + // Notify the client, if desired, that we are in a new source file. if (Callbacks && !CurLexer->Is_PragmaLexer) { SrcMgr::CharacteristicKind FileType = @@ -300,8 +301,7 @@ bool Preprocessor::HandleEndOfFile(Token &Result, bool isEndOfMacro) { if (const IdentifierInfo *ControllingMacro = CurPPLexer->MIOpt.GetControllingMacroAtEndOfFile()) { // Okay, this has a controlling macro, remember in HeaderFileInfo. - if (const FileEntry *FE = - SourceMgr.getFileEntryForID(CurPPLexer->getFileID())) { + if (const FileEntry *FE = CurPPLexer->getFileEntry()) { HeaderInfo.SetFileControllingMacro(FE, ControllingMacro); if (MacroInfo *MI = getMacroInfo(const_cast(ControllingMacro))) { @@ -561,7 +561,6 @@ void Preprocessor::RemoveTopOfLexerStack() { void Preprocessor::HandleMicrosoftCommentPaste(Token &Tok) { assert(CurTokenLexer && !CurPPLexer && "Pasted comment can only be formed from macro"); - // We handle this by scanning for the closest real lexer, switching it to // raw mode and preprocessor mode. This will cause it to return \n as an // explicit EOD token. diff --git a/lib/Lex/PPMacroExpansion.cpp b/lib/Lex/PPMacroExpansion.cpp index 64ce8c918258..18348df0a39e 100644 --- a/lib/Lex/PPMacroExpansion.cpp +++ b/lib/Lex/PPMacroExpansion.cpp @@ -145,8 +145,12 @@ void Preprocessor::updateModuleMacroInfo(const IdentifierInfo *II, NumHiddenOverrides[O] = -1; // Collect all macros that are not overridden by a visible macro. - llvm::SmallVector Worklist(Leaf->second.begin(), - Leaf->second.end()); + llvm::SmallVector Worklist; + for (auto *LeafMM : Leaf->second) { + assert(LeafMM->getNumOverridingMacros() == 0 && "leaf macro overridden"); + if (NumHiddenOverrides.lookup(LeafMM) == 0) + Worklist.push_back(LeafMM); + } while (!Worklist.empty()) { auto *MM = Worklist.pop_back_val(); if (CurSubmoduleState->VisibleModules.isVisible(MM->getOwningModule())) { @@ -593,9 +597,7 @@ static bool CheckMatchedBrackets(const SmallVectorImpl &Tokens) { Brackets.pop_back(); } } - if (!Brackets.empty()) - return false; - return true; + return Brackets.empty(); } /// GenerateNewArgTokens - Returns true if OldTokens can be converted to a new @@ -867,7 +869,7 @@ MacroArgs *Preprocessor::ReadFunctionLikeMacroArgs(Token &MacroName, DiagnosticBuilder DB = Diag(MacroName, diag::note_init_list_at_beginning_of_macro_argument); - for (const SourceRange &Range : InitLists) + for (SourceRange Range : InitLists) DB << Range; } return nullptr; @@ -876,7 +878,7 @@ MacroArgs *Preprocessor::ReadFunctionLikeMacroArgs(Token &MacroName, return nullptr; DiagnosticBuilder DB = Diag(MacroName, diag::note_suggest_parens_for_macro); - for (const SourceRange &ParenLocation : ParenHints) { + for (SourceRange ParenLocation : ParenHints) { DB << FixItHint::CreateInsertion(ParenLocation.getBegin(), "("); DB << FixItHint::CreateInsertion(ParenLocation.getEnd(), ")"); } @@ -1057,6 +1059,9 @@ static bool HasFeature(const Preprocessor &PP, const IdentifierInfo *II) { .Case("attribute_availability", true) .Case("attribute_availability_with_message", true) .Case("attribute_availability_app_extension", true) + .Case("attribute_availability_with_version_underscores", true) + .Case("attribute_availability_tvos", true) + .Case("attribute_availability_watchos", true) .Case("attribute_cf_returns_not_retained", true) .Case("attribute_cf_returns_retained", true) .Case("attribute_cf_returns_on_parameters", true) @@ -1075,7 +1080,7 @@ static bool HasFeature(const Preprocessor &PP, const IdentifierInfo *II) { .Case("blocks", LangOpts.Blocks) .Case("c_thread_safety_attributes", true) .Case("cxx_exceptions", LangOpts.CXXExceptions) - .Case("cxx_rtti", LangOpts.RTTI) + .Case("cxx_rtti", LangOpts.RTTI && LangOpts.RTTIData) .Case("enumerator_attributes", true) .Case("nullability", true) .Case("memory_sanitizer", LangOpts.Sanitize.has(SanitizerKind::Memory)) @@ -1084,7 +1089,7 @@ static bool HasFeature(const Preprocessor &PP, const IdentifierInfo *II) { // Objective-C features .Case("objc_arr", LangOpts.ObjCAutoRefCount) // FIXME: REMOVE? .Case("objc_arc", LangOpts.ObjCAutoRefCount) - .Case("objc_arc_weak", LangOpts.ObjCARCWeak) + .Case("objc_arc_weak", LangOpts.ObjCWeak) .Case("objc_default_synthesize_properties", LangOpts.ObjC2) .Case("objc_fixed_enum", LangOpts.ObjC2) .Case("objc_instancetype", LangOpts.ObjC2) @@ -1629,16 +1634,23 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) { Value = FeatureII->getTokenID() == tok::identifier; else if (II == Ident__has_builtin) { // Check for a builtin is trivial. - Value = FeatureII->getBuiltinID() != 0; + if (FeatureII->getBuiltinID() != 0) { + Value = true; + } else { + StringRef Feature = FeatureII->getName(); + Value = llvm::StringSwitch(Feature) + .Case("__make_integer_seq", getLangOpts().CPlusPlus) + .Default(false); + } } else if (II == Ident__has_attribute) Value = hasAttribute(AttrSyntax::GNU, nullptr, FeatureII, - getTargetInfo().getTriple(), getLangOpts()); + getTargetInfo(), getLangOpts()); else if (II == Ident__has_cpp_attribute) Value = hasAttribute(AttrSyntax::CXX, ScopeII, FeatureII, - getTargetInfo().getTriple(), getLangOpts()); + getTargetInfo(), getLangOpts()); else if (II == Ident__has_declspec) Value = hasAttribute(AttrSyntax::Declspec, nullptr, FeatureII, - getTargetInfo().getTriple(), getLangOpts()); + getTargetInfo(), getLangOpts()); else if (II == Ident__has_extension) Value = HasExtension(*this, FeatureII); else { diff --git a/lib/Lex/Pragma.cpp b/lib/Lex/Pragma.cpp index 5eb665549e86..3134790ccb90 100644 --- a/lib/Lex/Pragma.cpp +++ b/lib/Lex/Pragma.cpp @@ -38,7 +38,7 @@ PragmaHandler::~PragmaHandler() { // EmptyPragmaHandler Implementation. //===----------------------------------------------------------------------===// -EmptyPragmaHandler::EmptyPragmaHandler() {} +EmptyPragmaHandler::EmptyPragmaHandler(StringRef Name) : PragmaHandler(Name) {} void EmptyPragmaHandler::HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, @@ -191,9 +191,13 @@ void Preprocessor::Handle_Pragma(Token &Tok) { Lex(Tok); if (!tok::isStringLiteral(Tok.getKind())) { Diag(PragmaLoc, diag::err__Pragma_malformed); - // Skip this token, and the ')', if present. + // Skip bad tokens, and the ')', if present. if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::eof)) Lex(Tok); + while (Tok.isNot(tok::r_paren) && + !Tok.isAtStartOfLine() && + Tok.isNot(tok::eof)) + Lex(Tok); if (Tok.is(tok::r_paren)) Lex(Tok); return _PragmaLexing.failed(); diff --git a/lib/Lex/PreprocessingRecord.cpp b/lib/Lex/PreprocessingRecord.cpp index a423041a2d95..32e6de69f0db 100644 --- a/lib/Lex/PreprocessingRecord.cpp +++ b/lib/Lex/PreprocessingRecord.cpp @@ -66,7 +66,7 @@ PreprocessingRecord::getPreprocessedEntitiesInRange(SourceRange Range) { static bool isPreprocessedEntityIfInFileID(PreprocessedEntity *PPE, FileID FID, SourceManager &SM) { - assert(!FID.isInvalid()); + assert(FID.isValid()); if (!PPE) return false; diff --git a/lib/Lex/Preprocessor.cpp b/lib/Lex/Preprocessor.cpp index e2db638a33d0..142d9ce09049 100644 --- a/lib/Lex/Preprocessor.cpp +++ b/lib/Lex/Preprocessor.cpp @@ -38,6 +38,7 @@ #include "clang/Lex/MacroArgs.h" #include "clang/Lex/MacroInfo.h" #include "clang/Lex/ModuleLoader.h" +#include "clang/Lex/PTHManager.h" #include "clang/Lex/Pragma.h" #include "clang/Lex/PreprocessingRecord.h" #include "clang/Lex/PreprocessorOptions.h" @@ -62,20 +63,19 @@ Preprocessor::Preprocessor(IntrusiveRefCntPtr PPOpts, IdentifierInfoLookup *IILookup, bool OwnsHeaders, TranslationUnitKind TUKind) : PPOpts(PPOpts), Diags(&diags), LangOpts(opts), Target(nullptr), - FileMgr(Headers.getFileMgr()), SourceMgr(SM), - ScratchBuf(new ScratchBuffer(SourceMgr)),HeaderInfo(Headers), + AuxTarget(nullptr), FileMgr(Headers.getFileMgr()), SourceMgr(SM), + 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(0), - 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) { + IncrementalProcessing(false), TUKind(TUKind), CodeComplete(nullptr), + CodeCompletionFile(nullptr), CodeCompletionOffset(0), + LastTokenWasAt(false), ModuleImportExpectsIdentifier(false), + CodeCompletionReached(0), 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) { OwnsHeaderSearch = OwnsHeaders; CounterValue = 0; // __COUNTER__ starts at 0. @@ -170,13 +170,18 @@ Preprocessor::~Preprocessor() { delete &HeaderInfo; } -void Preprocessor::Initialize(const TargetInfo &Target) { +void Preprocessor::Initialize(const TargetInfo &Target, + const TargetInfo *AuxTarget) { assert((!this->Target || this->Target == &Target) && "Invalid override of target information"); this->Target = &Target; - + + assert((!this->AuxTarget || this->AuxTarget == AuxTarget) && + "Invalid override of aux target information."); + this->AuxTarget = AuxTarget; + // Initialize information about built-ins. - BuiltinInfo.InitializeTarget(Target); + BuiltinInfo.InitializeTarget(Target, AuxTarget); HeaderInfo.setTarget(Target); } @@ -515,7 +520,7 @@ void Preprocessor::EnterMainSourceFile() { llvm::MemoryBuffer::getMemBufferCopy(Predefines, ""); assert(SB && "Cannot create predefined source buffer"); FileID FID = SourceMgr.createFileID(std::move(SB)); - assert(!FID.isInvalid() && "Could not create FileID for predefines?"); + assert(FID.isValid() && "Could not create FileID for predefines?"); setPredefinesFileID(FID); // Start parsing the predefines. @@ -712,7 +717,7 @@ bool Preprocessor::HandleIdentifier(Token &Identifier) { } void Preprocessor::Lex(Token &Result) { - // We loop here until a lex function retuns a token; this avoids recursion. + // We loop here until a lex function returns a token; this avoids recursion. bool ReturnedToken; do { switch (CurLexerKind) { diff --git a/lib/Lex/TokenLexer.cpp b/lib/Lex/TokenLexer.cpp index e7512fa2831a..c42966928e52 100644 --- a/lib/Lex/TokenLexer.cpp +++ b/lib/Lex/TokenLexer.cpp @@ -624,21 +624,22 @@ bool TokenLexer::PasteTokens(Token &Tok) { // error. This occurs with "x ## +" and other stuff. Return with Tok // unmodified and with RHS as the next token to lex. if (isInvalid) { + // Explicitly convert the token location to have proper expansion + // information so that the user knows where it came from. + SourceManager &SM = PP.getSourceManager(); + SourceLocation Loc = + SM.createExpansionLoc(PasteOpLoc, ExpandLocStart, ExpandLocEnd, 2); + // Test for the Microsoft extension of /##/ turning into // here on the // error path. if (PP.getLangOpts().MicrosoftExt && Tok.is(tok::slash) && RHS.is(tok::slash)) { - HandleMicrosoftCommentPaste(Tok); + HandleMicrosoftCommentPaste(Tok, Loc); return true; } // Do not emit the error when preprocessing assembler code. if (!PP.getLangOpts().AsmPreprocessor) { - // Explicitly convert the token location to have proper expansion - // information so that the user knows where it came from. - SourceManager &SM = PP.getSourceManager(); - SourceLocation Loc = - SM.createExpansionLoc(PasteOpLoc, ExpandLocStart, ExpandLocEnd, 2); // If we're in microsoft extensions mode, downgrade this from a hard // error to an extension that defaults to an error. This allows // disabling it. @@ -719,7 +720,9 @@ bool TokenLexer::isParsingPreprocessorDirective() const { /// macro, other active macros, and anything left on the current physical /// source line of the expanded buffer. Handle this by returning the /// first token on the next line. -void TokenLexer::HandleMicrosoftCommentPaste(Token &Tok) { +void TokenLexer::HandleMicrosoftCommentPaste(Token &Tok, SourceLocation OpLoc) { + PP.Diag(OpLoc, diag::ext_comment_paste_microsoft); + // We 'comment out' the rest of this macro by just ignoring the rest of the // tokens that have not been lexed yet, if any. -- cgit v1.2.3