aboutsummaryrefslogtreecommitdiffstats
path: root/lib/Lex
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2014-11-24 09:15:30 +0000
committerDimitry Andric <dim@FreeBSD.org>2014-11-24 09:15:30 +0000
commit9f4dbff6669c8037f3b036bcf580d14f1a4f12a5 (patch)
tree47df2c12b57214af6c31e47404b005675b8b7ffc /lib/Lex
parentf73d5f23a889b93d89ddef61ac0995df40286bb8 (diff)
downloadsrc-9f4dbff6669c8037f3b036bcf580d14f1a4f12a5.tar.gz
src-9f4dbff6669c8037f3b036bcf580d14f1a4f12a5.zip
Vendor import of clang RELEASE_350/final tag r216957 (effectively, 3.5.0 release):vendor/clang/clang-release_350-r216957
Notes
Notes: svn path=/vendor/clang/dist/; revision=274958 svn path=/vendor/clang/clang-release_350-r216957/; revision=274959; tag=vendor/clang/clang-release_350-r216957
Diffstat (limited to 'lib/Lex')
-rw-r--r--lib/Lex/CMakeLists.txt9
-rw-r--r--lib/Lex/HeaderMap.cpp41
-rw-r--r--lib/Lex/HeaderSearch.cpp621
-rw-r--r--lib/Lex/Lexer.cpp223
-rw-r--r--lib/Lex/LiteralSupport.cpp148
-rw-r--r--lib/Lex/MacroArgs.cpp8
-rw-r--r--lib/Lex/MacroInfo.cpp86
-rw-r--r--lib/Lex/ModuleMap.cpp605
-rw-r--r--lib/Lex/PPCaching.cpp22
-rw-r--r--lib/Lex/PPConditionalDirectiveRecord.cpp4
-rw-r--r--lib/Lex/PPDirectives.cpp441
-rw-r--r--lib/Lex/PPExpressions.cpp28
-rw-r--r--lib/Lex/PPLexerChange.cpp128
-rw-r--r--lib/Lex/PPMacroExpansion.cpp210
-rw-r--r--lib/Lex/PTHLexer.cpp198
-rw-r--r--lib/Lex/Pragma.cpp184
-rw-r--r--lib/Lex/PreprocessingRecord.cpp10
-rw-r--r--lib/Lex/Preprocessor.cpp136
-rw-r--r--lib/Lex/ScratchBuffer.cpp5
-rw-r--r--lib/Lex/TokenLexer.cpp93
-rw-r--r--lib/Lex/UnicodeCharSets.h2
21 files changed, 1876 insertions, 1326 deletions
diff --git a/lib/Lex/CMakeLists.txt b/lib/Lex/CMakeLists.txt
index 2ee468294ae7..38df144adf9a 100644
--- a/lib/Lex/CMakeLists.txt
+++ b/lib/Lex/CMakeLists.txt
@@ -25,14 +25,7 @@ add_clang_library(clangLex
ScratchBuffer.cpp
TokenConcatenation.cpp
TokenLexer.cpp
- )
-
-add_dependencies(clangLex
- ClangAttrSpellings
- ClangDiagnosticCommon
- ClangDiagnosticLex
- )
-target_link_libraries(clangLex
+ LINK_LIBS
clangBasic
)
diff --git a/lib/Lex/HeaderMap.cpp b/lib/Lex/HeaderMap.cpp
index 478462c3c20d..f6c658e11926 100644
--- a/lib/Lex/HeaderMap.cpp
+++ b/lib/Lex/HeaderMap.cpp
@@ -14,12 +14,12 @@
#include "clang/Lex/HeaderMap.h"
#include "clang/Basic/CharInfo.h"
#include "clang/Basic/FileManager.h"
-#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/DataTypes.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/MemoryBuffer.h"
#include <cstdio>
+#include <memory>
using namespace clang;
//===----------------------------------------------------------------------===//
@@ -79,10 +79,10 @@ static inline unsigned HashHMapKey(StringRef Str) {
const HeaderMap *HeaderMap::Create(const FileEntry *FE, FileManager &FM) {
// If the file is too small to be a header map, ignore it.
unsigned FileSize = FE->getSize();
- if (FileSize <= sizeof(HMapHeader)) return 0;
+ if (FileSize <= sizeof(HMapHeader)) return nullptr;
- OwningPtr<const llvm::MemoryBuffer> FileBuffer(FM.getBufferForFile(FE));
- if (!FileBuffer) return 0; // Unreadable file?
+ std::unique_ptr<const llvm::MemoryBuffer> FileBuffer(FM.getBufferForFile(FE));
+ if (!FileBuffer) return nullptr; // Unreadable file?
const char *FileStart = FileBuffer->getBufferStart();
// We know the file is at least as big as the header, check it now.
@@ -98,12 +98,12 @@ const HeaderMap *HeaderMap::Create(const FileEntry *FE, FileManager &FM) {
Header->Version == llvm::ByteSwap_16(HMAP_HeaderVersion))
NeedsByteSwap = true; // Mixed endianness headermap.
else
- return 0; // Not a header map.
+ return nullptr; // Not a header map.
- if (Header->Reserved != 0) return 0;
+ if (Header->Reserved != 0) return nullptr;
// Okay, everything looks good, create the header map.
- return new HeaderMap(FileBuffer.take(), NeedsByteSwap);
+ return new HeaderMap(FileBuffer.release(), NeedsByteSwap);
}
HeaderMap::~HeaderMap() {
@@ -165,7 +165,7 @@ const char *HeaderMap::getString(unsigned StrTabIdx) const {
// Check for invalid index.
if (StrTabIdx >= FileBuffer->getBufferSize())
- return 0;
+ return nullptr;
// Otherwise, we have a valid pointer into the file. Just return it. We know
// that the "string" can not overrun the end of the file, because the buffer
@@ -201,18 +201,29 @@ void HeaderMap::dump() const {
/// this HeaderMap. If so, open it and return its FileEntry.
const FileEntry *HeaderMap::LookupFile(
StringRef Filename, FileManager &FM) const {
+
+ SmallString<1024> Path;
+ StringRef Dest = lookupFilename(Filename, Path);
+ if (Dest.empty())
+ return nullptr;
+
+ return FM.getFile(Dest);
+}
+
+StringRef HeaderMap::lookupFilename(StringRef Filename,
+ SmallVectorImpl<char> &DestPath) const {
const HMapHeader &Hdr = getHeader();
unsigned NumBuckets = getEndianAdjustedWord(Hdr.NumBuckets);
// If the number of buckets is not a power of two, the headermap is corrupt.
// Don't probe infinitely.
if (NumBuckets & (NumBuckets-1))
- return 0;
+ return StringRef();
// Linearly probe the hash table.
for (unsigned Bucket = HashHMapKey(Filename);; ++Bucket) {
HMapBucket B = getBucket(Bucket & (NumBuckets-1));
- if (B.Key == HMAP_EmptyBucketKey) return 0; // Hash miss.
+ if (B.Key == HMAP_EmptyBucketKey) return StringRef(); // Hash miss.
// See if the key matches. If not, probe on.
if (!Filename.equals_lower(getString(B.Key)))
@@ -220,9 +231,11 @@ const FileEntry *HeaderMap::LookupFile(
// If so, we have a match in the hash table. Construct the destination
// path.
- SmallString<1024> DestPath;
- DestPath += getString(B.Prefix);
- DestPath += getString(B.Suffix);
- return FM.getFile(DestPath.str());
+ StringRef Prefix = getString(B.Prefix);
+ StringRef Suffix = getString(B.Suffix);
+ DestPath.clear();
+ DestPath.append(Prefix.begin(), Prefix.end());
+ DestPath.append(Suffix.begin(), Suffix.end());
+ return StringRef(DestPath.begin(), DestPath.size());
}
}
diff --git a/lib/Lex/HeaderSearch.cpp b/lib/Lex/HeaderSearch.cpp
index 9e43dda226bf..c12d7314ee23 100644
--- a/lib/Lex/HeaderSearch.cpp
+++ b/lib/Lex/HeaderSearch.cpp
@@ -12,12 +12,14 @@
//===----------------------------------------------------------------------===//
#include "clang/Lex/HeaderSearch.h"
-#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/IdentifierTable.h"
#include "clang/Lex/HeaderMap.h"
#include "clang/Lex/HeaderSearchOptions.h"
+#include "clang/Lex/LexDiagnostic.h"
#include "clang/Lex/Lexer.h"
+#include "llvm/ADT/APInt.h"
+#include "llvm/ADT/Hashing.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/Capacity.h"
#include "llvm/Support/FileSystem.h"
@@ -35,7 +37,7 @@ HeaderFileInfo::getControllingMacro(ExternalIdentifierLookup *External) {
return ControllingMacro;
if (!ControllingMacroID || !External)
- return 0;
+ return nullptr;
ControllingMacro = External->GetIdentifier(ControllingMacroID);
return ControllingMacro;
@@ -45,20 +47,21 @@ ExternalHeaderFileInfoSource::~ExternalHeaderFileInfoSource() {}
HeaderSearch::HeaderSearch(IntrusiveRefCntPtr<HeaderSearchOptions> HSOpts,
SourceManager &SourceMgr, DiagnosticsEngine &Diags,
- const LangOptions &LangOpts,
+ const LangOptions &LangOpts,
const TargetInfo *Target)
- : HSOpts(HSOpts), FileMgr(SourceMgr.getFileManager()), FrameworkMap(64),
- ModMap(SourceMgr, *Diags.getClient(), LangOpts, Target, *this)
-{
+ : HSOpts(HSOpts), Diags(Diags), FileMgr(SourceMgr.getFileManager()),
+ FrameworkMap(64), ModMap(SourceMgr, Diags, LangOpts, Target, *this) {
AngledDirIdx = 0;
SystemDirIdx = 0;
NoCurDirSearch = false;
- ExternalLookup = 0;
- ExternalSource = 0;
+ ExternalLookup = nullptr;
+ ExternalSource = nullptr;
NumIncluded = 0;
NumMultiIncludeFileOptzn = 0;
NumFrameworkLookups = NumSubFrameworkLookups = 0;
+
+ EnabledModules = LangOpts.Modules;
}
HeaderSearch::~HeaderSearch() {
@@ -107,28 +110,37 @@ const HeaderMap *HeaderSearch::CreateHeaderMap(const FileEntry *FE) {
return HM;
}
- return 0;
+ return nullptr;
}
std::string HeaderSearch::getModuleFileName(Module *Module) {
- // If we don't have a module cache path, we can't do anything.
- if (ModuleCachePath.empty())
- return std::string();
-
-
- SmallString<256> Result(ModuleCachePath);
- llvm::sys::path::append(Result, Module->getTopLevelModule()->Name + ".pcm");
- return Result.str().str();
+ return getModuleFileName(Module->Name, Module->ModuleMap->getName());
}
-std::string HeaderSearch::getModuleFileName(StringRef ModuleName) {
+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())
return std::string();
-
-
+
SmallString<256> Result(ModuleCachePath);
- llvm::sys::path::append(Result, ModuleName + ".pcm");
+ llvm::sys::fs::make_absolute(Result);
+
+ if (HSOpts->DisableModuleHash) {
+ llvm::sys::path::append(Result, ModuleName + ".pcm");
+ } else {
+ // Construct the name <ModuleName>-<hash of ModuleMapPath>.pcm which should
+ // be globally unique to this particular module. To avoid false-negatives
+ // on case-insensitive filesystems, we use lower-case, which is safe because
+ // to cause a collision the modules must have the same name, which is an
+ // error if they are imported in the same translation.
+ SmallString<256> AbsModuleMapPath(ModuleMapPath);
+ llvm::sys::fs::make_absolute(AbsModuleMapPath);
+ llvm::APInt Code(64, llvm::hash_value(AbsModuleMapPath.str().lower()));
+ SmallString<128> HashStr;
+ Code.toStringUnsigned(HashStr, /*Radix*/36);
+ llvm::sys::path::append(Result, ModuleName + "-" + HashStr.str() + ".pcm");
+ }
return Result.str().str();
}
@@ -164,8 +176,8 @@ Module *HeaderSearch::lookupModule(StringRef ModuleName, bool AllowSearch) {
bool IsSystem = SearchDirs[Idx].isSystemHeaderDirectory();
// Search for a module map file in this directory.
- if (loadModuleMapFile(SearchDirs[Idx].getDir(), IsSystem)
- == LMM_NewlyLoaded) {
+ if (loadModuleMapFile(SearchDirs[Idx].getDir(), IsSystem,
+ /*IsFramework*/false) == LMM_NewlyLoaded) {
// We just loaded a module map file; check whether the module is
// available now.
Module = ModMap.findModule(ModuleName);
@@ -178,7 +190,8 @@ Module *HeaderSearch::lookupModule(StringRef ModuleName, bool AllowSearch) {
SmallString<128> NestedModuleMapDirName;
NestedModuleMapDirName = SearchDirs[Idx].getDir()->getName();
llvm::sys::path::append(NestedModuleMapDirName, ModuleName);
- if (loadModuleMapFile(NestedModuleMapDirName, IsSystem) == LMM_NewlyLoaded){
+ if (loadModuleMapFile(NestedModuleMapDirName, IsSystem,
+ /*IsFramework*/false) == LMM_NewlyLoaded){
// If we just loaded a module map file, look for the module again.
Module = ModMap.findModule(ModuleName);
if (Module)
@@ -218,51 +231,65 @@ const char *DirectoryLookup::getName() const {
return getHeaderMap()->getFileName();
}
+static const FileEntry *
+getFileAndSuggestModule(HeaderSearch &HS, StringRef FileName,
+ const DirectoryEntry *Dir, bool IsSystemHeaderDir,
+ 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);
+ }
+
+ return File;
+ }
+
+ return HS.getFileMgr().getFile(FileName, /*openFile=*/true);
+}
/// LookupFile - Lookup the specified file in this search path, returning it
/// if it exists or returning null if not.
const FileEntry *DirectoryLookup::LookupFile(
- StringRef Filename,
+ StringRef &Filename,
HeaderSearch &HS,
SmallVectorImpl<char> *SearchPath,
SmallVectorImpl<char> *RelativePath,
ModuleMap::KnownHeader *SuggestedModule,
- bool &InUserSpecifiedSystemFramework) const {
+ bool &InUserSpecifiedSystemFramework,
+ bool &HasBeenMapped,
+ SmallVectorImpl<char> &MappedName) const {
InUserSpecifiedSystemFramework = false;
+ HasBeenMapped = false;
SmallString<1024> TmpDir;
if (isNormalDir()) {
// Concatenate the requested file onto the directory.
TmpDir = getDir()->getName();
llvm::sys::path::append(TmpDir, Filename);
- if (SearchPath != NULL) {
+ if (SearchPath) {
StringRef SearchPathRef(getDir()->getName());
SearchPath->clear();
SearchPath->append(SearchPathRef.begin(), SearchPathRef.end());
}
- if (RelativePath != NULL) {
+ if (RelativePath) {
RelativePath->clear();
RelativePath->append(Filename.begin(), Filename.end());
}
-
- // 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(TmpDir, getDir(), isSystemHeaderDirectory());
- if (SuggestedModule) {
- const FileEntry *File = HS.getFileMgr().getFile(TmpDir.str(),
- /*openFile=*/false);
- if (!File)
- return File;
-
- // If there is a module that corresponds to this header, suggest it.
- *SuggestedModule = HS.findModuleForHeader(File);
- if (!SuggestedModule->getModule() &&
- HS.hasModuleMap(TmpDir, getDir(), isSystemHeaderDirectory()))
- *SuggestedModule = HS.findModuleForHeader(File);
- return File;
- }
-
- return HS.getFileMgr().getFile(TmpDir.str(), /*openFile=*/true);
+
+ return getFileAndSuggestModule(HS, TmpDir.str(), getDir(),
+ isSystemHeaderDirectory(),
+ SuggestedModule);
}
if (isFramework())
@@ -270,15 +297,35 @@ const FileEntry *DirectoryLookup::LookupFile(
SuggestedModule, InUserSpecifiedSystemFramework);
assert(isHeaderMap() && "Unknown directory lookup");
- const FileEntry * const Result = getHeaderMap()->LookupFile(
- Filename, HS.getFileMgr());
+ const HeaderMap *HM = getHeaderMap();
+ SmallString<1024> Path;
+ StringRef Dest = HM->lookupFilename(Filename, Path);
+ if (Dest.empty())
+ return nullptr;
+
+ const FileEntry *Result;
+
+ // Check if the headermap maps the filename to a framework include
+ // ("Foo.h" -> "Foo/Foo.h"), in which case continue header lookup using the
+ // framework include.
+ if (llvm::sys::path::is_relative(Dest)) {
+ MappedName.clear();
+ MappedName.append(Dest.begin(), Dest.end());
+ Filename = StringRef(MappedName.begin(), MappedName.size());
+ HasBeenMapped = true;
+ Result = HM->LookupFile(Filename, HS.getFileMgr());
+
+ } else {
+ Result = HS.getFileMgr().getFile(Dest);
+ }
+
if (Result) {
- if (SearchPath != NULL) {
+ if (SearchPath) {
StringRef SearchPathRef(getName());
SearchPath->clear();
SearchPath->append(SearchPathRef.begin(), SearchPathRef.end());
}
- if (RelativePath != NULL) {
+ if (RelativePath) {
RelativePath->clear();
RelativePath->append(Filename.begin(), Filename.end());
}
@@ -350,7 +397,7 @@ const FileEntry *DirectoryLookup::DoFrameworkLookup(
// Framework names must have a '/' in the filename.
size_t SlashPos = Filename.find('/');
- if (SlashPos == StringRef::npos) return 0;
+ if (SlashPos == StringRef::npos) return nullptr;
// Find out if this is the home for the specified framework, by checking
// HeaderSearch. Possible answers are yes/no and unknown.
@@ -359,7 +406,7 @@ const FileEntry *DirectoryLookup::DoFrameworkLookup(
// If it is known and in some other directory, fail.
if (CacheEntry.Directory && CacheEntry.Directory != getFrameworkDir())
- return 0;
+ return nullptr;
// Otherwise, construct the path to this framework dir.
@@ -377,12 +424,12 @@ const FileEntry *DirectoryLookup::DoFrameworkLookup(
FrameworkName += ".framework/";
// If the cache entry was unresolved, populate it now.
- if (CacheEntry.Directory == 0) {
+ if (!CacheEntry.Directory) {
HS.IncrementFrameworkLookupCount();
// If the framework dir doesn't exist, we fail.
const DirectoryEntry *Dir = FileMgr.getDirectory(FrameworkName.str());
- if (Dir == 0) return 0;
+ if (!Dir) return nullptr;
// Otherwise, if it does, remember that this is the right direntry for this
// framework.
@@ -402,7 +449,7 @@ const FileEntry *DirectoryLookup::DoFrameworkLookup(
// Set the 'user-specified system framework' flag.
InUserSpecifiedSystemFramework = CacheEntry.IsUserSpecifiedSystemFramework;
- if (RelativePath != NULL) {
+ if (RelativePath) {
RelativePath->clear();
RelativePath->append(Filename.begin()+SlashPos+1, Filename.end());
}
@@ -412,7 +459,7 @@ const FileEntry *DirectoryLookup::DoFrameworkLookup(
FrameworkName += "Headers/";
- if (SearchPath != NULL) {
+ if (SearchPath) {
SearchPath->clear();
// Without trailing '/'.
SearchPath->append(FrameworkName.begin(), FrameworkName.end()-1);
@@ -426,7 +473,7 @@ const FileEntry *DirectoryLookup::DoFrameworkLookup(
const char *Private = "Private";
FrameworkName.insert(FrameworkName.begin()+OrigSize, Private,
Private+strlen(Private));
- if (SearchPath != NULL)
+ if (SearchPath)
SearchPath->insert(SearchPath->begin()+OrigSize, Private,
Private+strlen(Private));
@@ -436,14 +483,9 @@ const FileEntry *DirectoryLookup::DoFrameworkLookup(
// If we found the header and are allowed to suggest a module, do so now.
if (FE && SuggestedModule) {
// Find the framework in which this header occurs.
- StringRef FrameworkPath = FE->getName();
+ StringRef FrameworkPath = FE->getDir()->getName();
bool FoundFramework = false;
do {
- // Get the parent directory name.
- FrameworkPath = llvm::sys::path::parent_path(FrameworkPath);
- if (FrameworkPath.empty())
- break;
-
// Determine whether this directory exists.
const DirectoryEntry *Dir = FileMgr.getDirectory(FrameworkPath);
if (!Dir)
@@ -455,6 +497,11 @@ const FileEntry *DirectoryLookup::DoFrameworkLookup(
FoundFramework = true;
break;
}
+
+ // Get the parent directory name.
+ FrameworkPath = llvm::sys::path::parent_path(FrameworkPath);
+ if (FrameworkPath.empty())
+ break;
} while (true);
if (FoundFramework) {
@@ -488,28 +535,43 @@ void HeaderSearch::setTarget(const TargetInfo &Target) {
// Header File Location.
//===----------------------------------------------------------------------===//
+/// \brief 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,
+ const FileEntry *MSFE, const FileEntry *FE,
+ SourceLocation IncludeLoc) {
+ if (MSFE && FE != MSFE) {
+ Diags.Report(IncludeLoc, diag::ext_pp_include_search_ms) << MSFE->getName();
+ return true;
+ }
+ return false;
+}
+
+static const char *copyString(StringRef Str, llvm::BumpPtrAllocator &Alloc) {
+ assert(!Str.empty());
+ char *CopyStr = Alloc.Allocate<char>(Str.size()+1);
+ std::copy(Str.begin(), Str.end(), CopyStr);
+ CopyStr[Str.size()] = '\0';
+ return CopyStr;
+}
/// 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 ""). CurFileEnt, if
-/// non-null, indicates where the \#including file is, in case a relative search
-/// is needed.
+/// for system \#include's or not (i.e. using <> instead of ""). Includers, if
+/// non-empty, indicates where the \#including file(s) are, in case a relative
+/// search is needed. Microsoft mode will pass all \#including files.
const FileEntry *HeaderSearch::LookupFile(
- StringRef Filename,
- bool isAngled,
- const DirectoryLookup *FromDir,
- const DirectoryLookup *&CurDir,
- const FileEntry *CurFileEnt,
- SmallVectorImpl<char> *SearchPath,
+ StringRef Filename, SourceLocation IncludeLoc, bool isAngled,
+ const DirectoryLookup *FromDir, const DirectoryLookup *&CurDir,
+ ArrayRef<const FileEntry *> Includers, SmallVectorImpl<char> *SearchPath,
SmallVectorImpl<char> *RelativePath,
- ModuleMap::KnownHeader *SuggestedModule,
- bool SkipCache)
-{
+ ModuleMap::KnownHeader *SuggestedModule, bool SkipCache) {
if (!HSOpts->ModuleMapFiles.empty()) {
// Preload all explicitly specified module map files. This enables modules
// map files lying in a directory structure separate from the header files
// that they describe. These cannot be loaded lazily upon encountering a
- // header file, as there is no other knwon mapping from a header file to its
+ // header file, as there is no other known mapping from a header file to its
// module map file.
for (llvm::SetVector<std::string>::iterator
I = HSOpts->ModuleMapFiles.begin(),
@@ -528,14 +590,14 @@ const FileEntry *HeaderSearch::LookupFile(
// If 'Filename' is absolute, check to see if it exists and no searching.
if (llvm::sys::path::is_absolute(Filename)) {
- CurDir = 0;
+ CurDir = nullptr;
// If this was an #include_next "/absolute/file", fail.
- if (FromDir) return 0;
+ if (FromDir) return nullptr;
- if (SearchPath != NULL)
+ if (SearchPath)
SearchPath->clear();
- if (RelativePath != NULL) {
+ if (RelativePath) {
RelativePath->clear();
RelativePath->append(Filename.begin(), Filename.end());
}
@@ -543,49 +605,82 @@ const FileEntry *HeaderSearch::LookupFile(
return FileMgr.getFile(Filename, /*openFile=*/true);
}
+ // This is the header that MSVC's header search would have found.
+ const FileEntry *MSFE = nullptr;
+ ModuleMap::KnownHeader MSSuggestedModule;
+
// Unless disabled, check to see if the file is in the #includer's
- // directory. This has to be based on CurFileEnt, not CurDir, because
- // CurFileEnt could be a #include of a subdirectory (#include "foo/bar.h") and
- // a subsequent include of "baz.h" should resolve to "whatever/foo/baz.h".
+ // directory. This cannot be based on CurDir, because each includer could be
+ // a #include of a subdirectory (#include "foo/bar.h") and a subsequent
+ // include of "baz.h" should resolve to "whatever/foo/baz.h".
// This search is not done for <> headers.
- if (CurFileEnt && !isAngled && !NoCurDirSearch) {
+ if (!Includers.empty() && !isAngled && !NoCurDirSearch) {
SmallString<1024> TmpDir;
- // Concatenate the requested file onto the directory.
- // FIXME: Portability. Filename concatenation should be in sys::Path.
- TmpDir += CurFileEnt->getDir()->getName();
- TmpDir.push_back('/');
- TmpDir.append(Filename.begin(), Filename.end());
- if (const FileEntry *FE = FileMgr.getFile(TmpDir.str(),/*openFile=*/true)) {
- // Leave CurDir unset.
- // This file is a system header or C++ unfriendly if the old file is.
- //
- // Note that we only use one of FromHFI/ToHFI at once, due to potential
- // reallocation of the underlying vector potentially making the first
- // reference binding dangling.
- HeaderFileInfo &FromHFI = getFileInfo(CurFileEnt);
- unsigned DirInfo = FromHFI.DirInfo;
- bool IndexHeaderMapHeader = FromHFI.IndexHeaderMapHeader;
- StringRef Framework = FromHFI.Framework;
-
- HeaderFileInfo &ToHFI = getFileInfo(FE);
- ToHFI.DirInfo = DirInfo;
- ToHFI.IndexHeaderMapHeader = IndexHeaderMapHeader;
- ToHFI.Framework = Framework;
-
- if (SearchPath != NULL) {
- StringRef SearchPathRef(CurFileEnt->getDir()->getName());
- SearchPath->clear();
- SearchPath->append(SearchPathRef.begin(), SearchPathRef.end());
- }
- if (RelativePath != NULL) {
- RelativePath->clear();
- RelativePath->append(Filename.begin(), Filename.end());
+ for (ArrayRef<const FileEntry *>::iterator I = Includers.begin(),
+ E = Includers.end();
+ I != E; ++I) {
+ const FileEntry *Includer = *I;
+ // Concatenate the requested file onto the directory.
+ // FIXME: Portability. Filename concatenation should be in sys::Path.
+ TmpDir = Includer->getDir()->getName();
+ TmpDir.push_back('/');
+ TmpDir.append(Filename.begin(), Filename.end());
+
+ // FIXME: We don't cache the result of getFileInfo across the call to
+ // getFileAndSuggestModule, because it's a reference to an element of
+ // a container that could be reallocated across this call.
+ bool IncluderIsSystemHeader =
+ getFileInfo(Includer).DirInfo != SrcMgr::C_User;
+ if (const FileEntry *FE =
+ getFileAndSuggestModule(*this, TmpDir.str(), Includer->getDir(),
+ IncluderIsSystemHeader,
+ SuggestedModule)) {
+ // Leave CurDir unset.
+ // This file is a system header or C++ unfriendly if the old file is.
+ //
+ // Note that we only use one of FromHFI/ToHFI at once, due to potential
+ // reallocation of the underlying vector potentially making the first
+ // reference binding dangling.
+ HeaderFileInfo &FromHFI = getFileInfo(Includer);
+ unsigned DirInfo = FromHFI.DirInfo;
+ bool IndexHeaderMapHeader = FromHFI.IndexHeaderMapHeader;
+ StringRef Framework = FromHFI.Framework;
+
+ HeaderFileInfo &ToHFI = getFileInfo(FE);
+ ToHFI.DirInfo = DirInfo;
+ ToHFI.IndexHeaderMapHeader = IndexHeaderMapHeader;
+ ToHFI.Framework = Framework;
+
+ if (SearchPath) {
+ StringRef SearchPathRef(Includer->getDir()->getName());
+ SearchPath->clear();
+ SearchPath->append(SearchPathRef.begin(), SearchPathRef.end());
+ }
+ if (RelativePath) {
+ RelativePath->clear();
+ RelativePath->append(Filename.begin(), Filename.end());
+ }
+ if (I == Includers.begin())
+ 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
+ // would've found this header in -I or -isystem directories.
+ if (Diags.isIgnored(diag::ext_pp_include_search_ms, IncludeLoc)) {
+ return FE;
+ } else {
+ MSFE = FE;
+ if (SuggestedModule) {
+ MSSuggestedModule = *SuggestedModule;
+ *SuggestedModule = ModuleMap::KnownHeader();
+ }
+ break;
+ }
}
- return FE;
}
}
- CurDir = 0;
+ CurDir = nullptr;
// If this is a system #include, ignore the user #include locs.
unsigned i = isAngled ? AngledDirIdx : 0;
@@ -599,28 +694,38 @@ const FileEntry *HeaderSearch::LookupFile(
// multiply included, and the "pragma once" optimization prevents them from
// being relex/pp'd, but they would still have to search through a
// (potentially huge) series of SearchDirs to find it.
- std::pair<unsigned, unsigned> &CacheLookup =
+ LookupFileCacheInfo &CacheLookup =
LookupFileCache.GetOrCreateValue(Filename).getValue();
// If the entry has been previously looked up, the first value will be
// non-zero. If the value is equal to i (the start point of our search), then
// this is a matching hit.
- if (!SkipCache && CacheLookup.first == i+1) {
+ if (!SkipCache && CacheLookup.StartIdx == i+1) {
// Skip querying potentially lots of directories for this lookup.
- i = CacheLookup.second;
+ i = CacheLookup.HitIdx;
+ if (CacheLookup.MappedName)
+ Filename = CacheLookup.MappedName;
} else {
// Otherwise, this is the first query, or the previous query didn't match
// our search start. We will fill in our found location below, so prime the
// start point value.
- CacheLookup.first = i+1;
+ CacheLookup.reset(/*StartIdx=*/i+1);
}
+ SmallString<64> MappedName;
+
// Check each directory in sequence to see if it contains this file.
for (; i != SearchDirs.size(); ++i) {
bool InUserSpecifiedSystemFramework = false;
+ bool HasBeenMapped = false;
const FileEntry *FE =
SearchDirs[i].LookupFile(Filename, *this, SearchPath, RelativePath,
- SuggestedModule, InUserSpecifiedSystemFramework);
+ SuggestedModule, InUserSpecifiedSystemFramework,
+ HasBeenMapped, MappedName);
+ if (HasBeenMapped) {
+ CacheLookup.MappedName =
+ copyString(Filename, LookupFileCache.getAllocator());
+ }
if (!FE) continue;
CurDir = &SearchDirs[i];
@@ -655,9 +760,15 @@ const FileEntry *HeaderSearch::LookupFile(
SlashPos));
}
}
-
+
+ if (checkMSVCHeaderSearch(Diags, MSFE, FE, IncludeLoc)) {
+ if (SuggestedModule)
+ *SuggestedModule = MSSuggestedModule;
+ return MSFE;
+ }
+
// Remember this location for the next lookup we do.
- CacheLookup.second = i;
+ CacheLookup.HitIdx = i;
return FE;
}
@@ -665,29 +776,43 @@ const FileEntry *HeaderSearch::LookupFile(
// a header in a framework that is currently being built, and we couldn't
// resolve "foo.h" any other way, change the include to <Foo/foo.h>, where
// "Foo" is the name of the framework in which the including header was found.
- if (CurFileEnt && !isAngled && Filename.find('/') == StringRef::npos) {
- HeaderFileInfo &IncludingHFI = getFileInfo(CurFileEnt);
+ if (!Includers.empty() && !isAngled &&
+ Filename.find('/') == StringRef::npos) {
+ HeaderFileInfo &IncludingHFI = getFileInfo(Includers.front());
if (IncludingHFI.IndexHeaderMapHeader) {
SmallString<128> ScratchFilename;
ScratchFilename += IncludingHFI.Framework;
ScratchFilename += '/';
ScratchFilename += Filename;
-
- const FileEntry *Result = LookupFile(ScratchFilename, /*isAngled=*/true,
- FromDir, CurDir, CurFileEnt,
- SearchPath, RelativePath,
- SuggestedModule);
- std::pair<unsigned, unsigned> &CacheLookup
+
+ const FileEntry *FE = LookupFile(
+ ScratchFilename, IncludeLoc, /*isAngled=*/true, FromDir, CurDir,
+ Includers.front(), SearchPath, RelativePath, SuggestedModule);
+
+ if (checkMSVCHeaderSearch(Diags, MSFE, FE, IncludeLoc)) {
+ if (SuggestedModule)
+ *SuggestedModule = MSSuggestedModule;
+ return MSFE;
+ }
+
+ LookupFileCacheInfo &CacheLookup
= LookupFileCache.GetOrCreateValue(Filename).getValue();
- CacheLookup.second
- = LookupFileCache.GetOrCreateValue(ScratchFilename).getValue().second;
- return Result;
+ CacheLookup.HitIdx
+ = LookupFileCache.GetOrCreateValue(ScratchFilename).getValue().HitIdx;
+ // FIXME: SuggestedModule.
+ return FE;
}
}
+ if (checkMSVCHeaderSearch(Diags, MSFE, nullptr, IncludeLoc)) {
+ if (SuggestedModule)
+ *SuggestedModule = MSSuggestedModule;
+ return MSFE;
+ }
+
// Otherwise, didn't find it. Remember we didn't find this.
- CacheLookup.second = SearchDirs.size();
- return 0;
+ CacheLookup.HitIdx = SearchDirs.size();
+ return nullptr;
}
/// LookupSubframeworkHeader - Look up a subframework for the specified
@@ -706,7 +831,7 @@ LookupSubframeworkHeader(StringRef Filename,
// Framework names must have a '/' in the filename. Find it.
// FIXME: Should we permit '\' on Windows?
size_t SlashPos = Filename.find('/');
- if (SlashPos == StringRef::npos) return 0;
+ if (SlashPos == StringRef::npos) return nullptr;
// Look up the base framework name of the ContextFileEnt.
const char *ContextName = ContextFileEnt->getName();
@@ -714,10 +839,10 @@ LookupSubframeworkHeader(StringRef Filename,
// If the context info wasn't a framework, couldn't be a subframework.
const unsigned DotFrameworkLen = 10;
const char *FrameworkPos = strstr(ContextName, ".framework");
- if (FrameworkPos == 0 ||
+ if (FrameworkPos == nullptr ||
(FrameworkPos[DotFrameworkLen] != '/' &&
FrameworkPos[DotFrameworkLen] != '\\'))
- return 0;
+ return nullptr;
SmallString<1024> FrameworkName(ContextName, FrameworkPos+DotFrameworkLen+1);
@@ -734,24 +859,24 @@ LookupSubframeworkHeader(StringRef Filename,
CacheLookup.getKeyLength() == FrameworkName.size() &&
memcmp(CacheLookup.getKeyData(), &FrameworkName[0],
CacheLookup.getKeyLength()) != 0)
- return 0;
+ return nullptr;
// Cache subframework.
- if (CacheLookup.getValue().Directory == 0) {
+ if (!CacheLookup.getValue().Directory) {
++NumSubFrameworkLookups;
// If the framework dir doesn't exist, we fail.
const DirectoryEntry *Dir = FileMgr.getDirectory(FrameworkName.str());
- if (Dir == 0) return 0;
+ if (!Dir) return nullptr;
// Otherwise, if it does, remember that this is the right direntry for this
// framework.
CacheLookup.getValue().Directory = Dir;
}
- const FileEntry *FE = 0;
+ const FileEntry *FE = nullptr;
- if (RelativePath != NULL) {
+ if (RelativePath) {
RelativePath->clear();
RelativePath->append(Filename.begin()+SlashPos+1, Filename.end());
}
@@ -759,7 +884,7 @@ LookupSubframeworkHeader(StringRef Filename,
// Check ".../Frameworks/HIToolbox.framework/Headers/HIToolbox.h"
SmallString<1024> HeadersFilename(FrameworkName);
HeadersFilename += "Headers/";
- if (SearchPath != NULL) {
+ if (SearchPath) {
SearchPath->clear();
// Without trailing '/'.
SearchPath->append(HeadersFilename.begin(), HeadersFilename.end()-1);
@@ -771,7 +896,7 @@ LookupSubframeworkHeader(StringRef Filename,
// Check ".../Frameworks/HIToolbox.framework/PrivateHeaders/HIToolbox.h"
HeadersFilename = FrameworkName;
HeadersFilename += "PrivateHeaders/";
- if (SearchPath != NULL) {
+ if (SearchPath) {
SearchPath->clear();
// Without trailing '/'.
SearchPath->append(HeadersFilename.begin(), HeadersFilename.end()-1);
@@ -779,7 +904,7 @@ LookupSubframeworkHeader(StringRef Filename,
HeadersFilename.append(Filename.begin()+SlashPos+1, Filename.end());
if (!(FE = FileMgr.getFile(HeadersFilename.str(), /*openFile=*/true)))
- return 0;
+ return nullptr;
}
// This file is a system header or C++ unfriendly if the old file is.
@@ -873,9 +998,21 @@ HeaderFileInfo &HeaderSearch::getFileInfo(const FileEntry *FE) {
HeaderFileInfo &HFI = FileInfo[FE->getUID()];
if (ExternalSource && !HFI.Resolved)
mergeHeaderFileInfo(HFI, ExternalSource->GetHeaderFileInfo(FE));
+ HFI.IsValid = 1;
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;
+ }
+ return false;
+}
+
bool HeaderSearch::isFileMultipleIncludeGuarded(const FileEntry *File) {
// Check if we've ever seen this file as a header.
if (File->getUID() >= FileInfo.size())
@@ -953,6 +1090,9 @@ StringRef HeaderSearch::getUniqueFrameworkName(StringRef Framework) {
bool HeaderSearch::hasModuleMap(StringRef FileName,
const DirectoryEntry *Root,
bool IsSystem) {
+ if (!enabledModules())
+ return false;
+
SmallVector<const DirectoryEntry *, 2> FixUpDirectories;
StringRef DirName = FileName;
@@ -967,8 +1107,8 @@ bool HeaderSearch::hasModuleMap(StringRef FileName,
if (!Dir)
return false;
- // Try to load the "module.map" file in this directory.
- switch (loadModuleMapFile(Dir, IsSystem)) {
+ // Try to load the module map file in this directory.
+ switch (loadModuleMapFile(Dir, IsSystem, /*IsFramework*/false)) {
case LMM_NewlyLoaded:
case LMM_AlreadyLoaded:
// Success. All of the directories we stepped through inherit this module
@@ -1002,122 +1142,127 @@ HeaderSearch::findModuleForHeader(const FileEntry *File) const {
return ModMap.findModuleForHeader(File);
}
+static const FileEntry *getPrivateModuleMap(StringRef ModuleMapPath,
+ const DirectoryEntry *Directory,
+ FileManager &FileMgr) {
+ StringRef Filename = llvm::sys::path::filename(ModuleMapPath);
+ SmallString<128> PrivateFilename(Directory->getName());
+ if (Filename == "module.map")
+ llvm::sys::path::append(PrivateFilename, "module_private.map");
+ else if (Filename == "module.modulemap")
+ llvm::sys::path::append(PrivateFilename, "module.private.modulemap");
+ else
+ return nullptr;
+ return FileMgr.getFile(PrivateFilename);
+}
+
bool HeaderSearch::loadModuleMapFile(const FileEntry *File, bool IsSystem) {
+ switch (loadModuleMapFileImpl(File, IsSystem)) {
+ case LMM_AlreadyLoaded:
+ case LMM_NewlyLoaded:
+ return false;
+ case LMM_NoDirectory:
+ case LMM_InvalidModuleMap:
+ return true;
+ }
+ llvm_unreachable("Unknown load module map result");
+}
+
+HeaderSearch::LoadModuleMapResult
+HeaderSearch::loadModuleMapFileImpl(const FileEntry *File, bool IsSystem) {
+ assert(File && "expected FileEntry");
+
const DirectoryEntry *Dir = File->getDir();
-
- llvm::DenseMap<const DirectoryEntry *, bool>::iterator KnownDir
- = DirectoryHasModuleMap.find(Dir);
+ auto KnownDir = DirectoryHasModuleMap.find(Dir);
if (KnownDir != DirectoryHasModuleMap.end())
- return !KnownDir->second;
-
- bool Result = ModMap.parseModuleMapFile(File, IsSystem);
- if (!Result && llvm::sys::path::filename(File->getName()) == "module.map") {
- // If the file we loaded was a module.map, look for the corresponding
- // module_private.map.
- SmallString<128> PrivateFilename(Dir->getName());
- llvm::sys::path::append(PrivateFilename, "module_private.map");
- if (const FileEntry *PrivateFile = FileMgr.getFile(PrivateFilename))
- Result = ModMap.parseModuleMapFile(PrivateFile, IsSystem);
+ return KnownDir->second ? LMM_AlreadyLoaded : LMM_InvalidModuleMap;
+
+ if (ModMap.parseModuleMapFile(File, IsSystem)) {
+ DirectoryHasModuleMap[Dir] = false;
+ return LMM_InvalidModuleMap;
}
-
- DirectoryHasModuleMap[Dir] = !Result;
- return Result;
+
+ // Try to load a corresponding private module map.
+ if (const FileEntry *PMMFile =
+ getPrivateModuleMap(File->getName(), Dir, FileMgr)) {
+ if (ModMap.parseModuleMapFile(PMMFile, IsSystem)) {
+ DirectoryHasModuleMap[Dir] = false;
+ return LMM_InvalidModuleMap;
+ }
+ }
+
+ // This directory has a module map.
+ DirectoryHasModuleMap[Dir] = true;
+ return LMM_NewlyLoaded;
}
-Module *HeaderSearch::loadFrameworkModule(StringRef Name,
+const FileEntry *
+HeaderSearch::lookupModuleMapFile(const DirectoryEntry *Dir, bool IsFramework) {
+ // For frameworks, the preferred spelling is Modules/module.modulemap, but
+ // module.map at the framework root is also accepted.
+ SmallString<128> ModuleMapFileName(Dir->getName());
+ if (IsFramework)
+ llvm::sys::path::append(ModuleMapFileName, "Modules");
+ llvm::sys::path::append(ModuleMapFileName, "module.modulemap");
+ if (const FileEntry *F = FileMgr.getFile(ModuleMapFileName))
+ return F;
+
+ // Continue to allow module.map
+ ModuleMapFileName = Dir->getName();
+ llvm::sys::path::append(ModuleMapFileName, "module.map");
+ return FileMgr.getFile(ModuleMapFileName);
+}
+
+Module *HeaderSearch::loadFrameworkModule(StringRef Name,
const DirectoryEntry *Dir,
bool IsSystem) {
if (Module *Module = ModMap.findModule(Name))
return Module;
// Try to load a module map file.
- switch (loadModuleMapFile(Dir, IsSystem)) {
+ switch (loadModuleMapFile(Dir, IsSystem, /*IsFramework*/true)) {
case LMM_InvalidModuleMap:
break;
case LMM_AlreadyLoaded:
case LMM_NoDirectory:
- return 0;
-
+ return nullptr;
+
case LMM_NewlyLoaded:
return ModMap.findModule(Name);
}
- // Figure out the top-level framework directory and the submodule path from
- // that top-level framework to the requested framework.
- SmallVector<std::string, 2> SubmodulePath;
- SubmodulePath.push_back(Name);
- const DirectoryEntry *TopFrameworkDir
- = ::getTopFrameworkDir(FileMgr, Dir->getName(), SubmodulePath);
-
-
- // Try to infer a module map from the top-level framework directory.
- Module *Result = ModMap.inferFrameworkModule(SubmodulePath.back(),
- TopFrameworkDir,
- IsSystem,
- /*Parent=*/0);
- if (!Result)
- return 0;
-
- // Follow the submodule path to find the requested (sub)framework module
- // within the top-level framework module.
- SubmodulePath.pop_back();
- while (!SubmodulePath.empty() && Result) {
- Result = ModMap.lookupModuleQualified(SubmodulePath.back(), Result);
- SubmodulePath.pop_back();
- }
- return Result;
+
+ // Try to infer a module map from the framework directory.
+ return ModMap.inferFrameworkModule(Name, Dir, IsSystem, /*Parent=*/nullptr);
}
HeaderSearch::LoadModuleMapResult
-HeaderSearch::loadModuleMapFile(StringRef DirName, bool IsSystem) {
+HeaderSearch::loadModuleMapFile(StringRef DirName, bool IsSystem,
+ bool IsFramework) {
if (const DirectoryEntry *Dir = FileMgr.getDirectory(DirName))
- return loadModuleMapFile(Dir, IsSystem);
+ return loadModuleMapFile(Dir, IsSystem, IsFramework);
return LMM_NoDirectory;
}
HeaderSearch::LoadModuleMapResult
-HeaderSearch::loadModuleMapFile(const DirectoryEntry *Dir, bool IsSystem) {
- llvm::DenseMap<const DirectoryEntry *, bool>::iterator KnownDir
- = DirectoryHasModuleMap.find(Dir);
+HeaderSearch::loadModuleMapFile(const DirectoryEntry *Dir, bool IsSystem,
+ bool IsFramework) {
+ auto KnownDir = DirectoryHasModuleMap.find(Dir);
if (KnownDir != DirectoryHasModuleMap.end())
return KnownDir->second? LMM_AlreadyLoaded : LMM_InvalidModuleMap;
-
- SmallString<128> ModuleMapFileName;
- ModuleMapFileName += Dir->getName();
- unsigned ModuleMapDirNameLen = ModuleMapFileName.size();
- llvm::sys::path::append(ModuleMapFileName, "module.map");
- if (const FileEntry *ModuleMapFile = FileMgr.getFile(ModuleMapFileName)) {
- // We have found a module map file. Try to parse it.
- if (ModMap.parseModuleMapFile(ModuleMapFile, IsSystem)) {
- // No suitable module map.
- DirectoryHasModuleMap[Dir] = false;
- return LMM_InvalidModuleMap;
- }
- // This directory has a module map.
- DirectoryHasModuleMap[Dir] = true;
-
- // Check whether there is a private module map that we need to load as well.
- ModuleMapFileName.erase(ModuleMapFileName.begin() + ModuleMapDirNameLen,
- ModuleMapFileName.end());
- llvm::sys::path::append(ModuleMapFileName, "module_private.map");
- if (const FileEntry *PrivateModuleMapFile
- = FileMgr.getFile(ModuleMapFileName)) {
- if (ModMap.parseModuleMapFile(PrivateModuleMapFile, IsSystem)) {
- // No suitable module map.
- DirectoryHasModuleMap[Dir] = false;
- return LMM_InvalidModuleMap;
- }
- }
-
- return LMM_NewlyLoaded;
+ if (const FileEntry *ModuleMapFile = lookupModuleMapFile(Dir, IsFramework)) {
+ LoadModuleMapResult Result = loadModuleMapFileImpl(ModuleMapFile, IsSystem);
+ // Add Dir explicitly in case ModuleMapFile is in a subdirectory.
+ // E.g. Foo.framework/Modules/module.modulemap
+ // ^Dir ^ModuleMapFile
+ if (Result == LMM_NewlyLoaded)
+ DirectoryHasModuleMap[Dir] = true;
+ return Result;
}
-
- // No suitable module map.
- DirectoryHasModuleMap[Dir] = false;
return LMM_InvalidModuleMap;
}
@@ -1128,7 +1273,7 @@ void HeaderSearch::collectAllModules(SmallVectorImpl<Module *> &Modules) {
for (unsigned Idx = 0, N = SearchDirs.size(); Idx != N; ++Idx) {
bool IsSystem = SearchDirs[Idx].isSystemHeaderDirectory();
if (SearchDirs[Idx].isFramework()) {
- llvm::error_code EC;
+ std::error_code EC;
SmallString<128> DirNative;
llvm::sys::path::native(SearchDirs[Idx].getFrameworkDir()->getName(),
DirNative);
@@ -1155,7 +1300,7 @@ void HeaderSearch::collectAllModules(SmallVectorImpl<Module *> &Modules) {
continue;
// Try to load a module map file for the search directory.
- loadModuleMapFile(SearchDirs[Idx].getDir(), IsSystem);
+ loadModuleMapFile(SearchDirs[Idx].getDir(), IsSystem, /*IsFramework*/false);
// Try to load module map files for immediate subdirectories of this search
// directory.
@@ -1180,20 +1325,22 @@ void HeaderSearch::loadTopLevelSystemModules() {
// Try to load a module map file for the search directory.
loadModuleMapFile(SearchDirs[Idx].getDir(),
- SearchDirs[Idx].isSystemHeaderDirectory());
+ SearchDirs[Idx].isSystemHeaderDirectory(),
+ SearchDirs[Idx].isFramework());
}
}
void HeaderSearch::loadSubdirectoryModuleMaps(DirectoryLookup &SearchDir) {
if (SearchDir.haveSearchedAllModuleMaps())
return;
-
- llvm::error_code EC;
+
+ std::error_code EC;
SmallString<128> DirNative;
llvm::sys::path::native(SearchDir.getDir()->getName(), DirNative);
for (llvm::sys::fs::directory_iterator Dir(DirNative.str(), EC), DirEnd;
Dir != DirEnd && !EC; Dir.increment(EC)) {
- loadModuleMapFile(Dir->path(), SearchDir.isSystemHeaderDirectory());
+ loadModuleMapFile(Dir->path(), SearchDir.isSystemHeaderDirectory(),
+ SearchDir.isFramework());
}
SearchDir.setSearchedAllModuleMaps(true);
diff --git a/lib/Lex/Lexer.cpp b/lib/Lex/Lexer.cpp
index c071455da662..6f6b50b246d7 100644
--- a/lib/Lex/Lexer.cpp
+++ b/lib/Lex/Lexer.cpp
@@ -10,21 +10,9 @@
// This file implements the Lexer and Token interfaces.
//
//===----------------------------------------------------------------------===//
-//
-// TODO: GCC Diagnostics emitted by the lexer:
-// PEDWARN: (form feed|vertical tab) in preprocessing directive
-//
-// Universal characters, unicode, char mapping:
-// WARNING: `%.*s' is not in NFKC
-// WARNING: `%.*s' is not in NFC
-//
-// Other:
-// TODO: Options to support:
-// -fexec-charset,-fwide-exec-charset
-//
-//===----------------------------------------------------------------------===//
#include "clang/Lex/Lexer.h"
+#include "UnicodeCharSets.h"
#include "clang/Basic/CharInfo.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Lex/CodeCompletionHandler.h"
@@ -37,7 +25,6 @@
#include "llvm/Support/Compiler.h"
#include "llvm/Support/ConvertUTF.h"
#include "llvm/Support/MemoryBuffer.h"
-#include "UnicodeCharSets.h"
#include <cstring>
using namespace clang;
@@ -174,7 +161,7 @@ Lexer::Lexer(FileID FID, const llvm::MemoryBuffer *FromFile,
/// expansion location that indicates where all lexed tokens should be
/// "expanded from".
///
-/// FIXME: It would really be nice to make _Pragma just be a wrapper around a
+/// TODO: It would really be nice to make _Pragma just be a wrapper around a
/// normal lexer that remaps tokens as they fly by. This would require making
/// Preprocessor::Lex virtual. Given that, we could just dump in a magic lexer
/// interface that could handle this stuff. This would pull GetMappedTokenLoc
@@ -379,10 +366,10 @@ unsigned Lexer::getSpelling(const Token &Tok, const char *&Buffer,
const LangOptions &LangOpts, bool *Invalid) {
assert((int)Tok.getLength() >= 0 && "Token character range is bogus!");
- const char *TokStart = 0;
+ const char *TokStart = nullptr;
// NOTE: this has to be checked *before* testing for an IdentifierInfo.
if (Tok.is(tok::raw_identifier))
- TokStart = Tok.getRawIdentifierData();
+ TokStart = Tok.getRawIdentifier().data();
else if (!Tok.hasUCN()) {
if (const IdentifierInfo *II = Tok.getIdentifierInfo()) {
// Just return the string from the identifier table, which is very quick.
@@ -395,7 +382,7 @@ unsigned Lexer::getSpelling(const Token &Tok, const char *&Buffer,
if (Tok.isLiteral())
TokStart = Tok.getLiteralData();
- if (TokStart == 0) {
+ if (!TokStart) {
// Compute the start of the token in the input lexer buffer.
bool CharDataInvalid = false;
TokStart = SourceMgr.getCharacterData(Tok.getLocation(), &CharDataInvalid);
@@ -637,8 +624,7 @@ Lexer::ComputePreamble(const llvm::MemoryBuffer *Buffer,
// the raw identifier to recognize and categorize preprocessor directives.
TheLexer.LexFromRawLexer(TheTok);
if (TheTok.getKind() == tok::raw_identifier && !TheTok.needsCleaning()) {
- StringRef Keyword(TheTok.getRawIdentifierData(),
- TheTok.getLength());
+ StringRef Keyword = TheTok.getRawIdentifier();
PreambleDirectiveKind PDK
= llvm::StringSwitch<PreambleDirectiveKind>(Keyword)
.Case("include", PDK_Skipped)
@@ -861,7 +847,7 @@ static CharSourceRange makeRangeFromFileLocs(CharSourceRange Range,
// Break down the source locations.
FileID FID;
unsigned BeginOffs;
- llvm::tie(FID, BeginOffs) = SM.getDecomposedLoc(Begin);
+ std::tie(FID, BeginOffs) = SM.getDecomposedLoc(Begin);
if (FID.isInvalid())
return CharSourceRange();
@@ -1287,7 +1273,7 @@ Slash:
if (Ptr[0] == '?' && Ptr[1] == '?') {
// If this is actually a legal trigraph (not something like "??x"), emit
// a trigraph warning. If so, and if trigraphs are enabled, return it.
- if (char C = DecodeTrigraphChar(Ptr+2, Tok ? this : 0)) {
+ if (char C = DecodeTrigraphChar(Ptr+2, Tok ? this : nullptr)) {
// Remember that this token needs to be cleaned.
if (Tok) Tok->setFlag(Token::NeedsCleaning);
@@ -1413,8 +1399,7 @@ static inline CharSourceRange makeCharRange(Lexer &L, const char *Begin,
static void maybeDiagnoseIDCharCompat(DiagnosticsEngine &Diags, uint32_t C,
CharSourceRange Range, bool IsFirst) {
// Check C99 compatibility.
- if (Diags.getDiagnosticLevel(diag::warn_c99_compat_unicode_id,
- Range.getBegin()) > DiagnosticsEngine::Ignored) {
+ if (!Diags.isIgnored(diag::warn_c99_compat_unicode_id, Range.getBegin())) {
enum {
CannotAppearInIdentifier = 0,
CannotStartIdentifier
@@ -1436,8 +1421,7 @@ static void maybeDiagnoseIDCharCompat(DiagnosticsEngine &Diags, uint32_t C,
}
// Check C++98 compatibility.
- if (Diags.getDiagnosticLevel(diag::warn_cxx98_compat_unicode_id,
- Range.getBegin()) > DiagnosticsEngine::Ignored) {
+ if (!Diags.isIgnored(diag::warn_cxx98_compat_unicode_id, Range.getBegin())) {
static const llvm::sys::UnicodeCharSet CXX03AllowedIDChars(
CXX03AllowedIDCharRanges);
if (!CXX03AllowedIDChars.contains(C)) {
@@ -1445,7 +1429,50 @@ static void maybeDiagnoseIDCharCompat(DiagnosticsEngine &Diags, uint32_t C,
<< Range;
}
}
- }
+}
+
+bool Lexer::tryConsumeIdentifierUCN(const char *&CurPtr, unsigned Size,
+ Token &Result) {
+ const char *UCNPtr = CurPtr + Size;
+ uint32_t CodePoint = tryReadUCN(UCNPtr, CurPtr, /*Token=*/nullptr);
+ if (CodePoint == 0 || !isAllowedIDChar(CodePoint, LangOpts))
+ return false;
+
+ if (!isLexingRawMode())
+ maybeDiagnoseIDCharCompat(PP->getDiagnostics(), CodePoint,
+ makeCharRange(*this, CurPtr, UCNPtr),
+ /*IsFirst=*/false);
+
+ Result.setFlag(Token::HasUCN);
+ if ((UCNPtr - CurPtr == 6 && CurPtr[1] == 'u') ||
+ (UCNPtr - CurPtr == 10 && CurPtr[1] == 'U'))
+ CurPtr = UCNPtr;
+ else
+ while (CurPtr != UCNPtr)
+ (void)getAndAdvanceChar(CurPtr, Result);
+ return true;
+}
+
+bool Lexer::tryConsumeIdentifierUTF8Char(const char *&CurPtr) {
+ const char *UnicodePtr = CurPtr;
+ UTF32 CodePoint;
+ ConversionResult Result =
+ llvm::convertUTF8Sequence((const UTF8 **)&UnicodePtr,
+ (const UTF8 *)BufferEnd,
+ &CodePoint,
+ strictConversion);
+ if (Result != conversionOK ||
+ !isAllowedIDChar(static_cast<uint32_t>(CodePoint), LangOpts))
+ return false;
+
+ if (!isLexingRawMode())
+ maybeDiagnoseIDCharCompat(PP->getDiagnostics(), CodePoint,
+ makeCharRange(*this, CurPtr, UnicodePtr),
+ /*IsFirst=*/false);
+
+ CurPtr = UnicodePtr;
+ return true;
+}
bool Lexer::LexIdentifier(Token &Result, const char *CurPtr) {
// Match [_A-Za-z0-9]*, we have already matched [_A-Za-z$]
@@ -1500,47 +1527,10 @@ FinishIdentifier:
C = getCharAndSize(CurPtr, Size);
continue;
- } else if (C == '\\') {
- const char *UCNPtr = CurPtr + Size;
- uint32_t CodePoint = tryReadUCN(UCNPtr, CurPtr, /*Token=*/0);
- if (CodePoint == 0 || !isAllowedIDChar(CodePoint, LangOpts))
- goto FinishIdentifier;
-
- if (!isLexingRawMode()) {
- maybeDiagnoseIDCharCompat(PP->getDiagnostics(), CodePoint,
- makeCharRange(*this, CurPtr, UCNPtr),
- /*IsFirst=*/false);
- }
-
- Result.setFlag(Token::HasUCN);
- if ((UCNPtr - CurPtr == 6 && CurPtr[1] == 'u') ||
- (UCNPtr - CurPtr == 10 && CurPtr[1] == 'U'))
- CurPtr = UCNPtr;
- else
- while (CurPtr != UCNPtr)
- (void)getAndAdvanceChar(CurPtr, Result);
-
+ } else if (C == '\\' && tryConsumeIdentifierUCN(CurPtr, Size, Result)) {
C = getCharAndSize(CurPtr, Size);
continue;
- } else if (!isASCII(C)) {
- const char *UnicodePtr = CurPtr;
- UTF32 CodePoint;
- ConversionResult Result =
- llvm::convertUTF8Sequence((const UTF8 **)&UnicodePtr,
- (const UTF8 *)BufferEnd,
- &CodePoint,
- strictConversion);
- if (Result != conversionOK ||
- !isAllowedIDChar(static_cast<uint32_t>(CodePoint), LangOpts))
- goto FinishIdentifier;
-
- if (!isLexingRawMode()) {
- maybeDiagnoseIDCharCompat(PP->getDiagnostics(), CodePoint,
- makeCharRange(*this, CurPtr, UnicodePtr),
- /*IsFirst=*/false);
- }
-
- CurPtr = UnicodePtr;
+ } else if (!isASCII(C) && tryConsumeIdentifierUTF8Char(CurPtr)) {
C = getCharAndSize(CurPtr, Size);
continue;
} else if (!isIdentifierBody(C)) {
@@ -1576,7 +1566,7 @@ bool Lexer::LexNumericConstant(Token &Result, const char *CurPtr) {
unsigned Size;
char C = getCharAndSize(CurPtr, Size);
char PrevCh = 0;
- while (isPreprocessingNumberBody(C)) { // FIXME: UCNs in ud-suffix.
+ while (isPreprocessingNumberBody(C)) {
CurPtr = ConsumeChar(CurPtr, Size, Result);
PrevCh = C;
C = getCharAndSize(CurPtr, Size);
@@ -1614,10 +1604,17 @@ bool Lexer::LexNumericConstant(Token &Result, const char *CurPtr) {
if (!isLexingRawMode())
Diag(CurPtr, diag::warn_cxx11_compat_digit_separator);
CurPtr = ConsumeChar(CurPtr, Size, Result);
+ CurPtr = ConsumeChar(CurPtr, NextSize, Result);
return LexNumericConstant(Result, CurPtr);
}
}
+ // If we have a UCN or UTF-8 character (perhaps in a ud-suffix), continue.
+ if (C == '\\' && tryConsumeIdentifierUCN(CurPtr, Size, Result))
+ return LexNumericConstant(Result, CurPtr);
+ if (!isASCII(C) && tryConsumeIdentifierUTF8Char(CurPtr))
+ return LexNumericConstant(Result, CurPtr);
+
// Update the location of token as well as BufferPtr.
const char *TokStart = BufferPtr;
FormTokenWithChars(Result, CurPtr, tok::numeric_constant);
@@ -1631,23 +1628,35 @@ const char *Lexer::LexUDSuffix(Token &Result, const char *CurPtr,
bool IsStringLiteral) {
assert(getLangOpts().CPlusPlus);
- // Maximally munch an identifier. FIXME: UCNs.
+ // Maximally munch an identifier.
unsigned Size;
char C = getCharAndSize(CurPtr, Size);
- if (isIdentifierHead(C)) {
- if (!getLangOpts().CPlusPlus11) {
- if (!isLexingRawMode())
- Diag(CurPtr,
- C == '_' ? diag::warn_cxx11_compat_user_defined_literal
- : diag::warn_cxx11_compat_reserved_user_defined_literal)
- << FixItHint::CreateInsertion(getSourceLocation(CurPtr), " ");
+ bool Consumed = false;
+
+ if (!isIdentifierHead(C)) {
+ if (C == '\\' && tryConsumeIdentifierUCN(CurPtr, Size, Result))
+ Consumed = true;
+ else if (!isASCII(C) && tryConsumeIdentifierUTF8Char(CurPtr))
+ Consumed = true;
+ else
return CurPtr;
- }
+ }
- // C++11 [lex.ext]p10, [usrlit.suffix]p1: A program containing a ud-suffix
- // that does not start with an underscore is ill-formed. As a conforming
- // extension, we treat all such suffixes as if they had whitespace before
- // them.
+ if (!getLangOpts().CPlusPlus11) {
+ if (!isLexingRawMode())
+ Diag(CurPtr,
+ C == '_' ? diag::warn_cxx11_compat_user_defined_literal
+ : diag::warn_cxx11_compat_reserved_user_defined_literal)
+ << FixItHint::CreateInsertion(getSourceLocation(CurPtr), " ");
+ return CurPtr;
+ }
+
+ // C++11 [lex.ext]p10, [usrlit.suffix]p1: A program containing a ud-suffix
+ // that does not start with an underscore is ill-formed. As a conforming
+ // extension, we treat all such suffixes as if they had whitespace before
+ // them. We assume a suffix beginning with a UCN or UTF-8 character is more
+ // likely to be a ud-suffix than a macro, however, and accept that.
+ if (!Consumed) {
bool IsUDSuffix = false;
if (C == '_')
IsUDSuffix = true;
@@ -1682,19 +1691,25 @@ const char *Lexer::LexUDSuffix(Token &Result, const char *CurPtr,
if (!IsUDSuffix) {
if (!isLexingRawMode())
- Diag(CurPtr, getLangOpts().MicrosoftMode ?
- diag::ext_ms_reserved_user_defined_literal :
- diag::ext_reserved_user_defined_literal)
+ Diag(CurPtr, getLangOpts().MSVCCompat
+ ? diag::ext_ms_reserved_user_defined_literal
+ : diag::ext_reserved_user_defined_literal)
<< FixItHint::CreateInsertion(getSourceLocation(CurPtr), " ");
return CurPtr;
}
- Result.setFlag(Token::HasUDSuffix);
- do {
- CurPtr = ConsumeChar(CurPtr, Size, Result);
- C = getCharAndSize(CurPtr, Size);
- } while (isIdentifierBody(C));
+ CurPtr = ConsumeChar(CurPtr, Size, Result);
+ }
+
+ Result.setFlag(Token::HasUDSuffix);
+ while (true) {
+ C = getCharAndSize(CurPtr, Size);
+ if (isIdentifierBody(C)) { CurPtr = ConsumeChar(CurPtr, Size, Result); }
+ else if (C == '\\' && tryConsumeIdentifierUCN(CurPtr, Size, Result)) {}
+ else if (!isASCII(C) && tryConsumeIdentifierUTF8Char(CurPtr)) {}
+ else break;
}
+
return CurPtr;
}
@@ -1702,7 +1717,8 @@ const char *Lexer::LexUDSuffix(Token &Result, const char *CurPtr,
/// either " or L" or u8" or u" or U".
bool Lexer::LexStringLiteral(Token &Result, const char *CurPtr,
tok::TokenKind Kind) {
- const char *NulCharacter = 0; // Does this string contain the \0 character?
+ // Does this string contain the \0 character?
+ const char *NulCharacter = nullptr;
if (!isLexingRawMode() &&
(Kind == tok::utf8_string_literal ||
@@ -1838,7 +1854,8 @@ bool Lexer::LexRawStringLiteral(Token &Result, const char *CurPtr,
/// LexAngledStringLiteral - Lex the remainder of an angled string literal,
/// after having lexed the '<' character. This is used for #include filenames.
bool Lexer::LexAngledStringLiteral(Token &Result, const char *CurPtr) {
- const char *NulCharacter = 0; // Does this string contain the \0 character?
+ // Does this string contain the \0 character?
+ const char *NulCharacter = nullptr;
const char *AfterLessPos = CurPtr;
char C = getAndAdvanceChar(CurPtr, Result);
while (C != '>') {
@@ -1875,7 +1892,8 @@ bool Lexer::LexAngledStringLiteral(Token &Result, const char *CurPtr) {
/// lexed either ' or L' or u' or U'.
bool Lexer::LexCharConstant(Token &Result, const char *CurPtr,
tok::TokenKind Kind) {
- const char *NulCharacter = 0; // Does this character contain the \0 character?
+ // Does this character contain the \0 character?
+ const char *NulCharacter = nullptr;
if (!isLexingRawMode() &&
(Kind == tok::utf16_char_constant || Kind == tok::utf32_char_constant))
@@ -2023,8 +2041,11 @@ bool Lexer::SkipLineComment(Token &Result, const char *CurPtr,
if (C != 0) {
// We found a newline, see if it's escaped.
const char *EscapePtr = CurPtr-1;
- while (isHorizontalWhitespace(*EscapePtr)) // Skip whitespace.
+ bool HasSpace = false;
+ while (isHorizontalWhitespace(*EscapePtr)) { // Skip whitespace.
--EscapePtr;
+ HasSpace = true;
+ }
if (*EscapePtr == '\\') // Escaped newline.
CurPtr = EscapePtr;
@@ -2033,6 +2054,10 @@ bool Lexer::SkipLineComment(Token &Result, const char *CurPtr,
CurPtr = EscapePtr-2;
else
break; // This is a newline, we're done.
+
+ // If there was space between the backslash and newline, warn about it.
+ if (HasSpace && !isLexingRawMode())
+ Diag(EscapePtr, diag::backslash_newline_space);
}
// Otherwise, this is a hard case. Fall back on getAndAdvanceChar to
@@ -2460,7 +2485,8 @@ bool Lexer::LexEndOfFile(Token &Result, const char *CurPtr) {
FormTokenWithChars(Result, CurPtr, tok::eod);
// Restore comment saving mode, in case it was disabled for directive.
- resetExtendedTokenMode();
+ if (PP)
+ resetExtendedTokenMode();
return true; // Have a token.
}
@@ -2494,8 +2520,7 @@ bool Lexer::LexEndOfFile(Token &Result, const char *CurPtr) {
// C++11 [lex.phases] 2.2 p2
// Prefer the C++98 pedantic compatibility warning over the generic,
// non-extension, user-requested "missing newline at EOF" warning.
- if (Diags.getDiagnosticLevel(diag::warn_cxx98_compat_no_newline_eof,
- EndLoc) != DiagnosticsEngine::Ignored) {
+ if (!Diags.isIgnored(diag::warn_cxx98_compat_no_newline_eof, EndLoc)) {
DiagID = diag::warn_cxx98_compat_no_newline_eof;
} else {
DiagID = diag::warn_no_newline_eof;
@@ -2568,7 +2593,7 @@ static const char *FindConflictEnd(const char *CurPtr, const char *BufferEnd,
}
return RestOfBuffer.data()+Pos;
}
- return 0;
+ return nullptr;
}
/// IsStartOfConflictMarker - If the specified pointer is the start of a version
@@ -2878,7 +2903,7 @@ bool Lexer::LexTokenInternal(Token &Result, bool TokAtPhysicalStartOfLine) {
LexNextToken:
// New token, can't need cleaning yet.
Result.clearFlag(Token::NeedsCleaning);
- Result.setIdentifierInfo(0);
+ Result.setIdentifierInfo(nullptr);
// CurPtr - Cache BufferPtr in an automatic variable.
const char *CurPtr = BufferPtr;
@@ -3344,7 +3369,7 @@ LexNextToken:
// We parsed a # character. If this occurs at the start of the line,
// it's actually the start of a preprocessing directive. Callback to
// the preprocessor to handle it.
- // FIXME: -fpreprocessed mode??
+ // TODO: -fpreprocessed mode??
if (TokAtPhysicalStartOfLine && !LexingRawMode && !Is_PragmaLexer)
goto HandleDirective;
@@ -3510,7 +3535,7 @@ LexNextToken:
// We parsed a # character. If this occurs at the start of the line,
// it's actually the start of a preprocessing directive. Callback to
// the preprocessor to handle it.
- // FIXME: -fpreprocessed mode??
+ // TODO: -fpreprocessed mode??
if (TokAtPhysicalStartOfLine && !LexingRawMode && !Is_PragmaLexer)
goto HandleDirective;
diff --git a/lib/Lex/LiteralSupport.cpp b/lib/Lex/LiteralSupport.cpp
index 17c6bb3049bc..6417d0f0f5f2 100644
--- a/lib/Lex/LiteralSupport.cpp
+++ b/lib/Lex/LiteralSupport.cpp
@@ -195,7 +195,7 @@ static unsigned ProcessCharEscape(const char *ThisTokBegin,
<< std::string(1, ResultChar);
break;
default:
- if (Diags == 0)
+ if (!Diags)
break;
if (isPrintable(ResultChar))
@@ -212,6 +212,48 @@ static unsigned ProcessCharEscape(const char *ThisTokBegin,
return ResultChar;
}
+static void appendCodePoint(unsigned Codepoint,
+ llvm::SmallVectorImpl<char> &Str) {
+ char ResultBuf[4];
+ char *ResultPtr = ResultBuf;
+ bool Res = llvm::ConvertCodePointToUTF8(Codepoint, ResultPtr);
+ (void)Res;
+ assert(Res && "Unexpected conversion failure");
+ Str.append(ResultBuf, ResultPtr);
+}
+
+void clang::expandUCNs(SmallVectorImpl<char> &Buf, StringRef Input) {
+ for (StringRef::iterator I = Input.begin(), E = Input.end(); I != E; ++I) {
+ if (*I != '\\') {
+ Buf.push_back(*I);
+ continue;
+ }
+
+ ++I;
+ assert(*I == 'u' || *I == 'U');
+
+ unsigned NumHexDigits;
+ if (*I == 'u')
+ NumHexDigits = 4;
+ else
+ NumHexDigits = 8;
+
+ assert(I + NumHexDigits <= E);
+
+ uint32_t CodePoint = 0;
+ for (++I; NumHexDigits != 0; ++I, --NumHexDigits) {
+ unsigned Value = llvm::hexDigitValue(*I);
+ assert(Value != -1U);
+
+ CodePoint <<= 4;
+ CodePoint += Value;
+ }
+
+ appendCodePoint(CodePoint, Buf);
+ --I;
+ }
+}
+
/// ProcessUCNEscape - Read the Universal Character Name, check constraints and
/// return the UTF32.
static bool ProcessUCNEscape(const char *ThisTokBegin, const char *&ThisTokBuf,
@@ -298,7 +340,7 @@ static int MeasureUCNEscape(const char *ThisTokBegin, const char *&ThisTokBuf,
FullSourceLoc Loc;
if (!ProcessUCNEscape(ThisTokBegin, ThisTokBuf, ThisTokEnd, UcnVal,
- UcnLen, Loc, 0, Features, true)) {
+ UcnLen, Loc, nullptr, Features, true)) {
HadError = true;
return 0;
}
@@ -480,7 +522,7 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling,
isLongLong = false;
isFloat = false;
isImaginary = false;
- isMicrosoftInteger = false;
+ MicrosoftInteger = 0;
hadError = false;
if (*s == '0') { // parse radix
@@ -529,7 +571,7 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling,
// Parse the suffix. At this point we can classify whether we have an FP or
// integer constant.
bool isFPConstant = isFloatingLiteral();
- const char *ImaginarySuffixLoc = 0;
+ const char *ImaginarySuffixLoc = nullptr;
// Loop over all of the characters of the suffix. If we see something bad,
// we break out of the loop.
@@ -564,49 +606,53 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling,
case 'i':
case 'I':
if (PP.getLangOpts().MicrosoftExt) {
- if (isFPConstant || isLong || isLongLong) break;
+ if (isLong || isLongLong || MicrosoftInteger)
+ break;
// Allow i8, i16, i32, i64, and i128.
if (s + 1 != ThisTokEnd) {
switch (s[1]) {
case '8':
+ if (isFPConstant) break;
s += 2; // i8 suffix
- isMicrosoftInteger = true;
+ MicrosoftInteger = 8;
break;
case '1':
+ if (isFPConstant) break;
if (s + 2 == ThisTokEnd) break;
if (s[2] == '6') {
s += 3; // i16 suffix
- isMicrosoftInteger = true;
+ MicrosoftInteger = 16;
}
else if (s[2] == '2') {
if (s + 3 == ThisTokEnd) break;
if (s[3] == '8') {
s += 4; // i128 suffix
- isMicrosoftInteger = true;
+ MicrosoftInteger = 128;
}
}
break;
case '3':
+ if (isFPConstant) break;
if (s + 2 == ThisTokEnd) break;
if (s[2] == '2') {
s += 3; // i32 suffix
- isLong = true;
- isMicrosoftInteger = true;
+ MicrosoftInteger = 32;
}
break;
case '6':
+ if (isFPConstant) break;
if (s + 2 == ThisTokEnd) break;
if (s[2] == '4') {
s += 3; // i64 suffix
- isLongLong = true;
- isMicrosoftInteger = true;
+ MicrosoftInteger = 64;
}
break;
default:
break;
}
- break;
+ if (MicrosoftInteger)
+ break;
}
}
// "i", "if", and "il" are user-defined suffixes in C++1y.
@@ -625,8 +671,9 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling,
}
if (s != ThisTokEnd) {
- if (isValidUDSuffix(PP.getLangOpts(),
- StringRef(SuffixBegin, ThisTokEnd - SuffixBegin))) {
+ // FIXME: Don't bother expanding UCNs if !tok.hasUCN().
+ expandUCNs(UDSuffixBuf, StringRef(SuffixBegin, ThisTokEnd - SuffixBegin));
+ if (isValidUDSuffix(PP.getLangOpts(), UDSuffixBuf)) {
// Any suffix pieces we might have parsed are actually part of the
// ud-suffix.
isLong = false;
@@ -634,7 +681,7 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling,
isLongLong = false;
isFloat = false;
isImaginary = false;
- isMicrosoftInteger = false;
+ MicrosoftInteger = 0;
saw_ud_suffix = true;
return;
@@ -722,6 +769,7 @@ void NumericLiteralParser::ParseNumberStartingWithZero(SourceLocation TokLoc) {
s++;
saw_period = true;
const char *floatDigitsBegin = s;
+ checkSeparator(TokLoc, s, CSK_BeforeDigits);
s = SkipHexDigits(s);
noSignificand &= (floatDigitsBegin == s);
}
@@ -736,6 +784,7 @@ void NumericLiteralParser::ParseNumberStartingWithZero(SourceLocation TokLoc) {
// A binary exponent can appear with or with a '.'. If dotted, the
// binary exponent is required.
if (*s == 'p' || *s == 'P') {
+ checkSeparator(TokLoc, s, CSK_AfterDigits);
const char *Exponent = s;
s++;
saw_exponent = true;
@@ -747,6 +796,7 @@ void NumericLiteralParser::ParseNumberStartingWithZero(SourceLocation TokLoc) {
hadError = true;
return;
}
+ checkSeparator(TokLoc, s, CSK_BeforeDigits);
s = first_non_digit;
if (!PP.getLangOpts().HexFloats)
@@ -815,9 +865,11 @@ void NumericLiteralParser::ParseNumberStartingWithZero(SourceLocation TokLoc) {
s++;
radix = 10;
saw_period = true;
+ checkSeparator(TokLoc, s, CSK_BeforeDigits);
s = SkipDigits(s); // Skip suffix.
}
if (*s == 'e' || *s == 'E') { // exponent
+ checkSeparator(TokLoc, s, CSK_AfterDigits);
const char *Exponent = s;
s++;
radix = 10;
@@ -825,6 +877,7 @@ void NumericLiteralParser::ParseNumberStartingWithZero(SourceLocation TokLoc) {
if (*s == '+' || *s == '-') s++; // sign
const char *first_non_digit = SkipDigits(s);
if (first_non_digit != s) {
+ checkSeparator(TokLoc, s, CSK_BeforeDigits);
s = first_non_digit;
} else {
PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, Exponent-ThisTokBegin),
@@ -992,7 +1045,8 @@ CharLiteralParser::CharLiteralParser(const char *begin, const char *end,
do {
--end;
} while (end[-1] != '\'');
- UDSuffixBuf.assign(end, UDSuffixEnd);
+ // FIXME: Don't bother with this if !tok.hasUCN().
+ expandUCNs(UDSuffixBuf, StringRef(end, UDSuffixEnd - end));
UDSuffixOffset = end - TokBegin;
}
@@ -1201,26 +1255,26 @@ CharLiteralParser::CharLiteralParser(const char *begin, const char *end,
/// \endverbatim
///
StringLiteralParser::
-StringLiteralParser(const Token *StringToks, unsigned NumStringToks,
+StringLiteralParser(ArrayRef<Token> StringToks,
Preprocessor &PP, bool Complain)
: SM(PP.getSourceManager()), Features(PP.getLangOpts()),
- Target(PP.getTargetInfo()), Diags(Complain ? &PP.getDiagnostics() : 0),
+ Target(PP.getTargetInfo()), Diags(Complain ? &PP.getDiagnostics() :nullptr),
MaxTokenLength(0), SizeBound(0), CharByteWidth(0), Kind(tok::unknown),
ResultPtr(ResultBuf.data()), hadError(false), Pascal(false) {
- init(StringToks, NumStringToks);
+ init(StringToks);
}
-void StringLiteralParser::init(const Token *StringToks, unsigned NumStringToks){
+void StringLiteralParser::init(ArrayRef<Token> StringToks){
// The literal token may have come from an invalid source location (e.g. due
// to a PCH error), in which case the token length will be 0.
- if (NumStringToks == 0 || StringToks[0].getLength() < 2)
+ if (StringToks.empty() || StringToks[0].getLength() < 2)
return DiagnoseLexingError(SourceLocation());
// Scan all of the string portions, remember the max individual token length,
// computing a bound on the concatenated string length, and see whether any
// piece is a wide-string. If any of the string portions is a wide-string
// literal, the result is a wide-string literal [C99 6.4.5p4].
- assert(NumStringToks && "expected at least one token");
+ assert(!StringToks.empty() && "expected at least one token");
MaxTokenLength = StringToks[0].getLength();
assert(StringToks[0].getLength() >= 2 && "literal token is invalid!");
SizeBound = StringToks[0].getLength()-2; // -2 for "".
@@ -1230,7 +1284,7 @@ void StringLiteralParser::init(const Token *StringToks, unsigned NumStringToks){
// Implement Translation Phase #6: concatenation of string literals
/// (C99 5.1.1.2p1). The common case is only one string fragment.
- for (unsigned i = 1; i != NumStringToks; ++i) {
+ for (unsigned i = 1; i != StringToks.size(); ++i) {
if (StringToks[i].getLength() < 2)
return DiagnoseLexingError(StringToks[i].getLocation());
@@ -1286,7 +1340,7 @@ void StringLiteralParser::init(const Token *StringToks, unsigned NumStringToks){
SourceLocation UDSuffixTokLoc;
- for (unsigned i = 0, e = NumStringToks; i != e; ++i) {
+ for (unsigned i = 0, e = StringToks.size(); i != e; ++i) {
const char *ThisTokBuf = &TokenBuf[0];
// Get the spelling of the token, which eliminates trigraphs, etc. We know
// that ThisTokBuf points to a buffer that is big enough for the whole token
@@ -1311,23 +1365,34 @@ void StringLiteralParser::init(const Token *StringToks, unsigned NumStringToks){
StringRef UDSuffix(ThisTokEnd, UDSuffixEnd - ThisTokEnd);
if (UDSuffixBuf.empty()) {
- UDSuffixBuf.assign(UDSuffix);
+ if (StringToks[i].hasUCN())
+ expandUCNs(UDSuffixBuf, UDSuffix);
+ else
+ UDSuffixBuf.assign(UDSuffix);
UDSuffixToken = i;
UDSuffixOffset = ThisTokEnd - ThisTokBuf;
UDSuffixTokLoc = StringToks[i].getLocation();
- } else if (!UDSuffixBuf.equals(UDSuffix)) {
+ } else {
+ SmallString<32> ExpandedUDSuffix;
+ if (StringToks[i].hasUCN()) {
+ expandUCNs(ExpandedUDSuffix, UDSuffix);
+ UDSuffix = ExpandedUDSuffix;
+ }
+
// C++11 [lex.ext]p8: At the end of phase 6, if a string literal is the
// result of a concatenation involving at least one user-defined-string-
// literal, all the participating user-defined-string-literals shall
// have the same ud-suffix.
- if (Diags) {
- SourceLocation TokLoc = StringToks[i].getLocation();
- Diags->Report(TokLoc, diag::err_string_concat_mixed_suffix)
- << UDSuffixBuf << UDSuffix
- << SourceRange(UDSuffixTokLoc, UDSuffixTokLoc)
- << SourceRange(TokLoc, TokLoc);
+ if (UDSuffixBuf != UDSuffix) {
+ if (Diags) {
+ SourceLocation TokLoc = StringToks[i].getLocation();
+ Diags->Report(TokLoc, diag::err_string_concat_mixed_suffix)
+ << UDSuffixBuf << UDSuffix
+ << SourceRange(UDSuffixTokLoc, UDSuffixTokLoc)
+ << SourceRange(TokLoc, TokLoc);
+ }
+ hadError = true;
}
- hadError = true;
}
}
@@ -1449,10 +1514,10 @@ void StringLiteralParser::init(const Token *StringToks, unsigned NumStringToks){
// Verify that pascal strings aren't too large.
if (GetStringLength() > 256) {
if (Diags)
- Diags->Report(StringToks[0].getLocation(),
+ Diags->Report(StringToks.front().getLocation(),
diag::err_pascal_string_too_long)
- << SourceRange(StringToks[0].getLocation(),
- StringToks[NumStringToks-1].getLocation());
+ << SourceRange(StringToks.front().getLocation(),
+ StringToks.back().getLocation());
hadError = true;
return;
}
@@ -1461,12 +1526,12 @@ void StringLiteralParser::init(const Token *StringToks, unsigned NumStringToks){
unsigned MaxChars = Features.CPlusPlus? 65536 : Features.C99 ? 4095 : 509;
if (GetNumStringChars() > MaxChars)
- Diags->Report(StringToks[0].getLocation(),
+ Diags->Report(StringToks.front().getLocation(),
diag::ext_string_too_long)
<< GetNumStringChars() << MaxChars
<< (Features.CPlusPlus ? 2 : Features.C99 ? 1 : 0)
- << SourceRange(StringToks[0].getLocation(),
- StringToks[NumStringToks-1].getLocation());
+ << SourceRange(StringToks.front().getLocation(),
+ StringToks.back().getLocation());
}
}
@@ -1516,8 +1581,7 @@ bool StringLiteralParser::CopyStringFragment(const Token &Tok,
Dummy.reserve(Fragment.size() * CharByteWidth);
char *Ptr = Dummy.data();
- while (!Builder.hasMaxRanges() &&
- !ConvertUTF8toWide(CharByteWidth, NextFragment, Ptr, ErrorPtrTmp)) {
+ while (!ConvertUTF8toWide(CharByteWidth, NextFragment, Ptr, ErrorPtrTmp)) {
const char *ErrorPtr = reinterpret_cast<const char *>(ErrorPtrTmp);
NextStart = resyncUTF8(ErrorPtr, Fragment.end());
Builder << MakeCharSourceRange(Features, SourceLoc, TokBegin,
diff --git a/lib/Lex/MacroArgs.cpp b/lib/Lex/MacroArgs.cpp
index d2dc04b36cf7..a746fb7f48bf 100644
--- a/lib/Lex/MacroArgs.cpp
+++ b/lib/Lex/MacroArgs.cpp
@@ -1,4 +1,4 @@
-//===--- TokenLexer.cpp - Lex from a token stream -------------------------===//
+//===--- MacroArgs.cpp - Formal argument info for Macros ------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,7 +7,7 @@
//
//===----------------------------------------------------------------------===//
//
-// This file implements the TokenLexer interface.
+// This file implements the MacroArgs interface.
//
//===----------------------------------------------------------------------===//
@@ -27,7 +27,7 @@ MacroArgs *MacroArgs::create(const MacroInfo *MI,
bool VarargsElided, Preprocessor &PP) {
assert(MI->isFunctionLike() &&
"Can't have args for an object-like macro!");
- MacroArgs **ResultEnt = 0;
+ MacroArgs **ResultEnt = nullptr;
unsigned ClosestMatch = ~0U;
// See if we have an entry with a big enough argument list to reuse on the
@@ -46,7 +46,7 @@ MacroArgs *MacroArgs::create(const MacroInfo *MI,
}
MacroArgs *Result;
- if (ResultEnt == 0) {
+ if (!ResultEnt) {
// Allocate memory for a MacroArgs object with the lexer tokens at the end.
Result = (MacroArgs*)malloc(sizeof(MacroArgs) +
UnexpArgTokens.size() * sizeof(Token));
diff --git a/lib/Lex/MacroInfo.cpp b/lib/Lex/MacroInfo.cpp
index b61ff71d1767..5416886cc9f7 100644
--- a/lib/Lex/MacroInfo.cpp
+++ b/lib/Lex/MacroInfo.cpp
@@ -17,7 +17,7 @@ using namespace clang;
MacroInfo::MacroInfo(SourceLocation DefLoc)
: Location(DefLoc),
- ArgumentList(0),
+ ArgumentList(nullptr),
NumArguments(0),
IsDefinitionLengthCached(false),
IsFunctionLike(false),
@@ -29,7 +29,8 @@ MacroInfo::MacroInfo(SourceLocation DefLoc)
IsUsed(false),
IsAllowRedefinitionsWithoutWarning(false),
IsWarnIfUnused(false),
- FromASTFile(false) {
+ FromASTFile(false),
+ UsedForHeaderGuard(false) {
}
unsigned MacroInfo::getDefinitionLengthSlow(SourceManager &SM) const {
@@ -125,14 +126,54 @@ bool MacroInfo::isIdenticalTo(const MacroInfo &Other, Preprocessor &PP,
return true;
}
-MacroDirective::DefInfo MacroDirective::getDefinition(bool AllowHidden) {
+void MacroInfo::dump() const {
+ llvm::raw_ostream &Out = llvm::errs();
+
+ // FIXME: Dump locations.
+ Out << "MacroInfo " << this;
+ if (IsBuiltinMacro) Out << " builtin";
+ if (IsDisabled) Out << " disabled";
+ if (IsUsed) Out << " used";
+ if (IsAllowRedefinitionsWithoutWarning)
+ Out << " allow_redefinitions_without_warning";
+ if (IsWarnIfUnused) Out << " warn_if_unused";
+ if (FromASTFile) Out << " imported";
+ if (UsedForHeaderGuard) Out << " header_guard";
+
+ Out << "\n #define <macro>";
+ if (IsFunctionLike) {
+ Out << "(";
+ for (unsigned I = 0; I != NumArguments; ++I) {
+ if (I) Out << ", ";
+ Out << ArgumentList[I]->getName();
+ }
+ if (IsC99Varargs || IsGNUVarargs) {
+ if (NumArguments && IsC99Varargs) Out << ", ";
+ Out << "...";
+ }
+ Out << ")";
+ }
+
+ for (const Token &Tok : ReplacementTokens) {
+ Out << " ";
+ 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
+ Out << Tok.getName();
+ }
+}
+
+MacroDirective::DefInfo MacroDirective::getDefinition() {
MacroDirective *MD = this;
SourceLocation UndefLoc;
Optional<bool> isPublic;
for (; MD; MD = MD->getPrevious()) {
- if (!AllowHidden && MD->isHidden())
- continue;
-
if (DefMacroDirective *DefMD = dyn_cast<DefMacroDirective>(MD))
return DefInfo(DefMD, UndefLoc,
!isPublic.hasValue() || isPublic.getValue());
@@ -147,7 +188,8 @@ MacroDirective::DefInfo MacroDirective::getDefinition(bool AllowHidden) {
isPublic = VisMD->isPublic();
}
- return DefInfo();
+ return DefInfo(nullptr, UndefLoc,
+ !isPublic.hasValue() || isPublic.getValue());
}
const MacroDirective::DefInfo
@@ -162,3 +204,33 @@ MacroDirective::findDirectiveAtLoc(SourceLocation L, SourceManager &SM) const {
}
return DefInfo();
}
+
+void MacroDirective::dump() const {
+ llvm::raw_ostream &Out = llvm::errs();
+
+ switch (getKind()) {
+ case MD_Define: Out << "DefMacroDirective"; break;
+ case MD_Undefine: Out << "UndefMacroDirective"; break;
+ case MD_Visibility: Out << "VisibilityMacroDirective"; break;
+ }
+ Out << " " << this;
+ // FIXME: Dump SourceLocation.
+ if (auto *Prev = getPrevious())
+ Out << " prev " << Prev;
+ if (IsFromPCH) Out << " from_pch";
+ if (IsImported) Out << " imported";
+ if (IsAmbiguous) Out << " ambiguous";
+
+ if (IsPublic)
+ Out << " public";
+ else if (isa<VisibilityMacroDirective>(this))
+ Out << " private";
+
+ if (auto *DMD = dyn_cast<DefMacroDirective>(this)) {
+ if (auto *Info = DMD->getInfo()) {
+ Out << "\n ";
+ Info->dump();
+ }
+ }
+ Out << "\n";
+}
diff --git a/lib/Lex/ModuleMap.cpp b/lib/Lex/ModuleMap.cpp
index f4dfa12854a3..8fae9c933d33 100644
--- a/lib/Lex/ModuleMap.cpp
+++ b/lib/Lex/ModuleMap.cpp
@@ -42,7 +42,7 @@ ModuleMap::resolveExport(Module *Mod,
// We may have just a wildcard.
if (Unresolved.Id.empty()) {
assert(Unresolved.Wildcard && "Invalid unresolved export");
- return Module::ExportDecl(0, true);
+ return Module::ExportDecl(nullptr, true);
}
// Resolve the module-id.
@@ -59,10 +59,10 @@ Module *ModuleMap::resolveModuleId(const ModuleId &Id, Module *Mod,
Module *Context = lookupModuleUnqualified(Id[0].first, Mod);
if (!Context) {
if (Complain)
- Diags->Report(Id[0].second, diag::err_mmap_missing_module_unqualified)
+ Diags.Report(Id[0].second, diag::err_mmap_missing_module_unqualified)
<< Id[0].first << Mod->getFullModuleName();
- return 0;
+ return nullptr;
}
// Dig into the module path.
@@ -70,11 +70,11 @@ Module *ModuleMap::resolveModuleId(const ModuleId &Id, Module *Mod,
Module *Sub = lookupModuleQualified(Id[I].first, Context);
if (!Sub) {
if (Complain)
- Diags->Report(Id[I].second, diag::err_mmap_missing_module_qualified)
+ Diags.Report(Id[I].second, diag::err_mmap_missing_module_qualified)
<< Id[I].first << Context->getFullModuleName()
<< SourceRange(Id[0].second, Id[I-1].second);
- return 0;
+ return nullptr;
}
Context = Sub;
@@ -83,19 +83,12 @@ Module *ModuleMap::resolveModuleId(const ModuleId &Id, Module *Mod,
return Context;
}
-ModuleMap::ModuleMap(SourceManager &SourceMgr, DiagnosticConsumer &DC,
+ModuleMap::ModuleMap(SourceManager &SourceMgr, DiagnosticsEngine &Diags,
const LangOptions &LangOpts, const TargetInfo *Target,
HeaderSearch &HeaderInfo)
- : SourceMgr(SourceMgr), LangOpts(LangOpts), Target(Target),
- HeaderInfo(HeaderInfo), BuiltinIncludeDir(0), CompilingModule(0),
- SourceModule(0) {
- IntrusiveRefCntPtr<DiagnosticIDs> DiagIDs(new DiagnosticIDs);
- Diags = IntrusiveRefCntPtr<DiagnosticsEngine>(
- new DiagnosticsEngine(DiagIDs, new DiagnosticOptions));
- Diags->setClient(new ForwardingDiagnosticConsumer(DC),
- /*ShouldOwnClient=*/true);
- Diags->setSourceManager(&SourceMgr);
-}
+ : SourceMgr(SourceMgr), Diags(Diags), LangOpts(LangOpts), Target(Target),
+ HeaderInfo(HeaderInfo), BuiltinIncludeDir(nullptr),
+ CompilingModule(nullptr), SourceModule(nullptr) {}
ModuleMap::~ModuleMap() {
for (llvm::StringMap<Module *>::iterator I = Modules.begin(),
@@ -166,10 +159,165 @@ static bool isBuiltinHeader(StringRef FileName) {
.Default(false);
}
+ModuleMap::HeadersMap::iterator
+ModuleMap::findKnownHeader(const FileEntry *File) {
+ HeadersMap::iterator Known = Headers.find(File);
+ if (Known == Headers.end() && File->getDir() == BuiltinIncludeDir &&
+ isBuiltinHeader(llvm::sys::path::filename(File->getName()))) {
+ HeaderInfo.loadTopLevelSystemModules();
+ return Headers.find(File);
+ }
+ return Known;
+}
+
+ModuleMap::KnownHeader
+ModuleMap::findHeaderInUmbrellaDirs(const FileEntry *File,
+ SmallVectorImpl<const DirectoryEntry *> &IntermediateDirs) {
+ const DirectoryEntry *Dir = File->getDir();
+ assert(Dir && "file in no directory");
+
+ // Note: as an egregious but useful hack we use the real path here, because
+ // frameworks moving from top-level frameworks to embedded frameworks tend
+ // to be symlinked from the top-level location to the embedded location,
+ // and we need to resolve lookups as if we had found the embedded location.
+ StringRef DirName = SourceMgr.getFileManager().getCanonicalName(Dir);
+
+ // Keep walking up the directory hierarchy, looking for a directory with
+ // an umbrella header.
+ do {
+ auto KnownDir = UmbrellaDirs.find(Dir);
+ if (KnownDir != UmbrellaDirs.end())
+ return KnownHeader(KnownDir->second, NormalHeader);
+
+ IntermediateDirs.push_back(Dir);
+
+ // Retrieve our parent path.
+ DirName = llvm::sys::path::parent_path(DirName);
+ if (DirName.empty())
+ break;
+
+ // Resolve the parent path to a directory entry.
+ Dir = SourceMgr.getFileManager().getDirectory(DirName);
+ } while (Dir);
+ return KnownHeader();
+}
+
+// Returns 'true' if 'RequestingModule directly uses 'RequestedModule'.
+static bool directlyUses(const Module *RequestingModule,
+ const Module *RequestedModule) {
+ return std::find(RequestingModule->DirectUses.begin(),
+ RequestingModule->DirectUses.end(),
+ RequestedModule) != RequestingModule->DirectUses.end();
+}
+
+static bool violatesPrivateInclude(Module *RequestingModule,
+ const FileEntry *IncFileEnt,
+ ModuleMap::ModuleHeaderRole Role,
+ Module *RequestedModule) {
+ #ifndef NDEBUG
+ // Check for consistency between the module header role
+ // as obtained from the lookup and as obtained from the module.
+ // This check is not cheap, so enable it only for debugging.
+ SmallVectorImpl<const FileEntry *> &PvtHdrs
+ = RequestedModule->PrivateHeaders;
+ SmallVectorImpl<const FileEntry *>::iterator Look
+ = std::find(PvtHdrs.begin(), PvtHdrs.end(), IncFileEnt);
+ bool IsPrivate = Look != PvtHdrs.end();
+ assert((IsPrivate && Role == ModuleMap::PrivateHeader)
+ || (!IsPrivate && Role != ModuleMap::PrivateHeader));
+ #endif
+ return Role == ModuleMap::PrivateHeader &&
+ RequestedModule->getTopLevelModule() != RequestingModule;
+}
+
+static Module *getTopLevelOrNull(Module *M) {
+ return M ? M->getTopLevelModule() : nullptr;
+}
+
+void ModuleMap::diagnoseHeaderInclusion(Module *RequestingModule,
+ SourceLocation FilenameLoc,
+ StringRef Filename,
+ const FileEntry *File) {
+ // No errors for indirect modules. This may be a bit of a problem for modules
+ // with no source files.
+ if (getTopLevelOrNull(RequestingModule) != getTopLevelOrNull(SourceModule))
+ return;
+
+ if (RequestingModule)
+ resolveUses(RequestingModule, /*Complain=*/false);
+
+ bool Excluded = false;
+ Module *Private = nullptr;
+ Module *NotUsed = nullptr;
+
+ HeadersMap::iterator Known = findKnownHeader(File);
+ if (Known != Headers.end()) {
+ for (const KnownHeader &Header : Known->second) {
+ // Excluded headers don't really belong to a module.
+ if (Header.getRole() == ModuleMap::ExcludedHeader) {
+ Excluded = true;
+ continue;
+ }
+
+ // If 'File' is part of 'RequestingModule' we can definitely include it.
+ if (Header.getModule() == RequestingModule)
+ return;
+
+ // Remember private headers for later printing of a diagnostic.
+ if (violatesPrivateInclude(RequestingModule, File, Header.getRole(),
+ Header.getModule())) {
+ Private = Header.getModule();
+ continue;
+ }
+
+ // If uses need to be specified explicitly, we are only allowed to return
+ // modules that are explicitly used by the requesting module.
+ if (RequestingModule && LangOpts.ModulesDeclUse &&
+ !directlyUses(RequestingModule, Header.getModule())) {
+ NotUsed = Header.getModule();
+ continue;
+ }
+
+ // We have found a module that we can happily use.
+ return;
+ }
+ }
+
+ // We have found a header, but it is private.
+ if (Private) {
+ Diags.Report(FilenameLoc, diag::error_use_of_private_header_outside_module)
+ << Filename;
+ return;
+ }
+
+ // We have found a module, but we don't use it.
+ if (NotUsed) {
+ Diags.Report(FilenameLoc, diag::error_undeclared_use_of_module)
+ << RequestingModule->getFullModuleName() << Filename;
+ return;
+ }
+
+ if (Excluded || isHeaderInUmbrellaDirs(File))
+ return;
+
+ // At this point, only non-modular includes remain.
+
+ if (LangOpts.ModulesStrictDeclUse) {
+ Diags.Report(FilenameLoc, diag::error_undeclared_use_of_module)
+ << RequestingModule->getFullModuleName() << Filename;
+ } else if (RequestingModule) {
+ diag::kind DiagID = RequestingModule->getTopLevelModule()->IsFramework ?
+ diag::warn_non_modular_include_in_framework_module :
+ diag::warn_non_modular_include_in_module;
+ Diags.Report(FilenameLoc, DiagID) << RequestingModule->getFullModuleName();
+ }
+}
+
ModuleMap::KnownHeader
ModuleMap::findModuleForHeader(const FileEntry *File,
Module *RequestingModule) {
- HeadersMap::iterator Known = Headers.find(File);
+ HeadersMap::iterator Known = findKnownHeader(File);
+
if (Known != Headers.end()) {
ModuleMap::KnownHeader Result = KnownHeader();
@@ -177,9 +325,12 @@ ModuleMap::findModuleForHeader(const FileEntry *File,
for (SmallVectorImpl<KnownHeader>::iterator I = Known->second.begin(),
E = Known->second.end();
I != E; ++I) {
- // Cannot use a module if the header is excluded or unavailable in it.
- if (I->getRole() == ModuleMap::ExcludedHeader ||
- !I->getModule()->isAvailable())
+ // Cannot use a module if the header is excluded in it.
+ if (I->getRole() == ModuleMap::ExcludedHeader)
+ continue;
+
+ // Cannot use a module if it is unavailable.
+ if (!I->getModule()->isAvailable())
continue;
// If 'File' is part of 'RequestingModule', 'RequestingModule' is the
@@ -190,146 +341,125 @@ ModuleMap::findModuleForHeader(const FileEntry *File,
// If uses need to be specified explicitly, we are only allowed to return
// modules that are explicitly used by the requesting module.
if (RequestingModule && LangOpts.ModulesDeclUse &&
- std::find(RequestingModule->DirectUses.begin(),
- RequestingModule->DirectUses.end(),
- I->getModule()) == RequestingModule->DirectUses.end())
+ !directlyUses(RequestingModule, I->getModule()))
continue;
+
Result = *I;
// If 'File' is a public header of this module, this is as good as we
// are going to get.
+ // FIXME: If we have a RequestingModule, we should prefer the header from
+ // that module.
if (I->getRole() == ModuleMap::NormalHeader)
break;
}
return Result;
}
- // If we've found a builtin header within Clang's builtin include directory,
- // load all of the module maps to see if it will get associated with a
- // specific module (e.g., in /usr/include).
- if (File->getDir() == BuiltinIncludeDir &&
- isBuiltinHeader(llvm::sys::path::filename(File->getName()))) {
- HeaderInfo.loadTopLevelSystemModules();
-
- // Check again.
- if (Headers.find(File) != Headers.end())
- return findModuleForHeader(File, RequestingModule);
- }
-
- const DirectoryEntry *Dir = File->getDir();
SmallVector<const DirectoryEntry *, 2> SkippedDirs;
-
- // Note: as an egregious but useful hack we use the real path here, because
- // frameworks moving from top-level frameworks to embedded frameworks tend
- // to be symlinked from the top-level location to the embedded location,
- // and we need to resolve lookups as if we had found the embedded location.
- StringRef DirName = SourceMgr.getFileManager().getCanonicalName(Dir);
-
- // Keep walking up the directory hierarchy, looking for a directory with
- // an umbrella header.
- do {
- llvm::DenseMap<const DirectoryEntry *, Module *>::iterator KnownDir
- = UmbrellaDirs.find(Dir);
- if (KnownDir != UmbrellaDirs.end()) {
- Module *Result = KnownDir->second;
-
- // Search up the module stack until we find a module with an umbrella
- // directory.
- Module *UmbrellaModule = Result;
- while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent)
- UmbrellaModule = UmbrellaModule->Parent;
-
- if (UmbrellaModule->InferSubmodules) {
- // Infer submodules for each of the directories we found between
- // the directory of the umbrella header and the directory where
- // the actual header is located.
- bool Explicit = UmbrellaModule->InferExplicitSubmodules;
-
- for (unsigned I = SkippedDirs.size(); I != 0; --I) {
- // Find or create the module that corresponds to this directory name.
- SmallString<32> NameBuf;
- StringRef Name = sanitizeFilenameAsIdentifier(
- llvm::sys::path::stem(SkippedDirs[I-1]->getName()),
- NameBuf);
- Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
- Explicit).first;
-
- // Associate the module and the directory.
- UmbrellaDirs[SkippedDirs[I-1]] = Result;
-
- // If inferred submodules export everything they import, add a
- // wildcard to the set of exports.
- if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
- Result->Exports.push_back(Module::ExportDecl(0, true));
- }
-
- // Infer a submodule with the same name as this header file.
+ KnownHeader H = findHeaderInUmbrellaDirs(File, SkippedDirs);
+ if (H) {
+ Module *Result = H.getModule();
+
+ // Search up the module stack until we find a module with an umbrella
+ // directory.
+ Module *UmbrellaModule = Result;
+ while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent)
+ UmbrellaModule = UmbrellaModule->Parent;
+
+ if (UmbrellaModule->InferSubmodules) {
+ // Infer submodules for each of the directories we found between
+ // the directory of the umbrella header and the directory where
+ // the actual header is located.
+ bool Explicit = UmbrellaModule->InferExplicitSubmodules;
+
+ for (unsigned I = SkippedDirs.size(); I != 0; --I) {
+ // Find or create the module that corresponds to this directory name.
SmallString<32> NameBuf;
StringRef Name = sanitizeFilenameAsIdentifier(
- llvm::sys::path::stem(File->getName()), NameBuf);
- Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
- Explicit).first;
- Result->addTopHeader(File);
-
- // If inferred submodules export everything they import, add a
+ llvm::sys::path::stem(SkippedDirs[I-1]->getName()), NameBuf);
+ Result = findOrCreateModule(Name, Result, UmbrellaModule->ModuleMap,
+ /*IsFramework=*/false, Explicit).first;
+ Result->IsInferred = true;
+
+ // Associate the module and the directory.
+ UmbrellaDirs[SkippedDirs[I-1]] = Result;
+
+ // If inferred submodules export everything they import, add a
// wildcard to the set of exports.
if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
- Result->Exports.push_back(Module::ExportDecl(0, true));
- } else {
- // Record each of the directories we stepped through as being part of
- // the module we found, since the umbrella header covers them all.
- for (unsigned I = 0, N = SkippedDirs.size(); I != N; ++I)
- UmbrellaDirs[SkippedDirs[I]] = Result;
+ Result->Exports.push_back(Module::ExportDecl(nullptr, true));
}
-
- 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 Headers[File].back();
+ // Infer a submodule with the same name as this header file.
+ SmallString<32> NameBuf;
+ StringRef Name = sanitizeFilenameAsIdentifier(
+ llvm::sys::path::stem(File->getName()), NameBuf);
+ Result = findOrCreateModule(Name, Result, UmbrellaModule->ModuleMap,
+ /*IsFramework=*/false, Explicit).first;
+ Result->IsInferred = true;
+ Result->addTopHeader(File);
+
+ // If inferred submodules export everything they import, add a
+ // wildcard to the set of exports.
+ if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
+ Result->Exports.push_back(Module::ExportDecl(nullptr, true));
+ } else {
+ // Record each of the directories we stepped through as being part of
+ // the module we found, since the umbrella header covers them all.
+ for (unsigned I = 0, N = SkippedDirs.size(); I != N; ++I)
+ UmbrellaDirs[SkippedDirs[I]] = Result;
}
-
- SkippedDirs.push_back(Dir);
-
- // Retrieve our parent path.
- DirName = llvm::sys::path::parent_path(DirName);
- if (DirName.empty())
- break;
-
- // Resolve the parent path to a directory entry.
- Dir = SourceMgr.getFileManager().getDirectory(DirName);
- } while (Dir);
+
+ 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 Headers[File].back();
+ }
return KnownHeader();
}
bool ModuleMap::isHeaderInUnavailableModule(const FileEntry *Header) const {
+ return isHeaderUnavailableInModule(Header, nullptr);
+}
+
+bool
+ModuleMap::isHeaderUnavailableInModule(const FileEntry *Header,
+ const Module *RequestingModule) const {
HeadersMap::const_iterator Known = Headers.find(Header);
if (Known != Headers.end()) {
for (SmallVectorImpl<KnownHeader>::const_iterator
I = Known->second.begin(),
E = Known->second.end();
I != E; ++I) {
- if (I->isAvailable())
+ if (I->isAvailable() && (!RequestingModule ||
+ I->getModule()->isSubModuleOf(RequestingModule)))
return false;
}
return true;
}
-
+
const DirectoryEntry *Dir = Header->getDir();
SmallVector<const DirectoryEntry *, 2> SkippedDirs;
StringRef DirName = Dir->getName();
+ auto IsUnavailable = [&](const Module *M) {
+ return !M->isAvailable() && (!RequestingModule ||
+ M->isSubModuleOf(RequestingModule));
+ };
+
// Keep walking up the directory hierarchy, looking for a directory with
// an umbrella header.
- do {
+ do {
llvm::DenseMap<const DirectoryEntry *, Module *>::const_iterator KnownDir
= UmbrellaDirs.find(Dir);
if (KnownDir != UmbrellaDirs.end()) {
Module *Found = KnownDir->second;
- if (!Found->isAvailable())
+ if (IsUnavailable(Found))
return true;
// Search up the module stack until we find a module with an umbrella
@@ -348,7 +478,7 @@ bool ModuleMap::isHeaderInUnavailableModule(const FileEntry *Header) const {
Found = lookupModuleQualified(Name, Found);
if (!Found)
return false;
- if (!Found->isAvailable())
+ if (IsUnavailable(Found))
return true;
}
@@ -362,7 +492,7 @@ bool ModuleMap::isHeaderInUnavailableModule(const FileEntry *Header) const {
return false;
}
- return !Found->isAvailable();
+ return IsUnavailable(Found);
}
SkippedDirs.push_back(Dir);
@@ -383,8 +513,8 @@ Module *ModuleMap::findModule(StringRef Name) const {
llvm::StringMap<Module *>::const_iterator Known = Modules.find(Name);
if (Known != Modules.end())
return Known->getValue();
-
- return 0;
+
+ return nullptr;
}
Module *ModuleMap::lookupModuleUnqualified(StringRef Name,
@@ -405,15 +535,16 @@ Module *ModuleMap::lookupModuleQualified(StringRef Name, Module *Context) const{
}
std::pair<Module *, bool>
-ModuleMap::findOrCreateModule(StringRef Name, Module *Parent, bool IsFramework,
+ModuleMap::findOrCreateModule(StringRef Name, Module *Parent,
+ const FileEntry *ModuleMap, bool IsFramework,
bool IsExplicit) {
// 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);
+ Module *Result = new Module(Name, SourceLocation(), Parent, ModuleMap,
+ IsFramework, IsExplicit);
if (LangOpts.CurrentModule == Name) {
SourceModule = Result;
SourceModuleName = Name;
@@ -482,6 +613,7 @@ ModuleMap::inferFrameworkModule(StringRef ModuleName,
// If the framework has a parent path from which we're allowed to infer
// a framework module, do so.
+ const FileEntry *ModuleMapFile = nullptr;
if (!Parent) {
// Determine whether we're allowed to infer a module map.
@@ -492,6 +624,12 @@ ModuleMap::inferFrameworkModule(StringRef ModuleName,
StringRef FrameworkDirName
= SourceMgr.getFileManager().getCanonicalName(FrameworkDir);
+ // In case this is a case-insensitive filesystem, make sure the canonical
+ // directory name matches ModuleName exactly. Modules are case-sensitive.
+ // FIXME: we should be able to give a fix-it hint for the correct spelling.
+ if (llvm::sys::path::stem(FrameworkDirName) != ModuleName)
+ return nullptr;
+
bool canInfer = false;
if (llvm::sys::path::has_parent_path(FrameworkDirName)) {
// Figure out the parent path.
@@ -504,9 +642,9 @@ ModuleMap::inferFrameworkModule(StringRef ModuleName,
if (inferred == InferredDirectories.end()) {
// We haven't looked here before. Load a module map, if there is
// one.
- SmallString<128> ModMapPath = Parent;
- llvm::sys::path::append(ModMapPath, "module.map");
- if (const FileEntry *ModMapFile = FileMgr.getFile(ModMapPath)) {
+ bool IsFrameworkDir = Parent.endswith(".framework");
+ if (const FileEntry *ModMapFile =
+ HeaderInfo.lookupModuleMapFile(ParentDir, IsFrameworkDir)) {
parseModuleMapFile(ModMapFile, IsSystem);
inferred = InferredDirectories.find(ParentDir);
}
@@ -526,14 +664,16 @@ ModuleMap::inferFrameworkModule(StringRef ModuleName,
if (inferred->second.InferSystemModules)
IsSystem = true;
+ ModuleMapFile = inferred->second.ModuleMapFile;
}
}
}
// If we're not allowed to infer a framework module, don't.
if (!canInfer)
- return 0;
- }
+ return nullptr;
+ } else
+ ModuleMapFile = Parent->ModuleMap;
// Look for an umbrella header.
@@ -545,9 +685,9 @@ ModuleMap::inferFrameworkModule(StringRef ModuleName,
// framework to load *everything*. But, it's not clear that this is a good
// idea.
if (!UmbrellaHeader)
- return 0;
-
- Module *Result = new Module(ModuleName, SourceLocation(), Parent,
+ return nullptr;
+
+ Module *Result = new Module(ModuleName, SourceLocation(), Parent, ModuleMapFile,
/*IsFramework=*/true, /*IsExplicit=*/false);
if (LangOpts.CurrentModule == ModuleName) {
SourceModule = Result;
@@ -565,14 +705,14 @@ ModuleMap::inferFrameworkModule(StringRef ModuleName,
UmbrellaDirs[UmbrellaHeader->getDir()] = Result;
// export *
- Result->Exports.push_back(Module::ExportDecl(0, true));
-
+ Result->Exports.push_back(Module::ExportDecl(nullptr, true));
+
// module * { export * }
Result->InferSubmodules = true;
Result->InferExportWildcard = true;
// Look for subframeworks.
- llvm::error_code EC;
+ std::error_code EC;
SmallString<128> SubframeworksDirName
= StringRef(FrameworkDir->getName());
llvm::sys::path::append(SubframeworksDirName, "Frameworks");
@@ -653,7 +793,7 @@ void ModuleMap::addHeader(Module *Mod, const FileEntry *Header,
const FileEntry *
ModuleMap::getContainingModuleMapFile(Module *Module) const {
if (Module->DefinitionLoc.isInvalid())
- return 0;
+ return nullptr;
return SourceMgr.getFileEntryForID(
SourceMgr.getFileID(Module->DefinitionLoc));
@@ -730,14 +870,13 @@ bool ModuleMap::resolveConflicts(Module *Mod, bool Complain) {
Module *ModuleMap::inferModuleFromLocation(FullSourceLoc Loc) {
if (Loc.isInvalid())
- return 0;
-
+ return nullptr;
+
// Use the expansion location to determine which module we're in.
FullSourceLoc ExpansionLoc = Loc.getExpansionLoc();
if (!ExpansionLoc.isFileID())
- return 0;
-
-
+ return nullptr;
+
const SourceManager &SrcMgr = Loc.getManager();
FileID ExpansionFileID = ExpansionLoc.getFileID();
@@ -751,12 +890,12 @@ Module *ModuleMap::inferModuleFromLocation(FullSourceLoc Loc) {
// any included header has an associated module.
SourceLocation IncludeLoc = SrcMgr.getIncludeLoc(ExpansionFileID);
if (IncludeLoc.isInvalid())
- return 0;
-
+ return nullptr;
+
ExpansionFileID = SrcMgr.getFileID(IncludeLoc);
}
-
- return 0;
+
+ return nullptr;
}
//----------------------------------------------------------------------------//
@@ -802,7 +941,7 @@ namespace clang {
Kind = EndOfFile;
Location = 0;
StringLength = 0;
- StringData = 0;
+ StringData = nullptr;
}
bool is(TokenKind K) const { return Kind == K; }
@@ -818,11 +957,14 @@ namespace clang {
/// \brief The set of attributes that can be attached to a module.
struct Attributes {
- Attributes() : IsSystem(), IsExhaustive() { }
+ Attributes() : IsSystem(), IsExternC(), IsExhaustive() { }
/// \brief Whether this is a system module.
unsigned IsSystem : 1;
+ /// \brief Whether this is an extern "C" module.
+ unsigned IsExternC : 1;
+
/// \brief Whether this is an exhaustive set of configuration macros.
unsigned IsExhaustive : 1;
};
@@ -838,6 +980,9 @@ namespace clang {
DiagnosticsEngine &Diags;
ModuleMap &Map;
+
+ /// \brief The current module map file.
+ const FileEntry *ModuleMapFile;
/// \brief The directory that this module map resides in.
const DirectoryEntry *Directory;
@@ -883,20 +1028,20 @@ namespace clang {
void parseConflict();
void parseInferredModuleDecl(bool Framework, bool Explicit);
bool parseOptionalAttributes(Attributes &Attrs);
-
- const DirectoryEntry *getOverriddenHeaderSearchDir();
public:
explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr,
const TargetInfo *Target,
DiagnosticsEngine &Diags,
ModuleMap &Map,
+ const FileEntry *ModuleMapFile,
const DirectoryEntry *Directory,
const DirectoryEntry *BuiltinIncludeDir,
bool IsSystem)
: L(L), SourceMgr(SourceMgr), Target(Target), Diags(Diags), Map(Map),
- Directory(Directory), BuiltinIncludeDir(BuiltinIncludeDir),
- IsSystem(IsSystem), HadError(false), ActiveModule(0)
+ ModuleMapFile(ModuleMapFile), Directory(Directory),
+ BuiltinIncludeDir(BuiltinIncludeDir), IsSystem(IsSystem),
+ HadError(false), ActiveModule(nullptr)
{
Tok.clear();
consumeToken();
@@ -915,10 +1060,11 @@ retry:
L.LexFromRawLexer(LToken);
Tok.Location = LToken.getLocation().getRawEncoding();
switch (LToken.getKind()) {
- case tok::raw_identifier:
- Tok.StringData = LToken.getRawIdentifierData();
- Tok.StringLength = LToken.getLength();
- Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(Tok.getString())
+ case tok::raw_identifier: {
+ StringRef RI = LToken.getRawIdentifier();
+ Tok.StringData = RI.data();
+ Tok.StringLength = RI.size();
+ Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(RI)
.Case("config_macros", MMToken::ConfigMacros)
.Case("conflict", MMToken::Conflict)
.Case("exclude", MMToken::ExcludeKeyword)
@@ -935,6 +1081,7 @@ retry:
.Case("use", MMToken::UseKeyword)
.Default(MMToken::Identifier);
break;
+ }
case tok::comma:
Tok.Kind = MMToken::Comma;
@@ -981,7 +1128,7 @@ retry:
// Parse the string literal.
LangOptions LangOpts;
- StringLiteralParser StringLiteral(&LToken, 1, SourceMgr, LangOpts, *Target);
+ StringLiteralParser StringLiteral(LToken, SourceMgr, LangOpts, *Target);
if (StringLiteral.hadError)
goto retry;
@@ -1066,7 +1213,7 @@ void ModuleMapParser::skipUntil(MMToken::TokenKind K) {
bool ModuleMapParser::parseModuleId(ModuleId &Id) {
Id.clear();
do {
- if (Tok.is(MMToken::Identifier)) {
+ if (Tok.is(MMToken::Identifier) || Tok.is(MMToken::StringLiteral)) {
Id.push_back(std::make_pair(Tok.getString(), Tok.getLocation()));
consumeToken();
} else {
@@ -1090,6 +1237,8 @@ namespace {
AT_unknown,
/// \brief The 'system' attribute.
AT_system,
+ /// \brief The 'extern_c' attribute.
+ AT_extern_c,
/// \brief The 'exhaustive' attribute.
AT_exhaustive
};
@@ -1178,7 +1327,7 @@ void ModuleMapParser::parseModuleDecl() {
if (Id.size() > 1) {
// This module map defines a submodule. Go find the module of which it
// is a submodule.
- ActiveModule = 0;
+ ActiveModule = nullptr;
for (unsigned I = 0, N = Id.size() - 1; I != N; ++I) {
if (Module *Next = Map.lookupModuleQualified(Id[I].first, ActiveModule)) {
ActiveModule = Next;
@@ -1187,7 +1336,8 @@ void ModuleMapParser::parseModuleDecl() {
if (ActiveModule) {
Diags.Report(Id[I].second, diag::err_mmap_missing_module_qualified)
- << Id[I].first << ActiveModule->getTopLevelModule();
+ << Id[I].first
+ << ActiveModule->getTopLevelModule()->getFullModuleName();
} else {
Diags.Report(Id[I].second, diag::err_mmap_expected_module_name);
}
@@ -1240,13 +1390,20 @@ void ModuleMapParser::parseModuleDecl() {
return;
}
+ // If this is a submodule, use the parent's module map, since we don't want
+ // the private module map file.
+ const FileEntry *ModuleMap = ActiveModule ? ActiveModule->ModuleMap
+ : ModuleMapFile;
+
// Start defining this module.
- ActiveModule = Map.findOrCreateModule(ModuleName, ActiveModule, Framework,
- Explicit).first;
+ ActiveModule = Map.findOrCreateModule(ModuleName, ActiveModule, ModuleMap,
+ Framework, Explicit).first;
ActiveModule->DefinitionLoc = ModuleNameLoc;
if (Attrs.IsSystem || IsSystem)
ActiveModule->IsSystem = true;
-
+ if (Attrs.IsExternC)
+ ActiveModule->IsExternC = true;
+
bool Done = false;
do {
switch (Tok.Kind) {
@@ -1343,6 +1500,15 @@ void ModuleMapParser::parseModuleDecl() {
inferFrameworkLink(ActiveModule, Directory, SourceMgr.getFileManager());
}
+ // If the module meets all requirements but is still unavailable, mark the
+ // whole tree as unavailable to prevent it from building.
+ if (!ActiveModule->IsAvailable && !ActiveModule->IsMissingRequirement &&
+ ActiveModule->Parent) {
+ ActiveModule->getTopLevelModule()->markUnavailable();
+ ActiveModule->getTopLevelModule()->MissingHeaders.append(
+ ActiveModule->MissingHeaders.begin(), ActiveModule->MissingHeaders.end());
+ }
+
// We're done parsing this module. Pop back to the previous module.
ActiveModule = PreviousActiveModule;
}
@@ -1474,27 +1640,24 @@ void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken,
HadError = true;
return;
}
- std::string FileName = Tok.getString();
- SourceLocation FileNameLoc = consumeToken();
+ Module::HeaderDirective Header;
+ Header.FileName = Tok.getString();
+ Header.FileNameLoc = consumeToken();
// Check whether we already have an umbrella.
if (LeadingToken == MMToken::UmbrellaKeyword && ActiveModule->Umbrella) {
- Diags.Report(FileNameLoc, diag::err_mmap_umbrella_clash)
+ Diags.Report(Header.FileNameLoc, diag::err_mmap_umbrella_clash)
<< ActiveModule->getFullModuleName();
HadError = true;
return;
}
// Look for this file.
- const FileEntry *File = 0;
- const FileEntry *BuiltinFile = 0;
+ const FileEntry *File = nullptr;
+ const FileEntry *BuiltinFile = nullptr;
SmallString<128> PathName;
- if (llvm::sys::path::is_absolute(FileName)) {
- PathName = FileName;
- File = SourceMgr.getFileManager().getFile(PathName);
- } else if (const DirectoryEntry *Dir = getOverriddenHeaderSearchDir()) {
- PathName = Dir->getName();
- llvm::sys::path::append(PathName, FileName);
+ if (llvm::sys::path::is_absolute(Header.FileName)) {
+ PathName = Header.FileName;
File = SourceMgr.getFileManager().getFile(PathName);
} else {
// Search for the header file within the search directory.
@@ -1505,18 +1668,18 @@ void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken,
appendSubframeworkPaths(ActiveModule, PathName);
// Check whether this file is in the public headers.
- llvm::sys::path::append(PathName, "Headers", FileName);
+ llvm::sys::path::append(PathName, "Headers", Header.FileName);
File = SourceMgr.getFileManager().getFile(PathName);
if (!File) {
// Check whether this file is in the private headers.
PathName.resize(PathLength);
- llvm::sys::path::append(PathName, "PrivateHeaders", FileName);
+ llvm::sys::path::append(PathName, "PrivateHeaders", Header.FileName);
File = SourceMgr.getFileManager().getFile(PathName);
}
} else {
// Lookup for normal headers.
- llvm::sys::path::append(PathName, FileName);
+ llvm::sys::path::append(PathName, Header.FileName);
File = SourceMgr.getFileManager().getFile(PathName);
// If this is a system module with a top-level header, this header
@@ -1524,9 +1687,9 @@ void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken,
// supplied by Clang. Find that builtin header.
if (ActiveModule->IsSystem && LeadingToken != MMToken::UmbrellaKeyword &&
BuiltinIncludeDir && BuiltinIncludeDir != Directory &&
- isBuiltinHeader(FileName)) {
+ isBuiltinHeader(Header.FileName)) {
SmallString<128> BuiltinPathName(BuiltinIncludeDir->getName());
- llvm::sys::path::append(BuiltinPathName, FileName);
+ llvm::sys::path::append(BuiltinPathName, Header.FileName);
BuiltinFile = SourceMgr.getFileManager().getFile(BuiltinPathName);
// If Clang supplies this header but the underlying system does not,
@@ -1534,7 +1697,7 @@ void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken,
// up adding both (later).
if (!File && BuiltinFile) {
File = BuiltinFile;
- BuiltinFile = 0;
+ BuiltinFile = nullptr;
}
}
}
@@ -1571,10 +1734,12 @@ void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken,
}
} else if (LeadingToken != MMToken::ExcludeKeyword) {
// Ignore excluded header files. They're optional anyway.
-
- Diags.Report(FileNameLoc, diag::err_mmap_header_not_found)
- << (LeadingToken == MMToken::UmbrellaKeyword) << FileName;
- HadError = true;
+
+ // If we find a module that has a missing header, we mark this module as
+ // unavailable and store the header directive for displaying diagnostics.
+ Header.IsUmbrella = LeadingToken == MMToken::UmbrellaKeyword;
+ ActiveModule->markUnavailable();
+ ActiveModule->MissingHeaders.push_back(Header);
}
}
@@ -1603,7 +1768,7 @@ void ModuleMapParser::parseUmbrellaDirDecl(SourceLocation UmbrellaLoc) {
}
// Look for this file.
- const DirectoryEntry *Dir = 0;
+ const DirectoryEntry *Dir = nullptr;
if (llvm::sys::path::is_absolute(DirName))
Dir = SourceMgr.getFileManager().getDirectory(DirName);
else {
@@ -1687,25 +1852,7 @@ void ModuleMapParser::parseUseDecl() {
consumeToken();
// Parse the module-id.
ModuleId ParsedModuleId;
-
- do {
- if (Tok.is(MMToken::Identifier)) {
- ParsedModuleId.push_back(
- std::make_pair(Tok.getString(), Tok.getLocation()));
- consumeToken();
-
- if (Tok.is(MMToken::Period)) {
- consumeToken();
- continue;
- }
-
- break;
- }
-
- Diags.Report(Tok.getLocation(), diag::err_mmap_module_id);
- HadError = true;
- return;
- } while (true);
+ parseModuleId(ParsedModuleId);
ActiveModule->UnresolvedDirectUses.push_back(ParsedModuleId);
}
@@ -1864,7 +2011,8 @@ void ModuleMapParser::parseInferredModuleDecl(bool Framework, bool Explicit) {
if (ActiveModule) {
// Inferred modules must have umbrella directories.
- if (!Failed && !ActiveModule->getUmbrellaDir()) {
+ if (!Failed && ActiveModule->IsAvailable &&
+ !ActiveModule->getUmbrellaDir()) {
Diags.Report(StarLoc, diag::err_mmap_inferred_no_umbrella);
Failed = true;
}
@@ -1913,6 +2061,8 @@ void ModuleMapParser::parseInferredModuleDecl(bool Framework, bool Explicit) {
// We'll be inferring framework modules for this directory.
Map.InferredDirectories[Directory].InferModules = true;
Map.InferredDirectories[Directory].InferSystemModules = Attrs.IsSystem;
+ Map.InferredDirectories[Directory].ModuleMapFile = ModuleMapFile;
+ // FIXME: Handle the 'framework' keyword.
}
// Parse the opening brace.
@@ -1935,7 +2085,7 @@ void ModuleMapParser::parseInferredModuleDecl(bool Framework, bool Explicit) {
case MMToken::ExcludeKeyword: {
if (ActiveModule) {
Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
- << (ActiveModule != 0);
+ << (ActiveModule != nullptr);
consumeToken();
break;
}
@@ -1955,7 +2105,7 @@ void ModuleMapParser::parseInferredModuleDecl(bool Framework, bool Explicit) {
case MMToken::ExportKeyword:
if (!ActiveModule) {
Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
- << (ActiveModule != 0);
+ << (ActiveModule != nullptr);
consumeToken();
break;
}
@@ -1976,7 +2126,7 @@ void ModuleMapParser::parseInferredModuleDecl(bool Framework, bool Explicit) {
case MMToken::UmbrellaKeyword:
default:
Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
- << (ActiveModule != 0);
+ << (ActiveModule != nullptr);
consumeToken();
break;
}
@@ -2023,6 +2173,7 @@ bool ModuleMapParser::parseOptionalAttributes(Attributes &Attrs) {
AttributeKind Attribute
= llvm::StringSwitch<AttributeKind>(Tok.getString())
.Case("exhaustive", AT_exhaustive)
+ .Case("extern_c", AT_extern_c)
.Case("system", AT_system)
.Default(AT_unknown);
switch (Attribute) {
@@ -2035,6 +2186,10 @@ bool ModuleMapParser::parseOptionalAttributes(Attributes &Attrs) {
Attrs.IsSystem = true;
break;
+ case AT_extern_c:
+ Attrs.IsExternC = true;
+ break;
+
case AT_exhaustive:
Attrs.IsExhaustive = true;
break;
@@ -2056,22 +2211,6 @@ bool ModuleMapParser::parseOptionalAttributes(Attributes &Attrs) {
return HadError;
}
-/// \brief If there is a specific header search directory due the presence
-/// of an umbrella directory, retrieve that directory. Otherwise, returns null.
-const DirectoryEntry *ModuleMapParser::getOverriddenHeaderSearchDir() {
- for (Module *Mod = ActiveModule; Mod; Mod = Mod->Parent) {
- // If we have an umbrella directory, use that.
- if (Mod->hasUmbrellaDir())
- return Mod->getUmbrellaDir();
-
- // If we have a framework directory, stop looking.
- if (Mod->IsFramework)
- return 0;
- }
-
- return 0;
-}
-
/// \brief Parse a module map file.
///
/// module-map-file:
@@ -2123,19 +2262,29 @@ bool ModuleMap::parseModuleMapFile(const FileEntry *File, bool IsSystem) {
if (Known != ParsedModuleMap.end())
return Known->second;
- assert(Target != 0 && "Missing target information");
- FileID ID = SourceMgr.createFileID(File, SourceLocation(), SrcMgr::C_User);
+ assert(Target && "Missing target information");
+ auto FileCharacter = IsSystem ? SrcMgr::C_System : SrcMgr::C_User;
+ FileID ID = SourceMgr.createFileID(File, SourceLocation(), FileCharacter);
const llvm::MemoryBuffer *Buffer = SourceMgr.getBuffer(ID);
if (!Buffer)
return ParsedModuleMap[File] = true;
+
+ // Find the directory for the module. For frameworks, that may require going
+ // up from the 'Modules' directory.
+ const DirectoryEntry *Dir = File->getDir();
+ StringRef DirName(Dir->getName());
+ if (llvm::sys::path::filename(DirName) == "Modules") {
+ DirName = llvm::sys::path::parent_path(DirName);
+ if (DirName.endswith(".framework"))
+ Dir = SourceMgr.getFileManager().getDirectory(DirName);
+ assert(Dir && "parent must exist");
+ }
// Parse this module map file.
Lexer L(ID, SourceMgr.getBuffer(ID), SourceMgr, MMapLangOpts);
- Diags->getClient()->BeginSourceFile(MMapLangOpts);
- ModuleMapParser Parser(L, SourceMgr, Target, *Diags, *this, File->getDir(),
+ ModuleMapParser Parser(L, SourceMgr, Target, Diags, *this, File, Dir,
BuiltinIncludeDir, IsSystem);
bool Result = Parser.parseModuleMapFile();
- Diags->getClient()->EndSourceFile();
ParsedModuleMap[File] = Result;
return Result;
}
diff --git a/lib/Lex/PPCaching.cpp b/lib/Lex/PPCaching.cpp
index 6f4c189b4f6a..bd48ae64ab4b 100644
--- a/lib/Lex/PPCaching.cpp
+++ b/lib/Lex/PPCaching.cpp
@@ -15,28 +15,28 @@
#include "clang/Lex/Preprocessor.h"
using namespace clang;
-/// EnableBacktrackAtThisPos - From the point that this method is called, and
-/// until CommitBacktrackedTokens() or Backtrack() is called, the Preprocessor
-/// keeps track of the lexed tokens so that a subsequent Backtrack() call will
-/// make the Preprocessor re-lex the same tokens.
-///
-/// Nested backtracks are allowed, meaning that EnableBacktrackAtThisPos can
-/// be called multiple times and CommitBacktrackedTokens/Backtrack calls will
-/// be combined with the EnableBacktrackAtThisPos calls in reverse order.
+// EnableBacktrackAtThisPos - From the point that this method is called, and
+// until CommitBacktrackedTokens() or Backtrack() is called, the Preprocessor
+// keeps track of the lexed tokens so that a subsequent Backtrack() call will
+// make the Preprocessor re-lex the same tokens.
+//
+// Nested backtracks are allowed, meaning that EnableBacktrackAtThisPos can
+// be called multiple times and CommitBacktrackedTokens/Backtrack calls will
+// be combined with the EnableBacktrackAtThisPos calls in reverse order.
void Preprocessor::EnableBacktrackAtThisPos() {
BacktrackPositions.push_back(CachedLexPos);
EnterCachingLexMode();
}
-/// CommitBacktrackedTokens - Disable the last EnableBacktrackAtThisPos call.
+// Disable the last EnableBacktrackAtThisPos call.
void Preprocessor::CommitBacktrackedTokens() {
assert(!BacktrackPositions.empty()
&& "EnableBacktrackAtThisPos was not called!");
BacktrackPositions.pop_back();
}
-/// Backtrack - Make Preprocessor re-lex the tokens that were lexed since
-/// EnableBacktrackAtThisPos() was previously called.
+// Make Preprocessor re-lex the tokens that were lexed since
+// EnableBacktrackAtThisPos() was previously called.
void Preprocessor::Backtrack() {
assert(!BacktrackPositions.empty()
&& "EnableBacktrackAtThisPos was not called!");
diff --git a/lib/Lex/PPConditionalDirectiveRecord.cpp b/lib/Lex/PPConditionalDirectiveRecord.cpp
index 16dc1d8f0913..99b87a0a1525 100644
--- a/lib/Lex/PPConditionalDirectiveRecord.cpp
+++ b/lib/Lex/PPConditionalDirectiveRecord.cpp
@@ -77,7 +77,7 @@ void PPConditionalDirectiveRecord::addCondDirectiveLoc(
void PPConditionalDirectiveRecord::If(SourceLocation Loc,
SourceRange ConditionRange,
- bool ConditionValue) {
+ ConditionValueKind ConditionValue) {
addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back()));
CondDirectiveStack.push_back(Loc);
}
@@ -98,7 +98,7 @@ void PPConditionalDirectiveRecord::Ifndef(SourceLocation Loc,
void PPConditionalDirectiveRecord::Elif(SourceLocation Loc,
SourceRange ConditionRange,
- bool ConditionValue,
+ ConditionValueKind ConditionValue,
SourceLocation IfLoc) {
addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back()));
CondDirectiveStack.back() = Loc;
diff --git a/lib/Lex/PPDirectives.cpp b/lib/Lex/PPDirectives.cpp
index 86c508fe9b1b..1741c302f338 100644
--- a/lib/Lex/PPDirectives.cpp
+++ b/lib/Lex/PPDirectives.cpp
@@ -25,6 +25,7 @@
#include "clang/Lex/Pragma.h"
#include "llvm/ADT/APInt.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/FileSystem.h"
#include "llvm/Support/SaveAndRestore.h"
using namespace clang;
@@ -44,7 +45,7 @@ MacroInfo *Preprocessor::AllocateMacroInfo() {
}
MIChain->Next = MIChainHead;
- MIChain->Prev = 0;
+ MIChain->Prev = nullptr;
if (MIChainHead)
MIChainHead->Prev = MIChain;
MIChainHead = MIChain;
@@ -60,8 +61,8 @@ MacroInfo *Preprocessor::AllocateMacroInfo(SourceLocation L) {
MacroInfo *Preprocessor::AllocateDeserializedMacroInfo(SourceLocation L,
unsigned SubModuleID) {
- LLVM_STATIC_ASSERT(llvm::AlignOf<MacroInfo>::Alignment >= sizeof(SubModuleID),
- "alignment for MacroInfo is less than the ID");
+ static_assert(llvm::AlignOf<MacroInfo>::Alignment >= sizeof(SubModuleID),
+ "alignment for MacroInfo is less than the ID");
DeserializedMacroInfoChain *MIChain =
BP.Allocate<DeserializedMacroInfoChain>();
MIChain->Next = DeserialMIChainHead;
@@ -100,17 +101,16 @@ Preprocessor::AllocateVisibilityMacroDirective(SourceLocation Loc,
/// \brief Release the specified MacroInfo to be reused for allocating
/// new MacroInfo objects.
void Preprocessor::ReleaseMacroInfo(MacroInfo *MI) {
- MacroInfoChain *MIChain = (MacroInfoChain*) MI;
+ MacroInfoChain *MIChain = (MacroInfoChain *)MI;
if (MacroInfoChain *Prev = MIChain->Prev) {
MacroInfoChain *Next = MIChain->Next;
Prev->Next = Next;
if (Next)
Next->Prev = Prev;
- }
- else {
+ } else {
assert(MIChainHead == MIChain);
MIChainHead = MIChain->Next;
- MIChainHead->Prev = 0;
+ MIChainHead->Prev = nullptr;
}
MIChain->Next = MICache;
MICache = MIChain;
@@ -128,6 +128,50 @@ void Preprocessor::DiscardUntilEndOfDirective() {
} while (Tmp.isNot(tok::eod));
}
+bool Preprocessor::CheckMacroName(Token &MacroNameTok, char isDefineUndef) {
+ // Missing macro name?
+ if (MacroNameTok.is(tok::eod))
+ return Diag(MacroNameTok, diag::err_pp_missing_macro_name);
+
+ IdentifierInfo *II = MacroNameTok.getIdentifierInfo();
+ if (!II) {
+ bool Invalid = false;
+ std::string Spelling = getSpelling(MacroNameTok, &Invalid);
+ if (Invalid)
+ return Diag(MacroNameTok, diag::err_pp_macro_not_identifier);
+ II = getIdentifierInfo(Spelling);
+
+ if (!II->isCPlusPlusOperatorKeyword())
+ return Diag(MacroNameTok, diag::err_pp_macro_not_identifier);
+
+ // C++ 2.5p2: Alternative tokens behave the same as its primary token
+ // except for their spellings.
+ Diag(MacroNameTok, getLangOpts().MicrosoftExt
+ ? diag::ext_pp_operator_used_as_macro_name
+ : diag::err_pp_operator_used_as_macro_name)
+ << II << MacroNameTok.getKind();
+
+ // Allow #defining |and| and friends for Microsoft compatibility or
+ // recovery when legacy C headers are included in C++.
+ MacroNameTok.setIdentifierInfo(II);
+ }
+
+ if (isDefineUndef && II->getPPKeywordID() == tok::pp_defined) {
+ // Error if defining "defined": C99 6.10.8/4, C++ [cpp.predefined]p4.
+ return Diag(MacroNameTok, diag::err_defined_macro_name);
+ }
+
+ if (isDefineUndef == 2 && II->hasMacroDefinition() &&
+ getMacroInfo(II)->isBuiltinMacro()) {
+ // Warn if undefining "__LINE__" and other builtins, per C99 6.10.8/4
+ // and C++ [cpp.predefined]p4], but allow it as an extension.
+ Diag(MacroNameTok, diag::ext_pp_undef_builtin_macro);
+ }
+
+ // Okay, we got a good identifier.
+ return false;
+}
+
/// \brief Lex and validate a macro name, which occurs after a
/// \#define or \#undef.
///
@@ -145,53 +189,16 @@ void Preprocessor::ReadMacroName(Token &MacroNameTok, char isDefineUndef) {
setCodeCompletionReached();
LexUnexpandedToken(MacroNameTok);
}
-
- // Missing macro name?
- if (MacroNameTok.is(tok::eod)) {
- Diag(MacroNameTok, diag::err_pp_missing_macro_name);
- return;
- }
- IdentifierInfo *II = MacroNameTok.getIdentifierInfo();
- if (II == 0) {
- bool Invalid = false;
- std::string Spelling = getSpelling(MacroNameTok, &Invalid);
- if (Invalid)
- return;
-
- const IdentifierInfo &Info = Identifiers.get(Spelling);
-
- // Allow #defining |and| and friends in microsoft mode.
- if (Info.isCPlusPlusOperatorKeyword() && getLangOpts().MicrosoftMode) {
- MacroNameTok.setIdentifierInfo(getIdentifierInfo(Spelling));
- return;
- }
-
- if (Info.isCPlusPlusOperatorKeyword())
- // C++ 2.5p2: Alternative tokens behave the same as its primary token
- // except for their spellings.
- Diag(MacroNameTok, diag::err_pp_operator_used_as_macro_name) << Spelling;
- else
- Diag(MacroNameTok, diag::err_pp_macro_not_identifier);
- // Fall through on error.
- } else if (isDefineUndef && II->getPPKeywordID() == tok::pp_defined) {
- // Error if defining "defined": C99 6.10.8/4, C++ [cpp.predefined]p4.
- Diag(MacroNameTok, diag::err_defined_macro_name);
- } else if (isDefineUndef == 2 && II->hasMacroDefinition() &&
- getMacroInfo(II)->isBuiltinMacro()) {
- // Warn if undefining "__LINE__" and other builtins, per C99 6.10.8/4
- // and C++ [cpp.predefined]p4], but allow it as an extension.
- Diag(MacroNameTok, diag::ext_pp_undef_builtin_macro);
+ if (!CheckMacroName(MacroNameTok, isDefineUndef))
return;
- } else {
- // Okay, we got a good identifier node. Return it.
- return;
- }
- // Invalid macro name, read and discard the rest of the line. Then set the
- // token kind to tok::eod.
- MacroNameTok.setKind(tok::eod);
- return DiscardUntilEndOfDirective();
+ // Invalid macro name, read and discard the rest of the line and set the
+ // token kind to tok::eod if necessary.
+ if (MacroNameTok.isNot(tok::eod)) {
+ MacroNameTok.setKind(tok::eod);
+ DiscardUntilEndOfDirective();
+ }
}
/// \brief Ensure that the next token is a tok::eod token.
@@ -309,9 +316,9 @@ void Preprocessor::SkipExcludedConditionalBlock(SourceLocation IfTokenLoc,
// to spell an i/e in a strange way that is another letter. Skipping this
// allows us to avoid looking up the identifier info for #define/#undef and
// other common directives.
- const char *RawCharData = Tok.getRawIdentifierData();
+ StringRef RI = Tok.getRawIdentifier();
- char FirstChar = RawCharData[0];
+ char FirstChar = RI[0];
if (FirstChar >= 'a' && FirstChar <= 'z' &&
FirstChar != 'i' && FirstChar != 'e') {
CurPPLexer->ParsingPreprocessorDirective = false;
@@ -325,8 +332,8 @@ void Preprocessor::SkipExcludedConditionalBlock(SourceLocation IfTokenLoc,
// when skipping.
char DirectiveBuf[20];
StringRef Directive;
- if (!Tok.needsCleaning() && Tok.getLength() < 20) {
- Directive = StringRef(RawCharData, Tok.getLength());
+ if (!Tok.needsCleaning() && RI.size() < 20) {
+ Directive = RI;
} else {
std::string DirectiveStr = getSpelling(Tok);
unsigned IdLen = DirectiveStr.size();
@@ -404,35 +411,33 @@ void Preprocessor::SkipExcludedConditionalBlock(SourceLocation IfTokenLoc,
} else if (Sub == "lif") { // "elif".
PPConditionalInfo &CondInfo = CurPPLexer->peekConditionalLevel();
- bool ShouldEnter;
- const SourceLocation ConditionalBegin = CurPPLexer->getSourceLocation();
+ // If this is a #elif with a #else before it, report the error.
+ if (CondInfo.FoundElse) Diag(Tok, diag::pp_err_elif_after_else);
+
// If this is in a skipping block or if we're already handled this #if
// block, don't bother parsing the condition.
if (CondInfo.WasSkipping || CondInfo.FoundNonSkip) {
DiscardUntilEndOfDirective();
- ShouldEnter = false;
} else {
+ const SourceLocation CondBegin = CurPPLexer->getSourceLocation();
// Restore the value of LexingRawMode so that identifiers are
// looked up, etc, inside the #elif expression.
assert(CurPPLexer->LexingRawMode && "We have to be skipping here!");
CurPPLexer->LexingRawMode = false;
- IdentifierInfo *IfNDefMacro = 0;
- ShouldEnter = EvaluateDirectiveExpression(IfNDefMacro);
+ IdentifierInfo *IfNDefMacro = nullptr;
+ const bool CondValue = EvaluateDirectiveExpression(IfNDefMacro);
CurPPLexer->LexingRawMode = true;
- }
- const SourceLocation ConditionalEnd = CurPPLexer->getSourceLocation();
-
- // If this is a #elif with a #else before it, report the error.
- if (CondInfo.FoundElse) Diag(Tok, diag::pp_err_elif_after_else);
-
- // If this condition is true, enter it!
- if (ShouldEnter) {
- CondInfo.FoundNonSkip = true;
- if (Callbacks)
+ if (Callbacks) {
+ const SourceLocation CondEnd = CurPPLexer->getSourceLocation();
Callbacks->Elif(Tok.getLocation(),
- SourceRange(ConditionalBegin, ConditionalEnd),
- ShouldEnter, CondInfo.IfLoc);
- break;
+ SourceRange(CondBegin, CondEnd),
+ (CondValue ? PPCallbacks::CVK_True : PPCallbacks::CVK_False), CondInfo.IfLoc);
+ }
+ // If this condition is true, enter it!
+ if (CondValue) {
+ CondInfo.FoundNonSkip = true;
+ break;
+ }
}
}
}
@@ -516,7 +521,7 @@ void Preprocessor::PTHSkipExcludedConditionalBlock() {
continue;
// Evaluate the condition of the #elif.
- IdentifierInfo *IfNDefMacro = 0;
+ IdentifierInfo *IfNDefMacro = nullptr;
CurPTHLexer->ParsingPreprocessorDirective = true;
bool ShouldEnter = EvaluateDirectiveExpression(IfNDefMacro);
CurPTHLexer->ParsingPreprocessorDirective = false;
@@ -540,7 +545,8 @@ Module *Preprocessor::getModuleForLocation(SourceLocation FilenameLoc) {
return HeaderInfo.getModuleMap().SourceModule; // Compiling a source.
}
// Try to determine the module of the include directive.
- FileID IDOfIncl = SourceMgr.getFileID(FilenameLoc);
+ // FIXME: Look into directly passing the FileEntry from LookupFile instead.
+ FileID IDOfIncl = SourceMgr.getFileID(SourceMgr.getExpansionLoc(FilenameLoc));
if (const FileEntry *EntryOfIncl = SourceMgr.getFileEntryForID(IDOfIncl)) {
// The include comes from a file.
return ModMap.findModuleForHeader(EntryOfIncl).getModule();
@@ -551,69 +557,6 @@ Module *Preprocessor::getModuleForLocation(SourceLocation FilenameLoc) {
}
}
-bool Preprocessor::violatesPrivateInclude(
- Module *RequestingModule,
- const FileEntry *IncFileEnt,
- ModuleMap::ModuleHeaderRole Role,
- Module *RequestedModule) {
- #ifndef NDEBUG
- // Check for consistency between the module header role
- // as obtained from the lookup and as obtained from the module.
- // This check is not cheap, so enable it only for debugging.
- SmallVectorImpl<const FileEntry *> &PvtHdrs
- = RequestedModule->PrivateHeaders;
- SmallVectorImpl<const FileEntry *>::iterator Look
- = std::find(PvtHdrs.begin(), PvtHdrs.end(), IncFileEnt);
- bool IsPrivate = Look != PvtHdrs.end();
- assert((IsPrivate && Role == ModuleMap::PrivateHeader)
- || (!IsPrivate && Role != ModuleMap::PrivateHeader));
- #endif
- return Role == ModuleMap::PrivateHeader &&
- RequestedModule->getTopLevelModule() != RequestingModule;
-}
-
-bool Preprocessor::violatesUseDeclarations(
- Module *RequestingModule,
- Module *RequestedModule) {
- ModuleMap &ModMap = HeaderInfo.getModuleMap();
- ModMap.resolveUses(RequestingModule, /*Complain=*/false);
- const SmallVectorImpl<Module *> &AllowedUses = RequestingModule->DirectUses;
- SmallVectorImpl<Module *>::const_iterator Declared =
- std::find(AllowedUses.begin(), AllowedUses.end(), RequestedModule);
- return Declared == AllowedUses.end();
-}
-
-void Preprocessor::verifyModuleInclude(SourceLocation FilenameLoc,
- StringRef Filename,
- const FileEntry *IncFileEnt) {
- Module *RequestingModule = getModuleForLocation(FilenameLoc);
- if (RequestingModule)
- HeaderInfo.getModuleMap().resolveUses(RequestingModule, /*Complain=*/false);
- ModuleMap::KnownHeader RequestedModule =
- HeaderInfo.getModuleMap().findModuleForHeader(IncFileEnt,
- RequestingModule);
-
- if (RequestingModule == RequestedModule.getModule())
- return; // No faults wihin a module, or between files both not in modules.
-
- if (RequestingModule != HeaderInfo.getModuleMap().SourceModule)
- return; // No errors for indirect modules.
- // This may be a bit of a problem for modules with no source files.
-
- if (RequestedModule && violatesPrivateInclude(RequestingModule, IncFileEnt,
- RequestedModule.getRole(),
- RequestedModule.getModule()))
- Diag(FilenameLoc, diag::error_use_of_private_header_outside_module)
- << Filename;
-
- // FIXME: Add support for FixIts in module map files and offer adding the
- // required use declaration.
- if (RequestingModule && getLangOpts().ModulesDeclUse &&
- violatesUseDeclarations(RequestingModule, RequestedModule.getModule()))
- Diag(FilenameLoc, diag::error_undeclared_use_of_module)
- << Filename;
-}
-
const FileEntry *Preprocessor::LookupFile(
SourceLocation FilenameLoc,
StringRef Filename,
@@ -624,12 +567,12 @@ const FileEntry *Preprocessor::LookupFile(
SmallVectorImpl<char> *RelativePath,
ModuleMap::KnownHeader *SuggestedModule,
bool SkipCache) {
- // If the header lookup mechanism may be relative to the current file, pass in
- // info about where the current file is.
- const FileEntry *CurFileEnt = 0;
+ // If the header lookup mechanism may be relative to the current inclusion
+ // stack, record the parent #includes.
+ SmallVector<const FileEntry *, 16> Includers;
if (!FromDir) {
FileID FID = getCurrentFileLexer()->getFileID();
- CurFileEnt = SourceMgr.getFileEntryForID(FID);
+ const FileEntry *FileEnt = SourceMgr.getFileEntryForID(FID);
// If there is no file entry associated with this file, it must be the
// predefines buffer. Any other file is not lexed with a normal lexer, so
@@ -637,48 +580,74 @@ const FileEntry *Preprocessor::LookupFile(
// predefines buffer, resolve #include references (which come from the
// -include command line argument) as if they came from the main file, this
// affects file lookup etc.
- if (CurFileEnt == 0) {
- FID = SourceMgr.getMainFileID();
- CurFileEnt = SourceMgr.getFileEntryForID(FID);
+ if (!FileEnt)
+ FileEnt = SourceMgr.getFileEntryForID(SourceMgr.getMainFileID());
+
+ if (FileEnt)
+ Includers.push_back(FileEnt);
+
+ // MSVC searches the current include stack from top to bottom for
+ // headers included by quoted include directives.
+ // See: http://msdn.microsoft.com/en-us/library/36k2cdd4.aspx
+ if (LangOpts.MSVCCompat && !isAngled) {
+ for (unsigned i = 0, e = IncludeMacroStack.size(); i != e; ++i) {
+ IncludeStackInfo &ISEntry = IncludeMacroStack[e - i - 1];
+ if (IsFileLexer(ISEntry))
+ if ((FileEnt = SourceMgr.getFileEntryForID(
+ ISEntry.ThePPLexer->getFileID())))
+ Includers.push_back(FileEnt);
+ }
}
}
// Do a standard file entry lookup.
CurDir = CurDirLookup;
const FileEntry *FE = HeaderInfo.LookupFile(
- Filename, isAngled, FromDir, CurDir, CurFileEnt,
- SearchPath, RelativePath, SuggestedModule, SkipCache);
+ Filename, FilenameLoc, isAngled, FromDir, CurDir, Includers, SearchPath,
+ RelativePath, SuggestedModule, SkipCache);
if (FE) {
- if (SuggestedModule)
- verifyModuleInclude(FilenameLoc, Filename, FE);
+ if (SuggestedModule && !LangOpts.AsmPreprocessor)
+ HeaderInfo.getModuleMap().diagnoseHeaderInclusion(
+ getModuleForLocation(FilenameLoc), FilenameLoc, Filename, FE);
return FE;
}
+ const FileEntry *CurFileEnt;
// Otherwise, see if this is a subframework header. If so, this is relative
// 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 = SourceMgr.getFileEntryForID(CurPPLexer->getFileID()))) {
if ((FE = HeaderInfo.LookupSubframeworkHeader(Filename, CurFileEnt,
SearchPath, RelativePath,
- SuggestedModule)))
+ SuggestedModule))) {
+ if (SuggestedModule && !LangOpts.AsmPreprocessor)
+ HeaderInfo.getModuleMap().diagnoseHeaderInclusion(
+ getModuleForLocation(FilenameLoc), FilenameLoc, Filename, FE);
return FE;
+ }
+ }
}
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())))
+ SourceMgr.getFileEntryForID(ISEntry.ThePPLexer->getFileID()))) {
if ((FE = HeaderInfo.LookupSubframeworkHeader(
Filename, CurFileEnt, SearchPath, RelativePath,
- SuggestedModule)))
+ SuggestedModule))) {
+ if (SuggestedModule && !LangOpts.AsmPreprocessor)
+ HeaderInfo.getModuleMap().diagnoseHeaderInclusion(
+ getModuleForLocation(FilenameLoc), FilenameLoc, Filename, FE);
return FE;
+ }
+ }
}
}
// Otherwise, we really couldn't find the file.
- return 0;
+ return nullptr;
}
@@ -776,7 +745,7 @@ void Preprocessor::HandleDirective(Token &Result) {
return HandleDigitDirective(Result);
default:
IdentifierInfo *II = Result.getIdentifierInfo();
- if (II == 0) break; // Not an identifier.
+ if (!II) break; // Not an identifier.
// Ask what the preprocessor keyword ID is.
switch (II->getPPKeywordID()) {
@@ -986,7 +955,7 @@ void Preprocessor::HandleLineDirective(Token &Tok) {
return DiscardUntilEndOfDirective();
} else {
// Parse and validate the string, converting it into a unique ID.
- StringLiteralParser Literal(&StrTok, 1, *this);
+ StringLiteralParser Literal(StrTok, *this);
assert(Literal.isAscii() && "Didn't allow wide strings in");
if (Literal.hadError)
return DiscardUntilEndOfDirective();
@@ -1122,7 +1091,7 @@ void Preprocessor::HandleDigitDirective(Token &DigitTok) {
return DiscardUntilEndOfDirective();
} else {
// Parse and validate the string, converting it into a unique ID.
- StringLiteralParser Literal(&StrTok, 1, *this);
+ StringLiteralParser Literal(StrTok, *this);
assert(Literal.isAscii() && "Didn't allow wide strings in");
if (Literal.hadError)
return DiscardUntilEndOfDirective();
@@ -1241,7 +1210,7 @@ void Preprocessor::HandleMacroPublicDirective(Token &Tok) {
MacroDirective *MD = getMacroDirective(II);
// If the macro is not defined, this is an error.
- if (MD == 0) {
+ if (!MD) {
Diag(MacroNameTok, diag::err_pp_visibility_non_macro) << II;
return;
}
@@ -1268,7 +1237,7 @@ void Preprocessor::HandleMacroPrivateDirective(Token &Tok) {
MacroDirective *MD = getMacroDirective(II);
// If the macro is not defined, this is an error.
- if (MD == 0) {
+ if (!MD) {
Diag(MacroNameTok, diag::err_pp_visibility_non_macro) << II;
return;
}
@@ -1327,21 +1296,20 @@ bool Preprocessor::GetIncludeFilenameSpelling(SourceLocation Loc,
return isAngled;
}
-/// \brief 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:
-/// \code
-/// \#define FOO <a/b.h>
-/// \#include FOO
-/// \endcode
-/// because in this case, "<a/b.h>" is returned as 7 tokens, not one.
-///
-/// This code concatenates and consumes tokens up to the '>' token. It returns
-/// false if the > was found, otherwise it returns true if it finds and consumes
-/// the EOD marker.
-bool Preprocessor::ConcatenateIncludeName(
- SmallString<128> &FilenameBuffer,
+// \brief 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:
+// \code
+// \#define FOO <a/b.h>
+// \#include FOO
+// \endcode
+// because in this case, "<a/b.h>" is returned as 7 tokens, not one.
+//
+// This code concatenates and consumes tokens up to the '>' token. It returns
+// false if the > was found, otherwise it returns true if it finds and consumes
+// the EOD marker.
+bool Preprocessor::ConcatenateIncludeName(SmallString<128> &FilenameBuffer,
SourceLocation &End) {
Token CurTok;
@@ -1389,6 +1357,19 @@ bool Preprocessor::ConcatenateIncludeName(
return true;
}
+/// \brief Push a token onto the token stream containing an annotation.
+static void EnterAnnotationToken(Preprocessor &PP,
+ SourceLocation Begin, SourceLocation End,
+ tok::TokenKind Kind, void *AnnotationVal) {
+ Token *Tok = new Token[1];
+ Tok[0].startToken();
+ Tok[0].setKind(Kind);
+ Tok[0].setLocation(Begin);
+ Tok[0].setAnnotationEndLoc(End);
+ Tok[0].setAnnotationValue(AnnotationVal);
+ PP.EnterTokenStream(Tok, 1, true, true);
+}
+
/// HandleIncludeDirective - The "\#include" tokens have just been read, read
/// the file to be included from the lexer, then include it! This is a common
/// routine with functionality shared between \#include, \#include_next and
@@ -1485,10 +1466,16 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
// the path.
ModuleMap::KnownHeader SuggestedModule;
SourceLocation FilenameLoc = FilenameTok.getLocation();
+ SmallString<128> NormalizedPath;
+ if (LangOpts.MSVCCompat) {
+ NormalizedPath = Filename.str();
+ llvm::sys::fs::normalize_separators(NormalizedPath);
+ }
const FileEntry *File = LookupFile(
- FilenameLoc, Filename, isAngled, LookupFrom, CurDir,
- Callbacks ? &SearchPath : NULL, Callbacks ? &RelativePath : NULL,
- HeaderInfo.getHeaderSearchOpts().ModuleMaps ? &SuggestedModule : 0);
+ FilenameLoc, LangOpts.MSVCCompat ? NormalizedPath.c_str() : Filename,
+ isAngled, LookupFrom, CurDir, Callbacks ? &SearchPath : nullptr,
+ Callbacks ? &RelativePath : nullptr,
+ HeaderInfo.getHeaderSearchOpts().ModuleMaps ? &SuggestedModule : nullptr);
if (Callbacks) {
if (!File) {
@@ -1501,10 +1488,13 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
HeaderInfo.AddSearchPath(DL, isAngled);
// Try the lookup again, skipping the cache.
- File = LookupFile(FilenameLoc, Filename, isAngled, LookupFrom, CurDir,
- 0, 0, HeaderInfo.getHeaderSearchOpts().ModuleMaps
+ File = LookupFile(FilenameLoc,
+ LangOpts.MSVCCompat ? NormalizedPath.c_str()
+ : Filename,
+ isAngled, LookupFrom, CurDir, nullptr, nullptr,
+ HeaderInfo.getHeaderSearchOpts().ModuleMaps
? &SuggestedModule
- : 0,
+ : nullptr,
/*SkipCache*/ true);
}
}
@@ -1512,23 +1502,26 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
if (!SuggestedModule || !getLangOpts().Modules) {
// Notify the callback object that we've seen an inclusion directive.
- Callbacks->InclusionDirective(HashLoc, IncludeTok, Filename, isAngled,
- FilenameRange, File,
- SearchPath, RelativePath,
- /*ImportedModule=*/0);
+ Callbacks->InclusionDirective(HashLoc, IncludeTok,
+ LangOpts.MSVCCompat ? NormalizedPath.c_str()
+ : Filename,
+ isAngled, FilenameRange, File, SearchPath,
+ RelativePath, /*ImportedModule=*/nullptr);
}
}
-
- if (File == 0) {
+
+ if (!File) {
if (!SuppressIncludeNotFoundError) {
// If the file could not be located and it was included via angle
// brackets, we can attempt a lookup as though it were a quoted path to
// provide the user with a possible fixit.
if (isAngled) {
File = LookupFile(
- FilenameLoc, Filename, false, LookupFrom, CurDir,
- Callbacks ? &SearchPath : 0, Callbacks ? &RelativePath : 0,
- HeaderInfo.getHeaderSearchOpts().ModuleMaps ? &SuggestedModule : 0);
+ FilenameLoc, LangOpts.MSVCCompat ? NormalizedPath.c_str() : Filename,
+ false, LookupFrom, CurDir, Callbacks ? &SearchPath : nullptr,
+ Callbacks ? &RelativePath : nullptr,
+ HeaderInfo.getHeaderSearchOpts().ModuleMaps ? &SuggestedModule
+ : nullptr);
if (File) {
SourceRange Range(FilenameTok.getLocation(), CharEnd);
Diag(FilenameTok, diag::err_pp_file_not_found_not_fatal) <<
@@ -1590,7 +1583,7 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
// include directive maps to.
bool BuildingImportedModule
= Path[0].first->getName() == getLangOpts().CurrentModule;
-
+
if (!BuildingImportedModule && getLangOpts().ObjC2) {
// If we're not building the imported module, warn that we're going
// to automatically turn this inclusion directive into a module import.
@@ -1609,7 +1602,7 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
ModuleLoadResult Imported
= TheModuleLoader.loadModule(IncludeTok.getLocation(), Path, Visibility,
/*IsIncludeDirective=*/true);
- assert((Imported == 0 || Imported == SuggestedModule.getModule()) &&
+ assert((Imported == nullptr || Imported == SuggestedModule.getModule()) &&
"the imported module is different than the suggested one");
if (!Imported && hadModuleLoaderFatalFailure()) {
@@ -1639,13 +1632,8 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
// make the module visible.
// FIXME: Produce this as the current token directly, rather than
// allocating a new token for it.
- Token *Tok = new Token[1];
- Tok[0].startToken();
- Tok[0].setKind(tok::annot_module_include);
- Tok[0].setLocation(HashLoc);
- Tok[0].setAnnotationEndLoc(End);
- Tok[0].setAnnotationValue(Imported);
- EnterTokenStream(Tok, 1, true, true);
+ EnterAnnotationToken(*this, HashLoc, End, tok::annot_module_include,
+ Imported);
}
return;
}
@@ -1665,7 +1653,7 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
Callbacks->InclusionDirective(HashLoc, IncludeTok, Filename, isAngled,
FilenameRange, File,
SearchPath, RelativePath,
- /*ImportedModule=*/0);
+ /*ImportedModule=*/nullptr);
}
// The #included file will be considered to be a system header if either it is
@@ -1692,8 +1680,27 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
FileID FID = SourceMgr.createFileID(File, IncludePos, FileCharacter);
assert(!FID.isInvalid() && "Expected valid file ID");
- // Finally, if all is good, enter the new file!
- EnterSourceFile(FID, CurDir, FilenameTok.getLocation());
+ // Determine if we're switching to building a new submodule, and which one.
+ ModuleMap::KnownHeader BuildingModule;
+ if (getLangOpts().Modules && !getLangOpts().CurrentModule.empty()) {
+ Module *RequestingModule = getModuleForLocation(FilenameLoc);
+ BuildingModule =
+ HeaderInfo.getModuleMap().findModuleForHeader(File, RequestingModule);
+ }
+
+ // If all is good, enter the new file!
+ if (EnterSourceFile(FID, CurDir, FilenameTok.getLocation()))
+ return;
+
+ // If we're walking into another part of the same module, let the parser
+ // know that any future declarations are within that other submodule.
+ if (BuildingModule) {
+ assert(!CurSubmodule && "should not have marked this as a module yet");
+ CurSubmodule = BuildingModule.getModule();
+
+ EnterAnnotationToken(*this, HashLoc, End, tok::annot_module_begin,
+ CurSubmodule);
+ }
}
/// HandleIncludeNextDirective - Implements \#include_next.
@@ -1707,9 +1714,9 @@ void Preprocessor::HandleIncludeNextDirective(SourceLocation HashLoc,
// diagnostic.
const DirectoryLookup *Lookup = CurDirLookup;
if (isInPrimaryFile()) {
- Lookup = 0;
+ Lookup = nullptr;
Diag(IncludeNextTok, diag::pp_include_next_in_primary);
- } else if (Lookup == 0) {
+ } else if (!Lookup) {
Diag(IncludeNextTok, diag::pp_include_next_absolute_path);
} else {
// Start looking up in the next directory.
@@ -1738,11 +1745,11 @@ void Preprocessor::HandleMicrosoftImportDirective(Token &Tok) {
void Preprocessor::HandleImportDirective(SourceLocation HashLoc,
Token &ImportTok) {
if (!LangOpts.ObjC1) { // #import is standard for ObjC.
- if (LangOpts.MicrosoftMode)
+ if (LangOpts.MSVCCompat)
return HandleMicrosoftImportDirective(ImportTok);
Diag(ImportTok, diag::ext_pp_import_directive);
}
- return HandleIncludeDirective(HashLoc, ImportTok, 0, true);
+ return HandleIncludeDirective(HashLoc, ImportTok, nullptr, true);
}
/// HandleIncludeMacrosDirective - The -imacros command line option turns into a
@@ -1763,7 +1770,7 @@ void Preprocessor::HandleIncludeMacrosDirective(SourceLocation HashLoc,
// Treat this as a normal #include for checking purposes. If this is
// successful, it will push a new lexer onto the include stack.
- HandleIncludeDirective(HashLoc, IncludeMacrosTok, 0, false);
+ HandleIncludeDirective(HashLoc, IncludeMacrosTok, nullptr, false);
Token TmpTok;
do {
@@ -1823,7 +1830,7 @@ bool Preprocessor::ReadMacroDefinitionArgList(MacroInfo *MI, Token &Tok) {
// Handle keywords and identifiers here to accept things like
// #define Foo(for) for.
IdentifierInfo *II = Tok.getIdentifierInfo();
- if (II == 0) {
+ if (!II) {
// #define X(1
Diag(Tok, diag::err_pp_invalid_tok_in_arg_list);
return true;
@@ -2027,7 +2034,7 @@ void Preprocessor::HandleDefineDirective(Token &DefineTok,
LexUnexpandedToken(Tok);
// Check for a valid macro arg identifier.
- if (Tok.getIdentifierInfo() == 0 ||
+ if (Tok.getIdentifierInfo() == nullptr ||
MI->getArgumentNum(Tok.getIdentifierInfo()) == -1) {
// If this is assembler-with-cpp mode, we accept random gibberish after
@@ -2115,8 +2122,7 @@ void Preprocessor::HandleDefineDirective(Token &DefineTok,
// If we need warning for not using the macro, add its location in the
// warn-because-unused-macro set. If it gets used it will be removed from set.
if (getSourceManager().isInMainFile(MI->getDefinitionLoc()) &&
- Diags->getDiagnosticLevel(diag::pp_macro_not_used,
- MI->getDefinitionLoc()) != DiagnosticsEngine::Ignored) {
+ !Diags->isIgnored(diag::pp_macro_not_used, MI->getDefinitionLoc())) {
MI->setIsWarnIfUnused(true);
WarnUnusedMacroLocs.insert(MI->getDefinitionLoc());
}
@@ -2143,7 +2149,7 @@ void Preprocessor::HandleUndefDirective(Token &UndefTok) {
// Okay, we finally have a valid identifier to undef.
MacroDirective *MD = getMacroDirective(MacroNameTok.getIdentifierInfo());
- const MacroInfo *MI = MD ? MD->getMacroInfo() : 0;
+ const MacroInfo *MI = MD ? MD->getMacroInfo() : nullptr;
// If the callbacks want to know, tell them about the macro #undef.
// Note: no matter if the macro was defined or not.
@@ -2151,7 +2157,8 @@ void Preprocessor::HandleUndefDirective(Token &UndefTok) {
Callbacks->MacroUndefined(MacroNameTok, MD);
// If the macro is not defined, this is a noop undef, just return.
- if (MI == 0) return;
+ if (!MI)
+ return;
if (!MI->isUsed() && MI->isWarnIfUnused())
Diag(MI->getDefinitionLoc(), diag::pp_macro_not_used);
@@ -2195,14 +2202,14 @@ void Preprocessor::HandleIfdefDirective(Token &Result, bool isIfndef,
IdentifierInfo *MII = MacroNameTok.getIdentifierInfo();
MacroDirective *MD = getMacroDirective(MII);
- MacroInfo *MI = MD ? MD->getMacroInfo() : 0;
+ MacroInfo *MI = MD ? MD->getMacroInfo() : nullptr;
if (CurPPLexer->getConditionalStackDepth() == 0) {
// If the start of a top-level #ifdef and if the macro is not defined,
// inform MIOpt that this might be the start of a proper include guard.
// Otherwise it is some other form of unknown conditional which we can't
// handle.
- if (!ReadAnyTokensBeforeDirective && MI == 0) {
+ if (!ReadAnyTokensBeforeDirective && !MI) {
assert(isIfndef && "#ifdef shouldn't reach here");
CurPPLexer->MIOpt.EnterTopLevelIfndef(MII, MacroNameTok.getLocation());
} else
@@ -2241,7 +2248,7 @@ void Preprocessor::HandleIfDirective(Token &IfToken,
++NumIf;
// Parse and evaluate the conditional expression.
- IdentifierInfo *IfNDefMacro = 0;
+ IdentifierInfo *IfNDefMacro = nullptr;
const SourceLocation ConditionalBegin = CurPPLexer->getSourceLocation();
const bool ConditionalTrue = EvaluateDirectiveExpression(IfNDefMacro);
const SourceLocation ConditionalEnd = CurPPLexer->getSourceLocation();
@@ -2259,7 +2266,7 @@ void Preprocessor::HandleIfDirective(Token &IfToken,
if (Callbacks)
Callbacks->If(IfToken.getLocation(),
SourceRange(ConditionalBegin, ConditionalEnd),
- ConditionalTrue);
+ (ConditionalTrue ? PPCallbacks::CVK_True : PPCallbacks::CVK_False));
// Should we include the stuff contained by this directive?
if (ConditionalTrue) {
@@ -2356,7 +2363,7 @@ void Preprocessor::HandleElifDirective(Token &ElifToken) {
if (Callbacks)
Callbacks->Elif(ElifToken.getLocation(),
SourceRange(ConditionalBegin, ConditionalEnd),
- true, CI.IfLoc);
+ PPCallbacks::CVK_NotEvaluated, CI.IfLoc);
// Finally, skip the rest of the contents of this block.
SkipExcludedConditionalBlock(CI.IfLoc, /*Foundnonskip*/true,
diff --git a/lib/Lex/PPExpressions.cpp b/lib/Lex/PPExpressions.cpp
index 87c0a6ace6cb..2260bf98f7a5 100644
--- a/lib/Lex/PPExpressions.cpp
+++ b/lib/Lex/PPExpressions.cpp
@@ -81,7 +81,6 @@ struct DefinedTracker {
/// EvaluateDefined - Process a 'defined(sym)' expression.
static bool EvaluateDefined(PPValue &Result, Token &PeekTok, DefinedTracker &DT,
bool ValueLive, Preprocessor &PP) {
- IdentifierInfo *II;
SourceLocation beginLoc(PeekTok.getLocation());
Result.setBegin(beginLoc);
@@ -102,18 +101,17 @@ static bool EvaluateDefined(PPValue &Result, Token &PeekTok, DefinedTracker &DT,
PP.setCodeCompletionReached();
PP.LexUnexpandedNonComment(PeekTok);
}
-
+
// If we don't have a pp-identifier now, this is an error.
- if ((II = PeekTok.getIdentifierInfo()) == 0) {
- PP.Diag(PeekTok, diag::err_pp_defined_requires_identifier);
+ if (PP.CheckMacroName(PeekTok, 0))
return true;
- }
// Otherwise, we got an identifier, is it defined to something?
+ IdentifierInfo *II = PeekTok.getIdentifierInfo();
Result.Val = II->hasMacroDefinition();
Result.Val.setIsUnsigned(false); // Result is signed intmax_t.
- MacroDirective *Macro = 0;
+ MacroDirective *Macro = nullptr;
// If there is a macro, mark it used.
if (Result.Val != 0 && ValueLive) {
Macro = PP.getMacroDirective(II);
@@ -130,8 +128,9 @@ static bool EvaluateDefined(PPValue &Result, Token &PeekTok, DefinedTracker &DT,
PP.LexUnexpandedNonComment(PeekTok);
if (PeekTok.isNot(tok::r_paren)) {
- PP.Diag(PeekTok.getLocation(), diag::err_pp_missing_rparen) << "defined";
- PP.Diag(LParenLoc, diag::note_matching) << "(";
+ PP.Diag(PeekTok.getLocation(), diag::err_pp_expected_after)
+ << "'defined'" << tok::r_paren;
+ PP.Diag(LParenLoc, diag::note_matching) << tok::l_paren;
return true;
}
// Consume the ).
@@ -257,9 +256,10 @@ static bool EvaluateValue(PPValue &Result, Token &PeekTok, DefinedTracker &DT,
// large that it is unsigned" e.g. on 12345678901234567890 where intmax_t
// is 64-bits.
if (!Literal.isUnsigned && Result.Val.isNegative()) {
- // Don't warn for a hex or octal literal: 0x8000..0 shouldn't warn.
+ // Octal, hexadecimal, and binary literals are implicitly unsigned if
+ // the value does not fit into a signed integer type.
if (ValueLive && Literal.getRadix() == 10)
- PP.Diag(PeekTok, diag::warn_integer_too_large_for_signed);
+ PP.Diag(PeekTok, diag::ext_integer_too_large_for_signed);
Result.Val.setIsUnsigned(true);
}
}
@@ -342,7 +342,7 @@ static bool EvaluateValue(PPValue &Result, Token &PeekTok, DefinedTracker &DT,
if (PeekTok.isNot(tok::r_paren)) {
PP.Diag(PeekTok.getLocation(), diag::err_pp_expected_rparen)
<< Result.getRange();
- PP.Diag(Start, diag::note_matching) << "(";
+ PP.Diag(Start, diag::note_matching) << tok::l_paren;
return true;
}
DT.State = DefinedTracker::Unknown;
@@ -680,9 +680,9 @@ static bool EvaluateDirectiveSubExpr(PPValue &LHS, unsigned MinPrec,
case tok::question: {
// Parse the : part of the expression.
if (PeekTok.isNot(tok::colon)) {
- PP.Diag(PeekTok.getLocation(), diag::err_expected_colon)
- << LHS.getRange(), RHS.getRange();
- PP.Diag(OpLoc, diag::note_matching) << "?";
+ PP.Diag(PeekTok.getLocation(), diag::err_expected)
+ << tok::colon << LHS.getRange() << RHS.getRange();
+ PP.Diag(OpLoc, diag::note_matching) << tok::question;
return true;
}
// Consume the :.
diff --git a/lib/Lex/PPLexerChange.cpp b/lib/Lex/PPLexerChange.cpp
index 1f970a4450de..22ee971f4889 100644
--- a/lib/Lex/PPLexerChange.cpp
+++ b/lib/Lex/PPLexerChange.cpp
@@ -58,7 +58,7 @@ PreprocessorLexer *Preprocessor::getCurrentFileLexer() const {
if (IsFileLexer(ISI))
return ISI.ThePPLexer;
}
- return 0;
+ return nullptr;
}
@@ -68,7 +68,7 @@ PreprocessorLexer *Preprocessor::getCurrentFileLexer() const {
/// EnterSourceFile - Add a source file to the top of the include stack and
/// start lexing tokens from it instead of the current buffer.
-void Preprocessor::EnterSourceFile(FileID FID, const DirectoryLookup *CurDir,
+bool Preprocessor::EnterSourceFile(FileID FID, const DirectoryLookup *CurDir,
SourceLocation Loc) {
assert(!CurTokenLexer && "Cannot #include a file inside a macro!");
++NumEnteredSourceFiles;
@@ -79,7 +79,7 @@ void Preprocessor::EnterSourceFile(FileID FID, const DirectoryLookup *CurDir,
if (PTH) {
if (PTHLexer *PL = PTH->CreateLexer(FID)) {
EnterSourceFileWithPTH(PL, CurDir);
- return;
+ return false;
}
}
@@ -91,7 +91,7 @@ void Preprocessor::EnterSourceFile(FileID FID, const DirectoryLookup *CurDir,
SourceLocation FileStart = SourceMgr.getLocForStartOfFile(FID);
Diag(Loc, diag::err_pp_error_opening_file)
<< std::string(SourceMgr.getBufferName(FileStart)) << "";
- return;
+ return true;
}
if (isCodeCompletionEnabled() &&
@@ -102,7 +102,7 @@ void Preprocessor::EnterSourceFile(FileID FID, const DirectoryLookup *CurDir,
}
EnterSourceFileWithLexer(new Lexer(FID, InputFile, *this), CurDir);
- return;
+ return false;
}
/// EnterSourceFileWithLexer - Add a source file to the top of the include stack
@@ -117,6 +117,7 @@ void Preprocessor::EnterSourceFileWithLexer(Lexer *TheLexer,
CurLexer.reset(TheLexer);
CurPPLexer = TheLexer;
CurDirLookup = CurDir;
+ CurSubmodule = nullptr;
if (CurLexerKind != CLK_LexAfterModuleImport)
CurLexerKind = CLK_Lexer;
@@ -141,6 +142,7 @@ void Preprocessor::EnterSourceFileWithPTH(PTHLexer *PL,
CurDirLookup = CurDir;
CurPTHLexer.reset(PL);
CurPPLexer = CurPTHLexer.get();
+ CurSubmodule = nullptr;
if (CurLexerKind != CLK_LexAfterModuleImport)
CurLexerKind = CLK_PTHLexer;
@@ -167,7 +169,7 @@ void Preprocessor::EnterMacro(Token &Tok, SourceLocation ILEnd,
}
PushIncludeMacroStack();
- CurDirLookup = 0;
+ CurDirLookup = nullptr;
CurTokenLexer.reset(TokLexer);
if (CurLexerKind != CLK_LexAfterModuleImport)
CurLexerKind = CLK_TokenLexer;
@@ -200,7 +202,7 @@ void Preprocessor::EnterTokenStream(const Token *Toks, unsigned NumToks,
// Save our current state.
PushIncludeMacroStack();
- CurDirLookup = 0;
+ CurDirLookup = nullptr;
CurTokenLexer.reset(TokLexer);
if (CurLexerKind != CLK_LexAfterModuleImport)
CurLexerKind = CLK_TokenLexer;
@@ -244,6 +246,29 @@ 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.
+///
+/// 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
+/// diagnostics relating to the end of file include the last file that the user
+/// actually typed, which is goodness.
+const char *Preprocessor::getCurLexerEndPos() {
+ const char *EndPos = CurLexer->BufferEnd;
+ if (EndPos != CurLexer->BufferStart &&
+ (EndPos[-1] == '\n' || EndPos[-1] == '\r')) {
+ --EndPos;
+
+ // Handle \n\r and \r\n:
+ if (EndPos != CurLexer->BufferStart &&
+ (EndPos[-1] == '\n' || EndPos[-1] == '\r') &&
+ EndPos[-1] != EndPos[0])
+ --EndPos;
+ }
+
+ return EndPos;
+}
+
+
/// HandleEndOfFile - This callback is invoked when the lexer hits the end of
/// the current file. This either returns the EOF token or pops a level off
/// the include stack and keeps going.
@@ -259,6 +284,10 @@ bool Preprocessor::HandleEndOfFile(Token &Result, bool isEndOfMacro) {
if (const FileEntry *FE =
SourceMgr.getFileEntryForID(CurPPLexer->getFileID())) {
HeaderInfo.SetFileControllingMacro(FE, ControllingMacro);
+ if (MacroInfo *MI =
+ getMacroInfo(const_cast<IdentifierInfo*>(ControllingMacro))) {
+ MI->UsedForHeaderGuard = true;
+ }
if (const IdentifierInfo *DefinedMacro =
CurPPLexer->MIOpt.GetDefinedMacro()) {
if (!ControllingMacro->hasMacroDefinition() &&
@@ -325,7 +354,7 @@ bool Preprocessor::HandleEndOfFile(Token &Result, bool isEndOfMacro) {
CurPTHLexer.reset();
}
- CurPPLexer = 0;
+ CurPPLexer = nullptr;
return true;
}
@@ -342,7 +371,18 @@ bool Preprocessor::HandleEndOfFile(Token &Result, bool isEndOfMacro) {
FileID ExitedFID;
if (Callbacks && !isEndOfMacro && CurPPLexer)
ExitedFID = CurPPLexer->getFileID();
-
+
+ bool LeavingSubmodule = CurSubmodule && CurLexer;
+ if (LeavingSubmodule) {
+ // Notify the parser that we've left the module.
+ const char *EndPos = getCurLexerEndPos();
+ Result.startToken();
+ CurLexer->BufferPtr = EndPos;
+ CurLexer->FormTokenWithChars(Result, EndPos, tok::annot_module_end);
+ Result.setAnnotationEndLoc(Result.getLocation());
+ Result.setAnnotationValue(CurSubmodule);
+ }
+
// We're done with the #included file.
RemoveTopOfLexerStack();
@@ -357,27 +397,13 @@ bool Preprocessor::HandleEndOfFile(Token &Result, bool isEndOfMacro) {
PPCallbacks::ExitFile, FileType, ExitedFID);
}
- // Client should lex another token.
- return false;
+ // Client should lex another token unless we generated an EOM.
+ return LeavingSubmodule;
}
- // 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
- // diagnostics relating to the end of file include the last file that the user
- // actually typed, which is goodness.
+ // If this is the end of the main file, form an EOF token.
if (CurLexer) {
- const char *EndPos = CurLexer->BufferEnd;
- if (EndPos != CurLexer->BufferStart &&
- (EndPos[-1] == '\n' || EndPos[-1] == '\r')) {
- --EndPos;
-
- // Handle \n\r and \r\n:
- if (EndPos != CurLexer->BufferStart &&
- (EndPos[-1] == '\n' || EndPos[-1] == '\r') &&
- EndPos[-1] != EndPos[0])
- --EndPos;
- }
-
+ const char *EndPos = getCurLexerEndPos();
Result.startToken();
CurLexer->BufferPtr = EndPos;
CurLexer->FormTokenWithChars(Result, EndPos, tok::eof);
@@ -403,13 +429,17 @@ bool Preprocessor::HandleEndOfFile(Token &Result, bool isEndOfMacro) {
}
if (!isIncrementalProcessingEnabled())
- CurPPLexer = 0;
-
- // This is the end of the top-level file. 'WarnUnusedMacroLocs' has collected
- // all macro locations that we need to warn because they are not used.
- for (WarnUnusedMacroLocsTy::iterator
- I=WarnUnusedMacroLocs.begin(), E=WarnUnusedMacroLocs.end(); I!=E; ++I)
- Diag(*I, diag::pp_macro_not_used);
+ CurPPLexer = nullptr;
+
+ if (TUKind == TU_Complete) {
+ // This is the end of the top-level file. 'WarnUnusedMacroLocs' has
+ // collected all macro locations that we need to warn because they are not
+ // used.
+ for (WarnUnusedMacroLocsTy::iterator
+ I=WarnUnusedMacroLocs.begin(), E=WarnUnusedMacroLocs.end();
+ I!=E; ++I)
+ Diag(*I, diag::pp_macro_not_used);
+ }
// If we are building a module that has an umbrella header, make sure that
// each of the headers within the directory covered by the umbrella header
@@ -419,26 +449,25 @@ bool Preprocessor::HandleEndOfFile(Token &Result, bool isEndOfMacro) {
SourceLocation StartLoc
= SourceMgr.getLocForStartOfFile(SourceMgr.getMainFileID());
- if (getDiagnostics().getDiagnosticLevel(
- diag::warn_uncovered_module_header,
- StartLoc) != DiagnosticsEngine::Ignored) {
+ if (!getDiagnostics().isIgnored(diag::warn_uncovered_module_header,
+ StartLoc)) {
ModuleMap &ModMap = getHeaderSearchInfo().getModuleMap();
- typedef llvm::sys::fs::recursive_directory_iterator
- recursive_directory_iterator;
const DirectoryEntry *Dir = Mod->getUmbrellaDir();
- llvm::error_code EC;
- for (recursive_directory_iterator Entry(Dir->getName(), EC), End;
+ vfs::FileSystem &FS = *FileMgr.getVirtualFileSystem();
+ std::error_code EC;
+ for (vfs::recursive_directory_iterator Entry(FS, Dir->getName(), EC), End;
Entry != End && !EC; Entry.increment(EC)) {
using llvm::StringSwitch;
// Check whether this entry has an extension typically associated with
// headers.
- if (!StringSwitch<bool>(llvm::sys::path::extension(Entry->path()))
+ if (!StringSwitch<bool>(llvm::sys::path::extension(Entry->getName()))
.Cases(".h", ".H", ".hh", ".hpp", true)
.Default(false))
continue;
- if (const FileEntry *Header = getFileManager().getFile(Entry->path()))
+ if (const FileEntry *Header =
+ getFileManager().getFile(Entry->getName()))
if (!getSourceManager().hasFileInfo(Header)) {
if (!ModMap.isHeaderInUnavailableModule(Header)) {
// Find the relative path that would access this header.
@@ -456,9 +485,8 @@ bool Preprocessor::HandleEndOfFile(Token &Result, bool isEndOfMacro) {
// mentioned at all in the module map. Such headers
SourceLocation StartLoc
= SourceMgr.getLocForStartOfFile(SourceMgr.getMainFileID());
- if (getDiagnostics().getDiagnosticLevel(diag::warn_forgotten_module_header,
- StartLoc)
- != DiagnosticsEngine::Ignored) {
+ if (!getDiagnostics().isIgnored(diag::warn_forgotten_module_header,
+ StartLoc)) {
ModuleMap &ModMap = getHeaderSearchInfo().getModuleMap();
for (unsigned I = 0, N = SourceMgr.local_sloc_entry_size(); I != N; ++I) {
// We only care about file entries.
@@ -498,7 +526,7 @@ bool Preprocessor::HandleEndOfTokenLexer(Token &Result) {
if (NumCachedTokenLexers == TokenLexerCacheSize)
CurTokenLexer.reset();
else
- TokenLexerCache[NumCachedTokenLexers++] = CurTokenLexer.take();
+ TokenLexerCache[NumCachedTokenLexers++] = CurTokenLexer.release();
// Handle this like a #include file being popped off the stack.
return HandleEndOfFile(Result, true);
@@ -515,7 +543,7 @@ void Preprocessor::RemoveTopOfLexerStack() {
if (NumCachedTokenLexers == TokenLexerCacheSize)
CurTokenLexer.reset();
else
- TokenLexerCache[NumCachedTokenLexers++] = CurTokenLexer.take();
+ TokenLexerCache[NumCachedTokenLexers++] = CurTokenLexer.release();
}
PopIncludeMacroStack();
@@ -531,11 +559,11 @@ void Preprocessor::HandleMicrosoftCommentPaste(Token &Tok) {
// 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.
- PreprocessorLexer *FoundLexer = 0;
+ PreprocessorLexer *FoundLexer = nullptr;
bool LexerWasInPPMode = false;
for (unsigned i = 0, e = IncludeMacroStack.size(); i != e; ++i) {
IncludeStackInfo &ISI = *(IncludeMacroStack.end()-i-1);
- if (ISI.ThePPLexer == 0) continue; // Scan for a real lexer.
+ if (ISI.ThePPLexer == nullptr) continue; // Scan for a real lexer.
// Once we find a real lexer, mark it as raw mode (disabling macro
// expansions) and preprocessor mode (return EOD). We know that the lexer
diff --git a/lib/Lex/PPMacroExpansion.cpp b/lib/Lex/PPMacroExpansion.cpp
index f20633fda8c9..2d7c6d4b5227 100644
--- a/lib/Lex/PPMacroExpansion.cpp
+++ b/lib/Lex/PPMacroExpansion.cpp
@@ -7,19 +7,20 @@
//
//===----------------------------------------------------------------------===//
//
-// This file implements the top level handling of macro expasion for the
+// This file implements the top level handling of macro expansion for the
// preprocessor.
//
//===----------------------------------------------------------------------===//
#include "clang/Lex/Preprocessor.h"
-#include "clang/Lex/MacroArgs.h"
+#include "clang/Basic/Attributes.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Lex/CodeCompletionHandler.h"
#include "clang/Lex/ExternalPreprocessorSource.h"
#include "clang/Lex/LexDiagnostic.h"
+#include "clang/Lex/MacroArgs.h"
#include "clang/Lex/MacroInfo.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
@@ -97,6 +98,15 @@ void Preprocessor::RegisterBuiltinMacros() {
Ident__INCLUDE_LEVEL__ = RegisterBuiltinMacro(*this, "__INCLUDE_LEVEL__");
Ident__TIMESTAMP__ = RegisterBuiltinMacro(*this, "__TIMESTAMP__");
+ // Microsoft Extensions.
+ if (LangOpts.MicrosoftExt) {
+ Ident__identifier = RegisterBuiltinMacro(*this, "__identifier");
+ Ident__pragma = RegisterBuiltinMacro(*this, "__pragma");
+ } else {
+ Ident__identifier = nullptr;
+ Ident__pragma = nullptr;
+ }
+
// Clang Extensions.
Ident__has_feature = RegisterBuiltinMacro(*this, "__has_feature");
Ident__has_extension = RegisterBuiltinMacro(*this, "__has_extension");
@@ -105,6 +115,7 @@ void Preprocessor::RegisterBuiltinMacros() {
Ident__has_include = RegisterBuiltinMacro(*this, "__has_include");
Ident__has_include_next = RegisterBuiltinMacro(*this, "__has_include_next");
Ident__has_warning = RegisterBuiltinMacro(*this, "__has_warning");
+ Ident__is_identifier = RegisterBuiltinMacro(*this, "__is_identifier");
// Modules.
if (LangOpts.Modules) {
@@ -114,17 +125,11 @@ void Preprocessor::RegisterBuiltinMacros() {
if (!LangOpts.CurrentModule.empty())
Ident__MODULE__ = RegisterBuiltinMacro(*this, "__MODULE__");
else
- Ident__MODULE__ = 0;
+ Ident__MODULE__ = nullptr;
} else {
- Ident__building_module = 0;
- Ident__MODULE__ = 0;
+ Ident__building_module = nullptr;
+ Ident__MODULE__ = nullptr;
}
-
- // Microsoft Extensions.
- if (LangOpts.MicrosoftExt)
- Ident__pragma = RegisterBuiltinMacro(*this, "__pragma");
- else
- Ident__pragma = 0;
}
/// isTrivialSingleTokenExpansion - Return true if MI, which has a single token
@@ -135,7 +140,7 @@ static bool isTrivialSingleTokenExpansion(const MacroInfo *MI,
IdentifierInfo *II = MI->getReplacementToken(0).getIdentifierInfo();
// If the token isn't an identifier, it's always literally expanded.
- if (II == 0) return true;
+ if (!II) return true;
// If the information about this identifier is out of date, update it from
// the external source.
@@ -223,7 +228,8 @@ bool Preprocessor::HandleMacroExpandedIdentifier(Token &Identifier,
// If this is a builtin macro, like __LINE__ or _Pragma, handle it specially.
if (MI->isBuiltinMacro()) {
if (Callbacks) Callbacks->MacroExpands(Identifier, MD,
- Identifier.getLocation(),/*Args=*/0);
+ Identifier.getLocation(),
+ /*Args=*/nullptr);
ExpandBuiltinMacro(Identifier);
return true;
}
@@ -231,7 +237,7 @@ bool Preprocessor::HandleMacroExpandedIdentifier(Token &Identifier,
/// Args - If this is a function-like macro expansion, this contains,
/// for each macro argument, the list of tokens that were provided to the
/// invocation.
- MacroArgs *Args = 0;
+ MacroArgs *Args = nullptr;
// Remember where the end of the expansion occurred. For an object-like
// macro, this is the identifier. For a function-like macro, this is the ')'.
@@ -249,7 +255,7 @@ bool Preprocessor::HandleMacroExpandedIdentifier(Token &Identifier,
InMacroArgs = false;
// If there was an error parsing the arguments, bail out.
- if (Args == 0) return true;
+ if (!Args) return true;
++NumFnMacroExpanded;
} else {
@@ -277,7 +283,8 @@ bool Preprocessor::HandleMacroExpandedIdentifier(Token &Identifier,
for (unsigned i=0, e = DelayedMacroExpandsCallbacks.size(); i!=e; ++i) {
MacroExpandsInfo &Info = DelayedMacroExpandsCallbacks[i];
// FIXME: We lose macro args info with delayed callback.
- Callbacks->MacroExpands(Info.Tok, Info.MD, Info.Range, /*Args=*/0);
+ Callbacks->MacroExpands(Info.Tok, Info.MD, Info.Range,
+ /*Args=*/nullptr);
}
DelayedMacroExpandsCallbacks.clear();
}
@@ -293,11 +300,11 @@ bool Preprocessor::HandleMacroExpandedIdentifier(Token &Identifier,
for (MacroDirective::DefInfo PrevDef = Def.getPreviousDefinition();
PrevDef && !PrevDef.isUndefined();
PrevDef = PrevDef.getPreviousDefinition()) {
- if (PrevDef.getDirective()->isAmbiguous()) {
- Diag(PrevDef.getMacroInfo()->getDefinitionLoc(),
- diag::note_pp_ambiguous_macro_other)
- << Identifier.getIdentifierInfo();
- }
+ Diag(PrevDef.getMacroInfo()->getDefinitionLoc(),
+ diag::note_pp_ambiguous_macro_other)
+ << Identifier.getIdentifierInfo();
+ if (!PrevDef.getDirective()->isAmbiguous())
+ break;
}
}
@@ -552,7 +559,7 @@ MacroArgs *Preprocessor::ReadFunctionLikeMacroArgs(Token &MacroName,
<< MacroName.getIdentifierInfo();
// Do not lose the EOF/EOD. Return it to the client.
MacroName = Tok;
- return 0;
+ return nullptr;
} else {
// Do not lose the EOF/EOD.
Token *Toks = new Token[1];
@@ -584,7 +591,7 @@ MacroArgs *Preprocessor::ReadFunctionLikeMacroArgs(Token &MacroName,
// If this is a comment token in the argument list and we're just in
// -C mode (not -CC mode), discard the comment.
continue;
- } else if (Tok.getIdentifierInfo() != 0) {
+ } else if (Tok.getIdentifierInfo() != nullptr) {
// Reading macro arguments can cause macros that we are currently
// expanding from to be popped off the expansion stack. Doing so causes
// them to be reenabled for expansion. Here we record whether any
@@ -668,29 +675,18 @@ MacroArgs *Preprocessor::ReadFunctionLikeMacroArgs(Token &MacroName,
DiagnosticBuilder DB =
Diag(MacroName,
diag::note_init_list_at_beginning_of_macro_argument);
- for (SmallVector<SourceRange, 4>::iterator
- Range = InitLists.begin(), RangeEnd = InitLists.end();
- Range != RangeEnd; ++Range) {
- if (DB.hasMaxRanges())
- break;
- DB << *Range;
- }
+ for (const SourceRange &Range : InitLists)
+ DB << Range;
}
- return 0;
+ return nullptr;
}
if (FixedNumArgs != MinArgsExpected)
- return 0;
+ return nullptr;
DiagnosticBuilder DB = Diag(MacroName, diag::note_suggest_parens_for_macro);
- for (SmallVector<SourceRange, 4>::iterator
- ParenLocation = ParenHints.begin(), ParenEnd = ParenHints.end();
- ParenLocation != ParenEnd; ++ParenLocation) {
- if (DB.hasMaxFixItHints())
- break;
- DB << FixItHint::CreateInsertion(ParenLocation->getBegin(), "(");
- if (DB.hasMaxFixItHints())
- break;
- DB << FixItHint::CreateInsertion(ParenLocation->getEnd(), ")");
+ for (const SourceRange &ParenLocation : ParenHints) {
+ DB << FixItHint::CreateInsertion(ParenLocation.getBegin(), "(");
+ DB << FixItHint::CreateInsertion(ParenLocation.getEnd(), ")");
}
ArgTokens.swap(FixedArgTokens);
NumActuals = FixedNumArgs;
@@ -746,7 +742,7 @@ MacroArgs *Preprocessor::ReadFunctionLikeMacroArgs(Token &MacroName,
Diag(Tok, diag::err_too_few_args_in_macro_invoc);
Diag(MI->getDefinitionLoc(), diag::note_macro_here)
<< MacroName.getIdentifierInfo();
- return 0;
+ return nullptr;
}
// Add a marker EOF token to the end of the token list for this argument.
@@ -768,7 +764,7 @@ MacroArgs *Preprocessor::ReadFunctionLikeMacroArgs(Token &MacroName,
Diag(MacroName, diag::err_too_many_args_in_macro_invoc);
Diag(MI->getDefinitionLoc(), diag::note_macro_here)
<< MacroName.getIdentifierInfo();
- return 0;
+ return nullptr;
}
return MacroArgs::create(MI, ArgTokens, isVarargsElided, *this);
@@ -783,7 +779,7 @@ Token *Preprocessor::cacheMacroExpandedTokens(TokenLexer *tokLexer,
ArrayRef<Token> tokens) {
assert(tokLexer);
if (tokens.empty())
- return 0;
+ return nullptr;
size_t newIndex = MacroExpandedTokens.size();
bool cacheNeedsToGrow = tokens.size() >
@@ -796,7 +792,7 @@ Token *Preprocessor::cacheMacroExpandedTokens(TokenLexer *tokLexer,
for (unsigned i = 0, e = MacroExpandingLexersStack.size(); i != e; ++i) {
TokenLexer *prevLexer;
size_t tokIndex;
- llvm::tie(prevLexer, tokIndex) = MacroExpandingLexersStack[i];
+ std::tie(prevLexer, tokIndex) = MacroExpandingLexersStack[i];
prevLexer->Tokens = MacroExpandedTokens.data() + tokIndex;
}
}
@@ -819,7 +815,7 @@ void Preprocessor::removeCachedMacroExpandedTokensOfLastLexer() {
/// the identifier tokens inserted.
static void ComputeDATE_TIME(SourceLocation &DATELoc, SourceLocation &TIMELoc,
Preprocessor &PP) {
- time_t TT = time(0);
+ time_t TT = time(nullptr);
struct tm *TM = localtime(&TT);
static const char * const Months[] = {
@@ -881,7 +877,7 @@ static bool HasFeature(const Preprocessor &PP, const IdentifierInfo *II) {
.Case("attribute_unused_on_fields", true)
.Case("blocks", LangOpts.Blocks)
.Case("c_thread_safety_attributes", true)
- .Case("cxx_exceptions", LangOpts.Exceptions)
+ .Case("cxx_exceptions", LangOpts.CXXExceptions)
.Case("cxx_rtti", LangOpts.RTTI)
.Case("enumerator_attributes", true)
.Case("memory_sanitizer", LangOpts.Sanitize.Memory)
@@ -913,7 +909,7 @@ static bool HasFeature(const Preprocessor &PP, const IdentifierInfo *II) {
.Case("c_atomic", LangOpts.C11)
.Case("c_generic_selections", LangOpts.C11)
.Case("c_static_assert", LangOpts.C11)
- .Case("c_thread_local",
+ .Case("c_thread_local",
LangOpts.C11 && PP.getTargetInfo().isTLSSupported())
// C++11 features
.Case("cxx_access_control_sfinae", LangOpts.CPlusPlus11)
@@ -957,12 +953,17 @@ static bool HasFeature(const Preprocessor &PP, const IdentifierInfo *II) {
.Case("cxx_aggregate_nsdmi", LangOpts.CPlusPlus1y)
.Case("cxx_binary_literals", LangOpts.CPlusPlus1y)
.Case("cxx_contextual_conversions", LangOpts.CPlusPlus1y)
- //.Case("cxx_generic_lambdas", LangOpts.CPlusPlus1y)
+ .Case("cxx_decltype_auto", LangOpts.CPlusPlus1y)
+ .Case("cxx_generic_lambdas", LangOpts.CPlusPlus1y)
.Case("cxx_init_captures", LangOpts.CPlusPlus1y)
.Case("cxx_relaxed_constexpr", LangOpts.CPlusPlus1y)
.Case("cxx_return_type_deduction", LangOpts.CPlusPlus1y)
- //.Case("cxx_runtime_arrays", LangOpts.CPlusPlus1y)
.Case("cxx_variable_templates", LangOpts.CPlusPlus1y)
+ // 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
.Case("has_nothrow_assign", LangOpts.CPlusPlus)
.Case("has_nothrow_copy", LangOpts.CPlusPlus)
@@ -975,6 +976,7 @@ static bool HasFeature(const Preprocessor &PP, const IdentifierInfo *II) {
.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)
@@ -1004,8 +1006,8 @@ static bool HasExtension(const Preprocessor &PP, const IdentifierInfo *II) {
// If the use of an extension results in an error diagnostic, extensions are
// effectively unavailable, so just return false here.
- if (PP.getDiagnostics().getExtensionHandlingBehavior() ==
- DiagnosticsEngine::Ext_Error)
+ if (PP.getDiagnostics().getExtensionHandlingBehavior() >=
+ diag::Severity::Error)
return false;
const LangOptions &LangOpts = PP.getLangOpts();
@@ -1039,24 +1041,10 @@ static bool HasExtension(const Preprocessor &PP, const IdentifierInfo *II) {
// C++1y features supported by other languages as extensions.
.Case("cxx_binary_literals", true)
.Case("cxx_init_captures", LangOpts.CPlusPlus11)
- .Case("cxx_variable_templates", true)
+ .Case("cxx_variable_templates", LangOpts.CPlusPlus)
.Default(false);
}
-/// HasAttribute - Return true if we recognize and implement the attribute
-/// specified by the given identifier.
-static bool HasAttribute(const IdentifierInfo *II) {
- StringRef Name = II->getName();
- // Normalize the attribute name, __foo__ becomes foo.
- if (Name.startswith("__") && Name.endswith("__") && Name.size() >= 4)
- Name = Name.substr(2, Name.size() - 4);
-
- // FIXME: Do we need to handle namespaces here?
- return llvm::StringSwitch<bool>(Name)
-#include "clang/Lex/AttrSpellings.inc"
- .Default(false);
-}
-
/// EvaluateHasIncludeCommon - Process a '__has_include("path")'
/// or '__has_include_next("path")' expression.
/// Returns true if successful.
@@ -1080,7 +1068,7 @@ static bool EvaluateHasIncludeCommon(Token &Tok,
if (Tok.isNot(tok::l_paren)) {
// No '(', use end of last token.
LParenLoc = PP.getLocForEndOfToken(LParenLoc);
- PP.Diag(LParenLoc, diag::err_pp_missing_lparen) << II->getName();
+ PP.Diag(LParenLoc, diag::err_pp_expected_after) << II << tok::l_paren;
// If the next token looks like a filename or the start of one,
// assume it is and process it as such.
if (!Tok.is(tok::angle_string_literal) && !Tok.is(tok::string_literal) &&
@@ -1142,9 +1130,9 @@ static bool EvaluateHasIncludeCommon(Token &Tok,
// Ensure we have a trailing ).
if (Tok.isNot(tok::r_paren)) {
- PP.Diag(PP.getLocForEndOfToken(FilenameLoc), diag::err_pp_missing_rparen)
- << II->getName();
- PP.Diag(LParenLoc, diag::note_matching) << "(";
+ PP.Diag(PP.getLocForEndOfToken(FilenameLoc), diag::err_pp_expected_after)
+ << II << tok::r_paren;
+ PP.Diag(LParenLoc, diag::note_matching) << tok::l_paren;
return false;
}
@@ -1157,18 +1145,18 @@ static bool EvaluateHasIncludeCommon(Token &Tok,
// Search include directories.
const DirectoryLookup *CurDir;
const FileEntry *File =
- PP.LookupFile(FilenameLoc, Filename, isAngled, LookupFrom, CurDir, NULL,
- NULL, NULL);
+ PP.LookupFile(FilenameLoc, Filename, isAngled, LookupFrom, CurDir,
+ nullptr, nullptr, nullptr);
// Get the result value. A result of true means the file exists.
- return File != 0;
+ return File != nullptr;
}
/// EvaluateHasInclude - Process a '__has_include("path")' expression.
/// Returns true if successful.
static bool EvaluateHasInclude(Token &Tok, IdentifierInfo *II,
Preprocessor &PP) {
- return EvaluateHasIncludeCommon(Tok, II, PP, NULL);
+ return EvaluateHasIncludeCommon(Tok, II, PP, nullptr);
}
/// EvaluateHasIncludeNext - Process '__has_include_next("path")' expression.
@@ -1180,9 +1168,9 @@ static bool EvaluateHasIncludeNext(Token &Tok,
// issue a diagnostic.
const DirectoryLookup *Lookup = PP.GetCurDirLookup();
if (PP.isInPrimaryFile()) {
- Lookup = 0;
+ Lookup = nullptr;
PP.Diag(Tok, diag::pp_include_next_in_primary);
- } else if (Lookup == 0) {
+ } else if (!Lookup) {
PP.Diag(Tok, diag::pp_include_next_absolute_path);
} else {
// Start looking up in the next directory.
@@ -1201,7 +1189,8 @@ static bool EvaluateBuildingModule(Token &Tok,
// Ensure we have a '('.
if (Tok.isNot(tok::l_paren)) {
- PP.Diag(Tok.getLocation(), diag::err_pp_missing_lparen) << II->getName();
+ PP.Diag(Tok.getLocation(), diag::err_pp_expected_after) << II
+ << tok::l_paren;
return false;
}
@@ -1225,8 +1214,9 @@ static bool EvaluateBuildingModule(Token &Tok,
// Ensure we have a trailing ).
if (Tok.isNot(tok::r_paren)) {
- PP.Diag(Tok.getLocation(), diag::err_pp_missing_rparen) << II->getName();
- PP.Diag(LParenLoc, diag::note_matching) << "(";
+ PP.Diag(Tok.getLocation(), diag::err_pp_expected_after) << II
+ << tok::r_paren;
+ PP.Diag(LParenLoc, diag::note_matching) << tok::l_paren;
return false;
}
@@ -1253,7 +1243,7 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) {
llvm::raw_svector_ostream OS(TmpBuffer);
// Set up the return result.
- Tok.setIdentifierInfo(0);
+ Tok.setIdentifierInfo(nullptr);
Tok.clearFlag(Token::NeedsCleaning);
if (II == Ident__LINE__) {
@@ -1304,6 +1294,7 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) {
}
Tok.setKind(tok::string_literal);
} else if (II == Ident__DATE__) {
+ Diag(Tok.getLocation(), diag::warn_pp_date_time);
if (!DATELoc.isValid())
ComputeDATE_TIME(DATELoc, TIMELoc, *this);
Tok.setKind(tok::string_literal);
@@ -1313,6 +1304,7 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) {
Tok.getLength()));
return;
} else if (II == Ident__TIME__) {
+ Diag(Tok.getLocation(), diag::warn_pp_date_time);
if (!TIMELoc.isValid())
ComputeDATE_TIME(DATELoc, TIMELoc, *this);
Tok.setKind(tok::string_literal);
@@ -1337,12 +1329,13 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) {
OS << Depth;
Tok.setKind(tok::numeric_constant);
} else if (II == Ident__TIMESTAMP__) {
+ Diag(Tok.getLocation(), diag::warn_pp_date_time);
// MSVC, ICC, GCC, VisualAge C++ extension. The generated string should be
// of the form "Ddd Mmm dd hh::mm::ss yyyy", which is returned by asctime.
// Get the file that we are lexing out of. If we're currently lexing from
// a macro, dig into the include stack.
- const FileEntry *CurFile = 0;
+ const FileEntry *CurFile = nullptr;
PreprocessorLexer *TheLexer = getCurrentFileLexer();
if (TheLexer)
@@ -1357,7 +1350,7 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) {
Result = "??? ??? ?? ??:??:?? ????\n";
}
// Surround the string with " and strip the trailing newline.
- OS << '"' << StringRef(Result, strlen(Result)-1) << '"';
+ OS << '"' << StringRef(Result).drop_back() << '"';
Tok.setKind(tok::string_literal);
} else if (II == Ident__COUNTER__) {
// __COUNTER__ expands to a simple numeric value.
@@ -1366,12 +1359,13 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) {
} else if (II == Ident__has_feature ||
II == Ident__has_extension ||
II == Ident__has_builtin ||
+ II == Ident__is_identifier ||
II == Ident__has_attribute) {
// The argument to these builtins should be a parenthesized identifier.
SourceLocation StartLoc = Tok.getLocation();
bool IsValid = false;
- IdentifierInfo *FeatureII = 0;
+ IdentifierInfo *FeatureII = nullptr;
// Read the '('.
LexUnexpandedToken(Tok);
@@ -1389,11 +1383,14 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) {
bool Value = false;
if (!IsValid)
Diag(StartLoc, diag::err_feature_check_malformed);
+ else if (II == Ident__is_identifier)
+ Value = FeatureII->getTokenID() == tok::identifier;
else if (II == Ident__has_builtin) {
// Check for a builtin is trivial.
Value = FeatureII->getBuiltinID() != 0;
} else if (II == Ident__has_attribute)
- Value = HasAttribute(FeatureII);
+ Value = hasAttribute(AttrSyntax::Generic, nullptr, FeatureII,
+ getTargetInfo().getTriple(), getLangOpts());
else if (II == Ident__has_extension)
Value = HasExtension(*this, FeatureII);
else {
@@ -1449,6 +1446,8 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) {
break;
}
+ // FIXME: Should we accept "-R..." flags here, or should that be handled
+ // by a separate __has_remark?
if (WarningName.size() < 3 || WarningName[0] != '-' ||
WarningName[1] != 'W') {
Diag(StrStartLoc, diag::warn_has_warning_invalid_option);
@@ -1461,7 +1460,8 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) {
// worth special casing.
SmallVector<diag::kind, 10> Diags;
Value = !getDiagnostics().getDiagnosticIDs()->
- getDiagnosticsInGroup(WarningName.substr(2), Diags);
+ getDiagnosticsInGroup(diag::Flavor::WarningOrError,
+ WarningName.substr(2), Diags);
} while (false);
OS << (int)Value;
@@ -1479,6 +1479,44 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) {
IdentifierInfo *ModuleII = getIdentifierInfo(getLangOpts().CurrentModule);
Tok.setIdentifierInfo(ModuleII);
Tok.setKind(ModuleII->getTokenID());
+ } else if (II == Ident__identifier) {
+ SourceLocation Loc = Tok.getLocation();
+
+ // We're expecting '__identifier' '(' identifier ')'. Try to recover
+ // if the parens are missing.
+ LexNonComment(Tok);
+ if (Tok.isNot(tok::l_paren)) {
+ // No '(', use end of last token.
+ Diag(getLocForEndOfToken(Loc), diag::err_pp_expected_after)
+ << II << tok::l_paren;
+ // If the next token isn't valid as our argument, we can't recover.
+ if (!Tok.isAnnotation() && Tok.getIdentifierInfo())
+ Tok.setKind(tok::identifier);
+ return;
+ }
+
+ SourceLocation LParenLoc = Tok.getLocation();
+ LexNonComment(Tok);
+
+ if (!Tok.isAnnotation() && Tok.getIdentifierInfo())
+ Tok.setKind(tok::identifier);
+ else {
+ Diag(Tok.getLocation(), diag::err_pp_identifier_arg_not_identifier)
+ << Tok.getKind();
+ // Don't walk past anything that's not a real token.
+ if (Tok.is(tok::eof) || Tok.is(tok::eod) || Tok.isAnnotation())
+ return;
+ }
+
+ // Discard the ')', preserving 'Tok' as our result.
+ Token RParen;
+ LexNonComment(RParen);
+ if (RParen.isNot(tok::r_paren)) {
+ Diag(getLocForEndOfToken(Tok.getLocation()), diag::err_pp_expected_after)
+ << Tok.getKind() << tok::r_paren;
+ Diag(LParenLoc, diag::note_matching) << tok::l_paren;
+ }
+ return;
} else {
llvm_unreachable("Unknown identifier!");
}
diff --git a/lib/Lex/PTHLexer.cpp b/lib/Lex/PTHLexer.cpp
index e2629a3b2c49..fce31c4be296 100644
--- a/lib/Lex/PTHLexer.cpp
+++ b/lib/Lex/PTHLexer.cpp
@@ -15,21 +15,21 @@
#include "clang/Basic/FileManager.h"
#include "clang/Basic/FileSystemStatCache.h"
#include "clang/Basic/IdentifierTable.h"
-#include "clang/Basic/OnDiskHashTable.h"
#include "clang/Basic/TokenKinds.h"
#include "clang/Lex/LexDiagnostic.h"
#include "clang/Lex/PTHManager.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Lex/Token.h"
-#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringMap.h"
+#include "llvm/Support/EndianStream.h"
#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/system_error.h"
+#include "llvm/Support/OnDiskHashTable.h"
+#include <memory>
+#include <system_error>
using namespace clang;
-using namespace clang::io;
-#define DISK_TOKEN_SIZE (1+1+2+4+4)
+static const unsigned StoredTokenSize = 1 + 1 + 2 + 4 + 4;
//===----------------------------------------------------------------------===//
// PTHLexer methods.
@@ -37,7 +37,7 @@ using namespace clang::io;
PTHLexer::PTHLexer(Preprocessor &PP, FileID FID, const unsigned char *D,
const unsigned char *ppcond, PTHManager &PM)
- : PreprocessorLexer(&PP, FID), TokBuf(D), CurPtr(D), LastHashTokPtr(0),
+ : PreprocessorLexer(&PP, FID), TokBuf(D), CurPtr(D), LastHashTokPtr(nullptr),
PPCond(ppcond), CurPPCondPtr(ppcond), PTHMgr(PM) {
FileStartLoc = PP.getSourceManager().getLocForStartOfFile(FID);
@@ -47,14 +47,17 @@ bool PTHLexer::Lex(Token& Tok) {
//===--------------------------------------==//
// Read the raw token data.
//===--------------------------------------==//
+ using namespace llvm::support;
// Shadow CurPtr into an automatic variable.
const unsigned char *CurPtrShadow = CurPtr;
// Read in the data for the token.
- unsigned Word0 = ReadLE32(CurPtrShadow);
- uint32_t IdentifierID = ReadLE32(CurPtrShadow);
- uint32_t FileOffset = ReadLE32(CurPtrShadow);
+ unsigned Word0 = endian::readNext<uint32_t, little, aligned>(CurPtrShadow);
+ uint32_t IdentifierID =
+ endian::readNext<uint32_t, little, aligned>(CurPtrShadow);
+ uint32_t FileOffset =
+ endian::readNext<uint32_t, little, aligned>(CurPtrShadow);
tok::TokenKind TKind = (tok::TokenKind) (Word0 & 0xFF);
Token::TokenFlags TFlags = (Token::TokenFlags) ((Word0 >> 8) & 0xFF);
@@ -107,7 +110,7 @@ bool PTHLexer::Lex(Token& Tok) {
}
if (TKind == tok::hash && Tok.isAtStartOfLine()) {
- LastHashTokPtr = CurPtr - DISK_TOKEN_SIZE;
+ LastHashTokPtr = CurPtr - StoredTokenSize;
assert(!LexingRawMode);
PP->HandleDirective(Tok);
@@ -176,7 +179,7 @@ void PTHLexer::DiscardToEndOfLine() {
if (y & Token::StartOfLine) break;
// Skip to the next token.
- p += DISK_TOKEN_SIZE;
+ p += StoredTokenSize;
}
CurPtr = p;
@@ -184,18 +187,19 @@ void PTHLexer::DiscardToEndOfLine() {
/// SkipBlock - Used by Preprocessor to skip the current conditional block.
bool PTHLexer::SkipBlock() {
+ using namespace llvm::support;
assert(CurPPCondPtr && "No cached PP conditional information.");
assert(LastHashTokPtr && "No known '#' token.");
- const unsigned char* HashEntryI = 0;
+ const unsigned char *HashEntryI = nullptr;
uint32_t TableIdx;
do {
// Read the token offset from the side-table.
- uint32_t Offset = ReadLE32(CurPPCondPtr);
+ uint32_t Offset = endian::readNext<uint32_t, little, aligned>(CurPPCondPtr);
// Read the target table index from the side-table.
- TableIdx = ReadLE32(CurPPCondPtr);
+ TableIdx = endian::readNext<uint32_t, little, aligned>(CurPPCondPtr);
// Compute the actual memory address of the '#' token data for this entry.
HashEntryI = TokBuf + Offset;
@@ -212,12 +216,13 @@ bool PTHLexer::SkipBlock() {
PPCond + TableIdx*(sizeof(uint32_t)*2);
assert(NextPPCondPtr >= CurPPCondPtr);
// Read where we should jump to.
- const unsigned char* HashEntryJ = TokBuf + ReadLE32(NextPPCondPtr);
+ const unsigned char *HashEntryJ =
+ TokBuf + endian::readNext<uint32_t, little, aligned>(NextPPCondPtr);
if (HashEntryJ <= LastHashTokPtr) {
// Jump directly to the next entry in the side table.
HashEntryI = HashEntryJ;
- TableIdx = ReadLE32(NextPPCondPtr);
+ TableIdx = endian::readNext<uint32_t, little, aligned>(NextPPCondPtr);
CurPPCondPtr = NextPPCondPtr;
}
}
@@ -232,8 +237,9 @@ bool PTHLexer::SkipBlock() {
CurPPCondPtr = NextPPCondPtr;
// Read where we should jump to.
- HashEntryI = TokBuf + ReadLE32(NextPPCondPtr);
- uint32_t NextIdx = ReadLE32(NextPPCondPtr);
+ HashEntryI =
+ TokBuf + endian::readNext<uint32_t, little, aligned>(NextPPCondPtr);
+ uint32_t NextIdx = endian::readNext<uint32_t, little, aligned>(NextPPCondPtr);
// By construction NextIdx will be zero if this is a #endif. This is useful
// to know to obviate lexing another token.
@@ -249,10 +255,10 @@ bool PTHLexer::SkipBlock() {
// already points 'elif'. Just return.
if (CurPtr > HashEntryI) {
- assert(CurPtr == HashEntryI + DISK_TOKEN_SIZE);
+ assert(CurPtr == HashEntryI + StoredTokenSize);
// Did we reach a #endif? If so, go ahead and consume that token as well.
if (isEndif)
- CurPtr += DISK_TOKEN_SIZE*2;
+ CurPtr += StoredTokenSize * 2;
else
LastHashTokPtr = HashEntryI;
@@ -268,10 +274,12 @@ bool PTHLexer::SkipBlock() {
// Skip the '#' token.
assert(((tok::TokenKind)*CurPtr) == tok::hash);
- CurPtr += DISK_TOKEN_SIZE;
+ CurPtr += StoredTokenSize;
// Did we reach a #endif? If so, go ahead and consume that token as well.
- if (isEndif) { CurPtr += DISK_TOKEN_SIZE*2; }
+ if (isEndif) {
+ CurPtr += StoredTokenSize * 2;
+ }
return isEndif;
}
@@ -282,8 +290,10 @@ SourceLocation PTHLexer::getSourceLocation() {
// handling a #included file. Just read the necessary data from the token
// data buffer to construct the SourceLocation object.
// NOTE: This is a virtual function; hence it is defined out-of-line.
- const unsigned char *OffsetPtr = CurPtr + (DISK_TOKEN_SIZE - 4);
- uint32_t Offset = ReadLE32(OffsetPtr);
+ using namespace llvm::support;
+
+ const unsigned char *OffsetPtr = CurPtr + (StoredTokenSize - 4);
+ uint32_t Offset = endian::readNext<uint32_t, little, aligned>(OffsetPtr);
return FileStartLoc.getLocWithOffset(Offset);
}
@@ -310,14 +320,18 @@ public:
class PTHFileLookupCommonTrait {
public:
typedef std::pair<unsigned char, const char*> internal_key_type;
+ typedef unsigned hash_value_type;
+ typedef unsigned offset_type;
- static unsigned ComputeHash(internal_key_type x) {
+ static hash_value_type ComputeHash(internal_key_type x) {
return llvm::HashString(x.second);
}
static std::pair<unsigned, unsigned>
ReadKeyDataLength(const unsigned char*& d) {
- unsigned keyLen = (unsigned) ReadUnalignedLE16(d);
+ using namespace llvm::support;
+ unsigned keyLen =
+ (unsigned)endian::readNext<uint16_t, little, unaligned>(d);
unsigned dataLen = (unsigned) *(d++);
return std::make_pair(keyLen, dataLen);
}
@@ -344,21 +358,20 @@ public:
static PTHFileData ReadData(const internal_key_type& k,
const unsigned char* d, unsigned) {
assert(k.first == 0x1 && "Only file lookups can match!");
- uint32_t x = ::ReadUnalignedLE32(d);
- uint32_t y = ::ReadUnalignedLE32(d);
+ using namespace llvm::support;
+ uint32_t x = endian::readNext<uint32_t, little, unaligned>(d);
+ uint32_t y = endian::readNext<uint32_t, little, unaligned>(d);
return PTHFileData(x, y);
}
};
class PTHStringLookupTrait {
public:
- typedef uint32_t
- data_type;
-
- typedef const std::pair<const char*, unsigned>
- external_key_type;
-
+ typedef uint32_t data_type;
+ typedef const std::pair<const char*, unsigned> external_key_type;
typedef external_key_type internal_key_type;
+ typedef uint32_t hash_value_type;
+ typedef unsigned offset_type;
static bool EqualKey(const internal_key_type& a,
const internal_key_type& b) {
@@ -366,7 +379,7 @@ public:
: false;
}
- static unsigned ComputeHash(const internal_key_type& a) {
+ static hash_value_type ComputeHash(const internal_key_type& a) {
return llvm::HashString(StringRef(a.first, a.second));
}
@@ -376,7 +389,10 @@ public:
static std::pair<unsigned, unsigned>
ReadKeyDataLength(const unsigned char*& d) {
- return std::make_pair((unsigned) ReadUnalignedLE16(d), sizeof(uint32_t));
+ using namespace llvm::support;
+ return std::make_pair(
+ (unsigned)endian::readNext<uint16_t, little, unaligned>(d),
+ sizeof(uint32_t));
}
static std::pair<const char*, unsigned>
@@ -387,14 +403,15 @@ public:
static uint32_t ReadData(const internal_key_type& k, const unsigned char* d,
unsigned) {
- return ::ReadUnalignedLE32(d);
+ using namespace llvm::support;
+ return endian::readNext<uint32_t, little, unaligned>(d);
}
};
} // end anonymous namespace
-typedef OnDiskChainedHashTable<PTHFileLookupTrait> PTHFileLookup;
-typedef OnDiskChainedHashTable<PTHStringLookupTrait> PTHStringIdLookup;
+typedef llvm::OnDiskChainedHashTable<PTHFileLookupTrait> PTHFileLookup;
+typedef llvm::OnDiskChainedHashTable<PTHStringLookupTrait> PTHStringIdLookup;
//===----------------------------------------------------------------------===//
// PTHManager methods.
@@ -408,7 +425,7 @@ PTHManager::PTHManager(const llvm::MemoryBuffer* buf, void* fileLookup,
const char* originalSourceFile)
: Buf(buf), PerIDCache(perIDCache), FileLookup(fileLookup),
IdDataTable(idDataTable), StringIdLookup(stringIdLookup),
- NumIds(numIds), PP(0), SpellingBase(spellingBase),
+ NumIds(numIds), PP(nullptr), SpellingBase(spellingBase),
OriginalSourceFile(originalSourceFile) {}
PTHManager::~PTHManager() {
@@ -419,19 +436,23 @@ PTHManager::~PTHManager() {
}
static void InvalidPTH(DiagnosticsEngine &Diags, const char *Msg) {
- Diags.Report(Diags.getCustomDiagID(DiagnosticsEngine::Error, Msg));
+ Diags.Report(Diags.getCustomDiagID(DiagnosticsEngine::Error, "%0")) << Msg;
}
PTHManager *PTHManager::Create(const std::string &file,
DiagnosticsEngine &Diags) {
// Memory map the PTH file.
- OwningPtr<llvm::MemoryBuffer> File;
+ llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> FileOrErr =
+ llvm::MemoryBuffer::getFile(file);
- if (llvm::MemoryBuffer::getFile(file, File)) {
+ if (!FileOrErr) {
// FIXME: Add ec.message() to this diag.
Diags.Report(diag::err_invalid_pth_file) << file;
- return 0;
+ return nullptr;
}
+ std::unique_ptr<llvm::MemoryBuffer> File = std::move(FileOrErr.get());
+
+ using namespace llvm::support;
// Get the buffer ranges and check if there are at least three 32-bit
// words at the end of the file.
@@ -442,19 +463,19 @@ PTHManager *PTHManager::Create(const std::string &file,
if ((BufEnd - BufBeg) < (signed)(sizeof("cfe-pth") + 4 + 4) ||
memcmp(BufBeg, "cfe-pth", sizeof("cfe-pth")) != 0) {
Diags.Report(diag::err_invalid_pth_file) << file;
- return 0;
+ return nullptr;
}
// Read the PTH version.
const unsigned char *p = BufBeg + (sizeof("cfe-pth"));
- unsigned Version = ReadLE32(p);
+ unsigned Version = endian::readNext<uint32_t, little, aligned>(p);
if (Version < PTHManager::Version) {
InvalidPTH(Diags,
Version < PTHManager::Version
? "PTH file uses an older PTH format that is no longer supported"
: "PTH file uses a newer PTH format that cannot be read");
- return 0;
+ return nullptr;
}
// Compute the address of the index table at the end of the PTH file.
@@ -462,20 +483,21 @@ PTHManager *PTHManager::Create(const std::string &file,
if (PrologueOffset >= BufEnd) {
Diags.Report(diag::err_invalid_pth_file) << file;
- return 0;
+ return nullptr;
}
// Construct the file lookup table. This will be used for mapping from
// FileEntry*'s to cached tokens.
const unsigned char* FileTableOffset = PrologueOffset + sizeof(uint32_t)*2;
- const unsigned char* FileTable = BufBeg + ReadLE32(FileTableOffset);
+ const unsigned char *FileTable =
+ BufBeg + endian::readNext<uint32_t, little, aligned>(FileTableOffset);
if (!(FileTable > BufBeg && FileTable < BufEnd)) {
Diags.Report(diag::err_invalid_pth_file) << file;
- return 0; // FIXME: Proper error diagnostic?
+ return nullptr; // FIXME: Proper error diagnostic?
}
- OwningPtr<PTHFileLookup> FL(PTHFileLookup::Create(FileTable, BufBeg));
+ std::unique_ptr<PTHFileLookup> FL(PTHFileLookup::Create(FileTable, BufBeg));
// Warn if the PTH file is empty. We still want to create a PTHManager
// as the PTH could be used with -include-pth.
@@ -485,65 +507,71 @@ PTHManager *PTHManager::Create(const std::string &file,
// Get the location of the table mapping from persistent ids to the
// data needed to reconstruct identifiers.
const unsigned char* IDTableOffset = PrologueOffset + sizeof(uint32_t)*0;
- const unsigned char* IData = BufBeg + ReadLE32(IDTableOffset);
+ const unsigned char *IData =
+ BufBeg + endian::readNext<uint32_t, little, aligned>(IDTableOffset);
if (!(IData >= BufBeg && IData < BufEnd)) {
Diags.Report(diag::err_invalid_pth_file) << file;
- return 0;
+ return nullptr;
}
// Get the location of the hashtable mapping between strings and
// persistent IDs.
const unsigned char* StringIdTableOffset = PrologueOffset + sizeof(uint32_t)*1;
- const unsigned char* StringIdTable = BufBeg + ReadLE32(StringIdTableOffset);
+ const unsigned char *StringIdTable =
+ BufBeg + endian::readNext<uint32_t, little, aligned>(StringIdTableOffset);
if (!(StringIdTable >= BufBeg && StringIdTable < BufEnd)) {
Diags.Report(diag::err_invalid_pth_file) << file;
- return 0;
+ return nullptr;
}
- OwningPtr<PTHStringIdLookup> SL(PTHStringIdLookup::Create(StringIdTable,
- BufBeg));
+ std::unique_ptr<PTHStringIdLookup> SL(
+ PTHStringIdLookup::Create(StringIdTable, BufBeg));
// Get the location of the spelling cache.
const unsigned char* spellingBaseOffset = PrologueOffset + sizeof(uint32_t)*3;
- const unsigned char* spellingBase = BufBeg + ReadLE32(spellingBaseOffset);
+ const unsigned char *spellingBase =
+ BufBeg + endian::readNext<uint32_t, little, aligned>(spellingBaseOffset);
if (!(spellingBase >= BufBeg && spellingBase < BufEnd)) {
Diags.Report(diag::err_invalid_pth_file) << file;
- return 0;
+ return nullptr;
}
// Get the number of IdentifierInfos and pre-allocate the identifier cache.
- uint32_t NumIds = ReadLE32(IData);
+ uint32_t NumIds = endian::readNext<uint32_t, little, aligned>(IData);
// Pre-allocate the persistent ID -> IdentifierInfo* cache. We use calloc()
// so that we in the best case only zero out memory once when the OS returns
// us new pages.
- IdentifierInfo** PerIDCache = 0;
+ IdentifierInfo **PerIDCache = nullptr;
if (NumIds) {
PerIDCache = (IdentifierInfo**)calloc(NumIds, sizeof(*PerIDCache));
if (!PerIDCache) {
InvalidPTH(Diags, "Could not allocate memory for processing PTH file");
- return 0;
+ return nullptr;
}
}
// Compute the address of the original source file.
const unsigned char* originalSourceBase = PrologueOffset + sizeof(uint32_t)*4;
- unsigned len = ReadUnalignedLE16(originalSourceBase);
- if (!len) originalSourceBase = 0;
+ unsigned len =
+ endian::readNext<uint16_t, little, unaligned>(originalSourceBase);
+ if (!len) originalSourceBase = nullptr;
// Create the new PTHManager.
- return new PTHManager(File.take(), FL.take(), IData, PerIDCache,
- SL.take(), NumIds, spellingBase,
- (const char*) originalSourceBase);
+ return new PTHManager(File.release(), FL.release(), IData, PerIDCache,
+ SL.release(), NumIds, spellingBase,
+ (const char *)originalSourceBase);
}
IdentifierInfo* PTHManager::LazilyCreateIdentifierInfo(unsigned PersistentID) {
+ using namespace llvm::support;
// Look in the PTH file for the string data for the IdentifierInfo object.
const unsigned char* TableEntry = IdDataTable + sizeof(uint32_t)*PersistentID;
- const unsigned char* IDData =
- (const unsigned char*)Buf->getBufferStart() + ReadLE32(TableEntry);
+ const unsigned char *IDData =
+ (const unsigned char *)Buf->getBufferStart() +
+ endian::readNext<uint32_t, little, aligned>(TableEntry);
assert(IDData < (const unsigned char*)Buf->getBufferEnd());
// Allocate the object.
@@ -567,7 +595,7 @@ IdentifierInfo* PTHManager::get(StringRef Name) {
PTHStringIdLookup::iterator I = SL.find(std::make_pair(Name.data(),
Name.size()));
if (I == SL.end()) // No identifier found?
- return 0;
+ return nullptr;
// Match found. Return the identifier!
assert(*I > 0);
@@ -577,7 +605,9 @@ IdentifierInfo* PTHManager::get(StringRef Name) {
PTHLexer *PTHManager::CreateLexer(FileID FID) {
const FileEntry *FE = PP->getSourceManager().getFileEntryForID(FID);
if (!FE)
- return 0;
+ return nullptr;
+
+ using namespace llvm::support;
// Lookup the FileEntry object in our file lookup data structure. It will
// return a variant that indicates whether or not there is an offset within
@@ -586,7 +616,7 @@ PTHLexer *PTHManager::CreateLexer(FileID FID) {
PTHFileLookup::iterator I = PFL.find(FE);
if (I == PFL.end()) // No tokens available?
- return 0;
+ return nullptr;
const PTHFileData& FileData = *I;
@@ -596,8 +626,8 @@ PTHLexer *PTHManager::CreateLexer(FileID FID) {
// Get the location of pp-conditional table.
const unsigned char* ppcond = BufStart + FileData.getPPCondOffset();
- uint32_t Len = ReadLE32(ppcond);
- if (Len == 0) ppcond = 0;
+ uint32_t Len = endian::readNext<uint32_t, little, aligned>(ppcond);
+ if (Len == 0) ppcond = nullptr;
assert(PP && "No preprocessor set yet!");
return new PTHLexer(*PP, FID, data, ppcond, *this);
@@ -650,11 +680,13 @@ public:
d += 4 * 2; // Skip the first 2 words.
}
- uint64_t File = ReadUnalignedLE64(d);
- uint64_t Device = ReadUnalignedLE64(d);
+ using namespace llvm::support;
+
+ uint64_t File = endian::readNext<uint64_t, little, unaligned>(d);
+ uint64_t Device = endian::readNext<uint64_t, little, unaligned>(d);
llvm::sys::fs::UniqueID UniqueID(File, Device);
- time_t ModTime = ReadUnalignedLE64(d);
- uint64_t Size = ReadUnalignedLE64(d);
+ time_t ModTime = endian::readNext<uint64_t, little, unaligned>(d);
+ uint64_t Size = endian::readNext<uint64_t, little, unaligned>(d);
return data_type(Size, ModTime, UniqueID, IsDirectory);
}
@@ -664,7 +696,7 @@ public:
};
class PTHStatCache : public FileSystemStatCache {
- typedef OnDiskChainedHashTable<PTHStatLookupTrait> CacheTy;
+ typedef llvm::OnDiskChainedHashTable<PTHStatLookupTrait> CacheTy;
CacheTy Cache;
public:
@@ -672,22 +704,22 @@ public:
Cache(FL.getNumBuckets(), FL.getNumEntries(), FL.getBuckets(),
FL.getBase()) {}
- ~PTHStatCache() {}
-
LookupResult getStat(const char *Path, FileData &Data, bool isFile,
- int *FileDescriptor) {
+ std::unique_ptr<vfs::File> *F,
+ vfs::FileSystem &FS) override {
// Do the lookup for the file's data in the PTH file.
CacheTy::iterator I = Cache.find(Path);
// If we don't get a hit in the PTH file just forward to 'stat'.
if (I == Cache.end())
- return statChained(Path, Data, isFile, FileDescriptor);
+ return statChained(Path, Data, isFile, F, FS);
const PTHStatData &D = *I;
if (!D.HasData)
return CacheMissing;
+ Data.Name = Path;
Data.Size = D.Size;
Data.ModTime = D.ModTime;
Data.UniqueID = D.UniqueID;
diff --git a/lib/Lex/Pragma.cpp b/lib/Lex/Pragma.cpp
index e4059eeb6fc0..cf76bdb7a913 100644
--- a/lib/Lex/Pragma.cpp
+++ b/lib/Lex/Pragma.cpp
@@ -48,9 +48,7 @@ void EmptyPragmaHandler::HandlePragma(Preprocessor &PP,
//===----------------------------------------------------------------------===//
PragmaNamespace::~PragmaNamespace() {
- for (llvm::StringMap<PragmaHandler*>::iterator
- I = Handlers.begin(), E = Handlers.end(); I != E; ++I)
- delete I->second;
+ llvm::DeleteContainerSeconds(Handlers);
}
/// FindHandler - Check to see if there is already a handler for the
@@ -61,7 +59,7 @@ PragmaHandler *PragmaNamespace::FindHandler(StringRef Name,
bool IgnoreNull) const {
if (PragmaHandler *Handler = Handlers.lookup(Name))
return Handler;
- return IgnoreNull ? 0 : Handlers.lookup(StringRef());
+ return IgnoreNull ? nullptr : Handlers.lookup(StringRef());
}
void PragmaNamespace::AddPragma(PragmaHandler *Handler) {
@@ -90,7 +88,7 @@ void PragmaNamespace::HandlePragma(Preprocessor &PP,
= FindHandler(Tok.getIdentifierInfo() ? Tok.getIdentifierInfo()->getName()
: StringRef(),
/*IgnoreNull=*/false);
- if (Handler == 0) {
+ if (!Handler) {
PP.Diag(Tok, diag::warn_pragma_ignored);
return;
}
@@ -292,7 +290,7 @@ void Preprocessor::Handle_Pragma(Token &Tok) {
Lexer *TL = Lexer::Create_PragmaLexer(TokLoc, PragmaLoc, RParenLoc,
StrVal.size(), *this);
- EnterSourceFileWithLexer(TL, 0);
+ EnterSourceFileWithLexer(TL, nullptr);
// With everything set up, lex this as a #pragma directive.
HandlePragmaDirective(PragmaLoc, PIK__Pragma);
@@ -475,8 +473,9 @@ void Preprocessor::HandlePragmaDependency(Token &DependencyTok) {
// Search include directories for this file.
const DirectoryLookup *CurDir;
const FileEntry *File = LookupFile(FilenameTok.getLocation(), Filename,
- isAngled, 0, CurDir, NULL, NULL, NULL);
- if (File == 0) {
+ isAngled, nullptr, CurDir, nullptr,
+ nullptr, nullptr);
+ if (!File) {
if (!SuppressIncludeNotFoundError)
Diag(FilenameTok, diag::err_pp_file_not_found) << Filename;
return;
@@ -512,7 +511,7 @@ IdentifierInfo *Preprocessor::ParsePragmaPushOrPopMacro(Token &Tok) {
if (Tok.isNot(tok::l_paren)) {
Diag(PragmaTok.getLocation(), diag::err_pragma_push_pop_macro_malformed)
<< getSpelling(PragmaTok);
- return 0;
+ return nullptr;
}
// Read the macro name string.
@@ -520,12 +519,12 @@ IdentifierInfo *Preprocessor::ParsePragmaPushOrPopMacro(Token &Tok) {
if (Tok.isNot(tok::string_literal)) {
Diag(PragmaTok.getLocation(), diag::err_pragma_push_pop_macro_malformed)
<< getSpelling(PragmaTok);
- return 0;
+ return nullptr;
}
if (Tok.hasUDSuffix()) {
Diag(Tok, diag::err_invalid_string_udl);
- return 0;
+ return nullptr;
}
// Remember the macro string.
@@ -536,7 +535,7 @@ IdentifierInfo *Preprocessor::ParsePragmaPushOrPopMacro(Token &Tok) {
if (Tok.isNot(tok::r_paren)) {
Diag(PragmaTok.getLocation(), diag::err_pragma_push_pop_macro_malformed)
<< getSpelling(PragmaTok);
- return 0;
+ return nullptr;
}
assert(StrVal[0] == '"' && StrVal[StrVal.size()-1] == '"' &&
@@ -738,7 +737,7 @@ void Preprocessor::AddPragmaHandler(StringRef Namespace,
// we already have the namespace to insert into.
if (PragmaHandler *Existing = PragmaHandlers->FindHandler(Namespace)) {
InsertNS = Existing->getIfNamespace();
- assert(InsertNS != 0 && "Cannot have a pragma namespace and pragma"
+ assert(InsertNS != nullptr && "Cannot have a pragma namespace and pragma"
" handler with the same name!");
} else {
// Otherwise, this namespace doesn't exist yet, create and insert the
@@ -812,8 +811,8 @@ namespace {
/// PragmaOnceHandler - "\#pragma once" marks the file as atomically included.
struct PragmaOnceHandler : public PragmaHandler {
PragmaOnceHandler() : PragmaHandler("once") {}
- virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
- Token &OnceTok) {
+ void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &OnceTok) override {
PP.CheckEndOfDirective("pragma once");
PP.HandlePragmaOnce(OnceTok);
}
@@ -823,8 +822,8 @@ struct PragmaOnceHandler : public PragmaHandler {
/// rest of the line is not lexed.
struct PragmaMarkHandler : public PragmaHandler {
PragmaMarkHandler() : PragmaHandler("mark") {}
- virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
- Token &MarkTok) {
+ void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &MarkTok) override {
PP.HandlePragmaMark();
}
};
@@ -832,8 +831,8 @@ struct PragmaMarkHandler : public PragmaHandler {
/// PragmaPoisonHandler - "\#pragma poison x" marks x as not usable.
struct PragmaPoisonHandler : public PragmaHandler {
PragmaPoisonHandler() : PragmaHandler("poison") {}
- virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
- Token &PoisonTok) {
+ void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &PoisonTok) override {
PP.HandlePragmaPoison(PoisonTok);
}
};
@@ -842,24 +841,24 @@ struct PragmaPoisonHandler : public PragmaHandler {
/// as a system header, which silences warnings in it.
struct PragmaSystemHeaderHandler : public PragmaHandler {
PragmaSystemHeaderHandler() : PragmaHandler("system_header") {}
- virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
- Token &SHToken) {
+ void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &SHToken) override {
PP.HandlePragmaSystemHeader(SHToken);
PP.CheckEndOfDirective("pragma");
}
};
struct PragmaDependencyHandler : public PragmaHandler {
PragmaDependencyHandler() : PragmaHandler("dependency") {}
- virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
- Token &DepToken) {
+ void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &DepToken) override {
PP.HandlePragmaDependency(DepToken);
}
};
struct PragmaDebugHandler : public PragmaHandler {
PragmaDebugHandler() : PragmaHandler("__debug") {}
- virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
- Token &DepToken) {
+ void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &DepToken) override {
Token Tok;
PP.LexUnexpandedToken(Tok);
if (Tok.isNot(tok::identifier)) {
@@ -926,8 +925,9 @@ struct PragmaDebugHandler : public PragmaHandler {
#ifdef _MSC_VER
#pragma warning(disable : 4717)
#endif
- void DebugOverflowStack() {
- DebugOverflowStack();
+ static void DebugOverflowStack() {
+ void (*volatile Self)() = DebugOverflowStack;
+ Self();
}
#ifdef _MSC_VER
#pragma warning(default : 4717)
@@ -942,8 +942,8 @@ private:
public:
explicit PragmaDiagnosticHandler(const char *NS) :
PragmaHandler("diagnostic"), Namespace(NS) {}
- virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
- Token &DiagToken) {
+ void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &DiagToken) override {
SourceLocation DiagLoc = DiagToken.getLocation();
Token Tok;
PP.LexUnexpandedToken(Tok);
@@ -954,16 +954,7 @@ public:
IdentifierInfo *II = Tok.getIdentifierInfo();
PPCallbacks *Callbacks = PP.getPPCallbacks();
- diag::Mapping Map;
- if (II->isStr("warning"))
- Map = diag::MAP_WARNING;
- else if (II->isStr("error"))
- Map = diag::MAP_ERROR;
- else if (II->isStr("ignored"))
- Map = diag::MAP_IGNORE;
- else if (II->isStr("fatal"))
- Map = diag::MAP_FATAL;
- else if (II->isStr("pop")) {
+ if (II->isStr("pop")) {
if (!PP.getDiagnostics().popMappings(DiagLoc))
PP.Diag(Tok, diag::warn_pragma_diagnostic_cannot_pop);
else if (Callbacks)
@@ -974,7 +965,16 @@ public:
if (Callbacks)
Callbacks->PragmaDiagnosticPush(DiagLoc, Namespace);
return;
- } else {
+ }
+
+ diag::Severity SV = llvm::StringSwitch<diag::Severity>(II->getName())
+ .Case("ignored", diag::Severity::Ignored)
+ .Case("warning", diag::Severity::Warning)
+ .Case("error", diag::Severity::Error)
+ .Case("fatal", diag::Severity::Fatal)
+ .Default(diag::Severity());
+
+ if (SV == diag::Severity()) {
PP.Diag(Tok, diag::warn_pragma_diagnostic_invalid);
return;
}
@@ -993,46 +993,30 @@ public:
}
if (WarningName.size() < 3 || WarningName[0] != '-' ||
- WarningName[1] != 'W') {
+ (WarningName[1] != 'W' && WarningName[1] != 'R')) {
PP.Diag(StringLoc, diag::warn_pragma_diagnostic_invalid_option);
return;
}
- if (PP.getDiagnostics().setDiagnosticGroupMapping(WarningName.substr(2),
- Map, DiagLoc))
+ if (PP.getDiagnostics().setSeverityForGroup(
+ WarningName[1] == 'W' ? diag::Flavor::WarningOrError
+ : diag::Flavor::Remark,
+ WarningName.substr(2), SV, DiagLoc))
PP.Diag(StringLoc, diag::warn_pragma_diagnostic_unknown_warning)
<< WarningName;
else if (Callbacks)
- Callbacks->PragmaDiagnostic(DiagLoc, Namespace, Map, WarningName);
+ Callbacks->PragmaDiagnostic(DiagLoc, Namespace, SV, WarningName);
}
};
-// Returns -1 on failure.
-static int LexSimpleInt(Preprocessor &PP, Token &Tok) {
- assert(Tok.is(tok::numeric_constant));
- SmallString<8> IntegerBuffer;
- bool NumberInvalid = false;
- StringRef Spelling = PP.getSpelling(Tok, IntegerBuffer, &NumberInvalid);
- if (NumberInvalid)
- return -1;
- NumericLiteralParser Literal(Spelling, Tok.getLocation(), PP);
- if (Literal.hadError || !Literal.isIntegerLiteral() || Literal.hasUDSuffix())
- return -1;
- llvm::APInt APVal(32, 0);
- if (Literal.GetIntegerValue(APVal))
- return -1;
- PP.Lex(Tok);
- return int(APVal.getLimitedValue(INT_MAX));
-}
-
/// "\#pragma warning(...)". MSVC's diagnostics do not map cleanly to clang's
/// diagnostics, so we don't really implement this pragma. We parse it and
/// ignore it to avoid -Wunknown-pragma warnings.
struct PragmaWarningHandler : public PragmaHandler {
PragmaWarningHandler() : PragmaHandler("warning") {}
- virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
- Token &Tok) {
+ void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &Tok) override {
// Parse things like:
// warning(push, 1)
// warning(pop)
@@ -1059,8 +1043,10 @@ struct PragmaWarningHandler : public PragmaHandler {
PP.Lex(Tok);
if (Tok.is(tok::comma)) {
PP.Lex(Tok);
- if (Tok.is(tok::numeric_constant))
- Level = LexSimpleInt(PP, Tok);
+ uint64_t Value;
+ if (Tok.is(tok::numeric_constant) &&
+ PP.parseSimpleIntegerLiteral(Tok, Value))
+ Level = int(Value);
if (Level < 0 || Level > 4) {
PP.Diag(Tok, diag::warn_pragma_warning_push_level);
return;
@@ -1104,12 +1090,13 @@ struct PragmaWarningHandler : public PragmaHandler {
SmallVector<int, 4> Ids;
PP.Lex(Tok);
while (Tok.is(tok::numeric_constant)) {
- int Id = LexSimpleInt(PP, Tok);
- if (Id <= 0) {
+ uint64_t Value;
+ if (!PP.parseSimpleIntegerLiteral(Tok, Value) || Value == 0 ||
+ Value > INT_MAX) {
PP.Diag(Tok, diag::warn_pragma_warning_expected_number);
return;
}
- Ids.push_back(Id);
+ Ids.push_back(int(Value));
}
if (Callbacks)
Callbacks->PragmaWarning(DiagLoc, Specifier, Ids);
@@ -1135,8 +1122,8 @@ struct PragmaWarningHandler : public PragmaHandler {
/// PragmaIncludeAliasHandler - "\#pragma include_alias("...")".
struct PragmaIncludeAliasHandler : public PragmaHandler {
PragmaIncludeAliasHandler() : PragmaHandler("include_alias") {}
- virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
- Token &IncludeAliasTok) {
+ void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &IncludeAliasTok) override {
PP.HandlePragmaIncludeAlias(IncludeAliasTok);
}
};
@@ -1177,8 +1164,8 @@ public:
StringRef Namespace = StringRef())
: PragmaHandler(PragmaKind(Kind, true)), Kind(Kind), Namespace(Namespace) {}
- virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
- Token &Tok) {
+ void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &Tok) override {
SourceLocation MessageLoc = Tok.getLocation();
PP.Lex(Tok);
bool ExpectClosingParen = false;
@@ -1230,8 +1217,8 @@ public:
/// macro on the top of the stack.
struct PragmaPushMacroHandler : public PragmaHandler {
PragmaPushMacroHandler() : PragmaHandler("push_macro") {}
- virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
- Token &PushMacroTok) {
+ void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &PushMacroTok) override {
PP.HandlePragmaPushMacro(PushMacroTok);
}
};
@@ -1241,8 +1228,8 @@ struct PragmaPushMacroHandler : public PragmaHandler {
/// macro to the value on the top of the stack.
struct PragmaPopMacroHandler : public PragmaHandler {
PragmaPopMacroHandler() : PragmaHandler("pop_macro") {}
- virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
- Token &PopMacroTok) {
+ void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &PopMacroTok) override {
PP.HandlePragmaPopMacro(PopMacroTok);
}
};
@@ -1252,8 +1239,8 @@ struct PragmaPopMacroHandler : public PragmaHandler {
/// PragmaSTDC_FENV_ACCESSHandler - "\#pragma STDC FENV_ACCESS ...".
struct PragmaSTDC_FENV_ACCESSHandler : public PragmaHandler {
PragmaSTDC_FENV_ACCESSHandler() : PragmaHandler("FENV_ACCESS") {}
- virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
- Token &Tok) {
+ void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &Tok) override {
tok::OnOffSwitch OOS;
if (PP.LexOnOffSwitch(OOS))
return;
@@ -1266,8 +1253,8 @@ struct PragmaSTDC_FENV_ACCESSHandler : public PragmaHandler {
struct PragmaSTDC_CX_LIMITED_RANGEHandler : public PragmaHandler {
PragmaSTDC_CX_LIMITED_RANGEHandler()
: PragmaHandler("CX_LIMITED_RANGE") {}
- virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
- Token &Tok) {
+ void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &Tok) override {
tok::OnOffSwitch OOS;
PP.LexOnOffSwitch(OOS);
}
@@ -1276,8 +1263,8 @@ struct PragmaSTDC_CX_LIMITED_RANGEHandler : public PragmaHandler {
/// PragmaSTDC_UnknownHandler - "\#pragma STDC ...".
struct PragmaSTDC_UnknownHandler : public PragmaHandler {
PragmaSTDC_UnknownHandler() {}
- virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
- Token &UnknownTok) {
+ 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);
}
@@ -1287,8 +1274,8 @@ struct PragmaSTDC_UnknownHandler : public PragmaHandler {
/// \#pragma clang arc_cf_code_audited begin/end
struct PragmaARCCFCodeAuditedHandler : public PragmaHandler {
PragmaARCCFCodeAuditedHandler() : PragmaHandler("arc_cf_code_audited") {}
- virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
- Token &NameTok) {
+ void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &NameTok) override {
SourceLocation Loc = NameTok.getLocation();
bool IsBegin;
@@ -1351,8 +1338,8 @@ struct PragmaARCCFCodeAuditedHandler : public PragmaHandler {
struct PragmaRegionHandler : public PragmaHandler {
PragmaRegionHandler(const char *pragma) : PragmaHandler(pragma) { }
- virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
- Token &NameTok) {
+ void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &NameTok) override {
// #pragma region: endregion matches can be verified
// __pragma(region): no sense, but ignored by msvc
// _Pragma is not valid for MSVC, but there isn't any point
@@ -1401,3 +1388,26 @@ void Preprocessor::RegisterBuiltinPragmas() {
AddPragmaHandler(new PragmaRegionHandler("endregion"));
}
}
+
+/// Ignore all pragmas, useful for modes such as -Eonly which would otherwise
+/// warn about those pragmas being unknown.
+void Preprocessor::IgnorePragmas() {
+ AddPragmaHandler(new EmptyPragmaHandler());
+ // Also ignore all pragmas in all namespaces created
+ // 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 090aeedb7150..41bb581bb0aa 100644
--- a/lib/Lex/PreprocessingRecord.cpp
+++ b/lib/Lex/PreprocessingRecord.cpp
@@ -40,7 +40,7 @@ InclusionDirective::InclusionDirective(PreprocessingRecord &PPRec,
PreprocessingRecord::PreprocessingRecord(SourceManager &SM)
: SourceMgr(SM),
- ExternalSource(0) {
+ ExternalSource(nullptr) {
}
/// \brief Returns a pair of [Begin, End) iterators of preprocessed entities
@@ -334,7 +334,7 @@ PreprocessedEntity *PreprocessingRecord::getPreprocessedEntity(PPEntityID PPID){
}
if (PPID.ID == 0)
- return 0;
+ return nullptr;
unsigned Index = PPID.ID - 1;
assert(Index < PreprocessedEntities.size() &&
"Out-of bounds local preprocessed entity");
@@ -361,7 +361,7 @@ MacroDefinition *PreprocessingRecord::findMacroDefinition(const MacroInfo *MI) {
llvm::DenseMap<const MacroInfo *, MacroDefinition *>::iterator Pos
= MacroDefinitions.find(MI);
if (Pos == MacroDefinitions.end())
- return 0;
+ return nullptr;
return Pos->second;
}
@@ -406,6 +406,10 @@ void PreprocessingRecord::Defined(const Token &MacroNameTok,
MacroNameTok.getLocation());
}
+void PreprocessingRecord::SourceRangeSkipped(SourceRange Range) {
+ SkippedRanges.push_back(Range);
+}
+
void PreprocessingRecord::MacroExpands(const Token &Id,const MacroDirective *MD,
SourceRange Range,
const MacroArgs *Args) {
diff --git a/lib/Lex/Preprocessor.cpp b/lib/Lex/Preprocessor.cpp
index b500efee4e61..4a11803aa954 100644
--- a/lib/Lex/Preprocessor.cpp
+++ b/lib/Lex/Preprocessor.cpp
@@ -26,7 +26,6 @@
//===----------------------------------------------------------------------===//
#include "clang/Lex/Preprocessor.h"
-#include "clang/Lex/MacroArgs.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetInfo.h"
@@ -35,6 +34,7 @@
#include "clang/Lex/HeaderSearch.h"
#include "clang/Lex/LexDiagnostic.h"
#include "clang/Lex/LiteralSupport.h"
+#include "clang/Lex/MacroArgs.h"
#include "clang/Lex/MacroInfo.h"
#include "clang/Lex/ModuleLoader.h"
#include "clang/Lex/Pragma.h"
@@ -42,8 +42,8 @@
#include "clang/Lex/PreprocessorOptions.h"
#include "clang/Lex/ScratchBuffer.h"
#include "llvm/ADT/APFloat.h"
-#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/Capacity.h"
#include "llvm/Support/ConvertUTF.h"
@@ -56,20 +56,21 @@ ExternalPreprocessorSource::~ExternalPreprocessorSource() { }
Preprocessor::Preprocessor(IntrusiveRefCntPtr<PreprocessorOptions> PPOpts,
DiagnosticsEngine &diags, LangOptions &opts,
- const TargetInfo *target, SourceManager &SM,
- HeaderSearch &Headers, ModuleLoader &TheModuleLoader,
+ SourceManager &SM, HeaderSearch &Headers,
+ ModuleLoader &TheModuleLoader,
IdentifierInfoLookup *IILookup, bool OwnsHeaders,
- bool DelayInitialization, bool IncrProcessing)
- : PPOpts(PPOpts), Diags(&diags), LangOpts(opts), Target(target),
+ TranslationUnitKind TUKind)
+ : PPOpts(PPOpts), Diags(&diags), LangOpts(opts), Target(nullptr),
FileMgr(Headers.getFileMgr()), SourceMgr(SM), HeaderInfo(Headers),
- TheModuleLoader(TheModuleLoader), ExternalSource(0),
- Identifiers(opts, IILookup), IncrementalProcessing(IncrProcessing),
- CodeComplete(0), CodeCompletionFile(0), CodeCompletionOffset(0),
- LastTokenWasAt(false), ModuleImportExpectsIdentifier(false),
- CodeCompletionReached(0), SkipMainFilePreamble(0, true), CurPPLexer(0),
- CurDirLookup(0), CurLexerKind(CLK_Lexer), Callbacks(0),
- MacroArgCache(0), Record(0), MIChainHead(0), MICache(0),
- DeserialMIChainHead(0) {
+ TheModuleLoader(TheModuleLoader), ExternalSource(nullptr),
+ Identifiers(opts, IILookup), IncrementalProcessing(false), TUKind(TUKind),
+ CodeComplete(nullptr), CodeCompletionFile(nullptr),
+ CodeCompletionOffset(0), LastTokenWasAt(false),
+ ModuleImportExpectsIdentifier(false), CodeCompletionReached(0),
+ SkipMainFilePreamble(0, true), CurPPLexer(nullptr),
+ CurDirLookup(nullptr), CurLexerKind(CLK_Lexer), CurSubmodule(nullptr),
+ Callbacks(nullptr), MacroArgCache(nullptr), Record(nullptr),
+ MIChainHead(nullptr), MICache(nullptr), DeserialMIChainHead(nullptr) {
OwnsHeaderSearch = OwnsHeaders;
ScratchBuf = new ScratchBuffer(SourceMgr);
@@ -127,39 +128,35 @@ Preprocessor::Preprocessor(IntrusiveRefCntPtr<PreprocessorOptions> PPOpts,
Ident___abnormal_termination = getIdentifierInfo("__abnormal_termination");
Ident_AbnormalTermination = getIdentifierInfo("AbnormalTermination");
} else {
- Ident__exception_info = Ident__exception_code = Ident__abnormal_termination = 0;
- Ident___exception_info = Ident___exception_code = Ident___abnormal_termination = 0;
- Ident_GetExceptionInfo = Ident_GetExceptionCode = Ident_AbnormalTermination = 0;
- }
-
- if (!DelayInitialization) {
- assert(Target && "Must provide target information for PP initialization");
- Initialize(*Target);
+ Ident__exception_info = Ident__exception_code = nullptr;
+ Ident__abnormal_termination = Ident___exception_info = nullptr;
+ Ident___exception_code = Ident___abnormal_termination = nullptr;
+ Ident_GetExceptionInfo = Ident_GetExceptionCode = nullptr;
+ Ident_AbnormalTermination = nullptr;
}
}
Preprocessor::~Preprocessor() {
assert(BacktrackPositions.empty() && "EnableBacktrack/Backtrack imbalance!");
- while (!IncludeMacroStack.empty()) {
- delete IncludeMacroStack.back().TheLexer;
- delete IncludeMacroStack.back().TheTokenLexer;
- IncludeMacroStack.pop_back();
- }
+ IncludeMacroStack.clear();
// Free any macro definitions.
for (MacroInfoChain *I = MIChainHead ; I ; I = I->Next)
I->MI.Destroy();
// Free any cached macro expanders.
+ // This populates MacroArgCache, so all TokenLexers need to be destroyed
+ // before the code below that frees up the MacroArgCache list.
for (unsigned i = 0, e = NumCachedTokenLexers; i != e; ++i)
delete TokenLexerCache[i];
+ CurTokenLexer.reset();
for (DeserializedMacroInfoChain *I = DeserialMIChainHead ; I ; I = I->Next)
I->MI.Destroy();
// Free any cached MacroArgs.
- for (MacroArgs *ArgList = MacroArgCache; ArgList; )
+ for (MacroArgs *ArgList = MacroArgCache; ArgList;)
ArgList = ArgList->deallocate();
// Release pragma information.
@@ -444,8 +441,8 @@ void Preprocessor::CreateString(StringRef Str, Token &Tok,
Module *Preprocessor::getCurrentModule() {
if (getLangOpts().CurrentModule.empty())
- return 0;
-
+ return nullptr;
+
return getHeaderSearchInfo().lookupModule(getLangOpts().CurrentModule);
}
@@ -467,8 +464,8 @@ void Preprocessor::EnterMainSourceFile() {
// a main file.
if (!SourceMgr.isLoadedFileID(MainFileID)) {
// Enter the main file source buffer.
- EnterSourceFile(MainFileID, 0, SourceLocation());
-
+ EnterSourceFile(MainFileID, nullptr, SourceLocation());
+
// If we've been asked to skip bytes in the main file (e.g., as part of a
// precompiled preamble), do so now.
if (SkipMainFilePreamble.first > 0)
@@ -485,12 +482,12 @@ void Preprocessor::EnterMainSourceFile() {
llvm::MemoryBuffer *SB =
llvm::MemoryBuffer::getMemBufferCopy(Predefines, "<built-in>");
assert(SB && "Cannot create predefined source buffer");
- FileID FID = SourceMgr.createFileIDForMemBuffer(SB);
+ FileID FID = SourceMgr.createFileID(SB);
assert(!FID.isInvalid() && "Could not create FileID for predefines?");
setPredefinesFileID(FID);
// Start parsing the predefines.
- EnterSourceFile(FID, 0, SourceLocation());
+ EnterSourceFile(FID, nullptr, SourceLocation());
}
void Preprocessor::EndSourceFile() {
@@ -503,60 +500,17 @@ void Preprocessor::EndSourceFile() {
// Lexer Event Handling.
//===----------------------------------------------------------------------===//
-static void appendCodePoint(unsigned Codepoint,
- llvm::SmallVectorImpl<char> &Str) {
- char ResultBuf[4];
- char *ResultPtr = ResultBuf;
- bool Res = llvm::ConvertCodePointToUTF8(Codepoint, ResultPtr);
- (void)Res;
- assert(Res && "Unexpected conversion failure");
- Str.append(ResultBuf, ResultPtr);
-}
-
-static void expandUCNs(SmallVectorImpl<char> &Buf, StringRef Input) {
- for (StringRef::iterator I = Input.begin(), E = Input.end(); I != E; ++I) {
- if (*I != '\\') {
- Buf.push_back(*I);
- continue;
- }
-
- ++I;
- assert(*I == 'u' || *I == 'U');
-
- unsigned NumHexDigits;
- if (*I == 'u')
- NumHexDigits = 4;
- else
- NumHexDigits = 8;
-
- assert(I + NumHexDigits <= E);
-
- uint32_t CodePoint = 0;
- for (++I; NumHexDigits != 0; ++I, --NumHexDigits) {
- unsigned Value = llvm::hexDigitValue(*I);
- assert(Value != -1U);
-
- CodePoint <<= 4;
- CodePoint += Value;
- }
-
- appendCodePoint(CodePoint, Buf);
- --I;
- }
-}
-
/// LookUpIdentifierInfo - Given a tok::raw_identifier token, look up the
/// identifier information for the token and install it into the token,
/// updating the token kind accordingly.
IdentifierInfo *Preprocessor::LookUpIdentifierInfo(Token &Identifier) const {
- assert(Identifier.getRawIdentifierData() != 0 && "No raw identifier data!");
+ assert(!Identifier.getRawIdentifier().empty() && "No raw identifier data!");
// Look up this token, see if it is a macro, or if it is a language keyword.
IdentifierInfo *II;
if (!Identifier.needsCleaning() && !Identifier.hasUCN()) {
// No cleaning needed, just use the characters from the lexed buffer.
- II = getIdentifierInfo(StringRef(Identifier.getRawIdentifierData(),
- Identifier.getLength()));
+ II = getIdentifierInfo(Identifier.getRawIdentifier());
} else {
// Cleaning needed, alloca a buffer, clean into it, then use the buffer.
SmallString<64> IdentifierBuffer;
@@ -669,7 +623,7 @@ bool Preprocessor::HandleIdentifier(Token &Identifier) {
// name of a macro.
// FIXME: This warning is disabled in cases where it shouldn't be, like
// "#define constexpr constexpr", "int constexpr;"
- if (II.isCXX11CompatKeyword() & !DisableMacroExpansion) {
+ if (II.isCXX11CompatKeyword() && !DisableMacroExpansion) {
Diag(Identifier, diag::warn_cxx11_keyword) << II.getName();
// Don't diagnose this keyword again in this translation unit.
II.setIsCXX11CompatKeyword(false);
@@ -679,7 +633,7 @@ bool Preprocessor::HandleIdentifier(Token &Identifier) {
// then we act as if it is the actual operator and not the textual
// representation of it.
if (II.isCPlusPlusOperatorKeyword())
- Identifier.setIdentifierInfo(0);
+ Identifier.setIdentifierInfo(nullptr);
// If this is an extension token, diagnose its use.
// We avoid diagnosing tokens that originate from macro definitions.
@@ -803,7 +757,7 @@ bool Preprocessor::FinishLexStringLiteral(Token &Result, std::string &String,
} while (Result.is(tok::string_literal));
// Concatenate and parse the strings.
- StringLiteralParser Literal(&StrToks[0], StrToks.size(), *this);
+ StringLiteralParser Literal(StrToks, *this);
assert(Literal.isAscii() && "Didn't allow wide strings in");
if (Literal.hadError)
@@ -819,6 +773,24 @@ bool Preprocessor::FinishLexStringLiteral(Token &Result, std::string &String,
return true;
}
+bool Preprocessor::parseSimpleIntegerLiteral(Token &Tok, uint64_t &Value) {
+ assert(Tok.is(tok::numeric_constant));
+ SmallString<8> IntegerBuffer;
+ bool NumberInvalid = false;
+ StringRef Spelling = getSpelling(Tok, IntegerBuffer, &NumberInvalid);
+ if (NumberInvalid)
+ return false;
+ NumericLiteralParser Literal(Spelling, Tok.getLocation(), *this);
+ if (Literal.hadError || !Literal.isIntegerLiteral() || Literal.hasUDSuffix())
+ return false;
+ llvm::APInt APVal(64, 0);
+ if (Literal.GetIntegerValue(APVal))
+ return false;
+ Lex(Tok);
+ Value = APVal.getLimitedValue();
+ return true;
+}
+
void Preprocessor::addCommentHandler(CommentHandler *Handler) {
assert(Handler && "NULL comment handler");
assert(std::find(CommentHandlers.begin(), CommentHandlers.end(), Handler) ==
diff --git a/lib/Lex/ScratchBuffer.cpp b/lib/Lex/ScratchBuffer.cpp
index 3d363fa4b472..d7104b178860 100644
--- a/lib/Lex/ScratchBuffer.cpp
+++ b/lib/Lex/ScratchBuffer.cpp
@@ -21,7 +21,8 @@ using namespace clang;
//than a page, almost certainly enough for anything. :)
static const unsigned ScratchBufSize = 4060;
-ScratchBuffer::ScratchBuffer(SourceManager &SM) : SourceMgr(SM), CurBuffer(0) {
+ScratchBuffer::ScratchBuffer(SourceManager &SM)
+ : SourceMgr(SM), CurBuffer(nullptr) {
// Set BytesUsed so that the first call to getToken will require an alloc.
BytesUsed = ScratchBufSize;
}
@@ -65,7 +66,7 @@ void ScratchBuffer::AllocScratchBuffer(unsigned RequestLen) {
llvm::MemoryBuffer *Buf =
llvm::MemoryBuffer::getNewMemBuffer(RequestLen, "<scratch space>");
- FileID FID = SourceMgr.createFileIDForMemBuffer(Buf);
+ FileID FID = SourceMgr.createFileID(Buf);
BufferStartLoc = SourceMgr.getLocForStartOfFile(FID);
CurBuffer = const_cast<char*>(Buf->getBufferStart());
BytesUsed = 1;
diff --git a/lib/Lex/TokenLexer.cpp b/lib/Lex/TokenLexer.cpp
index 0213afcee921..9d03e8d30b8b 100644
--- a/lib/Lex/TokenLexer.cpp
+++ b/lib/Lex/TokenLexer.cpp
@@ -12,9 +12,9 @@
//===----------------------------------------------------------------------===//
#include "clang/Lex/TokenLexer.h"
-#include "clang/Lex/MacroArgs.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Lex/LexDiagnostic.h"
+#include "clang/Lex/MacroArgs.h"
#include "clang/Lex/MacroInfo.h"
#include "clang/Lex/Preprocessor.h"
#include "llvm/ADT/SmallString.h"
@@ -37,6 +37,7 @@ void TokenLexer::Init(Token &Tok, SourceLocation ELEnd, MacroInfo *MI,
ExpandLocEnd = ELEnd;
AtStartOfLine = Tok.isAtStartOfLine();
HasLeadingSpace = Tok.hasLeadingSpace();
+ NextTokGetsSpace = false;
Tokens = &*Macro->tokens_begin();
OwnsTokens = false;
DisableMacroExpansion = false;
@@ -85,8 +86,8 @@ void TokenLexer::Init(const Token *TokArray, unsigned NumToks,
// associated with it.
destroy();
- Macro = 0;
- ActualArgs = 0;
+ Macro = nullptr;
+ ActualArgs = nullptr;
Tokens = TokArray;
OwnsTokens = ownsTokens;
DisableMacroExpansion = disableMacroExpansion;
@@ -95,6 +96,7 @@ void TokenLexer::Init(const Token *TokArray, unsigned NumToks,
ExpandLocStart = ExpandLocEnd = SourceLocation();
AtStartOfLine = false;
HasLeadingSpace = false;
+ NextTokGetsSpace = false;
MacroExpansionStart = SourceLocation();
// Set HasLeadingSpace/AtStartOfLine so that the first token will be
@@ -111,7 +113,7 @@ void TokenLexer::destroy() {
// the expanded tokens.
if (OwnsTokens) {
delete [] Tokens;
- Tokens = 0;
+ Tokens = nullptr;
OwnsTokens = false;
}
@@ -119,13 +121,9 @@ void TokenLexer::destroy() {
if (ActualArgs) ActualArgs->destroy(PP);
}
-/// Remove comma ahead of __VA_ARGS__, if present, according to compiler dialect
-/// settings. Returns true if the comma is removed.
-static bool MaybeRemoveCommaBeforeVaArgs(SmallVectorImpl<Token> &ResultToks,
- bool &NextTokGetsSpace,
- bool HasPasteOperator,
- MacroInfo *Macro, unsigned MacroArgNo,
- Preprocessor &PP) {
+bool TokenLexer::MaybeRemoveCommaBeforeVaArgs(
+ SmallVectorImpl<Token> &ResultToks, bool HasPasteOperator, MacroInfo *Macro,
+ unsigned MacroArgNo, Preprocessor &PP) {
// Is the macro argument __VA_ARGS__?
if (!Macro->isVariadic() || MacroArgNo != Macro->getNumArgs()-1)
return false;
@@ -133,7 +131,7 @@ static bool MaybeRemoveCommaBeforeVaArgs(SmallVectorImpl<Token> &ResultToks,
// In Microsoft-compatibility mode, a comma is removed in the expansion
// of " ... , __VA_ARGS__ " if __VA_ARGS__ is empty. This extension is
// not supported by gcc.
- if (!HasPasteOperator && !PP.getLangOpts().MicrosoftMode)
+ if (!HasPasteOperator && !PP.getLangOpts().MSVCCompat)
return false;
// GCC removes the comma in the expansion of " ... , ## __VA_ARGS__ " if
@@ -179,16 +177,14 @@ void TokenLexer::ExpandFunctionArguments() {
// we install the newly expanded sequence as the new 'Tokens' list.
bool MadeChange = false;
- // NextTokGetsSpace - When this is true, the next token appended to the
- // output list will get a leading space, regardless of whether it had one to
- // begin with or not. This is used for placemarker support.
- bool NextTokGetsSpace = false;
-
for (unsigned i = 0, e = NumTokens; i != e; ++i) {
// If we found the stringify operator, get the argument stringified. The
// preprocessor already verified that the following token is a macro name
// when the #define was parsed.
const Token &CurTok = Tokens[i];
+ if (i != 0 && !Tokens[i-1].is(tok::hashhash) && CurTok.hasLeadingSpace())
+ NextTokGetsSpace = true;
+
if (CurTok.is(tok::hash) || CurTok.is(tok::hashat)) {
int ArgNo = Macro->getArgumentNum(Tokens[i+1].getIdentifierInfo());
assert(ArgNo != -1 && "Token following # is not an argument?");
@@ -213,7 +209,7 @@ void TokenLexer::ExpandFunctionArguments() {
// The stringified/charified string leading space flag gets set to match
// the #/#@ operator.
- if (CurTok.hasLeadingSpace() || NextTokGetsSpace)
+ if (NextTokGetsSpace)
Res.setFlag(Token::LeadingSpace);
ResultToks.push_back(Res);
@@ -223,6 +219,13 @@ void TokenLexer::ExpandFunctionArguments() {
continue;
}
+ // Find out if there is a paste (##) operator before or after the token.
+ bool NonEmptyPasteBefore =
+ !ResultToks.empty() && ResultToks.back().is(tok::hashhash);
+ bool PasteBefore = i != 0 && Tokens[i-1].is(tok::hashhash);
+ bool PasteAfter = i+1 != e && Tokens[i+1].is(tok::hashhash);
+ assert(!NonEmptyPasteBefore || PasteBefore);
+
// Otherwise, if this is not an argument token, just add the token to the
// output buffer.
IdentifierInfo *II = CurTok.getIdentifierInfo();
@@ -234,7 +237,9 @@ void TokenLexer::ExpandFunctionArguments() {
if (NextTokGetsSpace) {
ResultToks.back().setFlag(Token::LeadingSpace);
NextTokGetsSpace = false;
- }
+ } else if (PasteBefore && !NonEmptyPasteBefore)
+ ResultToks.back().clearFlag(Token::LeadingSpace);
+
continue;
}
@@ -242,18 +247,12 @@ void TokenLexer::ExpandFunctionArguments() {
// input.
MadeChange = true;
- // Otherwise, this is a use of the argument. Find out if there is a paste
- // (##) operator before or after the argument.
- bool NonEmptyPasteBefore =
- !ResultToks.empty() && ResultToks.back().is(tok::hashhash);
- bool PasteBefore = i != 0 && Tokens[i-1].is(tok::hashhash);
- bool PasteAfter = i+1 != e && Tokens[i+1].is(tok::hashhash);
- assert(!NonEmptyPasteBefore || PasteBefore);
+ // Otherwise, this is a use of the argument.
// In Microsoft mode, remove the comma before __VA_ARGS__ to ensure there
// are no trailing commas if __VA_ARGS__ is empty.
if (!PasteBefore && ActualArgs->isVarargsElidedUse() &&
- MaybeRemoveCommaBeforeVaArgs(ResultToks, NextTokGetsSpace,
+ MaybeRemoveCommaBeforeVaArgs(ResultToks,
/*HasPasteOperator=*/false,
Macro, ArgNo, PP))
continue;
@@ -282,7 +281,7 @@ void TokenLexer::ExpandFunctionArguments() {
// behavior by not considering single commas from nested macro
// expansions as argument separators. Set a flag on the token so we can
// test for this later when the macro expansion is processed.
- if (PP.getLangOpts().MicrosoftMode && NumToks == 1 &&
+ if (PP.getLangOpts().MSVCCompat && NumToks == 1 &&
ResultToks.back().is(tok::comma))
ResultToks.back().setFlag(Token::IgnoredComma);
@@ -304,13 +303,8 @@ void TokenLexer::ExpandFunctionArguments() {
// before the first token should match the whitespace of the arg
// identifier.
ResultToks[FirstResult].setFlagValue(Token::LeadingSpace,
- CurTok.hasLeadingSpace() ||
NextTokGetsSpace);
NextTokGetsSpace = false;
- } else {
- // If this is an empty argument, and if there was whitespace before the
- // formal token, make sure the next token gets whitespace before it.
- NextTokGetsSpace = CurTok.hasLeadingSpace();
}
continue;
}
@@ -358,8 +352,7 @@ void TokenLexer::ExpandFunctionArguments() {
// assembler-with-cpp mode, invalid pastes are allowed through: in this
// case, we do not want the extra whitespace to be added. For example,
// we want ". ## foo" -> ".foo" not ". foo".
- if ((CurTok.hasLeadingSpace() || NextTokGetsSpace) &&
- !NonEmptyPasteBefore)
+ if (NextTokGetsSpace)
ResultToks[ResultToks.size()-NumToks].setFlag(Token::LeadingSpace);
NextTokGetsSpace = false;
@@ -370,11 +363,9 @@ void TokenLexer::ExpandFunctionArguments() {
// 6.10.3.3p2,3) calls for a bunch of placemarker stuff to occur. We
// implement this by eating ## operators when a LHS or RHS expands to
// empty.
- NextTokGetsSpace |= CurTok.hasLeadingSpace();
if (PasteAfter) {
// Discard the argument token and skip (don't copy to the expansion
// buffer) the paste operator after it.
- NextTokGetsSpace |= Tokens[i+1].hasLeadingSpace();
++i;
continue;
}
@@ -385,7 +376,7 @@ void TokenLexer::ExpandFunctionArguments() {
assert(PasteBefore);
if (NonEmptyPasteBefore) {
assert(ResultToks.back().is(tok::hashhash));
- NextTokGetsSpace |= ResultToks.pop_back_val().hasLeadingSpace();
+ ResultToks.pop_back();
}
// If this is the __VA_ARGS__ token, and if the argument wasn't provided,
@@ -393,7 +384,7 @@ void TokenLexer::ExpandFunctionArguments() {
// the ## was a comma, remove the comma. This is a GCC extension which is
// disabled when using -std=c99.
if (ActualArgs->isVarargsElidedUse())
- MaybeRemoveCommaBeforeVaArgs(ResultToks, NextTokGetsSpace,
+ MaybeRemoveCommaBeforeVaArgs(ResultToks,
/*HasPasteOperator=*/true,
Macro, ArgNo, PP);
@@ -425,7 +416,7 @@ bool TokenLexer::Lex(Token &Tok) {
Tok.startToken();
Tok.setFlagValue(Token::StartOfLine , AtStartOfLine);
- Tok.setFlagValue(Token::LeadingSpace, HasLeadingSpace);
+ Tok.setFlagValue(Token::LeadingSpace, HasLeadingSpace || NextTokGetsSpace);
if (CurToken == 0)
Tok.setFlag(Token::LeadingEmptyMacro);
return PP.HandleEndOfTokenLexer(Tok);
@@ -479,12 +470,17 @@ bool TokenLexer::Lex(Token &Tok) {
if (isFirstToken) {
Tok.setFlagValue(Token::StartOfLine , AtStartOfLine);
Tok.setFlagValue(Token::LeadingSpace, HasLeadingSpace);
- AtStartOfLine = false;
- HasLeadingSpace = false;
+ } else {
+ // If this is not the first token, we may still need to pass through
+ // leading whitespace if we've expanded a macro.
+ if (AtStartOfLine) Tok.setFlag(Token::StartOfLine);
+ if (HasLeadingSpace) Tok.setFlag(Token::LeadingSpace);
}
+ AtStartOfLine = false;
+ HasLeadingSpace = false;
// Handle recursive expansion!
- if (!Tok.isAnnotation() && Tok.getIdentifierInfo() != 0) {
+ if (!Tok.isAnnotation() && Tok.getIdentifierInfo() != nullptr) {
// Change the kind of this identifier to the appropriate token kind, e.g.
// turning "for" into a keyword.
IdentifierInfo *II = Tok.getIdentifierInfo();
@@ -511,7 +507,7 @@ bool TokenLexer::Lex(Token &Tok) {
/// If this returns true, the caller should immediately return the token.
bool TokenLexer::PasteTokens(Token &Tok) {
SmallString<128> Buffer;
- const char *ResultTokStrPtr = 0;
+ const char *ResultTokStrPtr = nullptr;
SourceLocation StartLoc = Tok.getLocation();
SourceLocation PasteOpLoc;
do {
@@ -620,12 +616,11 @@ bool TokenLexer::PasteTokens(Token &Tok) {
SourceLocation Loc =
SM.createExpansionLoc(PasteOpLoc, ExpandLocStart, ExpandLocEnd, 2);
// If we're in microsoft extensions mode, downgrade this from a hard
- // error to a warning that defaults to an error. This allows
+ // error to an extension that defaults to an error. This allows
// disabling it.
- PP.Diag(Loc,
- PP.getLangOpts().MicrosoftExt ? diag::err_pp_bad_paste_ms
- : diag::err_pp_bad_paste)
- << Buffer.str();
+ PP.Diag(Loc, PP.getLangOpts().MicrosoftExt ? diag::ext_pp_bad_paste_ms
+ : diag::err_pp_bad_paste)
+ << Buffer.str();
}
// An error has occurred so exit loop.
diff --git a/lib/Lex/UnicodeCharSets.h b/lib/Lex/UnicodeCharSets.h
index 01ae7e839dfd..12b24564bfd3 100644
--- a/lib/Lex/UnicodeCharSets.h
+++ b/lib/Lex/UnicodeCharSets.h
@@ -298,7 +298,7 @@ static const llvm::sys::UnicodeCharRange C99AllowedIDCharRanges[] = {
// Malayam
{ 0x0D02, 0x0D03 }, { 0x0D05, 0x0D0C }, { 0x0D0E, 0x0D10 },
{ 0x0D12, 0x0D28 }, { 0x0D2A, 0x0D39 }, { 0x0D3E, 0x0D43 },
- { 0x0D46, 0x0D48 }, { 0x0D4A, 0x0D4D }, { 0x0D60, 0x0D60 },
+ { 0x0D46, 0x0D48 }, { 0x0D4A, 0x0D4D }, { 0x0D60, 0x0D61 },
// Digits (11)
{ 0x0D66, 0x0D6F },