summaryrefslogtreecommitdiff
path: root/lib/Lex
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2018-07-28 11:06:01 +0000
committerDimitry Andric <dim@FreeBSD.org>2018-07-28 11:06:01 +0000
commit486754660bb926339aefcf012a3f848592babb8b (patch)
treeecdbc446c9876f4f120f701c243373cd3cb43db3 /lib/Lex
parent55e6d896ad333f07bb3b1ba487df214fc268a4ab (diff)
Notes
Diffstat (limited to 'lib/Lex')
-rw-r--r--lib/Lex/HeaderSearch.cpp140
-rw-r--r--lib/Lex/Lexer.cpp103
-rw-r--r--lib/Lex/LiteralSupport.cpp197
-rw-r--r--lib/Lex/MacroArgs.cpp5
-rw-r--r--lib/Lex/MacroInfo.cpp2
-rw-r--r--lib/Lex/ModuleMap.cpp310
-rw-r--r--lib/Lex/PPCaching.cpp4
-rw-r--r--lib/Lex/PPDirectives.cpp124
-rw-r--r--lib/Lex/PPExpressions.cpp2
-rw-r--r--lib/Lex/PPLexerChange.cpp32
-rw-r--r--lib/Lex/PPMacroExpansion.cpp238
-rw-r--r--lib/Lex/PTHLexer.cpp10
-rw-r--r--lib/Lex/Pragma.cpp83
-rw-r--r--lib/Lex/PreprocessingRecord.cpp34
-rw-r--r--lib/Lex/Preprocessor.cpp117
-rw-r--r--lib/Lex/PreprocessorLexer.cpp2
-rw-r--r--lib/Lex/ScratchBuffer.cpp8
-rw-r--r--lib/Lex/TokenLexer.cpp14
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 &Map;
- /// \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