diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2017-01-02 19:18:08 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2017-01-02 19:18:08 +0000 |
commit | bab175ec4b075c8076ba14c762900392533f6ee4 (patch) | |
tree | 01f4f29419a2cb10abe13c1e63cd2a66068b0137 /lib/Lex | |
parent | 8b7a8012d223fac5d17d16a66bb39168a9a1dfc0 (diff) |
Notes
Diffstat (limited to 'lib/Lex')
-rw-r--r-- | lib/Lex/HeaderMap.cpp | 2 | ||||
-rw-r--r-- | lib/Lex/HeaderSearch.cpp | 128 | ||||
-rw-r--r-- | lib/Lex/Lexer.cpp | 82 | ||||
-rw-r--r-- | lib/Lex/LiteralSupport.cpp | 52 | ||||
-rw-r--r-- | lib/Lex/MacroInfo.cpp | 2 | ||||
-rw-r--r-- | lib/Lex/ModuleMap.cpp | 119 | ||||
-rw-r--r-- | lib/Lex/PPCaching.cpp | 4 | ||||
-rw-r--r-- | lib/Lex/PPDirectives.cpp | 87 | ||||
-rw-r--r-- | lib/Lex/PPExpressions.cpp | 17 | ||||
-rw-r--r-- | lib/Lex/PPLexerChange.cpp | 16 | ||||
-rw-r--r-- | lib/Lex/PPMacroExpansion.cpp | 95 | ||||
-rw-r--r-- | lib/Lex/PTHLexer.cpp | 17 | ||||
-rw-r--r-- | lib/Lex/Pragma.cpp | 66 | ||||
-rw-r--r-- | lib/Lex/PreprocessingRecord.cpp | 15 | ||||
-rw-r--r-- | lib/Lex/Preprocessor.cpp | 73 | ||||
-rw-r--r-- | lib/Lex/TokenConcatenation.cpp | 2 | ||||
-rw-r--r-- | lib/Lex/TokenLexer.cpp | 11 |
17 files changed, 550 insertions, 238 deletions
diff --git a/lib/Lex/HeaderMap.cpp b/lib/Lex/HeaderMap.cpp index 4cace5b002450..24a14b6cdb573 100644 --- a/lib/Lex/HeaderMap.cpp +++ b/lib/Lex/HeaderMap.cpp @@ -106,7 +106,7 @@ bool HeaderMapImpl::checkHeader(const llvm::MemoryBuffer &File, /// getFileName - Return the filename of the headermap. -const char *HeaderMapImpl::getFileName() const { +StringRef HeaderMapImpl::getFileName() const { return FileBuffer->getBufferIdentifier(); } diff --git a/lib/Lex/HeaderSearch.cpp b/lib/Lex/HeaderSearch.cpp index e5cc30e41c573..b5228fc6c8cbd 100644 --- a/lib/Lex/HeaderSearch.cpp +++ b/lib/Lex/HeaderSearch.cpp @@ -26,7 +26,6 @@ #include "llvm/Support/Capacity.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Path.h" -#include "llvm/Support/raw_ostream.h" #include <cstdio> #include <utility> #if defined(LLVM_ON_UNIX) @@ -37,9 +36,12 @@ using namespace clang; const IdentifierInfo * HeaderFileInfo::getControllingMacro(ExternalPreprocessorSource *External) { if (ControllingMacro) { - if (ControllingMacro->isOutOfDate()) + if (ControllingMacro->isOutOfDate()) { + assert(External && "We must have an external source if we have a " + "controlling macro that is out of date."); External->updateOutOfDateIdentifier( *const_cast<IdentifierInfo *>(ControllingMacro)); + } return ControllingMacro; } @@ -119,14 +121,39 @@ const HeaderMap *HeaderSearch::CreateHeaderMap(const FileEntry *FE) { return nullptr; } +/// \brief Get filenames for all registered header maps. +void HeaderSearch::getHeaderMapFileNames( + SmallVectorImpl<std::string> &Names) const { + for (auto &HM : HeaderMaps) + Names.push_back(HM.first->getName()); +} + std::string HeaderSearch::getModuleFileName(Module *Module) { const FileEntry *ModuleMap = getModuleMap().getModuleMapFileForUniquing(Module); - return getModuleFileName(Module->Name, ModuleMap->getName()); + return getModuleFileName(Module->Name, ModuleMap->getName(), + /*UsePrebuiltPath*/false); } std::string HeaderSearch::getModuleFileName(StringRef ModuleName, - StringRef ModuleMapPath) { + StringRef ModuleMapPath, + bool UsePrebuiltPath) { + if (UsePrebuiltPath) { + if (HSOpts->PrebuiltModulePaths.empty()) + return std::string(); + + // Go though each prebuilt module path and try to find the pcm file. + for (const std::string &Dir : HSOpts->PrebuiltModulePaths) { + SmallString<256> Result(Dir); + llvm::sys::fs::make_absolute(Result); + + llvm::sys::path::append(Result, ModuleName + ".pcm"); + if (getFileMgr().getFile(Result.str())) + return Result.str().str(); + } + return std::string(); + } + // If we don't have a module cache path or aren't supposed to use one, we // can't do anything. if (getModuleCachePath().empty()) @@ -167,16 +194,36 @@ Module *HeaderSearch::lookupModule(StringRef ModuleName, bool AllowSearch) { Module *Module = ModMap.findModule(ModuleName); if (Module || !AllowSearch || !HSOpts->ImplicitModuleMaps) return Module; - + + StringRef SearchName = ModuleName; + Module = lookupModule(ModuleName, SearchName); + + // The facility for "private modules" -- adjacent, optional module maps named + // module.private.modulemap that are supposed to define private submodules -- + // is sometimes misused by frameworks that name their associated private + // module FooPrivate, rather than as a submodule named Foo.Private as + // intended. Here we compensate for such cases by looking in directories named + // Foo.framework, when we previously looked and failed to find a + // FooPrivate.framework. + if (!Module && SearchName.consume_back("Private")) + Module = lookupModule(ModuleName, SearchName); + return Module; +} + +Module *HeaderSearch::lookupModule(StringRef ModuleName, StringRef SearchName) { + Module *Module = nullptr; + // Look through the various header search paths to load any available module // maps, searching for a module map that describes this module. for (unsigned Idx = 0, N = SearchDirs.size(); Idx != N; ++Idx) { if (SearchDirs[Idx].isFramework()) { - // Search for or infer a module map for a framework. + // Search for or infer a module map for a framework. Here we use + // SearchName rather than ModuleName, to permit finding private modules + // named FooPrivate in buggy frameworks named Foo. SmallString<128> FrameworkDirName; FrameworkDirName += SearchDirs[Idx].getFrameworkDir()->getName(); - llvm::sys::path::append(FrameworkDirName, ModuleName + ".framework"); - if (const DirectoryEntry *FrameworkDir + llvm::sys::path::append(FrameworkDirName, SearchName + ".framework"); + if (const DirectoryEntry *FrameworkDir = FileMgr.getDirectory(FrameworkDirName)) { bool IsSystem = SearchDirs[Idx].getDirCharacteristic() != SrcMgr::C_User; @@ -240,7 +287,7 @@ Module *HeaderSearch::lookupModule(StringRef ModuleName, bool AllowSearch) { /// getName - Return the directory or filename corresponding to this lookup /// object. -const char *DirectoryLookup::getName() const { +StringRef DirectoryLookup::getName() const { if (isNormalDir()) return getDir()->getName(); if (isFramework()) @@ -396,6 +443,12 @@ getTopFrameworkDir(FileManager &FileMgr, StringRef DirName, return TopFrameworkDir; } +static bool needModuleLookup(Module *RequestingModule, + bool HasSuggestedModule) { + return HasSuggestedModule || + (RequestingModule && RequestingModule->NoUndeclaredIncludes); +} + /// DoFrameworkLookup - Do a lookup of the specified file in the current /// DirectoryLookup, which is a framework directory. const FileEntry *DirectoryLookup::DoFrameworkLookup( @@ -491,7 +544,7 @@ const FileEntry *DirectoryLookup::DoFrameworkLookup( } // If we found the header and are allowed to suggest a module, do so now. - if (FE && SuggestedModule) { + if (FE && needModuleLookup(RequestingModule, SuggestedModule)) { // Find the framework in which this header occurs. StringRef FrameworkPath = FE->getDir()->getName(); bool FoundFramework = false; @@ -830,17 +883,19 @@ LookupSubframeworkHeader(StringRef Filename, if (SlashPos == StringRef::npos) return nullptr; // Look up the base framework name of the ContextFileEnt. - const char *ContextName = ContextFileEnt->getName(); + StringRef ContextName = ContextFileEnt->getName(); // If the context info wasn't a framework, couldn't be a subframework. const unsigned DotFrameworkLen = 10; - const char *FrameworkPos = strstr(ContextName, ".framework"); - if (FrameworkPos == nullptr || - (FrameworkPos[DotFrameworkLen] != '/' && - FrameworkPos[DotFrameworkLen] != '\\')) + auto FrameworkPos = ContextName.find(".framework"); + if (FrameworkPos == StringRef::npos || + (ContextName[FrameworkPos + DotFrameworkLen] != '/' && + ContextName[FrameworkPos + DotFrameworkLen] != '\\')) return nullptr; - SmallString<1024> FrameworkName(ContextName, FrameworkPos+DotFrameworkLen+1); + SmallString<1024> FrameworkName(ContextName.data(), ContextName.data() + + FrameworkPos + + DotFrameworkLen + 1); // Append Frameworks/HIToolbox.framework/ FrameworkName += "Frameworks/"; @@ -1139,22 +1194,45 @@ bool HeaderSearch::hasModuleMap(StringRef FileName, } ModuleMap::KnownHeader -HeaderSearch::findModuleForHeader(const FileEntry *File) const { +HeaderSearch::findModuleForHeader(const FileEntry *File, + bool AllowTextual) 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)getExistingFileInfo(File); } - return ModMap.findModuleForHeader(File); + return ModMap.findModuleForHeader(File, AllowTextual); +} + +static bool suggestModule(HeaderSearch &HS, const FileEntry *File, + Module *RequestingModule, + ModuleMap::KnownHeader *SuggestedModule) { + ModuleMap::KnownHeader Module = + HS.findModuleForHeader(File, /*AllowTextual*/true); + if (SuggestedModule) + *SuggestedModule = (Module.getRole() & ModuleMap::TextualHeader) + ? ModuleMap::KnownHeader() + : Module; + + // If this module specifies [no_undeclared_includes], we cannot find any + // file that's in a non-dependency module. + if (RequestingModule && Module && RequestingModule->NoUndeclaredIncludes) { + HS.getModuleMap().resolveUses(RequestingModule, /*Complain*/false); + if (!RequestingModule->directlyUses(Module.getModule())) { + return false; + } + } + + return true; } bool HeaderSearch::findUsableModuleForHeader( const FileEntry *File, const DirectoryEntry *Root, Module *RequestingModule, ModuleMap::KnownHeader *SuggestedModule, bool IsSystemHeaderDir) { - if (File && SuggestedModule) { + if (File && needModuleLookup(RequestingModule, SuggestedModule)) { // If there is a module that corresponds to this header, suggest it. hasModuleMap(File->getName(), Root, IsSystemHeaderDir); - *SuggestedModule = findModuleForHeader(File); + return suggestModule(*this, File, RequestingModule, SuggestedModule); } return true; } @@ -1163,7 +1241,7 @@ 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) { + if (needModuleLookup(RequestingModule, SuggestedModule)) { // Find the top-level framework based on this framework. SmallVector<std::string, 4> SubmodulePath; const DirectoryEntry *TopFrameworkDir @@ -1180,7 +1258,7 @@ bool HeaderSearch::findUsableModuleForFrameworkHeader( // 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 suggestModule(*this, File, RequestingModule, SuggestedModule); } return true; } @@ -1432,7 +1510,7 @@ std::string HeaderSearch::suggestPathToFileForDiagnostics(const FileEntry *File, // FIXME: We assume that the path name currently cached in the FileEntry is // the most appropriate one for this analysis (and that it's spelled the same // way as the corresponding header search path). - const char *Name = File->getName(); + StringRef Name = File->getName(); unsigned BestPrefixLength = 0; unsigned BestSearchDir; @@ -1442,7 +1520,7 @@ std::string HeaderSearch::suggestPathToFileForDiagnostics(const FileEntry *File, if (!SearchDirs[I].isNormalDir()) continue; - const char *Dir = SearchDirs[I].getDir()->getName(); + StringRef Dir = SearchDirs[I].getDir()->getName(); for (auto NI = llvm::sys::path::begin(Name), NE = llvm::sys::path::end(Name), DI = llvm::sys::path::begin(Dir), @@ -1475,5 +1553,5 @@ std::string HeaderSearch::suggestPathToFileForDiagnostics(const FileEntry *File, if (IsSystem) *IsSystem = BestPrefixLength ? BestSearchDir >= SystemDirIdx : false; - return Name + BestPrefixLength; + return Name.drop_front(BestPrefixLength); } diff --git a/lib/Lex/Lexer.cpp b/lib/Lex/Lexer.cpp index 9c2a0163acead..6025a66751254 100644 --- a/lib/Lex/Lexer.cpp +++ b/lib/Lex/Lexer.cpp @@ -14,18 +14,27 @@ #include "clang/Lex/Lexer.h" #include "UnicodeCharSets.h" #include "clang/Basic/CharInfo.h" +#include "clang/Basic/IdentifierTable.h" #include "clang/Basic/SourceManager.h" -#include "clang/Lex/CodeCompletionHandler.h" #include "clang/Lex/LexDiagnostic.h" #include "clang/Lex/LiteralSupport.h" #include "clang/Lex/Preprocessor.h" -#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/ConvertUTF.h" +#include "llvm/Support/MathExtras.h" #include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/UnicodeCharRanges.h" +#include <algorithm> +#include <cassert> +#include <cstddef> +#include <cstdint> #include <cstring> +#include <string> +#include <tuple> +#include <utility> + using namespace clang; //===----------------------------------------------------------------------===// @@ -45,7 +54,6 @@ tok::ObjCKeywordKind Token::getObjCKeywordID() const { return specId ? specId->getObjCKeywordID() : tok::objc_not_keyword; } - //===----------------------------------------------------------------------===// // Lexer Class Implementation //===----------------------------------------------------------------------===// @@ -196,7 +204,6 @@ Lexer *Lexer::Create_PragmaLexer(SourceLocation SpellingLoc, return L; } - /// Stringify - Convert the specified string into a C string, with surrounding /// ""'s, and with escaped \ and " characters. std::string Lexer::Stringify(StringRef Str, bool Charify) { @@ -398,7 +405,6 @@ unsigned Lexer::getSpelling(const Token &Tok, const char *&Buffer, return getSpellingSlow(Tok, TokStart, LangOpts, const_cast<char*>(Buffer)); } - /// MeasureTokenLength - Relex the token at the specified location and return /// its length in bytes in the input file. If the token needs cleaning (e.g. /// includes a trigraph or an escaped newline) then this count includes bytes @@ -526,13 +532,15 @@ SourceLocation Lexer::GetBeginningOfToken(SourceLocation Loc, } namespace { + enum PreambleDirectiveKind { PDK_Skipped, PDK_StartIf, PDK_EndIf, PDK_Unknown }; -} + +} // end anonymous namespace std::pair<unsigned, bool> Lexer::ComputePreamble(StringRef Buffer, const LangOptions &LangOpts, @@ -694,7 +702,6 @@ std::pair<unsigned, bool> Lexer::ComputePreamble(StringRef Buffer, : TheTok.isAtStartOfLine()); } - /// AdvanceToTokenCharacter - Given a location that specifies the start of a /// token, return a new location that specifies a character within the token. SourceLocation Lexer::AdvanceToTokenCharacter(SourceLocation TokStart, @@ -961,7 +968,7 @@ StringRef Lexer::getImmediateMacroName(SourceLocation Loc, assert(Loc.isMacroID() && "Only reasonble to call this on macros"); // Find the location of the immediate macro expansion. - while (1) { + while (true) { FileID FID = SM.getFileID(Loc); const SrcMgr::SLocEntry *E = &SM.getSLocEntry(FID); const SrcMgr::ExpansionInfo &Expansion = E->getExpansion(); @@ -1031,7 +1038,6 @@ bool Lexer::isIdentifierBodyChar(char c, const LangOptions &LangOpts) { return isIdentifierBody(c, LangOpts.DollarIdents); } - //===----------------------------------------------------------------------===// // Diagnostics forwarding code. //===----------------------------------------------------------------------===// @@ -1157,7 +1163,7 @@ unsigned Lexer::getEscapedNewLineSize(const char *Ptr) { /// them), skip over them and return the first non-escaped-newline found, /// otherwise return P. const char *Lexer::SkipEscapedNewLines(const char *P) { - while (1) { + while (true) { const char *AfterEscape; if (*P == '\\') { AfterEscape = P+1; @@ -1310,7 +1316,6 @@ Slash: return *Ptr; } - /// getCharAndSizeSlowNoWarn - Handle the slow/uncommon case of the /// getCharAndSizeNoWarn method. Here we know that we can accumulate into Size, /// and that we have already incremented Ptr by Size bytes. @@ -1480,13 +1485,13 @@ bool Lexer::tryConsumeIdentifierUCN(const char *&CurPtr, unsigned Size, bool Lexer::tryConsumeIdentifierUTF8Char(const char *&CurPtr) { const char *UnicodePtr = CurPtr; - UTF32 CodePoint; - ConversionResult Result = - llvm::convertUTF8Sequence((const UTF8 **)&UnicodePtr, - (const UTF8 *)BufferEnd, + llvm::UTF32 CodePoint; + llvm::ConversionResult Result = + llvm::convertUTF8Sequence((const llvm::UTF8 **)&UnicodePtr, + (const llvm::UTF8 *)BufferEnd, &CodePoint, - strictConversion); - if (Result != conversionOK || + llvm::strictConversion); + if (Result != llvm::conversionOK || !isAllowedIDChar(static_cast<uint32_t>(CodePoint), LangOpts)) return false; @@ -1533,14 +1538,22 @@ FinishIdentifier: // preprocessor, which may macro expand it or something. if (II->isHandleIdentifierCase()) return PP->HandleIdentifier(Result); - + + if (II->getTokenID() == tok::identifier && isCodeCompletionPoint(CurPtr) + && II->getPPKeywordID() == tok::pp_not_keyword + && II->getObjCKeywordID() == tok::objc_not_keyword) { + // Return the code-completion token. + Result.setKind(tok::code_completion); + cutOffLexing(); + return true; + } return true; } // Otherwise, $,\,? in identifier found. Enter slower path. C = getCharAndSize(CurPtr, Size); - while (1) { + while (true) { if (C == '$') { // If we hit a $ and they are not supported in identifiers, we are done. if (!LangOpts.DollarIdents) goto FinishIdentifier; @@ -1700,9 +1713,9 @@ const char *Lexer::LexUDSuffix(Token &Result, const char *CurPtr, getLangOpts()); if (!isIdentifierBody(Next)) { // End of suffix. Check whether this is on the whitelist. - IsUDSuffix = (Chars == 1 && Buffer[0] == 's') || - NumericLiteralParser::isValidUDSuffix( - getLangOpts(), StringRef(Buffer, Chars)); + const StringRef CompleteSuffix(Buffer, Chars); + IsUDSuffix = StringLiteralParser::isValidUDSuffix(getLangOpts(), + CompleteSuffix); break; } @@ -1829,7 +1842,7 @@ bool Lexer::LexRawStringLiteral(Token &Result, const char *CurPtr, // Search for the next '"' in hopes of salvaging the lexer. Unfortunately, // it's possible the '"' was intended to be part of the raw string, but // there's not much we can do about that. - while (1) { + while (true) { char C = *CurPtr++; if (C == '"') @@ -1848,7 +1861,7 @@ bool Lexer::LexRawStringLiteral(Token &Result, const char *CurPtr, const char *Prefix = CurPtr; CurPtr += PrefixLen + 1; // skip over prefix and '(' - while (1) { + while (true) { char C = *CurPtr++; if (C == ')') { @@ -1913,7 +1926,6 @@ bool Lexer::LexAngledStringLiteral(Token &Result, const char *CurPtr) { return true; } - /// LexCharConstant - Lex the remainder of a character constant, after having /// lexed either ' or L' or u8' or u' or U'. bool Lexer::LexCharConstant(Token &Result, const char *CurPtr, @@ -1992,7 +2004,7 @@ bool Lexer::SkipWhitespace(Token &Result, const char *CurPtr, unsigned char Char = *CurPtr; // Skip consecutive spaces efficiently. - while (1) { + while (true) { // Skip horizontal whitespace very aggressively. while (isHorizontalWhitespace(Char)) Char = *++CurPtr; @@ -2315,7 +2327,7 @@ bool Lexer::SkipBlockComment(Token &Result, const char *CurPtr, if (C == '/') C = *CurPtr++; - while (1) { + while (true) { // Skip over all non-interesting characters until we find end of buffer or a // (probably ending) '/' character. if (CurPtr + 24 < BufferEnd && @@ -2456,7 +2468,7 @@ void Lexer::ReadToEndOfLine(SmallVectorImpl<char> *Result) { // CurPtr - Cache BufferPtr in an automatic variable. const char *CurPtr = BufferPtr; - while (1) { + while (true) { char Char = getAndAdvanceChar(CurPtr, Tmp); switch (Char) { default: @@ -2669,7 +2681,6 @@ bool Lexer::IsStartOfConflictMarker(const char *CurPtr) { return false; } - /// HandleEndOfConflictMarker - If this is a '====' or '||||' or '>>>>', or if /// it is '<<<<' and the conflict marker started with a '>>>>' marker, then it /// is the end of a conflict marker. Handle it by ignoring up until the end of @@ -3498,7 +3509,6 @@ LexNextToken: CurPtr = ConsumeChar(CurPtr, SizeTmp, Result); Kind = tok::greatergreater; } - } else { Kind = tok::greater; } @@ -3615,17 +3625,17 @@ LexNextToken: break; } - UTF32 CodePoint; + llvm::UTF32 CodePoint; // We can't just reset CurPtr to BufferPtr because BufferPtr may point to // an escaped newline. --CurPtr; - ConversionResult Status = - llvm::convertUTF8Sequence((const UTF8 **)&CurPtr, - (const UTF8 *)BufferEnd, + llvm::ConversionResult Status = + llvm::convertUTF8Sequence((const llvm::UTF8 **)&CurPtr, + (const llvm::UTF8 *)BufferEnd, &CodePoint, - strictConversion); - if (Status == conversionOK) { + llvm::strictConversion); + if (Status == llvm::conversionOK) { if (CheckUnicodeWhitespace(Result, CodePoint, CurPtr)) { if (SkipWhitespace(Result, CurPtr, TokAtPhysicalStartOfLine)) return true; // KeepWhitespaceMode diff --git a/lib/Lex/LiteralSupport.cpp b/lib/Lex/LiteralSupport.cpp index e68b82fb499af..fbfd3fe5cce0f 100644 --- a/lib/Lex/LiteralSupport.cpp +++ b/lib/Lex/LiteralSupport.cpp @@ -14,12 +14,25 @@ #include "clang/Lex/LiteralSupport.h" #include "clang/Basic/CharInfo.h" +#include "clang/Basic/LangOptions.h" +#include "clang/Basic/SourceLocation.h" #include "clang/Basic/TargetInfo.h" #include "clang/Lex/LexDiagnostic.h" +#include "clang/Lex/Lexer.h" #include "clang/Lex/Preprocessor.h" +#include "clang/Lex/Token.h" +#include "llvm/ADT/APInt.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/StringSwitch.h" #include "llvm/Support/ConvertUTF.h" #include "llvm/Support/ErrorHandling.h" +#include <algorithm> +#include <cassert> +#include <cstddef> +#include <cstdint> +#include <cstring> +#include <string> using namespace clang; @@ -134,7 +147,7 @@ static unsigned ProcessCharEscape(const char *ThisTokBegin, if (Diags) Diag(Diags, Features, Loc, ThisTokBegin, EscapeBegin, ThisTokBuf, diag::err_hex_escape_no_digits) << "x"; - HadError = 1; + HadError = true; break; } @@ -389,7 +402,7 @@ static void EncodeUCNEscape(const char *ThisTokBegin, const char *&ThisTokBuf, if (CharByteWidth == 4) { // FIXME: Make the type of the result buffer correct instead of // using reinterpret_cast. - UTF32 *ResultPtr = reinterpret_cast<UTF32*>(ResultBuf); + llvm::UTF32 *ResultPtr = reinterpret_cast<llvm::UTF32*>(ResultBuf); *ResultPtr = UcnVal; ResultBuf += 4; return; @@ -398,7 +411,7 @@ static void EncodeUCNEscape(const char *ThisTokBegin, const char *&ThisTokBuf, if (CharByteWidth == 2) { // FIXME: Make the type of the result buffer correct instead of // using reinterpret_cast. - UTF16 *ResultPtr = reinterpret_cast<UTF16*>(ResultBuf); + llvm::UTF16 *ResultPtr = reinterpret_cast<llvm::UTF16*>(ResultBuf); if (UcnVal <= (UTF32)0xFFFF) { *ResultPtr = UcnVal; @@ -452,7 +465,6 @@ static void EncodeUCNEscape(const char *ThisTokBegin, const char *&ThisTokBuf, ResultBuf += bytesToWrite; } - /// integer-constant: [C99 6.4.4.1] /// decimal-constant integer-suffix /// octal-constant integer-suffix @@ -985,7 +997,6 @@ NumericLiteralParser::GetFloatValue(llvm::APFloat &Result) { return Result.convertFromString(Str, APFloat::rmNearestTiesToEven); } - /// \verbatim /// user-defined-character-literal: [C++11 lex.ext] /// character-literal ud-suffix @@ -1103,11 +1114,11 @@ CharLiteralParser::CharLiteralParser(const char *begin, const char *end, char const *tmp_in_start = start; uint32_t *tmp_out_start = buffer_begin; - ConversionResult res = - ConvertUTF8toUTF32(reinterpret_cast<UTF8 const **>(&start), - reinterpret_cast<UTF8 const *>(begin), - &buffer_begin, buffer_end, strictConversion); - if (res != conversionOK) { + llvm::ConversionResult res = + llvm::ConvertUTF8toUTF32(reinterpret_cast<llvm::UTF8 const **>(&start), + reinterpret_cast<llvm::UTF8 const *>(begin), + &buffer_begin, buffer_end, llvm::strictConversion); + if (res != llvm::conversionOK) { // If we see bad encoding for unprefixed character literals, warn and // simply copy the byte values, for compatibility with gcc and // older versions of clang. @@ -1499,13 +1510,13 @@ void StringLiteralParser::init(ArrayRef<Token> StringToks){ if (CharByteWidth == 4) { // FIXME: Make the type of the result buffer correct instead of // using reinterpret_cast. - UTF32 *ResultWidePtr = reinterpret_cast<UTF32*>(ResultPtr); + llvm::UTF32 *ResultWidePtr = reinterpret_cast<llvm::UTF32*>(ResultPtr); *ResultWidePtr = ResultChar; ResultPtr += 4; } else if (CharByteWidth == 2) { // FIXME: Make the type of the result buffer correct instead of // using reinterpret_cast. - UTF16 *ResultWidePtr = reinterpret_cast<UTF16*>(ResultPtr); + llvm::UTF16 *ResultWidePtr = reinterpret_cast<llvm::UTF16*>(ResultPtr); *ResultWidePtr = ResultChar & 0xFFFF; ResultPtr += 2; } else { @@ -1520,12 +1531,12 @@ void StringLiteralParser::init(ArrayRef<Token> StringToks){ if (CharByteWidth == 4) { // FIXME: Make the type of the result buffer correct instead of // using reinterpret_cast. - UTF32 *ResultWidePtr = reinterpret_cast<UTF32*>(ResultBuf.data()); + llvm::UTF32 *ResultWidePtr = reinterpret_cast<llvm::UTF32*>(ResultBuf.data()); ResultWidePtr[0] = GetNumStringChars() - 1; } else if (CharByteWidth == 2) { // FIXME: Make the type of the result buffer correct instead of // using reinterpret_cast. - UTF16 *ResultWidePtr = reinterpret_cast<UTF16*>(ResultBuf.data()); + llvm::UTF16 *ResultWidePtr = reinterpret_cast<llvm::UTF16*>(ResultBuf.data()); ResultWidePtr[0] = GetNumStringChars() - 1; } else { assert(CharByteWidth == 1 && "Unexpected char width"); @@ -1559,7 +1570,7 @@ void StringLiteralParser::init(ArrayRef<Token> StringToks){ static const char *resyncUTF8(const char *Err, const char *End) { if (Err == End) return End; - End = Err + std::min<unsigned>(getNumBytesForUTF8(*Err), End-Err); + End = Err + std::min<unsigned>(llvm::getNumBytesForUTF8(*Err), End-Err); while (++Err != End && (*Err & 0xC0) == 0x80) ; return Err; @@ -1571,7 +1582,7 @@ static const char *resyncUTF8(const char *Err, const char *End) { bool StringLiteralParser::CopyStringFragment(const Token &Tok, const char *TokBegin, StringRef Fragment) { - const UTF8 *ErrorPtrTmp; + const llvm::UTF8 *ErrorPtrTmp; if (ConvertUTF8toWide(CharByteWidth, Fragment, ResultPtr, ErrorPtrTmp)) return false; @@ -1697,3 +1708,12 @@ unsigned StringLiteralParser::getOffsetOfStringByte(const Token &Tok, return SpellingPtr-SpellingStart; } + +/// Determine whether a suffix is a valid ud-suffix. We avoid treating reserved +/// suffixes as ud-suffixes, because the diagnostic experience is better if we +/// treat it as an invalid suffix. +bool StringLiteralParser::isValidUDSuffix(const LangOptions &LangOpts, + StringRef Suffix) { + return NumericLiteralParser::isValidUDSuffix(LangOpts, Suffix) || + Suffix == "sv"; +} diff --git a/lib/Lex/MacroInfo.cpp b/lib/Lex/MacroInfo.cpp index 2ef4387b99ba0..924613dcb8405 100644 --- a/lib/Lex/MacroInfo.cpp +++ b/lib/Lex/MacroInfo.cpp @@ -240,6 +240,6 @@ ModuleMacro *ModuleMacro::create(Preprocessor &PP, Module *OwningModule, ArrayRef<ModuleMacro *> Overrides) { void *Mem = PP.getPreprocessorAllocator().Allocate( sizeof(ModuleMacro) + sizeof(ModuleMacro *) * Overrides.size(), - llvm::alignOf<ModuleMacro>()); + alignof(ModuleMacro)); return new (Mem) ModuleMacro(OwningModule, II, Macro, Overrides); } diff --git a/lib/Lex/ModuleMap.cpp b/lib/Lex/ModuleMap.cpp index 3e3215dee82a8..9d0f2eb2fa79f 100644 --- a/lib/Lex/ModuleMap.cpp +++ b/lib/Lex/ModuleMap.cpp @@ -297,11 +297,14 @@ void ModuleMap::diagnoseHeaderInclusion(Module *RequestingModule, if (LangOpts.ModulesStrictDeclUse) { Diags.Report(FilenameLoc, diag::err_undeclared_use_of_module) << RequestingModule->getFullModuleName() << Filename; - } else if (RequestingModule && RequestingModuleIsModuleInterface) { + } else if (RequestingModule && RequestingModuleIsModuleInterface && + LangOpts.isCompilingModule()) { + // Do not diagnose when we are not compiling a module. diag::kind DiagID = RequestingModule->getTopLevelModule()->IsFramework ? diag::warn_non_modular_include_in_framework_module : diag::warn_non_modular_include_in_module; - Diags.Report(FilenameLoc, DiagID) << RequestingModule->getFullModuleName(); + Diags.Report(FilenameLoc, DiagID) << RequestingModule->getFullModuleName() + << File->getName(); } } @@ -325,9 +328,10 @@ static bool isBetterKnownHeader(const ModuleMap::KnownHeader &New, return false; } -ModuleMap::KnownHeader ModuleMap::findModuleForHeader(const FileEntry *File) { +ModuleMap::KnownHeader ModuleMap::findModuleForHeader(const FileEntry *File, + bool AllowTextual) { auto MakeResult = [&](ModuleMap::KnownHeader R) -> ModuleMap::KnownHeader { - if (R.getRole() & ModuleMap::TextualHeader) + if (!AllowTextual && R.getRole() & ModuleMap::TextualHeader) return ModuleMap::KnownHeader(); return R; }; @@ -558,6 +562,25 @@ ModuleMap::findOrCreateModule(StringRef Name, Module *Parent, bool IsFramework, return std::make_pair(Result, true); } +Module *ModuleMap::createModuleForInterfaceUnit(SourceLocation Loc, + StringRef Name) { + assert(LangOpts.CurrentModule == Name && "module name mismatch"); + assert(!Modules[Name] && "redefining existing module"); + + auto *Result = + new Module(Name, Loc, nullptr, /*IsFramework*/ false, + /*IsExplicit*/ false, NumCreatedModules++); + Modules[Name] = SourceModule = Result; + + // Mark the main source file as being within the newly-created module so that + // declarations and macros are properly visibility-restricted to it. + auto *MainFile = SourceMgr.getFileEntryForID(SourceMgr.getMainFileID()); + assert(MainFile && "no input file for module interface"); + Headers[MainFile].push_back(KnownHeader(Result, PrivateHeader)); + + return Result; +} + /// \brief For a framework module, infer the framework against which we /// should link. static void inferFrameworkLink(Module *Mod, const DirectoryEntry *FrameworkDir, @@ -573,8 +596,7 @@ static void inferFrameworkLink(Module *Mod, const DirectoryEntry *FrameworkDir, // 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) { + for (const char *extension : {"", ".tbd"}) { llvm::sys::path::replace_extension(LibName, extension); if (FileMgr.getFile(LibName)) { Mod->LinkLibraries.push_back(Module::LinkLibrary(Mod->Name, @@ -653,6 +675,8 @@ Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir, Attrs.IsSystem |= inferred->second.Attrs.IsSystem; Attrs.IsExternC |= inferred->second.Attrs.IsExternC; Attrs.IsExhaustive |= inferred->second.Attrs.IsExhaustive; + Attrs.NoUndeclaredIncludes |= + inferred->second.Attrs.NoUndeclaredIncludes; ModuleMapFile = inferred->second.ModuleMapFile; } } @@ -690,6 +714,7 @@ Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir, Result->IsSystem |= Attrs.IsSystem; Result->IsExternC |= Attrs.IsExternC; Result->ConfigMacrosExhaustive |= Attrs.IsExhaustive; + Result->NoUndeclaredIncludes |= Attrs.NoUndeclaredIncludes; Result->Directory = FrameworkDir; // umbrella header "umbrella-header-name" @@ -802,10 +827,10 @@ void ModuleMap::addHeader(Module *Mod, Module::Header Header, return; HeaderList.push_back(KH); - Mod->Headers[headerRoleToKind(Role)].push_back(std::move(Header)); + Mod->Headers[headerRoleToKind(Role)].push_back(Header); bool isCompilingModuleHeader = - LangOpts.CompilingModule && Mod->getTopLevelModule() == SourceModule; + LangOpts.isCompilingModule() && Mod->getTopLevelModule() == SourceModule; if (!Imported || isCompilingModuleHeader) { // When we import HeaderFileInfo, the external source is expected to // set the isModuleHeader flag itself. @@ -1288,7 +1313,9 @@ namespace { /// \brief The 'extern_c' attribute. AT_extern_c, /// \brief The 'exhaustive' attribute. - AT_exhaustive + AT_exhaustive, + /// \brief The 'no_undeclared_includes' attribute. + AT_no_undeclared_includes }; } @@ -1458,8 +1485,47 @@ void ModuleMapParser::parseModuleDecl() { ActiveModule->IsSystem = true; if (Attrs.IsExternC) ActiveModule->IsExternC = true; + if (Attrs.NoUndeclaredIncludes || + (!ActiveModule->Parent && ModuleName == "Darwin")) + ActiveModule->NoUndeclaredIncludes = true; ActiveModule->Directory = Directory; + if (!ActiveModule->Parent) { + StringRef MapFileName(ModuleMapFile->getName()); + if (MapFileName.endswith("module.private.modulemap") || + MapFileName.endswith("module_private.map")) { + // Adding a top-level module from a private modulemap is likely a + // user error; we check to see if there's another top-level module + // defined in the non-private map in the same dir, and if so emit a + // warning. + for (auto E = Map.module_begin(); E != Map.module_end(); ++E) { + auto const *M = E->getValue(); + if (!M->Parent && + M->Directory == ActiveModule->Directory && + M->Name != ActiveModule->Name) { + Diags.Report(ActiveModule->DefinitionLoc, + diag::warn_mmap_mismatched_top_level_private) + << ActiveModule->Name << M->Name; + // The pattern we're defending against here is typically due to + // a module named FooPrivate which is supposed to be a submodule + // called Foo.Private. Emit a fixit in that case. + auto D = + Diags.Report(ActiveModule->DefinitionLoc, + diag::note_mmap_rename_top_level_private_as_submodule); + D << ActiveModule->Name << M->Name; + StringRef Bad(ActiveModule->Name); + if (Bad.consume_back("Private")) { + SmallString<128> Fixed = Bad; + Fixed.append(".Private"); + D << FixItHint::CreateReplacement(ActiveModule->DefinitionLoc, + Fixed); + } + break; + } + } + } + } + bool Done = false; do { switch (Tok.Kind) { @@ -1624,15 +1690,12 @@ void ModuleMapParser::parseExternModuleDecl() { /// 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))) { + if (Feature == "excluded" && + (M->fullModuleNameIs({"Darwin", "C", "excluded"}) || + M->fullModuleNameIs({"Tcl", "Private"}))) { IsRequiresExcludedHack = true; return false; - } else if (Feature == "cplusplus" && M->fullModuleNameIs(IOKitAVC)) { + } else if (Feature == "cplusplus" && M->fullModuleNameIs({"IOKit", "avc"})) { return false; } @@ -1824,13 +1887,7 @@ void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken, // 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). - // - // For local visibility, entirely replace the system file with our - // one and textually include the system one. We need to pass macros - // from our header to the system one if we #include_next it. - // - // FIXME: Can we do this in all cases? - if (BuiltinFile && (!File || Map.LangOpts.ModulesLocalVisibility)) { + if (BuiltinFile && !File) { File = BuiltinFile; RelativePathName = BuiltinPathName; BuiltinFile = nullptr; @@ -1856,15 +1913,20 @@ void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken, Module::Header H = {RelativePathName.str(), File}; Map.excludeHeader(ActiveModule, H); } else { - // If there is a builtin counterpart to this file, add it now, before - // the "real" header, so we build the built-in one first when building - // the module. + // 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); } // Record this header. @@ -2354,6 +2416,7 @@ bool ModuleMapParser::parseOptionalAttributes(Attributes &Attrs) { = llvm::StringSwitch<AttributeKind>(Tok.getString()) .Case("exhaustive", AT_exhaustive) .Case("extern_c", AT_extern_c) + .Case("no_undeclared_includes", AT_no_undeclared_includes) .Case("system", AT_system) .Default(AT_unknown); switch (Attribute) { @@ -2373,6 +2436,10 @@ bool ModuleMapParser::parseOptionalAttributes(Attributes &Attrs) { case AT_exhaustive: Attrs.IsExhaustive = true; break; + + case AT_no_undeclared_includes: + Attrs.NoUndeclaredIncludes = true; + break; } consumeToken(); diff --git a/lib/Lex/PPCaching.cpp b/lib/Lex/PPCaching.cpp index 4742aae5c1230..45bdce32062ab 100644 --- a/lib/Lex/PPCaching.cpp +++ b/lib/Lex/PPCaching.cpp @@ -86,7 +86,7 @@ void Preprocessor::EnterCachingLexMode() { const Token &Preprocessor::PeekAhead(unsigned N) { assert(CachedLexPos + N > CachedTokens.size() && "Confused caching."); ExitCachingLexMode(); - for (unsigned C = CachedLexPos + N - CachedTokens.size(); C > 0; --C) { + for (size_t C = CachedLexPos + N - CachedTokens.size(); C > 0; --C) { CachedTokens.push_back(Token()); Lex(CachedTokens.back()); } @@ -105,7 +105,7 @@ void Preprocessor::AnnotatePreviousCachedTokens(const Token &Tok) { for (CachedTokensTy::size_type i = CachedLexPos; i != 0; --i) { CachedTokensTy::iterator AnnotBegin = CachedTokens.begin() + i-1; if (AnnotBegin->getLocation() == Tok.getLocation()) { - assert((BacktrackPositions.empty() || BacktrackPositions.back() < i) && + assert((BacktrackPositions.empty() || BacktrackPositions.back() <= i) && "The backtrack pos points inside the annotated tokens!"); // Replace the cached tokens with the single annotation token. if (i < CachedLexPos) diff --git a/lib/Lex/PPDirectives.cpp b/lib/Lex/PPDirectives.cpp index 77f118fd3ccb7..85504de3d15d8 100644 --- a/lib/Lex/PPDirectives.cpp +++ b/lib/Lex/PPDirectives.cpp @@ -12,25 +12,41 @@ /// //===----------------------------------------------------------------------===// -#include "clang/Lex/Preprocessor.h" +#include "clang/Basic/CharInfo.h" #include "clang/Basic/FileManager.h" +#include "clang/Basic/IdentifierTable.h" +#include "clang/Basic/LangOptions.h" +#include "clang/Basic/Module.h" +#include "clang/Basic/SourceLocation.h" #include "clang/Basic/SourceManager.h" +#include "clang/Basic/TokenKinds.h" #include "clang/Lex/CodeCompletionHandler.h" #include "clang/Lex/HeaderSearch.h" -#include "clang/Lex/HeaderSearchOptions.h" #include "clang/Lex/LexDiagnostic.h" #include "clang/Lex/LiteralSupport.h" #include "clang/Lex/MacroInfo.h" #include "clang/Lex/ModuleLoader.h" +#include "clang/Lex/ModuleMap.h" +#include "clang/Lex/PPCallbacks.h" #include "clang/Lex/Pragma.h" -#include "llvm/ADT/APInt.h" +#include "clang/Lex/Preprocessor.h" +#include "clang/Lex/PTHLexer.h" +#include "clang/Lex/Token.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringSwitch.h" -#include "llvm/ADT/iterator_range.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/AlignOf.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Path.h" -#include "llvm/Support/SaveAndRestore.h" +#include <algorithm> +#include <cassert> +#include <cstring> +#include <new> +#include <string> +#include <utility> using namespace clang; @@ -53,7 +69,7 @@ MacroInfo *Preprocessor::AllocateMacroInfo(SourceLocation L) { MacroInfo *Preprocessor::AllocateDeserializedMacroInfo(SourceLocation L, unsigned SubModuleID) { - static_assert(llvm::AlignOf<MacroInfo>::Alignment >= sizeof(SubModuleID), + static_assert(alignof(MacroInfo) >= sizeof(SubModuleID), "alignment for MacroInfo is less than the ID"); DeserializedMacroInfoChain *MIChain = BP.Allocate<DeserializedMacroInfoChain>(); @@ -268,7 +284,7 @@ bool Preprocessor::CheckMacroName(Token &MacroNameTok, MacroUse isDefineUndef, if (ShadowFlag) *ShadowFlag = false; if (!SourceMgr.isInSystemHeader(MacroNameLoc) && - (strcmp(SourceMgr.getBufferName(MacroNameLoc), "<built-in>") != 0)) { + (SourceMgr.getBufferName(MacroNameLoc) != "<built-in>")) { MacroDiag D = MD_NoWarn; if (isDefineUndef == MU_Define) { D = shouldWarnOnMacroDef(*this, II); @@ -382,7 +398,7 @@ void Preprocessor::SkipExcludedConditionalBlock(SourceLocation IfTokenLoc, // disabling warnings, etc. CurPPLexer->LexingRawMode = true; Token Tok; - while (1) { + while (true) { CurLexer->Lex(Tok); if (Tok.is(tok::code_completion)) { @@ -455,7 +471,7 @@ void Preprocessor::SkipExcludedConditionalBlock(SourceLocation IfTokenLoc, Directive = RI; } else { std::string DirectiveStr = getSpelling(Tok); - unsigned IdLen = DirectiveStr.size(); + size_t IdLen = DirectiveStr.size(); if (IdLen >= 20) { CurPPLexer->ParsingPreprocessorDirective = false; // Restore comment saving mode. @@ -578,7 +594,7 @@ void Preprocessor::SkipExcludedConditionalBlock(SourceLocation IfTokenLoc, } void Preprocessor::PTHSkipExcludedConditionalBlock() { - while (1) { + while (true) { assert(CurPTHLexer); assert(CurPTHLexer->LexingRawMode == false); @@ -785,8 +801,7 @@ const FileEntry *Preprocessor::LookupFile( // headers included by quoted include directives. // See: http://msdn.microsoft.com/en-us/library/36k2cdd4.aspx if (LangOpts.MSVCCompat && !isAngled) { - for (unsigned i = 0, e = IncludeMacroStack.size(); i != e; ++i) { - IncludeStackInfo &ISEntry = IncludeMacroStack[e - i - 1]; + for (IncludeStackInfo &ISEntry : llvm::reverse(IncludeMacroStack)) { if (IsFileLexer(ISEntry)) if ((FileEnt = ISEntry.ThePPLexer->getFileEntry())) Includers.push_back(std::make_pair(FileEnt, FileEnt->getDir())); @@ -849,8 +864,7 @@ const FileEntry *Preprocessor::LookupFile( } } - for (unsigned i = 0, e = IncludeMacroStack.size(); i != e; ++i) { - IncludeStackInfo &ISEntry = IncludeMacroStack[e-i-1]; + for (IncludeStackInfo &ISEntry : llvm::reverse(IncludeMacroStack)) { if (IsFileLexer(ISEntry)) { if ((CurFileEnt = ISEntry.ThePPLexer->getFileEntry())) { if ((FE = HeaderInfo.LookupSubframeworkHeader( @@ -998,11 +1012,11 @@ void Preprocessor::HandleDirective(Token &Result) { case tok::pp_define: return HandleDefineDirective(Result, ImmediatelyAfterTopLevelIfndef); case tok::pp_undef: - return HandleUndefDirective(Result); + return HandleUndefDirective(); // C99 6.10.4 - Line Control. case tok::pp_line: - return HandleLineDirective(Result); + return HandleLineDirective(); // C99 6.10.5 - Error Directive. case tok::pp_error: @@ -1039,7 +1053,7 @@ void Preprocessor::HandleDirective(Token &Result) { case tok::pp___private_macro: if (getLangOpts().Modules) - return HandleMacroPrivateDirective(Result); + return HandleMacroPrivateDirective(); break; } break; @@ -1137,7 +1151,7 @@ static bool GetLineValue(Token &DigitTok, unsigned &Val, /// # line digit-sequence /// # line digit-sequence "s-char-sequence" /// \endverbatim -void Preprocessor::HandleLineDirective(Token &Tok) { +void Preprocessor::HandleLineDirective() { // Read the line # and string argument. Per C99 6.10.4p5, these tokens are // expanded. Token DigitTok; @@ -1442,7 +1456,7 @@ void Preprocessor::HandleMacroPublicDirective(Token &Tok) { } /// \brief Handle a #private directive. -void Preprocessor::HandleMacroPrivateDirective(Token &Tok) { +void Preprocessor::HandleMacroPrivateDirective() { Token MacroNameTok; ReadMacroName(MacroNameTok, MU_Undef); @@ -1551,7 +1565,7 @@ bool Preprocessor::ConcatenateIncludeName(SmallString<128> &FilenameBuffer, FilenameBuffer.push_back(' '); // Get the spelling of the token, directly into FilenameBuffer if possible. - unsigned PreAppendSize = FilenameBuffer.size(); + size_t PreAppendSize = FilenameBuffer.size(); FilenameBuffer.resize(PreAppendSize+CurTok.getLength()); const char *BufPtr = &FilenameBuffer[PreAppendSize]; @@ -1602,7 +1616,7 @@ static void diagnoseAutoModuleImport( assert(PP.getLangOpts().ObjC2 && "no import syntax available"); SmallString<128> PathString; - for (unsigned I = 0, N = Path.size(); I != N; ++I) { + for (size_t I = 0, N = Path.size(); I != N; ++I) { if (I) PathString += '.'; PathString += Path[I].first->getName(); @@ -1831,7 +1845,8 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc, // If the file is still not found, just go with the vanilla diagnostic if (!File) - Diag(FilenameTok, diag::err_pp_file_not_found) << Filename; + Diag(FilenameTok, diag::err_pp_file_not_found) << Filename + << FilenameRange; } } @@ -1851,12 +1866,9 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc, // unavailable, diagnose the situation and bail out. // FIXME: Remove this; loadModule does the same check (but produces // slightly worse diagnostics). - if (!SuggestedModule.getModule()->isAvailable() && - !SuggestedModule.getModule() - ->getTopLevelModule() - ->HasIncompatibleModuleFile) { - clang::Module::Requirement Requirement; - clang::Module::UnresolvedHeaderDirective MissingHeader; + if (!SuggestedModule.getModule()->isAvailable()) { + Module::Requirement Requirement; + Module::UnresolvedHeaderDirective MissingHeader; Module *M = SuggestedModule.getModule(); // Identify the cause. (void)M->isAvailable(getLangOpts(), getTargetInfo(), Requirement, @@ -1903,9 +1915,12 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc, else if (Imported.isMissingExpected()) { // We failed to find a submodule that we assumed would exist (because it // was in the directory of an umbrella header, for instance), but no - // actual module exists for it (because the umbrella header is + // actual module containing it exists (because the umbrella header is // incomplete). Treat this as a textual inclusion. SuggestedModule = ModuleMap::KnownHeader(); + } else if (Imported.isConfigMismatch()) { + // On a configuration mismatch, enter the header textually. We still know + // that it's part of the corresponding module. } else { // We hit an error processing the import. Bail out. if (hadModuleLoaderFatalFailure()) { @@ -2043,7 +2058,11 @@ void Preprocessor::HandleIncludeNextDirective(SourceLocation HashLoc, // diagnostic. const DirectoryLookup *Lookup = CurDirLookup; const FileEntry *LookupFromFile = nullptr; - if (isInPrimaryFile()) { + if (isInPrimaryFile() && LangOpts.IsHeaderFile) { + // If the main file is a header, then it's either for PCH/AST generation, + // or libclang opened it. Either way, handle it as a normal include below + // and do not complain about include_next. + } else if (isInPrimaryFile()) { Lookup = nullptr; Diag(IncludeNextTok, diag::pp_include_next_in_primary); } else if (CurSubmodule) { @@ -2098,7 +2117,7 @@ void Preprocessor::HandleIncludeMacrosDirective(SourceLocation HashLoc, // This directive should only occur in the predefines buffer. If not, emit an // error and reject it. SourceLocation Loc = IncludeMacrosTok.getLocation(); - if (strcmp(SourceMgr.getBufferName(Loc), "<built-in>") != 0) { + if (SourceMgr.getBufferName(Loc) != "<built-in>") { Diag(IncludeMacrosTok.getLocation(), diag::pp_include_macros_out_of_predefines); DiscardUntilEndOfDirective(); @@ -2127,7 +2146,7 @@ void Preprocessor::HandleIncludeMacrosDirective(SourceLocation HashLoc, bool Preprocessor::ReadMacroDefinitionArgList(MacroInfo *MI, Token &Tok) { SmallVector<IdentifierInfo*, 32> Arguments; - while (1) { + while (true) { LexUnexpandedToken(Tok); switch (Tok.getKind()) { case tok::r_paren: @@ -2536,7 +2555,7 @@ void Preprocessor::HandleDefineDirective(Token &DefineTok, /// HandleUndefDirective - Implements \#undef. /// -void Preprocessor::HandleUndefDirective(Token &UndefTok) { +void Preprocessor::HandleUndefDirective() { ++NumUndefined; Token MacroNameTok; diff --git a/lib/Lex/PPExpressions.cpp b/lib/Lex/PPExpressions.cpp index 94075ece35cac..862a4713e4bca 100644 --- a/lib/Lex/PPExpressions.cpp +++ b/lib/Lex/PPExpressions.cpp @@ -17,14 +17,24 @@ //===----------------------------------------------------------------------===// #include "clang/Lex/Preprocessor.h" +#include "clang/Basic/IdentifierTable.h" +#include "clang/Basic/SourceLocation.h" +#include "clang/Basic/SourceManager.h" #include "clang/Basic/TargetInfo.h" +#include "clang/Basic/TokenKinds.h" #include "clang/Lex/CodeCompletionHandler.h" #include "clang/Lex/LexDiagnostic.h" #include "clang/Lex/LiteralSupport.h" #include "clang/Lex/MacroInfo.h" +#include "clang/Lex/PPCallbacks.h" +#include "clang/Lex/Token.h" #include "llvm/ADT/APSInt.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringRef.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/SaveAndRestore.h" +#include <cassert> + using namespace clang; namespace { @@ -34,6 +44,7 @@ namespace { class PPValue { SourceRange Range; IdentifierInfo *II; + public: llvm::APSInt Val; @@ -58,7 +69,7 @@ public: void setEnd(SourceLocation L) { Range.setEnd(L); } }; -} +} // end anonymous namespace static bool EvaluateDirectiveSubExpr(PPValue &LHS, unsigned MinPrec, Token &PeekTok, bool ValueLive, @@ -469,8 +480,6 @@ static bool EvaluateValue(PPValue &Result, Token &PeekTok, DefinedTracker &DT, } } - - /// getPrecedence - Return the precedence of the specified binary operator /// token. This returns: /// ~0 - Invalid token. @@ -531,7 +540,7 @@ static bool EvaluateDirectiveSubExpr(PPValue &LHS, unsigned MinPrec, return true; } - while (1) { + while (true) { // If this token has a lower precedence than we are allowed to parse, return // it so that higher levels of the recursion can parse it. if (PeekPrec < MinPrec) diff --git a/lib/Lex/PPLexerChange.cpp b/lib/Lex/PPLexerChange.cpp index e2eceafd983b8..4db17c344b677 100644 --- a/lib/Lex/PPLexerChange.cpp +++ b/lib/Lex/PPLexerChange.cpp @@ -40,10 +40,10 @@ bool Preprocessor::isInPrimaryFile() const { // If there are any stacked lexers, we're in a #include. assert(IsFileLexer(IncludeMacroStack[0]) && "Top level include stack isn't our primary lexer?"); - for (unsigned i = 1, e = IncludeMacroStack.size(); i != e; ++i) - if (IsFileLexer(IncludeMacroStack[i])) - return false; - return true; + return std::none_of(IncludeMacroStack.begin() + 1, IncludeMacroStack.end(), + [this](const IncludeStackInfo &ISI) -> bool { + return IsFileLexer(ISI); + }); } /// getCurrentLexer - Return the current file lexer being lexed from. Note @@ -54,8 +54,7 @@ PreprocessorLexer *Preprocessor::getCurrentFileLexer() const { return CurPPLexer; // Look for a stacked lexer. - for (unsigned i = IncludeMacroStack.size(); i != 0; --i) { - const IncludeStackInfo& ISI = IncludeMacroStack[i-1]; + for (const IncludeStackInfo &ISI : llvm::reverse(IncludeMacroStack)) { if (IsFileLexer(ISI)) return ISI.ThePPLexer; } @@ -566,8 +565,7 @@ void Preprocessor::HandleMicrosoftCommentPaste(Token &Tok) { // explicit EOD token. PreprocessorLexer *FoundLexer = nullptr; bool LexerWasInPPMode = false; - for (unsigned i = 0, e = IncludeMacroStack.size(); i != e; ++i) { - IncludeStackInfo &ISI = *(IncludeMacroStack.end()-i-1); + for (const IncludeStackInfo &ISI : llvm::reverse(IncludeMacroStack)) { if (ISI.ThePPLexer == nullptr) continue; // Scan for a real lexer. // Once we find a real lexer, mark it as raw mode (disabling macro @@ -685,7 +683,7 @@ bool Preprocessor::needModuleMacros() const { return true; // Otherwise, we only need module macros if we're actually compiling a module // interface. - return getLangOpts().CompilingModule; + return getLangOpts().isCompilingModule(); } void Preprocessor::LeaveSubmodule() { diff --git a/lib/Lex/PPMacroExpansion.cpp b/lib/Lex/PPMacroExpansion.cpp index 2ade6df9456a6..aebebaac46ac0 100644 --- a/lib/Lex/PPMacroExpansion.cpp +++ b/lib/Lex/PPMacroExpansion.cpp @@ -12,25 +12,49 @@ // //===----------------------------------------------------------------------===// -#include "clang/Lex/Preprocessor.h" #include "clang/Basic/Attributes.h" #include "clang/Basic/FileManager.h" -#include "clang/Basic/SourceManager.h" +#include "clang/Basic/IdentifierTable.h" +#include "clang/Basic/LLVM.h" +#include "clang/Basic/LangOptions.h" +#include "clang/Basic/ObjCRuntime.h" +#include "clang/Basic/SourceLocation.h" #include "clang/Basic/TargetInfo.h" #include "clang/Lex/CodeCompletionHandler.h" +#include "clang/Lex/DirectoryLookup.h" #include "clang/Lex/ExternalPreprocessorSource.h" #include "clang/Lex/LexDiagnostic.h" #include "clang/Lex/MacroArgs.h" #include "clang/Lex/MacroInfo.h" -#include "llvm/ADT/STLExtras.h" +#include "clang/Lex/Preprocessor.h" +#include "clang/Lex/PreprocessorLexer.h" +#include "clang/Lex/PTHLexer.h" +#include "clang/Lex/Token.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/None.h" +#include "llvm/ADT/Optional.h" #include "llvm/ADT/SmallString.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/Config/llvm-config.h" +#include "llvm/Support/Casting.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Format.h" #include "llvm/Support/raw_ostream.h" -#include <cstdio> +#include <algorithm> +#include <cassert> +#include <cstddef> +#include <cstring> #include <ctime> +#include <string> +#include <tuple> +#include <utility> + using namespace clang; MacroDirective * @@ -68,12 +92,35 @@ void Preprocessor::appendMacroDirective(IdentifierInfo *II, MacroDirective *MD){ } void Preprocessor::setLoadedMacroDirective(IdentifierInfo *II, + MacroDirective *ED, MacroDirective *MD) { + // Normally, when a macro is defined, it goes through appendMacroDirective() + // above, which chains a macro to previous defines, undefs, etc. + // However, in a pch, the whole macro history up to the end of the pch is + // stored, so ASTReader goes through this function instead. + // However, built-in macros are already registered in the Preprocessor + // ctor, and ASTWriter stops writing the macro chain at built-in macros, + // so in that case the chain from the pch needs to be spliced to the existing + // built-in. + assert(II && MD); MacroState &StoredMD = CurSubmoduleState->Macros[II]; - assert(!StoredMD.getLatest() && - "the macro history was modified before initializing it from a pch"); - StoredMD = MD; + + if (auto *OldMD = StoredMD.getLatest()) { + // shouldIgnoreMacro() in ASTWriter also stops at macros from the + // predefines buffer in module builds. However, in module builds, modules + // are loaded completely before predefines are processed, so StoredMD + // will be nullptr for them when they're loaded. StoredMD should only be + // non-nullptr for builtins read from a pch file. + assert(OldMD->getMacroInfo()->isBuiltinMacro() && + "only built-ins should have an entry here"); + assert(!OldMD->getPrevious() && "builtin should only have a single entry"); + ED->setPrevious(OldMD); + StoredMD.setLatest(MD); + } else { + StoredMD = MD; + } + // Setup the identifier as having associated macro history. II->setHasMacroDefinition(true); if (!MD->isDefined() && LeafModuleMacros.find(II) == LeafModuleMacros.end()) @@ -286,7 +333,6 @@ static IdentifierInfo *RegisterBuiltinMacro(Preprocessor &PP, const char *Name){ return Id; } - /// RegisterBuiltinMacros - Register builtin macros, such as __LINE__ with the /// identifier table. void Preprocessor::RegisterBuiltinMacros() { @@ -367,10 +413,8 @@ 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(); - } - /// isNextPPTokenLParen - Determine whether the next preprocessor token to be /// lexed is a '('. If so, consume the token and return true, if not, this /// method should have no observable side-effect on the lexed tokens. @@ -390,8 +434,7 @@ bool Preprocessor::isNextPPTokenLParen() { // macro stack. if (CurPPLexer) return false; - for (unsigned i = IncludeMacroStack.size(); i != 0; --i) { - IncludeStackInfo &Entry = IncludeMacroStack[i-1]; + for (const IncludeStackInfo &Entry : llvm::reverse(IncludeMacroStack)) { if (Entry.TheLexer) Val = Entry.TheLexer->isNextPPTokenLParen(); else if (Entry.ThePTHLexer) @@ -480,8 +523,7 @@ bool Preprocessor::HandleMacroExpandedIdentifier(Token &Identifier, } else { Callbacks->MacroExpands(Identifier, M, ExpansionRange, Args); if (!DelayedMacroExpandsCallbacks.empty()) { - for (unsigned i=0, e = DelayedMacroExpandsCallbacks.size(); i!=e; ++i) { - MacroExpandsInfo &Info = DelayedMacroExpandsCallbacks[i]; + for (const MacroExpandsInfo &Info : DelayedMacroExpandsCallbacks) { // FIXME: We lose macro args info with delayed callback. Callbacks->MacroExpands(Info.Tok, Info.MD, Info.Range, /*Args=*/nullptr); @@ -735,14 +777,14 @@ MacroArgs *Preprocessor::ReadFunctionLikeMacroArgs(Token &MacroName, assert(Tok.isOneOf(tok::l_paren, tok::comma) && "only expect argument separators here"); - unsigned ArgTokenStart = ArgTokens.size(); + size_t ArgTokenStart = ArgTokens.size(); SourceLocation ArgStartLoc = Tok.getLocation(); // C99 6.10.3p11: Keep track of the number of l_parens we have seen. Note // that we already consumed the first one. unsigned NumParens = 0; - while (1) { + while (true) { // Read arguments as unexpanded tokens. This avoids issues, e.g., where // an argument value in a macro could expand to ',' or '(' or ')'. LexUnexpandedToken(Tok); @@ -987,10 +1029,10 @@ Token *Preprocessor::cacheMacroExpandedTokens(TokenLexer *tokLexer, if (cacheNeedsToGrow) { // Go through all the TokenLexers whose 'Tokens' pointer points in the // buffer and update the pointers to the (potential) new buffer array. - for (unsigned i = 0, e = MacroExpandingLexersStack.size(); i != e; ++i) { + for (const auto &Lexer : MacroExpandingLexersStack) { TokenLexer *prevLexer; size_t tokIndex; - std::tie(prevLexer, tokIndex) = MacroExpandingLexersStack[i]; + std::tie(prevLexer, tokIndex) = Lexer; prevLexer->Tokens = MacroExpandedTokens.data() + tokIndex; } } @@ -1043,7 +1085,6 @@ static void ComputeDATE_TIME(SourceLocation &DATELoc, SourceLocation &TIMELoc, } } - /// HasFeature - Return true if we recognize and implement the feature /// specified by the identifier as a standard language feature. static bool HasFeature(const Preprocessor &PP, StringRef Feature) { @@ -1090,6 +1131,7 @@ static bool HasFeature(const Preprocessor &PP, StringRef Feature) { .Case("cxx_rtti", LangOpts.RTTI && LangOpts.RTTIData) .Case("enumerator_attributes", true) .Case("nullability", true) + .Case("nullability_on_arrays", true) .Case("memory_sanitizer", LangOpts.Sanitize.has(SanitizerKind::Memory)) .Case("thread_sanitizer", LangOpts.Sanitize.has(SanitizerKind::Thread)) .Case("dataflow_sanitizer", LangOpts.Sanitize.has(SanitizerKind::DataFlow)) @@ -1171,7 +1213,7 @@ static bool HasFeature(const Preprocessor &PP, StringRef Feature) { .Case("cxx_unrestricted_unions", LangOpts.CPlusPlus11) .Case("cxx_user_literals", LangOpts.CPlusPlus11) .Case("cxx_variadic_templates", LangOpts.CPlusPlus11) - // C++1y features + // C++14 features .Case("cxx_aggregate_nsdmi", LangOpts.CPlusPlus14) .Case("cxx_binary_literals", LangOpts.CPlusPlus14) .Case("cxx_contextual_conversions", LangOpts.CPlusPlus14) @@ -1181,6 +1223,9 @@ static bool HasFeature(const Preprocessor &PP, StringRef Feature) { .Case("cxx_relaxed_constexpr", LangOpts.CPlusPlus14) .Case("cxx_return_type_deduction", LangOpts.CPlusPlus14) .Case("cxx_variable_templates", LangOpts.CPlusPlus14) + // NOTE: For features covered by SD-6, it is preferable to provide *only* + // the SD-6 macro and not a __has_feature check. + // C++ TSes //.Case("cxx_runtime_arrays", LangOpts.CPlusPlusTSArrays) //.Case("cxx_concepts", LangOpts.CPlusPlusTSConcepts) @@ -1264,7 +1309,7 @@ static bool HasExtension(const Preprocessor &PP, StringRef Extension) { .Case("cxx_reference_qualified_functions", LangOpts.CPlusPlus) .Case("cxx_rvalue_references", LangOpts.CPlusPlus) .Case("cxx_variadic_templates", LangOpts.CPlusPlus) - // C++1y features supported by other languages as extensions. + // C++14 features supported by other languages as extensions. .Case("cxx_binary_literals", true) .Case("cxx_init_captures", LangOpts.CPlusPlus11) .Case("cxx_variable_templates", LangOpts.CPlusPlus) @@ -1400,7 +1445,11 @@ static bool EvaluateHasIncludeNext(Token &Tok, // Preprocessor::HandleIncludeNextDirective. const DirectoryLookup *Lookup = PP.GetCurDirLookup(); const FileEntry *LookupFromFile = nullptr; - if (PP.isInPrimaryFile()) { + if (PP.isInPrimaryFile() && PP.getLangOpts().IsHeaderFile) { + // If the main file is a header, then it's either for PCH/AST generation, + // or libclang opened it. Either way, handle it as a normal include below + // and do not complain about __has_include_next. + } else if (PP.isInPrimaryFile()) { Lookup = nullptr; PP.Diag(Tok, diag::pp_include_next_in_primary); } else if (PP.getCurrentSubmodule()) { @@ -1796,7 +1845,7 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) { [this](Token &Tok, bool &HasLexedNextToken) -> int { IdentifierInfo *II = ExpectFeatureIdentifierInfo(Tok, *this, diag::err_expected_id_building_module); - return getLangOpts().CompilingModule && II && + return getLangOpts().isCompilingModule() && II && (II->getName() == getLangOpts().CurrentModule); }); } else if (II == Ident__MODULE__) { diff --git a/lib/Lex/PTHLexer.cpp b/lib/Lex/PTHLexer.cpp index 5f63d35c5be74..ec806e8445311 100644 --- a/lib/Lex/PTHLexer.cpp +++ b/lib/Lex/PTHLexer.cpp @@ -21,7 +21,6 @@ #include "clang/Lex/Preprocessor.h" #include "clang/Lex/Token.h" #include "llvm/ADT/StringExtras.h" -#include "llvm/ADT/StringMap.h" #include "llvm/Support/EndianStream.h" #include "llvm/Support/MemoryBuffer.h" #include <memory> @@ -318,7 +317,7 @@ public: class PTHFileLookupCommonTrait { public: - typedef std::pair<unsigned char, const char*> internal_key_type; + typedef std::pair<unsigned char, StringRef> internal_key_type; typedef unsigned hash_value_type; typedef unsigned offset_type; @@ -353,7 +352,7 @@ public: } static bool EqualKey(internal_key_type a, internal_key_type b) { - return a.first == b.first && strcmp(a.second, b.second) == 0; + return a.first == b.first && a.second == b.second; } static PTHFileData ReadData(const internal_key_type& k, @@ -629,15 +628,15 @@ PTHLexer *PTHManager::CreateLexer(FileID FID) { namespace { class PTHStatData { public: - const bool HasData; uint64_t Size; time_t ModTime; llvm::sys::fs::UniqueID UniqueID; + const bool HasData; bool IsDirectory; PTHStatData(uint64_t Size, time_t ModTime, llvm::sys::fs::UniqueID UniqueID, bool IsDirectory) - : HasData(true), Size(Size), ModTime(ModTime), UniqueID(UniqueID), + : Size(Size), ModTime(ModTime), UniqueID(UniqueID), HasData(true), IsDirectory(IsDirectory) {} PTHStatData() : HasData(false) {} @@ -645,10 +644,10 @@ public: class PTHStatLookupTrait : public PTHFileLookupCommonTrait { public: - typedef const char* external_key_type; // const char* + typedef StringRef external_key_type; // const char* typedef PTHStatData data_type; - static internal_key_type GetInternalKey(const char *path) { + static internal_key_type GetInternalKey(StringRef path) { // The key 'kind' doesn't matter here because it is ignored in EqualKey. return std::make_pair((unsigned char) 0x0, path); } @@ -656,7 +655,7 @@ public: static bool EqualKey(internal_key_type a, internal_key_type b) { // When doing 'stat' lookups we don't care about the kind of 'a' and 'b', // just the paths. - return strcmp(a.second, b.second) == 0; + return a.second == b.second; } static data_type ReadData(const internal_key_type& k, const unsigned char* d, @@ -695,7 +694,7 @@ public: : Cache(FL.getNumBuckets(), FL.getNumEntries(), FL.getBuckets(), FL.getBase()) {} - LookupResult getStat(const char *Path, FileData &Data, bool isFile, + LookupResult getStat(StringRef Path, FileData &Data, bool isFile, std::unique_ptr<vfs::File> *F, vfs::FileSystem &FS) override { // Do the lookup for the file's data in the PTH file. diff --git a/lib/Lex/Pragma.cpp b/lib/Lex/Pragma.cpp index 3bdd31b26ff8b..100da514144a6 100644 --- a/lib/Lex/Pragma.cpp +++ b/lib/Lex/Pragma.cpp @@ -14,21 +14,36 @@ #include "clang/Lex/Pragma.h" #include "clang/Basic/FileManager.h" +#include "clang/Basic/IdentifierTable.h" +#include "clang/Basic/SourceLocation.h" #include "clang/Basic/SourceManager.h" +#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" +#include "clang/Lex/PreprocessorLexer.h" +#include "clang/Lex/PTHLexer.h" +#include "clang/Lex/Token.h" +#include "clang/Lex/TokenLexer.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringSwitch.h" -#include "llvm/ADT/StringExtras.h" #include "llvm/Support/CrashRecoveryContext.h" +#include "llvm/Support/Compiler.h" #include "llvm/Support/ErrorHandling.h" #include <algorithm> -using namespace clang; +#include <cassert> +#include <cstdint> +#include <limits> +#include <string> +#include <vector> -#include "llvm/Support/raw_ostream.h" +using namespace clang; // Out-of-line destructor to provide a home for the class. PragmaHandler::~PragmaHandler() { @@ -123,6 +138,7 @@ void Preprocessor::HandlePragmaDirective(SourceLocation IntroducerLoc, } namespace { + /// \brief Helper class for \see Preprocessor::Handle_Pragma. class LexingFor_PragmaRAII { Preprocessor &PP; @@ -157,7 +173,8 @@ public: Failed = true; } }; -} + +} // end anonymous namespace /// Handle_Pragma - Read a _Pragma directive, slice it up, process it, then /// return the first token after the directive. The _Pragma token has just @@ -264,7 +281,7 @@ void Preprocessor::Handle_Pragma(Token &Tok) { // Remove escaped quotes and escapes. unsigned ResultPos = 1; - for (unsigned i = 1, e = StrVal.size() - 1; i != e; ++i) { + for (size_t i = 1, e = StrVal.size() - 1; i != e; ++i) { // Skip escapes. \\ -> '\' and \" -> '"'. if (StrVal[i] == '\\' && i + 1 < e && (StrVal[i + 1] == '\\' || StrVal[i + 1] == '"')) @@ -355,8 +372,10 @@ void Preprocessor::HandleMicrosoft__pragma(Token &Tok) { /// void Preprocessor::HandlePragmaOnce(Token &OnceTok) { // Don't honor the 'once' when handling the primary source file, unless - // this is a prefix to a TU, which indicates we're generating a PCH file. - if (isInPrimaryFile() && TUKind != TU_Prefix) { + // this is a prefix to a TU, which indicates we're generating a PCH file, or + // when the main file is a header (e.g. when -xc-header is provided on the + // commandline). + if (isInPrimaryFile() && TUKind != TU_Prefix && !getLangOpts().IsHeaderFile) { Diag(OnceTok, diag::pp_pragma_once_in_main_file); return; } @@ -374,13 +393,12 @@ void Preprocessor::HandlePragmaMark() { CurPTHLexer->DiscardToEndOfLine(); } - /// HandlePragmaPoison - Handle \#pragma GCC poison. PoisonTok is the 'poison'. /// -void Preprocessor::HandlePragmaPoison(Token &PoisonTok) { +void Preprocessor::HandlePragmaPoison() { Token Tok; - while (1) { + while (true) { // Read the next token to poison. While doing this, pretend that we are // skipping while reading the identifier to poison. // This avoids errors on code like: @@ -612,7 +630,7 @@ void Preprocessor::HandlePragmaPopMacro(Token &PopMacroTok) { // Pop PragmaPushMacroInfo stack. iter->second.pop_back(); - if (iter->second.size() == 0) + if (iter->second.empty()) PragmaPushMacroInfo.erase(iter); } else { Diag(MessageLoc, diag::warn_pragma_pop_macro_no_push) @@ -809,6 +827,7 @@ bool Preprocessor::LexOnOffSwitch(tok::OnOffSwitch &Result) { } namespace { + /// PragmaOnceHandler - "\#pragma once" marks the file as atomically included. struct PragmaOnceHandler : public PragmaHandler { PragmaOnceHandler() : PragmaHandler("once") {} @@ -823,6 +842,7 @@ struct PragmaOnceHandler : public PragmaHandler { /// rest of the line is not lexed. struct PragmaMarkHandler : public PragmaHandler { PragmaMarkHandler() : PragmaHandler("mark") {} + void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, Token &MarkTok) override { PP.HandlePragmaMark(); @@ -832,9 +852,10 @@ struct PragmaMarkHandler : public PragmaHandler { /// PragmaPoisonHandler - "\#pragma poison x" marks x as not usable. struct PragmaPoisonHandler : public PragmaHandler { PragmaPoisonHandler() : PragmaHandler("poison") {} + void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, Token &PoisonTok) override { - PP.HandlePragmaPoison(PoisonTok); + PP.HandlePragmaPoison(); } }; @@ -842,14 +863,17 @@ struct PragmaPoisonHandler : public PragmaHandler { /// as a system header, which silences warnings in it. struct PragmaSystemHeaderHandler : public PragmaHandler { PragmaSystemHeaderHandler() : PragmaHandler("system_header") {} + void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, Token &SHToken) override { PP.HandlePragmaSystemHeader(SHToken); PP.CheckEndOfDirective("pragma"); } }; + struct PragmaDependencyHandler : public PragmaHandler { PragmaDependencyHandler() : PragmaHandler("dependency") {} + void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, Token &DepToken) override { PP.HandlePragmaDependency(DepToken); @@ -858,6 +882,7 @@ struct PragmaDependencyHandler : public PragmaHandler { struct PragmaDebugHandler : public PragmaHandler { PragmaDebugHandler() : PragmaHandler("__debug") {} + void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, Token &DepToken) override { Token Tok; @@ -967,9 +992,11 @@ struct PragmaDebugHandler : public PragmaHandler { struct PragmaDiagnosticHandler : public PragmaHandler { private: const char *Namespace; + public: explicit PragmaDiagnosticHandler(const char *NS) : PragmaHandler("diagnostic"), Namespace(NS) {} + void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, Token &DiagToken) override { SourceLocation DiagLoc = DiagToken.getLocation(); @@ -1142,7 +1169,7 @@ struct PragmaWarningHandler : public PragmaHandler { while (Tok.is(tok::numeric_constant)) { uint64_t Value; if (!PP.parseSimpleIntegerLiteral(Tok, Value) || Value == 0 || - Value > INT_MAX) { + Value > std::numeric_limits<int>::max()) { PP.Diag(Tok, diag::warn_pragma_warning_expected_number); return; } @@ -1267,17 +1294,18 @@ public: /// macro on the top of the stack. struct PragmaPushMacroHandler : public PragmaHandler { PragmaPushMacroHandler() : PragmaHandler("push_macro") {} + void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, Token &PushMacroTok) override { PP.HandlePragmaPushMacro(PushMacroTok); } }; - /// PragmaPopMacroHandler - "\#pragma pop_macro" sets the value of the /// macro to the value on the top of the stack. struct PragmaPopMacroHandler : public PragmaHandler { PragmaPopMacroHandler() : PragmaHandler("pop_macro") {} + void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, Token &PopMacroTok) override { PP.HandlePragmaPopMacro(PopMacroTok); @@ -1289,6 +1317,7 @@ struct PragmaPopMacroHandler : public PragmaHandler { /// PragmaSTDC_FENV_ACCESSHandler - "\#pragma STDC FENV_ACCESS ...". struct PragmaSTDC_FENV_ACCESSHandler : public PragmaHandler { PragmaSTDC_FENV_ACCESSHandler() : PragmaHandler("FENV_ACCESS") {} + void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, Token &Tok) override { tok::OnOffSwitch OOS; @@ -1303,6 +1332,7 @@ struct PragmaSTDC_FENV_ACCESSHandler : public PragmaHandler { struct PragmaSTDC_CX_LIMITED_RANGEHandler : public PragmaHandler { PragmaSTDC_CX_LIMITED_RANGEHandler() : PragmaHandler("CX_LIMITED_RANGE") {} + void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, Token &Tok) override { tok::OnOffSwitch OOS; @@ -1313,6 +1343,7 @@ struct PragmaSTDC_CX_LIMITED_RANGEHandler : public PragmaHandler { /// PragmaSTDC_UnknownHandler - "\#pragma STDC ...". struct PragmaSTDC_UnknownHandler : public PragmaHandler { PragmaSTDC_UnknownHandler() {} + void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, Token &UnknownTok) override { // C99 6.10.6p2, unknown forms are not allowed. @@ -1324,6 +1355,7 @@ struct PragmaSTDC_UnknownHandler : public PragmaHandler { /// \#pragma clang arc_cf_code_audited begin/end struct PragmaARCCFCodeAuditedHandler : public PragmaHandler { PragmaARCCFCodeAuditedHandler() : PragmaHandler("arc_cf_code_audited") {} + void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, Token &NameTok) override { SourceLocation Loc = NameTok.getLocation(); @@ -1378,6 +1410,7 @@ struct PragmaARCCFCodeAuditedHandler : public PragmaHandler { /// \#pragma clang assume_nonnull begin/end struct PragmaAssumeNonNullHandler : public PragmaHandler { PragmaAssumeNonNullHandler() : PragmaHandler("assume_nonnull") {} + void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, Token &NameTok) override { SourceLocation Loc = NameTok.getLocation(); @@ -1451,8 +1484,7 @@ struct PragmaRegionHandler : public PragmaHandler { } }; -} // end anonymous namespace - +} // end anonymous namespace /// RegisterBuiltinPragmas - Install the standard preprocessor pragmas: /// \#pragma GCC poison/system_header/dependency and \#pragma once. diff --git a/lib/Lex/PreprocessingRecord.cpp b/lib/Lex/PreprocessingRecord.cpp index 32e6de69f0dbf..13e15f3c943be 100644 --- a/lib/Lex/PreprocessingRecord.cpp +++ b/lib/Lex/PreprocessingRecord.cpp @@ -21,18 +21,13 @@ using namespace clang; ExternalPreprocessingRecordSource::~ExternalPreprocessingRecordSource() { } - InclusionDirective::InclusionDirective(PreprocessingRecord &PPRec, - InclusionKind Kind, - StringRef FileName, + InclusionKind Kind, StringRef FileName, bool InQuotes, bool ImportedModule, - const FileEntry *File, - SourceRange Range) - : PreprocessingDirective(InclusionDirectiveKind, Range), - InQuotes(InQuotes), Kind(Kind), ImportedModule(ImportedModule), File(File) -{ - char *Memory - = (char*)PPRec.Allocate(FileName.size() + 1, llvm::alignOf<char>()); + const FileEntry *File, SourceRange Range) + : PreprocessingDirective(InclusionDirectiveKind, Range), InQuotes(InQuotes), + Kind(Kind), ImportedModule(ImportedModule), File(File) { + char *Memory = (char *)PPRec.Allocate(FileName.size() + 1, alignof(char)); memcpy(Memory, FileName.data(), FileName.size()); Memory[FileName.size()] = 0; this->FileName = StringRef(Memory, FileName.size()); diff --git a/lib/Lex/Preprocessor.cpp b/lib/Lex/Preprocessor.cpp index 78179dd7988df..0f7473b8c1ffc 100644 --- a/lib/Lex/Preprocessor.cpp +++ b/lib/Lex/Preprocessor.cpp @@ -43,18 +43,27 @@ #include "clang/Lex/PreprocessingRecord.h" #include "clang/Lex/PreprocessorOptions.h" #include "clang/Lex/ScratchBuffer.h" -#include "llvm/ADT/APFloat.h" -#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/APInt.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallString.h" -#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/StringSwitch.h" #include "llvm/Support/Capacity.h" -#include "llvm/Support/ConvertUTF.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/raw_ostream.h" +#include <algorithm> +#include <cassert> +#include <memory> +#include <string> #include <utility> +#include <vector> + using namespace clang; -template class llvm::Registry<clang::PragmaHandler>; +LLVM_INSTANTIATE_REGISTRY(PragmaHandlerRegistry) //===----------------------------------------------------------------------===// ExternalPreprocessorSource::~ExternalPreprocessorSource() { } @@ -74,11 +83,12 @@ Preprocessor::Preprocessor(IntrusiveRefCntPtr<PreprocessorOptions> PPOpts, 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) { + 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) { OwnsHeaderSearch = OwnsHeaders; CounterValue = 0; // __COUNTER__ starts at 0. @@ -480,7 +490,7 @@ void Preprocessor::CreateString(StringRef Str, Token &Tok, } Module *Preprocessor::getCurrentModule() { - if (!getLangOpts().CompilingModule) + if (!getLangOpts().isCompilingModule()) return nullptr; return getHeaderSearchInfo().lookupModule(getLangOpts().CurrentModule); @@ -490,7 +500,6 @@ Module *Preprocessor::getCurrentModule() { // Preprocessor Initialization Methods //===----------------------------------------------------------------------===// - /// EnterMainSourceFile - Enter the specified FileID as the main source file, /// which implicitly adds the builtin defines etc. void Preprocessor::EnterMainSourceFile() { @@ -618,6 +627,11 @@ static diag::kind getFutureCompatDiagKind(const IdentifierInfo &II, "Keyword not known to come from a newer Standard or proposed Standard"); } +void Preprocessor::updateOutOfDateIdentifier(IdentifierInfo &II) const { + assert(II.isOutOfDate() && "not out of date"); + getExternalSource()->updateOutOfDateIdentifier(II); +} + /// HandleIdentifier - This callback is invoked when the lexer reads an /// identifier. This callback looks up the identifier in the map and/or /// potentially macro expands it or turns it into a named token (like 'for'). @@ -642,7 +656,7 @@ bool Preprocessor::HandleIdentifier(Token &Identifier) { if (&II == Ident__VA_ARGS__) CurrentIsPoisoned = Ident__VA_ARGS__->isPoisoned(); - ExternalSource->updateOutOfDateIdentifier(II); + updateOutOfDateIdentifier(II); Identifier.setKind(II.getTokenID()); if (&II == Ident__VA_ARGS__) @@ -707,9 +721,12 @@ bool Preprocessor::HandleIdentifier(Token &Identifier) { // Note that we do not treat 'import' as a contextual // keyword when we're in a caching lexer, because caching lexers only get // used in contexts where import declarations are disallowed. - if (LastTokenWasAt && II.isModulesImport() && !InMacroArgs && - !DisableMacroExpansion && - (getLangOpts().Modules || getLangOpts().DebuggerSupport) && + // + // Likewise if this is the C++ Modules TS import keyword. + if (((LastTokenWasAt && II.isModulesImport()) || + Identifier.is(tok::kw_import)) && + !InMacroArgs && !DisableMacroExpansion && + (getLangOpts().Modules || getLangOpts().DebuggerSupport) && CurLexerKind != CLK_CachingLexer) { ModuleImportLoc = Identifier.getLocation(); ModuleImportPath.clear(); @@ -744,10 +761,12 @@ void Preprocessor::Lex(Token &Result) { } } while (!ReturnedToken); + if (Result.is(tok::code_completion)) + setCodeCompletionIdentifierInfo(Result.getIdentifierInfo()); + LastTokenWasAt = Result.is(tok::at); } - /// \brief Lex a token following the 'import' contextual keyword. /// void Preprocessor::LexAfterModuleImport(Token &Result) { @@ -774,7 +793,8 @@ void Preprocessor::LexAfterModuleImport(Token &Result) { } // If we're expecting a '.' or a ';', and we got a '.', then wait until we - // see the next identifier. + // see the next identifier. (We can also see a '[[' that begins an + // attribute-specifier-seq here under the C++ Modules TS.) if (!ModuleImportExpectsIdentifier && Result.getKind() == tok::period) { ModuleImportExpectsIdentifier = true; CurLexerKind = CLK_LexAfterModuleImport; @@ -783,6 +803,23 @@ void Preprocessor::LexAfterModuleImport(Token &Result) { // If we have a non-empty module path, load the named module. if (!ModuleImportPath.empty()) { + // Under the Modules TS, the dot is just part of the module name, and not + // a real hierarachy separator. Flatten such module names now. + // + // FIXME: Is this the right level to be performing this transformation? + std::string FlatModuleName; + if (getLangOpts().ModulesTS) { + for (auto &Piece : ModuleImportPath) { + if (!FlatModuleName.empty()) + FlatModuleName += "."; + FlatModuleName += Piece.first->getName(); + } + SourceLocation FirstPathLoc = ModuleImportPath[0].second; + ModuleImportPath.clear(); + ModuleImportPath.push_back( + std::make_pair(getIdentifierInfo(FlatModuleName), FirstPathLoc)); + } + Module *Imported = nullptr; if (getLangOpts().Modules) { Imported = TheModuleLoader.loadModule(ModuleImportLoc, diff --git a/lib/Lex/TokenConcatenation.cpp b/lib/Lex/TokenConcatenation.cpp index 27b4eab1a28db..d1facd9c68796 100644 --- a/lib/Lex/TokenConcatenation.cpp +++ b/lib/Lex/TokenConcatenation.cpp @@ -232,7 +232,7 @@ bool TokenConcatenation::AvoidConcat(const Token &PrevPrevTok, // it as an identifier. if (!PrevTok.hasUDSuffix()) return false; - // FALL THROUGH. + LLVM_FALLTHROUGH; case tok::identifier: // id+id or id+number or id+L"foo". // id+'.'... will not append. if (Tok.is(tok::numeric_constant)) diff --git a/lib/Lex/TokenLexer.cpp b/lib/Lex/TokenLexer.cpp index 994bae632aec7..a53c8014ebaf0 100644 --- a/lib/Lex/TokenLexer.cpp +++ b/lib/Lex/TokenLexer.cpp @@ -275,7 +275,7 @@ void TokenLexer::ExpandFunctionArguments() { // If the arg token expanded into anything, append it. if (ResultArgToks->isNot(tok::eof)) { - unsigned FirstResult = ResultToks.size(); + size_t FirstResult = ResultToks.size(); unsigned NumToks = MacroArgs::getArgLength(ResultArgToks); ResultToks.append(ResultArgToks, ResultArgToks+NumToks); @@ -289,8 +289,8 @@ void TokenLexer::ExpandFunctionArguments() { // If the '##' came from expanding an argument, turn it into 'unknown' // to avoid pasting. - for (unsigned i = FirstResult, e = ResultToks.size(); i != e; ++i) { - Token &Tok = ResultToks[i]; + for (Token &Tok : llvm::make_range(ResultToks.begin() + FirstResult, + ResultToks.end())) { if (Tok.is(tok::hashhash)) Tok.setKind(tok::unknown); } @@ -333,9 +333,8 @@ void TokenLexer::ExpandFunctionArguments() { // If the '##' came from expanding an argument, turn it into 'unknown' // to avoid pasting. - for (unsigned i = ResultToks.size() - NumToks, e = ResultToks.size(); - i != e; ++i) { - Token &Tok = ResultToks[i]; + for (Token &Tok : llvm::make_range(ResultToks.end() - NumToks, + ResultToks.end())) { if (Tok.is(tok::hashhash)) Tok.setKind(tok::unknown); } |