diff options
Diffstat (limited to 'lib/Lex')
-rw-r--r-- | lib/Lex/HeaderMap.cpp | 27 | ||||
-rw-r--r-- | lib/Lex/HeaderSearch.cpp | 52 | ||||
-rw-r--r-- | lib/Lex/Lexer.cpp | 10 | ||||
-rw-r--r-- | lib/Lex/LiteralSupport.cpp | 9 | ||||
-rw-r--r-- | lib/Lex/PPDirectives.cpp | 79 | ||||
-rw-r--r-- | lib/Lex/PPLexerChange.cpp | 3 | ||||
-rw-r--r-- | lib/Lex/PPMacroExpansion.cpp | 72 | ||||
-rw-r--r-- | lib/Lex/Pragma.cpp | 15 | ||||
-rw-r--r-- | lib/Lex/Preprocessor.cpp | 33 |
9 files changed, 154 insertions, 146 deletions
diff --git a/lib/Lex/HeaderMap.cpp b/lib/Lex/HeaderMap.cpp index df71276..4010d61 100644 --- a/lib/Lex/HeaderMap.cpp +++ b/lib/Lex/HeaderMap.cpp @@ -56,8 +56,9 @@ struct HMapHeader { /// HashHMapKey - This is the 'well known' hash function required by the file /// format, used to look up keys in the hash table. The hash table uses simple /// linear probing based on this function. -static inline unsigned HashHMapKey(const char *S, const char *End) { +static inline unsigned HashHMapKey(llvm::StringRef Str) { unsigned Result = 0; + const char *S = Str.begin(), *End = Str.end(); for (; S != End; S++) Result += tolower(*S) * 13; @@ -172,17 +173,6 @@ const char *HeaderMap::getString(unsigned StrTabIdx) const { return FileBuffer->getBufferStart()+StrTabIdx; } -/// StringsEqualWithoutCase - Compare the specified two strings for case- -/// insensitive equality, returning true if they are equal. Both strings are -/// known to have the same length. -static bool StringsEqualWithoutCase(const char *S1, const char *S2, - unsigned Len) { - for (; Len; ++S1, ++S2, --Len) - if (tolower(*S1) != tolower(*S2)) - return false; - return true; -} - //===----------------------------------------------------------------------===// // The Main Drivers //===----------------------------------------------------------------------===// @@ -209,8 +199,7 @@ void HeaderMap::dump() const { /// LookupFile - Check to see if the specified relative filename is located in /// this HeaderMap. If so, open it and return its FileEntry. -const FileEntry *HeaderMap::LookupFile(const char *FilenameStart, - const char *FilenameEnd, +const FileEntry *HeaderMap::LookupFile(llvm::StringRef Filename, FileManager &FM) const { const HMapHeader &Hdr = getHeader(); unsigned NumBuckets = getEndianAdjustedWord(Hdr.NumBuckets); @@ -221,18 +210,12 @@ const FileEntry *HeaderMap::LookupFile(const char *FilenameStart, return 0; // Linearly probe the hash table. - for (unsigned Bucket = HashHMapKey(FilenameStart, FilenameEnd);; ++Bucket) { + for (unsigned Bucket = HashHMapKey(Filename);; ++Bucket) { HMapBucket B = getBucket(Bucket & (NumBuckets-1)); if (B.Key == HMAP_EmptyBucketKey) return 0; // Hash miss. // See if the key matches. If not, probe on. - const char *Key = getString(B.Key); - unsigned BucketKeyLen = strlen(Key); - if (BucketKeyLen != unsigned(FilenameEnd-FilenameStart)) - continue; - - // See if the actual strings equal. - if (!StringsEqualWithoutCase(FilenameStart, Key, BucketKeyLen)) + if (!Filename.equals_lower(getString(B.Key))) continue; // If so, we have a match in the hash table. Construct the destination diff --git a/lib/Lex/HeaderSearch.cpp b/lib/Lex/HeaderSearch.cpp index 2b9b7c9..4554aba 100644 --- a/lib/Lex/HeaderSearch.cpp +++ b/lib/Lex/HeaderSearch.cpp @@ -109,8 +109,7 @@ const char *DirectoryLookup::getName() const { /// LookupFile - Lookup the specified file in this search path, returning it /// if it exists or returning null if not. -const FileEntry *DirectoryLookup::LookupFile(const char *FilenameStart, - const char *FilenameEnd, +const FileEntry *DirectoryLookup::LookupFile(llvm::StringRef Filename, HeaderSearch &HS) const { llvm::SmallString<1024> TmpDir; if (isNormalDir()) { @@ -118,33 +117,32 @@ const FileEntry *DirectoryLookup::LookupFile(const char *FilenameStart, // FIXME: Portability. Filename concatenation should be in sys::Path. TmpDir += getDir()->getName(); TmpDir.push_back('/'); - TmpDir.append(FilenameStart, FilenameEnd); + TmpDir.append(Filename.begin(), Filename.end()); return HS.getFileMgr().getFile(TmpDir.begin(), TmpDir.end()); } if (isFramework()) - return DoFrameworkLookup(FilenameStart, FilenameEnd, HS); + return DoFrameworkLookup(Filename, HS); assert(isHeaderMap() && "Unknown directory lookup"); - return getHeaderMap()->LookupFile(FilenameStart, FilenameEnd,HS.getFileMgr()); + return getHeaderMap()->LookupFile(Filename, HS.getFileMgr()); } /// DoFrameworkLookup - Do a lookup of the specified file in the current /// DirectoryLookup, which is a framework directory. -const FileEntry *DirectoryLookup::DoFrameworkLookup(const char *FilenameStart, - const char *FilenameEnd, +const FileEntry *DirectoryLookup::DoFrameworkLookup(llvm::StringRef Filename, HeaderSearch &HS) const { FileManager &FileMgr = HS.getFileMgr(); // Framework names must have a '/' in the filename. - const char *SlashPos = std::find(FilenameStart, FilenameEnd, '/'); - if (SlashPos == FilenameEnd) return 0; + size_t SlashPos = Filename.find('/'); + if (SlashPos == llvm::StringRef::npos) return 0; // Find out if this is the home for the specified framework, by checking // HeaderSearch. Possible answer are yes/no and unknown. const DirectoryEntry *&FrameworkDirCache = - HS.LookupFrameworkCache(FilenameStart, SlashPos); + HS.LookupFrameworkCache(Filename.substr(0, SlashPos)); // If it is known and in some other directory, fail. if (FrameworkDirCache && FrameworkDirCache != getFrameworkDir()) @@ -159,7 +157,7 @@ const FileEntry *DirectoryLookup::DoFrameworkLookup(const char *FilenameStart, FrameworkName.push_back('/'); // FrameworkName = "/System/Library/Frameworks/Cocoa" - FrameworkName.append(FilenameStart, SlashPos); + FrameworkName.append(Filename.begin(), Filename.begin()+SlashPos); // FrameworkName = "/System/Library/Frameworks/Cocoa.framework/" FrameworkName += ".framework/"; @@ -184,7 +182,7 @@ const FileEntry *DirectoryLookup::DoFrameworkLookup(const char *FilenameStart, unsigned OrigSize = FrameworkName.size(); FrameworkName += "Headers/"; - FrameworkName.append(SlashPos+1, FilenameEnd); + FrameworkName.append(Filename.begin()+SlashPos+1, Filename.end()); if (const FileEntry *FE = FileMgr.getFile(FrameworkName.begin(), FrameworkName.end())) { return FE; @@ -208,21 +206,20 @@ const FileEntry *DirectoryLookup::DoFrameworkLookup(const char *FilenameStart, /// for system #include's or not (i.e. using <> instead of ""). CurFileEnt, if /// non-null, indicates where the #including file is, in case a relative search /// is needed. -const FileEntry *HeaderSearch::LookupFile(const char *FilenameStart, - const char *FilenameEnd, +const FileEntry *HeaderSearch::LookupFile(llvm::StringRef Filename, bool isAngled, const DirectoryLookup *FromDir, const DirectoryLookup *&CurDir, const FileEntry *CurFileEnt) { // If 'Filename' is absolute, check to see if it exists and no searching. - if (llvm::sys::Path::isAbsolute(FilenameStart, FilenameEnd-FilenameStart)) { + if (llvm::sys::Path::isAbsolute(Filename.begin(), Filename.size())) { CurDir = 0; // If this was an #include_next "/absolute/file", fail. if (FromDir) return 0; // Otherwise, just return the file. - return FileMgr.getFile(FilenameStart, FilenameEnd); + return FileMgr.getFile(Filename); } // Step #0, unless disabled, check to see if the file is in the #includer's @@ -236,8 +233,8 @@ const FileEntry *HeaderSearch::LookupFile(const char *FilenameStart, // FIXME: Portability. Filename concatenation should be in sys::Path. TmpDir += CurFileEnt->getDir()->getName(); TmpDir.push_back('/'); - TmpDir.append(FilenameStart, FilenameEnd); - if (const FileEntry *FE = FileMgr.getFile(TmpDir.begin(), TmpDir.end())) { + TmpDir.append(Filename.begin(), Filename.end()); + if (const FileEntry *FE = FileMgr.getFile(TmpDir.str())) { // Leave CurDir unset. // This file is a system header or C++ unfriendly if the old file is. // @@ -265,7 +262,7 @@ const FileEntry *HeaderSearch::LookupFile(const char *FilenameStart, // being relex/pp'd, but they would still have to search through a // (potentially huge) series of SearchDirs to find it. std::pair<unsigned, unsigned> &CacheLookup = - LookupFileCache.GetOrCreateValue(FilenameStart, FilenameEnd).getValue(); + LookupFileCache.GetOrCreateValue(Filename).getValue(); // If the entry has been previously looked up, the first value will be // non-zero. If the value is equal to i (the start point of our search), then @@ -283,7 +280,7 @@ const FileEntry *HeaderSearch::LookupFile(const char *FilenameStart, // Check each directory in sequence to see if it contains this file. for (; i != SearchDirs.size(); ++i) { const FileEntry *FE = - SearchDirs[i].LookupFile(FilenameStart, FilenameEnd, *this); + SearchDirs[i].LookupFile(Filename, *this); if (!FE) continue; CurDir = &SearchDirs[i]; @@ -307,14 +304,13 @@ const FileEntry *HeaderSearch::LookupFile(const char *FilenameStart, /// is a subframework within Carbon.framework. If so, return the FileEntry /// for the designated file, otherwise return null. const FileEntry *HeaderSearch:: -LookupSubframeworkHeader(const char *FilenameStart, - const char *FilenameEnd, +LookupSubframeworkHeader(llvm::StringRef Filename, const FileEntry *ContextFileEnt) { assert(ContextFileEnt && "No context file?"); // Framework names must have a '/' in the filename. Find it. - const char *SlashPos = std::find(FilenameStart, FilenameEnd, '/'); - if (SlashPos == FilenameEnd) return 0; + size_t SlashPos = Filename.find('/'); + if (SlashPos == llvm::StringRef::npos) return 0; // Look up the base framework name of the ContextFileEnt. const char *ContextName = ContextFileEnt->getName(); @@ -329,11 +325,11 @@ LookupSubframeworkHeader(const char *FilenameStart, // Append Frameworks/HIToolbox.framework/ FrameworkName += "Frameworks/"; - FrameworkName.append(FilenameStart, SlashPos); + FrameworkName.append(Filename.begin(), Filename.begin()+SlashPos); FrameworkName += ".framework/"; llvm::StringMapEntry<const DirectoryEntry *> &CacheLookup = - FrameworkMap.GetOrCreateValue(FilenameStart, SlashPos); + FrameworkMap.GetOrCreateValue(Filename.begin(), Filename.begin()+SlashPos); // Some other location? if (CacheLookup.getValue() && @@ -361,14 +357,14 @@ LookupSubframeworkHeader(const char *FilenameStart, // Check ".../Frameworks/HIToolbox.framework/Headers/HIToolbox.h" llvm::SmallString<1024> HeadersFilename(FrameworkName); HeadersFilename += "Headers/"; - HeadersFilename.append(SlashPos+1, FilenameEnd); + HeadersFilename.append(Filename.begin()+SlashPos+1, Filename.end()); if (!(FE = FileMgr.getFile(HeadersFilename.begin(), HeadersFilename.end()))) { // Check ".../Frameworks/HIToolbox.framework/PrivateHeaders/HIToolbox.h" HeadersFilename = FrameworkName; HeadersFilename += "PrivateHeaders/"; - HeadersFilename.append(SlashPos+1, FilenameEnd); + HeadersFilename.append(Filename.begin()+SlashPos+1, Filename.end()); if (!(FE = FileMgr.getFile(HeadersFilename.begin(), HeadersFilename.end()))) return 0; } diff --git a/lib/Lex/Lexer.cpp b/lib/Lex/Lexer.cpp index d5a4643..0a74b26 100644 --- a/lib/Lex/Lexer.cpp +++ b/lib/Lex/Lexer.cpp @@ -643,14 +643,17 @@ void Lexer::LexIdentifier(Token &Result, const char *CurPtr) { // Match [_A-Za-z0-9]*, we have already matched [_A-Za-z$] unsigned Size; unsigned char C = *CurPtr++; - while (isIdentifierBody(C)) { + while (isIdentifierBody(C)) C = *CurPtr++; - } + --CurPtr; // Back up over the skipped character. // Fast path, no $,\,? in identifier found. '\' might be an escaped newline // or UCN, and ? might be a trigraph for '\', an escaped newline or UCN. // FIXME: UCNs. + // + // TODO: Could merge these checks into a CharInfo flag to make the comparison + // cheaper if (C != '\\' && C != '?' && (C != '$' || !Features.DollarIdents)) { FinishIdentifier: const char *IdStart = BufferPtr; @@ -724,7 +727,8 @@ void Lexer::LexNumericConstant(Token &Result, const char *CurPtr) { return LexNumericConstant(Result, ConsumeChar(CurPtr, Size, Result)); // If we have a hex FP constant, continue. - if ((C == '-' || C == '+') && (PrevCh == 'P' || PrevCh == 'p')) + if ((C == '-' || C == '+') && (PrevCh == 'P' || PrevCh == 'p') && + (!PP || !PP->getLangOptions().CPlusPlus0x)) return LexNumericConstant(Result, ConsumeChar(CurPtr, Size, Result)); // Update the location of token as well as BufferPtr. diff --git a/lib/Lex/LiteralSupport.cpp b/lib/Lex/LiteralSupport.cpp index 9aaa82d..5cd5497 100644 --- a/lib/Lex/LiteralSupport.cpp +++ b/lib/Lex/LiteralSupport.cpp @@ -458,7 +458,7 @@ void NumericLiteralParser::ParseNumberStartingWithZero(SourceLocation TokLoc) { } // A binary exponent can appear with or with a '.'. If dotted, the // binary exponent is required. - if (*s == 'p' || *s == 'P') { + if ((*s == 'p' || *s == 'P') && !PP.getLangOptions().CPlusPlus0x) { const char *Exponent = s; s++; saw_exponent = true; @@ -472,7 +472,12 @@ void NumericLiteralParser::ParseNumberStartingWithZero(SourceLocation TokLoc) { } s = first_non_digit; - if (!PP.getLangOptions().HexFloats) + // In C++0x, we cannot support hexadecmial floating literals because + // they conflict with user-defined literals, so we warn in previous + // versions of C++ by default. + if (PP.getLangOptions().CPlusPlus) + PP.Diag(TokLoc, diag::ext_hexconstant_cplusplus); + else if (!PP.getLangOptions().HexFloats) PP.Diag(TokLoc, diag::ext_hexconstant_invalid); } else if (saw_period) { PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, s-ThisTokBegin), diff --git a/lib/Lex/PPDirectives.cpp b/lib/Lex/PPDirectives.cpp index 9e3d283..aa807f8 100644 --- a/lib/Lex/PPDirectives.cpp +++ b/lib/Lex/PPDirectives.cpp @@ -404,8 +404,8 @@ void Preprocessor::PTHSkipExcludedConditionalBlock() { /// LookupFile - Given a "foo" or <foo> reference, look up the indicated file, /// return null on failure. isAngled indicates whether the file reference is /// for system #include's or not (i.e. using <> instead of ""). -const FileEntry *Preprocessor::LookupFile(const char *FilenameStart, - const char *FilenameEnd, +const FileEntry *Preprocessor::LookupFile(llvm::StringRef Filename, + SourceLocation FilenameTokLoc, bool isAngled, const DirectoryLookup *FromDir, const DirectoryLookup *&CurDir) { @@ -431,17 +431,24 @@ const FileEntry *Preprocessor::LookupFile(const char *FilenameStart, // Do a standard file entry lookup. CurDir = CurDirLookup; const FileEntry *FE = - HeaderInfo.LookupFile(FilenameStart, FilenameEnd, - isAngled, FromDir, CurDir, CurFileEnt); - if (FE) return FE; + HeaderInfo.LookupFile(Filename, isAngled, FromDir, CurDir, CurFileEnt); + if (FE) { + // Warn about normal quoted #include from framework headers. Since + // framework headers are published (both public and private ones) they + // should not do relative searches, they should do an include with the + // framework path included. + if (!isAngled && CurDir && FilenameTokLoc.isValid() && + CurDir->isFramework() && CurDir == CurDirLookup) + Diag(FilenameTokLoc, diag::warn_pp_relative_include_from_framework); + return FE; + } // Otherwise, see if this is a subframework header. If so, this is relative // to one of the headers on the #include stack. Walk the list of the current // headers on the #include stack and pass them to HeaderInfo. if (IsFileLexer()) { if ((CurFileEnt = SourceMgr.getFileEntryForID(CurPPLexer->getFileID()))) - if ((FE = HeaderInfo.LookupSubframeworkHeader(FilenameStart, FilenameEnd, - CurFileEnt))) + if ((FE = HeaderInfo.LookupSubframeworkHeader(Filename, CurFileEnt))) return FE; } @@ -450,8 +457,7 @@ const FileEntry *Preprocessor::LookupFile(const char *FilenameStart, if (IsFileLexer(ISEntry)) { if ((CurFileEnt = SourceMgr.getFileEntryForID(ISEntry.ThePPLexer->getFileID()))) - if ((FE = HeaderInfo.LookupSubframeworkHeader(FilenameStart, - FilenameEnd, CurFileEnt))) + if ((FE = HeaderInfo.LookupSubframeworkHeader(Filename, CurFileEnt))) return FE; } } @@ -922,43 +928,41 @@ void Preprocessor::HandleIdentSCCSDirective(Token &Tok) { /// spelling of the filename, but is also expected to handle the case when /// this method decides to use a different buffer. bool Preprocessor::GetIncludeFilenameSpelling(SourceLocation Loc, - const char *&BufStart, - const char *&BufEnd) { + llvm::StringRef &Buffer) { // Get the text form of the filename. - assert(BufStart != BufEnd && "Can't have tokens with empty spellings!"); + assert(!Buffer.empty() && "Can't have tokens with empty spellings!"); // Make sure the filename is <x> or "x". bool isAngled; - if (BufStart[0] == '<') { - if (BufEnd[-1] != '>') { + if (Buffer[0] == '<') { + if (Buffer.back() != '>') { Diag(Loc, diag::err_pp_expects_filename); - BufStart = 0; + Buffer = llvm::StringRef(); return true; } isAngled = true; - } else if (BufStart[0] == '"') { - if (BufEnd[-1] != '"') { + } else if (Buffer[0] == '"') { + if (Buffer.back() != '"') { Diag(Loc, diag::err_pp_expects_filename); - BufStart = 0; + Buffer = llvm::StringRef(); return true; } isAngled = false; } else { Diag(Loc, diag::err_pp_expects_filename); - BufStart = 0; + Buffer = llvm::StringRef(); return true; } // Diagnose #include "" as invalid. - if (BufEnd-BufStart <= 2) { + if (Buffer.size() <= 2) { Diag(Loc, diag::err_pp_empty_filename); - BufStart = 0; - return ""; + Buffer = llvm::StringRef(); + return true; } // Skip the brackets. - ++BufStart; - --BufEnd; + Buffer = Buffer.substr(1, Buffer.size()-2); return isAngled; } @@ -1024,8 +1028,8 @@ void Preprocessor::HandleIncludeDirective(Token &IncludeTok, CurPPLexer->LexIncludeFilename(FilenameTok); // Reserve a buffer to get the spelling. - llvm::SmallVector<char, 128> FilenameBuffer; - const char *FilenameStart, *FilenameEnd; + llvm::SmallString<128> FilenameBuffer; + llvm::StringRef Filename; switch (FilenameTok.getKind()) { case tok::eom: @@ -1035,9 +1039,9 @@ void Preprocessor::HandleIncludeDirective(Token &IncludeTok, case tok::angle_string_literal: case tok::string_literal: { FilenameBuffer.resize(FilenameTok.getLength()); - FilenameStart = &FilenameBuffer[0]; + const char *FilenameStart = &FilenameBuffer[0]; unsigned Len = getSpelling(FilenameTok, FilenameStart); - FilenameEnd = FilenameStart+Len; + Filename = llvm::StringRef(FilenameStart, Len); break; } @@ -1047,8 +1051,7 @@ void Preprocessor::HandleIncludeDirective(Token &IncludeTok, FilenameBuffer.push_back('<'); if (ConcatenateIncludeName(FilenameBuffer)) return; // Found <eom> but no ">"? Diagnostic already emitted. - FilenameStart = FilenameBuffer.data(); - FilenameEnd = FilenameStart + FilenameBuffer.size(); + Filename = FilenameBuffer.str(); break; default: Diag(FilenameTok.getLocation(), diag::err_pp_expects_filename); @@ -1056,11 +1059,11 @@ void Preprocessor::HandleIncludeDirective(Token &IncludeTok, return; } - bool isAngled = GetIncludeFilenameSpelling(FilenameTok.getLocation(), - FilenameStart, FilenameEnd); + bool isAngled = + GetIncludeFilenameSpelling(FilenameTok.getLocation(), Filename); // If GetIncludeFilenameSpelling set the start ptr to null, there was an // error. - if (FilenameStart == 0) { + if (Filename.empty()) { DiscardUntilEndOfDirective(); return; } @@ -1079,14 +1082,13 @@ void Preprocessor::HandleIncludeDirective(Token &IncludeTok, // Search include directories. const DirectoryLookup *CurDir; - const FileEntry *File = LookupFile(FilenameStart, FilenameEnd, + const FileEntry *File = LookupFile(Filename, FilenameTok.getLocation(), isAngled, LookupFrom, CurDir); if (File == 0) { - Diag(FilenameTok, diag::err_pp_file_not_found) - << std::string(FilenameStart, FilenameEnd); + Diag(FilenameTok, diag::err_pp_file_not_found) << Filename; return; } - + // Ask HeaderInfo if we should enter this #include file. If not, #including // this file will have no effect. if (!HeaderInfo.ShouldEnterIncludeFile(File, isImport)) @@ -1103,8 +1105,7 @@ void Preprocessor::HandleIncludeDirective(Token &IncludeTok, FileID FID = SourceMgr.createFileID(File, FilenameTok.getLocation(), FileCharacter); if (FID.isInvalid()) { - Diag(FilenameTok, diag::err_pp_file_not_found) - << std::string(FilenameStart, FilenameEnd); + Diag(FilenameTok, diag::err_pp_file_not_found) << Filename; return; } diff --git a/lib/Lex/PPLexerChange.cpp b/lib/Lex/PPLexerChange.cpp index ce1b19c..0b26ccb 100644 --- a/lib/Lex/PPLexerChange.cpp +++ b/lib/Lex/PPLexerChange.cpp @@ -249,7 +249,8 @@ bool Preprocessor::HandleEndOfFile(Token &Result, bool isEndOfMacro) { // 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(), E = macro_end(); I != E; ++I) + 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); } diff --git a/lib/Lex/PPMacroExpansion.cpp b/lib/Lex/PPMacroExpansion.cpp index dfb14ff..3792782 100644 --- a/lib/Lex/PPMacroExpansion.cpp +++ b/lib/Lex/PPMacroExpansion.cpp @@ -18,6 +18,7 @@ #include "clang/Basic/SourceManager.h" #include "clang/Basic/FileManager.h" #include "clang/Lex/LexDiagnostic.h" +#include "llvm/ADT/StringSwitch.h" #include <cstdio> #include <ctime> using namespace clang; @@ -481,34 +482,27 @@ static void ComputeDATE_TIME(SourceLocation &DATELoc, SourceLocation &TIMELoc, static bool HasFeature(const Preprocessor &PP, const IdentifierInfo *II) { const LangOptions &LangOpts = PP.getLangOptions(); - switch (II->getLength()) { - default: return false; - case 6: - if (II->isStr("blocks")) return LangOpts.Blocks; - return false; - case 8: - if (II->isStr("cxx_rtti")) return LangOpts.RTTI; - return false; - case 14: - if (II->isStr("cxx_exceptions")) return LangOpts.Exceptions; - return false; - case 19: - if (II->isStr("objc_nonfragile_abi")) return LangOpts.ObjCNonFragileABI; - return false; - case 22: - if (II->isStr("attribute_overloadable")) return true; - return false; - case 25: - if (II->isStr("attribute_ext_vector_type")) return true; - return false; - case 27: - if (II->isStr("attribute_analyzer_noreturn")) return true; - return false; - case 29: - if (II->isStr("attribute_ns_returns_retained")) return true; - if (II->isStr("attribute_cf_returns_retained")) return true; - return false; - } + return llvm::StringSwitch<bool>(II->getName()) + .Case("blocks", LangOpts.Blocks) + .Case("cxx_rtti", LangOpts.RTTI) + //.Case("cxx_lambdas", false) + //.Case("cxx_nullptr", false) + //.Case("cxx_concepts", false) + .Case("cxx_decltype", LangOpts.CPlusPlus0x) + .Case("cxx_auto_type", LangOpts.CPlusPlus0x) + .Case("cxx_exceptions", LangOpts.Exceptions) + .Case("cxx_attributes", LangOpts.CPlusPlus0x) + .Case("cxx_static_assert", LangOpts.CPlusPlus0x) + .Case("objc_nonfragile_abi", LangOpts.ObjCNonFragileABI) + .Case("cxx_deleted_functions", LangOpts.CPlusPlus0x) + //.Case("cxx_rvalue_references", false) + .Case("attribute_overloadable", true) + //.Case("cxx_variadic_templates", false) + .Case("attribute_ext_vector_type", true) + .Case("attribute_analyzer_noreturn", true) + .Case("attribute_ns_returns_retained", true) + .Case("attribute_cf_returns_retained", true) + .Default(false); } /// EvaluateHasIncludeCommon - Process a '__has_include("path")' @@ -535,8 +529,8 @@ static bool EvaluateHasIncludeCommon(bool &Result, Token &Tok, PP.getCurrentLexer()->LexIncludeFilename(Tok); // Reserve a buffer to get the spelling. - llvm::SmallVector<char, 128> FilenameBuffer; - const char *FilenameStart, *FilenameEnd; + llvm::SmallString<128> FilenameBuffer; + llvm::StringRef Filename; switch (Tok.getKind()) { case tok::eom: @@ -546,9 +540,9 @@ static bool EvaluateHasIncludeCommon(bool &Result, Token &Tok, case tok::angle_string_literal: case tok::string_literal: { FilenameBuffer.resize(Tok.getLength()); - FilenameStart = &FilenameBuffer[0]; + const char *FilenameStart = &FilenameBuffer[0]; unsigned Len = PP.getSpelling(Tok, FilenameStart); - FilenameEnd = FilenameStart+Len; + Filename = llvm::StringRef(FilenameStart, Len); break; } @@ -558,26 +552,24 @@ static bool EvaluateHasIncludeCommon(bool &Result, Token &Tok, FilenameBuffer.push_back('<'); if (PP.ConcatenateIncludeName(FilenameBuffer)) return false; // Found <eom> but no ">"? Diagnostic already emitted. - FilenameStart = FilenameBuffer.data(); - FilenameEnd = FilenameStart + FilenameBuffer.size(); + Filename = FilenameBuffer.str(); break; default: PP.Diag(Tok.getLocation(), diag::err_pp_expects_filename); return false; } - bool isAngled = PP.GetIncludeFilenameSpelling(Tok.getLocation(), - FilenameStart, FilenameEnd); + bool isAngled = PP.GetIncludeFilenameSpelling(Tok.getLocation(), Filename); // If GetIncludeFilenameSpelling set the start ptr to null, there was an // error. - if (FilenameStart == 0) { + if (Filename.empty()) return false; - } // Search include directories. const DirectoryLookup *CurDir; - const FileEntry *File = PP.LookupFile(FilenameStart, FilenameEnd, - isAngled, LookupFrom, CurDir); + const FileEntry *File = PP.LookupFile(Filename, + SourceLocation(),// produce no warnings. + isAngled, LookupFrom, CurDir); // Get the result value. Result = true means the file exists. Result = File != 0; diff --git a/lib/Lex/Pragma.cpp b/lib/Lex/Pragma.cpp index 8b46f71..856b3bd 100644 --- a/lib/Lex/Pragma.cpp +++ b/lib/Lex/Pragma.cpp @@ -286,26 +286,25 @@ void Preprocessor::HandlePragmaDependency(Token &DependencyTok) { return; // Reserve a buffer to get the spelling. - llvm::SmallVector<char, 128> FilenameBuffer; + llvm::SmallString<128> FilenameBuffer; FilenameBuffer.resize(FilenameTok.getLength()); const char *FilenameStart = &FilenameBuffer[0]; unsigned Len = getSpelling(FilenameTok, FilenameStart); - const char *FilenameEnd = FilenameStart+Len; - bool isAngled = GetIncludeFilenameSpelling(FilenameTok.getLocation(), - FilenameStart, FilenameEnd); + llvm::StringRef Filename(FilenameStart, Len); + bool isAngled = + GetIncludeFilenameSpelling(FilenameTok.getLocation(), Filename); // If GetIncludeFilenameSpelling set the start ptr to null, there was an // error. - if (FilenameStart == 0) + if (Filename.empty()) return; // Search include directories for this file. const DirectoryLookup *CurDir; - const FileEntry *File = LookupFile(FilenameStart, FilenameEnd, + const FileEntry *File = LookupFile(Filename, FilenameTok.getLocation(), isAngled, 0, CurDir); if (File == 0) { - Diag(FilenameTok, diag::err_pp_file_not_found) - << std::string(FilenameStart, FilenameEnd); + Diag(FilenameTok, diag::err_pp_file_not_found) << Filename; return; } diff --git a/lib/Lex/Preprocessor.cpp b/lib/Lex/Preprocessor.cpp index 81966cb..26bb3a9 100644 --- a/lib/Lex/Preprocessor.cpp +++ b/lib/Lex/Preprocessor.cpp @@ -27,6 +27,7 @@ #include "clang/Lex/Preprocessor.h" #include "MacroArgs.h" +#include "clang/Lex/ExternalPreprocessorSource.h" #include "clang/Lex/HeaderSearch.h" #include "clang/Lex/MacroInfo.h" #include "clang/Lex/Pragma.h" @@ -43,6 +44,7 @@ using namespace clang; //===----------------------------------------------------------------------===// +ExternalPreprocessorSource::~ExternalPreprocessorSource() { } Preprocessor::Preprocessor(Diagnostic &diags, const LangOptions &opts, const TargetInfo &target, SourceManager &SM, @@ -50,9 +52,9 @@ Preprocessor::Preprocessor(Diagnostic &diags, const LangOptions &opts, IdentifierInfoLookup* IILookup, bool OwnsHeaders) : Diags(&diags), Features(opts), Target(target),FileMgr(Headers.getFileMgr()), - SourceMgr(SM), HeaderInfo(Headers), Identifiers(opts, IILookup), - BuiltinInfo(Target), CodeCompletionFile(0), CurPPLexer(0), CurDirLookup(0), - Callbacks(0), MacroArgCache(0) { + SourceMgr(SM), HeaderInfo(Headers), ExternalSource(0), + Identifiers(opts, IILookup), BuiltinInfo(Target), CodeCompletionFile(0), + CurPPLexer(0), CurDirLookup(0), Callbacks(0), MacroArgCache(0) { ScratchBuf = new ScratchBuffer(SourceMgr); CounterValue = 0; // __COUNTER__ starts at 0. OwnsHeaderSearch = OwnsHeaders; @@ -77,6 +79,9 @@ Preprocessor::Preprocessor(Diagnostic &diags, const LangOptions &opts, CachedLexPos = 0; + // We haven't read anything from the external source. + ReadMacrosFromExternalSource = false; + // "Poison" __VA_ARGS__, which can only appear in the expansion of a macro. // This gets unpoisoned where it is allowed. (Ident__VA_ARGS__ = getIdentifierInfo("__VA_ARGS__"))->setIsPoisoned(); @@ -194,6 +199,28 @@ void Preprocessor::PrintStats() { << NumFastTokenPaste << " on the fast path.\n"; } +Preprocessor::macro_iterator +Preprocessor::macro_begin(bool IncludeExternalMacros) const { + if (IncludeExternalMacros && ExternalSource && + !ReadMacrosFromExternalSource) { + ReadMacrosFromExternalSource = true; + ExternalSource->ReadDefinedMacros(); + } + + return Macros.begin(); +} + +Preprocessor::macro_iterator +Preprocessor::macro_end(bool IncludeExternalMacros) const { + if (IncludeExternalMacros && ExternalSource && + !ReadMacrosFromExternalSource) { + ReadMacrosFromExternalSource = true; + ExternalSource->ReadDefinedMacros(); + } + + return Macros.end(); +} + bool Preprocessor::SetCodeCompletionPoint(const FileEntry *File, unsigned TruncateAtLine, unsigned TruncateAtColumn) { |