diff options
Diffstat (limited to 'lib/Lex')
-rw-r--r-- | lib/Lex/HeaderSearch.cpp | 140 | ||||
-rw-r--r-- | lib/Lex/Lexer.cpp | 103 | ||||
-rw-r--r-- | lib/Lex/LiteralSupport.cpp | 197 | ||||
-rw-r--r-- | lib/Lex/MacroArgs.cpp | 5 | ||||
-rw-r--r-- | lib/Lex/MacroInfo.cpp | 2 | ||||
-rw-r--r-- | lib/Lex/ModuleMap.cpp | 310 | ||||
-rw-r--r-- | lib/Lex/PPCaching.cpp | 4 | ||||
-rw-r--r-- | lib/Lex/PPDirectives.cpp | 124 | ||||
-rw-r--r-- | lib/Lex/PPExpressions.cpp | 2 | ||||
-rw-r--r-- | lib/Lex/PPLexerChange.cpp | 32 | ||||
-rw-r--r-- | lib/Lex/PPMacroExpansion.cpp | 238 | ||||
-rw-r--r-- | lib/Lex/PTHLexer.cpp | 10 | ||||
-rw-r--r-- | lib/Lex/Pragma.cpp | 83 | ||||
-rw-r--r-- | lib/Lex/PreprocessingRecord.cpp | 34 | ||||
-rw-r--r-- | lib/Lex/Preprocessor.cpp | 117 | ||||
-rw-r--r-- | lib/Lex/PreprocessorLexer.cpp | 2 | ||||
-rw-r--r-- | lib/Lex/ScratchBuffer.cpp | 8 | ||||
-rw-r--r-- | lib/Lex/TokenLexer.cpp | 14 |
18 files changed, 901 insertions, 524 deletions
diff --git a/lib/Lex/HeaderSearch.cpp b/lib/Lex/HeaderSearch.cpp index 6976294a2eaf3..b1a2ef121288e 100644 --- a/lib/Lex/HeaderSearch.cpp +++ b/lib/Lex/HeaderSearch.cpp @@ -124,7 +124,7 @@ const HeaderMap *HeaderSearch::CreateHeaderMap(const FileEntry *FE) { return nullptr; } -/// \brief Get filenames for all registered header maps. +/// Get filenames for all registered header maps. void HeaderSearch::getHeaderMapFileNames( SmallVectorImpl<std::string> &Names) const { for (auto &HM : HeaderMaps) @@ -198,31 +198,33 @@ std::string HeaderSearch::getCachedModuleFileName(StringRef ModuleName, return Result.str().str(); } -Module *HeaderSearch::lookupModule(StringRef ModuleName, bool AllowSearch) { +Module *HeaderSearch::lookupModule(StringRef ModuleName, bool AllowSearch, + bool AllowExtraModuleMapSearch) { // Look in the module map to determine if there is a module by this name. Module *Module = ModMap.findModule(ModuleName); if (Module || !AllowSearch || !HSOpts->ImplicitModuleMaps) return Module; StringRef SearchName = ModuleName; - Module = lookupModule(ModuleName, SearchName); + Module = lookupModule(ModuleName, SearchName, AllowExtraModuleMapSearch); // The facility for "private modules" -- adjacent, optional module maps named // module.private.modulemap that are supposed to define private submodules -- // may have different flavors of names: FooPrivate, Foo_Private and Foo.Private. // - // Foo.Private is now depracated in favor of Foo_Private. Users of FooPrivate + // Foo.Private is now deprecated in favor of Foo_Private. Users of FooPrivate // should also rename to Foo_Private. Representing private as submodules // could force building unwanted dependencies into the parent module and cause // dependency cycles. if (!Module && SearchName.consume_back("_Private")) - Module = lookupModule(ModuleName, SearchName); + Module = lookupModule(ModuleName, SearchName, AllowExtraModuleMapSearch); if (!Module && SearchName.consume_back("Private")) - Module = lookupModule(ModuleName, SearchName); + Module = lookupModule(ModuleName, SearchName, AllowExtraModuleMapSearch); return Module; } -Module *HeaderSearch::lookupModule(StringRef ModuleName, StringRef SearchName) { +Module *HeaderSearch::lookupModule(StringRef ModuleName, StringRef SearchName, + bool AllowExtraModuleMapSearch) { Module *Module = nullptr; // Look through the various header search paths to load any available module @@ -281,8 +283,9 @@ Module *HeaderSearch::lookupModule(StringRef ModuleName, StringRef SearchName) { continue; // Load all module maps in the immediate subdirectories of this search - // directory. - loadSubdirectoryModuleMaps(SearchDirs[Idx]); + // directory if ModuleName was from @import. + if (AllowExtraModuleMapSearch) + loadSubdirectoryModuleMaps(SearchDirs[Idx]); // Look again for the module. Module = ModMap.findModule(ModuleName); @@ -404,7 +407,7 @@ const FileEntry *DirectoryLookup::LookupFile( return Result; } -/// \brief Given a framework directory, find the top-most framework directory. +/// Given a framework directory, find the top-most framework directory. /// /// \param FileMgr The file manager to use for directory lookups. /// \param DirName The name of the framework directory. @@ -600,7 +603,7 @@ void HeaderSearch::setTarget(const TargetInfo &Target) { // Header File Location. //===----------------------------------------------------------------------===// -/// \brief Return true with a diagnostic if the file that MSVC would have found +/// Return true with a diagnostic if the file that MSVC would have found /// fails to match the one that Clang would have found with MSVC header search /// disabled. static bool checkMSVCHeaderSearch(DiagnosticsEngine &Diags, @@ -621,6 +624,74 @@ static const char *copyString(StringRef Str, llvm::BumpPtrAllocator &Alloc) { return CopyStr; } +static bool isFrameworkStylePath(StringRef Path, bool &IsPrivateHeader, + SmallVectorImpl<char> &FrameworkName) { + using namespace llvm::sys; + path::const_iterator I = path::begin(Path); + path::const_iterator E = path::end(Path); + IsPrivateHeader = false; + + // Detect different types of framework style paths: + // + // ...Foo.framework/{Headers,PrivateHeaders} + // ...Foo.framework/Versions/{A,Current}/{Headers,PrivateHeaders} + // ...Foo.framework/Frameworks/Nested.framework/{Headers,PrivateHeaders} + // ...<other variations with 'Versions' like in the above path> + // + // and some other variations among these lines. + int FoundComp = 0; + while (I != E) { + if (*I == "Headers") + ++FoundComp; + if (I->endswith(".framework")) { + FrameworkName.append(I->begin(), I->end()); + ++FoundComp; + } + if (*I == "PrivateHeaders") { + ++FoundComp; + IsPrivateHeader = true; + } + ++I; + } + + return FoundComp >= 2; +} + +static void +diagnoseFrameworkInclude(DiagnosticsEngine &Diags, SourceLocation IncludeLoc, + StringRef Includer, StringRef IncludeFilename, + const FileEntry *IncludeFE, bool isAngled = false, + bool FoundByHeaderMap = false) { + bool IsIncluderPrivateHeader = false; + SmallString<128> FromFramework, ToFramework; + if (!isFrameworkStylePath(Includer, IsIncluderPrivateHeader, FromFramework)) + return; + bool IsIncludeePrivateHeader = false; + bool IsIncludeeInFramework = isFrameworkStylePath( + IncludeFE->getName(), IsIncludeePrivateHeader, ToFramework); + + if (!isAngled && !FoundByHeaderMap) { + SmallString<128> NewInclude("<"); + if (IsIncludeeInFramework) { + NewInclude += StringRef(ToFramework).drop_back(10); // drop .framework + NewInclude += "/"; + } + NewInclude += IncludeFilename; + NewInclude += ">"; + Diags.Report(IncludeLoc, diag::warn_quoted_include_in_framework_header) + << IncludeFilename + << FixItHint::CreateReplacement(IncludeLoc, NewInclude); + } + + // Headers in Foo.framework/Headers should not include headers + // from Foo.framework/PrivateHeaders, since this violates public/private + // API boundaries and can cause modular dependency cycles. + if (!IsIncluderPrivateHeader && IsIncludeeInFramework && + IsIncludeePrivateHeader && FromFramework == ToFramework) + Diags.Report(IncludeLoc, diag::warn_framework_include_private_from_public) + << IncludeFilename; +} + /// LookupFile - Given a "foo" or \<foo> reference, look up the indicated file, /// return null on failure. isAngled indicates whether the file reference is /// for system \#include's or not (i.e. using <> instead of ""). Includers, if @@ -722,8 +793,12 @@ const FileEntry *HeaderSearch::LookupFile( RelativePath->clear(); RelativePath->append(Filename.begin(), Filename.end()); } - if (First) + if (First) { + diagnoseFrameworkInclude(Diags, IncludeLoc, + IncluderAndDir.second->getName(), Filename, + FE); return FE; + } // Otherwise, we found the path via MSVC header search rules. If // -Wmsvc-include is enabled, we have to keep searching to see if we @@ -834,6 +909,12 @@ const FileEntry *HeaderSearch::LookupFile( return MSFE; } + bool FoundByHeaderMap = !IsMapped ? false : *IsMapped; + if (!Includers.empty()) + diagnoseFrameworkInclude(Diags, IncludeLoc, + Includers.front().second->getName(), Filename, + FE, isAngled, FoundByHeaderMap); + // Remember this location for the next lookup we do. CacheLookup.HitIdx = i; return FE; @@ -996,7 +1077,7 @@ LookupSubframeworkHeader(StringRef Filename, // File Info Management. //===----------------------------------------------------------------------===// -/// \brief Merge the header file info provided by \p OtherHFI into the current +/// Merge the header file info provided by \p OtherHFI into the current /// header file info (\p HFI) static void mergeHeaderFileInfo(HeaderFileInfo &HFI, const HeaderFileInfo &OtherHFI) { @@ -1580,9 +1661,15 @@ void HeaderSearch::loadSubdirectoryModuleMaps(DirectoryLookup &SearchDir) { std::string HeaderSearch::suggestPathToFileForDiagnostics(const FileEntry *File, bool *IsSystem) { // FIXME: We assume that the path name currently cached in the FileEntry is - // the most appropriate one for this analysis (and that it's spelled the same - // way as the corresponding header search path). - StringRef Name = File->getName(); + // the most appropriate one for this analysis (and that it's spelled the + // same way as the corresponding header search path). + return suggestPathToFileForDiagnostics(File->getName(), /*BuildDir=*/"", + IsSystem); +} + +std::string HeaderSearch::suggestPathToFileForDiagnostics( + llvm::StringRef File, llvm::StringRef WorkingDir, bool *IsSystem) { + using namespace llvm::sys; unsigned BestPrefixLength = 0; unsigned BestSearchDir; @@ -1593,12 +1680,17 @@ std::string HeaderSearch::suggestPathToFileForDiagnostics(const FileEntry *File, continue; StringRef Dir = SearchDirs[I].getDir()->getName(); - for (auto NI = llvm::sys::path::begin(Name), - NE = llvm::sys::path::end(Name), - DI = llvm::sys::path::begin(Dir), - DE = llvm::sys::path::end(Dir); + llvm::SmallString<32> DirPath(Dir.begin(), Dir.end()); + if (!WorkingDir.empty() && !path::is_absolute(Dir)) { + auto err = fs::make_absolute(WorkingDir, DirPath); + if (!err) + path::remove_dots(DirPath, /*remove_dot_dot=*/true); + Dir = DirPath; + } + for (auto NI = path::begin(File), NE = path::end(File), + DI = path::begin(Dir), DE = path::end(Dir); /*termination condition in loop*/; ++NI, ++DI) { - // '.' components in Name are ignored. + // '.' components in File are ignored. while (NI != NE && *NI == ".") ++NI; if (NI == NE) @@ -1608,9 +1700,9 @@ std::string HeaderSearch::suggestPathToFileForDiagnostics(const FileEntry *File, while (DI != DE && *DI == ".") ++DI; if (DI == DE) { - // Dir is a prefix of Name, up to '.' components and choice of path + // Dir is a prefix of File, up to '.' components and choice of path // separators. - unsigned PrefixLength = NI - llvm::sys::path::begin(Name); + unsigned PrefixLength = NI - path::begin(File); if (PrefixLength > BestPrefixLength) { BestPrefixLength = PrefixLength; BestSearchDir = I; @@ -1625,5 +1717,5 @@ std::string HeaderSearch::suggestPathToFileForDiagnostics(const FileEntry *File, if (IsSystem) *IsSystem = BestPrefixLength ? BestSearchDir >= SystemDirIdx : false; - return Name.drop_front(BestPrefixLength); + return File.drop_front(BestPrefixLength); } diff --git a/lib/Lex/Lexer.cpp b/lib/Lex/Lexer.cpp index 830354ab23f0d..e8588a771a431 100644 --- a/lib/Lex/Lexer.cpp +++ b/lib/Lex/Lexer.cpp @@ -257,7 +257,7 @@ void Lexer::Stringify(SmallVectorImpl<char> &Str) { StringifyImpl(Str, '"'); } // Token Spelling //===----------------------------------------------------------------------===// -/// \brief Slow case of getSpelling. Extract the characters comprising the +/// Slow case of getSpelling. Extract the characters comprising the /// spelling of this token from the provided input buffer. static size_t getSpellingSlow(const Token &Tok, const char *BufPtr, const LangOptions &LangOpts, char *Spelling) { @@ -442,7 +442,7 @@ unsigned Lexer::MeasureTokenLength(SourceLocation Loc, return TheTok.getLength(); } -/// \brief Relex the token at the specified location. +/// Relex the token at the specified location. /// \returns true if there was a failure, false on success. bool Lexer::getRawToken(SourceLocation Loc, Token &Result, const SourceManager &SM, @@ -708,12 +708,9 @@ PreambleBounds Lexer::ComputePreamble(StringRef Buffer, TheTok.isAtStartOfLine()); } -/// AdvanceToTokenCharacter - Given a location that specifies the start of a -/// token, return a new location that specifies a character within the token. -SourceLocation Lexer::AdvanceToTokenCharacter(SourceLocation TokStart, - unsigned CharNo, - const SourceManager &SM, - const LangOptions &LangOpts) { +unsigned Lexer::getTokenPrefixLength(SourceLocation TokStart, unsigned CharNo, + const SourceManager &SM, + const LangOptions &LangOpts) { // Figure out how many physical characters away the specified expansion // character is. This needs to take into consideration newlines and // trigraphs. @@ -722,7 +719,7 @@ SourceLocation Lexer::AdvanceToTokenCharacter(SourceLocation TokStart, // If they request the first char of the token, we're trivially done. if (Invalid || (CharNo == 0 && Lexer::isObviouslySimpleCharacter(*TokPtr))) - return TokStart; + return 0; unsigned PhysOffset = 0; @@ -731,7 +728,7 @@ SourceLocation Lexer::AdvanceToTokenCharacter(SourceLocation TokStart, // chars, this method is extremely fast. while (Lexer::isObviouslySimpleCharacter(*TokPtr)) { if (CharNo == 0) - return TokStart.getLocWithOffset(PhysOffset); + return PhysOffset; ++TokPtr; --CharNo; ++PhysOffset; @@ -753,10 +750,10 @@ SourceLocation Lexer::AdvanceToTokenCharacter(SourceLocation TokStart, if (!Lexer::isObviouslySimpleCharacter(*TokPtr)) PhysOffset += Lexer::SkipEscapedNewLines(TokPtr)-TokPtr; - return TokStart.getLocWithOffset(PhysOffset); + return PhysOffset; } -/// \brief Computes the source location just past the end of the +/// Computes the source location just past the end of the /// token at this source location. /// /// This routine can be used to produce a source location that @@ -791,7 +788,7 @@ SourceLocation Lexer::getLocForEndOfToken(SourceLocation Loc, unsigned Offset, return Loc.getLocWithOffset(Len); } -/// \brief Returns true if the given MacroID location points at the first +/// Returns true if the given MacroID location points at the first /// token of the macro expansion. bool Lexer::isAtStartOfMacroExpansion(SourceLocation loc, const SourceManager &SM, @@ -813,7 +810,7 @@ bool Lexer::isAtStartOfMacroExpansion(SourceLocation loc, return isAtStartOfMacroExpansion(expansionLoc, SM, LangOpts, MacroBegin); } -/// \brief Returns true if the given MacroID location points at the last +/// Returns true if the given MacroID location points at the last /// token of the macro expansion. bool Lexer::isAtEndOfMacroExpansion(SourceLocation loc, const SourceManager &SM, @@ -971,7 +968,7 @@ StringRef Lexer::getSourceText(CharSourceRange Range, StringRef Lexer::getImmediateMacroName(SourceLocation Loc, const SourceManager &SM, const LangOptions &LangOpts) { - assert(Loc.isMacroID() && "Only reasonble to call this on macros"); + assert(Loc.isMacroID() && "Only reasonable to call this on macros"); // Find the location of the immediate macro expansion. while (true) { @@ -987,7 +984,7 @@ StringRef Lexer::getImmediateMacroName(SourceLocation Loc, // Loc points to the argument id of the macro definition, move to the // macro expansion. - Loc = SM.getImmediateExpansionRange(Loc).first; + Loc = SM.getImmediateExpansionRange(Loc).getBegin(); SourceLocation SpellLoc = Expansion.getSpellingLoc(); if (SpellLoc.isFileID()) break; // No inner macro. @@ -1017,10 +1014,10 @@ StringRef Lexer::getImmediateMacroName(SourceLocation Loc, StringRef Lexer::getImmediateMacroNameForDiagnostics( SourceLocation Loc, const SourceManager &SM, const LangOptions &LangOpts) { - assert(Loc.isMacroID() && "Only reasonble to call this on macros"); + assert(Loc.isMacroID() && "Only reasonable to call this on macros"); // Walk past macro argument expanions. while (SM.isMacroArgExpansion(Loc)) - Loc = SM.getImmediateExpansionRange(Loc).first; + Loc = SM.getImmediateExpansionRange(Loc).getBegin(); // If the macro's spelling has no FileID, then it's actually a token paste // or stringization (or similar) and not a macro at all. @@ -1030,7 +1027,7 @@ StringRef Lexer::getImmediateMacroNameForDiagnostics( // Find the spelling location of the start of the non-argument expansion // range. This is where the macro name was spelled in order to begin // expanding this macro. - Loc = SM.getSpellingLoc(SM.getImmediateExpansionRange(Loc).first); + Loc = SM.getSpellingLoc(SM.getImmediateExpansionRange(Loc).getBegin()); // Dig out the buffer where the macro name was spelled and the extents of the // name so that we can render it into the expansion note. @@ -1112,10 +1109,9 @@ static SourceLocation GetMappedTokenLoc(Preprocessor &PP, // Figure out the expansion loc range, which is the range covered by the // original _Pragma(...) sequence. - std::pair<SourceLocation,SourceLocation> II = - SM.getImmediateExpansionRange(FileLoc); + CharSourceRange II = SM.getImmediateExpansionRange(FileLoc); - return SM.createExpansionLoc(SpellingLoc, II.first, II.second, TokLen); + return SM.createExpansionLoc(SpellingLoc, II.getBegin(), II.getEnd(), TokLen); } /// getSourceLocation - Return a source location identifier for the specified @@ -1260,7 +1256,7 @@ Optional<Token> Lexer::findNextToken(SourceLocation Loc, return Tok; } -/// \brief Checks that the given token is the first token that occurs after the +/// Checks that the given token is the first token that occurs after the /// given location (this excludes comments and whitespace). Returns the location /// immediately after the specified token. If the token is not found or the /// location is inside a macro, the returned source location will be invalid. @@ -1413,7 +1409,7 @@ Slash: // Helper methods for lexing. //===----------------------------------------------------------------------===// -/// \brief Routine that indiscriminately sets the offset into the source file. +/// Routine that indiscriminately sets the offset into the source file. void Lexer::SetByteOffset(unsigned Offset, bool StartOfLine) { BufferPtr = BufferStart + Offset; if (BufferPtr > BufferEnd) @@ -1645,20 +1641,38 @@ FinishIdentifier: // Fill in Result.IdentifierInfo and update the token kind, // looking up the identifier in the identifier table. IdentifierInfo *II = PP->LookUpIdentifierInfo(Result); + // Note that we have to call PP->LookUpIdentifierInfo() even for code + // completion, it writes IdentifierInfo into Result, and callers rely on it. + + // If the completion point is at the end of an identifier, we want to treat + // the identifier as incomplete even if it resolves to a macro or a keyword. + // This allows e.g. 'class^' to complete to 'classifier'. + if (isCodeCompletionPoint(CurPtr)) { + // Return the code-completion token. + Result.setKind(tok::code_completion); + // Skip the code-completion char and all immediate identifier characters. + // This ensures we get consistent behavior when completing at any point in + // an identifier (i.e. at the start, in the middle, at the end). Note that + // only simple cases (i.e. [a-zA-Z0-9_]) are supported to keep the code + // simpler. + assert(*CurPtr == 0 && "Completion character must be 0"); + ++CurPtr; + // Note that code completion token is not added as a separate character + // when the completion point is at the end of the buffer. Therefore, we need + // to check if the buffer has ended. + if (CurPtr < BufferEnd) { + while (isIdentifierBody(*CurPtr)) + ++CurPtr; + } + BufferPtr = CurPtr; + return true; + } // Finally, now that we know we have an identifier, pass this off to the // preprocessor, which may macro expand it or something. if (II->isHandleIdentifierCase()) return PP->HandleIdentifier(Result); - if (II->getTokenID() == tok::identifier && isCodeCompletionPoint(CurPtr) - && II->getPPKeywordID() == tok::pp_not_keyword - && II->getObjCKeywordID() == tok::objc_not_keyword) { - // Return the code-completion token. - Result.setKind(tok::code_completion); - cutOffLexing(); - return true; - } return true; } @@ -2009,18 +2023,21 @@ bool Lexer::LexAngledStringLiteral(Token &Result, const char *CurPtr) { const char *AfterLessPos = CurPtr; char C = getAndAdvanceChar(CurPtr, Result); while (C != '>') { - // Skip escaped characters. - if (C == '\\' && CurPtr < BufferEnd) { - // Skip the escaped character. - getAndAdvanceChar(CurPtr, Result); - } else if (C == '\n' || C == '\r' || // Newline. - (C == 0 && (CurPtr-1 == BufferEnd || // End of file. - isCodeCompletionPoint(CurPtr-1)))) { + // Skip escaped characters. Escaped newlines will already be processed by + // getAndAdvanceChar. + if (C == '\\') + C = getAndAdvanceChar(CurPtr, Result); + + if (C == '\n' || C == '\r' || // Newline. + (C == 0 && (CurPtr-1 == BufferEnd || // End of file. + isCodeCompletionPoint(CurPtr-1)))) { // If the filename is unterminated, then it must just be a lone < // character. Return this as such. FormTokenWithChars(Result, AfterLessPos, tok::less); return true; - } else if (C == 0) { + } + + if (C == 0) { NulCharacter = CurPtr-1; } C = getAndAdvanceChar(CurPtr, Result); @@ -2160,7 +2177,7 @@ bool Lexer::SkipWhitespace(Token &Result, const char *CurPtr, } /// We have just read the // characters from input. Skip until we find the -/// newline character thats terminate the comment. Then update BufferPtr and +/// newline character that terminates the comment. Then update BufferPtr and /// return. /// /// If we're in KeepCommentMode or any CommentHandler has inserted @@ -2738,7 +2755,7 @@ unsigned Lexer::isNextPPTokenLParen() { return Tok.is(tok::l_paren); } -/// \brief Find the end of a version control conflict marker. +/// Find the end of a version control conflict marker. static const char *FindConflictEnd(const char *CurPtr, const char *BufferEnd, ConflictMarkerKind CMK) { const char *Terminator = CMK == CMK_Perforce ? "<<<<\n" : ">>>>>>>"; @@ -3509,7 +3526,7 @@ LexNextToken: // want to lex this as a comment. There is one problem with this though, // that in one particular corner case, this can change the behavior of the // resultant program. For example, In "foo //**/ bar", C89 would lex - // this as "foo / bar" and langauges with Line comments would lex it as + // this as "foo / bar" and languages with Line comments would lex it as // "foo". Check to see if the character after the second slash is a '*'. // If so, we will lex that as a "/" instead of the start of a comment. // However, we never do this if we are just preprocessing. diff --git a/lib/Lex/LiteralSupport.cpp b/lib/Lex/LiteralSupport.cpp index cbec5e6b63856..966dafca27197 100644 --- a/lib/Lex/LiteralSupport.cpp +++ b/lib/Lex/LiteralSupport.cpp @@ -70,7 +70,7 @@ static CharSourceRange MakeCharSourceRange(const LangOptions &Features, return CharSourceRange::getCharRange(Begin, End); } -/// \brief Produce a diagnostic highlighting some portion of a literal. +/// Produce a diagnostic highlighting some portion of a literal. /// /// Emits the diagnostic \p DiagID, highlighting the range of characters from /// \p TokRangeBegin (inclusive) to \p TokRangeEnd (exclusive), which must be @@ -538,6 +538,7 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling, saw_exponent = false; saw_period = false; saw_ud_suffix = false; + saw_fixed_point_suffix = false; isLong = false; isUnsigned = false; isLongLong = false; @@ -547,6 +548,8 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling, isFloat16 = false; isFloat128 = false; MicrosoftInteger = 0; + isFract = false; + isAccum = false; hadError = false; if (*s == '0') { // parse radix @@ -568,6 +571,16 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling, SuffixBegin = s; checkSeparator(TokLoc, s, CSK_AfterDigits); + // Initial scan to lookahead for fixed point suffix. + if (PP.getLangOpts().FixedPoint) { + for (const char *c = s; c != ThisTokEnd; ++c) { + if (*c == 'r' || *c == 'k' || *c == 'R' || *c == 'K') { + saw_fixed_point_suffix = true; + break; + } + } + } + // Parse the suffix. At this point we can classify whether we have an FP or // integer constant. bool isFPConstant = isFloatingLiteral(); @@ -576,11 +589,25 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling, // we break out of the loop. for (; s != ThisTokEnd; ++s) { switch (*s) { + case 'R': + case 'r': + if (!PP.getLangOpts().FixedPoint) break; + if (isFract || isAccum) break; + if (!(saw_period || saw_exponent)) break; + isFract = true; + continue; + case 'K': + case 'k': + if (!PP.getLangOpts().FixedPoint) break; + if (isFract || isAccum) break; + if (!(saw_period || saw_exponent)) break; + isAccum = true; + continue; case 'h': // FP Suffix for "half". case 'H': // OpenCL Extension v1.2 s9.5 - h or H suffix for half type. - if (!PP.getLangOpts().Half) break; - if (!isFPConstant) break; // Error for integer constant. + if (!(PP.getLangOpts().Half || PP.getLangOpts().FixedPoint)) break; + if (isIntegerLiteral()) break; // Error for integer constant. if (isHalf || isFloat || isLong) break; // HH, FH, LH invalid. isHalf = true; continue; // Success. @@ -693,6 +720,9 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling, isHalf = false; isImaginary = false; MicrosoftInteger = 0; + saw_fixed_point_suffix = false; + isFract = false; + isAccum = false; } saw_ud_suffix = true; @@ -707,6 +737,10 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling, hadError = true; } } + + if (!hadError && saw_fixed_point_suffix) { + assert(isFract || isAccum); + } } /// ParseDecimalOrOctalCommon - This method is called for decimal or octal @@ -717,7 +751,8 @@ void NumericLiteralParser::ParseDecimalOrOctalCommon(SourceLocation TokLoc){ // If we have a hex digit other than 'e' (which denotes a FP exponent) then // the code is using an incorrect base. - if (isHexDigit(*s) && *s != 'e' && *s != 'E') { + if (isHexDigit(*s) && *s != 'e' && *s != 'E' && + !isValidUDSuffix(PP.getLangOpts(), StringRef(s, ThisTokEnd - s))) { PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, s-ThisTokBegin), diag::err_invalid_digit) << StringRef(s, 1) << (radix == 8 ? 1 : 0); hadError = true; @@ -738,15 +773,17 @@ void NumericLiteralParser::ParseDecimalOrOctalCommon(SourceLocation TokLoc){ s++; radix = 10; saw_exponent = true; - if (*s == '+' || *s == '-') s++; // sign + if (s != ThisTokEnd && (*s == '+' || *s == '-')) s++; // sign const char *first_non_digit = SkipDigits(s); if (containsDigits(s, first_non_digit)) { checkSeparator(TokLoc, s, CSK_BeforeDigits); s = first_non_digit; } else { - PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, Exponent-ThisTokBegin), - diag::err_exponent_has_no_digits); - hadError = true; + if (!hadError) { + PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, Exponent-ThisTokBegin), + diag::err_exponent_has_no_digits); + hadError = true; + } return; } } @@ -768,12 +805,14 @@ bool NumericLiteralParser::isValidUDSuffix(const LangOptions &LangOpts, if (!LangOpts.CPlusPlus14) return false; - // In C++1y, "s", "h", "min", "ms", "us", and "ns" are used in the library. + // In C++14, "s", "h", "min", "ms", "us", and "ns" are used in the library. // Per tweaked N3660, "il", "i", and "if" are also used in the library. + // In C++2a "d" and "y" are used in the library. return llvm::StringSwitch<bool>(Suffix) .Cases("h", "min", "s", true) .Cases("ms", "us", "ns", true) .Cases("il", "i", "if", true) + .Cases("d", "y", LangOpts.CPlusPlus2a) .Default(false); } @@ -787,10 +826,12 @@ void NumericLiteralParser::checkSeparator(SourceLocation TokLoc, } else if (Pos == ThisTokEnd) return; - if (isDigitSeparator(*Pos)) + if (isDigitSeparator(*Pos)) { PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, Pos - ThisTokBegin), diag::err_digit_separator_not_between_digits) << IsAfterDigits; + hadError = true; + } } /// ParseNumberStartingWithZero - This method is called when the first character @@ -840,12 +881,14 @@ void NumericLiteralParser::ParseNumberStartingWithZero(SourceLocation TokLoc) { const char *Exponent = s; s++; saw_exponent = true; - if (*s == '+' || *s == '-') s++; // sign + if (s != ThisTokEnd && (*s == '+' || *s == '-')) s++; // sign const char *first_non_digit = SkipDigits(s); if (!containsDigits(s, first_non_digit)) { - PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, Exponent-ThisTokBegin), - diag::err_exponent_has_no_digits); - hadError = true; + if (!hadError) { + PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, Exponent-ThisTokBegin), + diag::err_exponent_has_no_digits); + hadError = true; + } return; } checkSeparator(TokLoc, s, CSK_BeforeDigits); @@ -882,7 +925,9 @@ void NumericLiteralParser::ParseNumberStartingWithZero(SourceLocation TokLoc) { s = SkipBinaryDigits(s); if (s == ThisTokEnd) { // Done. - } else if (isHexDigit(*s)) { + } else if (isHexDigit(*s) && + !isValidUDSuffix(PP.getLangOpts(), + StringRef(s, ThisTokEnd - s))) { PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, s-ThisTokBegin), diag::err_invalid_digit) << StringRef(s, 1) << 2; hadError = true; @@ -1006,6 +1051,126 @@ NumericLiteralParser::GetFloatValue(llvm::APFloat &Result) { return Result.convertFromString(Str, APFloat::rmNearestTiesToEven); } +static inline bool IsExponentPart(char c) { + return c == 'p' || c == 'P' || c == 'e' || c == 'E'; +} + +bool NumericLiteralParser::GetFixedPointValue(llvm::APInt &StoreVal, unsigned Scale) { + assert(radix == 16 || radix == 10); + + // Find how many digits are needed to store the whole literal. + unsigned NumDigits = SuffixBegin - DigitsBegin; + if (saw_period) --NumDigits; + + // Initial scan of the exponent if it exists + bool ExpOverflowOccurred = false; + bool NegativeExponent = false; + const char *ExponentBegin; + uint64_t Exponent = 0; + int64_t BaseShift = 0; + if (saw_exponent) { + const char *Ptr = DigitsBegin; + + while (!IsExponentPart(*Ptr)) ++Ptr; + ExponentBegin = Ptr; + ++Ptr; + NegativeExponent = *Ptr == '-'; + if (NegativeExponent) ++Ptr; + + unsigned NumExpDigits = SuffixBegin - Ptr; + if (alwaysFitsInto64Bits(radix, NumExpDigits)) { + llvm::StringRef ExpStr(Ptr, NumExpDigits); + llvm::APInt ExpInt(/*numBits=*/64, ExpStr, /*radix=*/10); + Exponent = ExpInt.getZExtValue(); + } else { + ExpOverflowOccurred = true; + } + + if (NegativeExponent) BaseShift -= Exponent; + else BaseShift += Exponent; + } + + // Number of bits needed for decimal literal is + // ceil(NumDigits * log2(10)) Integral part + // + Scale Fractional part + // + ceil(Exponent * log2(10)) Exponent + // -------------------------------------------------- + // ceil((NumDigits + Exponent) * log2(10)) + Scale + // + // But for simplicity in handling integers, we can round up log2(10) to 4, + // making: + // 4 * (NumDigits + Exponent) + Scale + // + // Number of digits needed for hexadecimal literal is + // 4 * NumDigits Integral part + // + Scale Fractional part + // + Exponent Exponent + // -------------------------------------------------- + // (4 * NumDigits) + Scale + Exponent + uint64_t NumBitsNeeded; + if (radix == 10) + NumBitsNeeded = 4 * (NumDigits + Exponent) + Scale; + else + NumBitsNeeded = 4 * NumDigits + Exponent + Scale; + + if (NumBitsNeeded > std::numeric_limits<unsigned>::max()) + ExpOverflowOccurred = true; + llvm::APInt Val(static_cast<unsigned>(NumBitsNeeded), 0, /*isSigned=*/false); + + bool FoundDecimal = false; + + int64_t FractBaseShift = 0; + const char *End = saw_exponent ? ExponentBegin : SuffixBegin; + for (const char *Ptr = DigitsBegin; Ptr < End; ++Ptr) { + if (*Ptr == '.') { + FoundDecimal = true; + continue; + } + + // Normal reading of an integer + unsigned C = llvm::hexDigitValue(*Ptr); + assert(C < radix && "NumericLiteralParser ctor should have rejected this"); + + Val *= radix; + Val += C; + + if (FoundDecimal) + // Keep track of how much we will need to adjust this value by from the + // number of digits past the radix point. + --FractBaseShift; + } + + // For a radix of 16, we will be multiplying by 2 instead of 16. + if (radix == 16) FractBaseShift *= 4; + BaseShift += FractBaseShift; + + Val <<= Scale; + + uint64_t Base = (radix == 16) ? 2 : 10; + if (BaseShift > 0) { + for (int64_t i = 0; i < BaseShift; ++i) { + Val *= Base; + } + } else if (BaseShift < 0) { + for (int64_t i = BaseShift; i < 0 && !Val.isNullValue(); ++i) + Val = Val.udiv(Base); + } + + bool IntOverflowOccurred = false; + auto MaxVal = llvm::APInt::getMaxValue(StoreVal.getBitWidth()); + if (Val.getBitWidth() > StoreVal.getBitWidth()) { + IntOverflowOccurred |= Val.ugt(MaxVal.zext(Val.getBitWidth())); + StoreVal = Val.trunc(StoreVal.getBitWidth()); + } else if (Val.getBitWidth() < StoreVal.getBitWidth()) { + IntOverflowOccurred |= Val.zext(MaxVal.getBitWidth()).ugt(MaxVal); + StoreVal = Val.zext(StoreVal.getBitWidth()); + } else { + StoreVal = Val; + } + + return IntOverflowOccurred || ExpOverflowOccurred; +} + /// \verbatim /// user-defined-character-literal: [C++11 lex.ext] /// character-literal ud-suffix @@ -1585,7 +1750,7 @@ static const char *resyncUTF8(const char *Err, const char *End) { return Err; } -/// \brief This function copies from Fragment, which is a sequence of bytes +/// This function copies from Fragment, which is a sequence of bytes /// within Tok's contents (which begin at TokBegin) into ResultPtr. /// Performs widening for multi-byte characters. bool StringLiteralParser::CopyStringFragment(const Token &Tok, diff --git a/lib/Lex/MacroArgs.cpp b/lib/Lex/MacroArgs.cpp index 5c0f0623c3e17..3b6e2dc2411a0 100644 --- a/lib/Lex/MacroArgs.cpp +++ b/lib/Lex/MacroArgs.cpp @@ -49,7 +49,8 @@ MacroArgs *MacroArgs::create(const MacroInfo *MI, if (!ResultEnt) { // Allocate memory for a MacroArgs object with the lexer tokens at the end, // and construct the MacroArgs object. - Result = new (std::malloc(totalSizeToAlloc<Token>(UnexpArgTokens.size()))) + Result = new ( + llvm::safe_malloc(totalSizeToAlloc<Token>(UnexpArgTokens.size()))) MacroArgs(UnexpArgTokens.size(), VarargsElided, MI->getNumParams()); } else { Result = *ResultEnt; @@ -272,7 +273,7 @@ Token MacroArgs::StringifyArgument(const Token *ArgToks, // If the last character of the string is a \, and if it isn't escaped, this // is an invalid string literal, diagnose it as specified in C99. if (Result.back() == '\\') { - // Count the number of consequtive \ characters. If even, then they are + // Count the number of consecutive \ characters. If even, then they are // just escaped backslashes, otherwise it's an error. unsigned FirstNonSlash = Result.size()-2; // Guaranteed to find the starting " if nothing else. diff --git a/lib/Lex/MacroInfo.cpp b/lib/Lex/MacroInfo.cpp index b13767aa1d673..4ed69ecc465db 100644 --- a/lib/Lex/MacroInfo.cpp +++ b/lib/Lex/MacroInfo.cpp @@ -65,7 +65,7 @@ unsigned MacroInfo::getDefinitionLengthSlow(const SourceManager &SM) const { return DefinitionLength; } -/// \brief Return true if the specified macro definition is equal to +/// Return true if the specified macro definition is equal to /// this macro in spelling, arguments, and whitespace. /// /// \param Syntactically if true, the macro definitions can be identical even diff --git a/lib/Lex/ModuleMap.cpp b/lib/Lex/ModuleMap.cpp index b3ac10c5c5ae8..f048a73a8ccc2 100644 --- a/lib/Lex/ModuleMap.cpp +++ b/lib/Lex/ModuleMap.cpp @@ -54,6 +54,24 @@ using namespace clang; +void ModuleMap::resolveLinkAsDependencies(Module *Mod) { + auto PendingLinkAs = PendingLinkAsModule.find(Mod->Name); + if (PendingLinkAs != PendingLinkAsModule.end()) { + for (auto &Name : PendingLinkAs->second) { + auto *M = findModule(Name.getKey()); + if (M) + M->UseExportAsModuleLinkName = true; + } + } +} + +void ModuleMap::addLinkAsDependency(Module *Mod) { + if (findModule(Mod->ExportAsModule)) + Mod->UseExportAsModuleLinkName = true; + else + PendingLinkAsModule[Mod->ExportAsModule].insert(Mod->Name); +} + Module::HeaderKind ModuleMap::headerRoleToKind(ModuleHeaderRole Role) { switch ((int)Role) { default: llvm_unreachable("unknown header role"); @@ -133,7 +151,7 @@ Module *ModuleMap::resolveModuleId(const ModuleId &Id, Module *Mod, return Context; } -/// \brief Append to \p Paths the set of paths needed to get to the +/// Append to \p Paths the set of paths needed to get to the /// subframework in which the given module lives. static void appendSubframeworkPaths(Module *Mod, SmallVectorImpl<char> &Path) { @@ -152,10 +170,13 @@ static void appendSubframeworkPaths(Module *Mod, llvm::sys::path::append(Path, "Frameworks", Paths[I-1] + ".framework"); } -const FileEntry * -ModuleMap::findHeader(Module *M, - const Module::UnresolvedHeaderDirective &Header, - SmallVectorImpl<char> &RelativePathName) { +const FileEntry *ModuleMap::findHeader( + Module *M, const Module::UnresolvedHeaderDirective &Header, + SmallVectorImpl<char> &RelativePathName, bool &NeedsFramework) { + // Search for the header file within the module's home directory. + auto *Directory = M->Directory; + SmallString<128> FullPathName(Directory->getName()); + auto GetFile = [&](StringRef Filename) -> const FileEntry * { auto *File = SourceMgr.getFileManager().getFile(Filename); if (!File || @@ -165,18 +186,8 @@ ModuleMap::findHeader(Module *M, return File; }; - if (llvm::sys::path::is_absolute(Header.FileName)) { - RelativePathName.clear(); - RelativePathName.append(Header.FileName.begin(), Header.FileName.end()); - return GetFile(Header.FileName); - } - - // Search for the header file within the module's home directory. - auto *Directory = M->Directory; - SmallString<128> FullPathName(Directory->getName()); - unsigned FullPathLength = FullPathName.size(); - - if (M->isPartOfFramework()) { + auto GetFrameworkFile = [&]() -> const FileEntry * { + unsigned FullPathLength = FullPathName.size(); appendSubframeworkPaths(M, RelativePathName); unsigned RelativePathLength = RelativePathName.size(); @@ -201,18 +212,46 @@ ModuleMap::findHeader(Module *M, Header.FileName); llvm::sys::path::append(FullPathName, RelativePathName); return GetFile(FullPathName); + }; + + if (llvm::sys::path::is_absolute(Header.FileName)) { + RelativePathName.clear(); + RelativePathName.append(Header.FileName.begin(), Header.FileName.end()); + return GetFile(Header.FileName); } + if (M->isPartOfFramework()) + return GetFrameworkFile(); + // Lookup for normal headers. llvm::sys::path::append(RelativePathName, Header.FileName); llvm::sys::path::append(FullPathName, RelativePathName); - return GetFile(FullPathName); + auto *NormalHdrFile = GetFile(FullPathName); + + if (M && !NormalHdrFile && Directory->getName().endswith(".framework")) { + // The lack of 'framework' keyword in a module declaration it's a simple + // mistake we can diagnose when the header exists within the proper + // framework style path. + FullPathName.assign(Directory->getName()); + RelativePathName.clear(); + if (GetFrameworkFile()) { + Diags.Report(Header.FileNameLoc, + diag::warn_mmap_incomplete_framework_module_declaration) + << Header.FileName << M->getFullModuleName(); + NeedsFramework = true; + } + return nullptr; + } + + return NormalHdrFile; } void ModuleMap::resolveHeader(Module *Mod, - const Module::UnresolvedHeaderDirective &Header) { + const Module::UnresolvedHeaderDirective &Header, + bool &NeedsFramework) { SmallString<128> RelativePathName; - if (const FileEntry *File = findHeader(Mod, Header, RelativePathName)) { + if (const FileEntry *File = + findHeader(Mod, Header, RelativePathName, NeedsFramework)) { if (Header.IsUmbrella) { const DirectoryEntry *UmbrellaDir = File->getDir(); if (Module *UmbrellaMod = UmbrellaDirs[UmbrellaDir]) @@ -281,6 +320,8 @@ ModuleMap::ModuleMap(SourceManager &SourceMgr, DiagnosticsEngine &Diags, ModuleMap::~ModuleMap() { for (auto &M : Modules) delete M.getValue(); + for (auto *M : ShadowModules) + delete M; } void ModuleMap::setTarget(const TargetInfo &Target) { @@ -289,7 +330,7 @@ void ModuleMap::setTarget(const TargetInfo &Target) { this->Target = &Target; } -/// \brief "Sanitize" a filename so that it can be used as an identifier. +/// "Sanitize" a filename so that it can be used as an identifier. static StringRef sanitizeFilenameAsIdentifier(StringRef Name, SmallVectorImpl<char> &Buffer) { if (Name.empty()) @@ -326,7 +367,7 @@ static StringRef sanitizeFilenameAsIdentifier(StringRef Name, return Name; } -/// \brief Determine whether the given file name is the name of a builtin +/// Determine whether the given file name is the name of a builtin /// header, supplied by Clang to replace, override, or augment existing system /// headers. bool ModuleMap::isBuiltinHeader(StringRef FileName) { @@ -473,7 +514,7 @@ void ModuleMap::diagnoseHeaderInclusion(Module *RequestingModule, // We have found a module, but we don't use it. if (NotUsed) { Diags.Report(FilenameLoc, diag::err_undeclared_use_of_module) - << RequestingModule->getFullModuleName() << Filename; + << RequestingModule->getTopLevelModule()->Name << Filename; return; } @@ -484,7 +525,7 @@ void ModuleMap::diagnoseHeaderInclusion(Module *RequestingModule, if (LangOpts.ModulesStrictDeclUse) { Diags.Report(FilenameLoc, diag::err_undeclared_use_of_module) - << RequestingModule->getFullModuleName() << Filename; + << RequestingModule->getTopLevelModule()->Name << Filename; } else if (RequestingModule && RequestingModuleIsModuleInterface && LangOpts.isCompilingModule()) { // Do not diagnose when we are not compiling a module. @@ -751,7 +792,7 @@ std::pair<Module *, bool> ModuleMap::findOrCreateModule(StringRef Name, // Try to find an existing module with this name. if (Module *Sub = lookupModuleQualified(Name, Parent)) return std::make_pair(Sub, false); - + // Create a new module with this name. Module *Result = new Module(Name, SourceLocation(), Parent, IsFramework, IsExplicit, NumCreatedModules++); @@ -759,6 +800,7 @@ std::pair<Module *, bool> ModuleMap::findOrCreateModule(StringRef Name, if (LangOpts.CurrentModule == Name) SourceModule = Result; Modules[Name] = Result; + ModuleScopeIDs[Result] = CurrentModuleScopeID; } return std::make_pair(Result, true); } @@ -799,7 +841,7 @@ Module *ModuleMap::createModuleForInterfaceUnit(SourceLocation Loc, return Result; } -/// \brief For a framework module, infer the framework against which we +/// For a framework module, infer the framework against which we /// should link. static void inferFrameworkLink(Module *Mod, const DirectoryEntry *FrameworkDir, FileManager &FileMgr) { @@ -927,6 +969,7 @@ Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir, if (LangOpts.CurrentModule == ModuleName) SourceModule = Result; Modules[ModuleName] = Result; + ModuleScopeIDs[Result] = CurrentModuleScopeID; } Result->IsSystem |= Attrs.IsSystem; @@ -999,6 +1042,21 @@ Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir, return Result; } +Module *ModuleMap::createShadowedModule(StringRef Name, bool IsFramework, + Module *ShadowingModule) { + + // Create a new module with this name. + Module *Result = + new Module(Name, SourceLocation(), /*Parent=*/nullptr, IsFramework, + /*IsExplicit=*/false, NumCreatedModules++); + Result->ShadowingModule = ShadowingModule; + Result->IsAvailable = false; + ModuleScopeIDs[Result] = CurrentModuleScopeID; + ShadowModules.push_back(Result); + + return Result; +} + void ModuleMap::setUmbrellaHeader(Module *Mod, const FileEntry *UmbrellaHeader, Twine NameAsWritten) { Headers[UmbrellaHeader].push_back(KnownHeader(Mod, NormalHeader)); @@ -1019,7 +1077,8 @@ void ModuleMap::setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir, } void ModuleMap::addUnresolvedHeader(Module *Mod, - Module::UnresolvedHeaderDirective Header) { + Module::UnresolvedHeaderDirective Header, + bool &NeedsFramework) { // If there is a builtin counterpart to this file, add it now so it can // wrap the system header. if (resolveAsBuiltinHeader(Mod, Header)) { @@ -1050,7 +1109,7 @@ void ModuleMap::addUnresolvedHeader(Module *Mod, // We don't have stat information or can't defer looking this file up. // Perform the lookup now. - resolveHeader(Mod, Header); + resolveHeader(Mod, Header, NeedsFramework); } void ModuleMap::resolveHeaderDirectives(const FileEntry *File) const { @@ -1070,10 +1129,11 @@ void ModuleMap::resolveHeaderDirectives(const FileEntry *File) const { } void ModuleMap::resolveHeaderDirectives(Module *Mod) const { + bool NeedsFramework = false; for (auto &Header : Mod->UnresolvedHeaders) // This operation is logically const; we're just changing how we represent // the header information for this file. - const_cast<ModuleMap*>(this)->resolveHeader(Mod, Header); + const_cast<ModuleMap*>(this)->resolveHeader(Mod, Header, NeedsFramework); Mod->UnresolvedHeaders.clear(); } @@ -1207,7 +1267,7 @@ bool ModuleMap::resolveConflicts(Module *Mod, bool Complain) { namespace clang { - /// \brief A token in a module map file. + /// A token in a module map file. struct MMToken { enum TokenKind { Comma, @@ -1277,37 +1337,40 @@ namespace clang { Lexer &L; SourceManager &SourceMgr; - /// \brief Default target information, used only for string literal + /// Default target information, used only for string literal /// parsing. const TargetInfo *Target; DiagnosticsEngine &Diags; ModuleMap ⤅ - /// \brief The current module map file. + /// The current module map file. const FileEntry *ModuleMapFile; - - /// \brief The directory that file names in this module map file should + + /// Source location of most recent parsed module declaration + SourceLocation CurrModuleDeclLoc; + + /// The directory that file names in this module map file should /// be resolved relative to. const DirectoryEntry *Directory; - /// \brief Whether this module map is in a system header directory. + /// Whether this module map is in a system header directory. bool IsSystem; - /// \brief Whether an error occurred. + /// Whether an error occurred. bool HadError = false; - /// \brief Stores string data for the various string literals referenced + /// Stores string data for the various string literals referenced /// during parsing. llvm::BumpPtrAllocator StringData; - /// \brief The current token. + /// The current token. MMToken Tok; - /// \brief The active module. + /// The active module. Module *ActiveModule = nullptr; - /// \brief Whether a module uses the 'requires excluded' hack to mark its + /// Whether a module uses the 'requires excluded' hack to mark its /// contents as 'textual'. /// /// On older Darwin SDK versions, 'requires excluded' is used to mark the @@ -1317,10 +1380,10 @@ namespace clang { /// 'textual' to match the original intent. llvm::SmallPtrSet<Module *, 2> UsesRequiresExcludedHack; - /// \brief Consume the current token and return its location. + /// Consume the current token and return its location. SourceLocation consumeToken(); - - /// \brief Skip tokens until we reach the a token with the given kind + + /// Skip tokens until we reach the a token with the given kind /// (or the end of the file). void skipUntil(MMToken::TokenKind K); @@ -1340,25 +1403,29 @@ namespace clang { void parseConflict(); void parseInferredModuleDecl(bool Framework, bool Explicit); + /// Private modules are canonicalized as Foo_Private. Clang provides extra + /// module map search logic to find the appropriate private module when PCH + /// is used with implicit module maps. Warn when private modules are written + /// in other ways (FooPrivate and Foo.Private), providing notes and fixits. + void diagnosePrivateModules(SourceLocation ExplicitLoc, + SourceLocation FrameworkLoc); + using Attributes = ModuleMap::Attributes; bool parseOptionalAttributes(Attributes &Attrs); public: - explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr, - const TargetInfo *Target, - DiagnosticsEngine &Diags, - ModuleMap &Map, - const FileEntry *ModuleMapFile, - const DirectoryEntry *Directory, - bool IsSystem) + explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr, + const TargetInfo *Target, DiagnosticsEngine &Diags, + ModuleMap &Map, const FileEntry *ModuleMapFile, + const DirectoryEntry *Directory, bool IsSystem) : L(L), SourceMgr(SourceMgr), Target(Target), Diags(Diags), Map(Map), ModuleMapFile(ModuleMapFile), Directory(Directory), IsSystem(IsSystem) { Tok.clear(); consumeToken(); } - + bool parseModuleMapFile(); bool terminatedByDirective() { return false; } @@ -1559,7 +1626,7 @@ void ModuleMapParser::skipUntil(MMToken::TokenKind K) { } while (true); } -/// \brief Parse a module-id. +/// Parse a module-id. /// /// module-id: /// identifier @@ -1588,21 +1655,21 @@ bool ModuleMapParser::parseModuleId(ModuleId &Id) { namespace { - /// \brief Enumerates the known attributes. + /// Enumerates the known attributes. enum AttributeKind { - /// \brief An unknown attribute. + /// An unknown attribute. AT_unknown, - /// \brief The 'system' attribute. + /// The 'system' attribute. AT_system, - /// \brief The 'extern_c' attribute. + /// The 'extern_c' attribute. AT_extern_c, - /// \brief The 'exhaustive' attribute. + /// The 'exhaustive' attribute. AT_exhaustive, - /// \brief The 'no_undeclared_includes' attribute. + /// The 'no_undeclared_includes' attribute. AT_no_undeclared_includes }; @@ -1612,16 +1679,14 @@ namespace { /// module map search logic to find the appropriate private module when PCH /// is used with implicit module maps. Warn when private modules are written /// in other ways (FooPrivate and Foo.Private), providing notes and fixits. -static void diagnosePrivateModules(const ModuleMap &Map, - DiagnosticsEngine &Diags, - const Module *ActiveModule) { - +void ModuleMapParser::diagnosePrivateModules(SourceLocation ExplicitLoc, + SourceLocation FrameworkLoc) { auto GenNoteAndFixIt = [&](StringRef BadName, StringRef Canonical, - const Module *M) { + const Module *M, SourceRange ReplLoc) { auto D = Diags.Report(ActiveModule->DefinitionLoc, diag::note_mmap_rename_top_level_private_module); D << BadName << M->Name; - D << FixItHint::CreateReplacement(ActiveModule->DefinitionLoc, Canonical); + D << FixItHint::CreateReplacement(ReplLoc, Canonical); }; for (auto E = Map.module_begin(); E != Map.module_end(); ++E) { @@ -1632,6 +1697,7 @@ static void diagnosePrivateModules(const ModuleMap &Map, SmallString<128> FullName(ActiveModule->getFullModuleName()); if (!FullName.startswith(M->Name) && !FullName.endswith("Private")) continue; + SmallString<128> FixedPrivModDecl; SmallString<128> Canonical(M->Name); Canonical.append("_Private"); @@ -1641,7 +1707,20 @@ static void diagnosePrivateModules(const ModuleMap &Map, Diags.Report(ActiveModule->DefinitionLoc, diag::warn_mmap_mismatched_private_submodule) << FullName; - GenNoteAndFixIt(FullName, Canonical, M); + + SourceLocation FixItInitBegin = CurrModuleDeclLoc; + if (FrameworkLoc.isValid()) + FixItInitBegin = FrameworkLoc; + if (ExplicitLoc.isValid()) + FixItInitBegin = ExplicitLoc; + + if (FrameworkLoc.isValid() || ActiveModule->Parent->IsFramework) + FixedPrivModDecl.append("framework "); + FixedPrivModDecl.append("module "); + FixedPrivModDecl.append(Canonical); + + GenNoteAndFixIt(FullName, FixedPrivModDecl, M, + SourceRange(FixItInitBegin, ActiveModule->DefinitionLoc)); continue; } @@ -1651,12 +1730,13 @@ static void diagnosePrivateModules(const ModuleMap &Map, Diags.Report(ActiveModule->DefinitionLoc, diag::warn_mmap_mismatched_private_module_name) << ActiveModule->Name; - GenNoteAndFixIt(ActiveModule->Name, Canonical, M); + GenNoteAndFixIt(ActiveModule->Name, Canonical, M, + SourceRange(ActiveModule->DefinitionLoc)); } } } -/// \brief Parse a module declaration. +/// Parse a module declaration. /// /// module-declaration: /// 'extern' 'module' module-id string-literal @@ -1684,6 +1764,7 @@ void ModuleMapParser::parseModuleDecl() { // Parse 'explicit' or 'framework' keyword, if present. SourceLocation ExplicitLoc; + SourceLocation FrameworkLoc; bool Explicit = false; bool Framework = false; @@ -1695,7 +1776,7 @@ void ModuleMapParser::parseModuleDecl() { // Parse 'framework' keyword, if present. if (Tok.is(MMToken::FrameworkKeyword)) { - consumeToken(); + FrameworkLoc = consumeToken(); Framework = true; } @@ -1706,7 +1787,7 @@ void ModuleMapParser::parseModuleDecl() { HadError = true; return; } - consumeToken(); // 'module' keyword + CurrModuleDeclLoc = consumeToken(); // 'module' keyword // If we have a wildcard for the module name, this is an inferred submodule. // Parse it. @@ -1787,6 +1868,7 @@ void ModuleMapParser::parseModuleDecl() { SourceLocation LBraceLoc = consumeToken(); // Determine whether this (sub)module has already been defined. + Module *ShadowingModule = nullptr; if (Module *Existing = Map.lookupModuleQualified(ModuleName, ActiveModule)) { // We might see a (re)definition of a module that we already have a // definition for in two cases: @@ -1812,23 +1894,35 @@ void ModuleMapParser::parseModuleDecl() { } return; } - - Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition) - << ModuleName; - Diags.Report(Existing->DefinitionLoc, diag::note_mmap_prev_definition); - - // Skip the module definition. - skipUntil(MMToken::RBrace); - if (Tok.is(MMToken::RBrace)) - consumeToken(); - - HadError = true; - return; + + if (!Existing->Parent && Map.mayShadowNewModule(Existing)) { + ShadowingModule = Existing; + } else { + // This is not a shawdowed module decl, it is an illegal redefinition. + Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition) + << ModuleName; + Diags.Report(Existing->DefinitionLoc, diag::note_mmap_prev_definition); + + // Skip the module definition. + skipUntil(MMToken::RBrace); + if (Tok.is(MMToken::RBrace)) + consumeToken(); + + HadError = true; + return; + } } // Start defining this module. - ActiveModule = Map.findOrCreateModule(ModuleName, ActiveModule, Framework, - Explicit).first; + if (ShadowingModule) { + ActiveModule = + Map.createShadowedModule(ModuleName, Framework, ShadowingModule); + } else { + ActiveModule = + Map.findOrCreateModule(ModuleName, ActiveModule, Framework, Explicit) + .first; + } + ActiveModule->DefinitionLoc = ModuleNameLoc; if (Attrs.IsSystem || IsSystem) ActiveModule->IsSystem = true; @@ -1839,21 +1933,24 @@ void ModuleMapParser::parseModuleDecl() { ActiveModule->NoUndeclaredIncludes = true; ActiveModule->Directory = Directory; + StringRef MapFileName(ModuleMapFile->getName()); + if (MapFileName.endswith("module.private.modulemap") || + MapFileName.endswith("module_private.map")) { + ActiveModule->ModuleMapIsPrivate = true; + } // Private modules named as FooPrivate, Foo.Private or similar are likely a // user error; provide warnings, notes and fixits to direct users to use // Foo_Private instead. SourceLocation StartLoc = SourceMgr.getLocForStartOfFile(SourceMgr.getMainFileID()); - StringRef MapFileName(ModuleMapFile->getName()); if (Map.HeaderInfo.getHeaderSearchOpts().ImplicitModuleMaps && !Diags.isIgnored(diag::warn_mmap_mismatched_private_submodule, StartLoc) && !Diags.isIgnored(diag::warn_mmap_mismatched_private_module_name, StartLoc) && - (MapFileName.endswith("module.private.modulemap") || - MapFileName.endswith("module_private.map"))) - diagnosePrivateModules(Map, Diags, ActiveModule); + ActiveModule->ModuleMapIsPrivate) + diagnosePrivateModules(ExplicitLoc, FrameworkLoc); bool Done = false; do { @@ -1958,7 +2055,7 @@ void ModuleMapParser::parseModuleDecl() { ActiveModule = PreviousActiveModule; } -/// \brief Parse an extern module declaration. +/// Parse an extern module declaration. /// /// extern module-declaration: /// 'extern' 'module' module-id string-literal @@ -2036,7 +2133,7 @@ static bool shouldAddRequirement(Module *M, StringRef Feature, return true; } -/// \brief Parse a requires declaration. +/// Parse a requires declaration. /// /// requires-declaration: /// 'requires' feature-list @@ -2092,7 +2189,7 @@ void ModuleMapParser::parseRequiresDecl() { } while (true); } -/// \brief Parse a header declaration. +/// Parse a header declaration. /// /// header-declaration: /// 'textual'[opt] 'header' string-literal @@ -2212,7 +2309,13 @@ void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken, } } - Map.addUnresolvedHeader(ActiveModule, std::move(Header)); + bool NeedsFramework = false; + Map.addUnresolvedHeader(ActiveModule, std::move(Header), NeedsFramework); + + if (NeedsFramework && ActiveModule) + Diags.Report(CurrModuleDeclLoc, diag::note_mmap_add_framework_keyword) + << ActiveModule->getFullModuleName() + << FixItHint::CreateReplacement(CurrModuleDeclLoc, "framework module"); } static int compareModuleHeaders(const Module::Header *A, @@ -2220,7 +2323,7 @@ static int compareModuleHeaders(const Module::Header *A, return A->NameAsWritten.compare(B->NameAsWritten); } -/// \brief Parse an umbrella directory declaration. +/// Parse an umbrella directory declaration. /// /// umbrella-dir-declaration: /// umbrella string-literal @@ -2298,7 +2401,7 @@ void ModuleMapParser::parseUmbrellaDirDecl(SourceLocation UmbrellaLoc) { Map.setUmbrellaDir(ActiveModule, Dir, DirName); } -/// \brief Parse a module export declaration. +/// Parse a module export declaration. /// /// export-declaration: /// 'export' wildcard-module-id @@ -2346,7 +2449,7 @@ void ModuleMapParser::parseExportDecl() { ActiveModule->UnresolvedExports.push_back(Unresolved); } -/// \brief Parse a module export_as declaration. +/// Parse a module export_as declaration. /// /// export-as-declaration: /// 'export_as' identifier @@ -2378,10 +2481,12 @@ void ModuleMapParser::parseExportAsDecl() { } ActiveModule->ExportAsModule = Tok.getString(); + Map.addLinkAsDependency(ActiveModule); + consumeToken(); } -/// \brief Parse a module use declaration. +/// Parse a module use declaration. /// /// use-declaration: /// 'use' wildcard-module-id @@ -2398,7 +2503,7 @@ void ModuleMapParser::parseUseDecl() { ActiveModule->UnresolvedDirectUses.push_back(ParsedModuleId); } -/// \brief Parse a link declaration. +/// Parse a link declaration. /// /// module-declaration: /// 'link' 'framework'[opt] string-literal @@ -2427,7 +2532,7 @@ void ModuleMapParser::parseLinkDecl() { IsFramework)); } -/// \brief Parse a configuration macro declaration. +/// Parse a configuration macro declaration. /// /// module-declaration: /// 'config_macros' attributes[opt] config-macro-list? @@ -2484,7 +2589,7 @@ void ModuleMapParser::parseConfigMacros() { } while (true); } -/// \brief Format a module-id into a string. +/// Format a module-id into a string. static std::string formatModuleId(const ModuleId &Id) { std::string result; { @@ -2500,7 +2605,7 @@ static std::string formatModuleId(const ModuleId &Id) { return result; } -/// \brief Parse a conflict declaration. +/// Parse a conflict declaration. /// /// module-declaration: /// 'conflict' module-id ',' string-literal @@ -2534,7 +2639,7 @@ void ModuleMapParser::parseConflict() { ActiveModule->UnresolvedConflicts.push_back(Conflict); } -/// \brief Parse an inferred module declaration (wildcard modules). +/// Parse an inferred module declaration (wildcard modules). /// /// module-declaration: /// 'explicit'[opt] 'framework'[opt] 'module' * attributes[opt] @@ -2687,7 +2792,7 @@ void ModuleMapParser::parseInferredModuleDecl(bool Framework, bool Explicit) { } } -/// \brief Parse optional attributes. +/// Parse optional attributes. /// /// attributes: /// attribute attributes @@ -2762,7 +2867,7 @@ bool ModuleMapParser::parseOptionalAttributes(Attributes &Attrs) { return HadError; } -/// \brief Parse a module map file. +/// Parse a module map file. /// /// module-map-file: /// module-declaration* @@ -2854,5 +2959,6 @@ bool ModuleMap::parseModuleMapFile(const FileEntry *File, bool IsSystem, // Notify callbacks that we parsed it. for (const auto &Cb : Callbacks) Cb->moduleMapFileRead(Start, *File, IsSystem); + return Result; } diff --git a/lib/Lex/PPCaching.cpp b/lib/Lex/PPCaching.cpp index f5e8cdc25d388..9758557d7b448 100644 --- a/lib/Lex/PPCaching.cpp +++ b/lib/Lex/PPCaching.cpp @@ -105,8 +105,10 @@ void Preprocessor::CachingLex(Token &Result) { } void Preprocessor::EnterCachingLexMode() { - if (InCachingLexMode()) + if (InCachingLexMode()) { + assert(CurLexerKind == CLK_CachingLexer && "Unexpected lexer kind"); return; + } PushIncludeMacroStack(); CurLexerKind = CLK_CachingLexer; diff --git a/lib/Lex/PPDirectives.cpp b/lib/Lex/PPDirectives.cpp index ca3e70fd1060e..d8dae73037a89 100644 --- a/lib/Lex/PPDirectives.cpp +++ b/lib/Lex/PPDirectives.cpp @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// /// /// \file -/// \brief Implements # directive processing for the Preprocessor. +/// Implements # directive processing for the Preprocessor. /// //===----------------------------------------------------------------------===// @@ -78,7 +78,7 @@ Preprocessor::AllocateVisibilityMacroDirective(SourceLocation Loc, return new (BP) VisibilityMacroDirective(Loc, isPublic); } -/// \brief Read and discard all tokens remaining on the current line until +/// Read and discard all tokens remaining on the current line until /// the tok::eod token is found. void Preprocessor::DiscardUntilEndOfDirective() { Token Tmp; @@ -88,14 +88,14 @@ void Preprocessor::DiscardUntilEndOfDirective() { } while (Tmp.isNot(tok::eod)); } -/// \brief Enumerates possible cases of #define/#undef a reserved identifier. +/// Enumerates possible cases of #define/#undef a reserved identifier. enum MacroDiag { MD_NoWarn, //> Not a reserved identifier MD_KeywordDef, //> Macro hides keyword, enabled by default MD_ReservedMacro //> #define of #undef reserved id, disabled by default }; -/// \brief Checks if the specified identifier is reserved in the specified +/// Checks if the specified identifier is reserved in the specified /// language. /// This function does not check if the identifier is a keyword. static bool isReservedId(StringRef Text, const LangOptions &Lang) { @@ -115,6 +115,25 @@ static bool isReservedId(StringRef Text, const LangOptions &Lang) { return false; } +// The -fmodule-name option tells the compiler to textually include headers in +// the specified module, meaning clang won't build the specified module. This is +// useful in a number of situations, for instance, when building a library that +// vends a module map, one might want to avoid hitting intermediate build +// products containig the the module map or avoid finding the system installed +// modulemap for that library. +static bool isForModuleBuilding(Module *M, StringRef CurrentModule, + StringRef ModuleName) { + StringRef TopLevelName = M->getTopLevelModuleName(); + + // When building framework Foo, we wanna make sure that Foo *and* Foo_Private + // are textually included and no modules are built for both. + if (M->getTopLevelModule()->IsFramework && CurrentModule == ModuleName && + !CurrentModule.endswith("_Private") && TopLevelName.endswith("_Private")) + TopLevelName = TopLevelName.drop_back(8); + + return TopLevelName == CurrentModule; +} + static MacroDiag shouldWarnOnMacroDef(Preprocessor &PP, IdentifierInfo *II) { const LangOptions &Lang = PP.getLangOpts(); StringRef Text = II->getName(); @@ -277,7 +296,7 @@ bool Preprocessor::CheckMacroName(Token &MacroNameTok, MacroUse isDefineUndef, return false; } -/// \brief Lex and validate a macro name, which occurs after a +/// Lex and validate a macro name, which occurs after a /// \#define or \#undef. /// /// This sets the token kind to eod and discards the rest of the macro line if @@ -309,7 +328,7 @@ void Preprocessor::ReadMacroName(Token &MacroNameTok, MacroUse isDefineUndef, } } -/// \brief Ensure that the next token is a tok::eod token. +/// Ensure that the next token is a tok::eod token. /// /// If not, emit a diagnostic and consume up until the eod. If EnableMacros is /// true, then we consider macros that expand to zero tokens as being ok. @@ -558,7 +577,9 @@ void Preprocessor::SkipExcludedConditionalBlock(SourceLocation HashTokenLoc, // the #if block. CurPPLexer->LexingRawMode = false; - if (Callbacks) + // The last skipped range isn't actually skipped yet if it's truncated + // by the end of the preamble; we'll resume parsing after the preamble. + if (Callbacks && (Tok.isNot(tok::eof) || !isRecordingPreamble())) Callbacks->SourceRangeSkipped( SourceRange(HashTokenLoc, CurPPLexer->getSourceLocation()), Tok.getLocation()); @@ -866,6 +887,22 @@ private: bool save; }; +/// Process a directive while looking for the through header. +/// Only #include (to check if it is the through header) and #define (to warn +/// about macros that don't match the PCH) are handled. All other directives +/// are completely discarded. +void Preprocessor::HandleSkippedThroughHeaderDirective(Token &Result, + SourceLocation HashLoc) { + if (const IdentifierInfo *II = Result.getIdentifierInfo()) { + if (II->getPPKeywordID() == tok::pp_include) + return HandleIncludeDirective(HashLoc, Result); + if (II->getPPKeywordID() == tok::pp_define) + return HandleDefineDirective(Result, + /*ImmediatelyAfterHeaderGuard=*/false); + } + DiscardUntilEndOfDirective(); +} + /// HandleDirective - This callback is invoked when the lexer sees a # token /// at the start of a line. This consumes the directive, modifies the /// lexer/preprocessor state, and advances the lexer(s) so that the next token @@ -927,6 +964,9 @@ void Preprocessor::HandleDirective(Token &Result) { // and reset to previous state when returning from this function. ResetMacroExpansionHelper helper(this); + if (SkippingUntilPCHThroughHeader) + return HandleSkippedThroughHeaderDirective(Result, SavedHash.getLocation()); + switch (Result.getKind()) { case tok::eod: return; // null directive. @@ -1107,7 +1147,7 @@ static bool GetLineValue(Token &DigitTok, unsigned &Val, return false; } -/// \brief Handle a \#line directive: C99 6.10.4. +/// Handle a \#line directive: C99 6.10.4. /// /// The two acceptable forms are: /// \verbatim @@ -1343,7 +1383,7 @@ void Preprocessor::HandleUserDiagnosticDirective(Token &Tok, // Read the rest of the line raw. We do this because we don't want macros // to be expanded and we don't require that the tokens be valid preprocessing // tokens. For example, this is allowed: "#warning ` 'foo". GCC does - // collapse multiple consequtive white space between tokens, but this isn't + // collapse multiple consecutive white space between tokens, but this isn't // specified by the standard. SmallString<128> Message; CurLexer->ReadToEndOfLine(&Message); @@ -1393,7 +1433,7 @@ void Preprocessor::HandleIdentSCCSDirective(Token &Tok) { } } -/// \brief Handle a #public directive. +/// Handle a #public directive. void Preprocessor::HandleMacroPublicDirective(Token &Tok) { Token MacroNameTok; ReadMacroName(MacroNameTok, MU_Undef); @@ -1420,7 +1460,7 @@ void Preprocessor::HandleMacroPublicDirective(Token &Tok) { MacroNameTok.getLocation(), /*IsPublic=*/true)); } -/// \brief Handle a #private directive. +/// Handle a #private directive. void Preprocessor::HandleMacroPrivateDirective() { Token MacroNameTok; ReadMacroName(MacroNameTok, MU_Undef); @@ -1496,7 +1536,7 @@ bool Preprocessor::GetIncludeFilenameSpelling(SourceLocation Loc, return isAngled; } -// \brief Handle cases where the \#include name is expanded from a macro +// Handle cases where the \#include name is expanded from a macro // as multiple tokens, which need to be glued together. // // This occurs for code like: @@ -1557,7 +1597,7 @@ bool Preprocessor::ConcatenateIncludeName(SmallString<128> &FilenameBuffer, return true; } -/// \brief Push a token onto the token stream containing an annotation. +/// Push a token onto the token stream containing an annotation. void Preprocessor::EnterAnnotationToken(SourceRange Range, tok::TokenKind Kind, void *AnnotationVal) { @@ -1572,7 +1612,7 @@ void Preprocessor::EnterAnnotationToken(SourceRange Range, EnterTokenStream(std::move(Tok), 1, true); } -/// \brief Produce a diagnostic informing the user that a #include or similar +/// Produce a diagnostic informing the user that a #include or similar /// was implicitly treated as a module import. static void diagnoseAutoModuleImport( Preprocessor &PP, SourceLocation HashLoc, Token &IncludeTok, @@ -1655,12 +1695,18 @@ bool Preprocessor::checkModuleIsAvailable(const LangOptions &LangOpts, DiagnosticsEngine &Diags, Module *M) { Module::Requirement Requirement; Module::UnresolvedHeaderDirective MissingHeader; - if (M->isAvailable(LangOpts, TargetInfo, Requirement, MissingHeader)) + Module *ShadowingModule = nullptr; + if (M->isAvailable(LangOpts, TargetInfo, Requirement, MissingHeader, + ShadowingModule)) return false; if (MissingHeader.FileNameLoc.isValid()) { Diags.Report(MissingHeader.FileNameLoc, diag::err_module_header_missing) << MissingHeader.IsUmbrella << MissingHeader.FileName; + } else if (ShadowingModule) { + Diags.Report(M->DefinitionLoc, diag::err_module_shadowed) << M->Name; + Diags.Report(ShadowingModule->DefinitionLoc, + diag::note_previous_definition); } else { // FIXME: Track the location at which the requirement was specified, and // use it here. @@ -1779,7 +1825,7 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc, SmallString<128> NormalizedPath; if (LangOpts.MSVCCompat) { NormalizedPath = Filename.str(); -#ifndef LLVM_ON_WIN32 +#ifndef _WIN32 llvm::sys::path::native(NormalizedPath); #endif } @@ -1835,6 +1881,12 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc, } } + if (usingPCHWithThroughHeader() && SkippingUntilPCHThroughHeader) { + if (isPCHThroughHeader(File)) + SkippingUntilPCHThroughHeader = false; + return; + } + // Should we enter the source file? Set to false if either the source file is // known to have no effect beyond its effect on module visibility -- that is, // if it's got an include guard that is already defined or is a modular header @@ -1844,12 +1896,19 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc, if (PPOpts->SingleFileParseMode) ShouldEnter = false; + // Any diagnostics after the fatal error will not be visible. As the + // compilation failed already and errors in subsequently included files won't + // be visible, avoid preprocessing those files. + if (ShouldEnter && Diags->hasFatalErrorOccurred()) + ShouldEnter = false; + // Determine whether we should try to import the module for this #include, if // there is one. Don't do so if precompiled module support is disabled or we // are processing this module textually (because we're building the module). if (ShouldEnter && File && SuggestedModule && getLangOpts().Modules && - SuggestedModule.getModule()->getTopLevelModuleName() != - getLangOpts().CurrentModule) { + !isForModuleBuilding(SuggestedModule.getModule(), + getLangOpts().CurrentModule, + getLangOpts().ModuleName)) { // If this include corresponds to a module but that module is // unavailable, diagnose the situation and bail out. // FIXME: Remove this; loadModule does the same check (but produces @@ -1940,7 +1999,7 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc, HashLoc, IncludeTok, LangOpts.MSVCCompat ? NormalizedPath.c_str() : Filename, isAngled, FilenameRange, File, SearchPath, RelativePath, - ShouldEnter ? nullptr : SuggestedModule.getModule()); + ShouldEnter ? nullptr : SuggestedModule.getModule(), FileCharacter); if (SkipHeader && !SuggestedModule.getModule()) Callbacks->FileSkipped(*File, FilenameTok, FileCharacter); } @@ -1996,7 +2055,8 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc, // ShouldEnter is false because we are skipping the header. In that // case, We are not importing the specified module. if (SkipHeader && getLangOpts().CompilingPCH && - M->getTopLevelModuleName() == getLangOpts().CurrentModule) + isForModuleBuilding(M, getLangOpts().CurrentModule, + getLangOpts().ModuleName)) return; makeModuleVisible(M, HashLoc); @@ -2014,7 +2074,7 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc, // If the filename string was the result of macro expansions, set the include // position on the file where it will be included and after the expansions. if (IncludePos.isMacroID()) - IncludePos = SourceMgr.getExpansionRange(IncludePos).second; + IncludePos = SourceMgr.getExpansionRange(IncludePos).getEnd(); FileID FID = SourceMgr.createFileID(File, IncludePos, FileCharacter); assert(FID.isValid() && "Expected valid file ID"); @@ -2024,11 +2084,21 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc, // Determine if we're switching to building a new submodule, and which one. if (auto *M = SuggestedModule.getModule()) { + if (M->getTopLevelModule()->ShadowingModule) { + // We are building a submodule that belongs to a shadowed module. This + // means we find header files in the shadowed module. + Diag(M->DefinitionLoc, diag::err_module_build_shadowed_submodule) + << M->getFullModuleName(); + Diag(M->getTopLevelModule()->ShadowingModule->DefinitionLoc, + diag::note_previous_definition); + return; + } // When building a pch, -fmodule-name tells the compiler to textually // include headers in the specified module. We are not building the // specified module. if (getLangOpts().CompilingPCH && - M->getTopLevelModuleName() == getLangOpts().CurrentModule) + isForModuleBuilding(M, getLangOpts().CurrentModule, + getLangOpts().ModuleName)) return; assert(!CurLexerSubmodule && "should not have marked this as a module yet"); @@ -2548,7 +2618,15 @@ void Preprocessor::HandleDefineDirective( } } - + // When skipping just warn about macros that do not match. + if (SkippingUntilPCHThroughHeader) { + const MacroInfo *OtherMI = getMacroInfo(MacroNameTok.getIdentifierInfo()); + if (!OtherMI || !MI->isIdenticalTo(*OtherMI, *this, + /*Syntactic=*/LangOpts.MicrosoftExt)) + Diag(MI->getDefinitionLoc(), diag::warn_pp_macro_def_mismatch_with_pch) + << MacroNameTok.getIdentifierInfo(); + return; + } // Finally, if this identifier already had a macro defined for it, verify that // the macro bodies are identical, and issue diagnostics if they are not. diff --git a/lib/Lex/PPExpressions.cpp b/lib/Lex/PPExpressions.cpp index d8431827e9cde..b1ed0e10c6fc7 100644 --- a/lib/Lex/PPExpressions.cpp +++ b/lib/Lex/PPExpressions.cpp @@ -363,7 +363,7 @@ static bool EvaluateValue(PPValue &Result, Token &PeekTok, DefinedTracker &DT, NumBits = TI.getChar16Width(); else if (Literal.isUTF32()) NumBits = TI.getChar32Width(); - else + else // char or char8_t NumBits = TI.getCharWidth(); // Set the width. diff --git a/lib/Lex/PPLexerChange.cpp b/lib/Lex/PPLexerChange.cpp index e484e9c4c3a38..352814d715fa9 100644 --- a/lib/Lex/PPLexerChange.cpp +++ b/lib/Lex/PPLexerChange.cpp @@ -13,6 +13,7 @@ //===----------------------------------------------------------------------===// #include "clang/Lex/Preprocessor.h" +#include "clang/Lex/PreprocessorOptions.h" #include "clang/Basic/FileManager.h" #include "clang/Basic/SourceManager.h" #include "clang/Lex/HeaderSearch.h" @@ -226,7 +227,7 @@ void Preprocessor::EnterTokenStream(const Token *Toks, unsigned NumToks, CurLexerKind = CLK_TokenLexer; } -/// \brief Compute the relative path that names the given file relative to +/// Compute the relative path that names the given file relative to /// the given directory. static void computeRelativePath(FileManager &FM, const DirectoryEntry *Dir, const FileEntry *File, @@ -264,7 +265,7 @@ void Preprocessor::PropagateLineStartLeadingSpaceInfo(Token &Result) { // but it might if they're empty? } -/// \brief Determine the location to use as the end of the buffer for a lexer. +/// Determine the location to use as the end of the buffer for a lexer. /// /// If the file ends with a newline, form the EOF token on the newline itself, /// rather than "on the line following it", which doesn't exist. This makes @@ -425,6 +426,8 @@ bool Preprocessor::HandleEndOfFile(Token &Result, bool isEndOfMacro) { PragmaAssumeNonNullLoc = SourceLocation(); } + bool LeavingPCHThroughHeader = false; + // If this is a #include'd file, pop it off the include stack and continue // lexing the #includer file. if (!IncludeMacroStack.empty()) { @@ -444,6 +447,7 @@ bool Preprocessor::HandleEndOfFile(Token &Result, bool isEndOfMacro) { } CurPPLexer = nullptr; + recomputeCurLexerKind(); return true; } @@ -480,6 +484,12 @@ bool Preprocessor::HandleEndOfFile(Token &Result, bool isEndOfMacro) { Result.setAnnotationValue(M); } + bool FoundPCHThroughHeader = false; + if (CurPPLexer && creatingPCHWithThroughHeader() && + isPCHThroughHeader( + SourceMgr.getFileEntryForID(CurPPLexer->getFileID()))) + FoundPCHThroughHeader = true; + // We're done with the #included file. RemoveTopOfLexerStack(); @@ -499,8 +509,16 @@ bool Preprocessor::HandleEndOfFile(Token &Result, bool isEndOfMacro) { if (ExitedFromPredefinesFile) replayPreambleConditionalStack(); - // Client should lex another token unless we generated an EOM. - return LeavingSubmodule; + if (!isEndOfMacro && CurPPLexer && FoundPCHThroughHeader && + (isInPrimaryFile() || + CurPPLexer->getFileID() == getPredefinesFileID())) { + // Leaving the through header. Continue directly to end of main file + // processing. + LeavingPCHThroughHeader = true; + } else { + // Client should lex another token unless we generated an EOM. + return LeavingSubmodule; + } } // If this is the end of the main file, form an EOF token. @@ -521,6 +539,12 @@ bool Preprocessor::HandleEndOfFile(Token &Result, bool isEndOfMacro) { Result.setLocation(Result.getLocation().getLocWithOffset(-1)); } + if (creatingPCHWithThroughHeader() && !LeavingPCHThroughHeader) { + // Reached the end of the compilation without finding the through header. + Diag(CurLexer->getFileLoc(), diag::err_pp_through_header_not_seen) + << PPOpts->PCHThroughHeader << 0; + } + if (!isIncrementalProcessingEnabled()) // We're done with lexing. CurLexer.reset(); diff --git a/lib/Lex/PPMacroExpansion.cpp b/lib/Lex/PPMacroExpansion.cpp index 41633f90c34da..d9992e00f8c0f 100644 --- a/lib/Lex/PPMacroExpansion.cpp +++ b/lib/Lex/PPMacroExpansion.cpp @@ -41,7 +41,6 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSwitch.h" -#include "llvm/Config/llvm-config.h" #include "llvm/Support/Casting.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Format.h" @@ -1016,7 +1015,7 @@ MacroArgs *Preprocessor::ReadMacroCallArgumentList(Token &MacroName, return MacroArgs::create(MI, ArgTokens, isVarargsElided, *this); } -/// \brief Keeps macro expanded tokens for TokenLexers. +/// Keeps macro expanded tokens for TokenLexers. // /// Works like a stack; a TokenLexer adds the macro expanded tokens that is /// going to lex in the cache and when it finishes the tokens are removed @@ -1100,183 +1099,11 @@ static bool HasFeature(const Preprocessor &PP, StringRef Feature) { if (Feature.startswith("__") && Feature.endswith("__") && Feature.size() >= 4) Feature = Feature.substr(2, Feature.size() - 4); +#define FEATURE(Name, Predicate) .Case(#Name, Predicate) return llvm::StringSwitch<bool>(Feature) - .Case("address_sanitizer", - LangOpts.Sanitize.hasOneOf(SanitizerKind::Address | - SanitizerKind::KernelAddress)) - .Case("hwaddress_sanitizer", - LangOpts.Sanitize.hasOneOf(SanitizerKind::HWAddress)) - .Case("assume_nonnull", true) - .Case("attribute_analyzer_noreturn", true) - .Case("attribute_availability", true) - .Case("attribute_availability_with_message", true) - .Case("attribute_availability_app_extension", true) - .Case("attribute_availability_with_version_underscores", true) - .Case("attribute_availability_tvos", true) - .Case("attribute_availability_watchos", true) - .Case("attribute_availability_with_strict", true) - .Case("attribute_availability_with_replacement", true) - .Case("attribute_availability_in_templates", true) - .Case("attribute_cf_returns_not_retained", true) - .Case("attribute_cf_returns_retained", true) - .Case("attribute_cf_returns_on_parameters", true) - .Case("attribute_deprecated_with_message", true) - .Case("attribute_deprecated_with_replacement", true) - .Case("attribute_ext_vector_type", true) - .Case("attribute_ns_returns_not_retained", true) - .Case("attribute_ns_returns_retained", true) - .Case("attribute_ns_consumes_self", true) - .Case("attribute_ns_consumed", true) - .Case("attribute_cf_consumed", true) - .Case("attribute_objc_ivar_unused", true) - .Case("attribute_objc_method_family", true) - .Case("attribute_overloadable", true) - .Case("attribute_unavailable_with_message", true) - .Case("attribute_unused_on_fields", true) - .Case("attribute_diagnose_if_objc", true) - .Case("blocks", LangOpts.Blocks) - .Case("c_thread_safety_attributes", true) - .Case("cxx_exceptions", LangOpts.CXXExceptions) - .Case("cxx_rtti", LangOpts.RTTI && LangOpts.RTTIData) - .Case("enumerator_attributes", true) - .Case("nullability", true) - .Case("nullability_on_arrays", true) - .Case("memory_sanitizer", LangOpts.Sanitize.has(SanitizerKind::Memory)) - .Case("thread_sanitizer", LangOpts.Sanitize.has(SanitizerKind::Thread)) - .Case("dataflow_sanitizer", - LangOpts.Sanitize.has(SanitizerKind::DataFlow)) - .Case("efficiency_sanitizer", - LangOpts.Sanitize.hasOneOf(SanitizerKind::Efficiency)) - .Case("scudo", LangOpts.Sanitize.hasOneOf(SanitizerKind::Scudo)) - // Objective-C features - .Case("objc_arr", LangOpts.ObjCAutoRefCount) // FIXME: REMOVE? - .Case("objc_arc", LangOpts.ObjCAutoRefCount) - .Case("objc_arc_weak", LangOpts.ObjCWeak) - .Case("objc_default_synthesize_properties", LangOpts.ObjC2) - .Case("objc_fixed_enum", LangOpts.ObjC2) - .Case("objc_instancetype", LangOpts.ObjC2) - .Case("objc_kindof", LangOpts.ObjC2) - .Case("objc_modules", LangOpts.ObjC2 && LangOpts.Modules) - .Case("objc_nonfragile_abi", LangOpts.ObjCRuntime.isNonFragile()) - .Case("objc_property_explicit_atomic", - true) // Does clang support explicit "atomic" keyword? - .Case("objc_protocol_qualifier_mangling", true) - .Case("objc_weak_class", LangOpts.ObjCRuntime.hasWeakClassImport()) - .Case("ownership_holds", true) - .Case("ownership_returns", true) - .Case("ownership_takes", true) - .Case("objc_bool", true) - .Case("objc_subscripting", LangOpts.ObjCRuntime.isNonFragile()) - .Case("objc_array_literals", LangOpts.ObjC2) - .Case("objc_dictionary_literals", LangOpts.ObjC2) - .Case("objc_boxed_expressions", LangOpts.ObjC2) - .Case("objc_boxed_nsvalue_expressions", LangOpts.ObjC2) - .Case("arc_cf_code_audited", true) - .Case("objc_bridge_id", true) - .Case("objc_bridge_id_on_typedefs", true) - .Case("objc_generics", LangOpts.ObjC2) - .Case("objc_generics_variance", LangOpts.ObjC2) - .Case("objc_class_property", LangOpts.ObjC2) - // C11 features - .Case("c_alignas", LangOpts.C11) - .Case("c_alignof", LangOpts.C11) - .Case("c_atomic", LangOpts.C11) - .Case("c_generic_selections", LangOpts.C11) - .Case("c_static_assert", LangOpts.C11) - .Case("c_thread_local", - LangOpts.C11 && PP.getTargetInfo().isTLSSupported()) - // C++11 features - .Case("cxx_access_control_sfinae", LangOpts.CPlusPlus11) - .Case("cxx_alias_templates", LangOpts.CPlusPlus11) - .Case("cxx_alignas", LangOpts.CPlusPlus11) - .Case("cxx_alignof", LangOpts.CPlusPlus11) - .Case("cxx_atomic", LangOpts.CPlusPlus11) - .Case("cxx_attributes", LangOpts.CPlusPlus11) - .Case("cxx_auto_type", LangOpts.CPlusPlus11) - .Case("cxx_constexpr", LangOpts.CPlusPlus11) - .Case("cxx_constexpr_string_builtins", LangOpts.CPlusPlus11) - .Case("cxx_decltype", LangOpts.CPlusPlus11) - .Case("cxx_decltype_incomplete_return_types", LangOpts.CPlusPlus11) - .Case("cxx_default_function_template_args", LangOpts.CPlusPlus11) - .Case("cxx_defaulted_functions", LangOpts.CPlusPlus11) - .Case("cxx_delegating_constructors", LangOpts.CPlusPlus11) - .Case("cxx_deleted_functions", LangOpts.CPlusPlus11) - .Case("cxx_explicit_conversions", LangOpts.CPlusPlus11) - .Case("cxx_generalized_initializers", LangOpts.CPlusPlus11) - .Case("cxx_implicit_moves", LangOpts.CPlusPlus11) - .Case("cxx_inheriting_constructors", LangOpts.CPlusPlus11) - .Case("cxx_inline_namespaces", LangOpts.CPlusPlus11) - .Case("cxx_lambdas", LangOpts.CPlusPlus11) - .Case("cxx_local_type_template_args", LangOpts.CPlusPlus11) - .Case("cxx_nonstatic_member_init", LangOpts.CPlusPlus11) - .Case("cxx_noexcept", LangOpts.CPlusPlus11) - .Case("cxx_nullptr", LangOpts.CPlusPlus11) - .Case("cxx_override_control", LangOpts.CPlusPlus11) - .Case("cxx_range_for", LangOpts.CPlusPlus11) - .Case("cxx_raw_string_literals", LangOpts.CPlusPlus11) - .Case("cxx_reference_qualified_functions", LangOpts.CPlusPlus11) - .Case("cxx_rvalue_references", LangOpts.CPlusPlus11) - .Case("cxx_strong_enums", LangOpts.CPlusPlus11) - .Case("cxx_static_assert", LangOpts.CPlusPlus11) - .Case("cxx_thread_local", - LangOpts.CPlusPlus11 && PP.getTargetInfo().isTLSSupported()) - .Case("cxx_trailing_return", LangOpts.CPlusPlus11) - .Case("cxx_unicode_literals", LangOpts.CPlusPlus11) - .Case("cxx_unrestricted_unions", LangOpts.CPlusPlus11) - .Case("cxx_user_literals", LangOpts.CPlusPlus11) - .Case("cxx_variadic_templates", LangOpts.CPlusPlus11) - // C++14 features - .Case("cxx_aggregate_nsdmi", LangOpts.CPlusPlus14) - .Case("cxx_binary_literals", LangOpts.CPlusPlus14) - .Case("cxx_contextual_conversions", LangOpts.CPlusPlus14) - .Case("cxx_decltype_auto", LangOpts.CPlusPlus14) - .Case("cxx_generic_lambdas", LangOpts.CPlusPlus14) - .Case("cxx_init_captures", LangOpts.CPlusPlus14) - .Case("cxx_relaxed_constexpr", LangOpts.CPlusPlus14) - .Case("cxx_return_type_deduction", LangOpts.CPlusPlus14) - .Case("cxx_variable_templates", LangOpts.CPlusPlus14) - // NOTE: For features covered by SD-6, it is preferable to provide *only* - // the SD-6 macro and not a __has_feature check. - - // C++ TSes - //.Case("cxx_runtime_arrays", LangOpts.CPlusPlusTSArrays) - //.Case("cxx_concepts", LangOpts.CPlusPlusTSConcepts) - // FIXME: Should this be __has_feature or __has_extension? - //.Case("raw_invocation_type", LangOpts.CPlusPlus) - // Type traits - // N.B. Additional type traits should not be added to the following list. - // Instead, they should be detected by has_extension. - .Case("has_nothrow_assign", LangOpts.CPlusPlus) - .Case("has_nothrow_copy", LangOpts.CPlusPlus) - .Case("has_nothrow_constructor", LangOpts.CPlusPlus) - .Case("has_trivial_assign", LangOpts.CPlusPlus) - .Case("has_trivial_copy", LangOpts.CPlusPlus) - .Case("has_trivial_constructor", LangOpts.CPlusPlus) - .Case("has_trivial_destructor", LangOpts.CPlusPlus) - .Case("has_virtual_destructor", LangOpts.CPlusPlus) - .Case("is_abstract", LangOpts.CPlusPlus) - .Case("is_base_of", LangOpts.CPlusPlus) - .Case("is_class", LangOpts.CPlusPlus) - .Case("is_constructible", LangOpts.CPlusPlus) - .Case("is_convertible_to", LangOpts.CPlusPlus) - .Case("is_empty", LangOpts.CPlusPlus) - .Case("is_enum", LangOpts.CPlusPlus) - .Case("is_final", LangOpts.CPlusPlus) - .Case("is_literal", LangOpts.CPlusPlus) - .Case("is_standard_layout", LangOpts.CPlusPlus) - .Case("is_pod", LangOpts.CPlusPlus) - .Case("is_polymorphic", LangOpts.CPlusPlus) - .Case("is_sealed", LangOpts.CPlusPlus && LangOpts.MicrosoftExt) - .Case("is_trivial", LangOpts.CPlusPlus) - .Case("is_trivially_assignable", LangOpts.CPlusPlus) - .Case("is_trivially_constructible", LangOpts.CPlusPlus) - .Case("is_trivially_copyable", LangOpts.CPlusPlus) - .Case("is_union", LangOpts.CPlusPlus) - .Case("modules", LangOpts.Modules) - .Case("safe_stack", LangOpts.Sanitize.has(SanitizerKind::SafeStack)) - .Case("tls", PP.getTargetInfo().isTLSSupported()) - .Case("underlying_type", LangOpts.CPlusPlus) +#include "clang/Basic/Features.def" .Default(false); +#undef FEATURE } /// HasExtension - Return true if we recognize and implement the feature @@ -1299,35 +1126,13 @@ static bool HasExtension(const Preprocessor &PP, StringRef Extension) { Extension.size() >= 4) Extension = Extension.substr(2, Extension.size() - 4); - // Because we inherit the feature list from HasFeature, this string switch - // must be less restrictive than HasFeature's. + // Because we inherit the feature list from HasFeature, this string switch + // must be less restrictive than HasFeature's. +#define EXTENSION(Name, Predicate) .Case(#Name, Predicate) return llvm::StringSwitch<bool>(Extension) - // C11 features supported by other languages as extensions. - .Case("c_alignas", true) - .Case("c_alignof", true) - .Case("c_atomic", true) - .Case("c_generic_selections", true) - .Case("c_static_assert", true) - .Case("c_thread_local", PP.getTargetInfo().isTLSSupported()) - // C++11 features supported by other languages as extensions. - .Case("cxx_atomic", LangOpts.CPlusPlus) - .Case("cxx_deleted_functions", LangOpts.CPlusPlus) - .Case("cxx_explicit_conversions", LangOpts.CPlusPlus) - .Case("cxx_inline_namespaces", LangOpts.CPlusPlus) - .Case("cxx_local_type_template_args", LangOpts.CPlusPlus) - .Case("cxx_nonstatic_member_init", LangOpts.CPlusPlus) - .Case("cxx_override_control", LangOpts.CPlusPlus) - .Case("cxx_range_for", LangOpts.CPlusPlus) - .Case("cxx_reference_qualified_functions", LangOpts.CPlusPlus) - .Case("cxx_rvalue_references", LangOpts.CPlusPlus) - .Case("cxx_variadic_templates", LangOpts.CPlusPlus) - // C++14 features supported by other languages as extensions. - .Case("cxx_binary_literals", true) - .Case("cxx_init_captures", LangOpts.CPlusPlus11) - .Case("cxx_variable_templates", LangOpts.CPlusPlus) - // Miscellaneous language extensions - .Case("overloadable_unmarked", true) - .Default(false); +#include "clang/Basic/Features.def" + .Default(false); +#undef EXTENSION } /// EvaluateHasIncludeCommon - Process a '__has_include("path")' @@ -1343,7 +1148,7 @@ static bool EvaluateHasIncludeCommon(Token &Tok, // These expressions are only allowed within a preprocessor directive. if (!PP.isParsingIfOrElifDirective()) { - PP.Diag(LParenLoc, diag::err_pp_directive_required) << II->getName(); + PP.Diag(LParenLoc, diag::err_pp_directive_required) << II; // Return a valid identifier token. assert(Tok.is(tok::identifier)); Tok.setIdentifierInfo(II); @@ -1482,7 +1287,7 @@ static bool EvaluateHasIncludeNext(Token &Tok, return EvaluateHasIncludeCommon(Tok, II, PP, Lookup, LookupFromFile); } -/// \brief Process single-argument builtin feature-like macros that return +/// Process single-argument builtin feature-like macros that return /// integer values. static void EvaluateFeatureLikeBuiltinMacro(llvm::raw_svector_ostream& OS, Token &Tok, IdentifierInfo *II, @@ -1585,7 +1390,7 @@ already_lexed: } } -/// \brief Helper function to return the IdentifierInfo structure of a Token +/// Helper function to return the IdentifierInfo structure of a Token /// or generate a diagnostic if none available. static IdentifierInfo *ExpectFeatureIdentifierInfo(Token &Tok, Preprocessor &PP, @@ -1686,7 +1491,7 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) { // can matter for a function-like macro that expands to contain __LINE__. // Skip down through expansion points until we find a file loc for the // end of the expansion history. - Loc = SourceMgr.getExpansionRange(Loc).second; + Loc = SourceMgr.getExpansionRange(Loc).getEnd(); PresumedLoc PLoc = SourceMgr.getPresumedLoc(Loc); // __LINE__ expands to a simple numeric value. @@ -1800,12 +1605,21 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) { [this](Token &Tok, bool &HasLexedNextToken) -> int { IdentifierInfo *II = ExpectFeatureIdentifierInfo(Tok, *this, diag::err_feature_check_malformed); + const LangOptions &LangOpts = getLangOpts(); if (!II) return false; - else if (II->getBuiltinID() != 0) + else if (II->getBuiltinID() != 0) { + switch (II->getBuiltinID()) { + case Builtin::BI__builtin_operator_new: + case Builtin::BI__builtin_operator_delete: + // denotes date of behavior change to support calling arbitrary + // usual allocation and deallocation functions. Required by libc++ + return 201802; + default: + return true; + } return true; - else { - const LangOptions &LangOpts = getLangOpts(); + } else { return llvm::StringSwitch<bool>(II->getName()) .Case("__make_integer_seq", LangOpts.CPlusPlus) .Case("__type_pack_element", LangOpts.CPlusPlus) diff --git a/lib/Lex/PTHLexer.cpp b/lib/Lex/PTHLexer.cpp index d6c20a13d27be..45cff56dcaa11 100644 --- a/lib/Lex/PTHLexer.cpp +++ b/lib/Lex/PTHLexer.cpp @@ -23,8 +23,8 @@ #include "clang/Lex/Preprocessor.h" #include "clang/Lex/Token.h" #include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringRef.h" +#include "llvm/Support/DJB.h" #include "llvm/Support/Endian.h" #include "llvm/Support/ErrorOr.h" #include "llvm/Support/FileSystem.h" @@ -145,7 +145,7 @@ bool PTHLexer::LexEndOfFile(Token &Result) { ParsingPreprocessorDirective = false; // Done parsing the "line". return true; // Have a token. } - + assert(!LexingRawMode); // If we are in a #if directive, emit an error. @@ -215,7 +215,7 @@ bool PTHLexer::SkipBlock() { // Compute the actual memory address of the '#' token data for this entry. HashEntryI = TokBuf + Offset; - // Optmization: "Sibling jumping". #if...#else...#endif blocks can + // Optimization: "Sibling jumping". #if...#else...#endif blocks can // contain nested blocks. In the side-table we can jump over these // nested blocks instead of doing a linear search if the next "sibling" // entry is not at a location greater than LastHashTokPtr. @@ -336,7 +336,7 @@ public: using offset_type = unsigned; static hash_value_type ComputeHash(internal_key_type x) { - return llvm::HashString(x.second); + return llvm::djbHash(x.second); } static std::pair<unsigned, unsigned> @@ -396,7 +396,7 @@ public: } static hash_value_type ComputeHash(const internal_key_type& a) { - return llvm::HashString(StringRef(a.first, a.second)); + return llvm::djbHash(StringRef(a.first, a.second)); } // This hopefully will just get inlined and removed by the optimizer. diff --git a/lib/Lex/Pragma.cpp b/lib/Lex/Pragma.cpp index b8acd92521fb5..930c5f6b069c8 100644 --- a/lib/Lex/Pragma.cpp +++ b/lib/Lex/Pragma.cpp @@ -148,7 +148,7 @@ void Preprocessor::HandlePragmaDirective(SourceLocation IntroducerLoc, namespace { -/// \brief Helper class for \see Preprocessor::Handle_Pragma. +/// Helper class for \see Preprocessor::Handle_Pragma. class LexingFor_PragmaRAII { Preprocessor &PP; bool InMacroArgPreExpansion; @@ -588,7 +588,7 @@ IdentifierInfo *Preprocessor::ParsePragmaPushOrPopMacro(Token &Tok) { return LookUpIdentifierInfo(MacroTok); } -/// \brief Handle \#pragma push_macro. +/// Handle \#pragma push_macro. /// /// The syntax is: /// \code @@ -611,7 +611,7 @@ void Preprocessor::HandlePragmaPushMacro(Token &PushMacroTok) { PragmaPushMacroInfo[IdentInfo].push_back(MI); } -/// \brief Handle \#pragma pop_macro. +/// Handle \#pragma pop_macro. /// /// The syntax is: /// \code @@ -1053,6 +1053,20 @@ struct PragmaDebugHandler : public PragmaHandler { PP.Diag(Identifier, diag::warn_pragma_debug_missing_argument) << II->getName(); } + } else if (II->isStr("diag_mapping")) { + Token DiagName; + PP.LexUnexpandedToken(DiagName); + if (DiagName.is(tok::eod)) + PP.getDiagnostics().dump(); + else if (DiagName.is(tok::string_literal) && !DiagName.hasUDSuffix()) { + StringLiteralParser Literal(DiagName, PP); + if (Literal.hadError) + return; + PP.getDiagnostics().dump(Literal.GetString()); + } else { + PP.Diag(DiagName, diag::warn_pragma_debug_missing_argument) + << II->getName(); + } } else if (II->isStr("llvm_fatal_error")) { llvm::report_fatal_error("#pragma clang __debug llvm_fatal_error"); } else if (II->isStr("llvm_unreachable")) { @@ -1601,44 +1615,6 @@ struct PragmaPopMacroHandler : public PragmaHandler { } }; -// Pragma STDC implementations. - -/// PragmaSTDC_FENV_ACCESSHandler - "\#pragma STDC FENV_ACCESS ...". -struct PragmaSTDC_FENV_ACCESSHandler : public PragmaHandler { - PragmaSTDC_FENV_ACCESSHandler() : PragmaHandler("FENV_ACCESS") {} - - void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, - Token &Tok) override { - tok::OnOffSwitch OOS; - if (PP.LexOnOffSwitch(OOS)) - return; - if (OOS == tok::OOS_ON) - PP.Diag(Tok, diag::warn_stdc_fenv_access_not_supported); - } -}; - -/// PragmaSTDC_CX_LIMITED_RANGEHandler - "\#pragma STDC CX_LIMITED_RANGE ...". -struct PragmaSTDC_CX_LIMITED_RANGEHandler : public PragmaHandler { - PragmaSTDC_CX_LIMITED_RANGEHandler() : PragmaHandler("CX_LIMITED_RANGE") {} - - void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, - Token &Tok) override { - tok::OnOffSwitch OOS; - PP.LexOnOffSwitch(OOS); - } -}; - -/// PragmaSTDC_UnknownHandler - "\#pragma STDC ...". -struct PragmaSTDC_UnknownHandler : public PragmaHandler { - PragmaSTDC_UnknownHandler() = default; - - void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, - Token &UnknownTok) override { - // C99 6.10.6p2, unknown forms are not allowed. - PP.Diag(UnknownTok, diag::ext_stdc_pragma_ignored); - } -}; - /// PragmaARCCFCodeAuditedHandler - /// \#pragma clang arc_cf_code_audited begin/end struct PragmaARCCFCodeAuditedHandler : public PragmaHandler { @@ -1754,7 +1730,7 @@ struct PragmaAssumeNonNullHandler : public PragmaHandler { } }; -/// \brief Handle "\#pragma region [...]" +/// Handle "\#pragma region [...]" /// /// The syntax is /// \code @@ -1814,17 +1790,15 @@ void Preprocessor::RegisterBuiltinPragmas() { ModuleHandler->AddPragma(new PragmaModuleEndHandler()); ModuleHandler->AddPragma(new PragmaModuleBuildHandler()); ModuleHandler->AddPragma(new PragmaModuleLoadHandler()); - - AddPragmaHandler("STDC", new PragmaSTDC_FENV_ACCESSHandler()); - AddPragmaHandler("STDC", new PragmaSTDC_CX_LIMITED_RANGEHandler()); - AddPragmaHandler("STDC", new PragmaSTDC_UnknownHandler()); + + // Add region pragmas. + AddPragmaHandler(new PragmaRegionHandler("region")); + AddPragmaHandler(new PragmaRegionHandler("endregion")); // MS extensions. if (LangOpts.MicrosoftExt) { AddPragmaHandler(new PragmaWarningHandler()); AddPragmaHandler(new PragmaIncludeAliasHandler()); - AddPragmaHandler(new PragmaRegionHandler("region")); - AddPragmaHandler(new PragmaRegionHandler("endregion")); } // Pragmas added by plugins @@ -1843,17 +1817,4 @@ void Preprocessor::IgnorePragmas() { // in Preprocessor::RegisterBuiltinPragmas(). AddPragmaHandler("GCC", new EmptyPragmaHandler()); AddPragmaHandler("clang", new EmptyPragmaHandler()); - if (PragmaHandler *NS = PragmaHandlers->FindHandler("STDC")) { - // Preprocessor::RegisterBuiltinPragmas() already registers - // PragmaSTDC_UnknownHandler as the empty handler, so remove it first, - // otherwise there will be an assert about a duplicate handler. - PragmaNamespace *STDCNamespace = NS->getIfNamespace(); - assert(STDCNamespace && - "Invalid namespace, registered as a regular pragma handler!"); - if (PragmaHandler *Existing = STDCNamespace->FindHandler("", false)) { - RemovePragmaHandler("STDC", Existing); - delete Existing; - } - } - AddPragmaHandler("STDC", new EmptyPragmaHandler()); } diff --git a/lib/Lex/PreprocessingRecord.cpp b/lib/Lex/PreprocessingRecord.cpp index af439dbfa5842..b59820003b56a 100644 --- a/lib/Lex/PreprocessingRecord.cpp +++ b/lib/Lex/PreprocessingRecord.cpp @@ -54,7 +54,7 @@ InclusionDirective::InclusionDirective(PreprocessingRecord &PPRec, PreprocessingRecord::PreprocessingRecord(SourceManager &SM) : SourceMgr(SM) {} -/// \brief Returns a pair of [Begin, End) iterators of preprocessed entities +/// Returns a pair of [Begin, End) iterators of preprocessed entities /// that source range \p Range encompasses. llvm::iterator_range<PreprocessingRecord::iterator> PreprocessingRecord::getPreprocessedEntitiesInRange(SourceRange Range) { @@ -88,7 +88,7 @@ static bool isPreprocessedEntityIfInFileID(PreprocessedEntity *PPE, FileID FID, return SM.isInFileID(SM.getFileLoc(Loc), FID); } -/// \brief Returns true if the preprocessed entity that \arg PPEI iterator +/// Returns true if the preprocessed entity that \arg PPEI iterator /// points to is coming from the file \arg FID. /// /// Can be used to avoid implicit deserializations of preallocated @@ -132,7 +132,7 @@ bool PreprocessingRecord::isEntityInFileID(iterator PPEI, FileID FID) { FID, SourceMgr); } -/// \brief Returns a pair of [Begin, End) iterators of preprocessed entities +/// Returns a pair of [Begin, End) iterators of preprocessed entities /// that source range \arg R encompasses. std::pair<int, int> PreprocessingRecord::getPreprocessedEntitiesInRangeSlow(SourceRange Range) { @@ -329,12 +329,29 @@ unsigned PreprocessingRecord::allocateLoadedEntities(unsigned NumEntities) { return Result; } +unsigned PreprocessingRecord::allocateSkippedRanges(unsigned NumRanges) { + unsigned Result = SkippedRanges.size(); + SkippedRanges.resize(SkippedRanges.size() + NumRanges); + SkippedRangesAllLoaded = false; + return Result; +} + +void PreprocessingRecord::ensureSkippedRangesLoaded() { + if (SkippedRangesAllLoaded || !ExternalSource) + return; + for (unsigned Index = 0; Index != SkippedRanges.size(); ++Index) { + if (SkippedRanges[Index].isInvalid()) + SkippedRanges[Index] = ExternalSource->ReadSkippedRange(Index); + } + SkippedRangesAllLoaded = true; +} + void PreprocessingRecord::RegisterMacroDefinition(MacroInfo *Macro, MacroDefinitionRecord *Def) { MacroDefinitions[Macro] = Def; } -/// \brief Retrieve the preprocessed entity at the given ID. +/// Retrieve the preprocessed entity at the given ID. PreprocessedEntity *PreprocessingRecord::getPreprocessedEntity(PPEntityID PPID){ if (PPID.ID < 0) { unsigned Index = -PPID.ID - 1; @@ -351,7 +368,7 @@ PreprocessedEntity *PreprocessingRecord::getPreprocessedEntity(PPEntityID PPID){ return PreprocessedEntities[Index]; } -/// \brief Retrieve the loaded preprocessed entity at the given index. +/// Retrieve the loaded preprocessed entity at the given index. PreprocessedEntity * PreprocessingRecord::getLoadedPreprocessedEntity(unsigned Index) { assert(Index < LoadedPreprocessedEntities.size() && @@ -418,6 +435,7 @@ void PreprocessingRecord::Defined(const Token &MacroNameTok, void PreprocessingRecord::SourceRangeSkipped(SourceRange Range, SourceLocation EndifLoc) { + assert(Range.isValid()); SkippedRanges.emplace_back(Range.getBegin(), EndifLoc); } @@ -453,7 +471,8 @@ void PreprocessingRecord::InclusionDirective( const FileEntry *File, StringRef SearchPath, StringRef RelativePath, - const Module *Imported) { + const Module *Imported, + SrcMgr::CharacteristicKind FileType) { InclusionDirective::InclusionKind Kind = InclusionDirective::Include; switch (IncludeTok.getIdentifierInfo()->getPPKeywordID()) { @@ -497,5 +516,6 @@ size_t PreprocessingRecord::getTotalMemory() const { return BumpAlloc.getTotalMemory() + llvm::capacity_in_bytes(MacroDefinitions) + llvm::capacity_in_bytes(PreprocessedEntities) - + llvm::capacity_in_bytes(LoadedPreprocessedEntities); + + llvm::capacity_in_bytes(LoadedPreprocessedEntities) + + llvm::capacity_in_bytes(SkippedRanges); } diff --git a/lib/Lex/Preprocessor.cpp b/lib/Lex/Preprocessor.cpp index 7d789e780113c..0217a2e60ede8 100644 --- a/lib/Lex/Preprocessor.cpp +++ b/lib/Lex/Preprocessor.cpp @@ -85,12 +85,14 @@ Preprocessor::Preprocessor(std::shared_ptr<PreprocessorOptions> PPOpts, IdentifierInfoLookup *IILookup, bool OwnsHeaders, TranslationUnitKind TUKind) : PPOpts(std::move(PPOpts)), Diags(&diags), LangOpts(opts), - FileMgr(Headers.getFileMgr()), SourceMgr(SM), - PCMCache(PCMCache), ScratchBuf(new ScratchBuffer(SourceMgr)), - HeaderInfo(Headers), TheModuleLoader(TheModuleLoader), - ExternalSource(nullptr), Identifiers(opts, IILookup), - PragmaHandlers(new PragmaNamespace(StringRef())), TUKind(TUKind), - SkipMainFilePreamble(0, true), + FileMgr(Headers.getFileMgr()), SourceMgr(SM), PCMCache(PCMCache), + ScratchBuf(new ScratchBuffer(SourceMgr)), HeaderInfo(Headers), + TheModuleLoader(TheModuleLoader), ExternalSource(nullptr), + // As the language options may have not been loaded yet (when + // deserializing an ASTUnit), adding keywords to the identifier table is + // deferred to Preprocessor::Initialize(). + Identifiers(IILookup), PragmaHandlers(new PragmaNamespace(StringRef())), + TUKind(TUKind), SkipMainFilePreamble(0, true), CurSubmoduleState(&NullSubmoduleState) { OwnsHeaderSearch = OwnsHeaders; @@ -147,6 +149,11 @@ Preprocessor::Preprocessor(std::shared_ptr<PreprocessorOptions> PPOpts, Ident_AbnormalTermination = nullptr; } + // If using a PCH with a through header, start skipping tokens. + if (!this->PPOpts->PCHThroughHeader.empty() && + !this->PPOpts->ImplicitPCHInclude.empty()) + SkippingUntilPCHThroughHeader = true; + if (this->PPOpts->GeneratePreamble) PreambleConditionalStack.startRecording(); } @@ -190,6 +197,9 @@ void Preprocessor::Initialize(const TargetInfo &Target, // Initialize information about built-ins. BuiltinInfo.InitializeTarget(Target, AuxTarget); HeaderInfo.setTarget(Target); + + // Populate the identifier table with info about keywords for the current language. + Identifiers.AddKeywords(LangOpts); } void Preprocessor::InitializeForModelFile() { @@ -328,7 +338,7 @@ Preprocessor::macro_end(bool IncludeExternalMacros) const { return CurSubmoduleState->Macros.end(); } -/// \brief Compares macro tokens with a specified token value sequence. +/// Compares macro tokens with a specified token value sequence. static bool MacroDefinitionEquals(const MacroInfo *MI, ArrayRef<TokenValue> Tokens) { return Tokens.size() == MI->getNumTokens() && @@ -482,6 +492,22 @@ void Preprocessor::CreateString(StringRef Str, Token &Tok, Tok.setLiteralData(DestPtr); } +SourceLocation Preprocessor::SplitToken(SourceLocation Loc, unsigned Length) { + auto &SM = getSourceManager(); + SourceLocation SpellingLoc = SM.getSpellingLoc(Loc); + std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(SpellingLoc); + bool Invalid = false; + StringRef Buffer = SM.getBufferData(LocInfo.first, &Invalid); + if (Invalid) + return SourceLocation(); + + // FIXME: We could consider re-using spelling for tokens we see repeatedly. + const char *DestPtr; + SourceLocation Spelling = + ScratchBuf->getToken(Buffer.data() + LocInfo.second, Length, DestPtr); + return SM.createTokenSplitLoc(Spelling, Loc, Loc.getLocWithOffset(Length)); +} + Module *Preprocessor::getCurrentModule() { if (!getLangOpts().isCompilingModule()) return nullptr; @@ -530,6 +556,72 @@ void Preprocessor::EnterMainSourceFile() { // Start parsing the predefines. EnterSourceFile(FID, nullptr, SourceLocation()); + + if (!PPOpts->PCHThroughHeader.empty()) { + // 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( + SourceLocation(), PPOpts->PCHThroughHeader, + /*isAngled=*/false, /*FromDir=*/nullptr, /*FromFile=*/nullptr, CurDir, + /*SearchPath=*/nullptr, /*RelativePath=*/nullptr, + /*SuggestedModule=*/nullptr, /*IsMapped=*/nullptr); + if (!File) { + Diag(SourceLocation(), diag::err_pp_through_header_not_found) + << PPOpts->PCHThroughHeader; + return; + } + setPCHThroughHeaderFileID( + SourceMgr.createFileID(File, SourceLocation(), SrcMgr::C_User)); + } + + // Skip tokens from the Predefines and if needed the main file. + if (usingPCHWithThroughHeader() && SkippingUntilPCHThroughHeader) + SkipTokensUntilPCHThroughHeader(); +} + +void Preprocessor::setPCHThroughHeaderFileID(FileID FID) { + assert(PCHThroughHeaderFileID.isInvalid() && + "PCHThroughHeaderFileID already set!"); + PCHThroughHeaderFileID = FID; +} + +bool Preprocessor::isPCHThroughHeader(const FileEntry *FE) { + assert(PCHThroughHeaderFileID.isValid() && + "Invalid PCH through header FileID"); + return FE == SourceMgr.getFileEntryForID(PCHThroughHeaderFileID); +} + +bool Preprocessor::creatingPCHWithThroughHeader() { + return TUKind == TU_Prefix && !PPOpts->PCHThroughHeader.empty() && + PCHThroughHeaderFileID.isValid(); +} + +bool Preprocessor::usingPCHWithThroughHeader() { + return TUKind != TU_Prefix && !PPOpts->PCHThroughHeader.empty() && + PCHThroughHeaderFileID.isValid(); +} + +/// Skip tokens until after the #include of the through header. +/// Tokens in the predefines file and the main file may be skipped. If the end +/// of the predefines file is reached, skipping continues into the main file. +/// If the end of the main file is reached, it's a fatal error. +void Preprocessor::SkipTokensUntilPCHThroughHeader() { + bool ReachedMainFileEOF = false; + Token Tok; + while (true) { + bool InPredefines = (CurLexer->getFileID() == getPredefinesFileID()); + CurLexer->Lex(Tok); + if (Tok.is(tok::eof) && !InPredefines) { + ReachedMainFileEOF = true; + break; + } + if (!SkippingUntilPCHThroughHeader) + break; + } + if (ReachedMainFileEOF) + Diag(SourceLocation(), diag::err_pp_through_header_not_seen) + << PPOpts->PCHThroughHeader << 1; } void Preprocessor::replayPreambleConditionalStack() { @@ -624,7 +716,7 @@ void Preprocessor::HandlePoisonedIdentifier(Token & Identifier) { Diag(Identifier,it->second) << Identifier.getIdentifierInfo(); } -/// \brief Returns a diagnostic message kind for reporting a future keyword as +/// Returns a diagnostic message kind for reporting a future keyword as /// appropriate for the identifier and specified language. static diag::kind getFutureCompatDiagKind(const IdentifierInfo &II, const LangOptions &LangOpts) { @@ -773,13 +865,18 @@ void Preprocessor::Lex(Token &Result) { } } while (!ReturnedToken); - if (Result.is(tok::code_completion)) + if (Result.is(tok::code_completion) && Result.getIdentifierInfo()) { + // Remember the identifier before code completion token. setCodeCompletionIdentifierInfo(Result.getIdentifierInfo()); + // Set IdenfitierInfo to null to avoid confusing code that handles both + // identifiers and completion tokens. + Result.setIdentifierInfo(nullptr); + } LastTokenWasAt = Result.is(tok::at); } -/// \brief Lex a token following the 'import' contextual keyword. +/// Lex a token following the 'import' contextual keyword. /// void Preprocessor::LexAfterModuleImport(Token &Result) { // Figure out what kind of lexer we actually have. diff --git a/lib/Lex/PreprocessorLexer.cpp b/lib/Lex/PreprocessorLexer.cpp index 2e85f46f52c59..9f930c3a3c6a0 100644 --- a/lib/Lex/PreprocessorLexer.cpp +++ b/lib/Lex/PreprocessorLexer.cpp @@ -28,7 +28,7 @@ PreprocessorLexer::PreprocessorLexer(Preprocessor *pp, FileID fid) InitialNumSLocEntries = pp->getSourceManager().local_sloc_entry_size(); } -/// \brief After the preprocessor has parsed a \#include, lex and +/// After the preprocessor has parsed a \#include, lex and /// (potentially) macro expand the filename. void PreprocessorLexer::LexIncludeFilename(Token &FilenameTok) { assert(ParsingPreprocessorDirective && diff --git a/lib/Lex/ScratchBuffer.cpp b/lib/Lex/ScratchBuffer.cpp index e0f3966fce480..dc03e16daa8b6 100644 --- a/lib/Lex/ScratchBuffer.cpp +++ b/lib/Lex/ScratchBuffer.cpp @@ -74,11 +74,11 @@ void ScratchBuffer::AllocScratchBuffer(unsigned RequestLen) { // Get scratch buffer. Zero-initialize it so it can be dumped into a PCH file // deterministically. - std::unique_ptr<llvm::MemoryBuffer> OwnBuf = - llvm::MemoryBuffer::getNewMemBuffer(RequestLen, "<scratch space>"); - llvm::MemoryBuffer &Buf = *OwnBuf; + std::unique_ptr<llvm::WritableMemoryBuffer> OwnBuf = + llvm::WritableMemoryBuffer::getNewMemBuffer(RequestLen, + "<scratch space>"); + CurBuffer = OwnBuf->getBufferStart(); FileID FID = SourceMgr.createFileID(std::move(OwnBuf)); BufferStartLoc = SourceMgr.getLocForStartOfFile(FID); - CurBuffer = const_cast<char*>(Buf.getBufferStart()); BytesUsed = 0; } diff --git a/lib/Lex/TokenLexer.cpp b/lib/Lex/TokenLexer.cpp index d7f1c7a93fdae..184b1b390287a 100644 --- a/lib/Lex/TokenLexer.cpp +++ b/lib/Lex/TokenLexer.cpp @@ -483,7 +483,7 @@ void TokenLexer::ExpandFunctionArguments() { bool VaArgsPseudoPaste = false; // If this is the GNU ", ## __VA_ARGS__" extension, and we just learned // that __VA_ARGS__ expands to multiple tokens, avoid a pasting error when - // the expander trys to paste ',' with the first token of the __VA_ARGS__ + // the expander tries to paste ',' with the first token of the __VA_ARGS__ // expansion. if (NonEmptyPasteBefore && ResultToks.size() >= 2 && ResultToks[ResultToks.size()-2].is(tok::comma) && @@ -574,7 +574,7 @@ void TokenLexer::ExpandFunctionArguments() { } } -/// \brief Checks if two tokens form wide string literal. +/// Checks if two tokens form wide string literal. static bool isWideStringLiteralFromMacro(const Token &FirstTok, const Token &SecondTok) { return FirstTok.is(tok::identifier) && @@ -865,9 +865,9 @@ bool TokenLexer::pasteTokens(Token &LHSTok, ArrayRef<Token> TokenStream, EndLoc = getExpansionLocForMacroDefLoc(EndLoc); FileID MacroFID = SM.getFileID(MacroExpansionStart); while (SM.getFileID(StartLoc) != MacroFID) - StartLoc = SM.getImmediateExpansionRange(StartLoc).first; + StartLoc = SM.getImmediateExpansionRange(StartLoc).getBegin(); while (SM.getFileID(EndLoc) != MacroFID) - EndLoc = SM.getImmediateExpansionRange(EndLoc).second; + EndLoc = SM.getImmediateExpansionRange(EndLoc).getEnd(); LHSTok.setLocation(SM.createExpansionLoc(LHSTok.getLocation(), StartLoc, EndLoc, LHSTok.getLength())); @@ -918,7 +918,7 @@ void TokenLexer::HandleMicrosoftCommentPaste(Token &Tok, SourceLocation OpLoc) { PP.HandleMicrosoftCommentPaste(Tok); } -/// \brief If \arg loc is a file ID and points inside the current macro +/// If \arg loc is a file ID and points inside the current macro /// definition, returns the appropriate source location pointing at the /// macro expansion source location entry, otherwise it returns an invalid /// SourceLocation. @@ -937,7 +937,7 @@ TokenLexer::getExpansionLocForMacroDefLoc(SourceLocation loc) const { return MacroExpansionStart.getLocWithOffset(relativeOffset); } -/// \brief Finds the tokens that are consecutive (from the same FileID) +/// Finds the tokens that are consecutive (from the same FileID) /// creates a single SLocEntry, and assigns SourceLocations to each token that /// point to that SLocEntry. e.g for /// assert(foo == bar); @@ -1007,7 +1007,7 @@ static void updateConsecutiveMacroArgTokens(SourceManager &SM, } } -/// \brief Creates SLocEntries and updates the locations of macro argument +/// Creates SLocEntries and updates the locations of macro argument /// tokens to their new expanded locations. /// /// \param ArgIdSpellLoc the location of the macro argument id inside the macro |