diff options
Diffstat (limited to 'lib/Lex')
-rw-r--r-- | lib/Lex/DependencyDirectivesSourceMinimizer.cpp | 250 | ||||
-rw-r--r-- | lib/Lex/HeaderMap.cpp | 8 | ||||
-rw-r--r-- | lib/Lex/HeaderSearch.cpp | 348 | ||||
-rw-r--r-- | lib/Lex/Lexer.cpp | 9 | ||||
-rw-r--r-- | lib/Lex/MacroArgs.cpp | 20 | ||||
-rw-r--r-- | lib/Lex/ModuleMap.cpp | 73 | ||||
-rw-r--r-- | lib/Lex/PPDirectives.cpp | 391 | ||||
-rw-r--r-- | lib/Lex/PPLexerChange.cpp | 25 | ||||
-rw-r--r-- | lib/Lex/PPMacroExpansion.cpp | 52 | ||||
-rw-r--r-- | lib/Lex/Pragma.cpp | 85 | ||||
-rw-r--r-- | lib/Lex/Preprocessor.cpp | 13 | ||||
-rw-r--r-- | lib/Lex/TokenLexer.cpp | 16 | ||||
-rw-r--r-- | lib/Lex/UnicodeCharSets.h | 2 |
13 files changed, 826 insertions, 466 deletions
diff --git a/lib/Lex/DependencyDirectivesSourceMinimizer.cpp b/lib/Lex/DependencyDirectivesSourceMinimizer.cpp index cfc37c5d3c62..f063ed711c44 100644 --- a/lib/Lex/DependencyDirectivesSourceMinimizer.cpp +++ b/lib/Lex/DependencyDirectivesSourceMinimizer.cpp @@ -59,6 +59,7 @@ private: LLVM_NODISCARD bool minimizeImpl(const char *First, const char *const End); LLVM_NODISCARD bool lexPPLine(const char *&First, const char *const End); LLVM_NODISCARD bool lexAt(const char *&First, const char *const End); + LLVM_NODISCARD bool lexModule(const char *&First, const char *const End); LLVM_NODISCARD bool lexDefine(const char *&First, const char *const End); LLVM_NODISCARD bool lexPragma(const char *&First, const char *const End); LLVM_NODISCARD bool lexEndif(const char *&First, const char *const End); @@ -184,26 +185,58 @@ static void skipRawString(const char *&First, const char *const End) { } } +// Returns the length of EOL, either 0 (no end-of-line), 1 (\n) or 2 (\r\n) +static unsigned isEOL(const char *First, const char *const End) { + if (First == End) + return 0; + if (End - First > 1 && isVerticalWhitespace(First[0]) && + isVerticalWhitespace(First[1]) && First[0] != First[1]) + return 2; + return !!isVerticalWhitespace(First[0]); +} + static void skipString(const char *&First, const char *const End) { - assert(*First == '\'' || *First == '"'); - const char Terminator = *First; - for (++First; First != End && *First != Terminator; ++First) - if (*First == '\\') - if (++First == End) - return; + assert(*First == '\'' || *First == '"' || *First == '<'); + const char Terminator = *First == '<' ? '>' : *First; + for (++First; First != End && *First != Terminator; ++First) { + // String and character literals don't extend past the end of the line. + if (isVerticalWhitespace(*First)) + return; + if (*First != '\\') + continue; + // Skip past backslash to the next character. This ensures that the + // character right after it is skipped as well, which matters if it's + // the terminator. + if (++First == End) + return; + if (!isWhitespace(*First)) + continue; + // Whitespace after the backslash might indicate a line continuation. + const char *FirstAfterBackslashPastSpace = First; + skipOverSpaces(FirstAfterBackslashPastSpace, End); + if (unsigned NLSize = isEOL(FirstAfterBackslashPastSpace, End)) { + // Advance the character pointer to the next line for the next + // iteration. + First = FirstAfterBackslashPastSpace + NLSize - 1; + } + } if (First != End) ++First; // Finish off the string. } -static void skipNewline(const char *&First, const char *End) { - assert(isVerticalWhitespace(*First)); - ++First; +// Returns the length of the skipped newline +static unsigned skipNewline(const char *&First, const char *End) { if (First == End) - return; + return 0; + assert(isVerticalWhitespace(*First)); + unsigned Len = isEOL(First, End); + assert(Len && "expected newline"); + First += Len; + return Len; +} - // Check for "\n\r" and "\r\n". - if (LLVM_UNLIKELY(isVerticalWhitespace(*First) && First[-1] != First[0])) - ++First; +static bool wasLineContinuation(const char *First, unsigned EOLLen) { + return *(First - (int)EOLLen - 1) == '\\'; } static void skipToNewlineRaw(const char *&First, const char *const End) { @@ -211,27 +244,40 @@ static void skipToNewlineRaw(const char *&First, const char *const End) { if (First == End) return; - if (isVerticalWhitespace(*First)) + unsigned Len = isEOL(First, End); + if (Len) return; - while (!isVerticalWhitespace(*First)) + do { if (++First == End) return; + Len = isEOL(First, End); + } while (!Len); if (First[-1] != '\\') return; - ++First; // Keep going... + First += Len; + // Keep skipping lines... } } -static const char *reverseOverSpaces(const char *First, const char *Last) { +static const char *findLastNonSpace(const char *First, const char *Last) { assert(First <= Last); while (First != Last && isHorizontalWhitespace(Last[-1])) --Last; return Last; } +static const char *findFirstTrailingSpace(const char *First, + const char *Last) { + const char *LastNonSpace = findLastNonSpace(First, Last); + if (Last == LastNonSpace) + return Last; + assert(isHorizontalWhitespace(LastNonSpace[0])); + return LastNonSpace + 1; +} + static void skipLineComment(const char *&First, const char *const End) { assert(First[0] == '/' && First[1] == '/'); First += 2; @@ -276,7 +322,7 @@ static bool isQuoteCppDigitSeparator(const char *const Start, } static void skipLine(const char *&First, const char *const End) { - do { + for (;;) { assert(First <= End); if (First == End) return; @@ -321,9 +367,10 @@ static void skipLine(const char *&First, const char *const End) { return; // Skip over the newline. - assert(isVerticalWhitespace(*First)); - skipNewline(First, End); - } while (First[-2] == '\\'); // Continue past line-continuations. + unsigned Len = skipNewline(First, End); + if (!wasLineContinuation(First, Len)) // Continue past line-continuations. + break; + } } static void skipDirective(StringRef Name, const char *&First, @@ -343,7 +390,8 @@ void Minimizer::printToNewline(const char *&First, const char *const End) { const char *Last = First; do { // Iterate over strings correctly to avoid comments and newlines. - if (*Last == '"' || *Last == '\'') { + if (*Last == '"' || *Last == '\'' || + (*Last == '<' && top() == pp_include)) { if (LLVM_UNLIKELY(isRawStringLiteral(First, Last))) skipRawString(Last, End); else @@ -361,7 +409,7 @@ void Minimizer::printToNewline(const char *&First, const char *const End) { } // Deal with "//..." and "/*...*/". - append(First, reverseOverSpaces(First, Last)); + append(First, findFirstTrailingSpace(First, Last)); First = Last; if (Last[1] == '/') { @@ -376,13 +424,20 @@ void Minimizer::printToNewline(const char *&First, const char *const End) { } while (Last != End && !isVerticalWhitespace(*Last)); // Print out the string. - if (Last == End || Last == First || Last[-1] != '\\') { - append(First, reverseOverSpaces(First, Last)); + const char *LastBeforeTrailingSpace = findLastNonSpace(First, Last); + if (Last == End || LastBeforeTrailingSpace == First || + LastBeforeTrailingSpace[-1] != '\\') { + append(First, LastBeforeTrailingSpace); + First = Last; + skipNewline(First, End); return; } - // Print up to the backslash, backing up over spaces. - append(First, reverseOverSpaces(First, Last - 1)); + // Print up to the backslash, backing up over spaces. Preserve at least one + // space, as the space matters when tokens are separated by a line + // continuation. + append(First, findFirstTrailingSpace( + First, LastBeforeTrailingSpace - 1)); First = Last; skipNewline(First, End); @@ -576,6 +631,59 @@ bool Minimizer::lexAt(const char *&First, const char *const End) { return false; } +bool Minimizer::lexModule(const char *&First, const char *const End) { + IdInfo Id = lexIdentifier(First, End); + First = Id.Last; + bool Export = false; + if (Id.Name == "export") { + Export = true; + skipWhitespace(First, End); + if (!isIdentifierBody(*First)) { + skipLine(First, End); + return false; + } + Id = lexIdentifier(First, End); + First = Id.Last; + } + + if (Id.Name != "module" && Id.Name != "import") { + skipLine(First, End); + return false; + } + + skipWhitespace(First, End); + + // Ignore this as a module directive if the next character can't be part of + // an import. + + switch (*First) { + case ':': + case '<': + case '"': + break; + default: + if (!isIdentifierBody(*First)) { + skipLine(First, End); + return false; + } + } + + if (Export) { + makeToken(cxx_export_decl); + append("export "); + } + + if (Id.Name == "module") + makeToken(cxx_module_decl); + else + makeToken(cxx_import_decl); + append(Id.Name); + append(" "); + printToNewline(First, End); + append("\n"); + return false; +} + bool Minimizer::lexDefine(const char *&First, const char *const End) { makeToken(pp_define); append("#define "); @@ -612,7 +720,21 @@ bool Minimizer::lexDefine(const char *&First, const char *const End) { bool Minimizer::lexPragma(const char *&First, const char *const End) { // #pragma. - if (!isNextIdentifier("clang", First, End)) { + skipWhitespace(First, End); + if (First == End || !isIdentifierHead(*First)) + return false; + + IdInfo FoundId = lexIdentifier(First, End); + First = FoundId.Last; + if (FoundId.Name == "once") { + // #pragma once + skipLine(First, End); + makeToken(pp_pragma_once); + append("#pragma once\n"); + return false; + } + + if (FoundId.Name != "clang") { skipLine(First, End); return false; } @@ -663,6 +785,18 @@ bool Minimizer::lexDefault(TokenKind Kind, StringRef Directive, return false; } +static bool isStartOfRelevantLine(char First) { + switch (First) { + case '#': + case '@': + case 'i': + case 'e': + case 'm': + return true; + } + return false; +} + bool Minimizer::lexPPLine(const char *&First, const char *const End) { assert(First != End); @@ -671,7 +805,7 @@ bool Minimizer::lexPPLine(const char *&First, const char *const End) { if (First == End) return false; - if (*First != '#' && *First != '@') { + if (!isStartOfRelevantLine(*First)) { skipLine(First, End); assert(First <= End); return false; @@ -681,6 +815,9 @@ bool Minimizer::lexPPLine(const char *&First, const char *const End) { if (*First == '@') return lexAt(First, End); + if (*First == 'i' || *First == 'e' || *First == 'm') + return lexModule(First, End); + // Handle preprocessing directives. ++First; // Skip over '#'. skipWhitespace(First, End); @@ -729,7 +866,14 @@ bool Minimizer::lexPPLine(const char *&First, const char *const End) { return lexDefault(Kind, Id.Name, First, End); } +static void skipUTF8ByteOrderMark(const char *&First, const char *const End) { + if ((End - First) >= 3 && First[0] == '\xef' && First[1] == '\xbb' && + First[2] == '\xbf') + First += 3; +} + bool Minimizer::minimizeImpl(const char *First, const char *const End) { + skipUTF8ByteOrderMark(First, End); while (First != End) if (lexPPLine(First, End)) return true; @@ -753,6 +897,54 @@ bool Minimizer::minimize() { return Error; } +bool clang::minimize_source_to_dependency_directives::computeSkippedRanges( + ArrayRef<Token> Input, llvm::SmallVectorImpl<SkippedRange> &Range) { + struct Directive { + enum DirectiveKind { + If, // if/ifdef/ifndef + Else // elif,else + }; + int Offset; + DirectiveKind Kind; + }; + llvm::SmallVector<Directive, 32> Offsets; + for (const Token &T : Input) { + switch (T.K) { + case pp_if: + case pp_ifdef: + case pp_ifndef: + Offsets.push_back({T.Offset, Directive::If}); + break; + + case pp_elif: + case pp_else: { + if (Offsets.empty()) + return true; + int PreviousOffset = Offsets.back().Offset; + Range.push_back({PreviousOffset, T.Offset - PreviousOffset}); + Offsets.push_back({T.Offset, Directive::Else}); + break; + } + + case pp_endif: { + if (Offsets.empty()) + return true; + int PreviousOffset = Offsets.back().Offset; + Range.push_back({PreviousOffset, T.Offset - PreviousOffset}); + do { + Directive::DirectiveKind Kind = Offsets.pop_back_val().Kind; + if (Kind == Directive::If) + break; + } while (!Offsets.empty()); + break; + } + default: + break; + } + } + return false; +} + bool clang::minimizeSourceToDependencyDirectives( StringRef Input, SmallVectorImpl<char> &Output, SmallVectorImpl<Token> &Tokens, DiagnosticsEngine *Diags, diff --git a/lib/Lex/HeaderMap.cpp b/lib/Lex/HeaderMap.cpp index e0bf58b67505..d44ef29c05d1 100644 --- a/lib/Lex/HeaderMap.cpp +++ b/lib/Lex/HeaderMap.cpp @@ -196,15 +196,15 @@ LLVM_DUMP_METHOD void HeaderMapImpl::dump() const { /// LookupFile - Check to see if the specified relative filename is located in /// this HeaderMap. If so, open it and return its FileEntry. -const FileEntry *HeaderMap::LookupFile( - StringRef Filename, FileManager &FM) const { +Optional<FileEntryRef> HeaderMap::LookupFile(StringRef Filename, + FileManager &FM) const { SmallString<1024> Path; StringRef Dest = HeaderMapImpl::lookupFilename(Filename, Path); if (Dest.empty()) - return nullptr; + return None; - return FM.getFile(Dest); + return FM.getOptionalFileRef(Dest); } StringRef HeaderMapImpl::lookupFilename(StringRef Filename, diff --git a/lib/Lex/HeaderSearch.cpp b/lib/Lex/HeaderSearch.cpp index 108630cc26f6..f0c5900c8ce4 100644 --- a/lib/Lex/HeaderSearch.cpp +++ b/lib/Lex/HeaderSearch.cpp @@ -27,9 +27,11 @@ #include "llvm/ADT/Hashing.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/Statistic.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/Capacity.h" +#include "llvm/Support/Errc.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Path.h" @@ -45,6 +47,16 @@ using namespace clang; +#define DEBUG_TYPE "file-search" + +ALWAYS_ENABLED_STATISTIC(NumIncluded, "Number of attempted #includes."); +ALWAYS_ENABLED_STATISTIC( + NumMultiIncludeFileOptzn, + "Number of #includes skipped due to the multi-include optimization."); +ALWAYS_ENABLED_STATISTIC(NumFrameworkLookups, "Number of framework lookups."); +ALWAYS_ENABLED_STATISTIC(NumSubFrameworkLookups, + "Number of subframework lookups."); + const IdentifierInfo * HeaderFileInfo::getControllingMacro(ExternalPreprocessorSource *External) { if (ControllingMacro) { @@ -75,8 +87,8 @@ HeaderSearch::HeaderSearch(std::shared_ptr<HeaderSearchOptions> HSOpts, ModMap(SourceMgr, Diags, LangOpts, Target, *this) {} void HeaderSearch::PrintStats() { - fprintf(stderr, "\n*** HeaderSearch Stats:\n"); - fprintf(stderr, "%d files tracked.\n", (int)FileInfo.size()); + llvm::errs() << "\n*** HeaderSearch Stats:\n" + << FileInfo.size() << " files tracked.\n"; unsigned NumOnceOnlyFiles = 0, MaxNumIncludes = 0, NumSingleIncludedFiles = 0; for (unsigned i = 0, e = FileInfo.size(); i != e; ++i) { NumOnceOnlyFiles += FileInfo[i].isImport; @@ -84,16 +96,16 @@ void HeaderSearch::PrintStats() { MaxNumIncludes = FileInfo[i].NumIncludes; NumSingleIncludedFiles += FileInfo[i].NumIncludes == 1; } - fprintf(stderr, " %d #import/#pragma once files.\n", NumOnceOnlyFiles); - fprintf(stderr, " %d included exactly once.\n", NumSingleIncludedFiles); - fprintf(stderr, " %d max times a file is included.\n", MaxNumIncludes); + llvm::errs() << " " << NumOnceOnlyFiles << " #import/#pragma once files.\n" + << " " << NumSingleIncludedFiles << " included exactly once.\n" + << " " << MaxNumIncludes << " max times a file is included.\n"; - fprintf(stderr, " %d #include/#include_next/#import.\n", NumIncluded); - fprintf(stderr, " %d #includes skipped due to" - " the multi-include optimization.\n", NumMultiIncludeFileOptzn); + llvm::errs() << " " << NumIncluded << " #include/#include_next/#import.\n" + << " " << NumMultiIncludeFileOptzn + << " #includes skipped due to the multi-include optimization.\n"; - fprintf(stderr, "%d framework lookups.\n", NumFrameworkLookups); - fprintf(stderr, "%d subframework lookups.\n", NumSubFrameworkLookups); + llvm::errs() << NumFrameworkLookups << " framework lookups.\n" + << NumSubFrameworkLookups << " subframework lookups.\n"; } /// CreateHeaderMap - This method returns a HeaderMap for the specified @@ -175,10 +187,10 @@ std::string HeaderSearch::getCachedModuleFileName(StringRef ModuleName, std::string Parent = llvm::sys::path::parent_path(ModuleMapPath); if (Parent.empty()) Parent = "."; - auto *Dir = FileMgr.getDirectory(Parent); + auto Dir = FileMgr.getDirectory(Parent); if (!Dir) return {}; - auto DirName = FileMgr.getCanonicalName(Dir); + auto DirName = FileMgr.getCanonicalName(*Dir); auto FileName = llvm::sys::path::filename(ModuleMapPath); llvm::hash_code Hash = @@ -230,11 +242,10 @@ Module *HeaderSearch::lookupModule(StringRef ModuleName, StringRef SearchName, SmallString<128> FrameworkDirName; FrameworkDirName += SearchDirs[Idx].getFrameworkDir()->getName(); llvm::sys::path::append(FrameworkDirName, SearchName + ".framework"); - if (const DirectoryEntry *FrameworkDir - = FileMgr.getDirectory(FrameworkDirName)) { + if (auto FrameworkDir = FileMgr.getDirectory(FrameworkDirName)) { bool IsSystem = SearchDirs[Idx].getDirCharacteristic() != SrcMgr::C_User; - Module = loadFrameworkModule(ModuleName, FrameworkDir, IsSystem); + Module = loadFrameworkModule(ModuleName, *FrameworkDir, IsSystem); if (Module) break; } @@ -296,6 +307,7 @@ Module *HeaderSearch::lookupModule(StringRef ModuleName, StringRef SearchName, /// getName - Return the directory or filename corresponding to this lookup /// object. StringRef DirectoryLookup::getName() const { + // FIXME: Use the name from \c DirectoryEntryRef. if (isNormalDir()) return getDir()->getName(); if (isFramework()) @@ -304,41 +316,46 @@ StringRef DirectoryLookup::getName() const { return getHeaderMap()->getFileName(); } -const FileEntry *HeaderSearch::getFileAndSuggestModule( +Optional<FileEntryRef> HeaderSearch::getFileAndSuggestModule( StringRef FileName, SourceLocation IncludeLoc, 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. - const FileEntry *File = getFileMgr().getFile(FileName, /*OpenFile=*/true); - if (!File) - return nullptr; + auto File = getFileMgr().getFileRef(FileName, /*OpenFile=*/true); + if (!File) { + // For rare, surprising errors (e.g. "out of file handles"), diag the EC + // message. + std::error_code EC = llvm::errorToErrorCode(File.takeError()); + if (EC != llvm::errc::no_such_file_or_directory && + EC != llvm::errc::invalid_argument && + EC != llvm::errc::is_a_directory && EC != llvm::errc::not_a_directory) { + Diags.Report(IncludeLoc, diag::err_cannot_open_file) + << FileName << EC.message(); + } + return None; + } // If there is a module that corresponds to this header, suggest it. - if (!findUsableModuleForHeader(File, Dir ? Dir : File->getDir(), - RequestingModule, SuggestedModule, - IsSystemHeaderDir)) - return nullptr; + if (!findUsableModuleForHeader( + &File->getFileEntry(), Dir ? Dir : File->getFileEntry().getDir(), + RequestingModule, SuggestedModule, IsSystemHeaderDir)) + return None; - return File; + return *File; } /// LookupFile - Lookup the specified file in this search path, returning it /// if it exists or returning null if not. -const FileEntry *DirectoryLookup::LookupFile( - StringRef &Filename, - HeaderSearch &HS, - SourceLocation IncludeLoc, - SmallVectorImpl<char> *SearchPath, - SmallVectorImpl<char> *RelativePath, - Module *RequestingModule, - ModuleMap::KnownHeader *SuggestedModule, - bool &InUserSpecifiedSystemFramework, - bool &IsFrameworkFound, - bool &HasBeenMapped, - SmallVectorImpl<char> &MappedName) const { +Optional<FileEntryRef> DirectoryLookup::LookupFile( + StringRef &Filename, HeaderSearch &HS, SourceLocation IncludeLoc, + SmallVectorImpl<char> *SearchPath, SmallVectorImpl<char> *RelativePath, + Module *RequestingModule, ModuleMap::KnownHeader *SuggestedModule, + bool &InUserSpecifiedSystemFramework, bool &IsFrameworkFound, + bool &IsInHeaderMap, SmallVectorImpl<char> &MappedName) const { InUserSpecifiedSystemFramework = false; - HasBeenMapped = false; + IsInHeaderMap = false; + MappedName.clear(); SmallString<1024> TmpDir; if (isNormalDir()) { @@ -370,24 +387,11 @@ const FileEntry *DirectoryLookup::LookupFile( SmallString<1024> Path; StringRef Dest = HM->lookupFilename(Filename, Path); if (Dest.empty()) - return nullptr; + return None; - const FileEntry *Result; - - // Check if the headermap maps the filename to a framework include - // ("Foo.h" -> "Foo/Foo.h"), in which case continue header lookup using the - // framework include. - if (llvm::sys::path::is_relative(Dest)) { - MappedName.clear(); - MappedName.append(Dest.begin(), Dest.end()); - Filename = StringRef(MappedName.begin(), MappedName.size()); - HasBeenMapped = true; - Result = HM->LookupFile(Filename, HS.getFileMgr()); - } else { - Result = HS.getFileMgr().getFile(Dest); - } + IsInHeaderMap = true; - if (Result) { + auto FixupSearchPath = [&]() { if (SearchPath) { StringRef SearchPathRef(getName()); SearchPath->clear(); @@ -397,8 +401,25 @@ const FileEntry *DirectoryLookup::LookupFile( RelativePath->clear(); RelativePath->append(Filename.begin(), Filename.end()); } + }; + + // Check if the headermap maps the filename to a framework include + // ("Foo.h" -> "Foo/Foo.h"), in which case continue header lookup using the + // framework include. + if (llvm::sys::path::is_relative(Dest)) { + MappedName.append(Dest.begin(), Dest.end()); + Filename = StringRef(MappedName.begin(), MappedName.size()); + Optional<FileEntryRef> Result = HM->LookupFile(Filename, HS.getFileMgr()); + if (Result) { + FixupSearchPath(); + return *Result; + } + } else if (auto Res = HS.getFileMgr().getOptionalFileRef(Dest)) { + FixupSearchPath(); + return *Res; } - return Result; + + return None; } /// Given a framework directory, find the top-most framework directory. @@ -427,8 +448,12 @@ getTopFrameworkDir(FileManager &FileMgr, StringRef DirName, // // Similar issues occur when a top-level framework has moved into an // embedded framework. - const DirectoryEntry *TopFrameworkDir = FileMgr.getDirectory(DirName); - DirName = FileMgr.getCanonicalName(TopFrameworkDir); + const DirectoryEntry *TopFrameworkDir = nullptr; + if (auto TopFrameworkDirOrErr = FileMgr.getDirectory(DirName)) + TopFrameworkDir = *TopFrameworkDirOrErr; + + if (TopFrameworkDir) + DirName = FileMgr.getCanonicalName(TopFrameworkDir); do { // Get the parent directory name. DirName = llvm::sys::path::parent_path(DirName); @@ -436,7 +461,7 @@ getTopFrameworkDir(FileManager &FileMgr, StringRef DirName, break; // Determine whether this directory exists. - const DirectoryEntry *Dir = FileMgr.getDirectory(DirName); + auto Dir = FileMgr.getDirectory(DirName); if (!Dir) break; @@ -444,7 +469,7 @@ getTopFrameworkDir(FileManager &FileMgr, StringRef DirName, // framework. if (llvm::sys::path::extension(DirName) == ".framework") { SubmodulePath.push_back(llvm::sys::path::stem(DirName)); - TopFrameworkDir = Dir; + TopFrameworkDir = *Dir; } } while (true); @@ -459,7 +484,7 @@ static bool needModuleLookup(Module *RequestingModule, /// DoFrameworkLookup - Do a lookup of the specified file in the current /// DirectoryLookup, which is a framework directory. -const FileEntry *DirectoryLookup::DoFrameworkLookup( +Optional<FileEntryRef> DirectoryLookup::DoFrameworkLookup( StringRef Filename, HeaderSearch &HS, SmallVectorImpl<char> *SearchPath, SmallVectorImpl<char> *RelativePath, Module *RequestingModule, ModuleMap::KnownHeader *SuggestedModule, @@ -468,7 +493,8 @@ const FileEntry *DirectoryLookup::DoFrameworkLookup( // Framework names must have a '/' in the filename. size_t SlashPos = Filename.find('/'); - if (SlashPos == StringRef::npos) return nullptr; + if (SlashPos == StringRef::npos) + return None; // Find out if this is the home for the specified framework, by checking // HeaderSearch. Possible answers are yes/no and unknown. @@ -477,13 +503,13 @@ const FileEntry *DirectoryLookup::DoFrameworkLookup( // If it is known and in some other directory, fail. if (CacheEntry.Directory && CacheEntry.Directory != getFrameworkDir()) - return nullptr; + return None; // Otherwise, construct the path to this framework dir. // FrameworkName = "/System/Library/Frameworks/" SmallString<1024> FrameworkName; - FrameworkName += getFrameworkDir()->getName(); + FrameworkName += getFrameworkDirRef()->getName(); if (FrameworkName.empty() || FrameworkName.back() != '/') FrameworkName.push_back('/'); @@ -496,11 +522,12 @@ const FileEntry *DirectoryLookup::DoFrameworkLookup( // If the cache entry was unresolved, populate it now. if (!CacheEntry.Directory) { - HS.IncrementFrameworkLookupCount(); + ++NumFrameworkLookups; // If the framework dir doesn't exist, we fail. - const DirectoryEntry *Dir = FileMgr.getDirectory(FrameworkName); - if (!Dir) return nullptr; + auto Dir = FileMgr.getDirectory(FrameworkName); + if (!Dir) + return None; // Otherwise, if it does, remember that this is the right direntry for this // framework. @@ -538,9 +565,10 @@ const FileEntry *DirectoryLookup::DoFrameworkLookup( } FrameworkName.append(Filename.begin()+SlashPos+1, Filename.end()); - const FileEntry *FE = FileMgr.getFile(FrameworkName, - /*OpenFile=*/!SuggestedModule); - if (!FE) { + + auto File = + FileMgr.getOptionalFileRef(FrameworkName, /*OpenFile=*/!SuggestedModule); + if (!File) { // Check "/System/Library/Frameworks/Cocoa.framework/PrivateHeaders/file.h" const char *Private = "Private"; FrameworkName.insert(FrameworkName.begin()+OrigSize, Private, @@ -549,17 +577,18 @@ const FileEntry *DirectoryLookup::DoFrameworkLookup( SearchPath->insert(SearchPath->begin()+OrigSize, Private, Private+strlen(Private)); - FE = FileMgr.getFile(FrameworkName, /*OpenFile=*/!SuggestedModule); + File = FileMgr.getOptionalFileRef(FrameworkName, + /*OpenFile=*/!SuggestedModule); } // If we found the header and are allowed to suggest a module, do so now. - if (FE && needModuleLookup(RequestingModule, SuggestedModule)) { + if (File && needModuleLookup(RequestingModule, SuggestedModule)) { // Find the framework in which this header occurs. - StringRef FrameworkPath = FE->getDir()->getName(); + StringRef FrameworkPath = File->getFileEntry().getDir()->getName(); bool FoundFramework = false; do { // Determine whether this directory exists. - const DirectoryEntry *Dir = FileMgr.getDirectory(FrameworkPath); + auto Dir = FileMgr.getDirectory(FrameworkPath); if (!Dir) break; @@ -579,15 +608,19 @@ const FileEntry *DirectoryLookup::DoFrameworkLookup( bool IsSystem = getDirCharacteristic() != SrcMgr::C_User; if (FoundFramework) { if (!HS.findUsableModuleForFrameworkHeader( - FE, FrameworkPath, RequestingModule, SuggestedModule, IsSystem)) - return nullptr; + &File->getFileEntry(), FrameworkPath, RequestingModule, + SuggestedModule, IsSystem)) + return None; } else { - if (!HS.findUsableModuleForHeader(FE, getDir(), RequestingModule, - SuggestedModule, IsSystem)) - return nullptr; + if (!HS.findUsableModuleForHeader(&File->getFileEntry(), getDir(), + RequestingModule, SuggestedModule, + IsSystem)) + return None; } } - return FE; + if (File) + return *File; + return None; } void HeaderSearch::setTarget(const TargetInfo &Target) { @@ -692,7 +725,7 @@ diagnoseFrameworkInclude(DiagnosticsEngine &Diags, SourceLocation IncludeLoc, /// for system \#include's or not (i.e. using <> instead of ""). Includers, if /// non-empty, indicates where the \#including file(s) are, in case a relative /// search is needed. Microsoft mode will pass all \#including files. -const FileEntry *HeaderSearch::LookupFile( +Optional<FileEntryRef> HeaderSearch::LookupFile( StringRef Filename, SourceLocation IncludeLoc, bool isAngled, const DirectoryLookup *FromDir, const DirectoryLookup *&CurDir, ArrayRef<std::pair<const FileEntry *, const DirectoryEntry *>> Includers, @@ -714,7 +747,8 @@ const FileEntry *HeaderSearch::LookupFile( CurDir = nullptr; // If this was an #include_next "/absolute/file", fail. - if (FromDir) return nullptr; + if (FromDir) + return None; if (SearchPath) SearchPath->clear(); @@ -729,8 +763,9 @@ const FileEntry *HeaderSearch::LookupFile( } // This is the header that MSVC's header search would have found. - const FileEntry *MSFE = nullptr; ModuleMap::KnownHeader MSSuggestedModule; + const FileEntry *MSFE_FE = nullptr; + StringRef MSFE_Name; // Unless disabled, check to see if the file is in the #includer's // directory. This cannot be based on CurDir, because each includer could be @@ -759,7 +794,7 @@ const FileEntry *HeaderSearch::LookupFile( bool IncluderIsSystemHeader = Includer ? getFileInfo(Includer).DirInfo != SrcMgr::C_User : BuildSystemModule; - if (const FileEntry *FE = getFileAndSuggestModule( + if (Optional<FileEntryRef> FE = getFileAndSuggestModule( TmpDir, IncludeLoc, IncluderAndDir.second, IncluderIsSystemHeader, RequestingModule, SuggestedModule)) { if (!Includer) { @@ -778,7 +813,7 @@ const FileEntry *HeaderSearch::LookupFile( bool IndexHeaderMapHeader = FromHFI.IndexHeaderMapHeader; StringRef Framework = FromHFI.Framework; - HeaderFileInfo &ToHFI = getFileInfo(FE); + HeaderFileInfo &ToHFI = getFileInfo(&FE->getFileEntry()); ToHFI.DirInfo = DirInfo; ToHFI.IndexHeaderMapHeader = IndexHeaderMapHeader; ToHFI.Framework = Framework; @@ -795,7 +830,7 @@ const FileEntry *HeaderSearch::LookupFile( if (First) { diagnoseFrameworkInclude(Diags, IncludeLoc, IncluderAndDir.second->getName(), Filename, - FE); + &FE->getFileEntry()); return FE; } @@ -805,7 +840,8 @@ const FileEntry *HeaderSearch::LookupFile( if (Diags.isIgnored(diag::ext_pp_include_search_ms, IncludeLoc)) { return FE; } else { - MSFE = FE; + MSFE_FE = &FE->getFileEntry(); + MSFE_Name = FE->getName(); if (SuggestedModule) { MSSuggestedModule = *SuggestedModule; *SuggestedModule = ModuleMap::KnownHeader(); @@ -817,6 +853,9 @@ const FileEntry *HeaderSearch::LookupFile( } } + Optional<FileEntryRef> MSFE(MSFE_FE ? FileEntryRef(MSFE_Name, *MSFE_FE) + : Optional<FileEntryRef>()); + CurDir = nullptr; // If this is a system #include, ignore the user #include locs. @@ -856,29 +895,34 @@ const FileEntry *HeaderSearch::LookupFile( // Check each directory in sequence to see if it contains this file. for (; i != SearchDirs.size(); ++i) { bool InUserSpecifiedSystemFramework = false; - bool HasBeenMapped = false; + bool IsInHeaderMap = false; bool IsFrameworkFoundInDir = false; - const FileEntry *FE = SearchDirs[i].LookupFile( + Optional<FileEntryRef> File = SearchDirs[i].LookupFile( Filename, *this, IncludeLoc, SearchPath, RelativePath, RequestingModule, SuggestedModule, InUserSpecifiedSystemFramework, IsFrameworkFoundInDir, - HasBeenMapped, MappedName); - if (HasBeenMapped) { + IsInHeaderMap, MappedName); + if (!MappedName.empty()) { + assert(IsInHeaderMap && "MappedName should come from a header map"); CacheLookup.MappedName = - copyString(Filename, LookupFileCache.getAllocator()); - if (IsMapped) - *IsMapped = true; + copyString(MappedName, LookupFileCache.getAllocator()); } + if (IsMapped) + // A filename is mapped when a header map remapped it to a relative path + // used in subsequent header search or to an absolute path pointing to an + // existing file. + *IsMapped |= (!MappedName.empty() || (IsInHeaderMap && File)); if (IsFrameworkFound) // Because we keep a filename remapped for subsequent search directory // lookups, ignore IsFrameworkFoundInDir after the first remapping and not // just for remapping in a current search directory. *IsFrameworkFound |= (IsFrameworkFoundInDir && !CacheLookup.MappedName); - if (!FE) continue; + if (!File) + continue; CurDir = &SearchDirs[i]; // This file is a system header or C++ unfriendly if the dir is. - HeaderFileInfo &HFI = getFileInfo(FE); + HeaderFileInfo &HFI = getFileInfo(&File->getFileEntry()); HFI.DirInfo = CurDir->getDirCharacteristic(); // If the directory characteristic is User but this framework was @@ -908,7 +952,8 @@ const FileEntry *HeaderSearch::LookupFile( } } - if (checkMSVCHeaderSearch(Diags, MSFE, FE, IncludeLoc)) { + if (checkMSVCHeaderSearch(Diags, MSFE ? &MSFE->getFileEntry() : nullptr, + &File->getFileEntry(), IncludeLoc)) { if (SuggestedModule) *SuggestedModule = MSSuggestedModule; return MSFE; @@ -916,13 +961,13 @@ const FileEntry *HeaderSearch::LookupFile( bool FoundByHeaderMap = !IsMapped ? false : *IsMapped; if (!Includers.empty()) - diagnoseFrameworkInclude(Diags, IncludeLoc, - Includers.front().second->getName(), Filename, - FE, isAngled, FoundByHeaderMap); + diagnoseFrameworkInclude( + Diags, IncludeLoc, Includers.front().second->getName(), Filename, + &File->getFileEntry(), isAngled, FoundByHeaderMap); // Remember this location for the next lookup we do. CacheLookup.HitIdx = i; - return FE; + return File; } // If we are including a file with a quoted include "foo.h" from inside @@ -938,12 +983,14 @@ const FileEntry *HeaderSearch::LookupFile( ScratchFilename += '/'; ScratchFilename += Filename; - const FileEntry *FE = LookupFile( + Optional<FileEntryRef> File = LookupFile( ScratchFilename, IncludeLoc, /*isAngled=*/true, FromDir, CurDir, Includers.front(), SearchPath, RelativePath, RequestingModule, SuggestedModule, IsMapped, /*IsFrameworkFound=*/nullptr); - if (checkMSVCHeaderSearch(Diags, MSFE, FE, IncludeLoc)) { + if (checkMSVCHeaderSearch(Diags, MSFE ? &MSFE->getFileEntry() : nullptr, + File ? &File->getFileEntry() : nullptr, + IncludeLoc)) { if (SuggestedModule) *SuggestedModule = MSSuggestedModule; return MSFE; @@ -952,11 +999,12 @@ const FileEntry *HeaderSearch::LookupFile( LookupFileCacheInfo &CacheLookup = LookupFileCache[Filename]; CacheLookup.HitIdx = LookupFileCache[ScratchFilename].HitIdx; // FIXME: SuggestedModule. - return FE; + return File; } } - if (checkMSVCHeaderSearch(Diags, MSFE, nullptr, IncludeLoc)) { + if (checkMSVCHeaderSearch(Diags, MSFE ? &MSFE->getFileEntry() : nullptr, + nullptr, IncludeLoc)) { if (SuggestedModule) *SuggestedModule = MSSuggestedModule; return MSFE; @@ -964,7 +1012,7 @@ const FileEntry *HeaderSearch::LookupFile( // Otherwise, didn't find it. Remember we didn't find this. CacheLookup.HitIdx = SearchDirs.size(); - return nullptr; + return None; } /// LookupSubframeworkHeader - Look up a subframework for the specified @@ -972,19 +1020,17 @@ const FileEntry *HeaderSearch::LookupFile( /// within ".../Carbon.framework/Headers/Carbon.h", check to see if HIToolbox /// is a subframework within Carbon.framework. If so, return the FileEntry /// for the designated file, otherwise return null. -const FileEntry *HeaderSearch:: -LookupSubframeworkHeader(StringRef Filename, - const FileEntry *ContextFileEnt, - SmallVectorImpl<char> *SearchPath, - SmallVectorImpl<char> *RelativePath, - Module *RequestingModule, - ModuleMap::KnownHeader *SuggestedModule) { +Optional<FileEntryRef> HeaderSearch::LookupSubframeworkHeader( + StringRef Filename, const FileEntry *ContextFileEnt, + SmallVectorImpl<char> *SearchPath, SmallVectorImpl<char> *RelativePath, + Module *RequestingModule, ModuleMap::KnownHeader *SuggestedModule) { assert(ContextFileEnt && "No context file?"); // Framework names must have a '/' in the filename. Find it. // FIXME: Should we permit '\' on Windows? size_t SlashPos = Filename.find('/'); - if (SlashPos == StringRef::npos) return nullptr; + if (SlashPos == StringRef::npos) + return None; // Look up the base framework name of the ContextFileEnt. StringRef ContextName = ContextFileEnt->getName(); @@ -995,7 +1041,7 @@ LookupSubframeworkHeader(StringRef Filename, if (FrameworkPos == StringRef::npos || (ContextName[FrameworkPos + DotFrameworkLen] != '/' && ContextName[FrameworkPos + DotFrameworkLen] != '\\')) - return nullptr; + return None; SmallString<1024> FrameworkName(ContextName.data(), ContextName.data() + FrameworkPos + @@ -1015,22 +1061,22 @@ LookupSubframeworkHeader(StringRef Filename, CacheLookup.first().size() == FrameworkName.size() && memcmp(CacheLookup.first().data(), &FrameworkName[0], CacheLookup.first().size()) != 0) - return nullptr; + return None; // Cache subframework. if (!CacheLookup.second.Directory) { ++NumSubFrameworkLookups; // If the framework dir doesn't exist, we fail. - const DirectoryEntry *Dir = FileMgr.getDirectory(FrameworkName); - if (!Dir) return nullptr; + auto Dir = FileMgr.getDirectory(FrameworkName); + if (!Dir) + return None; // Otherwise, if it does, remember that this is the right direntry for this // framework. - CacheLookup.second.Directory = Dir; + CacheLookup.second.Directory = *Dir; } - const FileEntry *FE = nullptr; if (RelativePath) { RelativePath->clear(); @@ -1047,7 +1093,8 @@ LookupSubframeworkHeader(StringRef Filename, } HeadersFilename.append(Filename.begin()+SlashPos+1, Filename.end()); - if (!(FE = FileMgr.getFile(HeadersFilename, /*OpenFile=*/true))) { + auto File = FileMgr.getOptionalFileRef(HeadersFilename, /*OpenFile=*/true); + if (!File) { // Check ".../Frameworks/HIToolbox.framework/PrivateHeaders/HIToolbox.h" HeadersFilename = FrameworkName; HeadersFilename += "PrivateHeaders/"; @@ -1058,8 +1105,10 @@ LookupSubframeworkHeader(StringRef Filename, } HeadersFilename.append(Filename.begin()+SlashPos+1, Filename.end()); - if (!(FE = FileMgr.getFile(HeadersFilename, /*OpenFile=*/true))) - return nullptr; + File = FileMgr.getOptionalFileRef(HeadersFilename, /*OpenFile=*/true); + + if (!File) + return None; } // This file is a system header or C++ unfriendly if the old file is. @@ -1068,14 +1117,15 @@ LookupSubframeworkHeader(StringRef Filename, // getFileInfo could resize the vector and we don't want to rely on order // of evaluation. unsigned DirInfo = getFileInfo(ContextFileEnt).DirInfo; - getFileInfo(FE).DirInfo = DirInfo; + getFileInfo(&File->getFileEntry()).DirInfo = DirInfo; FrameworkName.pop_back(); // remove the trailing '/' - if (!findUsableModuleForFrameworkHeader(FE, FrameworkName, RequestingModule, - SuggestedModule, /*IsSystem*/ false)) - return nullptr; + if (!findUsableModuleForFrameworkHeader(&File->getFileEntry(), FrameworkName, + RequestingModule, SuggestedModule, + /*IsSystem*/ false)) + return None; - return FE; + return *File; } //===----------------------------------------------------------------------===// @@ -1306,13 +1356,13 @@ bool HeaderSearch::hasModuleMap(StringRef FileName, return false; // Determine whether this directory exists. - const DirectoryEntry *Dir = FileMgr.getDirectory(DirName); + auto Dir = FileMgr.getDirectory(DirName); if (!Dir) return false; // Try to load the module map file in this directory. - switch (loadModuleMapFile(Dir, IsSystem, - llvm::sys::path::extension(Dir->getName()) == + switch (loadModuleMapFile(*Dir, IsSystem, + llvm::sys::path::extension((*Dir)->getName()) == ".framework")) { case LMM_NewlyLoaded: case LMM_AlreadyLoaded: @@ -1328,12 +1378,12 @@ bool HeaderSearch::hasModuleMap(StringRef FileName, } // If we hit the top of our search, we're done. - if (Dir == Root) + if (*Dir == Root) return false; // Keep track of all of the directories we checked, so we can mark them as // having module maps if we eventually do find a module map. - FixUpDirectories.push_back(Dir); + FixUpDirectories.push_back(*Dir); } while (true); } @@ -1417,7 +1467,9 @@ static const FileEntry *getPrivateModuleMap(const FileEntry *File, llvm::sys::path::append(PrivateFilename, "module.private.modulemap"); else return nullptr; - return FileMgr.getFile(PrivateFilename); + if (auto File = FileMgr.getFile(PrivateFilename)) + return *File; + return nullptr; } bool HeaderSearch::loadModuleMapFile(const FileEntry *File, bool IsSystem, @@ -1426,15 +1478,18 @@ bool HeaderSearch::loadModuleMapFile(const FileEntry *File, bool IsSystem, // Find the directory for the module. For frameworks, that may require going // up from the 'Modules' directory. const DirectoryEntry *Dir = nullptr; - if (getHeaderSearchOpts().ModuleMapFileHomeIsCwd) - Dir = FileMgr.getDirectory("."); - else { + if (getHeaderSearchOpts().ModuleMapFileHomeIsCwd) { + if (auto DirOrErr = FileMgr.getDirectory(".")) + Dir = *DirOrErr; + } else { if (!OriginalModuleMapFile.empty()) { // We're building a preprocessed module map. Find or invent the directory // that it originally occupied. - Dir = FileMgr.getDirectory( + auto DirOrErr = FileMgr.getDirectory( llvm::sys::path::parent_path(OriginalModuleMapFile)); - if (!Dir) { + if (DirOrErr) { + Dir = *DirOrErr; + } else { auto *FakeFile = FileMgr.getVirtualFile(OriginalModuleMapFile, 0, 0); Dir = FakeFile->getDir(); } @@ -1446,7 +1501,8 @@ bool HeaderSearch::loadModuleMapFile(const FileEntry *File, bool IsSystem, if (llvm::sys::path::filename(DirName) == "Modules") { DirName = llvm::sys::path::parent_path(DirName); if (DirName.endswith(".framework")) - Dir = FileMgr.getDirectory(DirName); + if (auto DirOrErr = FileMgr.getDirectory(DirName)) + Dir = *DirOrErr; // FIXME: This assert can fail if there's a race between the above check // and the removal of the directory. assert(Dir && "parent must exist"); @@ -1503,13 +1559,15 @@ HeaderSearch::lookupModuleMapFile(const DirectoryEntry *Dir, bool IsFramework) { if (IsFramework) llvm::sys::path::append(ModuleMapFileName, "Modules"); llvm::sys::path::append(ModuleMapFileName, "module.modulemap"); - if (const FileEntry *F = FileMgr.getFile(ModuleMapFileName)) - return F; + if (auto F = FileMgr.getFile(ModuleMapFileName)) + return *F; // Continue to allow module.map ModuleMapFileName = Dir->getName(); llvm::sys::path::append(ModuleMapFileName, "module.map"); - return FileMgr.getFile(ModuleMapFileName); + if (auto F = FileMgr.getFile(ModuleMapFileName)) + return *F; + return nullptr; } Module *HeaderSearch::loadFrameworkModule(StringRef Name, @@ -1540,8 +1598,8 @@ Module *HeaderSearch::loadFrameworkModule(StringRef Name, HeaderSearch::LoadModuleMapResult HeaderSearch::loadModuleMapFile(StringRef DirName, bool IsSystem, bool IsFramework) { - if (const DirectoryEntry *Dir = FileMgr.getDirectory(DirName)) - return loadModuleMapFile(Dir, IsSystem, IsFramework); + if (auto Dir = FileMgr.getDirectory(DirName)) + return loadModuleMapFile(*Dir, IsSystem, IsFramework); return LMM_NoDirectory; } @@ -1589,13 +1647,13 @@ void HeaderSearch::collectAllModules(SmallVectorImpl<Module *> &Modules) { if (llvm::sys::path::extension(Dir->path()) != ".framework") continue; - const DirectoryEntry *FrameworkDir = + auto FrameworkDir = FileMgr.getDirectory(Dir->path()); if (!FrameworkDir) continue; // Load this framework module. - loadFrameworkModule(llvm::sys::path::stem(Dir->path()), FrameworkDir, + loadFrameworkModule(llvm::sys::path::stem(Dir->path()), *FrameworkDir, IsSystem); } continue; diff --git a/lib/Lex/Lexer.cpp b/lib/Lex/Lexer.cpp index db53e6bec044..17f5ab1e035d 100644 --- a/lib/Lex/Lexer.cpp +++ b/lib/Lex/Lexer.cpp @@ -218,6 +218,15 @@ Lexer *Lexer::Create_PragmaLexer(SourceLocation SpellingLoc, return L; } +bool Lexer::skipOver(unsigned NumBytes) { + IsAtPhysicalStartOfLine = true; + IsAtStartOfLine = true; + if ((BufferPtr + NumBytes) > BufferEnd) + return true; + BufferPtr += NumBytes; + return false; +} + template <typename T> static void StringifyImpl(T &Str, char Quote) { typename T::size_type i = 0, e = Str.size(); while (i < e) { diff --git a/lib/Lex/MacroArgs.cpp b/lib/Lex/MacroArgs.cpp index 5aa4679fad46..7ede00b4aa64 100644 --- a/lib/Lex/MacroArgs.cpp +++ b/lib/Lex/MacroArgs.cpp @@ -76,8 +76,6 @@ MacroArgs *MacroArgs::create(const MacroInfo *MI, /// destroy - Destroy and deallocate the memory for this object. /// void MacroArgs::destroy(Preprocessor &PP) { - StringifiedArgs.clear(); - // Don't clear PreExpArgTokens, just clear the entries. Clearing the entries // would deallocate the element vectors. for (unsigned i = 0, e = PreExpArgTokens.size(); i != e; ++i) @@ -307,21 +305,3 @@ Token MacroArgs::StringifyArgument(const Token *ArgToks, ExpansionLocStart, ExpansionLocEnd); return Tok; } - -/// getStringifiedArgument - Compute, cache, and return the specified argument -/// that has been 'stringified' as required by the # operator. -const Token &MacroArgs::getStringifiedArgument(unsigned ArgNo, - Preprocessor &PP, - SourceLocation ExpansionLocStart, - SourceLocation ExpansionLocEnd) { - assert(ArgNo < getNumMacroArguments() && "Invalid argument number!"); - if (StringifiedArgs.empty()) - StringifiedArgs.resize(getNumMacroArguments(), {}); - - if (StringifiedArgs[ArgNo].isNot(tok::string_literal)) - StringifiedArgs[ArgNo] = StringifyArgument(getUnexpArgument(ArgNo), PP, - /*Charify=*/false, - ExpansionLocStart, - ExpansionLocEnd); - return StringifiedArgs[ArgNo]; -} diff --git a/lib/Lex/ModuleMap.cpp b/lib/Lex/ModuleMap.cpp index 5e0be1a57da4..db59629997ee 100644 --- a/lib/Lex/ModuleMap.cpp +++ b/lib/Lex/ModuleMap.cpp @@ -179,12 +179,12 @@ const FileEntry *ModuleMap::findHeader( SmallString<128> FullPathName(Directory->getName()); auto GetFile = [&](StringRef Filename) -> const FileEntry * { - auto *File = SourceMgr.getFileManager().getFile(Filename); + auto File = SourceMgr.getFileManager().getFile(Filename); if (!File || - (Header.Size && File->getSize() != *Header.Size) || - (Header.ModTime && File->getModificationTime() != *Header.ModTime)) + (Header.Size && (*File)->getSize() != *Header.Size) || + (Header.ModTime && (*File)->getModificationTime() != *Header.ModTime)) return nullptr; - return File; + return *File; }; auto GetFrameworkFile = [&]() -> const FileEntry * { @@ -300,12 +300,12 @@ bool ModuleMap::resolveAsBuiltinHeader( // supplied by Clang. Find that builtin header. SmallString<128> Path; llvm::sys::path::append(Path, BuiltinIncludeDir->getName(), Header.FileName); - auto *File = SourceMgr.getFileManager().getFile(Path); + auto File = SourceMgr.getFileManager().getFile(Path); if (!File) return false; auto Role = headerKindToRole(Header.Kind); - Module::Header H = {Path.str(), File}; + Module::Header H = {Path.str(), *File}; addHeader(Mod, H, Role); return true; } @@ -430,7 +430,10 @@ ModuleMap::findHeaderInUmbrellaDirs(const FileEntry *File, break; // Resolve the parent path to a directory entry. - Dir = SourceMgr.getFileManager().getDirectory(DirName); + if (auto DirEntry = SourceMgr.getFileManager().getDirectory(DirName)) + Dir = *DirEntry; + else + Dir = nullptr; } while (Dir); return {}; } @@ -755,7 +758,10 @@ ModuleMap::isHeaderUnavailableInModule(const FileEntry *Header, break; // Resolve the parent path to a directory entry. - Dir = SourceMgr.getFileManager().getDirectory(DirName); + if (auto DirEntry = SourceMgr.getFileManager().getDirectory(DirName)) + Dir = *DirEntry; + else + Dir = nullptr; } while (Dir); return false; @@ -938,24 +944,24 @@ Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir, if (llvm::sys::path::has_parent_path(FrameworkDirName)) { // Figure out the parent path. StringRef Parent = llvm::sys::path::parent_path(FrameworkDirName); - if (const DirectoryEntry *ParentDir = FileMgr.getDirectory(Parent)) { + if (auto ParentDir = FileMgr.getDirectory(Parent)) { // Check whether we have already looked into the parent directory // for a module map. llvm::DenseMap<const DirectoryEntry *, InferredDirectory>::const_iterator - inferred = InferredDirectories.find(ParentDir); + inferred = InferredDirectories.find(*ParentDir); if (inferred == InferredDirectories.end()) { // We haven't looked here before. Load a module map, if there is // one. bool IsFrameworkDir = Parent.endswith(".framework"); if (const FileEntry *ModMapFile = - HeaderInfo.lookupModuleMapFile(ParentDir, IsFrameworkDir)) { - parseModuleMapFile(ModMapFile, Attrs.IsSystem, ParentDir); - inferred = InferredDirectories.find(ParentDir); + HeaderInfo.lookupModuleMapFile(*ParentDir, IsFrameworkDir)) { + parseModuleMapFile(ModMapFile, Attrs.IsSystem, *ParentDir); + inferred = InferredDirectories.find(*ParentDir); } if (inferred == InferredDirectories.end()) inferred = InferredDirectories.insert( - std::make_pair(ParentDir, InferredDirectory())).first; + std::make_pair(*ParentDir, InferredDirectory())).first; } if (inferred->second.InferModules) { @@ -986,7 +992,7 @@ Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir, // Look for an umbrella header. SmallString<128> UmbrellaName = StringRef(FrameworkDir->getName()); llvm::sys::path::append(UmbrellaName, "Headers", ModuleName + ".h"); - const FileEntry *UmbrellaHeader = FileMgr.getFile(UmbrellaName); + auto UmbrellaHeader = FileMgr.getFile(UmbrellaName); // FIXME: If there's no umbrella header, we could probably scan the // framework to load *everything*. But, it's not clear that this is a good @@ -1016,7 +1022,7 @@ Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir, // // The "Headers/" component of the name is implied because this is // a framework module. - setUmbrellaHeader(Result, UmbrellaHeader, ModuleName + ".h"); + setUmbrellaHeader(Result, *UmbrellaHeader, ModuleName + ".h"); // export * Result->Exports.push_back(Module::ExportDecl(nullptr, true)); @@ -1039,13 +1045,14 @@ Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir, if (!StringRef(Dir->path()).endswith(".framework")) continue; - if (const DirectoryEntry *SubframeworkDir = + if (auto SubframeworkDir = FileMgr.getDirectory(Dir->path())) { // Note: as an egregious but useful hack, we use the real path here and // check whether it is actually a subdirectory of the parent directory. // This will not be the case if the 'subframework' is actually a symlink // out to a top-level framework. - StringRef SubframeworkDirName = FileMgr.getCanonicalName(SubframeworkDir); + StringRef SubframeworkDirName = + FileMgr.getCanonicalName(*SubframeworkDir); bool FoundParent = false; do { // Get the parent directory name. @@ -1054,9 +1061,11 @@ Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir, if (SubframeworkDirName.empty()) break; - if (FileMgr.getDirectory(SubframeworkDirName) == FrameworkDir) { - FoundParent = true; - break; + if (auto SubDir = FileMgr.getDirectory(SubframeworkDirName)) { + if (*SubDir == FrameworkDir) { + FoundParent = true; + break; + } } } while (true); @@ -1064,7 +1073,7 @@ Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir, continue; // FIXME: Do we want to warn about subframeworks without umbrella headers? - inferFrameworkModule(SubframeworkDir, Attrs, Result); + inferFrameworkModule(*SubframeworkDir, Attrs, Result); } } @@ -2130,12 +2139,12 @@ void ModuleMapParser::parseExternModuleDecl() { llvm::sys::path::append(ModuleMapFileName, FileName); FileNameRef = ModuleMapFileName; } - if (const FileEntry *File = SourceMgr.getFileManager().getFile(FileNameRef)) + if (auto File = SourceMgr.getFileManager().getFile(FileNameRef)) Map.parseModuleMapFile( - File, /*IsSystem=*/false, + *File, /*IsSystem=*/false, Map.HeaderInfo.getHeaderSearchOpts().ModuleMapFileHomeIsCwd ? Directory - : File->getDir(), + : (*File)->getDir(), FileID(), nullptr, ExternLoc); } @@ -2384,13 +2393,15 @@ void ModuleMapParser::parseUmbrellaDirDecl(SourceLocation UmbrellaLoc) { // Look for this file. const DirectoryEntry *Dir = nullptr; - if (llvm::sys::path::is_absolute(DirName)) - Dir = SourceMgr.getFileManager().getDirectory(DirName); - else { + if (llvm::sys::path::is_absolute(DirName)) { + if (auto D = SourceMgr.getFileManager().getDirectory(DirName)) + Dir = *D; + } else { SmallString<128> PathName; PathName = Directory->getName(); llvm::sys::path::append(PathName, DirName); - Dir = SourceMgr.getFileManager().getDirectory(PathName); + if (auto D = SourceMgr.getFileManager().getDirectory(PathName)) + Dir = *D; } if (!Dir) { @@ -2410,9 +2421,9 @@ void ModuleMapParser::parseUmbrellaDirDecl(SourceLocation UmbrellaLoc) { SourceMgr.getFileManager().getVirtualFileSystem(); for (llvm::vfs::recursive_directory_iterator I(FS, Dir->getName(), EC), E; I != E && !EC; I.increment(EC)) { - if (const FileEntry *FE = SourceMgr.getFileManager().getFile(I->path())) { + if (auto FE = SourceMgr.getFileManager().getFile(I->path())) { - Module::Header Header = {I->path(), FE}; + Module::Header Header = {I->path(), *FE}; Headers.push_back(std::move(Header)); } } diff --git a/lib/Lex/PPDirectives.cpp b/lib/Lex/PPDirectives.cpp index 2756042f23eb..3b7eaee3c914 100644 --- a/lib/Lex/PPDirectives.cpp +++ b/lib/Lex/PPDirectives.cpp @@ -33,6 +33,7 @@ #include "clang/Lex/Token.h" #include "clang/Lex/VariadicMacroSupport.h" #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/ScopeExit.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/STLExtras.h" @@ -369,6 +370,37 @@ SourceLocation Preprocessor::CheckEndOfDirective(const char *DirType, return DiscardUntilEndOfDirective().getEnd(); } +Optional<unsigned> Preprocessor::getSkippedRangeForExcludedConditionalBlock( + SourceLocation HashLoc) { + if (!ExcludedConditionalDirectiveSkipMappings) + return None; + if (!HashLoc.isFileID()) + return None; + + std::pair<FileID, unsigned> HashFileOffset = + SourceMgr.getDecomposedLoc(HashLoc); + const llvm::MemoryBuffer *Buf = SourceMgr.getBuffer(HashFileOffset.first); + auto It = ExcludedConditionalDirectiveSkipMappings->find(Buf); + if (It == ExcludedConditionalDirectiveSkipMappings->end()) + return None; + + const PreprocessorSkippedRangeMapping &SkippedRanges = *It->getSecond(); + // Check if the offset of '#' is mapped in the skipped ranges. + auto MappingIt = SkippedRanges.find(HashFileOffset.second); + if (MappingIt == SkippedRanges.end()) + return None; + + unsigned BytesToSkip = MappingIt->getSecond(); + unsigned CurLexerBufferOffset = CurLexer->getCurrentBufferOffset(); + assert(CurLexerBufferOffset >= HashFileOffset.second && + "lexer is before the hash?"); + // Take into account the fact that the lexer has already advanced, so the + // number of bytes to skip must be adjusted. + unsigned LengthDiff = CurLexerBufferOffset - HashFileOffset.second; + assert(BytesToSkip >= LengthDiff && "lexer is after the skipped range?"); + return BytesToSkip - LengthDiff; +} + /// SkipExcludedConditionalBlock - We just read a \#if or related directive and /// decided that the subsequent tokens are in the \#if'd out portion of the /// file. Lex the rest of the file, until we see an \#endif. If @@ -395,6 +427,11 @@ void Preprocessor::SkipExcludedConditionalBlock(SourceLocation HashTokenLoc, // disabling warnings, etc. CurPPLexer->LexingRawMode = true; Token Tok; + if (auto SkipLength = + getSkippedRangeForExcludedConditionalBlock(HashTokenLoc)) { + // Skip to the next '#endif' / '#else' / '#elif'. + CurLexer->skipOver(*SkipLength); + } while (true) { CurLexer->Lex(Tok); @@ -678,7 +715,7 @@ Preprocessor::getModuleHeaderToIncludeForDiagnostics(SourceLocation IncLoc, return nullptr; } -const FileEntry *Preprocessor::LookupFile( +Optional<FileEntryRef> Preprocessor::LookupFile( SourceLocation FilenameLoc, StringRef Filename, bool isAngled, const DirectoryLookup *FromDir, const FileEntry *FromFile, const DirectoryLookup *&CurDir, SmallVectorImpl<char> *SearchPath, @@ -715,7 +752,7 @@ const FileEntry *Preprocessor::LookupFile( BuildSystemModule = getCurrentModule()->IsSystem; } else if ((FileEnt = SourceMgr.getFileEntryForID(SourceMgr.getMainFileID()))) - Includers.push_back(std::make_pair(FileEnt, FileMgr.getDirectory("."))); + Includers.push_back(std::make_pair(FileEnt, *FileMgr.getDirectory("."))); } else { Includers.push_back(std::make_pair(FileEnt, FileEnt->getDir())); } @@ -739,7 +776,7 @@ const FileEntry *Preprocessor::LookupFile( // the include path until we find that file or run out of files. const DirectoryLookup *TmpCurDir = CurDir; const DirectoryLookup *TmpFromDir = nullptr; - while (const FileEntry *FE = HeaderInfo.LookupFile( + while (Optional<FileEntryRef> FE = HeaderInfo.LookupFile( Filename, FilenameLoc, isAngled, TmpFromDir, TmpCurDir, Includers, SearchPath, RelativePath, RequestingModule, SuggestedModule, /*IsMapped=*/nullptr, @@ -747,7 +784,7 @@ const FileEntry *Preprocessor::LookupFile( // Keep looking as if this file did a #include_next. TmpFromDir = TmpCurDir; ++TmpFromDir; - if (FE == FromFile) { + if (&FE->getFileEntry() == FromFile) { // Found it. FromDir = TmpFromDir; CurDir = TmpCurDir; @@ -757,7 +794,7 @@ const FileEntry *Preprocessor::LookupFile( } // Do a standard file entry lookup. - const FileEntry *FE = HeaderInfo.LookupFile( + Optional<FileEntryRef> FE = HeaderInfo.LookupFile( Filename, FilenameLoc, isAngled, FromDir, CurDir, Includers, SearchPath, RelativePath, RequestingModule, SuggestedModule, IsMapped, IsFrameworkFound, SkipCache, BuildSystemModule); @@ -765,7 +802,7 @@ const FileEntry *Preprocessor::LookupFile( if (SuggestedModule && !LangOpts.AsmPreprocessor) HeaderInfo.getModuleMap().diagnoseHeaderInclusion( RequestingModule, RequestingModuleIsModuleInterface, FilenameLoc, - Filename, FE); + Filename, &FE->getFileEntry()); return FE; } @@ -775,14 +812,13 @@ const FileEntry *Preprocessor::LookupFile( // headers on the #include stack and pass them to HeaderInfo. if (IsFileLexer()) { if ((CurFileEnt = CurPPLexer->getFileEntry())) { - if ((FE = HeaderInfo.LookupSubframeworkHeader(Filename, CurFileEnt, - SearchPath, RelativePath, - RequestingModule, - SuggestedModule))) { + if (Optional<FileEntryRef> FE = HeaderInfo.LookupSubframeworkHeader( + Filename, CurFileEnt, SearchPath, RelativePath, RequestingModule, + SuggestedModule)) { if (SuggestedModule && !LangOpts.AsmPreprocessor) HeaderInfo.getModuleMap().diagnoseHeaderInclusion( RequestingModule, RequestingModuleIsModuleInterface, FilenameLoc, - Filename, FE); + Filename, &FE->getFileEntry()); return FE; } } @@ -791,13 +827,13 @@ const FileEntry *Preprocessor::LookupFile( for (IncludeStackInfo &ISEntry : llvm::reverse(IncludeMacroStack)) { if (IsFileLexer(ISEntry)) { if ((CurFileEnt = ISEntry.ThePPLexer->getFileEntry())) { - if ((FE = HeaderInfo.LookupSubframeworkHeader( + if (Optional<FileEntryRef> FE = HeaderInfo.LookupSubframeworkHeader( Filename, CurFileEnt, SearchPath, RelativePath, - RequestingModule, SuggestedModule))) { + RequestingModule, SuggestedModule)) { if (SuggestedModule && !LangOpts.AsmPreprocessor) HeaderInfo.getModuleMap().diagnoseHeaderInclusion( RequestingModule, RequestingModuleIsModuleInterface, - FilenameLoc, Filename, FE); + FilenameLoc, Filename, &FE->getFileEntry()); return FE; } } @@ -805,7 +841,7 @@ const FileEntry *Preprocessor::LookupFile( } // Otherwise, we really couldn't find the file. - return nullptr; + return None; } //===----------------------------------------------------------------------===// @@ -1022,7 +1058,7 @@ void Preprocessor::HandleDirective(Token &Result) { // various pseudo-ops. Just return the # token and push back the following // token to be lexed next time. if (getLangOpts().AsmPreprocessor) { - auto Toks = llvm::make_unique<Token[]>(2); + auto Toks = std::make_unique<Token[]>(2); // Return the # and the token after it. Toks[0] = SavedHash; Toks[1] = Result; @@ -1512,7 +1548,7 @@ void Preprocessor::EnterAnnotationToken(SourceRange Range, void *AnnotationVal) { // FIXME: Produce this as the current token directly, rather than // allocating a new token for it. - auto Tok = llvm::make_unique<Token[]>(1); + auto Tok = std::make_unique<Token[]>(1); Tok[0].startToken(); Tok[0].setKind(Kind); Tok[0].setLocation(Range.getBegin()); @@ -1675,6 +1711,133 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc, } } +Optional<FileEntryRef> Preprocessor::LookupHeaderIncludeOrImport( + const DirectoryLookup *&CurDir, StringRef Filename, + SourceLocation FilenameLoc, CharSourceRange FilenameRange, + const Token &FilenameTok, bool &IsFrameworkFound, bool IsImportDecl, + bool &IsMapped, const DirectoryLookup *LookupFrom, + const FileEntry *LookupFromFile, StringRef LookupFilename, + SmallVectorImpl<char> &RelativePath, SmallVectorImpl<char> &SearchPath, + ModuleMap::KnownHeader &SuggestedModule, bool isAngled) { + Optional<FileEntryRef> File = LookupFile( + FilenameLoc, LookupFilename, + isAngled, LookupFrom, LookupFromFile, CurDir, + Callbacks ? &SearchPath : nullptr, Callbacks ? &RelativePath : nullptr, + &SuggestedModule, &IsMapped, &IsFrameworkFound); + if (File) + return File; + + if (Callbacks) { + // Give the clients a chance to recover. + SmallString<128> RecoveryPath; + if (Callbacks->FileNotFound(Filename, RecoveryPath)) { + if (auto DE = FileMgr.getOptionalDirectoryRef(RecoveryPath)) { + // Add the recovery path to the list of search paths. + DirectoryLookup DL(*DE, SrcMgr::C_User, false); + HeaderInfo.AddSearchPath(DL, isAngled); + + // Try the lookup again, skipping the cache. + Optional<FileEntryRef> File = LookupFile( + FilenameLoc, + LookupFilename, isAngled, + LookupFrom, LookupFromFile, CurDir, nullptr, nullptr, + &SuggestedModule, &IsMapped, /*IsFrameworkFound=*/nullptr, + /*SkipCache*/ true); + if (File) + return File; + } + } + } + + if (SuppressIncludeNotFoundError) + return None; + + // If the file could not be located and it was included via angle + // brackets, we can attempt a lookup as though it were a quoted path to + // provide the user with a possible fixit. + if (isAngled) { + Optional<FileEntryRef> File = LookupFile( + FilenameLoc, LookupFilename, + false, LookupFrom, LookupFromFile, CurDir, + Callbacks ? &SearchPath : nullptr, Callbacks ? &RelativePath : nullptr, + &SuggestedModule, &IsMapped, + /*IsFrameworkFound=*/nullptr); + if (File) { + Diag(FilenameTok, diag::err_pp_file_not_found_angled_include_not_fatal) + << Filename << IsImportDecl + << FixItHint::CreateReplacement(FilenameRange, + "\"" + Filename.str() + "\""); + return File; + } + } + + // Check for likely typos due to leading or trailing non-isAlphanumeric + // characters + StringRef OriginalFilename = Filename; + if (LangOpts.SpellChecking) { + // A heuristic to correct a typo file name by removing leading and + // trailing non-isAlphanumeric characters. + auto CorrectTypoFilename = [](llvm::StringRef Filename) { + Filename = Filename.drop_until(isAlphanumeric); + while (!Filename.empty() && !isAlphanumeric(Filename.back())) { + Filename = Filename.drop_back(); + } + return Filename; + }; + StringRef TypoCorrectionName = CorrectTypoFilename(Filename); + +#ifndef _WIN32 + // Normalize slashes when compiling with -fms-extensions on non-Windows. + // This is unnecessary on Windows since the filesystem there handles + // backslashes. + SmallString<128> NormalizedTypoCorrectionPath; + if (LangOpts.MicrosoftExt) { + NormalizedTypoCorrectionPath = TypoCorrectionName; + llvm::sys::path::native(NormalizedTypoCorrectionPath); + TypoCorrectionName = NormalizedTypoCorrectionPath; + } +#endif + + Optional<FileEntryRef> File = LookupFile( + FilenameLoc, TypoCorrectionName, isAngled, LookupFrom, LookupFromFile, + CurDir, Callbacks ? &SearchPath : nullptr, + Callbacks ? &RelativePath : nullptr, &SuggestedModule, &IsMapped, + /*IsFrameworkFound=*/nullptr); + if (File) { + auto Hint = + isAngled ? FixItHint::CreateReplacement( + FilenameRange, "<" + TypoCorrectionName.str() + ">") + : FixItHint::CreateReplacement( + FilenameRange, "\"" + TypoCorrectionName.str() + "\""); + Diag(FilenameTok, diag::err_pp_file_not_found_typo_not_fatal) + << OriginalFilename << TypoCorrectionName << Hint; + // We found the file, so set the Filename to the name after typo + // correction. + Filename = TypoCorrectionName; + return File; + } + } + + // If the file is still not found, just go with the vanilla diagnostic + assert(!File.hasValue() && "expected missing file"); + Diag(FilenameTok, diag::err_pp_file_not_found) + << OriginalFilename << FilenameRange; + if (IsFrameworkFound) { + size_t SlashPos = OriginalFilename.find('/'); + assert(SlashPos != StringRef::npos && + "Include with framework name should have '/' in the filename"); + StringRef FrameworkName = OriginalFilename.substr(0, SlashPos); + FrameworkCacheEntry &CacheEntry = + HeaderInfo.LookupFrameworkCache(FrameworkName); + assert(CacheEntry.Directory && "Found framework should be in cache"); + Diag(FilenameTok, diag::note_pp_framework_without_header) + << OriginalFilename.substr(SlashPos + 1) << FrameworkName + << CacheEntry.Directory->getName(); + } + + return None; +} + /// Handle either a #include-like directive or an import declaration that names /// a header file. /// @@ -1710,12 +1873,12 @@ Preprocessor::ImportAction Preprocessor::HandleHeaderIncludeOrImport( SourceLocation StartLoc = IsImportDecl ? IncludeTok.getLocation() : HashLoc; // Complain about attempts to #include files in an audit pragma. - if (PragmaARCCFCodeAuditedLoc.isValid()) { + if (PragmaARCCFCodeAuditedInfo.second.isValid()) { Diag(StartLoc, diag::err_pp_include_in_arc_cf_code_audited) << IsImportDecl; - Diag(PragmaARCCFCodeAuditedLoc, diag::note_pragma_entered_here); + Diag(PragmaARCCFCodeAuditedInfo.second, diag::note_pragma_entered_here); // Immediately leave the pragma. - PragmaARCCFCodeAuditedLoc = SourceLocation(); + PragmaARCCFCodeAuditedInfo = {nullptr, SourceLocation()}; } // Complain about attempts to #include files in an assume-nonnull pragma. @@ -1746,127 +1909,26 @@ Preprocessor::ImportAction Preprocessor::HandleHeaderIncludeOrImport( // the path. ModuleMap::KnownHeader SuggestedModule; SourceLocation FilenameLoc = FilenameTok.getLocation(); + StringRef LookupFilename = Filename; + +#ifndef _WIN32 + // Normalize slashes when compiling with -fms-extensions on non-Windows. This + // is unnecessary on Windows since the filesystem there handles backslashes. SmallString<128> NormalizedPath; - if (LangOpts.MSVCCompat) { + if (LangOpts.MicrosoftExt) { NormalizedPath = Filename.str(); -#ifndef _WIN32 llvm::sys::path::native(NormalizedPath); -#endif + LookupFilename = NormalizedPath; } - const FileEntry *File = LookupFile( - FilenameLoc, LangOpts.MSVCCompat ? NormalizedPath.c_str() : Filename, - isAngled, LookupFrom, LookupFromFile, CurDir, - Callbacks ? &SearchPath : nullptr, Callbacks ? &RelativePath : nullptr, - &SuggestedModule, &IsMapped, &IsFrameworkFound); - - if (!File) { - if (Callbacks) { - // Give the clients a chance to recover. - SmallString<128> RecoveryPath; - if (Callbacks->FileNotFound(Filename, RecoveryPath)) { - if (const DirectoryEntry *DE = FileMgr.getDirectory(RecoveryPath)) { - // Add the recovery path to the list of search paths. - DirectoryLookup DL(DE, SrcMgr::C_User, false); - HeaderInfo.AddSearchPath(DL, isAngled); - - // Try the lookup again, skipping the cache. - File = LookupFile( - FilenameLoc, - LangOpts.MSVCCompat ? NormalizedPath.c_str() : Filename, isAngled, - LookupFrom, LookupFromFile, CurDir, nullptr, nullptr, - &SuggestedModule, &IsMapped, /*IsFrameworkFound=*/nullptr, - /*SkipCache*/ true); - } - } - } - - if (!SuppressIncludeNotFoundError) { - // If the file could not be located and it was included via angle - // brackets, we can attempt a lookup as though it were a quoted path to - // provide the user with a possible fixit. - if (isAngled) { - File = LookupFile( - FilenameLoc, - LangOpts.MSVCCompat ? NormalizedPath.c_str() : Filename, false, - LookupFrom, LookupFromFile, CurDir, - Callbacks ? &SearchPath : nullptr, - Callbacks ? &RelativePath : nullptr, &SuggestedModule, &IsMapped, - /*IsFrameworkFound=*/nullptr); - if (File) { - Diag(FilenameTok, - diag::err_pp_file_not_found_angled_include_not_fatal) - << Filename << IsImportDecl - << FixItHint::CreateReplacement(FilenameRange, - "\"" + Filename.str() + "\""); - } - } - - // Check for likely typos due to leading or trailing non-isAlphanumeric - // characters - StringRef OriginalFilename = Filename; - if (LangOpts.SpellChecking && !File) { - // A heuristic to correct a typo file name by removing leading and - // trailing non-isAlphanumeric characters. - auto CorrectTypoFilename = [](llvm::StringRef Filename) { - Filename = Filename.drop_until(isAlphanumeric); - while (!Filename.empty() && !isAlphanumeric(Filename.back())) { - Filename = Filename.drop_back(); - } - return Filename; - }; - StringRef TypoCorrectionName = CorrectTypoFilename(Filename); - SmallString<128> NormalizedTypoCorrectionPath; - if (LangOpts.MSVCCompat) { - NormalizedTypoCorrectionPath = TypoCorrectionName.str(); -#ifndef _WIN32 - llvm::sys::path::native(NormalizedTypoCorrectionPath); #endif - } - File = LookupFile( - FilenameLoc, - LangOpts.MSVCCompat ? NormalizedTypoCorrectionPath.c_str() - : TypoCorrectionName, - isAngled, LookupFrom, LookupFromFile, CurDir, - Callbacks ? &SearchPath : nullptr, - Callbacks ? &RelativePath : nullptr, &SuggestedModule, &IsMapped, - /*IsFrameworkFound=*/nullptr); - if (File) { - auto Hint = - isAngled - ? FixItHint::CreateReplacement( - FilenameRange, "<" + TypoCorrectionName.str() + ">") - : FixItHint::CreateReplacement( - FilenameRange, "\"" + TypoCorrectionName.str() + "\""); - Diag(FilenameTok, diag::err_pp_file_not_found_typo_not_fatal) - << OriginalFilename << TypoCorrectionName << Hint; - // We found the file, so set the Filename to the name after typo - // correction. - Filename = TypoCorrectionName; - } - } - // If the file is still not found, just go with the vanilla diagnostic - if (!File) { - Diag(FilenameTok, diag::err_pp_file_not_found) << OriginalFilename - << FilenameRange; - if (IsFrameworkFound) { - size_t SlashPos = OriginalFilename.find('/'); - assert(SlashPos != StringRef::npos && - "Include with framework name should have '/' in the filename"); - StringRef FrameworkName = OriginalFilename.substr(0, SlashPos); - FrameworkCacheEntry &CacheEntry = - HeaderInfo.LookupFrameworkCache(FrameworkName); - assert(CacheEntry.Directory && "Found framework should be in cache"); - Diag(FilenameTok, diag::note_pp_framework_without_header) - << OriginalFilename.substr(SlashPos + 1) << FrameworkName - << CacheEntry.Directory->getName(); - } - } - } - } + Optional<FileEntryRef> File = LookupHeaderIncludeOrImport( + CurDir, Filename, FilenameLoc, FilenameRange, FilenameTok, + IsFrameworkFound, IsImportDecl, IsMapped, LookupFrom, LookupFromFile, + LookupFilename, RelativePath, SearchPath, SuggestedModule, isAngled); if (usingPCHWithThroughHeader() && SkippingUntilPCHThroughHeader) { - if (isPCHThroughHeader(File)) + if (File && isPCHThroughHeader(&File->getFileEntry())) SkippingUntilPCHThroughHeader = false; return {ImportAction::None}; } @@ -1877,7 +1939,8 @@ Preprocessor::ImportAction Preprocessor::HandleHeaderIncludeOrImport( // some directives (e.g. #endif of a header guard) will never be seen. // Since this will lead to confusing errors, avoid the inclusion. if (File && PreambleConditionalStack.isRecording() && - SourceMgr.translateFile(File) == SourceMgr.getMainFileID()) { + SourceMgr.translateFile(&File->getFileEntry()) == + SourceMgr.getMainFileID()) { Diag(FilenameTok.getLocation(), diag::err_pp_including_mainfile_in_preamble); return {ImportAction::None}; @@ -1896,7 +1959,7 @@ Preprocessor::ImportAction Preprocessor::HandleHeaderIncludeOrImport( // include cycle. Don't enter already processed files again as it can lead to // reaching the max allowed include depth again. if (Action == Enter && HasReachedMaxIncludeDepth && File && - HeaderInfo.getFileInfo(File).NumIncludes) + HeaderInfo.getFileInfo(&File->getFileEntry()).NumIncludes) Action = IncludeLimitReached; // Determine whether we should try to import the module for this #include, if @@ -1972,7 +2035,8 @@ Preprocessor::ImportAction Preprocessor::HandleHeaderIncludeOrImport( SrcMgr::CharacteristicKind FileCharacter = SourceMgr.getFileCharacteristic(FilenameTok.getLocation()); if (File) - FileCharacter = std::max(HeaderInfo.getFileDirFlavor(File), FileCharacter); + FileCharacter = std::max(HeaderInfo.getFileDirFlavor(&File->getFileEntry()), + FileCharacter); // If this is a '#import' or an import-declaration, don't re-enter the file. // @@ -1986,8 +2050,8 @@ Preprocessor::ImportAction Preprocessor::HandleHeaderIncludeOrImport( // Ask HeaderInfo if we should enter this #include file. If not, #including // this file will have no effect. if (Action == Enter && File && - !HeaderInfo.ShouldEnterIncludeFile(*this, File, EnterOnce, - getLangOpts().Modules, + !HeaderInfo.ShouldEnterIncludeFile(*this, &File->getFileEntry(), + EnterOnce, getLangOpts().Modules, SuggestedModule.getModule())) { // Even if we've already preprocessed this header once and know that we // don't need to see its contents again, we still need to import it if it's @@ -2003,12 +2067,11 @@ Preprocessor::ImportAction Preprocessor::HandleHeaderIncludeOrImport( // Notify the callback object that we've seen an inclusion directive. // FIXME: Use a different callback for a pp-import? Callbacks->InclusionDirective( - HashLoc, IncludeTok, - LangOpts.MSVCCompat ? NormalizedPath.c_str() : Filename, isAngled, - FilenameRange, File, SearchPath, RelativePath, + HashLoc, IncludeTok, LookupFilename, isAngled, FilenameRange, + File ? &File->getFileEntry() : nullptr, SearchPath, RelativePath, Action == Import ? SuggestedModule.getModule() : nullptr, FileCharacter); - if (Action == Skip) + if (Action == Skip && File) Callbacks->FileSkipped(*File, FilenameTok, FileCharacter); } @@ -2026,11 +2089,11 @@ Preprocessor::ImportAction Preprocessor::HandleHeaderIncludeOrImport( // Issue a diagnostic if the name of the file on disk has a different case // than the one we're about to open. const bool CheckIncludePathPortability = - !IsMapped && File && !File->tryGetRealPathName().empty(); + !IsMapped && !File->getFileEntry().tryGetRealPathName().empty(); if (CheckIncludePathPortability) { - StringRef Name = LangOpts.MSVCCompat ? NormalizedPath.str() : Filename; - StringRef RealPathName = File->tryGetRealPathName(); + StringRef Name = LookupFilename; + StringRef RealPathName = File->getFileEntry().tryGetRealPathName(); SmallVector<StringRef, 16> Components(llvm::sys::path::begin(Name), llvm::sys::path::end(Name)); @@ -2101,7 +2164,7 @@ Preprocessor::ImportAction Preprocessor::HandleHeaderIncludeOrImport( // position on the file where it will be included and after the expansions. if (IncludePos.isMacroID()) IncludePos = SourceMgr.getExpansionRange(IncludePos).getEnd(); - FileID FID = SourceMgr.createFileID(File, IncludePos, FileCharacter); + FileID FID = SourceMgr.createFileID(*File, IncludePos, FileCharacter); assert(FID.isValid() && "Expected valid file ID"); // If all is good, enter the new file! @@ -2399,6 +2462,13 @@ MacroInfo *Preprocessor::ReadOptionalMacroParameterListAndBody( Token Tok; LexUnexpandedToken(Tok); + // Ensure we consume the rest of the macro body if errors occur. + auto _ = llvm::make_scope_exit([&]() { + // The flag indicates if we are still waiting for 'eod'. + if (CurLexer->ParsingPreprocessorDirective) + DiscardUntilEndOfDirective(); + }); + // Used to un-poison and then re-poison identifiers of the __VA_ARGS__ ilk // within their appropriate context. VariadicMacroScopeGuard VariadicMacroScopeGuard(*this); @@ -2420,12 +2490,8 @@ MacroInfo *Preprocessor::ReadOptionalMacroParameterListAndBody( } else if (Tok.is(tok::l_paren)) { // This is a function-like macro definition. Read the argument list. MI->setIsFunctionLike(); - if (ReadMacroParameterList(MI, LastTok)) { - // Throw away the rest of the line. - if (CurPPLexer->ParsingPreprocessorDirective) - DiscardUntilEndOfDirective(); + if (ReadMacroParameterList(MI, LastTok)) return nullptr; - } // If this is a definition of an ISO C/C++ variadic function-like macro (not // using the GNU named varargs extension) inform our variadic scope guard @@ -2723,7 +2789,8 @@ void Preprocessor::HandleDefineDirective( // If we need warning for not using the macro, add its location in the // warn-because-unused-macro set. If it gets used it will be removed from set. if (getSourceManager().isInMainFile(MI->getDefinitionLoc()) && - !Diags->isIgnored(diag::pp_macro_not_used, MI->getDefinitionLoc())) { + !Diags->isIgnored(diag::pp_macro_not_used, MI->getDefinitionLoc()) && + !MacroExpansionInDirectivesOverride) { MI->setIsWarnIfUnused(true); WarnUnusedMacroLocs.insert(MI->getDefinitionLoc()); } @@ -2832,6 +2899,9 @@ void Preprocessor::HandleIfdefDirective(Token &Result, Callbacks->Ifdef(DirectiveTok.getLocation(), MacroNameTok, MD); } + bool RetainExcludedCB = PPOpts->RetainExcludedConditionalBlocks && + getSourceManager().isInMainFile(DirectiveTok.getLocation()); + // Should we include the stuff contained by this directive? if (PPOpts->SingleFileParseMode && !MI) { // In 'single-file-parse mode' undefined identifiers trigger parsing of all @@ -2839,7 +2909,7 @@ void Preprocessor::HandleIfdefDirective(Token &Result, CurPPLexer->pushConditionalLevel(DirectiveTok.getLocation(), /*wasskip*/false, /*foundnonskip*/false, /*foundelse*/false); - } else if (!MI == isIfndef) { + } else if (!MI == isIfndef || RetainExcludedCB) { // Yes, remember that we are inside a conditional, then lex the next token. CurPPLexer->pushConditionalLevel(DirectiveTok.getLocation(), /*wasskip*/false, /*foundnonskip*/true, @@ -2880,13 +2950,16 @@ void Preprocessor::HandleIfDirective(Token &IfToken, IfToken.getLocation(), DER.ExprRange, (ConditionalTrue ? PPCallbacks::CVK_True : PPCallbacks::CVK_False)); + bool RetainExcludedCB = PPOpts->RetainExcludedConditionalBlocks && + getSourceManager().isInMainFile(IfToken.getLocation()); + // Should we include the stuff contained by this directive? if (PPOpts->SingleFileParseMode && DER.IncludedUndefinedIds) { // In 'single-file-parse mode' undefined identifiers trigger parsing of all // the directive blocks. CurPPLexer->pushConditionalLevel(IfToken.getLocation(), /*wasskip*/false, /*foundnonskip*/false, /*foundelse*/false); - } else if (ConditionalTrue) { + } else if (ConditionalTrue || RetainExcludedCB) { // Yes, remember that we are inside a conditional, then lex the next token. CurPPLexer->pushConditionalLevel(IfToken.getLocation(), /*wasskip*/false, /*foundnonskip*/true, /*foundelse*/false); @@ -2948,7 +3021,10 @@ void Preprocessor::HandleElseDirective(Token &Result, const Token &HashToken) { if (Callbacks) Callbacks->Else(Result.getLocation(), CI.IfLoc); - if (PPOpts->SingleFileParseMode && !CI.FoundNonSkip) { + bool RetainExcludedCB = PPOpts->RetainExcludedConditionalBlocks && + getSourceManager().isInMainFile(Result.getLocation()); + + if ((PPOpts->SingleFileParseMode && !CI.FoundNonSkip) || RetainExcludedCB) { // In 'single-file-parse mode' undefined identifiers trigger parsing of all // the directive blocks. CurPPLexer->pushConditionalLevel(CI.IfLoc, /*wasskip*/false, @@ -2990,7 +3066,10 @@ void Preprocessor::HandleElifDirective(Token &ElifToken, Callbacks->Elif(ElifToken.getLocation(), ConditionRange, PPCallbacks::CVK_NotEvaluated, CI.IfLoc); - if (PPOpts->SingleFileParseMode && !CI.FoundNonSkip) { + bool RetainExcludedCB = PPOpts->RetainExcludedConditionalBlocks && + getSourceManager().isInMainFile(ElifToken.getLocation()); + + if ((PPOpts->SingleFileParseMode && !CI.FoundNonSkip) || RetainExcludedCB) { // In 'single-file-parse mode' undefined identifiers trigger parsing of all // the directive blocks. CurPPLexer->pushConditionalLevel(ElifToken.getLocation(), /*wasskip*/false, diff --git a/lib/Lex/PPLexerChange.cpp b/lib/Lex/PPLexerChange.cpp index 7cce5f9c9fe4..802172693960 100644 --- a/lib/Lex/PPLexerChange.cpp +++ b/lib/Lex/PPLexerChange.cpp @@ -128,7 +128,7 @@ void Preprocessor::EnterMacro(Token &Tok, SourceLocation ILEnd, MacroInfo *Macro, MacroArgs *Args) { std::unique_ptr<TokenLexer> TokLexer; if (NumCachedTokenLexers == 0) { - TokLexer = llvm::make_unique<TokenLexer>(Tok, ILEnd, Macro, Args, *this); + TokLexer = std::make_unique<TokenLexer>(Tok, ILEnd, Macro, Args, *this); } else { TokLexer = std::move(TokenLexerCache[--NumCachedTokenLexers]); TokLexer->Init(Tok, ILEnd, Macro, Args); @@ -180,7 +180,7 @@ void Preprocessor::EnterTokenStream(const Token *Toks, unsigned NumToks, // Create a macro expander to expand from the specified token stream. std::unique_ptr<TokenLexer> TokLexer; if (NumCachedTokenLexers == 0) { - TokLexer = llvm::make_unique<TokenLexer>( + TokLexer = std::make_unique<TokenLexer>( Toks, NumToks, DisableMacroExpansion, OwnsTokens, IsReinject, *this); } else { TokLexer = std::move(TokenLexerCache[--NumCachedTokenLexers]); @@ -206,8 +206,8 @@ static void computeRelativePath(FileManager &FM, const DirectoryEntry *Dir, StringRef FilePath = File->getDir()->getName(); StringRef Path = FilePath; while (!Path.empty()) { - if (const DirectoryEntry *CurDir = FM.getDirectory(Path)) { - if (CurDir == Dir) { + if (auto CurDir = FM.getDirectory(Path)) { + if (*CurDir == Dir) { Result = FilePath.substr(Path.size()); llvm::sys::path::append(Result, llvm::sys::path::filename(File->getName())); @@ -287,12 +287,12 @@ void Preprocessor::diagnoseMissingHeaderInUmbrellaDir(const Module &Mod) { .Default(false)) continue; - if (const FileEntry *Header = getFileManager().getFile(Entry->path())) - if (!getSourceManager().hasFileInfo(Header)) { - if (!ModMap.isHeaderInUnavailableModule(Header)) { + if (auto Header = getFileManager().getFile(Entry->path())) + if (!getSourceManager().hasFileInfo(*Header)) { + if (!ModMap.isHeaderInUnavailableModule(*Header)) { // Find the relative path that would access this header. SmallString<128> RelativePath; - computeRelativePath(FileMgr, Dir, Header, RelativePath); + computeRelativePath(FileMgr, Dir, *Header, RelativePath); Diag(StartLoc, diag::warn_uncovered_module_header) << Mod.getFullModuleName() << RelativePath; } @@ -376,12 +376,13 @@ bool Preprocessor::HandleEndOfFile(Token &Result, bool isEndOfMacro) { // Complain about reaching a true EOF within arc_cf_code_audited. // We don't want to complain about reaching the end of a macro // instantiation or a _Pragma. - if (PragmaARCCFCodeAuditedLoc.isValid() && - !isEndOfMacro && !(CurLexer && CurLexer->Is_PragmaLexer)) { - Diag(PragmaARCCFCodeAuditedLoc, diag::err_pp_eof_in_arc_cf_code_audited); + if (PragmaARCCFCodeAuditedInfo.second.isValid() && !isEndOfMacro && + !(CurLexer && CurLexer->Is_PragmaLexer)) { + Diag(PragmaARCCFCodeAuditedInfo.second, + diag::err_pp_eof_in_arc_cf_code_audited); // Recover by leaving immediately. - PragmaARCCFCodeAuditedLoc = SourceLocation(); + PragmaARCCFCodeAuditedInfo = {nullptr, SourceLocation()}; } // Complain about reaching a true EOF within assume_nonnull. diff --git a/lib/Lex/PPMacroExpansion.cpp b/lib/Lex/PPMacroExpansion.cpp index 687b9a9d3b7b..dfbcaedcacff 100644 --- a/lib/Lex/PPMacroExpansion.cpp +++ b/lib/Lex/PPMacroExpansion.cpp @@ -804,7 +804,7 @@ MacroArgs *Preprocessor::ReadMacroCallArgumentList(Token &MacroName, return nullptr; } // Do not lose the EOF/EOD. - auto Toks = llvm::make_unique<Token[]>(1); + auto Toks = std::make_unique<Token[]>(1); Toks[0] = Tok; EnterTokenStream(std::move(Toks), 1, true, /*IsReinject*/ false); break; @@ -1210,19 +1210,20 @@ static bool EvaluateHasIncludeCommon(Token &Tok, // Search include directories. const DirectoryLookup *CurDir; - const FileEntry *File = + Optional<FileEntryRef> File = PP.LookupFile(FilenameLoc, Filename, isAngled, LookupFrom, LookupFromFile, CurDir, nullptr, nullptr, nullptr, nullptr, nullptr); if (PPCallbacks *Callbacks = PP.getPPCallbacks()) { SrcMgr::CharacteristicKind FileType = SrcMgr::C_User; if (File) - FileType = PP.getHeaderSearchInfo().getFileDirFlavor(File); + FileType = + PP.getHeaderSearchInfo().getFileDirFlavor(&File->getFileEntry()); Callbacks->HasInclude(FilenameLoc, Filename, isAngled, File, FileType); } // Get the result value. A result of true means the file exists. - return File != nullptr; + return File.hasValue(); } /// EvaluateHasInclude - Process a '__has_include("path")' expression. @@ -1617,21 +1618,38 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) { return true; } return true; + } else if (II->getTokenID() != tok::identifier || + II->hasRevertedTokenIDToIdentifier()) { + // Treat all keywords that introduce a custom syntax of the form + // + // '__some_keyword' '(' [...] ')' + // + // as being "builtin functions", even if the syntax isn't a valid + // function call (for example, because the builtin takes a type + // argument). + if (II->getName().startswith("__builtin_") || + II->getName().startswith("__is_") || + II->getName().startswith("__has_")) + return true; + return llvm::StringSwitch<bool>(II->getName()) + .Case("__array_rank", true) + .Case("__array_extent", true) + .Case("__reference_binds_to_temporary", true) + .Case("__underlying_type", true) + .Default(false); } else { return llvm::StringSwitch<bool>(II->getName()) - .Case("__make_integer_seq", LangOpts.CPlusPlus) - .Case("__type_pack_element", LangOpts.CPlusPlus) - .Case("__builtin_available", true) - .Case("__is_target_arch", true) - .Case("__is_target_vendor", true) - .Case("__is_target_os", true) - .Case("__is_target_environment", true) - .Case("__builtin_LINE", true) - .Case("__builtin_FILE", true) - .Case("__builtin_FUNCTION", true) - .Case("__builtin_COLUMN", true) - .Case("__builtin_bit_cast", true) - .Default(false); + // Report builtin templates as being builtins. + .Case("__make_integer_seq", LangOpts.CPlusPlus) + .Case("__type_pack_element", LangOpts.CPlusPlus) + // Likewise for some builtin preprocessor macros. + // FIXME: This is inconsistent; we usually suggest detecting + // builtin macros via #ifdef. Don't add more cases here. + .Case("__is_target_arch", true) + .Case("__is_target_vendor", true) + .Case("__is_target_os", true) + .Case("__is_target_environment", true) + .Default(false); } }); } else if (II == Ident__is_identifier) { diff --git a/lib/Lex/Pragma.cpp b/lib/Lex/Pragma.cpp index 4e4db668551f..79953804b5d3 100644 --- a/lib/Lex/Pragma.cpp +++ b/lib/Lex/Pragma.cpp @@ -121,6 +121,40 @@ void PragmaNamespace::HandlePragma(Preprocessor &PP, // Preprocessor Pragma Directive Handling. //===----------------------------------------------------------------------===// +namespace { +// TokenCollector provides the option to collect tokens that were "read" +// and return them to the stream to be read later. +// Currently used when reading _Pragma/__pragma directives. +struct TokenCollector { + Preprocessor &Self; + bool Collect; + SmallVector<Token, 3> Tokens; + Token &Tok; + + void lex() { + if (Collect) + Tokens.push_back(Tok); + Self.Lex(Tok); + } + + void revert() { + assert(Collect && "did not collect tokens"); + assert(!Tokens.empty() && "collected unexpected number of tokens"); + + // Push the ( "string" ) tokens into the token stream. + auto Toks = std::make_unique<Token[]>(Tokens.size()); + std::copy(Tokens.begin() + 1, Tokens.end(), Toks.get()); + Toks[Tokens.size() - 1] = Tok; + Self.EnterTokenStream(std::move(Toks), Tokens.size(), + /*DisableMacroExpansion*/ true, + /*IsReinject*/ true); + + // ... and return the pragma token unchanged. + Tok = *Tokens.begin(); + } +}; +} // namespace + /// HandlePragmaDirective - The "\#pragma" directive has been parsed. Lex the /// rest of the pragma, passing it to the registered pragma handlers. void Preprocessor::HandlePragmaDirective(PragmaIntroducer Introducer) { @@ -166,35 +200,6 @@ void Preprocessor::Handle_Pragma(Token &Tok) { // In Case #2, we check the syntax now, but then put the tokens back into the // token stream for later consumption. - struct TokenCollector { - Preprocessor &Self; - bool Collect; - SmallVector<Token, 3> Tokens; - Token &Tok; - - void lex() { - if (Collect) - Tokens.push_back(Tok); - Self.Lex(Tok); - } - - void revert() { - assert(Collect && "did not collect tokens"); - assert(!Tokens.empty() && "collected unexpected number of tokens"); - - // Push the ( "string" ) tokens into the token stream. - auto Toks = llvm::make_unique<Token[]>(Tokens.size()); - std::copy(Tokens.begin() + 1, Tokens.end(), Toks.get()); - Toks[Tokens.size() - 1] = Tok; - Self.EnterTokenStream(std::move(Toks), Tokens.size(), - /*DisableMacroExpansion*/ true, - /*IsReinject*/ true); - - // ... and return the _Pragma token unchanged. - Tok = *Tokens.begin(); - } - }; - TokenCollector Toks = {*this, InMacroArgPreExpansion, {}, Tok}; // Remember the pragma token location. @@ -328,11 +333,15 @@ void Preprocessor::Handle_Pragma(Token &Tok) { /// HandleMicrosoft__pragma - Like Handle_Pragma except the pragma text /// is not enclosed within a string literal. void Preprocessor::HandleMicrosoft__pragma(Token &Tok) { + // During macro pre-expansion, check the syntax now but put the tokens back + // into the token stream for later consumption. Same as Handle_Pragma. + TokenCollector Toks = {*this, InMacroArgPreExpansion, {}, Tok}; + // Remember the pragma token location. SourceLocation PragmaLoc = Tok.getLocation(); // Read the '('. - Lex(Tok); + Toks.lex(); if (Tok.isNot(tok::l_paren)) { Diag(PragmaLoc, diag::err__Pragma_malformed); return; @@ -341,14 +350,14 @@ void Preprocessor::HandleMicrosoft__pragma(Token &Tok) { // Get the tokens enclosed within the __pragma(), as well as the final ')'. SmallVector<Token, 32> PragmaToks; int NumParens = 0; - Lex(Tok); + Toks.lex(); while (Tok.isNot(tok::eof)) { PragmaToks.push_back(Tok); if (Tok.is(tok::l_paren)) NumParens++; else if (Tok.is(tok::r_paren) && NumParens-- == 0) break; - Lex(Tok); + Toks.lex(); } if (Tok.is(tok::eof)) { @@ -356,6 +365,12 @@ void Preprocessor::HandleMicrosoft__pragma(Token &Tok) { return; } + // If we're expanding a macro argument, put the tokens back. + if (InMacroArgPreExpansion) { + Toks.revert(); + return; + } + PragmaToks.front().setFlag(Token::LeadingSpace); // Replace the ')' with an EOD to mark the end of the pragma. @@ -498,7 +513,7 @@ void Preprocessor::HandlePragmaDependency(Token &DependencyTok) { // Search include directories for this file. const DirectoryLookup *CurDir; - const FileEntry *File = + Optional<FileEntryRef> File = LookupFile(FilenameTok.getLocation(), Filename, isAngled, nullptr, nullptr, CurDir, nullptr, nullptr, nullptr, nullptr, nullptr); if (!File) { @@ -1722,7 +1737,7 @@ struct PragmaARCCFCodeAuditedHandler : public PragmaHandler { PP.Diag(Tok, diag::ext_pp_extra_tokens_at_eol) << "pragma"; // The start location of the active audit. - SourceLocation BeginLoc = PP.getPragmaARCCFCodeAuditedLoc(); + SourceLocation BeginLoc = PP.getPragmaARCCFCodeAuditedInfo().second; // The start location we want after processing this. SourceLocation NewLoc; @@ -1743,7 +1758,7 @@ struct PragmaARCCFCodeAuditedHandler : public PragmaHandler { NewLoc = SourceLocation(); } - PP.setPragmaARCCFCodeAuditedLoc(NewLoc); + PP.setPragmaARCCFCodeAuditedInfo(NameTok.getIdentifierInfo(), NewLoc); } }; diff --git a/lib/Lex/Preprocessor.cpp b/lib/Lex/Preprocessor.cpp index bdc5fbcd2bea..82007732a9b1 100644 --- a/lib/Lex/Preprocessor.cpp +++ b/lib/Lex/Preprocessor.cpp @@ -158,6 +158,11 @@ Preprocessor::Preprocessor(std::shared_ptr<PreprocessorOptions> PPOpts, if (this->PPOpts->GeneratePreamble) PreambleConditionalStack.startRecording(); + + ExcludedConditionalDirectiveSkipMappings = + this->PPOpts->ExcludedConditionalDirectiveSkipMappings; + if (ExcludedConditionalDirectiveSkipMappings) + ExcludedConditionalDirectiveSkipMappings->clear(); } Preprocessor::~Preprocessor() { @@ -209,7 +214,7 @@ void Preprocessor::InitializeForModelFile() { // Reset pragmas PragmaHandlersBackup = std::move(PragmaHandlers); - PragmaHandlers = llvm::make_unique<PragmaNamespace>(StringRef()); + PragmaHandlers = std::make_unique<PragmaNamespace>(StringRef()); RegisterBuiltinPragmas(); // Reset PredefinesFileID @@ -563,7 +568,7 @@ void Preprocessor::EnterMainSourceFile() { // Lookup and save the FileID for the through header. If it isn't found // in the search path, it's a fatal error. const DirectoryLookup *CurDir; - const FileEntry *File = LookupFile( + Optional<FileEntryRef> File = LookupFile( SourceLocation(), PPOpts->PCHThroughHeader, /*isAngled=*/false, /*FromDir=*/nullptr, /*FromFile=*/nullptr, CurDir, /*SearchPath=*/nullptr, /*RelativePath=*/nullptr, @@ -575,7 +580,7 @@ void Preprocessor::EnterMainSourceFile() { return; } setPCHThroughHeaderFileID( - SourceMgr.createFileID(File, SourceLocation(), SrcMgr::C_User)); + SourceMgr.createFileID(*File, SourceLocation(), SrcMgr::C_User)); } // Skip tokens from the Predefines and if needed the main file. @@ -1129,7 +1134,7 @@ bool Preprocessor::LexAfterModuleImport(Token &Result) { // Allocate a holding buffer for a sequence of tokens and introduce it into // the token stream. auto EnterTokens = [this](ArrayRef<Token> Toks) { - auto ToksCopy = llvm::make_unique<Token[]>(Toks.size()); + auto ToksCopy = std::make_unique<Token[]>(Toks.size()); std::copy(Toks.begin(), Toks.end(), ToksCopy.get()); EnterTokenStream(std::move(ToksCopy), Toks.size(), /*DisableMacroExpansion*/ true, /*IsReinject*/ false); diff --git a/lib/Lex/TokenLexer.cpp b/lib/Lex/TokenLexer.cpp index a7957e82e495..da5681aaf478 100644 --- a/lib/Lex/TokenLexer.cpp +++ b/lib/Lex/TokenLexer.cpp @@ -383,18 +383,10 @@ void TokenLexer::ExpandFunctionArguments() { SourceLocation ExpansionLocEnd = getExpansionLocForMacroDefLoc(Tokens[I+1].getLocation()); - Token Res; - if (CurTok.is(tok::hash)) // Stringify - Res = ActualArgs->getStringifiedArgument(ArgNo, PP, - ExpansionLocStart, - ExpansionLocEnd); - else { - // 'charify': don't bother caching these. - Res = MacroArgs::StringifyArgument(ActualArgs->getUnexpArgument(ArgNo), - PP, true, - ExpansionLocStart, - ExpansionLocEnd); - } + bool Charify = CurTok.is(tok::hashat); + const Token *UnexpArg = ActualArgs->getUnexpArgument(ArgNo); + Token Res = MacroArgs::StringifyArgument( + UnexpArg, PP, Charify, ExpansionLocStart, ExpansionLocEnd); Res.setFlag(Token::StringifiedInMacro); // The stringified/charified string leading space flag gets set to match diff --git a/lib/Lex/UnicodeCharSets.h b/lib/Lex/UnicodeCharSets.h index d56bc8ef6721..74dd57fdf118 100644 --- a/lib/Lex/UnicodeCharSets.h +++ b/lib/Lex/UnicodeCharSets.h @@ -215,7 +215,7 @@ static const llvm::sys::UnicodeCharRange C99AllowedIDCharRanges[] = { // Digits (2) { 0x06F0, 0x06F9 }, - // Devanagari and Special characeter 0x093D. + // Devanagari and Special character 0x093D. { 0x0901, 0x0903 }, { 0x0905, 0x0939 }, { 0x093D, 0x094D }, { 0x0950, 0x0952 }, { 0x0958, 0x0963 }, |