summaryrefslogtreecommitdiffstats
path: root/lib/Lex
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Lex')
-rw-r--r--lib/Lex/CMakeLists.txt8
-rw-r--r--lib/Lex/HeaderMap.cpp10
-rw-r--r--lib/Lex/HeaderSearch.cpp44
-rw-r--r--lib/Lex/Lexer.cpp230
-rw-r--r--lib/Lex/LiteralSupport.cpp275
-rw-r--r--lib/Lex/MacroInfo.cpp3
-rw-r--r--lib/Lex/PPDirectives.cpp212
-rw-r--r--lib/Lex/PPExpressions.cpp51
-rw-r--r--lib/Lex/PPLexerChange.cpp14
-rw-r--r--lib/Lex/PPMacroExpansion.cpp152
-rw-r--r--lib/Lex/PTHLexer.cpp44
-rw-r--r--lib/Lex/Pragma.cpp208
-rw-r--r--lib/Lex/PreprocessingRecord.cpp62
-rw-r--r--lib/Lex/Preprocessor.cpp227
-rw-r--r--lib/Lex/TokenConcatenation.cpp10
-rw-r--r--lib/Lex/TokenLexer.cpp11
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;
}
OpenPOWER on IntegriCloud