diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Lex')
20 files changed, 1875 insertions, 1318 deletions
diff --git a/contrib/llvm/tools/clang/lib/Lex/HeaderMap.cpp b/contrib/llvm/tools/clang/lib/Lex/HeaderMap.cpp index 478462c..f6c658e 100644 --- a/contrib/llvm/tools/clang/lib/Lex/HeaderMap.cpp +++ b/contrib/llvm/tools/clang/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/contrib/llvm/tools/clang/lib/Lex/HeaderSearch.cpp b/contrib/llvm/tools/clang/lib/Lex/HeaderSearch.cpp index 9e43dda..c12d731 100644 --- a/contrib/llvm/tools/clang/lib/Lex/HeaderSearch.cpp +++ b/contrib/llvm/tools/clang/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/contrib/llvm/tools/clang/lib/Lex/Lexer.cpp b/contrib/llvm/tools/clang/lib/Lex/Lexer.cpp index c071455..6f6b50b 100644 --- a/contrib/llvm/tools/clang/lib/Lex/Lexer.cpp +++ b/contrib/llvm/tools/clang/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/contrib/llvm/tools/clang/lib/Lex/LiteralSupport.cpp b/contrib/llvm/tools/clang/lib/Lex/LiteralSupport.cpp index 17c6bb3..6417d0f 100644 --- a/contrib/llvm/tools/clang/lib/Lex/LiteralSupport.cpp +++ b/contrib/llvm/tools/clang/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/contrib/llvm/tools/clang/lib/Lex/MacroArgs.cpp b/contrib/llvm/tools/clang/lib/Lex/MacroArgs.cpp index d2dc04b..a746fb7 100644 --- a/contrib/llvm/tools/clang/lib/Lex/MacroArgs.cpp +++ b/contrib/llvm/tools/clang/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/contrib/llvm/tools/clang/lib/Lex/MacroInfo.cpp b/contrib/llvm/tools/clang/lib/Lex/MacroInfo.cpp index b61ff71..5416886 100644 --- a/contrib/llvm/tools/clang/lib/Lex/MacroInfo.cpp +++ b/contrib/llvm/tools/clang/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/contrib/llvm/tools/clang/lib/Lex/ModuleMap.cpp b/contrib/llvm/tools/clang/lib/Lex/ModuleMap.cpp index f4dfa12..8fae9c9 100644 --- a/contrib/llvm/tools/clang/lib/Lex/ModuleMap.cpp +++ b/contrib/llvm/tools/clang/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 ⤅ + + /// \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(<oken, 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/contrib/llvm/tools/clang/lib/Lex/PPCaching.cpp b/contrib/llvm/tools/clang/lib/Lex/PPCaching.cpp index 6f4c189..bd48ae64 100644 --- a/contrib/llvm/tools/clang/lib/Lex/PPCaching.cpp +++ b/contrib/llvm/tools/clang/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/contrib/llvm/tools/clang/lib/Lex/PPConditionalDirectiveRecord.cpp b/contrib/llvm/tools/clang/lib/Lex/PPConditionalDirectiveRecord.cpp index 16dc1d8..99b87a0 100644 --- a/contrib/llvm/tools/clang/lib/Lex/PPConditionalDirectiveRecord.cpp +++ b/contrib/llvm/tools/clang/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/contrib/llvm/tools/clang/lib/Lex/PPDirectives.cpp b/contrib/llvm/tools/clang/lib/Lex/PPDirectives.cpp index 86c508f..1741c30 100644 --- a/contrib/llvm/tools/clang/lib/Lex/PPDirectives.cpp +++ b/contrib/llvm/tools/clang/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/contrib/llvm/tools/clang/lib/Lex/PPExpressions.cpp b/contrib/llvm/tools/clang/lib/Lex/PPExpressions.cpp index 87c0a6a..2260bf9 100644 --- a/contrib/llvm/tools/clang/lib/Lex/PPExpressions.cpp +++ b/contrib/llvm/tools/clang/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/contrib/llvm/tools/clang/lib/Lex/PPLexerChange.cpp b/contrib/llvm/tools/clang/lib/Lex/PPLexerChange.cpp index 1f970a4..22ee971 100644 --- a/contrib/llvm/tools/clang/lib/Lex/PPLexerChange.cpp +++ b/contrib/llvm/tools/clang/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/contrib/llvm/tools/clang/lib/Lex/PPMacroExpansion.cpp b/contrib/llvm/tools/clang/lib/Lex/PPMacroExpansion.cpp index f20633f..2d7c6d4 100644 --- a/contrib/llvm/tools/clang/lib/Lex/PPMacroExpansion.cpp +++ b/contrib/llvm/tools/clang/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/contrib/llvm/tools/clang/lib/Lex/PTHLexer.cpp b/contrib/llvm/tools/clang/lib/Lex/PTHLexer.cpp index e2629a3..fce31c4 100644 --- a/contrib/llvm/tools/clang/lib/Lex/PTHLexer.cpp +++ b/contrib/llvm/tools/clang/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/contrib/llvm/tools/clang/lib/Lex/Pragma.cpp b/contrib/llvm/tools/clang/lib/Lex/Pragma.cpp index e4059ee..cf76bdb 100644 --- a/contrib/llvm/tools/clang/lib/Lex/Pragma.cpp +++ b/contrib/llvm/tools/clang/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/contrib/llvm/tools/clang/lib/Lex/PreprocessingRecord.cpp b/contrib/llvm/tools/clang/lib/Lex/PreprocessingRecord.cpp index 090aeed..41bb581 100644 --- a/contrib/llvm/tools/clang/lib/Lex/PreprocessingRecord.cpp +++ b/contrib/llvm/tools/clang/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/contrib/llvm/tools/clang/lib/Lex/Preprocessor.cpp b/contrib/llvm/tools/clang/lib/Lex/Preprocessor.cpp index b500efe..4a11803 100644 --- a/contrib/llvm/tools/clang/lib/Lex/Preprocessor.cpp +++ b/contrib/llvm/tools/clang/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/contrib/llvm/tools/clang/lib/Lex/ScratchBuffer.cpp b/contrib/llvm/tools/clang/lib/Lex/ScratchBuffer.cpp index 3d363fa..d7104b1 100644 --- a/contrib/llvm/tools/clang/lib/Lex/ScratchBuffer.cpp +++ b/contrib/llvm/tools/clang/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/contrib/llvm/tools/clang/lib/Lex/TokenLexer.cpp b/contrib/llvm/tools/clang/lib/Lex/TokenLexer.cpp index 0213afc..9d03e8d 100644 --- a/contrib/llvm/tools/clang/lib/Lex/TokenLexer.cpp +++ b/contrib/llvm/tools/clang/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/contrib/llvm/tools/clang/lib/Lex/UnicodeCharSets.h b/contrib/llvm/tools/clang/lib/Lex/UnicodeCharSets.h index 01ae7e8..12b2456 100644 --- a/contrib/llvm/tools/clang/lib/Lex/UnicodeCharSets.h +++ b/contrib/llvm/tools/clang/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 }, |