diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2016-07-23 20:44:14 +0000 |
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2016-07-23 20:44:14 +0000 |
| commit | 2b6b257f4e5503a7a2675bdb8735693db769f75c (patch) | |
| tree | e85e046ae7003fe3bcc8b5454cd0fa3f7407b470 /lib/Lex | |
| parent | b4348ed0b7e90c0831b925fbee00b5f179a99796 (diff) | |
Notes
Diffstat (limited to 'lib/Lex')
| -rw-r--r-- | lib/Lex/HeaderMap.cpp | 163 | ||||
| -rw-r--r-- | lib/Lex/HeaderSearch.cpp | 99 | ||||
| -rw-r--r-- | lib/Lex/Lexer.cpp | 43 | ||||
| -rw-r--r-- | lib/Lex/LiteralSupport.cpp | 157 | ||||
| -rw-r--r-- | lib/Lex/MacroInfo.cpp | 4 | ||||
| -rw-r--r-- | lib/Lex/Makefile | 24 | ||||
| -rw-r--r-- | lib/Lex/ModuleMap.cpp | 101 | ||||
| -rw-r--r-- | lib/Lex/PPCaching.cpp | 26 | ||||
| -rw-r--r-- | lib/Lex/PPDirectives.cpp | 375 | ||||
| -rw-r--r-- | lib/Lex/PPExpressions.cpp | 85 | ||||
| -rw-r--r-- | lib/Lex/PPLexerChange.cpp | 76 | ||||
| -rw-r--r-- | lib/Lex/PPMacroExpansion.cpp | 414 | ||||
| -rw-r--r-- | lib/Lex/Pragma.cpp | 36 | ||||
| -rw-r--r-- | lib/Lex/Preprocessor.cpp | 7 | ||||
| -rw-r--r-- | lib/Lex/TokenLexer.cpp | 30 |
15 files changed, 1077 insertions, 563 deletions
diff --git a/lib/Lex/HeaderMap.cpp b/lib/Lex/HeaderMap.cpp index 09d53846d4cf..4cace5b00245 100644 --- a/lib/Lex/HeaderMap.cpp +++ b/lib/Lex/HeaderMap.cpp @@ -12,48 +12,20 @@ //===----------------------------------------------------------------------===// #include "clang/Lex/HeaderMap.h" +#include "clang/Lex/HeaderMapTypes.h" #include "clang/Basic/CharInfo.h" #include "clang/Basic/FileManager.h" #include "llvm/ADT/SmallString.h" +#include "llvm/Support/Compiler.h" #include "llvm/Support/DataTypes.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/MemoryBuffer.h" -#include <cstdio> +#include "llvm/Support/SwapByteOrder.h" +#include "llvm/Support/Debug.h" +#include <cstring> #include <memory> using namespace clang; -//===----------------------------------------------------------------------===// -// Data Structures and Manifest Constants -//===----------------------------------------------------------------------===// - -enum { - HMAP_HeaderMagicNumber = ('h' << 24) | ('m' << 16) | ('a' << 8) | 'p', - HMAP_HeaderVersion = 1, - - HMAP_EmptyBucketKey = 0 -}; - -namespace clang { -struct HMapBucket { - uint32_t Key; // Offset (into strings) of key. - - uint32_t Prefix; // Offset (into strings) of value prefix. - uint32_t Suffix; // Offset (into strings) of value suffix. -}; - -struct HMapHeader { - uint32_t Magic; // Magic word, also indicates byte order. - uint16_t Version; // Version number -- currently 1. - uint16_t Reserved; // Reserved for future use - zero for now. - uint32_t StringsOffset; // Offset to start of string pool. - uint32_t NumEntries; // Number of entries in the string table. - uint32_t NumBuckets; // Number of buckets (always a power of 2). - uint32_t MaxValueLength; // Length of longest result path (excluding nul). - // An array of 'NumBuckets' HMapBucket objects follows this header. - // Strings follow the buckets, at StringsOffset. -}; -} // end namespace clang. - /// HashHMapKey - This is the 'well known' hash function required by the file /// format, used to look up keys in the hash table. The hash table uses simple /// linear probing based on this function. @@ -82,15 +54,25 @@ const HeaderMap *HeaderMap::Create(const FileEntry *FE, FileManager &FM) { if (FileSize <= sizeof(HMapHeader)) return nullptr; auto FileBuffer = FM.getBufferForFile(FE); - if (!FileBuffer) return nullptr; // Unreadable file? - const char *FileStart = (*FileBuffer)->getBufferStart(); + if (!FileBuffer || !*FileBuffer) + return nullptr; + bool NeedsByteSwap; + if (!checkHeader(**FileBuffer, NeedsByteSwap)) + return nullptr; + return new HeaderMap(std::move(*FileBuffer), NeedsByteSwap); +} + +bool HeaderMapImpl::checkHeader(const llvm::MemoryBuffer &File, + bool &NeedsByteSwap) { + if (File.getBufferSize() <= sizeof(HMapHeader)) + return false; + const char *FileStart = File.getBufferStart(); // We know the file is at least as big as the header, check it now. const HMapHeader *Header = reinterpret_cast<const HMapHeader*>(FileStart); // Sniff it to see if it's a headermap by checking the magic number and // version. - bool NeedsByteSwap; if (Header->Magic == HMAP_HeaderMagicNumber && Header->Version == HMAP_HeaderVersion) NeedsByteSwap = false; @@ -98,12 +80,24 @@ const HeaderMap *HeaderMap::Create(const FileEntry *FE, FileManager &FM) { Header->Version == llvm::ByteSwap_16(HMAP_HeaderVersion)) NeedsByteSwap = true; // Mixed endianness headermap. else - return nullptr; // Not a header map. + return false; // Not a header map. - if (Header->Reserved != 0) return nullptr; + if (Header->Reserved != 0) + return false; - // Okay, everything looks good, create the header map. - return new HeaderMap(std::move(*FileBuffer), NeedsByteSwap); + // Check the number of buckets. It should be a power of two, and there + // should be enough space in the file for all of them. + uint32_t NumBuckets = NeedsByteSwap + ? llvm::sys::getSwappedBytes(Header->NumBuckets) + : Header->NumBuckets; + if (!llvm::isPowerOf2_32(NumBuckets)) + return false; + if (File.getBufferSize() < + sizeof(HMapHeader) + sizeof(HMapBucket) * NumBuckets) + return false; + + // Okay, everything looks good. + return true; } //===----------------------------------------------------------------------===// @@ -112,18 +106,18 @@ const HeaderMap *HeaderMap::Create(const FileEntry *FE, FileManager &FM) { /// getFileName - Return the filename of the headermap. -const char *HeaderMap::getFileName() const { +const char *HeaderMapImpl::getFileName() const { return FileBuffer->getBufferIdentifier(); } -unsigned HeaderMap::getEndianAdjustedWord(unsigned X) const { +unsigned HeaderMapImpl::getEndianAdjustedWord(unsigned X) const { if (!NeedsBSwap) return X; return llvm::ByteSwap_32(X); } /// getHeader - Return a reference to the file header, in unbyte-swapped form. /// This method cannot fail. -const HMapHeader &HeaderMap::getHeader() const { +const HMapHeader &HeaderMapImpl::getHeader() const { // We know the file is at least as big as the header. Return it. return *reinterpret_cast<const HMapHeader*>(FileBuffer->getBufferStart()); } @@ -131,42 +125,43 @@ const HMapHeader &HeaderMap::getHeader() const { /// getBucket - Return the specified hash table bucket from the header map, /// bswap'ing its fields as appropriate. If the bucket number is not valid, /// this return a bucket with an empty key (0). -HMapBucket HeaderMap::getBucket(unsigned BucketNo) const { +HMapBucket HeaderMapImpl::getBucket(unsigned BucketNo) const { + assert(FileBuffer->getBufferSize() >= + sizeof(HMapHeader) + sizeof(HMapBucket) * BucketNo && + "Expected bucket to be in range"); + HMapBucket Result; Result.Key = HMAP_EmptyBucketKey; const HMapBucket *BucketArray = reinterpret_cast<const HMapBucket*>(FileBuffer->getBufferStart() + sizeof(HMapHeader)); - const HMapBucket *BucketPtr = BucketArray+BucketNo; - if ((const char*)(BucketPtr+1) > FileBuffer->getBufferEnd()) { - Result.Prefix = 0; - Result.Suffix = 0; - return Result; // Invalid buffer, corrupt hmap. - } - // Otherwise, the bucket is valid. Load the values, bswapping as needed. + // Load the values, bswapping as needed. Result.Key = getEndianAdjustedWord(BucketPtr->Key); Result.Prefix = getEndianAdjustedWord(BucketPtr->Prefix); Result.Suffix = getEndianAdjustedWord(BucketPtr->Suffix); return Result; } -/// getString - Look up the specified string in the string table. If the string -/// index is not valid, it returns an empty string. -const char *HeaderMap::getString(unsigned StrTabIdx) const { +Optional<StringRef> HeaderMapImpl::getString(unsigned StrTabIdx) const { // Add the start of the string table to the idx. StrTabIdx += getEndianAdjustedWord(getHeader().StringsOffset); // Check for invalid index. if (StrTabIdx >= FileBuffer->getBufferSize()) - return nullptr; + return None; + + const char *Data = FileBuffer->getBufferStart() + StrTabIdx; + unsigned MaxLen = FileBuffer->getBufferSize() - StrTabIdx; + unsigned Len = strnlen(Data, MaxLen); + + // Check whether the buffer is null-terminated. + if (Len == MaxLen && Data[Len - 1]) + return None; - // 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 - // is nul terminated by virtue of being a MemoryBuffer. - return FileBuffer->getBufferStart()+StrTabIdx; + return StringRef(Data, Len); } //===----------------------------------------------------------------------===// @@ -174,22 +169,28 @@ const char *HeaderMap::getString(unsigned StrTabIdx) const { //===----------------------------------------------------------------------===// /// dump - Print the contents of this headermap to stderr. -void HeaderMap::dump() const { +LLVM_DUMP_METHOD void HeaderMapImpl::dump() const { const HMapHeader &Hdr = getHeader(); unsigned NumBuckets = getEndianAdjustedWord(Hdr.NumBuckets); - fprintf(stderr, "Header Map %s:\n %d buckets, %d entries\n", - getFileName(), NumBuckets, - getEndianAdjustedWord(Hdr.NumEntries)); + llvm::dbgs() << "Header Map " << getFileName() << ":\n " << NumBuckets + << ", " << getEndianAdjustedWord(Hdr.NumEntries) << "\n"; + + auto getStringOrInvalid = [this](unsigned Id) -> StringRef { + if (Optional<StringRef> S = getString(Id)) + return *S; + return "<invalid>"; + }; for (unsigned i = 0; i != NumBuckets; ++i) { HMapBucket B = getBucket(i); if (B.Key == HMAP_EmptyBucketKey) continue; - const char *Key = getString(B.Key); - const char *Prefix = getString(B.Prefix); - const char *Suffix = getString(B.Suffix); - fprintf(stderr, " %d. %s -> '%s' '%s'\n", i, Key, Prefix, Suffix); + StringRef Key = getStringOrInvalid(B.Key); + StringRef Prefix = getStringOrInvalid(B.Prefix); + StringRef Suffix = getStringOrInvalid(B.Suffix); + llvm::dbgs() << " " << i << ". " << Key << " -> '" << Prefix << "' '" + << Suffix << "'\n"; } } @@ -199,22 +200,20 @@ const FileEntry *HeaderMap::LookupFile( StringRef Filename, FileManager &FM) const { SmallString<1024> Path; - StringRef Dest = lookupFilename(Filename, Path); + StringRef Dest = HeaderMapImpl::lookupFilename(Filename, Path); if (Dest.empty()) return nullptr; return FM.getFile(Dest); } -StringRef HeaderMap::lookupFilename(StringRef Filename, - SmallVectorImpl<char> &DestPath) const { +StringRef HeaderMapImpl::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 StringRef(); + // Don't probe infinitely. This should be checked before constructing. + assert(llvm::isPowerOf2_32(NumBuckets) && "Expected power of 2"); // Linearly probe the hash table. for (unsigned Bucket = HashHMapKey(Filename);; ++Bucket) { @@ -222,16 +221,22 @@ StringRef HeaderMap::lookupFilename(StringRef Filename, 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))) + Optional<StringRef> Key = getString(B.Key); + if (LLVM_UNLIKELY(!Key)) + continue; + if (!Filename.equals_lower(*Key)) continue; // If so, we have a match in the hash table. Construct the destination // path. - StringRef Prefix = getString(B.Prefix); - StringRef Suffix = getString(B.Suffix); + Optional<StringRef> Prefix = getString(B.Prefix); + Optional<StringRef> Suffix = getString(B.Suffix); + DestPath.clear(); - DestPath.append(Prefix.begin(), Prefix.end()); - DestPath.append(Suffix.begin(), Suffix.end()); + if (LLVM_LIKELY(Prefix && Suffix)) { + DestPath.append(Prefix->begin(), Prefix->end()); + DestPath.append(Suffix->begin(), Suffix->end()); + } return StringRef(DestPath.begin(), DestPath.size()); } } diff --git a/lib/Lex/HeaderSearch.cpp b/lib/Lex/HeaderSearch.cpp index 2d005dd2e1f0..e5cc30e41c57 100644 --- a/lib/Lex/HeaderSearch.cpp +++ b/lib/Lex/HeaderSearch.cpp @@ -14,7 +14,6 @@ #include "clang/Lex/HeaderSearch.h" #include "clang/Basic/FileManager.h" #include "clang/Basic/IdentifierTable.h" -#include "clang/Frontend/PCHContainerOperations.h" #include "clang/Lex/ExternalPreprocessorSource.h" #include "clang/Lex/HeaderMap.h" #include "clang/Lex/HeaderSearchOptions.h" @@ -29,6 +28,7 @@ #include "llvm/Support/Path.h" #include "llvm/Support/raw_ostream.h" #include <cstdio> +#include <utility> #if defined(LLVM_ON_UNIX) #include <limits.h> #endif @@ -56,9 +56,9 @@ HeaderSearch::HeaderSearch(IntrusiveRefCntPtr<HeaderSearchOptions> HSOpts, SourceManager &SourceMgr, DiagnosticsEngine &Diags, const LangOptions &LangOpts, const TargetInfo *Target) - : HSOpts(HSOpts), Diags(Diags), FileMgr(SourceMgr.getFileManager()), - FrameworkMap(64), ModMap(SourceMgr, Diags, LangOpts, Target, *this), - LangOpts(LangOpts) { + : HSOpts(std::move(HSOpts)), Diags(Diags), + FileMgr(SourceMgr.getFileManager()), FrameworkMap(64), + ModMap(SourceMgr, Diags, LangOpts, Target, *this) { AngledDirIdx = 0; SystemDirIdx = 0; NoCurDirSearch = false; @@ -250,8 +250,9 @@ const char *DirectoryLookup::getName() const { } const FileEntry *HeaderSearch::getFileAndSuggestModule( - StringRef FileName, const DirectoryEntry *Dir, bool IsSystemHeaderDir, - Module *RequestingModule, ModuleMap::KnownHeader *SuggestedModule) { + StringRef FileName, SourceLocation IncludeLoc, const DirectoryEntry *Dir, + bool IsSystemHeaderDir, Module *RequestingModule, + ModuleMap::KnownHeader *SuggestedModule) { // If we have a module map that might map this header, load it and // check whether we'll have a suggestion for a module. const FileEntry *File = getFileMgr().getFile(FileName, /*OpenFile=*/true); @@ -272,6 +273,7 @@ const FileEntry *HeaderSearch::getFileAndSuggestModule( const FileEntry *DirectoryLookup::LookupFile( StringRef &Filename, HeaderSearch &HS, + SourceLocation IncludeLoc, SmallVectorImpl<char> *SearchPath, SmallVectorImpl<char> *RelativePath, Module *RequestingModule, @@ -297,7 +299,7 @@ const FileEntry *DirectoryLookup::LookupFile( RelativePath->append(Filename.begin(), Filename.end()); } - return HS.getFileAndSuggestModule(TmpDir, getDir(), + return HS.getFileAndSuggestModule(TmpDir, IncludeLoc, getDir(), isSystemHeaderDirectory(), RequestingModule, SuggestedModule); } @@ -567,7 +569,7 @@ const FileEntry *HeaderSearch::LookupFile( ArrayRef<std::pair<const FileEntry *, const DirectoryEntry *>> Includers, SmallVectorImpl<char> *SearchPath, SmallVectorImpl<char> *RelativePath, Module *RequestingModule, ModuleMap::KnownHeader *SuggestedModule, - bool SkipCache) { + bool SkipCache, bool BuildSystemModule) { if (SuggestedModule) *SuggestedModule = ModuleMap::KnownHeader(); @@ -585,7 +587,7 @@ const FileEntry *HeaderSearch::LookupFile( RelativePath->append(Filename.begin(), Filename.end()); } // Otherwise, just return the file. - return getFileAndSuggestModule(Filename, nullptr, + return getFileAndSuggestModule(Filename, IncludeLoc, nullptr, /*IsSystemHeaderDir*/false, RequestingModule, SuggestedModule); } @@ -615,13 +617,14 @@ const FileEntry *HeaderSearch::LookupFile( // getFileAndSuggestModule, because it's a reference to an element of // a container that could be reallocated across this call. // - // FIXME: If we have no includer, that means we're processing a #include + // If we have no includer, that means we're processing a #include // from a module build. We should treat this as a system header if we're // building a [system] module. bool IncluderIsSystemHeader = - Includer && getFileInfo(Includer).DirInfo != SrcMgr::C_User; + Includer ? getFileInfo(Includer).DirInfo != SrcMgr::C_User : + BuildSystemModule; if (const FileEntry *FE = getFileAndSuggestModule( - TmpDir, IncluderAndDir.second, IncluderIsSystemHeader, + TmpDir, IncludeLoc, IncluderAndDir.second, IncluderIsSystemHeader, RequestingModule, SuggestedModule)) { if (!Includer) { assert(First && "only first includer can have no file"); @@ -712,7 +715,7 @@ const FileEntry *HeaderSearch::LookupFile( bool InUserSpecifiedSystemFramework = false; bool HasBeenMapped = false; const FileEntry *FE = SearchDirs[i].LookupFile( - Filename, *this, SearchPath, RelativePath, RequestingModule, + Filename, *this, IncludeLoc, SearchPath, RelativePath, RequestingModule, SuggestedModule, InUserSpecifiedSystemFramework, HasBeenMapped, MappedName); if (HasBeenMapped) { @@ -1343,19 +1346,20 @@ void HeaderSearch::collectAllModules(SmallVectorImpl<Module *> &Modules) { DirNative); // Search each of the ".framework" directories to load them as modules. - for (llvm::sys::fs::directory_iterator Dir(DirNative, EC), DirEnd; + vfs::FileSystem &FS = *FileMgr.getVirtualFileSystem(); + for (vfs::directory_iterator Dir = FS.dir_begin(DirNative, EC), DirEnd; Dir != DirEnd && !EC; Dir.increment(EC)) { - if (llvm::sys::path::extension(Dir->path()) != ".framework") + if (llvm::sys::path::extension(Dir->getName()) != ".framework") continue; const DirectoryEntry *FrameworkDir = - FileMgr.getDirectory(Dir->path()); + FileMgr.getDirectory(Dir->getName()); if (!FrameworkDir) continue; // Load this framework module. - loadFrameworkModule(llvm::sys::path::stem(Dir->path()), FrameworkDir, - IsSystem); + loadFrameworkModule(llvm::sys::path::stem(Dir->getName()), + FrameworkDir, IsSystem); } continue; } @@ -1410,13 +1414,66 @@ void HeaderSearch::loadSubdirectoryModuleMaps(DirectoryLookup &SearchDir) { std::error_code EC; SmallString<128> DirNative; llvm::sys::path::native(SearchDir.getDir()->getName(), DirNative); - for (llvm::sys::fs::directory_iterator Dir(DirNative, EC), DirEnd; + vfs::FileSystem &FS = *FileMgr.getVirtualFileSystem(); + for (vfs::directory_iterator Dir = FS.dir_begin(DirNative, EC), DirEnd; Dir != DirEnd && !EC; Dir.increment(EC)) { - bool IsFramework = llvm::sys::path::extension(Dir->path()) == ".framework"; + bool IsFramework = + llvm::sys::path::extension(Dir->getName()) == ".framework"; if (IsFramework == SearchDir.isFramework()) - loadModuleMapFile(Dir->path(), SearchDir.isSystemHeaderDirectory(), + loadModuleMapFile(Dir->getName(), SearchDir.isSystemHeaderDirectory(), SearchDir.isFramework()); } SearchDir.setSearchedAllModuleMaps(true); } + +std::string HeaderSearch::suggestPathToFileForDiagnostics(const FileEntry *File, + bool *IsSystem) { + // FIXME: We assume that the path name currently cached in the FileEntry is + // the most appropriate one for this analysis (and that it's spelled the same + // way as the corresponding header search path). + const char *Name = File->getName(); + + unsigned BestPrefixLength = 0; + unsigned BestSearchDir; + + for (unsigned I = 0; I != SearchDirs.size(); ++I) { + // FIXME: Support this search within frameworks and header maps. + if (!SearchDirs[I].isNormalDir()) + continue; + + const char *Dir = SearchDirs[I].getDir()->getName(); + for (auto NI = llvm::sys::path::begin(Name), + NE = llvm::sys::path::end(Name), + DI = llvm::sys::path::begin(Dir), + DE = llvm::sys::path::end(Dir); + /*termination condition in loop*/; ++NI, ++DI) { + // '.' components in Name are ignored. + while (NI != NE && *NI == ".") + ++NI; + if (NI == NE) + break; + + // '.' components in Dir are ignored. + while (DI != DE && *DI == ".") + ++DI; + if (DI == DE) { + // Dir is a prefix of Name, up to '.' components and choice of path + // separators. + unsigned PrefixLength = NI - llvm::sys::path::begin(Name); + if (PrefixLength > BestPrefixLength) { + BestPrefixLength = PrefixLength; + BestSearchDir = I; + } + break; + } + + if (*NI != *DI) + break; + } + } + + if (IsSystem) + *IsSystem = BestPrefixLength ? BestSearchDir >= SystemDirIdx : false; + return Name + BestPrefixLength; +} diff --git a/lib/Lex/Lexer.cpp b/lib/Lex/Lexer.cpp index 27b0feb48270..9c2a0163acea 100644 --- a/lib/Lex/Lexer.cpp +++ b/lib/Lex/Lexer.cpp @@ -719,7 +719,9 @@ SourceLocation Lexer::AdvanceToTokenCharacter(SourceLocation TokStart, while (Lexer::isObviouslySimpleCharacter(*TokPtr)) { if (CharNo == 0) return TokStart.getLocWithOffset(PhysOffset); - ++TokPtr, --CharNo, ++PhysOffset; + ++TokPtr; + --CharNo; + ++PhysOffset; } // If we have a character that may be a trigraph or escaped newline, use a @@ -1000,6 +1002,31 @@ StringRef Lexer::getImmediateMacroName(SourceLocation Loc, return ExpansionBuffer.substr(ExpansionInfo.second, MacroTokenLength); } +StringRef Lexer::getImmediateMacroNameForDiagnostics( + SourceLocation Loc, const SourceManager &SM, const LangOptions &LangOpts) { + assert(Loc.isMacroID() && "Only reasonble to call this on macros"); + // Walk past macro argument expanions. + while (SM.isMacroArgExpansion(Loc)) + Loc = SM.getImmediateExpansionRange(Loc).first; + + // If the macro's spelling has no FileID, then it's actually a token paste + // or stringization (or similar) and not a macro at all. + if (!SM.getFileEntryForID(SM.getFileID(SM.getSpellingLoc(Loc)))) + return StringRef(); + + // Find the spelling location of the start of the non-argument expansion + // range. This is where the macro name was spelled in order to begin + // expanding this macro. + Loc = SM.getSpellingLoc(SM.getImmediateExpansionRange(Loc).first); + + // Dig out the buffer where the macro name was spelled and the extents of the + // name so that we can render it into the expansion note. + std::pair<FileID, unsigned> ExpansionInfo = SM.getDecomposedLoc(Loc); + unsigned MacroTokenLength = Lexer::MeasureTokenLength(Loc, SM, LangOpts); + StringRef ExpansionBuffer = SM.getBufferData(ExpansionInfo.first); + return ExpansionBuffer.substr(ExpansionInfo.second, MacroTokenLength); +} + bool Lexer::isIdentifierBodyChar(char c, const LangOptions &LangOpts) { return isIdentifierBody(c, LangOpts.DollarIdents); } @@ -1580,14 +1607,15 @@ bool Lexer::LexNumericConstant(Token &Result, const char *CurPtr) { // If we have a hex FP constant, continue. if ((C == '-' || C == '+') && (PrevCh == 'P' || PrevCh == 'p')) { - // Outside C99, we accept hexadecimal floating point numbers as a + // Outside C99 and C++17, we accept hexadecimal floating point numbers as a // not-quite-conforming extension. Only do so if this looks like it's // actually meant to be a hexfloat, and not if it has a ud-suffix. bool IsHexFloat = true; if (!LangOpts.C99) { if (!isHexaLiteral(BufferPtr, LangOpts)) IsHexFloat = false; - else if (std::find(BufferPtr, CurPtr, '_') != CurPtr) + else if (!getLangOpts().CPlusPlus1z && + std::find(BufferPtr, CurPtr, '_') != CurPtr) IsHexFloat = false; } if (IsHexFloat) @@ -2582,7 +2610,7 @@ static const char *FindConflictEnd(const char *CurPtr, const char *BufferEnd, ConflictMarkerKind CMK) { const char *Terminator = CMK == CMK_Perforce ? "<<<<\n" : ">>>>>>>"; size_t TermLen = CMK == CMK_Perforce ? 5 : 7; - StringRef RestOfBuffer(CurPtr+TermLen, BufferEnd-CurPtr-TermLen); + auto RestOfBuffer = StringRef(CurPtr, BufferEnd - CurPtr).substr(TermLen); size_t Pos = RestOfBuffer.find(Terminator); while (Pos != StringRef::npos) { // Must occur at start of line. @@ -2608,8 +2636,8 @@ bool Lexer::IsStartOfConflictMarker(const char *CurPtr) { return false; // Check to see if we have <<<<<<< or >>>>. - if ((BufferEnd-CurPtr < 8 || StringRef(CurPtr, 7) != "<<<<<<<") && - (BufferEnd-CurPtr < 6 || StringRef(CurPtr, 5) != ">>>> ")) + if (!StringRef(CurPtr, BufferEnd - CurPtr).startswith("<<<<<<<") && + !StringRef(CurPtr, BufferEnd - CurPtr).startswith(">>>> ")) return false; // If we have a situation where we don't care about conflict markers, ignore @@ -3480,6 +3508,9 @@ LexNextToken: if (Char == '=') { CurPtr = ConsumeChar(CurPtr, SizeTmp, Result); Kind = tok::caretequal; + } else if (LangOpts.OpenCL && Char == '^') { + CurPtr = ConsumeChar(CurPtr, SizeTmp, Result); + Kind = tok::caretcaret; } else { Kind = tok::caret; } diff --git a/lib/Lex/LiteralSupport.cpp b/lib/Lex/LiteralSupport.cpp index 5b1c49344e8d..e68b82fb499a 100644 --- a/lib/Lex/LiteralSupport.cpp +++ b/lib/Lex/LiteralSupport.cpp @@ -522,8 +522,10 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling, isLong = false; isUnsigned = false; isLongLong = false; + isHalf = false; isFloat = false; isImaginary = false; + isFloat128 = false; MicrosoftInteger = 0; hadError = false; @@ -536,34 +538,10 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling, s = SkipDigits(s); if (s == ThisTokEnd) { // Done. - } else if (isHexDigit(*s) && !(*s == 'e' || *s == 'E')) { - PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, s - ThisTokBegin), - diag::err_invalid_digit) << StringRef(s, 1) << 0; - hadError = true; - return; - } else if (*s == '.') { - checkSeparator(TokLoc, s, CSK_AfterDigits); - s++; - saw_period = true; - checkSeparator(TokLoc, s, CSK_BeforeDigits); - s = SkipDigits(s); - } - if ((*s == 'e' || *s == 'E')) { // exponent - checkSeparator(TokLoc, s, CSK_AfterDigits); - const char *Exponent = s; - s++; - saw_exponent = true; - if (*s == '+' || *s == '-') s++; // sign - checkSeparator(TokLoc, s, CSK_BeforeDigits); - const char *first_non_digit = SkipDigits(s); - if (first_non_digit != s) { - s = first_non_digit; - } else { - PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, Exponent - ThisTokBegin), - diag::err_exponent_has_no_digits); - hadError = true; + } else { + ParseDecimalOrOctalCommon(TokLoc); + if (hadError) return; - } } } @@ -579,12 +557,28 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling, // we break out of the loop. for (; s != ThisTokEnd; ++s) { switch (*s) { + case 'h': // FP Suffix for "half". + case 'H': + // OpenCL Extension v1.2 s9.5 - h or H suffix for half type. + if (!PP.getLangOpts().Half) break; + if (!isFPConstant) break; // Error for integer constant. + if (isHalf || isFloat || isLong) break; // HH, FH, LH invalid. + isHalf = true; + continue; // Success. case 'f': // FP Suffix for "float" case 'F': if (!isFPConstant) break; // Error for integer constant. - if (isFloat || isLong) break; // FF, LF invalid. + if (isHalf || isFloat || isLong || isFloat128) + break; // HF, FF, LF, QF invalid. isFloat = true; continue; // Success. + case 'q': // FP Suffix for "__float128" + case 'Q': + if (!isFPConstant) break; // Error for integer constant. + if (isHalf || isFloat || isLong || isFloat128) + break; // HQ, FQ, LQ, QQ invalid. + isFloat128 = true; + continue; // Success. case 'u': case 'U': if (isFPConstant) break; // Error for floating constant. @@ -594,7 +588,7 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling, case 'l': case 'L': if (isLong || isLongLong) break; // Cannot be repeated. - if (isFloat) break; // LF invalid. + if (isHalf || isFloat || isFloat128) break; // LH, LF, LQ invalid. // Check for long long. The L's need to be adjacent and the same case. if (s[1] == s[0]) { @@ -671,6 +665,7 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling, isUnsigned = false; isLongLong = false; isFloat = false; + isHalf = false; isImaginary = false; MicrosoftInteger = 0; @@ -693,6 +688,49 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling, } } +/// ParseDecimalOrOctalCommon - This method is called for decimal or octal +/// numbers. It issues an error for illegal digits, and handles floating point +/// parsing. If it detects a floating point number, the radix is set to 10. +void NumericLiteralParser::ParseDecimalOrOctalCommon(SourceLocation TokLoc){ + assert((radix == 8 || radix == 10) && "Unexpected radix"); + + // If we have a hex digit other than 'e' (which denotes a FP exponent) then + // the code is using an incorrect base. + if (isHexDigit(*s) && *s != 'e' && *s != 'E') { + PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, s-ThisTokBegin), + diag::err_invalid_digit) << StringRef(s, 1) << (radix == 8 ? 1 : 0); + hadError = true; + return; + } + + if (*s == '.') { + checkSeparator(TokLoc, s, CSK_AfterDigits); + 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; + saw_exponent = true; + if (*s == '+' || *s == '-') s++; // sign + const char *first_non_digit = SkipDigits(s); + if (containsDigits(s, first_non_digit)) { + checkSeparator(TokLoc, s, CSK_BeforeDigits); + s = first_non_digit; + } else { + PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, Exponent-ThisTokBegin), + diag::err_exponent_has_no_digits); + hadError = true; + return; + } + } +} + /// Determine whether a suffix is a valid ud-suffix. We avoid treating reserved /// suffixes as ud-suffixes, because the diagnostic experience is better if we /// treat it as an invalid suffix. @@ -752,21 +790,24 @@ void NumericLiteralParser::ParseNumberStartingWithZero(SourceLocation TokLoc) { radix = 16; DigitsBegin = s; s = SkipHexDigits(s); - bool noSignificand = (s == DigitsBegin); + bool HasSignificandDigits = containsDigits(DigitsBegin, s); if (s == ThisTokEnd) { // Done. } else if (*s == '.') { s++; saw_period = true; const char *floatDigitsBegin = s; - checkSeparator(TokLoc, s, CSK_BeforeDigits); s = SkipHexDigits(s); - noSignificand &= (floatDigitsBegin == s); + if (containsDigits(floatDigitsBegin, s)) + HasSignificandDigits = true; + if (HasSignificandDigits) + checkSeparator(TokLoc, floatDigitsBegin, CSK_BeforeDigits); } - if (noSignificand) { + if (!HasSignificandDigits) { PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, s - ThisTokBegin), - diag::err_hexconstant_requires) << 1; + diag::err_hex_constant_requires) + << PP.getLangOpts().CPlusPlus << 1; hadError = true; return; } @@ -780,7 +821,7 @@ void NumericLiteralParser::ParseNumberStartingWithZero(SourceLocation TokLoc) { saw_exponent = true; if (*s == '+' || *s == '-') s++; // sign const char *first_non_digit = SkipDigits(s); - if (first_non_digit == s) { + if (!containsDigits(s, first_non_digit)) { PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, Exponent-ThisTokBegin), diag::err_exponent_has_no_digits); hadError = true; @@ -790,10 +831,15 @@ void NumericLiteralParser::ParseNumberStartingWithZero(SourceLocation TokLoc) { s = first_non_digit; if (!PP.getLangOpts().HexFloats) - PP.Diag(TokLoc, diag::ext_hexconstant_invalid); + PP.Diag(TokLoc, PP.getLangOpts().CPlusPlus + ? diag::ext_hex_literal_invalid + : diag::ext_hex_constant_invalid); + else if (PP.getLangOpts().CPlusPlus1z) + PP.Diag(TokLoc, diag::warn_cxx1z_hex_literal); } else if (saw_period) { - PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, s-ThisTokBegin), - diag::err_hexconstant_requires) << 0; + PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, s - ThisTokBegin), + diag::err_hex_constant_requires) + << PP.getLangOpts().CPlusPlus << 0; hadError = true; } return; @@ -843,40 +889,7 @@ void NumericLiteralParser::ParseNumberStartingWithZero(SourceLocation TokLoc) { } } - // If we have a hex digit other than 'e' (which denotes a FP exponent) then - // the code is using an incorrect base. - if (isHexDigit(*s) && *s != 'e' && *s != 'E') { - PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, s-ThisTokBegin), - diag::err_invalid_digit) << StringRef(s, 1) << 1; - hadError = true; - return; - } - - if (*s == '.') { - 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; - saw_exponent = true; - 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), - diag::err_exponent_has_no_digits); - hadError = true; - return; - } - } + ParseDecimalOrOctalCommon(TokLoc); } static bool alwaysFitsInto64Bits(unsigned Radix, unsigned NumDigits) { diff --git a/lib/Lex/MacroInfo.cpp b/lib/Lex/MacroInfo.cpp index 0b4292fbeae5..2ef4387b99ba 100644 --- a/lib/Lex/MacroInfo.cpp +++ b/lib/Lex/MacroInfo.cpp @@ -126,7 +126,7 @@ bool MacroInfo::isIdenticalTo(const MacroInfo &Other, Preprocessor &PP, return true; } -void MacroInfo::dump() const { +LLVM_DUMP_METHOD void MacroInfo::dump() const { llvm::raw_ostream &Out = llvm::errs(); // FIXME: Dump locations. @@ -209,7 +209,7 @@ MacroDirective::findDirectiveAtLoc(SourceLocation L, SourceManager &SM) const { return DefInfo(); } -void MacroDirective::dump() const { +LLVM_DUMP_METHOD void MacroDirective::dump() const { llvm::raw_ostream &Out = llvm::errs(); switch (getKind()) { diff --git a/lib/Lex/Makefile b/lib/Lex/Makefile deleted file mode 100644 index d80fb55c78a7..000000000000 --- a/lib/Lex/Makefile +++ /dev/null @@ -1,24 +0,0 @@ -##===- clang/lib/Lex/Makefile ------------------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## -# -# This implements the Lexer library for the C-Language front-end. -# -##===----------------------------------------------------------------------===## - -CLANG_LEVEL := ../.. -include $(CLANG_LEVEL)/../../Makefile.config - -LIBRARYNAME := clangLex - -ifeq ($(ARCH),PowerPC) -CXX.Flags += -maltivec -endif - -include $(CLANG_LEVEL)/Makefile - diff --git a/lib/Lex/ModuleMap.cpp b/lib/Lex/ModuleMap.cpp index a7524028a229..3e3215dee82a 100644 --- a/lib/Lex/ModuleMap.cpp +++ b/lib/Lex/ModuleMap.cpp @@ -89,16 +89,13 @@ ModuleMap::ModuleMap(SourceManager &SourceMgr, DiagnosticsEngine &Diags, HeaderSearch &HeaderInfo) : SourceMgr(SourceMgr), Diags(Diags), LangOpts(LangOpts), Target(Target), HeaderInfo(HeaderInfo), BuiltinIncludeDir(nullptr), - CompilingModule(nullptr), SourceModule(nullptr), NumCreatedModules(0) { + SourceModule(nullptr), NumCreatedModules(0) { MMapLangOpts.LineComment = true; } ModuleMap::~ModuleMap() { - for (llvm::StringMap<Module *>::iterator I = Modules.begin(), - IEnd = Modules.end(); - I != IEnd; ++I) { - delete I->getValue(); - } + for (auto &M : Modules) + delete M.getValue(); } void ModuleMap::setTarget(const TargetInfo &Target) { @@ -154,6 +151,7 @@ static bool isBuiltinHeader(StringRef FileName) { .Case("limits.h", true) .Case("stdalign.h", true) .Case("stdarg.h", true) + .Case("stdatomic.h", true) .Case("stdbool.h", true) .Case("stddef.h", true) .Case("stdint.h", true) @@ -211,29 +209,25 @@ ModuleMap::findHeaderInUmbrellaDirs(const FileEntry *File, static bool violatesPrivateInclude(Module *RequestingModule, const FileEntry *IncFileEnt, - ModuleMap::ModuleHeaderRole Role, - Module *RequestedModule) { - bool IsPrivateRole = Role & ModuleMap::PrivateHeader; + ModuleMap::KnownHeader Header) { #ifndef NDEBUG - if (IsPrivateRole) { + if (Header.getRole() & ModuleMap::PrivateHeader) { // 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. bool IsPrivate = false; SmallVectorImpl<Module::Header> *HeaderList[] = { - &RequestedModule->Headers[Module::HK_Private], - &RequestedModule->Headers[Module::HK_PrivateTextual]}; + &Header.getModule()->Headers[Module::HK_Private], + &Header.getModule()->Headers[Module::HK_PrivateTextual]}; for (auto *Hs : HeaderList) IsPrivate |= std::find_if(Hs->begin(), Hs->end(), [&](const Module::Header &H) { return H.Entry == IncFileEnt; }) != Hs->end(); - assert((!IsPrivateRole || IsPrivate) && "inconsistent headers and roles"); + assert(IsPrivate && "inconsistent headers and roles"); } #endif - return IsPrivateRole && (!RequestingModule || - RequestedModule->getTopLevelModule() != - RequestingModule->getTopLevelModule()); + return !Header.isAccessibleFrom(RequestingModule); } static Module *getTopLevelOrNull(Module *M) { @@ -241,6 +235,7 @@ static Module *getTopLevelOrNull(Module *M) { } void ModuleMap::diagnoseHeaderInclusion(Module *RequestingModule, + bool RequestingModuleIsModuleInterface, SourceLocation FilenameLoc, StringRef Filename, const FileEntry *File) { @@ -260,8 +255,7 @@ void ModuleMap::diagnoseHeaderInclusion(Module *RequestingModule, if (Known != Headers.end()) { for (const KnownHeader &Header : Known->second) { // Remember private headers for later printing of a diagnostic. - if (violatesPrivateInclude(RequestingModule, File, Header.getRole(), - Header.getModule())) { + if (violatesPrivateInclude(RequestingModule, File, Header)) { Private = Header.getModule(); continue; } @@ -303,7 +297,7 @@ void ModuleMap::diagnoseHeaderInclusion(Module *RequestingModule, if (LangOpts.ModulesStrictDeclUse) { Diags.Report(FilenameLoc, diag::err_undeclared_use_of_module) << RequestingModule->getFullModuleName() << Filename; - } else if (RequestingModule) { + } else if (RequestingModule && RequestingModuleIsModuleInterface) { diag::kind DiagID = RequestingModule->getTopLevelModule()->IsFramework ? diag::warn_non_modular_include_in_framework_module : diag::warn_non_modular_include_in_module; @@ -343,8 +337,8 @@ ModuleMap::KnownHeader ModuleMap::findModuleForHeader(const FileEntry *File) { ModuleMap::KnownHeader Result; // Iterate over all modules that 'File' is part of to find the best fit. for (KnownHeader &H : Known->second) { - // Prefer a header from the current module over all others. - if (H.getModule()->getTopLevelModule() == CompilingModule) + // Prefer a header from the source module over all others. + if (H.getModule()->getTopLevelModule() == SourceModule) return MakeResult(H); if (!Result || isBetterKnownHeader(H, Result)) Result = H; @@ -556,16 +550,10 @@ ModuleMap::findOrCreateModule(StringRef Name, Module *Parent, bool IsFramework, // Create a new module with this name. Module *Result = new Module(Name, SourceLocation(), Parent, IsFramework, IsExplicit, NumCreatedModules++); - if (LangOpts.CurrentModule == Name) { - SourceModule = Result; - SourceModuleName = Name; - } if (!Parent) { + if (LangOpts.CurrentModule == Name) + SourceModule = Result; Modules[Name] = Result; - if (!LangOpts.CurrentModule.empty() && !CompilingModule && - Name == LangOpts.CurrentModule) { - CompilingModule = Result; - } } return std::make_pair(Result, true); } @@ -693,9 +681,10 @@ Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir, NumCreatedModules++); InferredModuleAllowedBy[Result] = ModuleMapFile; Result->IsInferred = true; - if (LangOpts.CurrentModule == ModuleName) { - SourceModule = Result; - SourceModuleName = ModuleName; + if (!Parent) { + if (LangOpts.CurrentModule == ModuleName) + SourceModule = Result; + Modules[ModuleName] = Result; } Result->IsSystem |= Attrs.IsSystem; @@ -703,9 +692,6 @@ Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir, Result->ConfigMacrosExhaustive |= Attrs.IsExhaustive; Result->Directory = FrameworkDir; - if (!Parent) - Modules[ModuleName] = Result; - // umbrella header "umbrella-header-name" // // The "Headers/" component of the name is implied because this is @@ -725,13 +711,15 @@ Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir, = StringRef(FrameworkDir->getName()); llvm::sys::path::append(SubframeworksDirName, "Frameworks"); llvm::sys::path::native(SubframeworksDirName); - for (llvm::sys::fs::directory_iterator Dir(SubframeworksDirName, EC), DirEnd; + vfs::FileSystem &FS = *FileMgr.getVirtualFileSystem(); + for (vfs::directory_iterator Dir = FS.dir_begin(SubframeworksDirName, EC), + DirEnd; Dir != DirEnd && !EC; Dir.increment(EC)) { - if (!StringRef(Dir->path()).endswith(".framework")) + if (!StringRef(Dir->getName()).endswith(".framework")) continue; - if (const DirectoryEntry *SubframeworkDir - = FileMgr.getDirectory(Dir->path())) { + if (const DirectoryEntry *SubframeworkDir = + FileMgr.getDirectory(Dir->getName())) { // Note: as an egregious but useful hack, we use the real path here and // check whether it is actually a subdirectory of the parent directory. // This will not be the case if the 'subframework' is actually a symlink @@ -774,6 +762,10 @@ void ModuleMap::setUmbrellaHeader(Module *Mod, const FileEntry *UmbrellaHeader, Mod->Umbrella = UmbrellaHeader; Mod->UmbrellaAsWritten = NameAsWritten.str(); UmbrellaDirs[UmbrellaHeader->getDir()] = Mod; + + // Notify callbacks that we just added a new header. + for (const auto &Cb : Callbacks) + Cb->moduleMapAddUmbrellaHeader(&SourceMgr.getFileManager(), UmbrellaHeader); } void ModuleMap::setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir, @@ -812,13 +804,18 @@ void ModuleMap::addHeader(Module *Mod, Module::Header Header, HeaderList.push_back(KH); Mod->Headers[headerRoleToKind(Role)].push_back(std::move(Header)); - bool isCompilingModuleHeader = Mod->getTopLevelModule() == CompilingModule; + bool isCompilingModuleHeader = + LangOpts.CompilingModule && Mod->getTopLevelModule() == SourceModule; if (!Imported || isCompilingModuleHeader) { // When we import HeaderFileInfo, the external source is expected to // set the isModuleHeader flag itself. HeaderInfo.MarkFileModuleHeader(Header.Entry, Role, isCompilingModuleHeader); } + + // Notify callbacks that we just added a new header. + for (const auto &Cb : Callbacks) + Cb->moduleMapAddHeader(Header.Entry->getName()); } void ModuleMap::excludeHeader(Module *Mod, Module::Header Header) { @@ -853,7 +850,7 @@ void ModuleMap::setInferredModuleAllowedBy(Module *M, const FileEntry *ModMap) { InferredModuleAllowedBy[M] = ModMap; } -void ModuleMap::dump() { +LLVM_DUMP_METHOD void ModuleMap::dump() { llvm::errs() << "Modules:"; for (llvm::StringMap<Module *>::iterator M = Modules.begin(), MEnd = Modules.end(); @@ -920,6 +917,9 @@ Module *ModuleMap::inferModuleFromLocation(FullSourceLoc Loc) { if (Loc.isInvalid()) return nullptr; + if (UmbrellaDirs.empty() && Headers.empty()) + return nullptr; + // Use the expansion location to determine which module we're in. FullSourceLoc ExpansionLoc = Loc.getExpansionLoc(); if (!ExpansionLoc.isFileID()) @@ -1409,7 +1409,9 @@ void ModuleMapParser::parseModuleDecl() { // Parse the optional attribute list. Attributes Attrs; - parseOptionalAttributes(Attrs); + if (parseOptionalAttributes(Attrs)) + return; + // Parse the opening brace. if (!Tok.is(MMToken::LBrace)) { @@ -1934,11 +1936,13 @@ void ModuleMapParser::parseUmbrellaDirDecl(SourceLocation UmbrellaLoc) { // uncommonly used Tcl module on Darwin platforms. std::error_code EC; SmallVector<Module::Header, 6> Headers; - for (llvm::sys::fs::recursive_directory_iterator I(Dir->getName(), EC), E; + vfs::FileSystem &FS = *SourceMgr.getFileManager().getVirtualFileSystem(); + for (vfs::recursive_directory_iterator I(FS, Dir->getName(), EC), E; I != E && !EC; I.increment(EC)) { - if (const FileEntry *FE = SourceMgr.getFileManager().getFile(I->path())) { + if (const FileEntry *FE = + SourceMgr.getFileManager().getFile(I->getName())) { - Module::Header Header = {I->path(), FE}; + Module::Header Header = {I->getName(), FE}; Headers.push_back(std::move(Header)); } } @@ -2074,7 +2078,9 @@ void ModuleMapParser::parseConfigMacros() { // Parse the optional attributes. Attributes Attrs; - parseOptionalAttributes(Attrs); + if (parseOptionalAttributes(Attrs)) + return; + if (Attrs.IsExhaustive && !ActiveModule->Parent) { ActiveModule->ConfigMacrosExhaustive = true; } @@ -2222,7 +2228,8 @@ void ModuleMapParser::parseInferredModuleDecl(bool Framework, bool Explicit) { // Parse optional attributes. Attributes Attrs; - parseOptionalAttributes(Attrs); + if (parseOptionalAttributes(Attrs)) + return; if (ActiveModule) { // Note that we have an inferred submodule. diff --git a/lib/Lex/PPCaching.cpp b/lib/Lex/PPCaching.cpp index bd48ae64ab4b..4742aae5c123 100644 --- a/lib/Lex/PPCaching.cpp +++ b/lib/Lex/PPCaching.cpp @@ -116,3 +116,29 @@ void Preprocessor::AnnotatePreviousCachedTokens(const Token &Tok) { } } } + +bool Preprocessor::IsPreviousCachedToken(const Token &Tok) const { + // There's currently no cached token... + if (!CachedLexPos) + return false; + + const Token LastCachedTok = CachedTokens[CachedLexPos - 1]; + if (LastCachedTok.getKind() != Tok.getKind()) + return false; + + int RelOffset = 0; + if ((!getSourceManager().isInSameSLocAddrSpace( + Tok.getLocation(), getLastCachedTokenLocation(), &RelOffset)) || + RelOffset) + return false; + + return true; +} + +void Preprocessor::ReplacePreviousCachedToken(ArrayRef<Token> NewToks) { + assert(CachedLexPos != 0 && "Expected to have some cached tokens"); + CachedTokens.insert(CachedTokens.begin() + CachedLexPos - 1, NewToks.begin(), + NewToks.end()); + CachedTokens.erase(CachedTokens.begin() + CachedLexPos - 1 + NewToks.size()); + CachedLexPos += NewToks.size() - 1; +} diff --git a/lib/Lex/PPDirectives.cpp b/lib/Lex/PPDirectives.cpp index c02a0cb8d302..77f118fd3ccb 100644 --- a/lib/Lex/PPDirectives.cpp +++ b/lib/Lex/PPDirectives.cpp @@ -24,9 +24,14 @@ #include "clang/Lex/ModuleLoader.h" #include "clang/Lex/Pragma.h" #include "llvm/ADT/APInt.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/StringSwitch.h" +#include "llvm/ADT/iterator_range.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Path.h" #include "llvm/Support/SaveAndRestore.h" + using namespace clang; //===----------------------------------------------------------------------===// @@ -136,6 +141,84 @@ static MacroDiag shouldWarnOnMacroUndef(Preprocessor &PP, IdentifierInfo *II) { return MD_NoWarn; } +// Return true if we want to issue a diagnostic by default if we +// encounter this name in a #include with the wrong case. For now, +// this includes the standard C and C++ headers, Posix headers, +// and Boost headers. Improper case for these #includes is a +// potential portability issue. +static bool warnByDefaultOnWrongCase(StringRef Include) { + // If the first component of the path is "boost", treat this like a standard header + // for the purposes of diagnostics. + if (::llvm::sys::path::begin(Include)->equals_lower("boost")) + return true; + + // "condition_variable" is the longest standard header name at 18 characters. + // If the include file name is longer than that, it can't be a standard header. + static const size_t MaxStdHeaderNameLen = 18u; + if (Include.size() > MaxStdHeaderNameLen) + return false; + + // Lowercase and normalize the search string. + SmallString<32> LowerInclude{Include}; + for (char &Ch : LowerInclude) { + // In the ASCII range? + if (static_cast<unsigned char>(Ch) > 0x7f) + return false; // Can't be a standard header + // ASCII lowercase: + if (Ch >= 'A' && Ch <= 'Z') + Ch += 'a' - 'A'; + // Normalize path separators for comparison purposes. + else if (::llvm::sys::path::is_separator(Ch)) + Ch = '/'; + } + + // The standard C/C++ and Posix headers + return llvm::StringSwitch<bool>(LowerInclude) + // C library headers + .Cases("assert.h", "complex.h", "ctype.h", "errno.h", "fenv.h", true) + .Cases("float.h", "inttypes.h", "iso646.h", "limits.h", "locale.h", true) + .Cases("math.h", "setjmp.h", "signal.h", "stdalign.h", "stdarg.h", true) + .Cases("stdatomic.h", "stdbool.h", "stddef.h", "stdint.h", "stdio.h", true) + .Cases("stdlib.h", "stdnoreturn.h", "string.h", "tgmath.h", "threads.h", true) + .Cases("time.h", "uchar.h", "wchar.h", "wctype.h", true) + + // C++ headers for C library facilities + .Cases("cassert", "ccomplex", "cctype", "cerrno", "cfenv", true) + .Cases("cfloat", "cinttypes", "ciso646", "climits", "clocale", true) + .Cases("cmath", "csetjmp", "csignal", "cstdalign", "cstdarg", true) + .Cases("cstdbool", "cstddef", "cstdint", "cstdio", "cstdlib", true) + .Cases("cstring", "ctgmath", "ctime", "cuchar", "cwchar", true) + .Case("cwctype", true) + + // C++ library headers + .Cases("algorithm", "fstream", "list", "regex", "thread", true) + .Cases("array", "functional", "locale", "scoped_allocator", "tuple", true) + .Cases("atomic", "future", "map", "set", "type_traits", true) + .Cases("bitset", "initializer_list", "memory", "shared_mutex", "typeindex", true) + .Cases("chrono", "iomanip", "mutex", "sstream", "typeinfo", true) + .Cases("codecvt", "ios", "new", "stack", "unordered_map", true) + .Cases("complex", "iosfwd", "numeric", "stdexcept", "unordered_set", true) + .Cases("condition_variable", "iostream", "ostream", "streambuf", "utility", true) + .Cases("deque", "istream", "queue", "string", "valarray", true) + .Cases("exception", "iterator", "random", "strstream", "vector", true) + .Cases("forward_list", "limits", "ratio", "system_error", true) + + // POSIX headers (which aren't also C headers) + .Cases("aio.h", "arpa/inet.h", "cpio.h", "dirent.h", "dlfcn.h", true) + .Cases("fcntl.h", "fmtmsg.h", "fnmatch.h", "ftw.h", "glob.h", true) + .Cases("grp.h", "iconv.h", "langinfo.h", "libgen.h", "monetary.h", true) + .Cases("mqueue.h", "ndbm.h", "net/if.h", "netdb.h", "netinet/in.h", true) + .Cases("netinet/tcp.h", "nl_types.h", "poll.h", "pthread.h", "pwd.h", true) + .Cases("regex.h", "sched.h", "search.h", "semaphore.h", "spawn.h", true) + .Cases("strings.h", "stropts.h", "sys/ipc.h", "sys/mman.h", "sys/msg.h", true) + .Cases("sys/resource.h", "sys/select.h", "sys/sem.h", "sys/shm.h", "sys/socket.h", true) + .Cases("sys/stat.h", "sys/statvfs.h", "sys/time.h", "sys/times.h", "sys/types.h", true) + .Cases("sys/uio.h", "sys/un.h", "sys/utsname.h", "sys/wait.h", "syslog.h", true) + .Cases("tar.h", "termios.h", "trace.h", "ulimit.h", true) + .Cases("unistd.h", "utime.h", "utmpx.h", "wordexp.h", true) + .Default(false); +} + bool Preprocessor::CheckMacroName(Token &MacroNameTok, MacroUse isDefineUndef, bool *ShadowFlag) { // Missing macro name? @@ -272,8 +355,6 @@ void Preprocessor::CheckEndOfDirective(const char *DirType, bool EnableMacros) { } } - - /// SkipExcludedConditionalBlock - We just read a \#if or related directive and /// decided that the subsequent tokens are in the \#if'd out portion of the /// file. Lex the rest of the file, until we see an \#endif. If @@ -310,7 +391,7 @@ void Preprocessor::SkipExcludedConditionalBlock(SourceLocation IfTokenLoc, setCodeCompletionReached(); continue; } - + // If this is the end of the buffer, we have an error. if (Tok.is(tok::eof)) { // Emit errors for each unterminated conditional on the stack, including @@ -497,7 +578,6 @@ void Preprocessor::SkipExcludedConditionalBlock(SourceLocation IfTokenLoc, } void Preprocessor::PTHSkipExcludedConditionalBlock() { - while (1) { assert(CurPTHLexer); assert(CurPTHLexer->LexingRawMode == false); @@ -571,28 +651,27 @@ void Preprocessor::PTHSkipExcludedConditionalBlock() { } // Otherwise, skip this block and go to the next one. - continue; } } Module *Preprocessor::getModuleForLocation(SourceLocation Loc) { - ModuleMap &ModMap = HeaderInfo.getModuleMap(); - if (SourceMgr.isInMainFile(Loc)) { - if (Module *CurMod = getCurrentModule()) - return CurMod; // Compiling a module. - return HeaderInfo.getModuleMap().SourceModule; // Compiling a source. - } - // Try to determine the module of the include directive. - // FIXME: Look into directly passing the FileEntry from LookupFile instead. - FileID IDOfIncl = SourceMgr.getFileID(SourceMgr.getExpansionLoc(Loc)); - if (const FileEntry *EntryOfIncl = SourceMgr.getFileEntryForID(IDOfIncl)) { - // The include comes from a file. - return ModMap.findModuleForHeader(EntryOfIncl).getModule(); - } else { - // The include does not come from a file, - // so it is probably a module compilation. - return getCurrentModule(); + if (!SourceMgr.isInMainFile(Loc)) { + // Try to determine the module of the include directive. + // FIXME: Look into directly passing the FileEntry from LookupFile instead. + FileID IDOfIncl = SourceMgr.getFileID(SourceMgr.getExpansionLoc(Loc)); + if (const FileEntry *EntryOfIncl = SourceMgr.getFileEntryForID(IDOfIncl)) { + // The include comes from an included file. + return HeaderInfo.getModuleMap() + .findModuleForHeader(EntryOfIncl) + .getModule(); + } } + + // This is either in the main file or not in a file at all. It belongs + // to the current module, if there is one. + return getLangOpts().CurrentModule.empty() + ? nullptr + : HeaderInfo.lookupModule(getLangOpts().CurrentModule); } Module *Preprocessor::getModuleContainingLocation(SourceLocation Loc) { @@ -600,6 +679,62 @@ Module *Preprocessor::getModuleContainingLocation(SourceLocation Loc) { FullSourceLoc(Loc, SourceMgr)); } +const FileEntry * +Preprocessor::getModuleHeaderToIncludeForDiagnostics(SourceLocation IncLoc, + SourceLocation Loc) { + // If we have a module import syntax, we shouldn't include a header to + // make a particular module visible. + if (getLangOpts().ObjC2) + return nullptr; + + // Figure out which module we'd want to import. + Module *M = getModuleContainingLocation(Loc); + if (!M) + return nullptr; + + Module *TopM = M->getTopLevelModule(); + Module *IncM = getModuleForLocation(IncLoc); + + // Walk up through the include stack, looking through textual headers of M + // until we hit a non-textual header that we can #include. (We assume textual + // headers of a module with non-textual headers aren't meant to be used to + // import entities from the module.) + auto &SM = getSourceManager(); + while (!Loc.isInvalid() && !SM.isInMainFile(Loc)) { + auto ID = SM.getFileID(SM.getExpansionLoc(Loc)); + auto *FE = SM.getFileEntryForID(ID); + + bool InTextualHeader = false; + for (auto Header : HeaderInfo.getModuleMap().findAllModulesForHeader(FE)) { + if (!Header.getModule()->isSubModuleOf(TopM)) + continue; + + if (!(Header.getRole() & ModuleMap::TextualHeader)) { + // If this is an accessible, non-textual header of M's top-level module + // that transitively includes the given location and makes the + // corresponding module visible, this is the thing to #include. + if (Header.isAccessibleFrom(IncM)) + return FE; + + // It's in a private header; we can't #include it. + // FIXME: If there's a public header in some module that re-exports it, + // then we could suggest including that, but it's not clear that's the + // expected way to make this entity visible. + continue; + } + + InTextualHeader = true; + } + + if (!InTextualHeader) + break; + + Loc = SM.getIncludeLoc(ID); + } + + return nullptr; +} + const FileEntry *Preprocessor::LookupFile( SourceLocation FilenameLoc, StringRef Filename, @@ -611,12 +746,14 @@ const FileEntry *Preprocessor::LookupFile( SmallVectorImpl<char> *RelativePath, ModuleMap::KnownHeader *SuggestedModule, bool SkipCache) { - Module *RequestingModule = getModuleForLocation(FilenameLoc); + Module *RequestingModule = getModuleForLocation(FilenameLoc); + bool RequestingModuleIsModuleInterface = !SourceMgr.isInMainFile(FilenameLoc); // If the header lookup mechanism may be relative to the current inclusion // stack, record the parent #includes. SmallVector<std::pair<const FileEntry *, const DirectoryEntry *>, 16> Includers; + bool BuildSystemModule = false; if (!FromDir && !FromFile) { FileID FID = getCurrentFileLexer()->getFileID(); const FileEntry *FileEnt = SourceMgr.getFileEntryForID(FID); @@ -634,9 +771,10 @@ const FileEntry *Preprocessor::LookupFile( // come from header declarations in the module map) relative to the module // map file. if (!FileEnt) { - if (FID == SourceMgr.getMainFileID() && MainFileDir) + if (FID == SourceMgr.getMainFileID() && MainFileDir) { Includers.push_back(std::make_pair(nullptr, MainFileDir)); - else if ((FileEnt = + BuildSystemModule = getCurrentModule()->IsSystem; + } else if ((FileEnt = SourceMgr.getFileEntryForID(SourceMgr.getMainFileID()))) Includers.push_back(std::make_pair(FileEnt, FileMgr.getDirectory("."))); } else { @@ -682,11 +820,13 @@ const FileEntry *Preprocessor::LookupFile( // Do a standard file entry lookup. const FileEntry *FE = HeaderInfo.LookupFile( Filename, FilenameLoc, isAngled, FromDir, CurDir, Includers, SearchPath, - RelativePath, RequestingModule, SuggestedModule, SkipCache); + RelativePath, RequestingModule, SuggestedModule, SkipCache, + BuildSystemModule); if (FE) { if (SuggestedModule && !LangOpts.AsmPreprocessor) HeaderInfo.getModuleMap().diagnoseHeaderInclusion( - RequestingModule, FilenameLoc, Filename, FE); + RequestingModule, RequestingModuleIsModuleInterface, FilenameLoc, + Filename, FE); return FE; } @@ -702,7 +842,8 @@ const FileEntry *Preprocessor::LookupFile( SuggestedModule))) { if (SuggestedModule && !LangOpts.AsmPreprocessor) HeaderInfo.getModuleMap().diagnoseHeaderInclusion( - RequestingModule, FilenameLoc, Filename, FE); + RequestingModule, RequestingModuleIsModuleInterface, FilenameLoc, + Filename, FE); return FE; } } @@ -717,7 +858,8 @@ const FileEntry *Preprocessor::LookupFile( RequestingModule, SuggestedModule))) { if (SuggestedModule && !LangOpts.AsmPreprocessor) HeaderInfo.getModuleMap().diagnoseHeaderInclusion( - RequestingModule, FilenameLoc, Filename, FE); + RequestingModule, RequestingModuleIsModuleInterface, + FilenameLoc, Filename, FE); return FE; } } @@ -728,7 +870,6 @@ const FileEntry *Preprocessor::LookupFile( return nullptr; } - //===----------------------------------------------------------------------===// // Preprocessor Directive Handling. //===----------------------------------------------------------------------===// @@ -740,9 +881,11 @@ public: if (pp->MacroExpansionInDirectivesOverride) pp->DisableMacroExpansion = false; } + ~ResetMacroExpansionHelper() { PP->DisableMacroExpansion = save; } + private: Preprocessor *PP; bool save; @@ -849,7 +992,7 @@ void Preprocessor::HandleDirective(Token &Result) { return HandleIncludeDirective(SavedHash.getLocation(), Result); case tok::pp___include_macros: // Handle -imacros. - return HandleIncludeMacrosDirective(SavedHash.getLocation(), Result); + return HandleIncludeMacrosDirective(SavedHash.getLocation(), Result); // C99 6.10.3 - Macro Replacement. case tok::pp_define: @@ -888,12 +1031,12 @@ void Preprocessor::HandleDirective(Token &Result) { case tok::pp_unassert: //isExtension = true; // FIXME: implement #unassert break; - + case tok::pp___public_macro: if (getLangOpts().Modules) return HandleMacroPublicDirective(Result); break; - + case tok::pp___private_macro: if (getLangOpts().Modules) return HandleMacroPrivateDirective(Result); @@ -907,20 +1050,20 @@ void Preprocessor::HandleDirective(Token &Result) { // various pseudo-ops. Just return the # token and push back the following // token to be lexed next time. if (getLangOpts().AsmPreprocessor) { - Token *Toks = new Token[2]; + auto Toks = llvm::make_unique<Token[]>(2); // Return the # and the token after it. Toks[0] = SavedHash; Toks[1] = Result; - + // If the second token is a hashhash token, then we need to translate it to // unknown so the token lexer doesn't try to perform token pasting. if (Result.is(tok::hashhash)) Toks[1].setKind(tok::unknown); - + // Enter this token stream so that we re-lex the tokens. Make sure to // enable macro expansion, in case the token after the # is an identifier // that is expanded. - EnterTokenStream(Toks, 2, false, true); + EnterTokenStream(std::move(Toks), 2, false); return; } @@ -953,7 +1096,7 @@ static bool GetLineValue(Token &DigitTok, unsigned &Val, unsigned ActualLength = PP.getSpelling(DigitTok, DigitTokBegin, &Invalid); if (Invalid) return true; - + // Verify that we have a simple digit-sequence, and compute the value. This // is always a simple digit string computed in decimal, so we do this manually // here. @@ -1004,7 +1147,7 @@ void Preprocessor::HandleLineDirective(Token &Tok) { unsigned LineNo; if (GetLineValue(DigitTok, LineNo, diag::err_pp_line_requires_integer,*this)) return; - + if (LineNo == 0) Diag(DigitTok, diag::ext_pp_line_zero); @@ -1087,7 +1230,7 @@ static bool ReadLineMarkerFlags(bool &IsFileEntry, bool &IsFileExit, PresumedLoc PLoc = SM.getPresumedLoc(FlagTok.getLocation()); if (PLoc.isInvalid()) return true; - + // If there is no include loc (main file) or if the include loc is in a // different physical file, then we aren't in a "1" line marker flag region. SourceLocation IncLoc = PLoc.getIncludeLoc(); @@ -1210,7 +1353,6 @@ void Preprocessor::HandleDigitDirective(Token &DigitTok) { } } - /// HandleUserDiagnosticDirective - Handle a #warning or #error directive. /// void Preprocessor::HandleUserDiagnosticDirective(Token &Tok, @@ -1229,7 +1371,7 @@ void Preprocessor::HandleUserDiagnosticDirective(Token &Tok, // Find the first non-whitespace character, so that we can make the // diagnostic more succinct. - StringRef Msg = StringRef(Message).ltrim(" "); + StringRef Msg = StringRef(Message).ltrim(' '); if (isWarning) Diag(Tok, diag::pp_hash_warning) << Msg; @@ -1276,7 +1418,7 @@ void Preprocessor::HandleIdentSCCSDirective(Token &Tok) { void Preprocessor::HandleMacroPublicDirective(Token &Tok) { Token MacroNameTok; ReadMacroName(MacroNameTok, MU_Undef); - + // Error reading macro name? If so, diagnostic already issued. if (MacroNameTok.is(tok::eod)) return; @@ -1287,13 +1429,13 @@ void Preprocessor::HandleMacroPublicDirective(Token &Tok) { IdentifierInfo *II = MacroNameTok.getIdentifierInfo(); // Okay, we finally have a valid identifier to undef. MacroDirective *MD = getLocalMacroDirective(II); - + // If the macro is not defined, this is an error. if (!MD) { Diag(MacroNameTok, diag::err_pp_visibility_non_macro) << II; return; } - + // Note that this macro has now been exported. appendMacroDirective(II, AllocateVisibilityMacroDirective( MacroNameTok.getLocation(), /*IsPublic=*/true)); @@ -1303,24 +1445,24 @@ void Preprocessor::HandleMacroPublicDirective(Token &Tok) { void Preprocessor::HandleMacroPrivateDirective(Token &Tok) { Token MacroNameTok; ReadMacroName(MacroNameTok, MU_Undef); - + // Error reading macro name? If so, diagnostic already issued. if (MacroNameTok.is(tok::eod)) return; - + // Check to see if this is the last token on the #__private_macro line. CheckEndOfDirective("__private_macro"); - + IdentifierInfo *II = MacroNameTok.getIdentifierInfo(); // Okay, we finally have a valid identifier to undef. MacroDirective *MD = getLocalMacroDirective(II); - + // If the macro is not defined, this is an error. if (!MD) { Diag(MacroNameTok, diag::err_pp_visibility_non_macro) << II; return; } - + // Note that this macro has now been marked private. appendMacroDirective(II, AllocateVisibilityMacroDirective( MacroNameTok.getLocation(), /*IsPublic=*/false)); @@ -1395,7 +1537,7 @@ bool Preprocessor::ConcatenateIncludeName(SmallString<128> &FilenameBuffer, Lex(CurTok); while (CurTok.isNot(tok::eod)) { End = CurTok.getLocation(); - + // FIXME: Provide code completion for #includes. if (CurTok.is(tok::code_completion)) { setCodeCompletionReached(); @@ -1442,13 +1584,13 @@ static void EnterAnnotationToken(Preprocessor &PP, tok::TokenKind Kind, void *AnnotationVal) { // FIXME: Produce this as the current token directly, rather than // allocating a new token for it. - Token *Tok = new Token[1]; + auto Tok = llvm::make_unique<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); + PP.EnterTokenStream(std::move(Tok), 1, true); } /// \brief Produce a diagnostic informing the user that a #include or similar @@ -1466,24 +1608,24 @@ static void diagnoseAutoModuleImport( PathString += Path[I].first->getName(); } int IncludeKind = 0; - + switch (IncludeTok.getIdentifierInfo()->getPPKeywordID()) { case tok::pp_include: IncludeKind = 0; break; - + case tok::pp_import: IncludeKind = 1; - break; - + break; + case tok::pp_include_next: IncludeKind = 2; break; - + case tok::pp___include_macros: IncludeKind = 3; break; - + default: llvm_unreachable("unknown include directive kind"); } @@ -1496,17 +1638,49 @@ static void diagnoseAutoModuleImport( ("@import " + PathString + ";").str()); } +// Given a vector of path components and a string containing the real +// path to the file, build a properly-cased replacement in the vector, +// and return true if the replacement should be suggested. +static bool trySimplifyPath(SmallVectorImpl<StringRef> &Components, + StringRef RealPathName) { + auto RealPathComponentIter = llvm::sys::path::rbegin(RealPathName); + auto RealPathComponentEnd = llvm::sys::path::rend(RealPathName); + int Cnt = 0; + bool SuggestReplacement = false; + // Below is a best-effort to handle ".." in paths. It is admittedly + // not 100% correct in the presence of symlinks. + for (auto &Component : llvm::reverse(Components)) { + if ("." == Component) { + } else if (".." == Component) { + ++Cnt; + } else if (Cnt) { + --Cnt; + } else if (RealPathComponentIter != RealPathComponentEnd) { + if (Component != *RealPathComponentIter) { + // If these path components differ by more than just case, then we + // may be looking at symlinked paths. Bail on this diagnostic to avoid + // noisy false positives. + SuggestReplacement = RealPathComponentIter->equals_lower(Component); + if (!SuggestReplacement) + break; + Component = *RealPathComponentIter; + } + ++RealPathComponentIter; + } + } + return SuggestReplacement; +} + /// 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 /// \#import. LookupFrom is set when this is a \#include_next directive, it /// specifies the file to start searching from. -void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc, +void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc, Token &IncludeTok, const DirectoryLookup *LookupFrom, const FileEntry *LookupFromFile, bool isImport) { - Token FilenameTok; CurPPLexer->LexIncludeFilename(FilenameTok); @@ -1515,7 +1689,7 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc, StringRef Filename; SourceLocation End; SourceLocation CharEnd; // the end of this directive, in characters - + switch (FilenameTok.getKind()) { case tok::eod: // If the token kind is EOD, the error has already been diagnosed. @@ -1586,8 +1760,8 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc, } if (HeaderInfo.HasIncludeAliasMap()) { - // Map the filename with the brackets still attached. If the name doesn't - // map to anything, fall back on the filename we've already gotten the + // Map the filename with the brackets still attached. If the name doesn't + // map to anything, fall back on the filename we've already gotten the // spelling for. StringRef NewName = HeaderInfo.MapHeaderToIncludeAlias(OriginalFilename); if (!NewName.empty()) @@ -1624,7 +1798,7 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc, // Add the recovery path to the list of search paths. DirectoryLookup DL(DE, SrcMgr::C_User, false); HeaderInfo.AddSearchPath(DL, isAngled); - + // Try the lookup again, skipping the cache. File = LookupFile( FilenameLoc, @@ -1636,7 +1810,7 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc, } if (!SuppressIncludeNotFoundError) { - // If the file could not be located and it was included via angle + // 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) { @@ -1649,8 +1823,8 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc, &SuggestedModule); if (File) { SourceRange Range(FilenameTok.getLocation(), CharEnd); - Diag(FilenameTok, diag::err_pp_file_not_found_not_fatal) << - Filename << + Diag(FilenameTok, diag::err_pp_file_not_found_not_fatal) << + Filename << FixItHint::CreateReplacement(Range, "\"" + Filename.str() + "\""); } } @@ -1672,13 +1846,15 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc, // are processing this module textually (because we're building the module). if (File && SuggestedModule && getLangOpts().Modules && SuggestedModule.getModule()->getTopLevelModuleName() != - getLangOpts().CurrentModule && - SuggestedModule.getModule()->getTopLevelModuleName() != - getLangOpts().ImplementationOfModule) { - + getLangOpts().CurrentModule) { // If this include corresponds to a module but that module is // unavailable, diagnose the situation and bail out. - if (!SuggestedModule.getModule()->isAvailable()) { + // FIXME: Remove this; loadModule does the same check (but produces + // slightly worse diagnostics). + if (!SuggestedModule.getModule()->isAvailable() && + !SuggestedModule.getModule() + ->getTopLevelModule() + ->HasIncompatibleModuleFile) { clang::Module::Requirement Requirement; clang::Module::UnresolvedHeaderDirective MissingHeader; Module *M = SuggestedModule.getModule(); @@ -1711,7 +1887,7 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc, // We only do this in Objective-C, where we have a module-import syntax. if (getLangOpts().ObjC2) diagnoseAutoModuleImport(*this, HashLoc, IncludeTok, Path, CharEnd); - + // Load the module to import its macros. We'll make the declarations // visible when the parser gets here. // FIXME: Pass SuggestedModule in here rather than converting it to a path @@ -1759,7 +1935,7 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc, if (!File) return; - + // The #included file will be considered to be a system header if either it is // in a system include directory, or if the #includer is a system include // header. @@ -1770,6 +1946,39 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc, // FIXME: If we have a suggested module, and we've already visited this file, // don't bother entering it again. We know it has no further effect. + // Issue a diagnostic if the name of the file on disk has a different case + // than the one we're about to open. + const bool CheckIncludePathPortability = + File && !File->tryGetRealPathName().empty(); + + if (CheckIncludePathPortability) { + StringRef Name = LangOpts.MSVCCompat ? NormalizedPath.str() : Filename; + StringRef RealPathName = File->tryGetRealPathName(); + SmallVector<StringRef, 16> Components(llvm::sys::path::begin(Name), + llvm::sys::path::end(Name)); + + if (trySimplifyPath(Components, RealPathName)) { + SmallString<128> Path; + Path.reserve(Name.size()+2); + Path.push_back(isAngled ? '<' : '"'); + for (auto Component : Components) { + Path.append(Component); + // Append the separator the user used, or the close quote + Path.push_back( + Path.size() <= Filename.size() ? Filename[Path.size()-1] : + (isAngled ? '>' : '"')); + } + auto Replacement = Path.str().str(); + // For user files and known standard headers, by default we issue a diagnostic. + // For other system headers, we don't. They can be controlled separately. + auto DiagId = (FileCharacter == SrcMgr::C_User || warnByDefaultOnWrongCase(Name)) ? + diag::pp_nonportable_path : diag::pp_nonportable_system_path; + SourceRange Range(FilenameTok.getLocation(), CharEnd); + Diag(FilenameTok, DiagId) << Replacement << + FixItHint::CreateReplacement(Range, Replacement); + } + } + // Ask HeaderInfo if we should enter this #include file. If not, #including // this file will have no effect. if (ShouldEnter && @@ -1863,7 +2072,7 @@ void Preprocessor::HandleMicrosoftImportDirective(Token &Tok) { // so we can continue processing from there. Diag(Tok, diag::err_pp_import_directive_ms ); - // Read tokens until we get to the end of the directive. Note that the + // Read tokens until we get to the end of the directive. Note that the // directive can be split over multiple lines using the backslash character. DiscardUntilEndOfDirective(); } @@ -1930,7 +2139,7 @@ bool Preprocessor::ReadMacroDefinitionArgList(MacroInfo *MI, Token &Tok) { return true; case tok::ellipsis: // #define X(... -> C99 varargs if (!LangOpts.C99) - Diag(Tok, LangOpts.CPlusPlus11 ? + Diag(Tok, LangOpts.CPlusPlus11 ? diag::warn_cxx98_compat_variadic_macro : diag::ext_variadic_macro); @@ -2147,7 +2356,6 @@ void Preprocessor::HandleDefineDirective(Token &DefineTok, // Get the next token of the macro. LexUnexpandedToken(Tok); } - } else { // Otherwise, read the body of a function-like macro. While we are at it, // check C99 6.10.3.2p1: ensure that # operators are followed by macro @@ -2155,7 +2363,7 @@ void Preprocessor::HandleDefineDirective(Token &DefineTok, while (Tok.isNot(tok::eod)) { LastTok = Tok; - if (Tok.isNot(tok::hash) && Tok.isNot(tok::hashhash)) { + if (!Tok.isOneOf(tok::hash, tok::hashat, tok::hashhash)) { MI->AddTokenToBody(Tok); // Get the next token of the macro. @@ -2176,11 +2384,10 @@ void Preprocessor::HandleDefineDirective(Token &DefineTok, } if (Tok.is(tok::hashhash)) { - // If we see token pasting, check if it looks like the gcc comma // pasting extension. We'll use this information to suppress // diagnostics later on. - + // Get the next token of the macro. LexUnexpandedToken(Tok); @@ -2215,7 +2422,8 @@ void Preprocessor::HandleDefineDirective(Token &DefineTok, MI->AddTokenToBody(LastTok); continue; } else { - Diag(Tok, diag::err_pp_stringize_not_parameter); + Diag(Tok, diag::err_pp_stringize_not_parameter) + << LastTok.is(tok::hashat); // Disable __VA_ARGS__ again. Ident__VA_ARGS__->setIsPoisoned(true); @@ -2292,7 +2500,7 @@ void Preprocessor::HandleDefineDirective(Token &DefineTok, if (!OtherMI->isUsed() && OtherMI->isWarnIfUnused()) Diag(OtherMI->getDefinitionLoc(), diag::pp_macro_not_used); - // Warn if defining "__LINE__" and other builtins, per C99 6.10.8/4 and + // Warn if defining "__LINE__" and other builtins, per C99 6.10.8/4 and // C++ [cpp.predefined]p4, but allow it as an extension. if (OtherMI->isBuiltinMacro()) Diag(MacroNameTok, diag::ext_pp_redef_builtin_macro); @@ -2365,7 +2573,6 @@ void Preprocessor::HandleUndefDirective(Token &UndefTok) { AllocateUndefMacroDirective(MacroNameTok.getLocation())); } - //===----------------------------------------------------------------------===// // Preprocessor Conditional Directive Handling. //===----------------------------------------------------------------------===// @@ -2554,7 +2761,7 @@ void Preprocessor::HandleElifDirective(Token &ElifToken) { // If this is a #elif with a #else before it, report the error. if (CI.FoundElse) Diag(ElifToken, diag::pp_err_elif_after_else); - + if (Callbacks) Callbacks->Elif(ElifToken.getLocation(), SourceRange(ConditionalBegin, ConditionalEnd), diff --git a/lib/Lex/PPExpressions.cpp b/lib/Lex/PPExpressions.cpp index c40598c06756..94075ece35ca 100644 --- a/lib/Lex/PPExpressions.cpp +++ b/lib/Lex/PPExpressions.cpp @@ -33,12 +33,18 @@ namespace { /// conditional and the source range covered by it. class PPValue { SourceRange Range; + IdentifierInfo *II; public: llvm::APSInt Val; // Default ctor - Construct an 'invalid' PPValue. PPValue(unsigned BitWidth) : Val(BitWidth) {} + // If this value was produced by directly evaluating an identifier, produce + // that identifier. + IdentifierInfo *getIdentifier() const { return II; } + void setIdentifier(IdentifierInfo *II) { this->II = II; } + unsigned getBitWidth() const { return Val.getBitWidth(); } bool isUnsigned() const { return Val.isUnsigned(); } @@ -140,6 +146,51 @@ static bool EvaluateDefined(PPValue &Result, Token &PeekTok, DefinedTracker &DT, PP.LexNonComment(PeekTok); } + // [cpp.cond]p4: + // Prior to evaluation, macro invocations in the list of preprocessing + // tokens that will become the controlling constant expression are replaced + // (except for those macro names modified by the 'defined' unary operator), + // just as in normal text. If the token 'defined' is generated as a result + // of this replacement process or use of the 'defined' unary operator does + // not match one of the two specified forms prior to macro replacement, the + // behavior is undefined. + // This isn't an idle threat, consider this program: + // #define FOO + // #define BAR defined(FOO) + // #if BAR + // ... + // #else + // ... + // #endif + // clang and gcc will pick the #if branch while Visual Studio will take the + // #else branch. Emit a warning about this undefined behavior. + if (beginLoc.isMacroID()) { + bool IsFunctionTypeMacro = + PP.getSourceManager() + .getSLocEntry(PP.getSourceManager().getFileID(beginLoc)) + .getExpansion() + .isFunctionMacroExpansion(); + // For object-type macros, it's easy to replace + // #define FOO defined(BAR) + // with + // #if defined(BAR) + // #define FOO 1 + // #else + // #define FOO 0 + // #endif + // and doing so makes sense since compilers handle this differently in + // practice (see example further up). But for function-type macros, + // there is no good way to write + // # define FOO(x) (defined(M_ ## x) && M_ ## x) + // in a different way, and compilers seem to agree on how to behave here. + // So warn by default on object-type macros, but only warn in -pedantic + // mode on function-type macros. + if (IsFunctionTypeMacro) + PP.Diag(beginLoc, diag::warn_defined_in_function_type_macro); + else + PP.Diag(beginLoc, diag::warn_defined_in_object_type_macro); + } + // Invoke the 'defined' callback. if (PPCallbacks *Callbacks = PP.getPPCallbacks()) { Callbacks->Defined(macroToken, Macro, @@ -164,6 +215,8 @@ static bool EvaluateValue(PPValue &Result, Token &PeekTok, DefinedTracker &DT, bool ValueLive, Preprocessor &PP) { DT.State = DefinedTracker::Unknown; + Result.setIdentifier(nullptr); + if (PeekTok.is(tok::code_completion)) { if (PP.getCodeCompletionHandler()) PP.getCodeCompletionHandler()->CodeCompletePreprocessorExpression(); @@ -177,8 +230,8 @@ static bool EvaluateValue(PPValue &Result, Token &PeekTok, DefinedTracker &DT, if (IdentifierInfo *II = PeekTok.getIdentifierInfo()) { // Handle "defined X" and "defined(X)". if (II->isStr("defined")) - return(EvaluateDefined(Result, PeekTok, DT, ValueLive, PP)); - + return EvaluateDefined(Result, PeekTok, DT, ValueLive, PP); + // If this identifier isn't 'defined' or one of the special // preprocessor keywords and it wasn't macro expanded, it turns // into a simple 0, unless it is the C++ keyword "true", in which case it @@ -189,6 +242,7 @@ static bool EvaluateValue(PPValue &Result, Token &PeekTok, DefinedTracker &DT, PP.Diag(PeekTok, diag::warn_pp_undef_identifier) << II; Result.Val = II->getTokenID() == tok::kw_true; Result.Val.setIsUnsigned(false); // "0" is signed intmax_t 0. + Result.setIdentifier(II); Result.setRange(PeekTok.getLocation()); PP.LexNonComment(PeekTok); return false; @@ -347,6 +401,7 @@ static bool EvaluateValue(PPValue &Result, Token &PeekTok, DefinedTracker &DT, DT.State = DefinedTracker::Unknown; } Result.setRange(Start, PeekTok.getLocation()); + Result.setIdentifier(nullptr); PP.LexNonComment(PeekTok); // Eat the ). return false; } @@ -356,6 +411,7 @@ static bool EvaluateValue(PPValue &Result, Token &PeekTok, DefinedTracker &DT, PP.LexNonComment(PeekTok); if (EvaluateValue(Result, PeekTok, DT, ValueLive, PP)) return true; Result.setBegin(Start); + Result.setIdentifier(nullptr); return false; } case tok::minus: { @@ -363,6 +419,7 @@ static bool EvaluateValue(PPValue &Result, Token &PeekTok, DefinedTracker &DT, PP.LexNonComment(PeekTok); if (EvaluateValue(Result, PeekTok, DT, ValueLive, PP)) return true; Result.setBegin(Loc); + Result.setIdentifier(nullptr); // C99 6.5.3.3p3: The sign of the result matches the sign of the operand. Result.Val = -Result.Val; @@ -383,6 +440,7 @@ static bool EvaluateValue(PPValue &Result, Token &PeekTok, DefinedTracker &DT, PP.LexNonComment(PeekTok); if (EvaluateValue(Result, PeekTok, DT, ValueLive, PP)) return true; Result.setBegin(Start); + Result.setIdentifier(nullptr); // C99 6.5.3.3p4: The sign of the result matches the sign of the operand. Result.Val = ~Result.Val; @@ -398,6 +456,7 @@ static bool EvaluateValue(PPValue &Result, Token &PeekTok, DefinedTracker &DT, Result.Val = !Result.Val; // C99 6.5.3.3p5: The sign of the result is 'int', aka it is signed. Result.Val.setIsUnsigned(false); + Result.setIdentifier(nullptr); if (DT.State == DefinedTracker::DefinedMacro) DT.State = DefinedTracker::NotDefinedMacro; @@ -446,6 +505,15 @@ static unsigned getPrecedence(tok::TokenKind Kind) { } } +static void diagnoseUnexpectedOperator(Preprocessor &PP, PPValue &LHS, + Token &Tok) { + if (Tok.is(tok::l_paren) && LHS.getIdentifier()) + PP.Diag(LHS.getRange().getBegin(), diag::err_pp_expr_bad_token_lparen) + << LHS.getIdentifier(); + else + PP.Diag(Tok.getLocation(), diag::err_pp_expr_bad_token_binop) + << LHS.getRange(); +} /// EvaluateDirectiveSubExpr - Evaluate the subexpression whose first token is /// PeekTok, and whose precedence is PeekPrec. This returns the result in LHS. @@ -459,8 +527,7 @@ static bool EvaluateDirectiveSubExpr(PPValue &LHS, unsigned MinPrec, unsigned PeekPrec = getPrecedence(PeekTok.getKind()); // If this token isn't valid, report the error. if (PeekPrec == ~0U) { - PP.Diag(PeekTok.getLocation(), diag::err_pp_expr_bad_token_binop) - << LHS.getRange(); + diagnoseUnexpectedOperator(PP, LHS, PeekTok); return true; } @@ -503,8 +570,7 @@ static bool EvaluateDirectiveSubExpr(PPValue &LHS, unsigned MinPrec, // If this token isn't valid, report the error. if (PeekPrec == ~0U) { - PP.Diag(PeekTok.getLocation(), diag::err_pp_expr_bad_token_binop) - << RHS.getRange(); + diagnoseUnexpectedOperator(PP, RHS, PeekTok); return true; } @@ -605,8 +671,10 @@ static bool EvaluateDirectiveSubExpr(PPValue &LHS, unsigned MinPrec, case tok::greatergreater: { // Determine whether overflow is about to happen. unsigned ShAmt = static_cast<unsigned>(RHS.Val.getLimitedValue()); - if (ShAmt >= LHS.getBitWidth()) - Overflow = true, ShAmt = LHS.getBitWidth()-1; + if (ShAmt >= LHS.getBitWidth()) { + Overflow = true; + ShAmt = LHS.getBitWidth()-1; + } Res = LHS.Val >> ShAmt; break; } @@ -722,6 +790,7 @@ static bool EvaluateDirectiveSubExpr(PPValue &LHS, unsigned MinPrec, // Put the result back into 'LHS' for our next iteration. LHS.Val = Res; LHS.setEnd(RHS.getRange().getEnd()); + RHS.setIdentifier(nullptr); } } diff --git a/lib/Lex/PPLexerChange.cpp b/lib/Lex/PPLexerChange.cpp index 2f09841c5b5d..e2eceafd983b 100644 --- a/lib/Lex/PPLexerChange.cpp +++ b/lib/Lex/PPLexerChange.cpp @@ -622,8 +622,8 @@ void Preprocessor::HandleMicrosoftCommentPaste(Token &Tok) { void Preprocessor::EnterSubmodule(Module *M, SourceLocation ImportLoc) { if (!getLangOpts().ModulesLocalVisibility) { // Just track that we entered this submodule. - BuildingSubmoduleStack.push_back( - BuildingSubmoduleInfo(M, ImportLoc, CurSubmoduleState)); + BuildingSubmoduleStack.push_back(BuildingSubmoduleInfo( + M, ImportLoc, CurSubmoduleState, PendingModuleMacroNames.size())); return; } @@ -664,8 +664,8 @@ void Preprocessor::EnterSubmodule(Module *M, SourceLocation ImportLoc) { } // Track that we entered this module. - BuildingSubmoduleStack.push_back( - BuildingSubmoduleInfo(M, ImportLoc, CurSubmoduleState)); + BuildingSubmoduleStack.push_back(BuildingSubmoduleInfo( + M, ImportLoc, CurSubmoduleState, PendingModuleMacroNames.size())); // Switch to this submodule as the current submodule. CurSubmoduleState = &State; @@ -675,42 +675,79 @@ void Preprocessor::EnterSubmodule(Module *M, SourceLocation ImportLoc) { makeModuleVisible(M, ImportLoc); } +bool Preprocessor::needModuleMacros() const { + // If we're not within a submodule, we never need to create ModuleMacros. + if (BuildingSubmoduleStack.empty()) + return false; + // If we are tracking module macro visibility even for textually-included + // headers, we need ModuleMacros. + if (getLangOpts().ModulesLocalVisibility) + return true; + // Otherwise, we only need module macros if we're actually compiling a module + // interface. + return getLangOpts().CompilingModule; +} + void Preprocessor::LeaveSubmodule() { auto &Info = BuildingSubmoduleStack.back(); Module *LeavingMod = Info.M; SourceLocation ImportLoc = Info.ImportLoc; + if (!needModuleMacros() || + (!getLangOpts().ModulesLocalVisibility && + LeavingMod->getTopLevelModuleName() != getLangOpts().CurrentModule)) { + // If we don't need module macros, or this is not a module for which we + // are tracking macro visibility, don't build any, and preserve the list + // of pending names for the surrounding submodule. + BuildingSubmoduleStack.pop_back(); + makeModuleVisible(LeavingMod, ImportLoc); + return; + } + // Create ModuleMacros for any macros defined in this submodule. - for (auto &Macro : CurSubmoduleState->Macros) { - auto *II = const_cast<IdentifierInfo*>(Macro.first); + llvm::SmallPtrSet<const IdentifierInfo*, 8> VisitedMacros; + for (unsigned I = Info.OuterPendingModuleMacroNames; + I != PendingModuleMacroNames.size(); ++I) { + auto *II = const_cast<IdentifierInfo*>(PendingModuleMacroNames[I]); + if (!VisitedMacros.insert(II).second) + continue; + + auto MacroIt = CurSubmoduleState->Macros.find(II); + if (MacroIt == CurSubmoduleState->Macros.end()) + continue; + auto &Macro = MacroIt->second; // Find the starting point for the MacroDirective chain in this submodule. MacroDirective *OldMD = nullptr; - if (getLangOpts().ModulesLocalVisibility) { + auto *OldState = Info.OuterSubmoduleState; + if (getLangOpts().ModulesLocalVisibility) + OldState = &NullSubmoduleState; + if (OldState && OldState != CurSubmoduleState) { // FIXME: It'd be better to start at the state from when we most recently // entered this submodule, but it doesn't really matter. - auto &PredefMacros = NullSubmoduleState.Macros; - auto PredefMacroIt = PredefMacros.find(Macro.first); - if (PredefMacroIt == PredefMacros.end()) + auto &OldMacros = OldState->Macros; + auto OldMacroIt = OldMacros.find(II); + if (OldMacroIt == OldMacros.end()) OldMD = nullptr; else - OldMD = PredefMacroIt->second.getLatest(); + OldMD = OldMacroIt->second.getLatest(); } // This module may have exported a new macro. If so, create a ModuleMacro // representing that fact. bool ExplicitlyPublic = false; - for (auto *MD = Macro.second.getLatest(); MD != OldMD; - MD = MD->getPrevious()) { + for (auto *MD = Macro.getLatest(); MD != OldMD; MD = MD->getPrevious()) { assert(MD && "broken macro directive chain"); - // Stop on macros defined in other submodules we #included along the way. - // There's no point doing this if we're tracking local submodule - // visibility, since there can be no such directives in our list. + // Stop on macros defined in other submodules of this module that we + // #included along the way. There's no point doing this if we're + // tracking local submodule visibility, since there can be no such + // directives in our list. if (!getLangOpts().ModulesLocalVisibility) { Module *Mod = getModuleContainingLocation(MD->getLocation()); - if (Mod != LeavingMod) + if (Mod != LeavingMod && + Mod->getTopLevelModule() == LeavingMod->getTopLevelModule()) break; } @@ -732,13 +769,14 @@ void Preprocessor::LeaveSubmodule() { bool IsNew; // Don't bother creating a module macro if it would represent a #undef // that doesn't override anything. - if (Def || !Macro.second.getOverriddenMacros().empty()) + if (Def || !Macro.getOverriddenMacros().empty()) addModuleMacro(LeavingMod, II, Def, - Macro.second.getOverriddenMacros(), IsNew); + Macro.getOverriddenMacros(), IsNew); break; } } } + PendingModuleMacroNames.resize(Info.OuterPendingModuleMacroNames); // FIXME: Before we leave this submodule, we should parse all the other // headers within it. Otherwise, we're left with an inconsistent state diff --git a/lib/Lex/PPMacroExpansion.cpp b/lib/Lex/PPMacroExpansion.cpp index 18348df0a39e..2ade6df9456a 100644 --- a/lib/Lex/PPMacroExpansion.cpp +++ b/lib/Lex/PPMacroExpansion.cpp @@ -52,6 +52,13 @@ void Preprocessor::appendMacroDirective(IdentifierInfo *II, MacroDirective *MD){ StoredMD.setLatest(MD); StoredMD.overrideActiveModuleMacros(*this, II); + if (needModuleMacros()) { + // Track that we created a new macro directive, so we know we should + // consider building a ModuleMacro for it when we get to the end of + // the module. + PendingModuleMacroNames.push_back(II); + } + // Set up the identifier as having associated macro history. II->setHasMacroDefinition(true); if (!MD->isDefined() && LeafModuleMacros.find(II) == LeafModuleMacros.end()) @@ -323,18 +330,11 @@ void Preprocessor::RegisterBuiltinMacros() { Ident__is_identifier = RegisterBuiltinMacro(*this, "__is_identifier"); // Modules. - if (LangOpts.Modules) { - Ident__building_module = RegisterBuiltinMacro(*this, "__building_module"); - - // __MODULE__ - if (!LangOpts.CurrentModule.empty()) - Ident__MODULE__ = RegisterBuiltinMacro(*this, "__MODULE__"); - else - Ident__MODULE__ = nullptr; - } else { - Ident__building_module = nullptr; + Ident__building_module = RegisterBuiltinMacro(*this, "__building_module"); + if (!LangOpts.CurrentModule.empty()) + Ident__MODULE__ = RegisterBuiltinMacro(*this, "__MODULE__"); + else Ident__MODULE__ = nullptr; - } } /// isTrivialSingleTokenExpansion - Return true if MI, which has a single token @@ -723,6 +723,7 @@ MacroArgs *Preprocessor::ReadFunctionLikeMacroArgs(Token &MacroName, // heap allocations in the common case. SmallVector<Token, 64> ArgTokens; bool ContainsCodeCompletionTok = false; + bool FoundElidedComma = false; SourceLocation TooManyArgsLoc; @@ -754,17 +755,20 @@ MacroArgs *Preprocessor::ReadFunctionLikeMacroArgs(Token &MacroName, // Do not lose the EOF/EOD. Return it to the client. MacroName = Tok; return nullptr; - } else { - // Do not lose the EOF/EOD. - Token *Toks = new Token[1]; - Toks[0] = Tok; - EnterTokenStream(Toks, 1, true, true); - break; } + // Do not lose the EOF/EOD. + auto Toks = llvm::make_unique<Token[]>(1); + Toks[0] = Tok; + EnterTokenStream(std::move(Toks), 1, true); + break; } else if (Tok.is(tok::r_paren)) { // If we found the ) token, the macro arg list is done. if (NumParens-- == 0) { MacroEnd = Tok.getLocation(); + if (!ArgTokens.empty() && + ArgTokens.back().commaAfterElided()) { + FoundElidedComma = true; + } break; } } else if (Tok.is(tok::l_paren)) { @@ -909,7 +913,7 @@ MacroArgs *Preprocessor::ReadFunctionLikeMacroArgs(Token &MacroName, // then we have an empty "()" argument empty list. This is fine, even if // the macro expects one argument (the argument is just empty). isVarargsElided = MI->isVariadic(); - } else if (MI->isVariadic() && + } else if ((FoundElidedComma || MI->isVariadic()) && (NumActuals+1 == MinArgsExpected || // A(x, ...) -> A(X) (NumActuals == 0 && MinArgsExpected == 2))) {// A(x,...) -> A() // Varargs where the named vararg parameter is missing: OK as extension. @@ -1042,9 +1046,8 @@ static void ComputeDATE_TIME(SourceLocation &DATELoc, SourceLocation &TIMELoc, /// HasFeature - Return true if we recognize and implement the feature /// specified by the identifier as a standard language feature. -static bool HasFeature(const Preprocessor &PP, const IdentifierInfo *II) { +static bool HasFeature(const Preprocessor &PP, StringRef Feature) { const LangOptions &LangOpts = PP.getLangOpts(); - StringRef Feature = II->getName(); // Normalize the feature name, __foo__ becomes foo. if (Feature.startswith("__") && Feature.endswith("__") && Feature.size() >= 4) @@ -1062,10 +1065,14 @@ static bool HasFeature(const Preprocessor &PP, const IdentifierInfo *II) { .Case("attribute_availability_with_version_underscores", true) .Case("attribute_availability_tvos", true) .Case("attribute_availability_watchos", true) + .Case("attribute_availability_with_strict", true) + .Case("attribute_availability_with_replacement", true) + .Case("attribute_availability_in_templates", true) .Case("attribute_cf_returns_not_retained", true) .Case("attribute_cf_returns_retained", true) .Case("attribute_cf_returns_on_parameters", true) .Case("attribute_deprecated_with_message", true) + .Case("attribute_deprecated_with_replacement", true) .Case("attribute_ext_vector_type", true) .Case("attribute_ns_returns_not_retained", true) .Case("attribute_ns_returns_retained", true) @@ -1086,6 +1093,8 @@ static bool HasFeature(const Preprocessor &PP, const IdentifierInfo *II) { .Case("memory_sanitizer", LangOpts.Sanitize.has(SanitizerKind::Memory)) .Case("thread_sanitizer", LangOpts.Sanitize.has(SanitizerKind::Thread)) .Case("dataflow_sanitizer", LangOpts.Sanitize.has(SanitizerKind::DataFlow)) + .Case("efficiency_sanitizer", + LangOpts.Sanitize.hasOneOf(SanitizerKind::Efficiency)) // Objective-C features .Case("objc_arr", LangOpts.ObjCAutoRefCount) // FIXME: REMOVE? .Case("objc_arc", LangOpts.ObjCAutoRefCount) @@ -1114,6 +1123,7 @@ static bool HasFeature(const Preprocessor &PP, const IdentifierInfo *II) { .Case("objc_bridge_id_on_typedefs", true) .Case("objc_generics", LangOpts.ObjC2) .Case("objc_generics_variance", LangOpts.ObjC2) + .Case("objc_class_property", LangOpts.ObjC2) // C11 features .Case("c_alignas", LangOpts.C11) .Case("c_alignof", LangOpts.C11) @@ -1177,6 +1187,8 @@ static bool HasFeature(const Preprocessor &PP, const IdentifierInfo *II) { // FIXME: Should this be __has_feature or __has_extension? //.Case("raw_invocation_type", LangOpts.CPlusPlus) // Type traits + // N.B. Additional type traits should not be added to the following list. + // Instead, they should be detected by has_extension. .Case("has_nothrow_assign", LangOpts.CPlusPlus) .Case("has_nothrow_copy", LangOpts.CPlusPlus) .Case("has_nothrow_constructor", LangOpts.CPlusPlus) @@ -1197,7 +1209,7 @@ static bool HasFeature(const Preprocessor &PP, const IdentifierInfo *II) { .Case("is_standard_layout", LangOpts.CPlusPlus) .Case("is_pod", LangOpts.CPlusPlus) .Case("is_polymorphic", LangOpts.CPlusPlus) - .Case("is_sealed", LangOpts.MicrosoftExt) + .Case("is_sealed", LangOpts.CPlusPlus && LangOpts.MicrosoftExt) .Case("is_trivial", LangOpts.CPlusPlus) .Case("is_trivially_assignable", LangOpts.CPlusPlus) .Case("is_trivially_constructible", LangOpts.CPlusPlus) @@ -1213,8 +1225,8 @@ static bool HasFeature(const Preprocessor &PP, const IdentifierInfo *II) { /// HasExtension - Return true if we recognize and implement the feature /// specified by the identifier, either as an extension or a standard language /// feature. -static bool HasExtension(const Preprocessor &PP, const IdentifierInfo *II) { - if (HasFeature(PP, II)) +static bool HasExtension(const Preprocessor &PP, StringRef Extension) { + if (HasFeature(PP, Extension)) return true; // If the use of an extension results in an error diagnostic, extensions are @@ -1224,7 +1236,6 @@ static bool HasExtension(const Preprocessor &PP, const IdentifierInfo *II) { return false; const LangOptions &LangOpts = PP.getLangOpts(); - StringRef Extension = II->getName(); // Normalize the extension name, __foo__ becomes foo. if (Extension.startswith("__") && Extension.endswith("__") && @@ -1408,47 +1419,120 @@ static bool EvaluateHasIncludeNext(Token &Tok, return EvaluateHasIncludeCommon(Tok, II, PP, Lookup, LookupFromFile); } -/// \brief Process __building_module(identifier) expression. -/// \returns true if we are building the named module, false otherwise. -static bool EvaluateBuildingModule(Token &Tok, - IdentifierInfo *II, Preprocessor &PP) { - // Get '('. - PP.LexNonComment(Tok); - - // Ensure we have a '('. +/// \brief Process single-argument builtin feature-like macros that return +/// integer values. +static void EvaluateFeatureLikeBuiltinMacro(llvm::raw_svector_ostream& OS, + Token &Tok, IdentifierInfo *II, + Preprocessor &PP, + llvm::function_ref< + int(Token &Tok, + bool &HasLexedNextTok)> Op) { + // Parse the initial '('. + PP.LexUnexpandedToken(Tok); if (Tok.isNot(tok::l_paren)) { PP.Diag(Tok.getLocation(), diag::err_pp_expected_after) << II << tok::l_paren; - return false; + + // Provide a dummy '0' value on output stream to elide further errors. + if (!Tok.isOneOf(tok::eof, tok::eod)) { + OS << 0; + Tok.setKind(tok::numeric_constant); + } + return; } - // Save '(' location for possible missing ')' message. + unsigned ParenDepth = 1; SourceLocation LParenLoc = Tok.getLocation(); + llvm::Optional<int> Result; - // Get the module name. - PP.LexNonComment(Tok); + Token ResultTok; + bool SuppressDiagnostic = false; + while (true) { + // Parse next token. + PP.LexUnexpandedToken(Tok); - // Ensure that we have an identifier. - if (Tok.isNot(tok::identifier)) { - PP.Diag(Tok.getLocation(), diag::err_expected_id_building_module); - return false; - } +already_lexed: + switch (Tok.getKind()) { + case tok::eof: + case tok::eod: + // Don't provide even a dummy value if the eod or eof marker is + // reached. Simply provide a diagnostic. + PP.Diag(Tok.getLocation(), diag::err_unterm_macro_invoc); + return; - bool Result - = Tok.getIdentifierInfo()->getName() == PP.getLangOpts().CurrentModule; + case tok::comma: + if (!SuppressDiagnostic) { + PP.Diag(Tok.getLocation(), diag::err_too_many_args_in_macro_invoc); + SuppressDiagnostic = true; + } + continue; - // Get ')'. - PP.LexNonComment(Tok); + case tok::l_paren: + ++ParenDepth; + if (Result.hasValue()) + break; + if (!SuppressDiagnostic) { + PP.Diag(Tok.getLocation(), diag::err_pp_nested_paren) << II; + SuppressDiagnostic = true; + } + continue; - // Ensure we have a trailing ). - if (Tok.isNot(tok::r_paren)) { - PP.Diag(Tok.getLocation(), diag::err_pp_expected_after) << II - << tok::r_paren; - PP.Diag(LParenLoc, diag::note_matching) << tok::l_paren; - return false; + case tok::r_paren: + if (--ParenDepth > 0) + continue; + + // The last ')' has been reached; return the value if one found or + // a diagnostic and a dummy value. + if (Result.hasValue()) + OS << Result.getValue(); + else { + OS << 0; + if (!SuppressDiagnostic) + PP.Diag(Tok.getLocation(), diag::err_too_few_args_in_macro_invoc); + } + Tok.setKind(tok::numeric_constant); + return; + + default: { + // Parse the macro argument, if one not found so far. + if (Result.hasValue()) + break; + + bool HasLexedNextToken = false; + Result = Op(Tok, HasLexedNextToken); + ResultTok = Tok; + if (HasLexedNextToken) + goto already_lexed; + continue; + } + } + + // Diagnose missing ')'. + if (!SuppressDiagnostic) { + if (auto Diag = PP.Diag(Tok.getLocation(), diag::err_pp_expected_after)) { + if (IdentifierInfo *LastII = ResultTok.getIdentifierInfo()) + Diag << LastII; + else + Diag << ResultTok.getKind(); + Diag << tok::r_paren << ResultTok.getLocation(); + } + PP.Diag(LParenLoc, diag::note_matching) << tok::l_paren; + SuppressDiagnostic = true; + } } +} - return Result; +/// \brief Helper function to return the IdentifierInfo structure of a Token +/// or generate a diagnostic if none available. +static IdentifierInfo *ExpectFeatureIdentifierInfo(Token &Tok, + Preprocessor &PP, + signed DiagID) { + IdentifierInfo *II; + if (!Tok.isAnnotation() && (II = Tok.getIdentifierInfo())) + return II; + + PP.Diag(Tok.getLocation(), DiagID); + return nullptr; } /// ExpandBuiltinMacro - If an identifier token is read that is to be expanded @@ -1584,84 +1668,82 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) { // __COUNTER__ expands to a simple numeric value. OS << CounterValue++; Tok.setKind(tok::numeric_constant); - } else if (II == Ident__has_feature || - II == Ident__has_extension || - II == Ident__has_builtin || - II == Ident__is_identifier || - II == Ident__has_attribute || - II == Ident__has_declspec || - II == Ident__has_cpp_attribute) { - // The argument to these builtins should be a parenthesized identifier. - SourceLocation StartLoc = Tok.getLocation(); - - bool IsValid = false; - IdentifierInfo *FeatureII = nullptr; - IdentifierInfo *ScopeII = nullptr; + } else if (II == Ident__has_feature) { + EvaluateFeatureLikeBuiltinMacro(OS, Tok, II, *this, + [this](Token &Tok, bool &HasLexedNextToken) -> int { + IdentifierInfo *II = ExpectFeatureIdentifierInfo(Tok, *this, + diag::err_feature_check_malformed); + return II && HasFeature(*this, II->getName()); + }); + } else if (II == Ident__has_extension) { + EvaluateFeatureLikeBuiltinMacro(OS, Tok, II, *this, + [this](Token &Tok, bool &HasLexedNextToken) -> int { + IdentifierInfo *II = ExpectFeatureIdentifierInfo(Tok, *this, + diag::err_feature_check_malformed); + return II && HasExtension(*this, II->getName()); + }); + } else if (II == Ident__has_builtin) { + EvaluateFeatureLikeBuiltinMacro(OS, Tok, II, *this, + [this](Token &Tok, bool &HasLexedNextToken) -> int { + IdentifierInfo *II = ExpectFeatureIdentifierInfo(Tok, *this, + diag::err_feature_check_malformed); + if (!II) + return false; + else if (II->getBuiltinID() != 0) + return true; + else { + const LangOptions &LangOpts = getLangOpts(); + return llvm::StringSwitch<bool>(II->getName()) + .Case("__make_integer_seq", LangOpts.CPlusPlus) + .Case("__type_pack_element", LangOpts.CPlusPlus) + .Default(false); + } + }); + } else if (II == Ident__is_identifier) { + EvaluateFeatureLikeBuiltinMacro(OS, Tok, II, *this, + [](Token &Tok, bool &HasLexedNextToken) -> int { + return Tok.is(tok::identifier); + }); + } else if (II == Ident__has_attribute) { + EvaluateFeatureLikeBuiltinMacro(OS, Tok, II, *this, + [this](Token &Tok, bool &HasLexedNextToken) -> int { + IdentifierInfo *II = ExpectFeatureIdentifierInfo(Tok, *this, + diag::err_feature_check_malformed); + return II ? hasAttribute(AttrSyntax::GNU, nullptr, II, + getTargetInfo(), getLangOpts()) : 0; + }); + } else if (II == Ident__has_declspec) { + EvaluateFeatureLikeBuiltinMacro(OS, Tok, II, *this, + [this](Token &Tok, bool &HasLexedNextToken) -> int { + IdentifierInfo *II = ExpectFeatureIdentifierInfo(Tok, *this, + diag::err_feature_check_malformed); + return II ? hasAttribute(AttrSyntax::Declspec, nullptr, II, + getTargetInfo(), getLangOpts()) : 0; + }); + } else if (II == Ident__has_cpp_attribute) { + EvaluateFeatureLikeBuiltinMacro(OS, Tok, II, *this, + [this](Token &Tok, bool &HasLexedNextToken) -> int { + IdentifierInfo *ScopeII = nullptr; + IdentifierInfo *II = ExpectFeatureIdentifierInfo(Tok, *this, + diag::err_feature_check_malformed); + if (!II) + return false; - // Read the '('. - LexUnexpandedToken(Tok); - if (Tok.is(tok::l_paren)) { - // Read the identifier - LexUnexpandedToken(Tok); - if ((FeatureII = Tok.getIdentifierInfo())) { - // If we're checking __has_cpp_attribute, it is possible to receive a - // scope token. Read the "::", if it's available. + // It is possible to receive a scope token. Read the "::", if it is + // available, and the subsequent identifier. LexUnexpandedToken(Tok); - bool IsScopeValid = true; - if (II == Ident__has_cpp_attribute && Tok.is(tok::coloncolon)) { + if (Tok.isNot(tok::coloncolon)) + HasLexedNextToken = true; + else { + ScopeII = II; LexUnexpandedToken(Tok); - // The first thing we read was not the feature, it was the scope. - ScopeII = FeatureII; - if ((FeatureII = Tok.getIdentifierInfo())) - LexUnexpandedToken(Tok); - else - IsScopeValid = false; + II = ExpectFeatureIdentifierInfo(Tok, *this, + diag::err_feature_check_malformed); } - // Read the closing paren. - if (IsScopeValid && Tok.is(tok::r_paren)) - IsValid = true; - } - // Eat tokens until ')'. - while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::eod) && - Tok.isNot(tok::eof)) - LexUnexpandedToken(Tok); - } - - int Value = 0; - 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. - if (FeatureII->getBuiltinID() != 0) { - Value = true; - } else { - StringRef Feature = FeatureII->getName(); - Value = llvm::StringSwitch<bool>(Feature) - .Case("__make_integer_seq", getLangOpts().CPlusPlus) - .Default(false); - } - } else if (II == Ident__has_attribute) - Value = hasAttribute(AttrSyntax::GNU, nullptr, FeatureII, - getTargetInfo(), getLangOpts()); - else if (II == Ident__has_cpp_attribute) - Value = hasAttribute(AttrSyntax::CXX, ScopeII, FeatureII, - getTargetInfo(), getLangOpts()); - else if (II == Ident__has_declspec) - Value = hasAttribute(AttrSyntax::Declspec, nullptr, FeatureII, - getTargetInfo(), getLangOpts()); - else if (II == Ident__has_extension) - Value = HasExtension(*this, FeatureII); - else { - assert(II == Ident__has_feature && "Must be feature check"); - Value = HasFeature(*this, FeatureII); - } - if (!IsValid) - return; - OS << Value; - Tok.setKind(tok::numeric_constant); + return II ? hasAttribute(AttrSyntax::CXX, ScopeII, II, + getTargetInfo(), getLangOpts()) : 0; + }); } else if (II == Ident__has_include || II == Ident__has_include_next) { // The argument to these two builtins should be a parenthesized @@ -1679,64 +1761,44 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) { Tok.setKind(tok::numeric_constant); } else if (II == Ident__has_warning) { // The argument should be a parenthesized string literal. - // The argument to these builtins should be a parenthesized identifier. - SourceLocation StartLoc = Tok.getLocation(); - bool IsValid = false; - bool Value = false; - // Read the '('. - LexUnexpandedToken(Tok); - do { - if (Tok.isNot(tok::l_paren)) { - Diag(StartLoc, diag::err_warning_check_malformed); - break; - } + EvaluateFeatureLikeBuiltinMacro(OS, Tok, II, *this, + [this](Token &Tok, bool &HasLexedNextToken) -> int { + std::string WarningName; + SourceLocation StrStartLoc = Tok.getLocation(); - LexUnexpandedToken(Tok); - std::string WarningName; - SourceLocation StrStartLoc = Tok.getLocation(); - if (!FinishLexStringLiteral(Tok, WarningName, "'__has_warning'", - /*MacroExpansion=*/false)) { - // Eat tokens until ')'. - while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::eod) && - Tok.isNot(tok::eof)) - LexUnexpandedToken(Tok); - break; - } + HasLexedNextToken = Tok.is(tok::string_literal); + if (!FinishLexStringLiteral(Tok, WarningName, "'__has_warning'", + /*MacroExpansion=*/false)) + return false; - // Is the end a ')'? - if (!(IsValid = Tok.is(tok::r_paren))) { - Diag(StartLoc, diag::err_warning_check_malformed); - 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); - break; - } - - // Finally, check if the warning flags maps to a diagnostic group. - // We construct a SmallVector here to talk to getDiagnosticIDs(). - // Although we don't use the result, this isn't a hot path, and not - // worth special casing. - SmallVector<diag::kind, 10> Diags; - Value = !getDiagnostics().getDiagnosticIDs()-> - getDiagnosticsInGroup(diag::Flavor::WarningOrError, - WarningName.substr(2), Diags); - } while (false); + // 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); + return false; + } - if (!IsValid) - return; - OS << (int)Value; - Tok.setKind(tok::numeric_constant); + // Finally, check if the warning flags maps to a diagnostic group. + // We construct a SmallVector here to talk to getDiagnosticIDs(). + // Although we don't use the result, this isn't a hot path, and not + // worth special casing. + SmallVector<diag::kind, 10> Diags; + return !getDiagnostics().getDiagnosticIDs()-> + getDiagnosticsInGroup(diag::Flavor::WarningOrError, + WarningName.substr(2), Diags); + }); } else if (II == Ident__building_module) { // The argument to this builtin should be an identifier. The // builtin evaluates to 1 when that identifier names the module we are // currently building. - OS << (int)EvaluateBuildingModule(Tok, II, *this); - Tok.setKind(tok::numeric_constant); + EvaluateFeatureLikeBuiltinMacro(OS, Tok, II, *this, + [this](Token &Tok, bool &HasLexedNextToken) -> int { + IdentifierInfo *II = ExpectFeatureIdentifierInfo(Tok, *this, + diag::err_expected_id_building_module); + return getLangOpts().CompilingModule && II && + (II->getName() == getLangOpts().CurrentModule); + }); } else if (II == Ident__MODULE__) { // The current module as an identifier. OS << getLangOpts().CurrentModule; diff --git a/lib/Lex/Pragma.cpp b/lib/Lex/Pragma.cpp index afb41a240776..1819f4f06bc5 100644 --- a/lib/Lex/Pragma.cpp +++ b/lib/Lex/Pragma.cpp @@ -938,13 +938,13 @@ struct PragmaDebugHandler : public PragmaHandler { } SourceLocation NameLoc = Tok.getLocation(); - Token *Toks = PP.getPreprocessorAllocator().Allocate<Token>(1); - Toks->startToken(); - Toks->setKind(tok::annot_pragma_captured); - Toks->setLocation(NameLoc); + MutableArrayRef<Token> Toks( + PP.getPreprocessorAllocator().Allocate<Token>(1), 1); + Toks[0].startToken(); + Toks[0].setKind(tok::annot_pragma_captured); + Toks[0].setLocation(NameLoc); - PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true, - /*OwnsTokens=*/false); + PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true); } // Disable MSVC warning about runtime stack overflow. @@ -1024,10 +1024,19 @@ public: return; } - if (PP.getDiagnostics().setSeverityForGroup( - WarningName[1] == 'W' ? diag::Flavor::WarningOrError - : diag::Flavor::Remark, - WarningName.substr(2), SV, DiagLoc)) + diag::Flavor Flavor = WarningName[1] == 'W' ? diag::Flavor::WarningOrError + : diag::Flavor::Remark; + StringRef Group = StringRef(WarningName).substr(2); + bool unknownDiag = false; + if (Group == "everything") { + // Special handling for pragma clang diagnostic ... "-Weverything". + // There is no formal group named "everything", so there has to be a + // special case for it. + PP.getDiagnostics().setSeverityForAll(Flavor, SV, DiagLoc); + } else + unknownDiag = PP.getDiagnostics().setSeverityForGroup(Flavor, Group, SV, + DiagLoc); + if (unknownDiag) PP.Diag(StringLoc, diag::warn_pragma_diagnostic_unknown_warning) << WarningName; else if (Callbacks) @@ -1481,6 +1490,13 @@ void Preprocessor::RegisterBuiltinPragmas() { AddPragmaHandler(new PragmaRegionHandler("region")); AddPragmaHandler(new PragmaRegionHandler("endregion")); } + + // Pragmas added by plugins + for (PragmaHandlerRegistry::iterator it = PragmaHandlerRegistry::begin(), + ie = PragmaHandlerRegistry::end(); + it != ie; ++it) { + AddPragmaHandler(it->instantiate().release()); + } } /// Ignore all pragmas, useful for modes such as -Eonly which would otherwise diff --git a/lib/Lex/Preprocessor.cpp b/lib/Lex/Preprocessor.cpp index 142d9ce09049..78179dd7988d 100644 --- a/lib/Lex/Preprocessor.cpp +++ b/lib/Lex/Preprocessor.cpp @@ -51,8 +51,11 @@ #include "llvm/Support/ConvertUTF.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/raw_ostream.h" +#include <utility> using namespace clang; +template class llvm::Registry<clang::PragmaHandler>; + //===----------------------------------------------------------------------===// ExternalPreprocessorSource::~ExternalPreprocessorSource() { } @@ -62,7 +65,7 @@ Preprocessor::Preprocessor(IntrusiveRefCntPtr<PreprocessorOptions> PPOpts, ModuleLoader &TheModuleLoader, IdentifierInfoLookup *IILookup, bool OwnsHeaders, TranslationUnitKind TUKind) - : PPOpts(PPOpts), Diags(&diags), LangOpts(opts), Target(nullptr), + : PPOpts(std::move(PPOpts)), Diags(&diags), LangOpts(opts), Target(nullptr), AuxTarget(nullptr), FileMgr(Headers.getFileMgr()), SourceMgr(SM), ScratchBuf(new ScratchBuffer(SourceMgr)), HeaderInfo(Headers), TheModuleLoader(TheModuleLoader), ExternalSource(nullptr), @@ -477,7 +480,7 @@ void Preprocessor::CreateString(StringRef Str, Token &Tok, } Module *Preprocessor::getCurrentModule() { - if (getLangOpts().CurrentModule.empty()) + if (!getLangOpts().CompilingModule) return nullptr; return getHeaderSearchInfo().lookupModule(getLangOpts().CurrentModule); diff --git a/lib/Lex/TokenLexer.cpp b/lib/Lex/TokenLexer.cpp index c42966928e52..994bae632aec 100644 --- a/lib/Lex/TokenLexer.cpp +++ b/lib/Lex/TokenLexer.cpp @@ -18,8 +18,8 @@ #include "clang/Lex/MacroInfo.h" #include "clang/Lex/Preprocessor.h" #include "llvm/ADT/SmallString.h" -using namespace clang; +using namespace clang; /// Create a TokenLexer for the specified macro with the specified actual /// arguments. Note that this ctor takes ownership of the ActualArgs pointer. @@ -76,8 +76,6 @@ void TokenLexer::Init(Token &Tok, SourceLocation ELEnd, MacroInfo *MI, Macro->DisableMacro(); } - - /// Create a TokenLexer for the specified token stream. This does not /// take ownership of the specified token vector. void TokenLexer::Init(const Token *TokArray, unsigned NumToks, @@ -107,7 +105,6 @@ void TokenLexer::Init(const Token *TokArray, unsigned NumToks, } } - void TokenLexer::destroy() { // If this was a function-like macro that actually uses its arguments, delete // the expanded tokens. @@ -154,12 +151,17 @@ bool TokenLexer::MaybeRemoveCommaBeforeVaArgs( // Remove the comma. ResultToks.pop_back(); - // If the comma was right after another paste (e.g. "X##,##__VA_ARGS__"), - // then removal of the comma should produce a placemarker token (in C99 - // terms) which we model by popping off the previous ##, giving us a plain - // "X" when __VA_ARGS__ is empty. - if (!ResultToks.empty() && ResultToks.back().is(tok::hashhash)) - ResultToks.pop_back(); + if (!ResultToks.empty()) { + // If the comma was right after another paste (e.g. "X##,##__VA_ARGS__"), + // then removal of the comma should produce a placemarker token (in C99 + // terms) which we model by popping off the previous ##, giving us a plain + // "X" when __VA_ARGS__ is empty. + if (ResultToks.back().is(tok::hashhash)) + ResultToks.pop_back(); + + // Remember that this comma was elided. + ResultToks.back().setFlag(Token::CommaAfterElided); + } // Never add a space, even if the comma, ##, or arg had a space. NextTokGetsSpace = false; @@ -169,7 +171,6 @@ bool TokenLexer::MaybeRemoveCommaBeforeVaArgs( /// Expand the arguments of a function-like macro so that we can quickly /// return preexpanded tokens from Tokens. void TokenLexer::ExpandFunctionArguments() { - SmallVector<Token, 128> ResultToks; // Loop through 'Tokens', expanding them into ResultToks. Keep @@ -305,6 +306,7 @@ void TokenLexer::ExpandFunctionArguments() { // identifier. ResultToks[FirstResult].setFlagValue(Token::LeadingSpace, NextTokGetsSpace); + ResultToks[FirstResult].setFlagValue(Token::StartOfLine, false); NextTokGetsSpace = false; } continue; @@ -388,8 +390,6 @@ void TokenLexer::ExpandFunctionArguments() { MaybeRemoveCommaBeforeVaArgs(ResultToks, /*HasPasteOperator=*/true, Macro, ArgNo, PP); - - continue; } // If anything changed, install this as the new Tokens list. @@ -794,6 +794,10 @@ static void updateConsecutiveMacroArgTokens(SourceManager &SM, // "characters" away. if (RelOffs < 0 || RelOffs > 50) break; + + if (CurLoc.isMacroID() && !SM.isWrittenInSameFile(CurLoc, NextLoc)) + break; // Token from a different macro. + CurLoc = NextLoc; } |
