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