diff options
author | dim <dim@FreeBSD.org> | 2011-02-20 13:06:31 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2011-02-20 13:06:31 +0000 |
commit | 39fcc9a984e2820e4ea0fa2ac4abd17d9f3a31df (patch) | |
tree | a9243275843fbeaa590afc07ee888e006b8d54ea /lib/Lex | |
parent | 69b4eca4a4255ba43baa5c1d9bbdec3ec17f479e (diff) | |
download | FreeBSD-src-39fcc9a984e2820e4ea0fa2ac4abd17d9f3a31df.zip FreeBSD-src-39fcc9a984e2820e4ea0fa2ac4abd17d9f3a31df.tar.gz |
Vendor import of clang trunk r126079:
http://llvm.org/svn/llvm-project/cfe/trunk@126079
Diffstat (limited to 'lib/Lex')
-rw-r--r-- | lib/Lex/CMakeLists.txt | 8 | ||||
-rw-r--r-- | lib/Lex/HeaderMap.cpp | 10 | ||||
-rw-r--r-- | lib/Lex/HeaderSearch.cpp | 44 | ||||
-rw-r--r-- | lib/Lex/Lexer.cpp | 230 | ||||
-rw-r--r-- | lib/Lex/LiteralSupport.cpp | 275 | ||||
-rw-r--r-- | lib/Lex/MacroInfo.cpp | 3 | ||||
-rw-r--r-- | lib/Lex/PPDirectives.cpp | 212 | ||||
-rw-r--r-- | lib/Lex/PPExpressions.cpp | 51 | ||||
-rw-r--r-- | lib/Lex/PPLexerChange.cpp | 14 | ||||
-rw-r--r-- | lib/Lex/PPMacroExpansion.cpp | 152 | ||||
-rw-r--r-- | lib/Lex/PTHLexer.cpp | 44 | ||||
-rw-r--r-- | lib/Lex/Pragma.cpp | 208 | ||||
-rw-r--r-- | lib/Lex/PreprocessingRecord.cpp | 62 | ||||
-rw-r--r-- | lib/Lex/Preprocessor.cpp | 227 | ||||
-rw-r--r-- | lib/Lex/TokenConcatenation.cpp | 10 | ||||
-rw-r--r-- | lib/Lex/TokenLexer.cpp | 11 |
16 files changed, 959 insertions, 602 deletions
diff --git a/lib/Lex/CMakeLists.txt b/lib/Lex/CMakeLists.txt index 632fbc6..80e2820 100644 --- a/lib/Lex/CMakeLists.txt +++ b/lib/Lex/CMakeLists.txt @@ -1,7 +1,9 @@ -set(LLVM_NO_RTTI 1) - # TODO: Add -maltivec when ARCH is PowerPC. +set(LLVM_LINK_COMPONENTS support) + +set(LLVM_USED_LIBS clangBasic) + add_clang_library(clangLex HeaderMap.cpp HeaderSearch.cpp @@ -24,4 +26,4 @@ add_clang_library(clangLex TokenLexer.cpp ) -add_dependencies(clangLex ClangDiagnosticLex) +add_dependencies(clangLex ClangDiagnosticLex ClangAttrSpellings) diff --git a/lib/Lex/HeaderMap.cpp b/lib/Lex/HeaderMap.cpp index 4010d61..e424f91 100644 --- a/lib/Lex/HeaderMap.cpp +++ b/lib/Lex/HeaderMap.cpp @@ -15,9 +15,10 @@ #include "clang/Basic/FileManager.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/SmallString.h" -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/MemoryBuffer.h" +#include <cctype> #include <cstdio> using namespace clang; @@ -75,13 +76,12 @@ static inline unsigned HashHMapKey(llvm::StringRef Str) { /// map. If it doesn't look like a HeaderMap, it gives up and returns null. /// If it looks like a HeaderMap but is obviously corrupted, it puts a reason /// into the string error argument and returns null. -const HeaderMap *HeaderMap::Create(const FileEntry *FE) { +const HeaderMap *HeaderMap::Create(const FileEntry *FE, FileManager &FM) { // If the file is too small to be a header map, ignore it. unsigned FileSize = FE->getSize(); if (FileSize <= sizeof(HMapHeader)) return 0; - llvm::OwningPtr<const llvm::MemoryBuffer> FileBuffer( - llvm::MemoryBuffer::getFile(FE->getName(), 0, FE->getSize())); + llvm::OwningPtr<const llvm::MemoryBuffer> FileBuffer(FM.getBufferForFile(FE)); if (FileBuffer == 0) return 0; // Unreadable file? const char *FileStart = FileBuffer->getBufferStart(); @@ -223,6 +223,6 @@ const FileEntry *HeaderMap::LookupFile(llvm::StringRef Filename, llvm::SmallString<1024> DestPath; DestPath += getString(B.Prefix); DestPath += getString(B.Suffix); - return FM.getFile(DestPath.begin(), DestPath.end()); + return FM.getFile(DestPath.str()); } } diff --git a/lib/Lex/HeaderSearch.cpp b/lib/Lex/HeaderSearch.cpp index 4554aba..b028e33 100644 --- a/lib/Lex/HeaderSearch.cpp +++ b/lib/Lex/HeaderSearch.cpp @@ -15,7 +15,8 @@ #include "clang/Lex/HeaderMap.h" #include "clang/Basic/FileManager.h" #include "clang/Basic/IdentifierTable.h" -#include "llvm/System/Path.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/Path.h" #include "llvm/ADT/SmallString.h" #include <cstdio> using namespace clang; @@ -32,11 +33,15 @@ HeaderFileInfo::getControllingMacro(ExternalIdentifierLookup *External) { return ControllingMacro; } -HeaderSearch::HeaderSearch(FileManager &FM) : FileMgr(FM), FrameworkMap(64) { +ExternalHeaderFileInfoSource::~ExternalHeaderFileInfoSource() {} + +HeaderSearch::HeaderSearch(FileManager &FM) + : FileMgr(FM), FrameworkMap(64) { SystemDirIdx = 0; NoCurDirSearch = false; ExternalLookup = 0; + ExternalSource = 0; NumIncluded = 0; NumMultiIncludeFileOptzn = 0; NumFrameworkLookups = NumSubFrameworkLookups = 0; @@ -83,7 +88,7 @@ const HeaderMap *HeaderSearch::CreateHeaderMap(const FileEntry *FE) { return HeaderMaps[i].second; } - if (const HeaderMap *HM = HeaderMap::Create(FE)) { + if (const HeaderMap *HM = HeaderMap::Create(FE, FileMgr)) { HeaderMaps.push_back(std::make_pair(FE, HM)); return HM; } @@ -118,7 +123,7 @@ const FileEntry *DirectoryLookup::LookupFile(llvm::StringRef Filename, TmpDir += getDir()->getName(); TmpDir.push_back('/'); TmpDir.append(Filename.begin(), Filename.end()); - return HS.getFileMgr().getFile(TmpDir.begin(), TmpDir.end()); + return HS.getFileMgr().getFile(TmpDir.str()); } if (isFramework()) @@ -169,8 +174,8 @@ const FileEntry *DirectoryLookup::DoFrameworkLookup(llvm::StringRef Filename, // If the framework dir doesn't exist, we fail. // FIXME: It's probably more efficient to query this with FileMgr.getDir. - if (!llvm::sys::Path(std::string(FrameworkName.begin(), - FrameworkName.end())).exists()) + bool Exists; + if (llvm::sys::fs::exists(FrameworkName.str(), Exists) || !Exists) return 0; // Otherwise, if it does, remember that this is the right direntry for this @@ -183,16 +188,14 @@ const FileEntry *DirectoryLookup::DoFrameworkLookup(llvm::StringRef Filename, FrameworkName += "Headers/"; FrameworkName.append(Filename.begin()+SlashPos+1, Filename.end()); - if (const FileEntry *FE = FileMgr.getFile(FrameworkName.begin(), - FrameworkName.end())) { + if (const FileEntry *FE = FileMgr.getFile(FrameworkName.str())) return FE; - } // Check "/System/Library/Frameworks/Cocoa.framework/PrivateHeaders/file.h" const char *Private = "Private"; FrameworkName.insert(FrameworkName.begin()+OrigSize, Private, Private+strlen(Private)); - return FileMgr.getFile(FrameworkName.begin(), FrameworkName.end()); + return FileMgr.getFile(FrameworkName.str()); } @@ -212,7 +215,7 @@ const FileEntry *HeaderSearch::LookupFile(llvm::StringRef Filename, const DirectoryLookup *&CurDir, const FileEntry *CurFileEnt) { // If 'Filename' is absolute, check to see if it exists and no searching. - if (llvm::sys::Path::isAbsolute(Filename.begin(), Filename.size())) { + if (llvm::sys::path::is_absolute(Filename)) { CurDir = 0; // If this was an #include_next "/absolute/file", fail. @@ -329,7 +332,7 @@ LookupSubframeworkHeader(llvm::StringRef Filename, FrameworkName += ".framework/"; llvm::StringMapEntry<const DirectoryEntry *> &CacheLookup = - FrameworkMap.GetOrCreateValue(Filename.begin(), Filename.begin()+SlashPos); + FrameworkMap.GetOrCreateValue(Filename.substr(0, SlashPos)); // Some other location? if (CacheLookup.getValue() && @@ -343,8 +346,7 @@ LookupSubframeworkHeader(llvm::StringRef Filename, ++NumSubFrameworkLookups; // If the framework dir doesn't exist, we fail. - const DirectoryEntry *Dir = FileMgr.getDirectory(FrameworkName.begin(), - FrameworkName.end()); + const DirectoryEntry *Dir = FileMgr.getDirectory(FrameworkName.str()); if (Dir == 0) return 0; // Otherwise, if it does, remember that this is the right direntry for this @@ -358,14 +360,13 @@ LookupSubframeworkHeader(llvm::StringRef Filename, llvm::SmallString<1024> HeadersFilename(FrameworkName); HeadersFilename += "Headers/"; HeadersFilename.append(Filename.begin()+SlashPos+1, Filename.end()); - if (!(FE = FileMgr.getFile(HeadersFilename.begin(), - HeadersFilename.end()))) { + if (!(FE = FileMgr.getFile(HeadersFilename.str()))) { // Check ".../Frameworks/HIToolbox.framework/PrivateHeaders/HIToolbox.h" HeadersFilename = FrameworkName; HeadersFilename += "PrivateHeaders/"; HeadersFilename.append(Filename.begin()+SlashPos+1, Filename.end()); - if (!(FE = FileMgr.getFile(HeadersFilename.begin(), HeadersFilename.end()))) + if (!(FE = FileMgr.getFile(HeadersFilename.str()))) return 0; } @@ -389,12 +390,19 @@ LookupSubframeworkHeader(llvm::StringRef Filename, HeaderFileInfo &HeaderSearch::getFileInfo(const FileEntry *FE) { if (FE->getUID() >= FileInfo.size()) FileInfo.resize(FE->getUID()+1); - return FileInfo[FE->getUID()]; + + HeaderFileInfo &HFI = FileInfo[FE->getUID()]; + if (ExternalSource && !HFI.Resolved) { + HFI = ExternalSource->GetHeaderFileInfo(FE); + HFI.Resolved = true; + } + return HFI; } void HeaderSearch::setHeaderFileInfoForUID(HeaderFileInfo HFI, unsigned UID) { if (UID >= FileInfo.size()) FileInfo.resize(UID+1); + HFI.Resolved = true; FileInfo[UID] = HFI; } diff --git a/lib/Lex/Lexer.cpp b/lib/Lex/Lexer.cpp index 917829b..b17198b 100644 --- a/lib/Lex/Lexer.cpp +++ b/lib/Lex/Lexer.cpp @@ -212,6 +212,109 @@ void Lexer::Stringify(llvm::SmallVectorImpl<char> &Str) { } } +//===----------------------------------------------------------------------===// +// Token Spelling +//===----------------------------------------------------------------------===// + +/// getSpelling() - Return the 'spelling' of this token. The spelling of a +/// token are the characters used to represent the token in the source file +/// after trigraph expansion and escaped-newline folding. In particular, this +/// wants to get the true, uncanonicalized, spelling of things like digraphs +/// UCNs, etc. +std::string Lexer::getSpelling(const Token &Tok, const SourceManager &SourceMgr, + const LangOptions &Features, bool *Invalid) { + assert((int)Tok.getLength() >= 0 && "Token character range is bogus!"); + + // If this token contains nothing interesting, return it directly. + bool CharDataInvalid = false; + const char* TokStart = SourceMgr.getCharacterData(Tok.getLocation(), + &CharDataInvalid); + if (Invalid) + *Invalid = CharDataInvalid; + if (CharDataInvalid) + return std::string(); + + if (!Tok.needsCleaning()) + return std::string(TokStart, TokStart+Tok.getLength()); + + std::string Result; + Result.reserve(Tok.getLength()); + + // Otherwise, hard case, relex the characters into the string. + for (const char *Ptr = TokStart, *End = TokStart+Tok.getLength(); + Ptr != End; ) { + unsigned CharSize; + Result.push_back(Lexer::getCharAndSizeNoWarn(Ptr, CharSize, Features)); + Ptr += CharSize; + } + assert(Result.size() != unsigned(Tok.getLength()) && + "NeedsCleaning flag set on something that didn't need cleaning!"); + return Result; +} + +/// getSpelling - This method is used to get the spelling of a token into a +/// preallocated buffer, instead of as an std::string. The caller is required +/// to allocate enough space for the token, which is guaranteed to be at least +/// Tok.getLength() bytes long. The actual length of the token is returned. +/// +/// Note that this method may do two possible things: it may either fill in +/// the buffer specified with characters, or it may *change the input pointer* +/// to point to a constant buffer with the data already in it (avoiding a +/// copy). The caller is not allowed to modify the returned buffer pointer +/// if an internal buffer is returned. +unsigned Lexer::getSpelling(const Token &Tok, const char *&Buffer, + const SourceManager &SourceMgr, + const LangOptions &Features, bool *Invalid) { + assert((int)Tok.getLength() >= 0 && "Token character range is bogus!"); + + const char *TokStart = 0; + // NOTE: this has to be checked *before* testing for an IdentifierInfo. + if (Tok.is(tok::raw_identifier)) + TokStart = Tok.getRawIdentifierData(); + else if (const IdentifierInfo *II = Tok.getIdentifierInfo()) { + // Just return the string from the identifier table, which is very quick. + Buffer = II->getNameStart(); + return II->getLength(); + } + + // NOTE: this can be checked even after testing for an IdentifierInfo. + if (Tok.isLiteral()) + TokStart = Tok.getLiteralData(); + + if (TokStart == 0) { + // Compute the start of the token in the input lexer buffer. + bool CharDataInvalid = false; + TokStart = SourceMgr.getCharacterData(Tok.getLocation(), &CharDataInvalid); + if (Invalid) + *Invalid = CharDataInvalid; + if (CharDataInvalid) { + Buffer = ""; + return 0; + } + } + + // If this token contains nothing interesting, return it directly. + if (!Tok.needsCleaning()) { + Buffer = TokStart; + return Tok.getLength(); + } + + // Otherwise, hard case, relex the characters into the string. + char *OutBuf = const_cast<char*>(Buffer); + for (const char *Ptr = TokStart, *End = TokStart+Tok.getLength(); + Ptr != End; ) { + unsigned CharSize; + *OutBuf++ = Lexer::getCharAndSizeNoWarn(Ptr, CharSize, Features); + Ptr += CharSize; + } + assert(unsigned(OutBuf-Buffer) != Tok.getLength() && + "NeedsCleaning flag set on something that didn't need cleaning!"); + + return OutBuf-Buffer; +} + + + static bool isWhitespace(unsigned char c); /// MeasureTokenLength - Relex the token at the specified location and return @@ -242,7 +345,8 @@ unsigned Lexer::MeasureTokenLength(SourceLocation Loc, return 0; // Create a lexer starting at the beginning of this token. - Lexer TheLexer(Loc, LangOpts, Buffer.begin(), StrData, Buffer.end()); + Lexer TheLexer(SM.getLocForStartOfFile(LocInfo.first), LangOpts, + Buffer.begin(), StrData, Buffer.end()); TheLexer.SetCommentRetentionState(true); Token TheTok; TheLexer.LexFromRawLexer(TheTok); @@ -253,6 +357,9 @@ SourceLocation Lexer::GetBeginningOfToken(SourceLocation Loc, const SourceManager &SM, const LangOptions &LangOpts) { std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(Loc); + if (LocInfo.first.isInvalid()) + return Loc; + bool Invalid = false; llvm::StringRef Buffer = SM.getBufferData(LocInfo.first, &Invalid); if (Invalid) @@ -261,6 +368,9 @@ SourceLocation Lexer::GetBeginningOfToken(SourceLocation Loc, // Back up from the current location until we hit the beginning of a line // (or the buffer). We'll relex from that point. const char *BufStart = Buffer.data(); + if (LocInfo.second >= Buffer.size()) + return Loc; + const char *StrData = BufStart+LocInfo.second; if (StrData[0] == '\n' || StrData[0] == '\r') return Loc; @@ -371,10 +481,9 @@ Lexer::ComputePreamble(const llvm::MemoryBuffer *Buffer, unsigned MaxLines) { // we don't have an identifier table available. Instead, just look at // the raw identifier to recognize and categorize preprocessor directives. TheLexer.LexFromRawLexer(TheTok); - if (TheTok.getKind() == tok::identifier && !TheTok.needsCleaning()) { - const char *IdStart = Buffer->getBufferStart() - + TheTok.getLocation().getRawEncoding() - 1; - llvm::StringRef Keyword(IdStart, TheTok.getLength()); + if (TheTok.getKind() == tok::raw_identifier && !TheTok.needsCleaning()) { + llvm::StringRef Keyword(TheTok.getRawIdentifierData(), + TheTok.getLength()); PreambleDirectiveKind PDK = llvm::StringSwitch<PreambleDirectiveKind>(Keyword) .Case("include", PDK_Skipped) @@ -443,6 +552,83 @@ Lexer::ComputePreamble(const llvm::MemoryBuffer *Buffer, unsigned MaxLines) { : TheTok.isAtStartOfLine()); } + +/// AdvanceToTokenCharacter - Given a location that specifies the start of a +/// token, return a new location that specifies a character within the token. +SourceLocation Lexer::AdvanceToTokenCharacter(SourceLocation TokStart, + unsigned CharNo, + const SourceManager &SM, + const LangOptions &Features) { + // Figure out how many physical characters away the specified instantiation + // character is. This needs to take into consideration newlines and + // trigraphs. + bool Invalid = false; + const char *TokPtr = SM.getCharacterData(TokStart, &Invalid); + + // If they request the first char of the token, we're trivially done. + if (Invalid || (CharNo == 0 && Lexer::isObviouslySimpleCharacter(*TokPtr))) + return TokStart; + + unsigned PhysOffset = 0; + + // The usual case is that tokens don't contain anything interesting. Skip + // over the uninteresting characters. If a token only consists of simple + // chars, this method is extremely fast. + while (Lexer::isObviouslySimpleCharacter(*TokPtr)) { + if (CharNo == 0) + return TokStart.getFileLocWithOffset(PhysOffset); + ++TokPtr, --CharNo, ++PhysOffset; + } + + // If we have a character that may be a trigraph or escaped newline, use a + // lexer to parse it correctly. + for (; CharNo; --CharNo) { + unsigned Size; + Lexer::getCharAndSizeNoWarn(TokPtr, Size, Features); + TokPtr += Size; + PhysOffset += Size; + } + + // Final detail: if we end up on an escaped newline, we want to return the + // location of the actual byte of the token. For example foo\<newline>bar + // advanced by 3 should return the location of b, not of \\. One compounding + // detail of this is that the escape may be made by a trigraph. + if (!Lexer::isObviouslySimpleCharacter(*TokPtr)) + PhysOffset += Lexer::SkipEscapedNewLines(TokPtr)-TokPtr; + + return TokStart.getFileLocWithOffset(PhysOffset); +} + +/// \brief Computes the source location just past the end of the +/// token at this source location. +/// +/// This routine can be used to produce a source location that +/// points just past the end of the token referenced by \p Loc, and +/// is generally used when a diagnostic needs to point just after a +/// token where it expected something different that it received. If +/// the returned source location would not be meaningful (e.g., if +/// it points into a macro), this routine returns an invalid +/// source location. +/// +/// \param Offset an offset from the end of the token, where the source +/// location should refer to. The default offset (0) produces a source +/// location pointing just past the end of the token; an offset of 1 produces +/// a source location pointing to the last character in the token, etc. +SourceLocation Lexer::getLocForEndOfToken(SourceLocation Loc, unsigned Offset, + const SourceManager &SM, + const LangOptions &Features) { + if (Loc.isInvalid() || !Loc.isFileID()) + return SourceLocation(); + + unsigned Len = Lexer::MeasureTokenLength(Loc, SM, Features); + if (Len > Offset) + Len = Len - Offset; + else + return Loc; + + return AdvanceToTokenCharacter(Loc, Len, SM, Features); +} + //===----------------------------------------------------------------------===// // Character information. //===----------------------------------------------------------------------===// @@ -584,10 +770,8 @@ static inline bool isNumberBody(unsigned char c) { /// lexer buffer was all instantiated at a single point, perform the mapping. /// This is currently only used for _Pragma implementation, so it is the slow /// path of the hot getSourceLocation method. Do not allow it to be inlined. -static DISABLE_INLINE SourceLocation GetMappedTokenLoc(Preprocessor &PP, - SourceLocation FileLoc, - unsigned CharNo, - unsigned TokLen); +static LLVM_ATTRIBUTE_NOINLINE SourceLocation GetMappedTokenLoc( + Preprocessor &PP, SourceLocation FileLoc, unsigned CharNo, unsigned TokLen); static SourceLocation GetMappedTokenLoc(Preprocessor &PP, SourceLocation FileLoc, unsigned CharNo, unsigned TokLen) { @@ -869,19 +1053,17 @@ void Lexer::LexIdentifier(Token &Result, const char *CurPtr) { if (C != '\\' && C != '?' && (C != '$' || !Features.DollarIdents)) { FinishIdentifier: const char *IdStart = BufferPtr; - FormTokenWithChars(Result, CurPtr, tok::identifier); + FormTokenWithChars(Result, CurPtr, tok::raw_identifier); + Result.setRawIdentifierData(IdStart); // If we are in raw mode, return this identifier raw. There is no need to // look up identifier information or attempt to macro expand it. - if (LexingRawMode) return; - - // Fill in Result.IdentifierInfo, looking up the identifier in the - // identifier table. - IdentifierInfo *II = PP->LookUpIdentifierInfo(Result, IdStart); + if (LexingRawMode) + return; - // Change the kind of this identifier to the appropriate token kind, e.g. - // turning "for" into a keyword. - Result.setKind(II->getTokenID()); + // Fill in Result.IdentifierInfo and update the token kind, + // looking up the identifier in the identifier table. + IdentifierInfo *II = PP->LookUpIdentifierInfo(Result); // Finally, now that we know we have an identifier, pass this off to the // preprocessor, which may macro expand it or something. @@ -980,7 +1162,7 @@ void Lexer::LexStringLiteral(Token &Result, const char *CurPtr, bool Wide) { if (C == 0 && PP && PP->isCodeCompletionFile(FileLoc)) PP->CodeCompleteNaturalLanguage(); else if (!isLexingRawMode() && !Features.AsmPreprocessor) - Diag(BufferPtr, diag::err_unterminated_string); + Diag(BufferPtr, diag::warn_unterminated_string); FormTokenWithChars(Result, CurPtr-1, tok::unknown); return; } @@ -1059,7 +1241,7 @@ void Lexer::LexCharConstant(Token &Result, const char *CurPtr) { if (C == 0 && PP && PP->isCodeCompletionFile(FileLoc)) PP->CodeCompleteNaturalLanguage(); else if (!isLexingRawMode() && !Features.AsmPreprocessor) - Diag(BufferPtr, diag::err_unterminated_char); + Diag(BufferPtr, diag::warn_unterminated_char); FormTokenWithChars(Result, CurPtr-1, tok::unknown); return; } else if (C == 0) { @@ -2141,6 +2323,10 @@ LexNextToken: // If this is actually a '<<<<<<<' version control conflict marker, // recognize it as such and recover nicely. goto LexNextToken; + } else if (Features.CUDA && After == '<') { + Kind = tok::lesslessless; + CurPtr = ConsumeChar(ConsumeChar(CurPtr, SizeTmp, Result), + SizeTmp2, Result); } else { CurPtr = ConsumeChar(CurPtr, SizeTmp, Result); Kind = tok::lessless; @@ -2172,6 +2358,10 @@ LexNextToken: } else if (After == '>' && HandleEndOfConflictMarker(CurPtr-1)) { // If this is '>>>>>>>' and we're in a conflict marker, ignore it. goto LexNextToken; + } else if (Features.CUDA && After == '>') { + Kind = tok::greatergreatergreater; + CurPtr = ConsumeChar(ConsumeChar(CurPtr, SizeTmp, Result), + SizeTmp2, Result); } else { CurPtr = ConsumeChar(CurPtr, SizeTmp, Result); Kind = tok::greatergreater; diff --git a/lib/Lex/LiteralSupport.cpp b/lib/Lex/LiteralSupport.cpp index fb543d0..16d7b36 100644 --- a/lib/Lex/LiteralSupport.cpp +++ b/lib/Lex/LiteralSupport.cpp @@ -33,8 +33,8 @@ static int HexDigitValue(char C) { /// either a character or a string literal. static unsigned ProcessCharEscape(const char *&ThisTokBuf, const char *ThisTokEnd, bool &HadError, - SourceLocation Loc, bool IsWide, - Preprocessor &PP, bool Complain) { + FullSourceLoc Loc, bool IsWide, + Diagnostic *Diags, const TargetInfo &Target) { // Skip the '\' char. ++ThisTokBuf; @@ -54,13 +54,13 @@ static unsigned ProcessCharEscape(const char *&ThisTokBuf, ResultChar = 8; break; case 'e': - if (Complain) - PP.Diag(Loc, diag::ext_nonstandard_escape) << "e"; + if (Diags) + Diags->Report(Loc, diag::ext_nonstandard_escape) << "e"; ResultChar = 27; break; case 'E': - if (Complain) - PP.Diag(Loc, diag::ext_nonstandard_escape) << "E"; + if (Diags) + Diags->Report(Loc, diag::ext_nonstandard_escape) << "E"; ResultChar = 27; break; case 'f': @@ -81,8 +81,8 @@ static unsigned ProcessCharEscape(const char *&ThisTokBuf, case 'x': { // Hex escape. ResultChar = 0; if (ThisTokBuf == ThisTokEnd || !isxdigit(*ThisTokBuf)) { - if (Complain) - PP.Diag(Loc, diag::err_hex_escape_no_digits); + if (Diags) + Diags->Report(Loc, diag::err_hex_escape_no_digits); HadError = 1; break; } @@ -99,9 +99,8 @@ static unsigned ProcessCharEscape(const char *&ThisTokBuf, } // See if any bits will be truncated when evaluated as a character. - unsigned CharWidth = IsWide - ? PP.getTargetInfo().getWCharWidth() - : PP.getTargetInfo().getCharWidth(); + unsigned CharWidth = + IsWide ? Target.getWCharWidth() : Target.getCharWidth(); if (CharWidth != 32 && (ResultChar >> CharWidth) != 0) { Overflow = true; @@ -109,8 +108,8 @@ static unsigned ProcessCharEscape(const char *&ThisTokBuf, } // Check for overflow. - if (Overflow && Complain) // Too many digits to fit in - PP.Diag(Loc, diag::warn_hex_escape_too_large); + if (Overflow && Diags) // Too many digits to fit in + Diags->Report(Loc, diag::warn_hex_escape_too_large); break; } case '0': case '1': case '2': case '3': @@ -130,13 +129,12 @@ static unsigned ProcessCharEscape(const char *&ThisTokBuf, ThisTokBuf[0] >= '0' && ThisTokBuf[0] <= '7'); // Check for overflow. Reject '\777', but not L'\777'. - unsigned CharWidth = IsWide - ? PP.getTargetInfo().getWCharWidth() - : PP.getTargetInfo().getCharWidth(); + unsigned CharWidth = + IsWide ? Target.getWCharWidth() : Target.getCharWidth(); if (CharWidth != 32 && (ResultChar >> CharWidth) != 0) { - if (Complain) - PP.Diag(Loc, diag::warn_octal_escape_too_large); + if (Diags) + Diags->Report(Loc, diag::warn_octal_escape_too_large); ResultChar &= ~0U >> (32-CharWidth); } break; @@ -145,18 +143,20 @@ static unsigned ProcessCharEscape(const char *&ThisTokBuf, // Otherwise, these are not valid escapes. case '(': case '{': case '[': case '%': // GCC accepts these as extensions. We warn about them as such though. - if (Complain) - PP.Diag(Loc, diag::ext_nonstandard_escape) + if (Diags) + Diags->Report(Loc, diag::ext_nonstandard_escape) << std::string()+(char)ResultChar; break; default: - if (!Complain) + if (Diags == 0) break; - if (isgraph(ThisTokBuf[0])) - PP.Diag(Loc, diag::ext_unknown_escape) << std::string()+(char)ResultChar; + if (isgraph(ResultChar)) + Diags->Report(Loc, diag::ext_unknown_escape) + << std::string()+(char)ResultChar; else - PP.Diag(Loc, diag::ext_unknown_escape) << "x"+llvm::utohexstr(ResultChar); + Diags->Report(Loc, diag::ext_unknown_escape) + << "x"+llvm::utohexstr(ResultChar); break; } @@ -164,16 +164,13 @@ static unsigned ProcessCharEscape(const char *&ThisTokBuf, } /// ProcessUCNEscape - Read the Universal Character Name, check constraints and -/// convert the UTF32 to UTF8. This is a subroutine of StringLiteralParser. -/// When we decide to implement UCN's for character constants and identifiers, -/// we will likely rework our support for UCN's. -static void ProcessUCNEscape(const char *&ThisTokBuf, const char *ThisTokEnd, - char *&ResultBuf, bool &HadError, - SourceLocation Loc, Preprocessor &PP, - bool wide, - bool Complain) { - // FIXME: Add a warning - UCN's are only valid in C++ & C99. - // FIXME: Handle wide strings. +/// return the UTF32. +static bool ProcessUCNEscape(const char *&ThisTokBuf, const char *ThisTokEnd, + uint32_t &UcnVal, unsigned short &UcnLen, + FullSourceLoc Loc, Diagnostic *Diags, + const LangOptions &Features) { + if (!Features.CPlusPlus && !Features.C99 && Diags) + Diags->Report(Loc, diag::warn_ucn_not_valid_in_c89); // Save the beginning of the string (for error diagnostics). const char *ThisTokBegin = ThisTokBuf; @@ -182,49 +179,87 @@ static void ProcessUCNEscape(const char *&ThisTokBuf, const char *ThisTokEnd, ThisTokBuf += 2; if (ThisTokBuf == ThisTokEnd || !isxdigit(*ThisTokBuf)) { - if (Complain) - PP.Diag(Loc, diag::err_ucn_escape_no_digits); - HadError = 1; - return; + if (Diags) + Diags->Report(Loc, diag::err_ucn_escape_no_digits); + return false; } - typedef uint32_t UTF32; - - UTF32 UcnVal = 0; - unsigned short UcnLen = (ThisTokBuf[-1] == 'u' ? 4 : 8); + UcnLen = (ThisTokBuf[-1] == 'u' ? 4 : 8); unsigned short UcnLenSave = UcnLen; - for (; ThisTokBuf != ThisTokEnd && UcnLen; ++ThisTokBuf, UcnLen--) { + for (; ThisTokBuf != ThisTokEnd && UcnLenSave; ++ThisTokBuf, UcnLenSave--) { int CharVal = HexDigitValue(ThisTokBuf[0]); if (CharVal == -1) break; UcnVal <<= 4; UcnVal |= CharVal; } // If we didn't consume the proper number of digits, there is a problem. - if (UcnLen) { - if (Complain) - PP.Diag(PP.AdvanceToTokenCharacter(Loc, ThisTokBuf-ThisTokBegin), - diag::err_ucn_escape_incomplete); - HadError = 1; - return; + if (UcnLenSave) { + if (Diags) { + SourceLocation L = + Lexer::AdvanceToTokenCharacter(Loc, ThisTokBuf-ThisTokBegin, + Loc.getManager(), Features); + Diags->Report(FullSourceLoc(L, Loc.getManager()), + diag::err_ucn_escape_incomplete); + } + return false; } // Check UCN constraints (C99 6.4.3p2). if ((UcnVal < 0xa0 && (UcnVal != 0x24 && UcnVal != 0x40 && UcnVal != 0x60 )) // $, @, ` || (UcnVal >= 0xD800 && UcnVal <= 0xDFFF) || (UcnVal > 0x10FFFF)) /* the maximum legal UTF32 value */ { - if (Complain) - PP.Diag(Loc, diag::err_ucn_escape_invalid); + if (Diags) + Diags->Report(Loc, diag::err_ucn_escape_invalid); + return false; + } + return true; +} + +/// EncodeUCNEscape - Read the Universal Character Name, check constraints and +/// convert the UTF32 to UTF8 or UTF16. This is a subroutine of +/// StringLiteralParser. When we decide to implement UCN's for identifiers, +/// we will likely rework our support for UCN's. +static void EncodeUCNEscape(const char *&ThisTokBuf, const char *ThisTokEnd, + char *&ResultBuf, bool &HadError, + FullSourceLoc Loc, bool wide, Diagnostic *Diags, + const LangOptions &Features) { + typedef uint32_t UTF32; + UTF32 UcnVal = 0; + unsigned short UcnLen = 0; + if (!ProcessUCNEscape(ThisTokBuf, ThisTokEnd, UcnVal, UcnLen, Loc, Diags, + Features)) { HadError = 1; return; } + if (wide) { - (void)UcnLenSave; - assert(UcnLenSave == 4 && - "ProcessUCNEscape - only ucn length of 4 supported"); - // little endian assumed. - *ResultBuf++ = (UcnVal & 0x000000FF); - *ResultBuf++ = (UcnVal & 0x0000FF00) >> 8; - *ResultBuf++ = (UcnVal & 0x00FF0000) >> 16; - *ResultBuf++ = (UcnVal & 0xFF000000) >> 24; + (void)UcnLen; + assert((UcnLen== 4 || UcnLen== 8) && "only ucn length of 4 or 8 supported"); + + if (!Features.ShortWChar) { + // Note: our internal rep of wide char tokens is always little-endian. + *ResultBuf++ = (UcnVal & 0x000000FF); + *ResultBuf++ = (UcnVal & 0x0000FF00) >> 8; + *ResultBuf++ = (UcnVal & 0x00FF0000) >> 16; + *ResultBuf++ = (UcnVal & 0xFF000000) >> 24; + return; + } + + // Convert to UTF16. + if (UcnVal < (UTF32)0xFFFF) { + *ResultBuf++ = (UcnVal & 0x000000FF); + *ResultBuf++ = (UcnVal & 0x0000FF00) >> 8; + return; + } + if (Diags) Diags->Report(Loc, diag::warn_ucn_escape_too_large); + + typedef uint16_t UTF16; + UcnVal -= 0x10000; + UTF16 surrogate1 = 0xD800 + (UcnVal >> 10); + UTF16 surrogate2 = 0xDC00 + (UcnVal & 0x3FF); + *ResultBuf++ = (surrogate1 & 0x000000FF); + *ResultBuf++ = (surrogate1 & 0x0000FF00) >> 8; + *ResultBuf++ = (surrogate2 & 0x000000FF); + *ResultBuf++ = (surrogate2 & 0x0000FF00) >> 8; return; } // Now that we've parsed/checked the UCN, we convert from UTF32->UTF8. @@ -398,6 +433,7 @@ NumericLiteralParser(const char *begin, const char *end, } continue; // Success. case 'i': + case 'I': if (PP.getLangOptions().Microsoft) { if (isFPConstant || isLong || isLongLong) break; @@ -410,22 +446,33 @@ NumericLiteralParser(const char *begin, const char *end, break; case '1': if (s + 2 == ThisTokEnd) break; - if (s[2] == '6') s += 3; // i16 suffix + if (s[2] == '6') { + s += 3; // i16 suffix + isMicrosoftInteger = true; + } else if (s[2] == '2') { if (s + 3 == ThisTokEnd) break; - if (s[3] == '8') s += 4; // i128 suffix + if (s[3] == '8') { + s += 4; // i128 suffix + isMicrosoftInteger = true; + } } - isMicrosoftInteger = true; break; case '3': if (s + 2 == ThisTokEnd) break; - if (s[2] == '2') s += 3; // i32 suffix - isMicrosoftInteger = true; + if (s[2] == '2') { + s += 3; // i32 suffix + isLong = true; + isMicrosoftInteger = true; + } break; case '6': if (s + 2 == ThisTokEnd) break; - if (s[2] == '4') s += 3; // i64 suffix - isMicrosoftInteger = true; + if (s[2] == '4') { + s += 3; // i64 suffix + isLongLong = true; + isMicrosoftInteger = true; + } break; default: break; @@ -434,7 +481,6 @@ NumericLiteralParser(const char *begin, const char *end, } } // fall through. - case 'I': case 'j': case 'J': if (isImaginary) break; // Cannot be repeated. @@ -681,11 +727,29 @@ CharLiteralParser::CharLiteralParser(const char *begin, const char *end, bool Warned = false; while (begin[0] != '\'') { uint64_t ResultChar; + + // Is this a Universal Character Name escape? if (begin[0] != '\\') // If this is a normal character, consume it. ResultChar = *begin++; - else // Otherwise, this is an escape character. - ResultChar = ProcessCharEscape(begin, end, HadError, Loc, IsWide, PP, - /*Complain=*/true); + else { // Otherwise, this is an escape character. + // Check for UCN. + if (begin[1] == 'u' || begin[1] == 'U') { + uint32_t utf32 = 0; + unsigned short UcnLen = 0; + if (!ProcessUCNEscape(begin, end, utf32, UcnLen, + FullSourceLoc(Loc, PP.getSourceManager()), + &PP.getDiagnostics(), PP.getLangOptions())) { + HadError = 1; + } + ResultChar = utf32; + } else { + // Otherwise, this is a non-UCN escape character. Process it. + ResultChar = ProcessCharEscape(begin, end, HadError, + FullSourceLoc(Loc,PP.getSourceManager()), + IsWide, + &PP.getDiagnostics(), PP.getTargetInfo()); + } + } // If this is a multi-character constant (e.g. 'abc'), handle it. These are // implementation defined (C99 6.4.4.4p10). @@ -725,6 +789,9 @@ CharLiteralParser::CharLiteralParser(const char *begin, const char *end, // Transfer the value from APInt to uint64_t Value = LitVal.getZExtValue(); + if (IsWide && PP.getLangOptions().ShortWChar && Value > 0xFFFF) + PP.Diag(Loc, diag::warn_ucn_escape_too_large); + // If this is a single narrow character, sign extend it (e.g. '\xFF' is "-1") // if 'char' is signed for this target (C99 6.4.4.4p10). Note that multiple // character constants are not sign extended in the this implementation: @@ -771,7 +838,13 @@ CharLiteralParser::CharLiteralParser(const char *begin, const char *end, /// StringLiteralParser:: StringLiteralParser(const Token *StringToks, unsigned NumStringToks, - Preprocessor &pp, bool Complain) : PP(pp) { + Preprocessor &PP, bool Complain) + : SM(PP.getSourceManager()), Features(PP.getLangOptions()), + Target(PP.getTargetInfo()), Diags(Complain ? &PP.getDiagnostics() : 0) { + init(StringToks, NumStringToks); +} + +void StringLiteralParser::init(const Token *StringToks, unsigned NumStringToks){ // Scan all of the string portions, remember the max individual token length, // computing a bound on the concatenated string length, and see whether any // piece is a wide-string. If any of the string portions is a wide-string @@ -806,7 +879,7 @@ StringLiteralParser(const Token *StringToks, unsigned NumStringToks, // query the target. As such, wchar_tByteWidth is only valid if AnyWide=true. wchar_tByteWidth = ~0U; if (AnyWide) { - wchar_tByteWidth = PP.getTargetInfo().getWCharWidth(); + wchar_tByteWidth = Target.getWCharWidth(); assert((wchar_tByteWidth & 7) == 0 && "Assumes wchar_t is byte multiple!"); wchar_tByteWidth /= 8; } @@ -835,8 +908,9 @@ StringLiteralParser(const Token *StringToks, unsigned NumStringToks, // that ThisTokBuf points to a buffer that is big enough for the whole token // and 'spelled' tokens can only shrink. bool StringInvalid = false; - unsigned ThisTokLen = PP.getSpelling(StringToks[i], ThisTokBuf, - &StringInvalid); + unsigned ThisTokLen = + Lexer::getSpelling(StringToks[i], ThisTokBuf, SM, Features, + &StringInvalid); if (StringInvalid) { hadError = 1; continue; @@ -856,7 +930,7 @@ StringLiteralParser(const Token *StringToks, unsigned NumStringToks, ++ThisTokBuf; // Check if this is a pascal string - if (pp.getLangOptions().PascalStrings && ThisTokBuf + 1 != ThisTokEnd && + if (Features.PascalStrings && ThisTokBuf + 1 != ThisTokEnd && ThisTokBuf[0] == '\\' && ThisTokBuf[1] == 'p') { // If the \p sequence is found in the first token, we have a pascal string @@ -894,15 +968,16 @@ StringLiteralParser(const Token *StringToks, unsigned NumStringToks, } // Is this a Universal Character Name escape? if (ThisTokBuf[1] == 'u' || ThisTokBuf[1] == 'U') { - ProcessUCNEscape(ThisTokBuf, ThisTokEnd, ResultPtr, - hadError, StringToks[i].getLocation(), PP, wide, - Complain); + EncodeUCNEscape(ThisTokBuf, ThisTokEnd, ResultPtr, + hadError, FullSourceLoc(StringToks[i].getLocation(),SM), + wide, Diags, Features); continue; } // Otherwise, this is a non-UCN escape character. Process it. - unsigned ResultChar = ProcessCharEscape(ThisTokBuf, ThisTokEnd, hadError, - StringToks[i].getLocation(), - AnyWide, PP, Complain); + unsigned ResultChar = + ProcessCharEscape(ThisTokBuf, ThisTokEnd, hadError, + FullSourceLoc(StringToks[i].getLocation(), SM), + AnyWide, Diags, Target); // Note: our internal rep of wide char tokens is always little-endian. *ResultPtr++ = ResultChar & 0xFF; @@ -920,25 +995,24 @@ StringLiteralParser(const Token *StringToks, unsigned NumStringToks, ResultBuf[0] /= wchar_tByteWidth; // Verify that pascal strings aren't too large. - if (GetStringLength() > 256 && Complain) { - PP.Diag(StringToks[0].getLocation(), diag::err_pascal_string_too_long) - << SourceRange(StringToks[0].getLocation(), - StringToks[NumStringToks-1].getLocation()); + if (GetStringLength() > 256) { + if (Diags) + Diags->Report(FullSourceLoc(StringToks[0].getLocation(), SM), + diag::err_pascal_string_too_long) + << SourceRange(StringToks[0].getLocation(), + StringToks[NumStringToks-1].getLocation()); hadError = 1; return; } - } else if (Complain) { + } else if (Diags) { // Complain if this string literal has too many characters. - unsigned MaxChars = PP.getLangOptions().CPlusPlus? 65536 - : PP.getLangOptions().C99 ? 4095 - : 509; + unsigned MaxChars = Features.CPlusPlus? 65536 : Features.C99 ? 4095 : 509; if (GetNumStringChars() > MaxChars) - PP.Diag(StringToks[0].getLocation(), diag::ext_string_too_long) + Diags->Report(FullSourceLoc(StringToks[0].getLocation(), SM), + diag::ext_string_too_long) << GetNumStringChars() << MaxChars - << (PP.getLangOptions().CPlusPlus? 2 - : PP.getLangOptions().C99 ? 1 - : 0) + << (Features.CPlusPlus ? 2 : Features.C99 ? 1 : 0) << SourceRange(StringToks[0].getLocation(), StringToks[NumStringToks-1].getLocation()); } @@ -949,19 +1023,17 @@ StringLiteralParser(const Token *StringToks, unsigned NumStringToks, /// specified byte of the string data represented by Token. This handles /// advancing over escape sequences in the string. unsigned StringLiteralParser::getOffsetOfStringByte(const Token &Tok, - unsigned ByteNo, - Preprocessor &PP, - bool Complain) { + unsigned ByteNo) const { // Get the spelling of the token. - llvm::SmallString<16> SpellingBuffer; + llvm::SmallString<32> SpellingBuffer; SpellingBuffer.resize(Tok.getLength()); bool StringInvalid = false; const char *SpellingPtr = &SpellingBuffer[0]; - unsigned TokLen = PP.getSpelling(Tok, SpellingPtr, &StringInvalid); - if (StringInvalid) { + unsigned TokLen = Lexer::getSpelling(Tok, SpellingPtr, SM, Features, + &StringInvalid); + if (StringInvalid) return 0; - } assert(SpellingPtr[0] != 'L' && "Doesn't handle wide strings yet"); @@ -987,7 +1059,8 @@ unsigned StringLiteralParser::getOffsetOfStringByte(const Token &Tok, // Otherwise, this is an escape character. Advance over it. bool HadError = false; ProcessCharEscape(SpellingPtr, SpellingEnd, HadError, - Tok.getLocation(), false, PP, Complain); + FullSourceLoc(Tok.getLocation(), SM), + false, Diags, Target); assert(!HadError && "This method isn't valid on erroneous strings"); --ByteNo; } diff --git a/lib/Lex/MacroInfo.cpp b/lib/Lex/MacroInfo.cpp index c6d0934..c819011 100644 --- a/lib/Lex/MacroInfo.cpp +++ b/lib/Lex/MacroInfo.cpp @@ -22,8 +22,9 @@ MacroInfo::MacroInfo(SourceLocation DefLoc) : Location(DefLoc) { IsBuiltinMacro = false; IsFromAST = false; IsDisabled = false; - IsUsed = true; + IsUsed = false; IsAllowRedefinitionsWithoutWarning = false; + IsWarnIfUnused = false; ArgumentList = 0; NumArguments = 0; diff --git a/lib/Lex/PPDirectives.cpp b/lib/Lex/PPDirectives.cpp index 8da7def..0f0d25b 100644 --- a/lib/Lex/PPDirectives.cpp +++ b/lib/Lex/PPDirectives.cpp @@ -17,6 +17,7 @@ #include "clang/Lex/MacroInfo.h" #include "clang/Lex/LexDiagnostic.h" #include "clang/Lex/CodeCompletionHandler.h" +#include "clang/Lex/Pragma.h" #include "clang/Basic/FileManager.h" #include "clang/Basic/SourceManager.h" #include "llvm/ADT/APInt.h" @@ -27,14 +28,23 @@ using namespace clang; //===----------------------------------------------------------------------===// MacroInfo *Preprocessor::AllocateMacroInfo() { - MacroInfo *MI; + MacroInfoChain *MIChain; - if (!MICache.empty()) { - MI = MICache.back(); - MICache.pop_back(); - } else - MI = (MacroInfo*) BP.Allocate<MacroInfo>(); - return MI; + if (MICache) { + MIChain = MICache; + MICache = MICache->Next; + } + else { + MIChain = BP.Allocate<MacroInfoChain>(); + } + + MIChain->Next = MIChainHead; + MIChain->Prev = 0; + if (MIChainHead) + MIChainHead->Prev = MIChain; + MIChainHead = MIChain; + + return &(MIChain->MI); } MacroInfo *Preprocessor::AllocateMacroInfo(SourceLocation L) { @@ -52,10 +62,23 @@ MacroInfo *Preprocessor::CloneMacroInfo(const MacroInfo &MacroToClone) { /// ReleaseMacroInfo - Release the specified MacroInfo. This memory will /// be reused for allocating new MacroInfo objects. void Preprocessor::ReleaseMacroInfo(MacroInfo *MI) { - MICache.push_back(MI); - MI->FreeArgumentList(); -} + MacroInfoChain *MIChain = (MacroInfoChain*) MI; + if (MacroInfoChain *Prev = MIChain->Prev) { + MacroInfoChain *Next = MIChain->Next; + Prev->Next = Next; + if (Next) + Next->Prev = Prev; + } + else { + assert(MIChainHead == MIChain); + MIChainHead = MIChain->Next; + MIChainHead->Prev = 0; + } + MIChain->Next = MICache; + MICache = MIChain; + MI->Destroy(); +} /// DiscardUntilEndOfDirective - Read and discard all tokens remaining on the /// current line until the tok::eom token is found. @@ -222,7 +245,7 @@ void Preprocessor::SkipExcludedConditionalBlock(SourceLocation IfTokenLoc, // If this isn't an identifier directive (e.g. is "# 1\n" or "#\n", or // something bogus), skip it. - if (Tok.isNot(tok::identifier)) { + if (Tok.isNot(tok::raw_identifier)) { CurPPLexer->ParsingPreprocessorDirective = false; // Restore comment saving mode. if (CurLexer) CurLexer->SetCommentRetentionState(KeepComments); @@ -234,12 +257,8 @@ void Preprocessor::SkipExcludedConditionalBlock(SourceLocation IfTokenLoc, // to spell an i/e in a strange way that is another letter. Skipping this // allows us to avoid looking up the identifier info for #define/#undef and // other common directives. - bool Invalid = false; - const char *RawCharData = SourceMgr.getCharacterData(Tok.getLocation(), - &Invalid); - if (Invalid) - return; - + const char *RawCharData = Tok.getRawIdentifierData(); + char FirstChar = RawCharData[0]; if (FirstChar >= 'a' && FirstChar <= 'z' && FirstChar != 'i' && FirstChar != 'e') { @@ -279,7 +298,10 @@ void Preprocessor::SkipExcludedConditionalBlock(SourceLocation IfTokenLoc, DiscardUntilEndOfDirective(); CurPPLexer->pushConditionalLevel(Tok.getLocation(), /*wasskipping*/true, /*foundnonskip*/false, - /*fnddelse*/false); + /*foundelse*/false); + + if (Callbacks) + Callbacks->Endif(); } } else if (Directive[0] == 'e') { llvm::StringRef Sub = Directive.substr(1); @@ -288,7 +310,7 @@ void Preprocessor::SkipExcludedConditionalBlock(SourceLocation IfTokenLoc, PPConditionalInfo CondInfo; CondInfo.WasSkipping = true; // Silence bogus warning. bool InCond = CurPPLexer->popConditionalLevel(CondInfo); - InCond = InCond; // Silence warning in no-asserts mode. + (void)InCond; // Silence warning in no-asserts mode. assert(!InCond && "Can't be skipping if not in a conditional!"); // If we popped the outermost skipping block, we're done skipping! @@ -307,6 +329,9 @@ void Preprocessor::SkipExcludedConditionalBlock(SourceLocation IfTokenLoc, // Note that we've seen a #else in this conditional. CondInfo.FoundElse = true; + if (Callbacks) + Callbacks->Else(); + // If the conditional is at the top level, and the #if block wasn't // entered, enter the #else block now. if (!CondInfo.WasSkipping && !CondInfo.FoundNonSkip) { @@ -317,6 +342,7 @@ void Preprocessor::SkipExcludedConditionalBlock(SourceLocation IfTokenLoc, PPConditionalInfo &CondInfo = CurPPLexer->peekConditionalLevel(); bool ShouldEnter; + const SourceLocation ConditionalBegin = CurPPLexer->getSourceLocation(); // If this is in a skipping block or if we're already handled this #if // block, don't bother parsing the condition. if (CondInfo.WasSkipping || CondInfo.FoundNonSkip) { @@ -331,10 +357,14 @@ void Preprocessor::SkipExcludedConditionalBlock(SourceLocation IfTokenLoc, ShouldEnter = EvaluateDirectiveExpression(IfNDefMacro); CurPPLexer->LexingRawMode = true; } + const SourceLocation ConditionalEnd = CurPPLexer->getSourceLocation(); // If this is a #elif with a #else before it, report the error. if (CondInfo.FoundElse) Diag(Tok, diag::pp_err_elif_after_else); + if (Callbacks) + Callbacks->Elif(SourceRange(ConditionalBegin, ConditionalEnd)); + // If this condition is true, enter it! if (ShouldEnter) { CondInfo.FoundNonSkip = true; @@ -366,7 +396,7 @@ void Preprocessor::PTHSkipExcludedConditionalBlock() { // have been consumed by the PTHLexer. Just pop off the condition level. PPConditionalInfo CondInfo; bool InCond = CurPTHLexer->popConditionalLevel(CondInfo); - InCond = InCond; // Silence warning in no-asserts mode. + (void)InCond; // Silence warning in no-asserts mode. assert(!InCond && "Can't be skipping if not in a conditional!"); break; } @@ -568,9 +598,11 @@ TryAgain: // C99 6.10.2 - Source File Inclusion. case tok::pp_include: - return HandleIncludeDirective(Result); // Handle #include. + // Handle #include. + return HandleIncludeDirective(SavedHash.getLocation(), Result); case tok::pp___include_macros: - return HandleIncludeMacrosDirective(Result); // Handle -imacros. + // Handle -imacros. + return HandleIncludeMacrosDirective(SavedHash.getLocation(), Result); // C99 6.10.3 - Macro Replacement. case tok::pp_define: @@ -588,13 +620,13 @@ TryAgain: // C99 6.10.6 - Pragma Directive. case tok::pp_pragma: - return HandlePragmaDirective(); + return HandlePragmaDirective(PIK_HashPragma); // GNU Extensions. case tok::pp_import: - return HandleImportDirective(Result); + return HandleImportDirective(SavedHash.getLocation(), Result); case tok::pp_include_next: - return HandleIncludeNextDirective(Result); + return HandleIncludeNextDirective(SavedHash.getLocation(), Result); case tok::pp_warning: Diag(Result, diag::ext_pp_warning_directive); @@ -622,6 +654,12 @@ TryAgain: // 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. @@ -779,7 +817,9 @@ static bool ReadLineMarkerFlags(bool &IsFileEntry, bool &IsFileExit, FileID CurFileID = SM.getDecomposedInstantiationLoc(FlagTok.getLocation()).first; 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(); @@ -1011,11 +1051,20 @@ bool Preprocessor::GetIncludeFilenameSpelling(SourceLocation Loc, /// false if the > was found, otherwise it returns true if it finds and consumes /// the EOM marker. bool Preprocessor::ConcatenateIncludeName( - llvm::SmallString<128> &FilenameBuffer) { + llvm::SmallString<128> &FilenameBuffer, + SourceLocation &End) { Token CurTok; Lex(CurTok); while (CurTok.isNot(tok::eom)) { + End = CurTok.getLocation(); + + // FIXME: Provide code completion for #includes. + if (CurTok.is(tok::code_completion)) { + Lex(CurTok); + continue; + } + // Append the spelling of this token to the buffer. If there was a space // before it, add it now. if (CurTok.hasLeadingSpace()) @@ -1054,7 +1103,8 @@ bool Preprocessor::ConcatenateIncludeName( /// 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(Token &IncludeTok, +void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc, + Token &IncludeTok, const DirectoryLookup *LookupFrom, bool isImport) { @@ -1064,7 +1114,8 @@ void Preprocessor::HandleIncludeDirective(Token &IncludeTok, // Reserve a buffer to get the spelling. llvm::SmallString<128> FilenameBuffer; llvm::StringRef Filename; - + SourceLocation End; + switch (FilenameTok.getKind()) { case tok::eom: // If the token kind is EOM, the error has already been diagnosed. @@ -1073,13 +1124,14 @@ void Preprocessor::HandleIncludeDirective(Token &IncludeTok, case tok::angle_string_literal: case tok::string_literal: Filename = getSpelling(FilenameTok, FilenameBuffer); + End = FilenameTok.getLocation(); break; case tok::less: // This could be a <foo/bar.h> file coming from a macro expansion. In this // case, glue the tokens together into FilenameBuffer and interpret those. FilenameBuffer.push_back('<'); - if (ConcatenateIncludeName(FilenameBuffer)) + if (ConcatenateIncludeName(FilenameBuffer, End)) return; // Found <eom> but no ">"? Diagnostic already emitted. Filename = FilenameBuffer.str(); break; @@ -1118,6 +1170,11 @@ void Preprocessor::HandleIncludeDirective(Token &IncludeTok, return; } + // Notify the callback object that we've seen an inclusion directive. + if (Callbacks) + Callbacks->InclusionDirective(HashLoc, IncludeTok, Filename, isAngled, File, + End); + // 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. @@ -1147,7 +1204,8 @@ void Preprocessor::HandleIncludeDirective(Token &IncludeTok, /// HandleIncludeNextDirective - Implements #include_next. /// -void Preprocessor::HandleIncludeNextDirective(Token &IncludeNextTok) { +void Preprocessor::HandleIncludeNextDirective(SourceLocation HashLoc, + Token &IncludeNextTok) { Diag(IncludeNextTok, diag::ext_pp_include_next_directive); // #include_next is like #include, except that we start searching after @@ -1164,23 +1222,25 @@ void Preprocessor::HandleIncludeNextDirective(Token &IncludeNextTok) { ++Lookup; } - return HandleIncludeDirective(IncludeNextTok, Lookup); + return HandleIncludeDirective(HashLoc, IncludeNextTok, Lookup); } /// HandleImportDirective - Implements #import. /// -void Preprocessor::HandleImportDirective(Token &ImportTok) { +void Preprocessor::HandleImportDirective(SourceLocation HashLoc, + Token &ImportTok) { if (!Features.ObjC1) // #import is standard for ObjC. Diag(ImportTok, diag::ext_pp_import_directive); - return HandleIncludeDirective(ImportTok, 0, true); + return HandleIncludeDirective(HashLoc, ImportTok, 0, true); } /// HandleIncludeMacrosDirective - The -imacros command line option turns into a /// pseudo directive in the predefines buffer. This handles it by sucking all /// tokens through the preprocessor and discarding them (only keeping the side /// effects on the preprocessor). -void Preprocessor::HandleIncludeMacrosDirective(Token &IncludeMacrosTok) { +void Preprocessor::HandleIncludeMacrosDirective(SourceLocation HashLoc, + Token &IncludeMacrosTok) { // This directive should only occur in the predefines buffer. If not, emit an // error and reject it. SourceLocation Loc = IncludeMacrosTok.getLocation(); @@ -1193,7 +1253,7 @@ void Preprocessor::HandleIncludeMacrosDirective(Token &IncludeMacrosTok) { // Treat this as a normal #include for checking purposes. If this is // successful, it will push a new lexer onto the include stack. - HandleIncludeDirective(IncludeMacrosTok, 0, false); + HandleIncludeDirective(HashLoc, IncludeMacrosTok, 0, false); Token TmpTok; do { @@ -1457,11 +1517,6 @@ void Preprocessor::HandleDefineDirective(Token &DefineTok) { } } - // If this is the primary source file, remember that this macro hasn't been - // used yet. - if (isInPrimaryFile()) - MI->setIsUsed(false); - MI->setDefinitionEndLoc(LastTok.getLocation()); // Finally, if this identifier already had a macro defined for it, verify that @@ -1472,7 +1527,7 @@ void Preprocessor::HandleDefineDirective(Token &DefineTok) { // then don't bother calling MacroInfo::isIdenticalTo. if (!getDiagnostics().getSuppressSystemWarnings() || !SourceMgr.isInSystemHeader(DefineTok.getLocation())) { - if (!OtherMI->isUsed()) + if (!OtherMI->isUsed() && OtherMI->isWarnIfUnused()) Diag(OtherMI->getDefinitionLoc(), diag::pp_macro_not_used); // Macros must be identical. This means all tokens and whitespace @@ -1484,14 +1539,26 @@ void Preprocessor::HandleDefineDirective(Token &DefineTok) { Diag(OtherMI->getDefinitionLoc(), diag::note_previous_definition); } } + if (OtherMI->isWarnIfUnused()) + WarnUnusedMacroLocs.erase(OtherMI->getDefinitionLoc()); ReleaseMacroInfo(OtherMI); } setMacroInfo(MacroNameTok.getIdentifierInfo(), MI); + assert(!MI->isUsed()); + // If we need warning for not using the macro, add its location in the + // warn-because-unused-macro set. If it gets used it will be removed from set. + if (isInPrimaryFile() && // don't warn for include'd macros. + Diags->getDiagnosticLevel(diag::pp_macro_not_used, + MI->getDefinitionLoc()) != Diagnostic::Ignored) { + MI->setIsWarnIfUnused(true); + WarnUnusedMacroLocs.insert(MI->getDefinitionLoc()); + } + // If the callbacks want to know, tell them about the macro definition. if (Callbacks) - Callbacks->MacroDefined(MacroNameTok.getIdentifierInfo(), MI); + Callbacks->MacroDefined(MacroNameTok, MI); } /// HandleUndefDirective - Implements #undef. @@ -1520,8 +1587,10 @@ void Preprocessor::HandleUndefDirective(Token &UndefTok) { // If the callbacks want to know, tell them about the macro #undef. if (Callbacks) - Callbacks->MacroUndefined(MacroNameTok.getLocation(), - MacroNameTok.getIdentifierInfo(), MI); + Callbacks->MacroUndefined(MacroNameTok, MI); + + if (MI->isWarnIfUnused()) + WarnUnusedMacroLocs.erase(MI->getDefinitionLoc()); // Free macro definition. ReleaseMacroInfo(MI); @@ -1575,7 +1644,7 @@ void Preprocessor::HandleIfdefDirective(Token &Result, bool isIfndef, // If there is a macro, process it. if (MI) // Mark it used. - MI->setIsUsed(true); + markMacroAsUsed(MI); // Should we include the stuff contained by this directive? if (!MI == isIfndef) { @@ -1584,11 +1653,18 @@ void Preprocessor::HandleIfdefDirective(Token &Result, bool isIfndef, /*wasskip*/false, /*foundnonskip*/true, /*foundelse*/false); } else { - // No, skip the contents of this block and return the first token after it. + // No, skip the contents of this block. SkipExcludedConditionalBlock(DirectiveTok.getLocation(), /*Foundnonskip*/false, /*FoundElse*/false); } + + if (Callbacks) { + if (isIfndef) + Callbacks->Ifndef(MacroNameTok); + else + Callbacks->Ifdef(MacroNameTok); + } } /// HandleIfDirective - Implements the #if directive. @@ -1597,10 +1673,11 @@ void Preprocessor::HandleIfDirective(Token &IfToken, bool ReadAnyTokensBeforeDirective) { ++NumIf; - // Parse and evaluation the conditional expression. + // Parse and evaluate the conditional expression. IdentifierInfo *IfNDefMacro = 0; - bool ConditionalTrue = EvaluateDirectiveExpression(IfNDefMacro); - + const SourceLocation ConditionalBegin = CurPPLexer->getSourceLocation(); + const bool ConditionalTrue = EvaluateDirectiveExpression(IfNDefMacro); + const SourceLocation ConditionalEnd = CurPPLexer->getSourceLocation(); // If this condition is equivalent to #ifndef X, and if this is the first // directive seen, handle it for the multiple-include optimization. @@ -1617,10 +1694,13 @@ void Preprocessor::HandleIfDirective(Token &IfToken, CurPPLexer->pushConditionalLevel(IfToken.getLocation(), /*wasskip*/false, /*foundnonskip*/true, /*foundelse*/false); } else { - // No, skip the contents of this block and return the first token after it. + // No, skip the contents of this block. SkipExcludedConditionalBlock(IfToken.getLocation(), /*Foundnonskip*/false, /*FoundElse*/false); } + + if (Callbacks) + Callbacks->If(SourceRange(ConditionalBegin, ConditionalEnd)); } /// HandleEndifDirective - Implements the #endif directive. @@ -1644,9 +1724,13 @@ void Preprocessor::HandleEndifDirective(Token &EndifToken) { assert(!CondInfo.WasSkipping && !CurPPLexer->LexingRawMode && "This code should only be reachable in the non-skipping case!"); -} + if (Callbacks) + Callbacks->Endif(); +} +/// HandleElseDirective - Implements the #else directive. +/// void Preprocessor::HandleElseDirective(Token &Result) { ++NumElse; @@ -1666,19 +1750,25 @@ void Preprocessor::HandleElseDirective(Token &Result) { // If this is a #else with a #else before it, report the error. if (CI.FoundElse) Diag(Result, diag::pp_err_else_after_else); - // Finally, skip the rest of the contents of this block and return the first - // token after it. - return SkipExcludedConditionalBlock(CI.IfLoc, /*Foundnonskip*/true, - /*FoundElse*/true); + // Finally, skip the rest of the contents of this block. + SkipExcludedConditionalBlock(CI.IfLoc, /*Foundnonskip*/true, + /*FoundElse*/true); + + if (Callbacks) + Callbacks->Else(); } +/// HandleElifDirective - Implements the #elif directive. +/// void Preprocessor::HandleElifDirective(Token &ElifToken) { ++NumElse; // #elif directive in a non-skipping conditional... start skipping. // We don't care what the condition is, because we will always skip it (since // the block immediately before it was included). + const SourceLocation ConditionalBegin = CurPPLexer->getSourceLocation(); DiscardUntilEndOfDirective(); + const SourceLocation ConditionalEnd = CurPPLexer->getSourceLocation(); PPConditionalInfo CI; if (CurPPLexer->popConditionalLevel(CI)) { @@ -1693,8 +1783,10 @@ 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); - // Finally, skip the rest of the contents of this block and return the first - // token after it. - return SkipExcludedConditionalBlock(CI.IfLoc, /*Foundnonskip*/true, - /*FoundElse*/CI.FoundElse); + // Finally, skip the rest of the contents of this block. + SkipExcludedConditionalBlock(CI.IfLoc, /*Foundnonskip*/true, + /*FoundElse*/CI.FoundElse); + + if (Callbacks) + Callbacks->Elif(SourceRange(ConditionalBegin, ConditionalEnd)); } diff --git a/lib/Lex/PPExpressions.cpp b/lib/Lex/PPExpressions.cpp index 163e869..1451c5a 100644 --- a/lib/Lex/PPExpressions.cpp +++ b/lib/Lex/PPExpressions.cpp @@ -112,7 +112,7 @@ static bool EvaluateDefined(PPValue &Result, Token &PeekTok, DefinedTracker &DT, // If there is a macro, mark it used. if (Result.Val != 0 && ValueLive) { MacroInfo *Macro = PP.getMacroInfo(II); - Macro->setIsUsed(true); + PP.markMacroAsUsed(Macro); } // Consume identifier. @@ -519,7 +519,6 @@ static bool EvaluateDirectiveSubExpr(PPValue &LHS, unsigned MinPrec, RHS.Val.setIsUnsigned(Res.isUnsigned()); } - // FIXME: All of these should detect and report overflow?? bool Overflow = false; switch (Operator) { default: assert(0 && "Unknown operator token!"); @@ -534,9 +533,10 @@ static bool EvaluateDirectiveSubExpr(PPValue &LHS, unsigned MinPrec, break; case tok::slash: if (RHS.Val != 0) { - Res = LHS.Val / RHS.Val; - if (LHS.Val.isSigned()) // MININT/-1 --> overflow. - Overflow = LHS.Val.isMinSignedValue() && RHS.Val.isAllOnesValue(); + if (LHS.Val.isSigned()) + Res = llvm::APSInt(LHS.Val.sdiv_ov(RHS.Val, Overflow), false); + else + Res = LHS.Val / RHS.Val; } else if (ValueLive) { PP.Diag(OpLoc, diag::err_pp_division_by_zero) << LHS.getRange() << RHS.getRange(); @@ -545,23 +545,22 @@ static bool EvaluateDirectiveSubExpr(PPValue &LHS, unsigned MinPrec, break; case tok::star: - Res = LHS.Val * RHS.Val; - if (Res.isSigned() && LHS.Val != 0 && RHS.Val != 0) - Overflow = Res/RHS.Val != LHS.Val || Res/LHS.Val != RHS.Val; + if (Res.isSigned()) + Res = llvm::APSInt(LHS.Val.smul_ov(RHS.Val, Overflow), false); + else + Res = LHS.Val * RHS.Val; break; case tok::lessless: { // Determine whether overflow is about to happen. unsigned ShAmt = static_cast<unsigned>(RHS.Val.getLimitedValue()); - if (ShAmt >= LHS.Val.getBitWidth()) - Overflow = true, ShAmt = LHS.Val.getBitWidth()-1; - else if (LHS.isUnsigned()) - Overflow = false; - else if (LHS.Val.isNonNegative()) // Don't allow sign change. - Overflow = ShAmt >= LHS.Val.countLeadingZeros(); - else - Overflow = ShAmt >= LHS.Val.countLeadingOnes(); - - Res = LHS.Val << ShAmt; + if (LHS.isUnsigned()) { + Overflow = ShAmt >= LHS.Val.getBitWidth(); + if (Overflow) + ShAmt = LHS.Val.getBitWidth()-1; + Res = LHS.Val << ShAmt; + } else { + Res = llvm::APSInt(LHS.Val.sshl_ov(ShAmt, Overflow), false); + } break; } case tok::greatergreater: { @@ -573,20 +572,16 @@ static bool EvaluateDirectiveSubExpr(PPValue &LHS, unsigned MinPrec, break; } case tok::plus: - Res = LHS.Val + RHS.Val; if (LHS.isUnsigned()) - Overflow = false; - else if (LHS.Val.isNonNegative() == RHS.Val.isNonNegative() && - Res.isNonNegative() != LHS.Val.isNonNegative()) - Overflow = true; // Overflow for signed addition. + Res = LHS.Val + RHS.Val; + else + Res = llvm::APSInt(LHS.Val.sadd_ov(RHS.Val, Overflow), false); break; case tok::minus: - Res = LHS.Val - RHS.Val; if (LHS.isUnsigned()) - Overflow = false; - else if (LHS.Val.isNonNegative() != RHS.Val.isNonNegative() && - Res.isNonNegative() != LHS.Val.isNonNegative()) - Overflow = true; // Overflow for signed subtraction. + Res = LHS.Val - RHS.Val; + else + Res = llvm::APSInt(LHS.Val.ssub_ov(RHS.Val, Overflow), false); break; case tok::lessequal: Res = LHS.Val <= RHS.Val; diff --git a/lib/Lex/PPLexerChange.cpp b/lib/Lex/PPLexerChange.cpp index 4a40405..eef42b6 100644 --- a/lib/Lex/PPLexerChange.cpp +++ b/lib/Lex/PPLexerChange.cpp @@ -250,15 +250,11 @@ bool Preprocessor::HandleEndOfFile(Token &Result, bool isEndOfMacro) { CurPPLexer = 0; - // This is the end of the top-level file. If the diag::pp_macro_not_used - // diagnostic is enabled, look for macros that have not been used. - if (getDiagnostics().getDiagnosticLevel(diag::pp_macro_not_used) != - Diagnostic::Ignored) { - for (macro_iterator I = macro_begin(false), E = macro_end(false); - I != E; ++I) - if (!I->second->isUsed()) - Diag(I->second->getDefinitionLoc(), diag::pp_macro_not_used); - } + // This is the end of the top-level file. 'WarnUnusedMacroLocs' has collected + // all macro locations that we need to warn because they are not used. + for (WarnUnusedMacroLocsTy::iterator + I=WarnUnusedMacroLocs.begin(), E=WarnUnusedMacroLocs.end(); I!=E; ++I) + Diag(*I, diag::pp_macro_not_used); return true; } diff --git a/lib/Lex/PPMacroExpansion.cpp b/lib/Lex/PPMacroExpansion.cpp index 9015c27..ba92614 100644 --- a/lib/Lex/PPMacroExpansion.cpp +++ b/lib/Lex/PPMacroExpansion.cpp @@ -20,12 +20,28 @@ #include "clang/Basic/TargetInfo.h" #include "clang/Lex/LexDiagnostic.h" #include "clang/Lex/CodeCompletionHandler.h" +#include "clang/Lex/ExternalPreprocessorSource.h" #include "llvm/ADT/StringSwitch.h" +#include "llvm/Config/config.h" #include "llvm/Support/raw_ostream.h" #include <cstdio> #include <ctime> using namespace clang; +MacroInfo *Preprocessor::getInfoForMacro(IdentifierInfo *II) const { + assert(II->hasMacroDefinition() && "Identifier is not a macro!"); + + llvm::DenseMap<IdentifierInfo*, MacroInfo*>::const_iterator Pos + = Macros.find(II); + if (Pos == Macros.end()) { + // Load this macro from the external source. + getExternalSource()->LoadMacroDefinition(II); + Pos = Macros.find(II); + } + assert(Pos != Macros.end() && "Identifier macro info is missing!"); + return Pos->second; +} + /// setMacroInfo - Specify a macro for this identifier. /// void Preprocessor::setMacroInfo(IdentifierInfo *II, MacroInfo *MI) { @@ -70,6 +86,7 @@ void Preprocessor::RegisterBuiltinMacros() { // Clang Extensions. Ident__has_feature = RegisterBuiltinMacro(*this, "__has_feature"); Ident__has_builtin = RegisterBuiltinMacro(*this, "__has_builtin"); + Ident__has_attribute = RegisterBuiltinMacro(*this, "__has_attribute"); Ident__has_include = RegisterBuiltinMacro(*this, "__has_include"); Ident__has_include_next = RegisterBuiltinMacro(*this, "__has_include_next"); @@ -206,7 +223,7 @@ bool Preprocessor::HandleMacroExpandedIdentifier(Token &Identifier, } // Notice that this macro has been used. - MI->setIsUsed(true); + markMacroAsUsed(MI); // If we started lexing a macro, enter the macro expansion body. @@ -231,6 +248,7 @@ bool Preprocessor::HandleMacroExpandedIdentifier(Token &Identifier, if (IsAtStartOfLine) Identifier.setFlag(Token::StartOfLine); if (HadLeadingSpace) Identifier.setFlag(Token::LeadingSpace); } + Identifier.setFlag(Token::LeadingEmptyMacro); ++NumFastMacroExpanded; return false; @@ -481,16 +499,25 @@ static void ComputeDATE_TIME(SourceLocation &DATELoc, SourceLocation &TIMELoc, "Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec" }; - char TmpBuffer[100]; + char TmpBuffer[32]; +#ifdef LLVM_ON_WIN32 sprintf(TmpBuffer, "\"%s %2d %4d\"", Months[TM->tm_mon], TM->tm_mday, TM->tm_year+1900); +#else + snprintf(TmpBuffer, sizeof(TmpBuffer), "\"%s %2d %4d\"", Months[TM->tm_mon], TM->tm_mday, + TM->tm_year+1900); +#endif Token TmpTok; TmpTok.startToken(); PP.CreateString(TmpBuffer, strlen(TmpBuffer), TmpTok); DATELoc = TmpTok.getLocation(); +#ifdef LLVM_ON_WIN32 sprintf(TmpBuffer, "\"%02d:%02d:%02d\"", TM->tm_hour, TM->tm_min, TM->tm_sec); +#else + snprintf(TmpBuffer, sizeof(TmpBuffer), "\"%02d:%02d:%02d\"", TM->tm_hour, TM->tm_min, TM->tm_sec); +#endif PP.CreateString(TmpBuffer, strlen(TmpBuffer), TmpTok); TIMELoc = TmpTok.getLocation(); } @@ -505,40 +532,77 @@ static bool HasFeature(const Preprocessor &PP, const IdentifierInfo *II) { .Case("attribute_analyzer_noreturn", true) .Case("attribute_cf_returns_not_retained", true) .Case("attribute_cf_returns_retained", true) + .Case("attribute_deprecated_with_message", true) .Case("attribute_ext_vector_type", true) .Case("attribute_ns_returns_not_retained", true) .Case("attribute_ns_returns_retained", true) + .Case("attribute_ns_consumes_self", true) + .Case("attribute_ns_consumed", true) + .Case("attribute_cf_consumed", true) .Case("attribute_objc_ivar_unused", true) .Case("attribute_overloadable", true) + .Case("attribute_unavailable_with_message", true) .Case("blocks", LangOpts.Blocks) - .Case("cxx_attributes", LangOpts.CPlusPlus0x) - .Case("cxx_auto_type", LangOpts.CPlusPlus0x) - .Case("cxx_decltype", LangOpts.CPlusPlus0x) - .Case("cxx_deleted_functions", LangOpts.CPlusPlus0x) .Case("cxx_exceptions", LangOpts.Exceptions) .Case("cxx_rtti", LangOpts.RTTI) - .Case("cxx_static_assert", LangOpts.CPlusPlus0x) + .Case("enumerator_attributes", true) .Case("objc_nonfragile_abi", LangOpts.ObjCNonFragileABI) .Case("objc_weak_class", LangOpts.ObjCNonFragileABI) .Case("ownership_holds", true) .Case("ownership_returns", true) .Case("ownership_takes", true) - .Case("cxx_inline_namespaces", true) - //.Case("cxx_concepts", false) + // C++0x features + .Case("cxx_attributes", LangOpts.CPlusPlus0x) + .Case("cxx_auto_type", LangOpts.CPlusPlus0x) + .Case("cxx_decltype", LangOpts.CPlusPlus0x) + .Case("cxx_default_function_template_args", LangOpts.CPlusPlus0x) + .Case("cxx_deleted_functions", LangOpts.CPlusPlus0x) + .Case("cxx_inline_namespaces", LangOpts.CPlusPlus0x) //.Case("cxx_lambdas", false) //.Case("cxx_nullptr", false) - //.Case("cxx_rvalue_references", false) - //.Case("cxx_variadic_templates", false) + .Case("cxx_reference_qualified_functions", LangOpts.CPlusPlus0x) + .Case("cxx_rvalue_references", LangOpts.CPlusPlus0x) + .Case("cxx_strong_enums", LangOpts.CPlusPlus0x) + .Case("cxx_static_assert", LangOpts.CPlusPlus0x) + .Case("cxx_trailing_return", LangOpts.CPlusPlus0x) + .Case("cxx_variadic_templates", LangOpts.CPlusPlus0x) + // Type traits + .Case("has_nothrow_assign", LangOpts.CPlusPlus) + .Case("has_nothrow_copy", LangOpts.CPlusPlus) + .Case("has_nothrow_constructor", LangOpts.CPlusPlus) + .Case("has_trivial_assign", LangOpts.CPlusPlus) + .Case("has_trivial_copy", LangOpts.CPlusPlus) + .Case("has_trivial_constructor", LangOpts.CPlusPlus) + .Case("has_trivial_destructor", LangOpts.CPlusPlus) + .Case("has_virtual_destructor", LangOpts.CPlusPlus) + .Case("is_abstract", LangOpts.CPlusPlus) + .Case("is_base_of", LangOpts.CPlusPlus) + .Case("is_class", LangOpts.CPlusPlus) + .Case("is_convertible_to", LangOpts.CPlusPlus) + .Case("is_empty", LangOpts.CPlusPlus) + .Case("is_enum", LangOpts.CPlusPlus) + .Case("is_pod", LangOpts.CPlusPlus) + .Case("is_polymorphic", LangOpts.CPlusPlus) + .Case("is_union", LangOpts.CPlusPlus) + .Case("is_literal", LangOpts.CPlusPlus) .Case("tls", PP.getTargetInfo().isTLSSupported()) .Default(false); } +/// HasAttribute - Return true if we recognize and implement the attribute +/// specified by the given identifier. +static bool HasAttribute(const IdentifierInfo *II) { + return llvm::StringSwitch<bool>(II->getName()) +#include "clang/Lex/AttrSpellings.inc" + .Default(false); +} + /// EvaluateHasIncludeCommon - Process a '__has_include("path")' /// or '__has_include_next("path")' expression. /// Returns true if successful. -static bool EvaluateHasIncludeCommon(bool &Result, Token &Tok, - IdentifierInfo *II, Preprocessor &PP, - const DirectoryLookup *LookupFrom) { +static bool EvaluateHasIncludeCommon(Token &Tok, + IdentifierInfo *II, Preprocessor &PP, + const DirectoryLookup *LookupFrom) { SourceLocation LParenLoc; // Get '('. @@ -559,7 +623,8 @@ static bool EvaluateHasIncludeCommon(bool &Result, Token &Tok, // Reserve a buffer to get the spelling. llvm::SmallString<128> FilenameBuffer; llvm::StringRef Filename; - + SourceLocation EndLoc; + switch (Tok.getKind()) { case tok::eom: // If the token kind is EOM, the error has already been diagnosed. @@ -578,7 +643,7 @@ static bool EvaluateHasIncludeCommon(bool &Result, Token &Tok, // This could be a <foo/bar.h> file coming from a macro expansion. In this // case, glue the tokens together into FilenameBuffer and interpret those. FilenameBuffer.push_back('<'); - if (PP.ConcatenateIncludeName(FilenameBuffer)) + if (PP.ConcatenateIncludeName(FilenameBuffer, EndLoc)) return false; // Found <eom> but no ">"? Diagnostic already emitted. Filename = FilenameBuffer.str(); break; @@ -598,7 +663,7 @@ static bool EvaluateHasIncludeCommon(bool &Result, Token &Tok, const FileEntry *File = PP.LookupFile(Filename, isAngled, LookupFrom, CurDir); // Get the result value. Result = true means the file exists. - Result = File != 0; + bool Result = File != 0; // Get ')'. PP.LexNonComment(Tok); @@ -610,19 +675,19 @@ static bool EvaluateHasIncludeCommon(bool &Result, Token &Tok, return false; } - return true; + return Result; } /// EvaluateHasInclude - Process a '__has_include("path")' expression. /// Returns true if successful. -static bool EvaluateHasInclude(bool &Result, Token &Tok, IdentifierInfo *II, +static bool EvaluateHasInclude(Token &Tok, IdentifierInfo *II, Preprocessor &PP) { - return(EvaluateHasIncludeCommon(Result, Tok, II, PP, NULL)); + return EvaluateHasIncludeCommon(Tok, II, PP, NULL); } /// EvaluateHasIncludeNext - Process '__has_include_next("path")' expression. /// Returns true if successful. -static bool EvaluateHasIncludeNext(bool &Result, Token &Tok, +static bool EvaluateHasIncludeNext(Token &Tok, IdentifierInfo *II, Preprocessor &PP) { // __has_include_next is like __has_include, except that we start // searching after the current found directory. If we can't do this, @@ -638,7 +703,7 @@ static bool EvaluateHasIncludeNext(bool &Result, Token &Tok, ++Lookup; } - return(EvaluateHasIncludeCommon(Result, Tok, II, PP, Lookup)); + return EvaluateHasIncludeCommon(Tok, II, PP, Lookup); } /// ExpandBuiltinMacro - If an identifier token is read that is to be expanded @@ -683,7 +748,7 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) { PresumedLoc PLoc = SourceMgr.getPresumedLoc(Loc); // __LINE__ expands to a simple numeric value. - OS << PLoc.getLine(); + OS << (PLoc.isValid()? PLoc.getLine() : 1); Tok.setKind(tok::numeric_constant); } else if (II == Ident__FILE__ || II == Ident__BASE_FILE__) { // C99 6.10.8: "__FILE__: The presumed name of the current source file (a @@ -692,19 +757,24 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) { // __BASE_FILE__ is a GNU extension that returns the top of the presumed // #include stack instead of the current file. - if (II == Ident__BASE_FILE__) { + if (II == Ident__BASE_FILE__ && PLoc.isValid()) { SourceLocation NextLoc = PLoc.getIncludeLoc(); while (NextLoc.isValid()) { PLoc = SourceMgr.getPresumedLoc(NextLoc); + if (PLoc.isInvalid()) + break; + NextLoc = PLoc.getIncludeLoc(); } } // Escape this filename. Turn '\' -> '\\' '"' -> '\"' llvm::SmallString<128> FN; - FN += PLoc.getFilename(); - Lexer::Stringify(FN); - OS << '"' << FN.str() << '"'; + if (PLoc.isValid()) { + FN += PLoc.getFilename(); + Lexer::Stringify(FN); + OS << '"' << FN.str() << '"'; + } Tok.setKind(tok::string_literal); } else if (II == Ident__DATE__) { if (!DATELoc.isValid()) @@ -730,9 +800,11 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) { unsigned Depth = 0; PresumedLoc PLoc = SourceMgr.getPresumedLoc(Tok.getLocation()); - PLoc = SourceMgr.getPresumedLoc(PLoc.getIncludeLoc()); - for (; PLoc.isValid(); ++Depth) + if (PLoc.isValid()) { PLoc = SourceMgr.getPresumedLoc(PLoc.getIncludeLoc()); + for (; PLoc.isValid(); ++Depth) + PLoc = SourceMgr.getPresumedLoc(PLoc.getIncludeLoc()); + } // __INCLUDE_LEVEL__ expands to a simple numeric value. OS << Depth; @@ -765,7 +837,8 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) { OS << CounterValue++; Tok.setKind(tok::numeric_constant); } else if (II == Ident__has_feature || - II == Ident__has_builtin) { + II == Ident__has_builtin || + II == Ident__has_attribute) { // The argument to these two builtins should be a parenthesized identifier. SourceLocation StartLoc = Tok.getLocation(); @@ -793,7 +866,9 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) { else if (II == Ident__has_builtin) { // Check for a builtin is trivial. Value = FeatureII->getBuiltinID() != 0; - } else { + } else if (II == Ident__has_attribute) + Value = HasAttribute(FeatureII); + else { assert(II == Ident__has_feature && "Must be feature check"); Value = HasFeature(*this, FeatureII); } @@ -805,12 +880,11 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) { // The argument to these two builtins should be a parenthesized // file name string literal using angle brackets (<>) or // double-quotes (""). - bool Value = false; - bool IsValid; + bool Value; if (II == Ident__has_include) - IsValid = EvaluateHasInclude(Value, Tok, II, *this); + Value = EvaluateHasInclude(Tok, II, *this); else - IsValid = EvaluateHasIncludeNext(Value, Tok, II, *this); + Value = EvaluateHasIncludeNext(Tok, II, *this); OS << (int)Value; Tok.setKind(tok::numeric_constant); } else { @@ -818,3 +892,11 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) { } CreateString(OS.str().data(), OS.str().size(), Tok, Tok.getLocation()); } + +void Preprocessor::markMacroAsUsed(MacroInfo *MI) { + // If the 'used' status changed, and the macro requires 'unused' warning, + // remove its SourceLocation from the warn-for-unused-macro locations. + if (MI->isWarnIfUnused() && !MI->isUsed()) + WarnUnusedMacroLocs.erase(MI->getDefinitionLoc()); + MI->setIsUsed(true); +} diff --git a/lib/Lex/PTHLexer.cpp b/lib/Lex/PTHLexer.cpp index 63b4823..975753b 100644 --- a/lib/Lex/PTHLexer.cpp +++ b/lib/Lex/PTHLexer.cpp @@ -13,6 +13,7 @@ #include "clang/Basic/TokenKinds.h" #include "clang/Basic/FileManager.h" +#include "clang/Basic/FileSystemStatCache.h" #include "clang/Basic/IdentifierTable.h" #include "clang/Basic/OnDiskHashTable.h" #include "clang/Lex/LexDiagnostic.h" @@ -25,7 +26,7 @@ #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringMap.h" #include "llvm/Support/MemoryBuffer.h" -#include <sys/stat.h> +#include "llvm/Support/system_error.h" using namespace clang; using namespace clang::io; @@ -434,23 +435,23 @@ static void InvalidPTH(Diagnostic &Diags, const char *Msg) { Diags.Report(Diags.getCustomDiagID(Diagnostic::Error, Msg)); } -PTHManager* PTHManager::Create(const std::string& file, Diagnostic &Diags) { +PTHManager *PTHManager::Create(const std::string &file, Diagnostic &Diags) { // Memory map the PTH file. - llvm::OwningPtr<llvm::MemoryBuffer> - File(llvm::MemoryBuffer::getFile(file.c_str())); + llvm::OwningPtr<llvm::MemoryBuffer> File; - if (!File) { + if (llvm::MemoryBuffer::getFile(file, File)) { + // FIXME: Add ec.message() to this diag. Diags.Report(diag::err_invalid_pth_file) << file; return 0; } // Get the buffer ranges and check if there are at least three 32-bit // words at the end of the file. - const unsigned char* BufBeg = (unsigned char*)File->getBufferStart(); - const unsigned char* BufEnd = (unsigned char*)File->getBufferEnd(); + const unsigned char *BufBeg = (unsigned char*)File->getBufferStart(); + const unsigned char *BufEnd = (unsigned char*)File->getBufferEnd(); // Check the prologue of the file. - if ((BufEnd - BufBeg) < (signed) (sizeof("cfe-pth") + 3 + 4) || + if ((BufEnd - BufBeg) < (signed)(sizeof("cfe-pth") + 3 + 4) || memcmp(BufBeg, "cfe-pth", sizeof("cfe-pth") - 1) != 0) { Diags.Report(diag::err_invalid_pth_file) << file; return 0; @@ -668,7 +669,7 @@ public: } }; -class PTHStatCache : public StatSysCallCache { +class PTHStatCache : public FileSystemStatCache { typedef OnDiskChainedHashTable<PTHStatLookupTrait> CacheTy; CacheTy Cache; @@ -679,29 +680,30 @@ public: ~PTHStatCache() {} - int stat(const char *path, struct stat *buf) { + LookupResult getStat(const char *Path, struct stat &StatBuf, + int *FileDescriptor) { // Do the lookup for the file's data in the PTH file. - CacheTy::iterator I = Cache.find(path); + CacheTy::iterator I = Cache.find(Path); // If we don't get a hit in the PTH file just forward to 'stat'. if (I == Cache.end()) - return StatSysCallCache::stat(path, buf); + return statChained(Path, StatBuf, FileDescriptor); - const PTHStatData& Data = *I; + const PTHStatData &Data = *I; if (!Data.hasStat) - return 1; + return CacheMissing; - buf->st_ino = Data.ino; - buf->st_dev = Data.dev; - buf->st_mtime = Data.mtime; - buf->st_mode = Data.mode; - buf->st_size = Data.size; - return 0; + StatBuf.st_ino = Data.ino; + StatBuf.st_dev = Data.dev; + StatBuf.st_mtime = Data.mtime; + StatBuf.st_mode = Data.mode; + StatBuf.st_size = Data.size; + return CacheExists; } }; } // end anonymous namespace -StatSysCallCache *PTHManager::createStatCache() { +FileSystemStatCache *PTHManager::createStatCache() { return new PTHStatCache(*((PTHFileLookup*) FileLookup)); } diff --git a/lib/Lex/Pragma.cpp b/lib/Lex/Pragma.cpp index a7b289e..f0475bc 100644 --- a/lib/Lex/Pragma.cpp +++ b/lib/Lex/Pragma.cpp @@ -35,7 +35,9 @@ PragmaHandler::~PragmaHandler() { EmptyPragmaHandler::EmptyPragmaHandler() {} -void EmptyPragmaHandler::HandlePragma(Preprocessor &PP, Token &FirstToken) {} +void EmptyPragmaHandler::HandlePragma(Preprocessor &PP, + PragmaIntroducerKind Introducer, + Token &FirstToken) {} //===----------------------------------------------------------------------===// // PragmaNamespace Implementation. @@ -73,7 +75,9 @@ void PragmaNamespace::RemovePragmaHandler(PragmaHandler *Handler) { Handlers.erase(Handler->getName()); } -void PragmaNamespace::HandlePragma(Preprocessor &PP, Token &Tok) { +void PragmaNamespace::HandlePragma(Preprocessor &PP, + PragmaIntroducerKind Introducer, + Token &Tok) { // Read the 'namespace' that the directive is in, e.g. STDC. Do not macro // expand it, the user can have a STDC #define, that should not affect this. PP.LexUnexpandedToken(Tok); @@ -89,7 +93,7 @@ void PragmaNamespace::HandlePragma(Preprocessor &PP, Token &Tok) { } // Otherwise, pass it down. - Handler->HandlePragma(PP, Tok); + Handler->HandlePragma(PP, Introducer, Tok); } //===----------------------------------------------------------------------===// @@ -98,12 +102,12 @@ void PragmaNamespace::HandlePragma(Preprocessor &PP, Token &Tok) { /// HandlePragmaDirective - The "#pragma" directive has been parsed. Lex the /// rest of the pragma, passing it to the registered pragma handlers. -void Preprocessor::HandlePragmaDirective() { +void Preprocessor::HandlePragmaDirective(unsigned Introducer) { ++NumPragma; // Invoke the first level of pragma handlers which reads the namespace id. Token Tok; - PragmaHandlers->HandlePragma(*this, Tok); + PragmaHandlers->HandlePragma(*this, PragmaIntroducerKind(Introducer), Tok); // If the pragma handler didn't read the rest of the line, consume it now. if (CurPPLexer && CurPPLexer->ParsingPreprocessorDirective) @@ -170,7 +174,7 @@ void Preprocessor::Handle_Pragma(Token &Tok) { } } - Handle_Pragma(StrVal, PragmaLoc, RParenLoc); + Handle_Pragma(PIK__Pragma, StrVal, PragmaLoc, RParenLoc); // Finally, return whatever came after the pragma directive. return Lex(Tok); @@ -216,13 +220,14 @@ void Preprocessor::HandleMicrosoft__pragma(Token &Tok) { SourceLocation RParenLoc = Tok.getLocation(); - Handle_Pragma(StrVal, PragmaLoc, RParenLoc); + Handle_Pragma(PIK___pragma, StrVal, PragmaLoc, RParenLoc); // Finally, return whatever came after the pragma directive. return Lex(Tok); } -void Preprocessor::Handle_Pragma(const std::string &StrVal, +void Preprocessor::Handle_Pragma(unsigned Introducer, + const std::string &StrVal, SourceLocation PragmaLoc, SourceLocation RParenLoc) { @@ -241,7 +246,7 @@ void Preprocessor::Handle_Pragma(const std::string &StrVal, EnterSourceFileWithLexer(TL, 0); // With everything set up, lex this as a #pragma directive. - HandlePragmaDirective(); + HandlePragmaDirective(Introducer); } @@ -287,7 +292,7 @@ void Preprocessor::HandlePragmaPoison(Token &PoisonTok) { if (Tok.is(tok::eom)) return; // Can only poison identifiers. - if (Tok.isNot(tok::identifier)) { + if (Tok.isNot(tok::raw_identifier)) { Diag(Tok, diag::err_pp_invalid_poison); return; } @@ -324,6 +329,9 @@ void Preprocessor::HandlePragmaSystemHeader(Token &SysHeaderTok) { PresumedLoc PLoc = SourceMgr.getPresumedLoc(SysHeaderTok.getLocation()); + if (PLoc.isInvalid()) + return; + unsigned FilenameLen = strlen(PLoc.getFilename()); unsigned FilenameID = SourceMgr.getLineTableFilenameID(PLoc.getFilename(), FilenameLen); @@ -478,23 +486,32 @@ void Preprocessor::HandlePragmaComment(Token &Tok) { Callbacks->PragmaComment(CommentLoc, II, ArgumentString); } -/// HandlePragmaMessage - Handle the microsoft #pragma message extension. The -/// syntax is: -/// #pragma message(messagestring) -/// messagestring is a string, which is fully macro expanded, and permits string -/// concatenation, embedded escape characters etc. See MSDN for more details. +/// HandlePragmaMessage - Handle the microsoft and gcc #pragma message +/// extension. The syntax is: +/// #pragma message(string) +/// OR, in GCC mode: +/// #pragma message string +/// string is a string, which is fully macro expanded, and permits string +/// concatenation, embedded escape characters, etc... See MSDN for more details. void Preprocessor::HandlePragmaMessage(Token &Tok) { SourceLocation MessageLoc = Tok.getLocation(); Lex(Tok); - if (Tok.isNot(tok::l_paren)) { + bool ExpectClosingParen = false; + switch (Tok.getKind()) { + case tok::l_paren: + // We have a MSVC style pragma message. + ExpectClosingParen = true; + // Read the string. + Lex(Tok); + break; + case tok::string_literal: + // We have a GCC style pragma message, and we just read the string. + break; + default: Diag(MessageLoc, diag::err_pragma_message_malformed); return; } - // Read the string. - Lex(Tok); - - // We need at least one string. if (Tok.isNot(tok::string_literal)) { Diag(Tok.getLocation(), diag::err_pragma_message_malformed); @@ -522,11 +539,13 @@ void Preprocessor::HandlePragmaMessage(Token &Tok) { llvm::StringRef MessageString(Literal.GetString(), Literal.GetStringLength()); - if (Tok.isNot(tok::r_paren)) { - Diag(Tok.getLocation(), diag::err_pragma_message_malformed); - return; + if (ExpectClosingParen) { + if (Tok.isNot(tok::r_paren)) { + Diag(Tok.getLocation(), diag::err_pragma_message_malformed); + return; + } + Lex(Tok); // eat the r_paren. } - Lex(Tok); // eat the r_paren. if (Tok.isNot(tok::eom)) { Diag(Tok.getLocation(), diag::err_pragma_message_malformed); @@ -580,7 +599,7 @@ IdentifierInfo *Preprocessor::ParsePragmaPushOrPopMacro(Token &Tok) { // Create a Token from the string. Token MacroTok; MacroTok.startToken(); - MacroTok.setKind(tok::identifier); + MacroTok.setKind(tok::raw_identifier); CreateString(&StrVal[1], StrVal.size() - 2, MacroTok); // Get the IdentifierInfo of MacroToPushTok. @@ -611,7 +630,7 @@ void Preprocessor::HandlePragmaPushMacro(Token &PushMacroTok) { PragmaPushMacroInfo[IdentInfo].push_back(MacroCopyToPush); } -/// HandlePragmaPopMacro - Handle #pragma push_macro. +/// HandlePragmaPopMacro - Handle #pragma pop_macro. /// The syntax is: /// #pragma pop_macro("macro") void Preprocessor::HandlePragmaPopMacro(Token &PopMacroTok) { @@ -627,7 +646,11 @@ void Preprocessor::HandlePragmaPopMacro(Token &PopMacroTok) { if (iter != PragmaPushMacroInfo.end()) { // Release the MacroInfo currently associated with IdentInfo. MacroInfo *CurrentMI = getMacroInfo(IdentInfo); - if (CurrentMI) ReleaseMacroInfo(CurrentMI); + if (CurrentMI) { + if (CurrentMI->isWarnIfUnused()) + WarnUnusedMacroLocs.erase(CurrentMI->getDefinitionLoc()); + ReleaseMacroInfo(CurrentMI); + } // Get the MacroInfo we want to reinstall. MacroInfo *MacroToReInstall = iter->second.back(); @@ -700,11 +723,39 @@ void Preprocessor::RemovePragmaHandler(llvm::StringRef Namespace, PragmaHandlers->RemovePragmaHandler(NS); } +bool Preprocessor::LexOnOffSwitch(tok::OnOffSwitch &Result) { + Token Tok; + LexUnexpandedToken(Tok); + + if (Tok.isNot(tok::identifier)) { + Diag(Tok, diag::ext_on_off_switch_syntax); + return true; + } + IdentifierInfo *II = Tok.getIdentifierInfo(); + if (II->isStr("ON")) + Result = tok::OOS_ON; + else if (II->isStr("OFF")) + Result = tok::OOS_OFF; + else if (II->isStr("DEFAULT")) + Result = tok::OOS_DEFAULT; + else { + Diag(Tok, diag::ext_on_off_switch_syntax); + return true; + } + + // Verify that this is followed by EOM. + LexUnexpandedToken(Tok); + if (Tok.isNot(tok::eom)) + Diag(Tok, diag::ext_pragma_syntax_eom); + return false; +} + namespace { /// PragmaOnceHandler - "#pragma once" marks the file as atomically included. struct PragmaOnceHandler : public PragmaHandler { PragmaOnceHandler() : PragmaHandler("once") {} - virtual void HandlePragma(Preprocessor &PP, Token &OnceTok) { + virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &OnceTok) { PP.CheckEndOfDirective("pragma once"); PP.HandlePragmaOnce(OnceTok); } @@ -714,7 +765,8 @@ struct PragmaOnceHandler : public PragmaHandler { /// rest of the line is not lexed. struct PragmaMarkHandler : public PragmaHandler { PragmaMarkHandler() : PragmaHandler("mark") {} - virtual void HandlePragma(Preprocessor &PP, Token &MarkTok) { + virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &MarkTok) { PP.HandlePragmaMark(); } }; @@ -722,7 +774,8 @@ struct PragmaMarkHandler : public PragmaHandler { /// PragmaPoisonHandler - "#pragma poison x" marks x as not usable. struct PragmaPoisonHandler : public PragmaHandler { PragmaPoisonHandler() : PragmaHandler("poison") {} - virtual void HandlePragma(Preprocessor &PP, Token &PoisonTok) { + virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &PoisonTok) { PP.HandlePragmaPoison(PoisonTok); } }; @@ -731,21 +784,24 @@ struct PragmaPoisonHandler : public PragmaHandler { /// as a system header, which silences warnings in it. struct PragmaSystemHeaderHandler : public PragmaHandler { PragmaSystemHeaderHandler() : PragmaHandler("system_header") {} - virtual void HandlePragma(Preprocessor &PP, Token &SHToken) { + virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &SHToken) { PP.HandlePragmaSystemHeader(SHToken); PP.CheckEndOfDirective("pragma"); } }; struct PragmaDependencyHandler : public PragmaHandler { PragmaDependencyHandler() : PragmaHandler("dependency") {} - virtual void HandlePragma(Preprocessor &PP, Token &DepToken) { + virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &DepToken) { PP.HandlePragmaDependency(DepToken); } }; struct PragmaDebugHandler : public PragmaHandler { PragmaDebugHandler() : PragmaHandler("__debug") {} - virtual void HandlePragma(Preprocessor &PP, Token &DepToken) { + virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &DepToken) { Token Tok; PP.LexUnexpandedToken(Tok); if (Tok.isNot(tok::identifier)) { @@ -783,7 +839,9 @@ struct PragmaDebugHandler : public PragmaHandler { struct PragmaDiagnosticHandler : public PragmaHandler { public: explicit PragmaDiagnosticHandler() : PragmaHandler("diagnostic") {} - virtual void HandlePragma(Preprocessor &PP, Token &DiagToken) { + virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &DiagToken) { + SourceLocation DiagLoc = DiagToken.getLocation(); Token Tok; PP.LexUnexpandedToken(Tok); if (Tok.isNot(tok::identifier)) { @@ -802,12 +860,12 @@ public: else if (II->isStr("fatal")) Map = diag::MAP_FATAL; else if (II->isStr("pop")) { - if (!PP.getDiagnostics().popMappings()) + if (!PP.getDiagnostics().popMappings(DiagLoc)) PP.Diag(Tok, diag::warn_pragma_diagnostic_cannot_pop); return; } else if (II->isStr("push")) { - PP.getDiagnostics().pushMappings(); + PP.getDiagnostics().pushMappings(DiagLoc); return; } else { PP.Diag(Tok, diag::warn_pragma_diagnostic_invalid); @@ -857,7 +915,7 @@ public: } if (PP.getDiagnostics().setDiagnosticGroupMapping(WarningName.c_str()+2, - Map)) + Map, DiagLoc)) PP.Diag(StrToks[0].getLocation(), diag::warn_pragma_diagnostic_unknown_warning) << WarningName; } @@ -866,7 +924,8 @@ public: /// PragmaCommentHandler - "#pragma comment ...". struct PragmaCommentHandler : public PragmaHandler { PragmaCommentHandler() : PragmaHandler("comment") {} - virtual void HandlePragma(Preprocessor &PP, Token &CommentTok) { + virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &CommentTok) { PP.HandlePragmaComment(CommentTok); } }; @@ -874,7 +933,8 @@ struct PragmaCommentHandler : public PragmaHandler { /// PragmaMessageHandler - "#pragma message("...")". struct PragmaMessageHandler : public PragmaHandler { PragmaMessageHandler() : PragmaHandler("message") {} - virtual void HandlePragma(Preprocessor &PP, Token &CommentTok) { + virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &CommentTok) { PP.HandlePragmaMessage(CommentTok); } }; @@ -883,7 +943,8 @@ struct PragmaMessageHandler : public PragmaHandler { /// macro on the top of the stack. struct PragmaPushMacroHandler : public PragmaHandler { PragmaPushMacroHandler() : PragmaHandler("push_macro") {} - virtual void HandlePragma(Preprocessor &PP, Token &PushMacroTok) { + virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &PushMacroTok) { PP.HandlePragmaPushMacro(PushMacroTok); } }; @@ -893,62 +954,23 @@ struct PragmaPushMacroHandler : public PragmaHandler { /// macro to the value on the top of the stack. struct PragmaPopMacroHandler : public PragmaHandler { PragmaPopMacroHandler() : PragmaHandler("pop_macro") {} - virtual void HandlePragma(Preprocessor &PP, Token &PopMacroTok) { + virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &PopMacroTok) { PP.HandlePragmaPopMacro(PopMacroTok); } }; // Pragma STDC implementations. -enum STDCSetting { - STDC_ON, STDC_OFF, STDC_DEFAULT, STDC_INVALID -}; - -static STDCSetting LexOnOffSwitch(Preprocessor &PP) { - Token Tok; - PP.LexUnexpandedToken(Tok); - - if (Tok.isNot(tok::identifier)) { - PP.Diag(Tok, diag::ext_stdc_pragma_syntax); - return STDC_INVALID; - } - IdentifierInfo *II = Tok.getIdentifierInfo(); - STDCSetting Result; - if (II->isStr("ON")) - Result = STDC_ON; - else if (II->isStr("OFF")) - Result = STDC_OFF; - else if (II->isStr("DEFAULT")) - Result = STDC_DEFAULT; - else { - PP.Diag(Tok, diag::ext_stdc_pragma_syntax); - return STDC_INVALID; - } - - // Verify that this is followed by EOM. - PP.LexUnexpandedToken(Tok); - if (Tok.isNot(tok::eom)) - PP.Diag(Tok, diag::ext_stdc_pragma_syntax_eom); - return Result; -} - -/// PragmaSTDC_FP_CONTRACTHandler - "#pragma STDC FP_CONTRACT ...". -struct PragmaSTDC_FP_CONTRACTHandler : public PragmaHandler { - PragmaSTDC_FP_CONTRACTHandler() : PragmaHandler("FP_CONTRACT") {} - virtual void HandlePragma(Preprocessor &PP, Token &Tok) { - // We just ignore the setting of FP_CONTRACT. Since we don't do contractions - // at all, our default is OFF and setting it to ON is an optimization hint - // we can safely ignore. When we support -ffma or something, we would need - // to diagnose that we are ignoring FMA. - LexOnOffSwitch(PP); - } -}; - /// PragmaSTDC_FENV_ACCESSHandler - "#pragma STDC FENV_ACCESS ...". struct PragmaSTDC_FENV_ACCESSHandler : public PragmaHandler { PragmaSTDC_FENV_ACCESSHandler() : PragmaHandler("FENV_ACCESS") {} - virtual void HandlePragma(Preprocessor &PP, Token &Tok) { - if (LexOnOffSwitch(PP) == STDC_ON) + virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &Tok) { + tok::OnOffSwitch OOS; + if (PP.LexOnOffSwitch(OOS)) + return; + if (OOS == tok::OOS_ON) PP.Diag(Tok, diag::warn_stdc_fenv_access_not_supported); } }; @@ -957,15 +979,18 @@ struct PragmaSTDC_FENV_ACCESSHandler : public PragmaHandler { struct PragmaSTDC_CX_LIMITED_RANGEHandler : public PragmaHandler { PragmaSTDC_CX_LIMITED_RANGEHandler() : PragmaHandler("CX_LIMITED_RANGE") {} - virtual void HandlePragma(Preprocessor &PP, Token &Tok) { - LexOnOffSwitch(PP); + virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &Tok) { + tok::OnOffSwitch OOS; + PP.LexOnOffSwitch(OOS); } }; /// PragmaSTDC_UnknownHandler - "#pragma STDC ...". struct PragmaSTDC_UnknownHandler : public PragmaHandler { PragmaSTDC_UnknownHandler() {} - virtual void HandlePragma(Preprocessor &PP, Token &UnknownTok) { + virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &UnknownTok) { // C99 6.10.6p2, unknown forms are not allowed. PP.Diag(UnknownTok, diag::ext_stdc_pragma_ignored); } @@ -981,6 +1006,7 @@ void Preprocessor::RegisterBuiltinPragmas() { AddPragmaHandler(new PragmaMarkHandler()); AddPragmaHandler(new PragmaPushMacroHandler()); AddPragmaHandler(new PragmaPopMacroHandler()); + AddPragmaHandler(new PragmaMessageHandler()); // #pragma GCC ... AddPragmaHandler("GCC", new PragmaPoisonHandler()); @@ -994,7 +1020,6 @@ void Preprocessor::RegisterBuiltinPragmas() { AddPragmaHandler("clang", new PragmaDependencyHandler()); AddPragmaHandler("clang", new PragmaDiagnosticHandler()); - AddPragmaHandler("STDC", new PragmaSTDC_FP_CONTRACTHandler()); AddPragmaHandler("STDC", new PragmaSTDC_FENV_ACCESSHandler()); AddPragmaHandler("STDC", new PragmaSTDC_CX_LIMITED_RANGEHandler()); AddPragmaHandler("STDC", new PragmaSTDC_UnknownHandler()); @@ -1002,6 +1027,5 @@ void Preprocessor::RegisterBuiltinPragmas() { // MS extensions. if (Features.Microsoft) { AddPragmaHandler(new PragmaCommentHandler()); - AddPragmaHandler(new PragmaMessageHandler()); } } diff --git a/lib/Lex/PreprocessingRecord.cpp b/lib/Lex/PreprocessingRecord.cpp index c446d96..3a43ac1 100644 --- a/lib/Lex/PreprocessingRecord.cpp +++ b/lib/Lex/PreprocessingRecord.cpp @@ -14,11 +14,29 @@ #include "clang/Lex/PreprocessingRecord.h" #include "clang/Lex/MacroInfo.h" #include "clang/Lex/Token.h" +#include "clang/Basic/IdentifierTable.h" +#include "llvm/Support/ErrorHandling.h" using namespace clang; ExternalPreprocessingRecordSource::~ExternalPreprocessingRecordSource() { } + +InclusionDirective::InclusionDirective(PreprocessingRecord &PPRec, + InclusionKind Kind, + llvm::StringRef FileName, + bool InQuotes, const FileEntry *File, + SourceRange Range) + : PreprocessingDirective(InclusionDirectiveKind, Range), + InQuotes(InQuotes), Kind(Kind), File(File) +{ + char *Memory + = (char*)PPRec.Allocate(FileName.size() + 1, llvm::alignOf<char>()); + memcpy(Memory, FileName.data(), FileName.size()); + Memory[FileName.size()] = 0; + this->FileName = llvm::StringRef(Memory, FileName.size()); +} + void PreprocessingRecord::MaybeLoadPreallocatedEntities() const { if (!ExternalSource || LoadedPreallocatedEntities) return; @@ -109,17 +127,18 @@ void PreprocessingRecord::MacroExpands(const Token &Id, const MacroInfo* MI) { Def)); } -void PreprocessingRecord::MacroDefined(const IdentifierInfo *II, +void PreprocessingRecord::MacroDefined(const Token &Id, const MacroInfo *MI) { SourceRange R(MI->getDefinitionLoc(), MI->getDefinitionEndLoc()); MacroDefinition *Def - = new (*this) MacroDefinition(II, MI->getDefinitionLoc(), R); + = new (*this) MacroDefinition(Id.getIdentifierInfo(), + MI->getDefinitionLoc(), + R); MacroDefinitions[MI] = Def; PreprocessedEntities.push_back(Def); } -void PreprocessingRecord::MacroUndefined(SourceLocation Loc, - const IdentifierInfo *II, +void PreprocessingRecord::MacroUndefined(const Token &Id, const MacroInfo *MI) { llvm::DenseMap<const MacroInfo *, MacroDefinition *>::iterator Pos = MacroDefinitions.find(MI); @@ -127,3 +146,38 @@ void PreprocessingRecord::MacroUndefined(SourceLocation Loc, MacroDefinitions.erase(Pos); } +void PreprocessingRecord::InclusionDirective(SourceLocation HashLoc, + const clang::Token &IncludeTok, + llvm::StringRef FileName, + bool IsAngled, + const FileEntry *File, + clang::SourceLocation EndLoc) { + InclusionDirective::InclusionKind Kind = InclusionDirective::Include; + + switch (IncludeTok.getIdentifierInfo()->getPPKeywordID()) { + case tok::pp_include: + Kind = InclusionDirective::Include; + break; + + case tok::pp_import: + Kind = InclusionDirective::Import; + break; + + case tok::pp_include_next: + Kind = InclusionDirective::IncludeNext; + break; + + case tok::pp___include_macros: + Kind = InclusionDirective::IncludeMacros; + break; + + default: + llvm_unreachable("Unknown include directive kind"); + return; + } + + clang::InclusionDirective *ID + = new (*this) clang::InclusionDirective(*this, Kind, FileName, !IsAngled, + File, SourceRange(HashLoc, EndLoc)); + PreprocessedEntities.push_back(ID); +} diff --git a/lib/Lex/Preprocessor.cpp b/lib/Lex/Preprocessor.cpp index 5160acf..6fe414b 100644 --- a/lib/Lex/Preprocessor.cpp +++ b/lib/Lex/Preprocessor.cpp @@ -53,10 +53,12 @@ Preprocessor::Preprocessor(Diagnostic &diags, const LangOptions &opts, IdentifierInfoLookup* IILookup, bool OwnsHeaders) : Diags(&diags), Features(opts), Target(target),FileMgr(Headers.getFileMgr()), - SourceMgr(SM), HeaderInfo(Headers), ExternalSource(0), + SourceMgr(SM), + HeaderInfo(Headers), ExternalSource(0), Identifiers(opts, IILookup), BuiltinInfo(Target), CodeComplete(0), CodeCompletionFile(0), SkipMainFilePreamble(0, true), CurPPLexer(0), - CurDirLookup(0), Callbacks(0), MacroArgCache(0), Record(0) { + CurDirLookup(0), Callbacks(0), MacroArgCache(0), Record(0), MIChainHead(0), + MICache(0) { ScratchBuf = new ScratchBuffer(SourceMgr); CounterValue = 0; // __COUNTER__ starts at 0. OwnsHeaderSearch = OwnsHeaders; @@ -106,23 +108,8 @@ Preprocessor::~Preprocessor() { } // Free any macro definitions. - for (llvm::DenseMap<IdentifierInfo*, MacroInfo*>::iterator I = - Macros.begin(), E = Macros.end(); I != E; ++I) { - // We don't need to free the MacroInfo objects directly. These - // will be released when the BumpPtrAllocator 'BP' object gets - // destroyed. We still need to run the dtor, however, to free - // memory alocated by MacroInfo. - I->second->Destroy(); - I->first->setHasMacroDefinition(false); - } - for (std::vector<MacroInfo*>::iterator I = MICache.begin(), - E = MICache.end(); I != E; ++I) { - // We don't need to free the MacroInfo objects directly. These - // will be released when the BumpPtrAllocator 'BP' object gets - // destroyed. We still need to run the dtor, however, to free - // memory alocated by MacroInfo. - (*I)->Destroy(); - } + for (MacroInfoChain *I = MIChainHead ; I ; I = I->Next) + I->MI.Destroy(); // Free any cached macro expanders. for (unsigned i = 0, e = NumCachedTokenLexers; i != e; ++i) @@ -291,114 +278,6 @@ void Preprocessor::CodeCompleteNaturalLanguage() { CodeComplete->CodeCompleteNaturalLanguage(); } -//===----------------------------------------------------------------------===// -// Token Spelling -//===----------------------------------------------------------------------===// - -/// getSpelling() - Return the 'spelling' of this token. The spelling of a -/// token are the characters used to represent the token in the source file -/// after trigraph expansion and escaped-newline folding. In particular, this -/// wants to get the true, uncanonicalized, spelling of things like digraphs -/// UCNs, etc. -std::string Preprocessor::getSpelling(const Token &Tok, - const SourceManager &SourceMgr, - const LangOptions &Features, - bool *Invalid) { - assert((int)Tok.getLength() >= 0 && "Token character range is bogus!"); - - // If this token contains nothing interesting, return it directly. - bool CharDataInvalid = false; - const char* TokStart = SourceMgr.getCharacterData(Tok.getLocation(), - &CharDataInvalid); - if (Invalid) - *Invalid = CharDataInvalid; - if (CharDataInvalid) - return std::string(); - - if (!Tok.needsCleaning()) - return std::string(TokStart, TokStart+Tok.getLength()); - - std::string Result; - Result.reserve(Tok.getLength()); - - // Otherwise, hard case, relex the characters into the string. - for (const char *Ptr = TokStart, *End = TokStart+Tok.getLength(); - Ptr != End; ) { - unsigned CharSize; - Result.push_back(Lexer::getCharAndSizeNoWarn(Ptr, CharSize, Features)); - Ptr += CharSize; - } - assert(Result.size() != unsigned(Tok.getLength()) && - "NeedsCleaning flag set on something that didn't need cleaning!"); - return Result; -} - -/// getSpelling() - Return the 'spelling' of this token. The spelling of a -/// token are the characters used to represent the token in the source file -/// after trigraph expansion and escaped-newline folding. In particular, this -/// wants to get the true, uncanonicalized, spelling of things like digraphs -/// UCNs, etc. -std::string Preprocessor::getSpelling(const Token &Tok, bool *Invalid) const { - return getSpelling(Tok, SourceMgr, Features, Invalid); -} - -/// getSpelling - This method is used to get the spelling of a token into a -/// preallocated buffer, instead of as an std::string. The caller is required -/// to allocate enough space for the token, which is guaranteed to be at least -/// Tok.getLength() bytes long. The actual length of the token is returned. -/// -/// Note that this method may do two possible things: it may either fill in -/// the buffer specified with characters, or it may *change the input pointer* -/// to point to a constant buffer with the data already in it (avoiding a -/// copy). The caller is not allowed to modify the returned buffer pointer -/// if an internal buffer is returned. -unsigned Preprocessor::getSpelling(const Token &Tok, - const char *&Buffer, bool *Invalid) const { - assert((int)Tok.getLength() >= 0 && "Token character range is bogus!"); - - // If this token is an identifier, just return the string from the identifier - // table, which is very quick. - if (const IdentifierInfo *II = Tok.getIdentifierInfo()) { - Buffer = II->getNameStart(); - return II->getLength(); - } - - // Otherwise, compute the start of the token in the input lexer buffer. - const char *TokStart = 0; - - if (Tok.isLiteral()) - TokStart = Tok.getLiteralData(); - - if (TokStart == 0) { - bool CharDataInvalid = false; - TokStart = SourceMgr.getCharacterData(Tok.getLocation(), &CharDataInvalid); - if (Invalid) - *Invalid = CharDataInvalid; - if (CharDataInvalid) { - Buffer = ""; - return 0; - } - } - - // If this token contains nothing interesting, return it directly. - if (!Tok.needsCleaning()) { - Buffer = TokStart; - return Tok.getLength(); - } - - // Otherwise, hard case, relex the characters into the string. - char *OutBuf = const_cast<char*>(Buffer); - for (const char *Ptr = TokStart, *End = TokStart+Tok.getLength(); - Ptr != End; ) { - unsigned CharSize; - *OutBuf++ = Lexer::getCharAndSizeNoWarn(Ptr, CharSize, Features); - Ptr += CharSize; - } - assert(unsigned(OutBuf-Buffer) != Tok.getLength() && - "NeedsCleaning flag set on something that didn't need cleaning!"); - - return OutBuf-Buffer; -} /// getSpelling - This method is used to get the spelling of a token into a /// SmallVector. Note that the returned StringRef may not point to the @@ -406,9 +285,12 @@ unsigned Preprocessor::getSpelling(const Token &Tok, llvm::StringRef Preprocessor::getSpelling(const Token &Tok, llvm::SmallVectorImpl<char> &Buffer, bool *Invalid) const { - // Try the fast path. - if (const IdentifierInfo *II = Tok.getIdentifierInfo()) - return II->getName(); + // NOTE: this has to be checked *before* testing for an IdentifierInfo. + if (Tok.isNot(tok::raw_identifier)) { + // Try the fast path. + if (const IdentifierInfo *II = Tok.getIdentifierInfo()) + return II->getName(); + } // Resize the buffer if we need to copy into it. if (Tok.needsCleaning()) @@ -434,71 +316,14 @@ void Preprocessor::CreateString(const char *Buf, unsigned Len, Token &Tok, InstantiationLoc, Len); Tok.setLocation(Loc); - // If this is a literal token, set the pointer data. - if (Tok.isLiteral()) + // If this is a raw identifier or a literal token, set the pointer data. + if (Tok.is(tok::raw_identifier)) + Tok.setRawIdentifierData(DestPtr); + else if (Tok.isLiteral()) Tok.setLiteralData(DestPtr); } -/// AdvanceToTokenCharacter - Given a location that specifies the start of a -/// token, return a new location that specifies a character within the token. -SourceLocation Preprocessor::AdvanceToTokenCharacter(SourceLocation TokStart, - unsigned CharNo) { - // Figure out how many physical characters away the specified instantiation - // character is. This needs to take into consideration newlines and - // trigraphs. - bool Invalid = false; - const char *TokPtr = SourceMgr.getCharacterData(TokStart, &Invalid); - - // If they request the first char of the token, we're trivially done. - if (Invalid || (CharNo == 0 && Lexer::isObviouslySimpleCharacter(*TokPtr))) - return TokStart; - - unsigned PhysOffset = 0; - - // The usual case is that tokens don't contain anything interesting. Skip - // over the uninteresting characters. If a token only consists of simple - // chars, this method is extremely fast. - while (Lexer::isObviouslySimpleCharacter(*TokPtr)) { - if (CharNo == 0) - return TokStart.getFileLocWithOffset(PhysOffset); - ++TokPtr, --CharNo, ++PhysOffset; - } - - // If we have a character that may be a trigraph or escaped newline, use a - // lexer to parse it correctly. - for (; CharNo; --CharNo) { - unsigned Size; - Lexer::getCharAndSizeNoWarn(TokPtr, Size, Features); - TokPtr += Size; - PhysOffset += Size; - } - - // Final detail: if we end up on an escaped newline, we want to return the - // location of the actual byte of the token. For example foo\<newline>bar - // advanced by 3 should return the location of b, not of \\. One compounding - // detail of this is that the escape may be made by a trigraph. - if (!Lexer::isObviouslySimpleCharacter(*TokPtr)) - PhysOffset += Lexer::SkipEscapedNewLines(TokPtr)-TokPtr; - - return TokStart.getFileLocWithOffset(PhysOffset); -} - -SourceLocation Preprocessor::getLocForEndOfToken(SourceLocation Loc, - unsigned Offset) { - if (Loc.isInvalid() || !Loc.isFileID()) - return SourceLocation(); - - unsigned Len = Lexer::MeasureTokenLength(Loc, getSourceManager(), Features); - if (Len > Offset) - Len = Len - Offset; - else - return Loc; - - return AdvanceToTokenCharacter(Loc, Len); -} - - //===----------------------------------------------------------------------===// // Preprocessor Initialization Methods @@ -549,25 +374,29 @@ void Preprocessor::EndSourceFile() { // Lexer Event Handling. //===----------------------------------------------------------------------===// -/// LookUpIdentifierInfo - Given a tok::identifier token, look up the -/// identifier information for the token and install it into the token. -IdentifierInfo *Preprocessor::LookUpIdentifierInfo(Token &Identifier, - const char *BufPtr) const { - assert(Identifier.is(tok::identifier) && "Not an identifier!"); - assert(Identifier.getIdentifierInfo() == 0 && "Identinfo already exists!"); +/// LookUpIdentifierInfo - Given a tok::raw_identifier token, look up the +/// identifier information for the token and install it into the token, +/// updating the token kind accordingly. +IdentifierInfo *Preprocessor::LookUpIdentifierInfo(Token &Identifier) const { + assert(Identifier.getRawIdentifierData() != 0 && "No raw identifier data!"); // Look up this token, see if it is a macro, or if it is a language keyword. IdentifierInfo *II; - if (BufPtr && !Identifier.needsCleaning()) { + if (!Identifier.needsCleaning()) { // No cleaning needed, just use the characters from the lexed buffer. - II = getIdentifierInfo(llvm::StringRef(BufPtr, Identifier.getLength())); + II = getIdentifierInfo(llvm::StringRef(Identifier.getRawIdentifierData(), + Identifier.getLength())); } else { // Cleaning needed, alloca a buffer, clean into it, then use the buffer. llvm::SmallString<64> IdentifierBuffer; llvm::StringRef CleanedStr = getSpelling(Identifier, IdentifierBuffer); II = getIdentifierInfo(CleanedStr); } + + // Update the token info (identifier info and appropriate token kind). Identifier.setIdentifierInfo(II); + Identifier.setKind(II->getTokenID()); + return II; } diff --git a/lib/Lex/TokenConcatenation.cpp b/lib/Lex/TokenConcatenation.cpp index fc6db21..3e9e855 100644 --- a/lib/Lex/TokenConcatenation.cpp +++ b/lib/Lex/TokenConcatenation.cpp @@ -13,6 +13,7 @@ #include "clang/Lex/TokenConcatenation.h" #include "clang/Lex/Preprocessor.h" +#include "llvm/Support/ErrorHandling.h" using namespace clang; @@ -165,7 +166,14 @@ bool TokenConcatenation::AvoidConcat(const Token &PrevPrevTok, } switch (PrevKind) { - default: assert(0 && "InitAvoidConcatTokenInfo built wrong"); + default: + llvm_unreachable("InitAvoidConcatTokenInfo built wrong"); + return true; + + case tok::raw_identifier: + llvm_unreachable("tok::raw_identifier in non-raw lexing mode!"); + return true; + case tok::identifier: // id+id or id+number or id+L"foo". // id+'.'... will not append. if (Tok.is(tok::numeric_constant)) diff --git a/lib/Lex/TokenLexer.cpp b/lib/Lex/TokenLexer.cpp index 94719b0..ea39b47 100644 --- a/lib/Lex/TokenLexer.cpp +++ b/lib/Lex/TokenLexer.cpp @@ -287,7 +287,7 @@ void TokenLexer::ExpandFunctionArguments() { llvm::BumpPtrAllocator &Alloc = PP.getPreprocessorAllocator(); Token *Res = static_cast<Token *>(Alloc.Allocate(sizeof(Token)*ResultToks.size(), - llvm::alignof<Token>())); + llvm::alignOf<Token>())); if (NumTokens) memcpy(Res, &ResultToks[0], NumTokens*sizeof(Token)); Tokens = Res; @@ -435,12 +435,13 @@ bool TokenLexer::PasteTokens(Token &Tok) { // Lex the resultant pasted token into Result. Token Result; - if (Tok.is(tok::identifier) && RHS.is(tok::identifier)) { + if (Tok.isAnyIdentifier() && RHS.isAnyIdentifier()) { // Common paste case: identifier+identifier = identifier. Avoid creating // a lexer and other overhead. PP.IncrementPasteCounter(true); Result.startToken(); - Result.setKind(tok::identifier); + Result.setKind(tok::raw_identifier); + Result.setRawIdentifierData(ResultTokStrPtr); Result.setLocation(ResultTokLoc); Result.setLength(LHSLen+RHSLen); } else { @@ -524,10 +525,10 @@ bool TokenLexer::PasteTokens(Token &Tok) { // Now that we got the result token, it will be subject to expansion. Since // token pasting re-lexes the result token in raw mode, identifier information // isn't looked up. As such, if the result is an identifier, look up id info. - if (Tok.is(tok::identifier)) { + if (Tok.is(tok::raw_identifier)) { // Look up the identifier info for the token. We disabled identifier lookup // by saying we're skipping contents, so we need to do this manually. - PP.LookUpIdentifierInfo(Tok, ResultTokStrPtr); + PP.LookUpIdentifierInfo(Tok); } return false; } |