diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2012-04-14 14:01:31 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2012-04-14 14:01:31 +0000 |
commit | dbe13110f59f48b4dbb7552b3ac2935acdeece7f (patch) | |
tree | be1815eb79b42ff482a8562b13c2dcbf0c5dcbee /include/clang/Lex | |
parent | 9da628931ebf2609493570f87824ca22402cc65f (diff) | |
download | src-test2-dbe13110f59f48b4dbb7552b3ac2935acdeece7f.tar.gz src-test2-dbe13110f59f48b4dbb7552b3ac2935acdeece7f.zip |
Notes
Diffstat (limited to 'include/clang/Lex')
-rw-r--r-- | include/clang/Lex/DirectoryLookup.h | 21 | ||||
-rw-r--r-- | include/clang/Lex/ExternalPreprocessorSource.h | 3 | ||||
-rw-r--r-- | include/clang/Lex/HeaderSearch.h | 229 | ||||
-rw-r--r-- | include/clang/Lex/LexDiagnostic.h | 2 | ||||
-rw-r--r-- | include/clang/Lex/Lexer.h | 75 | ||||
-rw-r--r-- | include/clang/Lex/LiteralSupport.h | 54 | ||||
-rw-r--r-- | include/clang/Lex/MacroInfo.h | 25 | ||||
-rw-r--r-- | include/clang/Lex/ModuleLoader.h | 32 | ||||
-rw-r--r-- | include/clang/Lex/ModuleMap.h | 237 | ||||
-rw-r--r-- | include/clang/Lex/PPCallbacks.h | 89 | ||||
-rw-r--r-- | include/clang/Lex/PreprocessingRecord.h | 111 | ||||
-rw-r--r-- | include/clang/Lex/Preprocessor.h | 210 | ||||
-rw-r--r-- | include/clang/Lex/PreprocessorLexer.h | 1 | ||||
-rw-r--r-- | include/clang/Lex/Token.h | 6 |
14 files changed, 892 insertions, 203 deletions
diff --git a/include/clang/Lex/DirectoryLookup.h b/include/clang/Lex/DirectoryLookup.h index f7da61b0ed71..95f0d2735093 100644 --- a/include/clang/Lex/DirectoryLookup.h +++ b/include/clang/Lex/DirectoryLookup.h @@ -22,7 +22,8 @@ class HeaderMap; class DirectoryEntry; class FileEntry; class HeaderSearch; - +class Module; + /// DirectoryLookup - This class represents one entry in the search list that /// specifies the search order for directories in #include directives. It /// represents either a directory, a framework, or a headermap. @@ -141,24 +142,26 @@ public: /// SearchPath at which the file was found. This only differs from the /// Filename for framework includes. /// - /// \param BuildingModule The name of the module we're currently building. - /// /// \param SuggestedModule If non-null, and the file found is semantically - /// part of a known module, this will be set to the name of the module that - /// could be imported instead of preprocessing/parsing the file found. + /// part of a known module, this will be set to the module that should + /// be imported instead of preprocessing/parsing the file found. + /// + /// \param InUserSpecifiedSystemHeader [out] If the file is found, set to true + /// if the file is located in a framework that has been user-specified to be + /// treated as a system framework. const FileEntry *LookupFile(StringRef Filename, HeaderSearch &HS, SmallVectorImpl<char> *SearchPath, SmallVectorImpl<char> *RelativePath, - StringRef BuildingModule, - StringRef *SuggestedModule) const; + Module **SuggestedModule, + bool &InUserSpecifiedSystemHeader) const; private: const FileEntry *DoFrameworkLookup( StringRef Filename, HeaderSearch &HS, SmallVectorImpl<char> *SearchPath, SmallVectorImpl<char> *RelativePath, - StringRef BuildingModule, - StringRef *SuggestedModule) const; + Module **SuggestedModule, + bool &InUserSpecifiedSystemHeader) const; }; diff --git a/include/clang/Lex/ExternalPreprocessorSource.h b/include/clang/Lex/ExternalPreprocessorSource.h index dbf738903371..f172b5c8d22d 100644 --- a/include/clang/Lex/ExternalPreprocessorSource.h +++ b/include/clang/Lex/ExternalPreprocessorSource.h @@ -30,6 +30,9 @@ public: /// \brief Read the definition for the given macro. virtual void LoadMacroDefinition(IdentifierInfo *II) = 0; + + /// \brief Update an out-of-date identifier. + virtual void updateOutOfDateIdentifier(IdentifierInfo &II) = 0; }; } diff --git a/include/clang/Lex/HeaderSearch.h b/include/clang/Lex/HeaderSearch.h index 84d59f793bbb..5128ce6c1144 100644 --- a/include/clang/Lex/HeaderSearch.h +++ b/include/clang/Lex/HeaderSearch.h @@ -15,13 +15,16 @@ #define LLVM_CLANG_LEX_HEADERSEARCH_H #include "clang/Lex/DirectoryLookup.h" +#include "clang/Lex/ModuleMap.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringSet.h" #include "llvm/Support/Allocator.h" +#include "llvm/ADT/OwningPtr.h" #include <vector> namespace clang { - + +class DiagnosticsEngine; class ExternalIdentifierLookup; class FileEntry; class FileManager; @@ -117,7 +120,19 @@ public: /// HeaderSearch - This class encapsulates the information needed to find the /// file referenced by a #include or #include_next, (sub-)framework lookup, etc. class HeaderSearch { + /// This structure is used to record entries in our framework cache. + struct FrameworkCacheEntry { + /// The directory entry which should be used for the cached framework. + const DirectoryEntry *Directory; + + /// Whether this framework has been "user-specified" to be treated as if it + /// were a system framework (even if it was found outside a system framework + /// directory). + bool IsUserSpecifiedSystemFramework; + }; + FileManager &FileMgr; + DiagnosticsEngine &Diags; /// #include search path information. Requests for #include "x" search the /// directory of the #including file first, then each directory in SearchDirs /// consecutively. Requests for <x> search the current dir first, then each @@ -132,9 +147,6 @@ class HeaderSearch { /// \brief The path to the module cache. std::string ModuleCachePath; - /// \brief The name of the module we're building. - std::string BuildingModule; - /// FileInfo - This contains all of the preprocessor-specific data about files /// that are included. The vector is indexed by the FileEntry's UID. /// @@ -149,16 +161,27 @@ class HeaderSearch { llvm::StringMap<std::pair<unsigned, unsigned>, llvm::BumpPtrAllocator> LookupFileCache; - /// FrameworkMap - This is a collection mapping a framework or subframework /// name like "Carbon" to the Carbon.framework directory. - llvm::StringMap<const DirectoryEntry *, llvm::BumpPtrAllocator> - FrameworkMap; + llvm::StringMap<FrameworkCacheEntry, llvm::BumpPtrAllocator> FrameworkMap; + + /// IncludeAliases - maps include file names (including the quotes or + /// angle brackets) to other include file names. This is used to support the + /// include_alias pragma for Microsoft compatibility. + typedef llvm::StringMap<std::string, llvm::BumpPtrAllocator> + IncludeAliasMap; + OwningPtr<IncludeAliasMap> IncludeAliases; /// HeaderMaps - This is a mapping from FileEntry -> HeaderMap, uniquing /// headermaps. This vector owns the headermap. std::vector<std::pair<const FileEntry*, const HeaderMap*> > HeaderMaps; + /// \brief The mapping between modules and headers. + ModuleMap ModMap; + + /// \brief Describes whether a given directory has a module map in it. + llvm::DenseMap<const DirectoryEntry *, bool> DirectoryHasModuleMap; + /// \brief Uniqued set of framework names, which is used to track which /// headers were included as framework headers. llvm::StringSet<llvm::BumpPtrAllocator> FrameworkNames; @@ -179,8 +202,12 @@ class HeaderSearch { explicit HeaderSearch(); explicit HeaderSearch(const HeaderSearch&); void operator=(const HeaderSearch&); + + friend class DirectoryLookup; + public: - HeaderSearch(FileManager &FM); + HeaderSearch(FileManager &FM, DiagnosticsEngine &Diags, + const LangOptions &LangOpts, const TargetInfo *Target); ~HeaderSearch(); FileManager &getFileMgr() const { return FileMgr; } @@ -199,13 +226,51 @@ public: //LookupFileCache.clear(); } - /// \brief Set the path to the module cache and the name of the module - /// we're building - void configureModules(StringRef CachePath, StringRef BuildingModule) { + /// AddSearchPath - Add an additional search path. + void AddSearchPath(const DirectoryLookup &dir, bool isAngled) { + unsigned idx = isAngled ? SystemDirIdx : AngledDirIdx; + SearchDirs.insert(SearchDirs.begin() + idx, dir); + if (!isAngled) + AngledDirIdx++; + SystemDirIdx++; + } + + /// HasIncludeAliasMap - Checks whether the map exists or not + bool HasIncludeAliasMap() const { + return IncludeAliases; + } + + /// AddIncludeAlias - Map the source include name to the dest include name. + /// The Source should include the angle brackets or quotes, the dest + /// should not. This allows for distinction between <> and "" headers. + void AddIncludeAlias(StringRef Source, StringRef Dest) { + if (!IncludeAliases) + IncludeAliases.reset(new IncludeAliasMap); + (*IncludeAliases)[Source] = Dest; + } + + /// MapHeaderToIncludeAlias - Maps one header file name to a different header + /// file name, for use with the include_alias pragma. Note that the source + /// file name should include the angle brackets or quotes. Returns StringRef + /// as null if the header cannot be mapped. + StringRef MapHeaderToIncludeAlias(StringRef Source) { + assert(IncludeAliases && "Trying to map headers when there's no map"); + + // Do any filename replacements before anything else + IncludeAliasMap::const_iterator Iter = IncludeAliases->find(Source); + if (Iter != IncludeAliases->end()) + return Iter->second; + return StringRef(); + } + + /// \brief Set the path to the module cache. + void setModuleCachePath(StringRef CachePath) { ModuleCachePath = CachePath; - this->BuildingModule = BuildingModule; } + /// \brief Retrieve the path to the module cache. + StringRef getModuleCachePath() const { return ModuleCachePath; } + /// ClearFileInfo - Forget everything we know about headers so far. void ClearFileInfo() { FileInfo.clear(); @@ -224,6 +289,10 @@ public: ExternalSource = ES; } + /// \brief Set the target information for the header search, if not + /// already known. + void setTarget(const TargetInfo &Target); + /// LookupFile - Given a "foo" or <foo> reference, look up the indicated file, /// return null on failure. /// @@ -247,15 +316,16 @@ public: /// Filename for framework includes. /// /// \param SuggestedModule If non-null, and the file found is semantically - /// part of a known module, this will be set to the name of the module that - /// could be imported instead of preprocessing/parsing the file found. + /// part of a known module, this will be set to the module that should + /// be imported instead of preprocessing/parsing the file found. const FileEntry *LookupFile(StringRef Filename, bool isAngled, const DirectoryLookup *FromDir, const DirectoryLookup *&CurDir, const FileEntry *CurFileEnt, SmallVectorImpl<char> *SearchPath, SmallVectorImpl<char> *RelativePath, - StringRef *SuggestedModule); + Module **SuggestedModule, + bool SkipCache = false); /// LookupSubframeworkHeader - Look up a subframework for the specified /// #include file. For example, if #include'ing <HIToolbox/HIToolbox.h> from @@ -271,7 +341,7 @@ public: /// LookupFrameworkCache - Look up the specified framework name in our /// framework cache, returning the DirectoryEntry it is in if we know, /// otherwise, return null. - const DirectoryEntry *&LookupFrameworkCache(StringRef FWName) { + FrameworkCacheEntry &LookupFrameworkCache(StringRef FWName) { return FrameworkMap.GetOrCreateValue(FWName).getValue(); } @@ -326,33 +396,96 @@ public: /// FileEntry, uniquing them through the the 'HeaderMaps' datastructure. const HeaderMap *CreateHeaderMap(const FileEntry *FE); - /// \brief Search in the module cache path for a module with the given - /// name. + /// \brief Retrieve the name of the module file that should be used to + /// load the given module. /// - /// \param If non-NULL, will be set to the module file name we expected to - /// find (regardless of whether it was actually found or not). + /// \param Module The module whose module file name will be returned. /// - /// \param UmbrellaHeader If non-NULL, and no module was found in the module - /// cache, this routine will search in the framework paths to determine - /// whether a module can be built from an umbrella header. If so, the pointee - /// will be set to the path of the umbrella header. + /// \returns The name of the module file that corresponds to this module, + /// or an empty string if this module does not correspond to any module file. + std::string getModuleFileName(Module *Module); + + /// \brief Retrieve the name of the module file that should be used to + /// load a module with the given name. + /// + /// \param Module The module whose module file name will be returned. + /// + /// \returns The name of the module file that corresponds to this module, + /// or an empty string if this module does not correspond to any module file. + std::string getModuleFileName(StringRef ModuleName); + + /// \brief Lookup a module Search for a module with the given name. /// - /// \returns A file describing the named module, if available, or NULL to - /// indicate that the module could not be found. - const FileEntry *lookupModule(StringRef ModuleName, - std::string *ModuleFileName = 0, - std::string *UmbrellaHeader = 0); + /// \param ModuleName The name of the module we're looking for. + /// + /// \param AllowSearch Whether we are allowed to search in the various + /// search directories to produce a module definition. If not, this lookup + /// will only return an already-known module. + /// + /// \returns The module with the given name. + Module *lookupModule(StringRef ModuleName, bool AllowSearch = true); void IncrementFrameworkLookupCount() { ++NumFrameworkLookups; } - typedef std::vector<HeaderFileInfo>::const_iterator header_file_iterator; - header_file_iterator header_file_begin() const { return FileInfo.begin(); } - header_file_iterator header_file_end() const { return FileInfo.end(); } + /// \brief Determine whether there is a module map that may map the header + /// with the given file name to a (sub)module. + /// + /// \param Filename The name of the file. + /// + /// \param Root The "root" directory, at which we should stop looking for + /// module maps. + bool hasModuleMap(StringRef Filename, const DirectoryEntry *Root); + + /// \brief Retrieve the module that corresponds to the given file, if any. + /// + /// \param File The header that we wish to map to a module. + Module *findModuleForHeader(const FileEntry *File); + + /// \brief Read the contents of the given module map file. + /// + /// \param File The module map file. + /// + /// \param OnlyModule If non-NULL, this will receive the + /// + /// \returns true if an error occurred, false otherwise. + bool loadModuleMapFile(const FileEntry *File); + + /// \brief Collect the set of all known, top-level modules. + /// + /// \param Modules Will be filled with the set of known, top-level modules. + void collectAllModules(llvm::SmallVectorImpl<Module *> &Modules); + +private: + /// \brief Retrieve a module with the given name, which may be part of the + /// given framework. + /// + /// \param Name The name of the module to retrieve. + /// + /// \param Dir The framework directory (e.g., ModuleName.framework). + /// + /// \param IsSystem Whether the framework directory is part of the system + /// frameworks. + /// + /// \returns The module, if found; otherwise, null. + Module *loadFrameworkModule(StringRef Name, + const DirectoryEntry *Dir, + bool IsSystem); + +public: + /// \brief Retrieve the module map. + ModuleMap &getModuleMap() { return ModMap; } + unsigned header_file_size() const { return FileInfo.size(); } // Used by ASTReader. void setHeaderFileInfoForUID(HeaderFileInfo HFI, unsigned UID); + /// getFileInfo - Return the HeaderFileInfo structure for the specified + /// FileEntry. + const HeaderFileInfo &getFileInfo(const FileEntry *FE) const { + return const_cast<HeaderSearch*>(this)->getFileInfo(FE); + } + // Used by external tools typedef std::vector<DirectoryLookup>::const_iterator search_dir_iterator; search_dir_iterator search_dir_begin() const { return SearchDirs.begin(); } @@ -385,7 +518,39 @@ public: size_t getTotalMemory() const; + static std::string NormalizeDashIncludePath(StringRef File, + FileManager &FileMgr); + private: + /// \brief Describes what happened when we tried to load a module map file. + enum LoadModuleMapResult { + /// \brief The module map file had already been loaded. + LMM_AlreadyLoaded, + /// \brief The module map file was loaded by this invocation. + LMM_NewlyLoaded, + /// \brief There is was directory with the given name. + LMM_NoDirectory, + /// \brief There was either no module map file or the module map file was + /// invalid. + LMM_InvalidModuleMap + }; + + /// \brief Try to load the module map file in the given directory. + /// + /// \param DirName The name of the directory where we will look for a module + /// map file. + /// + /// \returns The result of attempting to load the module map file from the + /// named directory. + LoadModuleMapResult loadModuleMapFile(StringRef DirName); + + /// \brief Try to load the module map file in the given directory. + /// + /// \param Dir The directory where we will look for a module map file. + /// + /// \returns The result of attempting to load the module map file from the + /// named directory. + LoadModuleMapResult loadModuleMapFile(const DirectoryEntry *Dir); /// getFileInfo - Return the HeaderFileInfo structure for the specified /// FileEntry. diff --git a/include/clang/Lex/LexDiagnostic.h b/include/clang/Lex/LexDiagnostic.h index f454e2309acb..41b93963a7ee 100644 --- a/include/clang/Lex/LexDiagnostic.h +++ b/include/clang/Lex/LexDiagnostic.h @@ -16,7 +16,7 @@ namespace clang { namespace diag { enum { #define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,\ - SFINAE,ACCESS,NOWERROR,SHOWINSYSHEADER,CATEGORY,BRIEF,FULL) ENUM, + SFINAE,ACCESS,NOWERROR,SHOWINSYSHEADER,CATEGORY) ENUM, #define LEXSTART #include "clang/Basic/DiagnosticLexKinds.inc" #undef DIAG diff --git a/include/clang/Lex/Lexer.h b/include/clang/Lex/Lexer.h index e01427f574d2..04bcead6d45e 100644 --- a/include/clang/Lex/Lexer.h +++ b/include/clang/Lex/Lexer.h @@ -44,12 +44,14 @@ enum ConflictMarkerKind { /// or buffering/seeking of tokens, only forward lexing is supported. It relies /// on the specified Preprocessor object to handle preprocessor directives, etc. class Lexer : public PreprocessorLexer { + virtual void anchor(); + //===--------------------------------------------------------------------===// // Constant configuration values for this lexer. const char *BufferStart; // Start of the buffer. const char *BufferEnd; // End of the buffer. SourceLocation FileLoc; // Location for start of file. - LangOptions Features; // Features enabled by this language (cache). + LangOptions LangOpts; // LangOpts enabled by this language (cache). bool Is_PragmaLexer; // True if lexer for _Pragma handling. //===--------------------------------------------------------------------===// @@ -97,14 +99,14 @@ public: /// Lexer constructor - Create a new raw lexer object. This object is only /// suitable for calls to 'LexRawToken'. This lexer assumes that the text /// range will outlive it, so it doesn't take ownership of it. - Lexer(SourceLocation FileLoc, const LangOptions &Features, + Lexer(SourceLocation FileLoc, const LangOptions &LangOpts, const char *BufStart, const char *BufPtr, const char *BufEnd); /// Lexer constructor - Create a new raw lexer object. This object is only /// suitable for calls to 'LexRawToken'. This lexer assumes that the text /// range will outlive it, so it doesn't take ownership of it. Lexer(FileID FID, const llvm::MemoryBuffer *InputBuffer, - const SourceManager &SM, const LangOptions &Features); + const SourceManager &SM, const LangOptions &LangOpts); /// Create_PragmaLexer: Lexer constructor - Create a new lexer object for /// _Pragma expansion. This has a variety of magic semantics that this method @@ -115,9 +117,9 @@ public: unsigned TokLen, Preprocessor &PP); - /// getFeatures - Return the language features currently enabled. NOTE: this - /// lexer modifies features as a file is parsed! - const LangOptions &getFeatures() const { return Features; } + /// getLangOpts - Return the language features currently enabled. + /// NOTE: this lexer modifies features as a file is parsed! + const LangOptions &getLangOpts() const { return LangOpts; } /// getFileLoc - Return the File Location for the file we are lexing out of. /// The physical location encodes the location where the characters come from, @@ -238,7 +240,7 @@ public: /// if an internal buffer is returned. static unsigned getSpelling(const Token &Tok, const char *&Buffer, const SourceManager &SourceMgr, - const LangOptions &Features, + const LangOptions &LangOpts, bool *Invalid = 0); /// getSpelling() - Return the 'spelling' of the Tok token. The spelling of a @@ -248,7 +250,7 @@ public: /// UCNs, etc. static std::string getSpelling(const Token &Tok, const SourceManager &SourceMgr, - const LangOptions &Features, + const LangOptions &LangOpts, bool *Invalid = 0); /// getSpelling - This method is used to get the spelling of the @@ -262,7 +264,7 @@ public: static StringRef getSpelling(SourceLocation loc, SmallVectorImpl<char> &buffer, const SourceManager &SourceMgr, - const LangOptions &Features, + const LangOptions &LangOpts, bool *invalid = 0); /// MeasureTokenLength - Relex the token at the specified location and return @@ -288,7 +290,7 @@ public: static SourceLocation AdvanceToTokenCharacter(SourceLocation TokStart, unsigned Character, const SourceManager &SM, - const LangOptions &Features); + const LangOptions &LangOpts); /// \brief Computes the source location just past the end of the /// token at this source location. @@ -307,19 +309,52 @@ public: /// a source location pointing to the last character in the token, etc. static SourceLocation getLocForEndOfToken(SourceLocation Loc, unsigned Offset, const SourceManager &SM, - const LangOptions &Features); + const LangOptions &LangOpts); /// \brief Returns true if the given MacroID location points at the first /// token of the macro expansion. + /// + /// \param MacroBegin If non-null and function returns true, it is set to + /// begin location of the macro. static bool isAtStartOfMacroExpansion(SourceLocation loc, - const SourceManager &SM, - const LangOptions &LangOpts); + const SourceManager &SM, + const LangOptions &LangOpts, + SourceLocation *MacroBegin = 0); /// \brief Returns true if the given MacroID location points at the last /// token of the macro expansion. + /// + /// \param MacroBegin If non-null and function returns true, it is set to + /// end location of the macro. static bool isAtEndOfMacroExpansion(SourceLocation loc, - const SourceManager &SM, - const LangOptions &LangOpts); + const SourceManager &SM, + const LangOptions &LangOpts, + SourceLocation *MacroEnd = 0); + + /// \brief Accepts a range and returns a character range with file locations. + /// + /// Returns a null range if a part of the range resides inside a macro + /// expansion or the range does not reside on the same FileID. + static CharSourceRange makeFileCharRange(CharSourceRange Range, + const SourceManager &SM, + const LangOptions &LangOpts); + + /// \brief Returns a string for the source that the range encompasses. + static StringRef getSourceText(CharSourceRange Range, + const SourceManager &SM, + const LangOptions &LangOpts, + bool *Invalid = 0); + + /// \brief Retrieve the name of the immediate macro expansion. + /// + /// This routine starts from a source location, and finds the name of the macro + /// responsible for its immediate expansion. It looks through any intervening + /// macro argument expansions to compute this. It returns a StringRef which + /// refers to the SourceManager-owned buffer of the source where that macro + /// name is spelled. Thus, the result shouldn't out-live that SourceManager. + static StringRef getImmediateMacroName(SourceLocation Loc, + const SourceManager &SM, + const LangOptions &LangOpts); /// \brief Compute the preamble of the given file. /// @@ -337,7 +372,7 @@ public: /// of the file begins along with a boolean value indicating whether /// the preamble ends at the beginning of a new line. static std::pair<unsigned, bool> - ComputePreamble(const llvm::MemoryBuffer *Buffer, const LangOptions &Features, + ComputePreamble(const llvm::MemoryBuffer *Buffer, const LangOptions &LangOpts, unsigned MaxLines = 0); //===--------------------------------------------------------------------===// @@ -451,7 +486,7 @@ public: /// getCharAndSizeNoWarn - Like the getCharAndSize method, but does not ever /// emit a warning. static inline char getCharAndSizeNoWarn(const char *Ptr, unsigned &Size, - const LangOptions &Features) { + const LangOptions &LangOpts) { // If this is not a trigraph and not a UCN or escaped newline, return // quickly. if (isObviouslySimpleCharacter(Ptr[0])) { @@ -460,7 +495,7 @@ public: } Size = 0; - return getCharAndSizeSlowNoWarn(Ptr, Size, Features); + return getCharAndSizeSlowNoWarn(Ptr, Size, LangOpts); } /// getEscapedNewLineSize - Return the size of the specified escaped newline, @@ -489,12 +524,14 @@ private: /// getCharAndSizeSlowNoWarn - Same as getCharAndSizeSlow, but never emits a /// diagnostic. static char getCharAndSizeSlowNoWarn(const char *Ptr, unsigned &Size, - const LangOptions &Features); + const LangOptions &LangOpts); //===--------------------------------------------------------------------===// // Other lexer functions. void SkipBytes(unsigned Bytes, bool StartOfLine); + + const char *LexUDSuffix(Token &Result, const char *CurPtr); // Helper functions to lex the remainder of a token of the specific type. void LexIdentifier (Token &Result, const char *CurPtr); diff --git a/include/clang/Lex/LiteralSupport.h b/include/clang/Lex/LiteralSupport.h index b33092c753a8..7e7f82f05fa1 100644 --- a/include/clang/Lex/LiteralSupport.h +++ b/include/clang/Lex/LiteralSupport.h @@ -45,7 +45,7 @@ class NumericLiteralParser { unsigned radix; - bool saw_exponent, saw_period; + bool saw_exponent, saw_period, saw_ud_suffix; public: NumericLiteralParser(const char *begin, const char *end, @@ -64,8 +64,17 @@ public: bool isFloatingLiteral() const { return saw_period || saw_exponent; } - bool hasSuffix() const { - return SuffixBegin != ThisTokEnd; + + bool hasUDSuffix() const { + return saw_ud_suffix; + } + StringRef getUDSuffix() const { + assert(saw_ud_suffix); + return StringRef(SuffixBegin, ThisTokEnd - SuffixBegin); + } + unsigned getUDSuffixOffset() const { + assert(saw_ud_suffix); + return SuffixBegin - ThisTokBegin; } unsigned getRadix() const { return radix; } @@ -128,6 +137,8 @@ class CharLiteralParser { tok::TokenKind Kind; bool IsMultiChar; bool HadError; + SmallString<32> UDSuffixBuf; + unsigned UDSuffixOffset; public: CharLiteralParser(const char *begin, const char *end, SourceLocation Loc, Preprocessor &PP, @@ -140,6 +151,11 @@ public: bool isUTF32() const { return Kind == tok::utf32_char_constant; } bool isMultiChar() const { return IsMultiChar; } uint64_t getValue() const { return Value; } + StringRef getUDSuffix() const { return UDSuffixBuf; } + unsigned getUDSuffixOffset() const { + assert(!UDSuffixBuf.empty() && "no ud-suffix"); + return UDSuffixOffset; + } }; /// StringLiteralParser - This decodes string escape characters and performs @@ -155,8 +171,11 @@ class StringLiteralParser { unsigned SizeBound; unsigned CharByteWidth; tok::TokenKind Kind; - llvm::SmallString<512> ResultBuf; + SmallString<512> ResultBuf; char *ResultPtr; // cursor + SmallString<32> UDSuffixBuf; + unsigned UDSuffixToken; + unsigned UDSuffixOffset; public: StringLiteralParser(const Token *StringToks, unsigned NumStringToks, Preprocessor &PP, bool Complain = true); @@ -189,15 +208,30 @@ public: /// checking of the string literal and emit errors and warnings. unsigned getOffsetOfStringByte(const Token &TheTok, unsigned ByteNo) const; - bool isAscii() { return Kind == tok::string_literal; } - bool isWide() { return Kind == tok::wide_string_literal; } - bool isUTF8() { return Kind == tok::utf8_string_literal; } - bool isUTF16() { return Kind == tok::utf16_string_literal; } - bool isUTF32() { return Kind == tok::utf32_string_literal; } + bool isAscii() const { return Kind == tok::string_literal; } + bool isWide() const { return Kind == tok::wide_string_literal; } + bool isUTF8() const { return Kind == tok::utf8_string_literal; } + bool isUTF16() const { return Kind == tok::utf16_string_literal; } + bool isUTF32() const { return Kind == tok::utf32_string_literal; } + bool isPascal() const { return Pascal; } + + StringRef getUDSuffix() const { return UDSuffixBuf; } + + /// Get the index of a token containing a ud-suffix. + unsigned getUDSuffixToken() const { + assert(!UDSuffixBuf.empty() && "no ud-suffix"); + return UDSuffixToken; + } + /// Get the spelling offset of the first byte of the ud-suffix. + unsigned getUDSuffixOffset() const { + assert(!UDSuffixBuf.empty() && "no ud-suffix"); + return UDSuffixOffset; + } private: void init(const Token *StringToks, unsigned NumStringToks); - void CopyStringFragment(StringRef Fragment); + bool CopyStringFragment(StringRef Fragment); + bool DiagnoseBadString(const Token& Tok); }; } // end namespace clang diff --git a/include/clang/Lex/MacroInfo.h b/include/clang/Lex/MacroInfo.h index b381e0f25f41..8775d39fe8dd 100644 --- a/include/clang/Lex/MacroInfo.h +++ b/include/clang/Lex/MacroInfo.h @@ -39,10 +39,11 @@ class MacroInfo { IdentifierInfo **ArgumentList; unsigned NumArguments; - /// \brief The location at which this macro was exported from its module. + /// \brief The location at which this macro was either explicitly exported + /// from its module or marked as private. /// - /// If invalid, this macro has not been explicitly exported. - SourceLocation ExportLocation; + /// If invalid, this macro has not been explicitly given any visibility. + SourceLocation VisibilityLocation; /// ReplacementTokens - This is the list of tokens that the macro is defined /// to. @@ -97,6 +98,9 @@ private: /// \brief Must warn if the macro is unused at the end of translation unit. bool IsWarnIfUnused : 1; + /// \brief Whether the macro has public (when described in a module). + bool IsPublic : 1; + ~MacroInfo() { assert(ArgumentList == 0 && "Didn't call destroy before dtor!"); } @@ -279,17 +283,18 @@ public: } /// \brief Set the export location for this macro. - void setExportLocation(SourceLocation ExportLoc) { - ExportLocation = ExportLoc; + void setVisibility(bool Public, SourceLocation Loc) { + VisibilityLocation = Loc; + IsPublic = Public; } - /// \brief Determine whether this macro was explicitly exported from its + /// \brief Determine whether this macro is part of the public API of its /// module. - bool isExported() const { return ExportLocation.isValid(); } + bool isPublic() const { return IsPublic; } - /// \brief Determine the location where this macro was explicitly exported - /// from its module. - SourceLocation getExportLocation() { return ExportLocation; } + /// \brief Determine the location where this macro was explicitly made + /// public or private within its module. + SourceLocation getVisibilityLocation() { return VisibilityLocation; } private: unsigned getDefinitionLengthSlow(SourceManager &SM) const; diff --git a/include/clang/Lex/ModuleLoader.h b/include/clang/Lex/ModuleLoader.h index 72ec0e3ebc9f..36d03c0aa2a3 100644 --- a/include/clang/Lex/ModuleLoader.h +++ b/include/clang/Lex/ModuleLoader.h @@ -14,15 +14,18 @@ #ifndef LLVM_CLANG_LEX_MODULE_LOADER_H #define LLVM_CLANG_LEX_MODULE_LOADER_H +#include "clang/Basic/Module.h" #include "clang/Basic/SourceLocation.h" +#include "llvm/ADT/ArrayRef.h" namespace clang { class IdentifierInfo; -/// \brief An opaque key that is used to describe the module and can be -/// interpreted by the module loader itself. -typedef void *ModuleKey; +/// \brief A sequence of identifier/location pairs used to describe a particular +/// module or submodule, e.g., std.vector. +typedef llvm::ArrayRef<std::pair<IdentifierInfo*, SourceLocation> > + ModuleIdPath; /// \brief Abstract interface for a module loader. /// @@ -39,15 +42,22 @@ public: /// parameters. /// /// \param ImportLoc The location of the 'import' keyword. - /// \param ModuleName The name of the module to be loaded. - /// \param ModuleNameLoc The location of the module name. /// - /// \returns If successful, a non-NULL module key describing this module. - /// Otherwise, returns NULL to indicate that the module could not be - /// loaded. - virtual ModuleKey loadModule(SourceLocation ImportLoc, - IdentifierInfo &ModuleName, - SourceLocation ModuleNameLoc) = 0; + /// \param Path The identifiers (and their locations) of the module + /// "path", e.g., "std.vector" would be split into "std" and "vector". + /// + /// \param Visibility The visibility provided for the names in the loaded + /// module. + /// + /// \param IsInclusionDirective Indicates that this module is being loaded + /// implicitly, due to the presence of an inclusion directive. Otherwise, + /// it is being loaded due to an import declaration. + /// + /// \returns If successful, returns the loaded module. Otherwise, returns + /// NULL to indicate that the module could not be loaded. + virtual Module *loadModule(SourceLocation ImportLoc, ModuleIdPath Path, + Module::NameVisibilityKind Visibility, + bool IsInclusionDirective) = 0; }; } diff --git a/include/clang/Lex/ModuleMap.h b/include/clang/Lex/ModuleMap.h new file mode 100644 index 000000000000..4ebb1d42bf3d --- /dev/null +++ b/include/clang/Lex/ModuleMap.h @@ -0,0 +1,237 @@ +//===--- ModuleMap.h - Describe the layout of modules -----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the ModuleMap interface, which describes the layout of a +// module as it relates to headers. +// +//===----------------------------------------------------------------------===// + + +#ifndef LLVM_CLANG_LEX_MODULEMAP_H +#define LLVM_CLANG_LEX_MODULEMAP_H + +#include "clang/Basic/LangOptions.h" +#include "clang/Basic/Module.h" +#include "clang/Basic/SourceManager.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/IntrusiveRefCntPtr.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/StringMap.h" +#include <string> + +namespace clang { + +class DirectoryEntry; +class FileEntry; +class FileManager; +class DiagnosticConsumer; +class DiagnosticsEngine; +class ModuleMapParser; + +class ModuleMap { + SourceManager *SourceMgr; + IntrusiveRefCntPtr<DiagnosticsEngine> Diags; + const LangOptions &LangOpts; + const TargetInfo *Target; + + /// \brief The directory used for Clang-supplied, builtin include headers, + /// such as "stdint.h". + const DirectoryEntry *BuiltinIncludeDir; + + /// \brief Language options used to parse the module map itself. + /// + /// These are always simple C language options. + LangOptions MMapLangOpts; + + /// \brief The top-level modules that are known. + llvm::StringMap<Module *> Modules; + + /// \brief Mapping from each header to the module that owns the contents of the + /// that header. + llvm::DenseMap<const FileEntry *, Module *> Headers; + + /// \brief Mapping from directories with umbrella headers to the module + /// that is generated from the umbrella header. + /// + /// This mapping is used to map headers that haven't explicitly been named + /// in the module map over to the module that includes them via its umbrella + /// header. + llvm::DenseMap<const DirectoryEntry *, Module *> UmbrellaDirs; + + friend class ModuleMapParser; + + /// \brief Resolve the given export declaration into an actual export + /// declaration. + /// + /// \param Mod The module in which we're resolving the export declaration. + /// + /// \param Unresolved The export declaration to resolve. + /// + /// \param Complain Whether this routine should complain about unresolvable + /// exports. + /// + /// \returns The resolved export declaration, which will have a NULL pointer + /// if the export could not be resolved. + Module::ExportDecl + resolveExport(Module *Mod, const Module::UnresolvedExportDecl &Unresolved, + bool Complain); + +public: + /// \brief Construct a new module map. + /// + /// \param FileMgr The file manager used to find module files and headers. + /// This file manager should be shared with the header-search mechanism, since + /// they will refer to the same headers. + /// + /// \param DC A diagnostic consumer that will be cloned for use in generating + /// diagnostics. + /// + /// \param LangOpts Language options for this translation unit. + /// + /// \param Target The target for this translation unit. + ModuleMap(FileManager &FileMgr, const DiagnosticConsumer &DC, + const LangOptions &LangOpts, const TargetInfo *Target); + + /// \brief Destroy the module map. + /// + ~ModuleMap(); + + /// \brief Set the target information. + void setTarget(const TargetInfo &Target); + + /// \brief Set the directory that contains Clang-supplied include + /// files, such as our stdarg.h or tgmath.h. + void setBuiltinIncludeDir(const DirectoryEntry *Dir) { + BuiltinIncludeDir = Dir; + } + + /// \brief Retrieve the module that owns the given header file, if any. + /// + /// \param File The header file that is likely to be included. + /// + /// \returns The module that owns the given header file, or null to indicate + /// that no module owns this header file. + Module *findModuleForHeader(const FileEntry *File); + + /// \brief Determine whether the given header is part of a module + /// marked 'unavailable'. + bool isHeaderInUnavailableModule(const FileEntry *Header); + + /// \brief Retrieve a module with the given name. + /// + /// \param The name of the module to look up. + /// + /// \returns The named module, if known; otherwise, returns null. + Module *findModule(StringRef Name); + + /// \brief Retrieve a module with the given name using lexical name lookup, + /// starting at the given context. + /// + /// \param The name of the module to look up. + /// + /// \param Context The module context, from which we will perform lexical + /// name lookup. + /// + /// \returns The named module, if known; otherwise, returns null. + Module *lookupModuleUnqualified(StringRef Name, Module *Context); + + /// \brief Retrieve a module with the given name within the given context, + /// using direct (qualified) name lookup. + /// + /// \param The name of the module to look up. + /// + /// \param Context The module for which we will look for a submodule. If + /// null, we will look for a top-level module. + /// + /// \returns The named submodule, if known; otherwose, returns null. + Module *lookupModuleQualified(StringRef Name, Module *Context); + + /// \brief Find a new module or submodule, or create it if it does not already + /// exist. + /// + /// \param Name The name of the module to find or create. + /// + /// \param Parent The module that will act as the parent of this submodule, + /// or NULL to indicate that this is a top-level module. + /// + /// \param IsFramework Whether this is a framework module. + /// + /// \param IsExplicit Whether this is an explicit submodule. + /// + /// \returns The found or newly-created module, along with a boolean value + /// that will be true if the module is newly-created. + std::pair<Module *, bool> findOrCreateModule(StringRef Name, Module *Parent, + bool IsFramework, + bool IsExplicit); + + /// \brief Infer the contents of a framework module map from the given + /// framework directory. + Module *inferFrameworkModule(StringRef ModuleName, + const DirectoryEntry *FrameworkDir, + bool IsSystem, Module *Parent); + + /// \brief Retrieve the module map file containing the definition of the given + /// module. + /// + /// \param Module The module whose module map file will be returned, if known. + /// + /// \returns The file entry for the module map file containing the given + /// module, or NULL if the module definition was inferred. + const FileEntry *getContainingModuleMapFile(Module *Module); + + /// \brief Resolve all of the unresolved exports in the given module. + /// + /// \param Mod The module whose exports should be resolved. + /// + /// \param Complain Whether to emit diagnostics for failures. + /// + /// \returns true if any errors were encountered while resolving exports, + /// false otherwise. + bool resolveExports(Module *Mod, bool Complain); + + /// \brief Infers the (sub)module based on the given source location and + /// source manager. + /// + /// \param Loc The location within the source that we are querying, along + /// with its source manager. + /// + /// \returns The module that owns this source location, or null if no + /// module owns this source location. + Module *inferModuleFromLocation(FullSourceLoc Loc); + + /// \brief Sets the umbrella header of the given module to the given + /// header. + void setUmbrellaHeader(Module *Mod, const FileEntry *UmbrellaHeader); + + /// \brief Sets the umbrella directory of the given module to the given + /// directory. + void setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir); + + /// \brief Adds this header to the given module. + void addHeader(Module *Mod, const FileEntry *Header); + + /// \brief Parse the given module map file, and record any modules we + /// encounter. + /// + /// \param File The file to be parsed. + /// + /// \returns true if an error occurred, false otherwise. + bool parseModuleMapFile(const FileEntry *File); + + /// \brief Dump the contents of the module map, for debugging purposes. + void dump(); + + typedef llvm::StringMap<Module *>::const_iterator module_iterator; + module_iterator module_begin() const { return Modules.begin(); } + module_iterator module_end() const { return Modules.end(); } +}; + +} +#endif diff --git a/include/clang/Lex/PPCallbacks.h b/include/clang/Lex/PPCallbacks.h index 1fc1a05db646..33558c8dfdc9 100644 --- a/include/clang/Lex/PPCallbacks.h +++ b/include/clang/Lex/PPCallbacks.h @@ -58,6 +58,23 @@ public: SrcMgr::CharacteristicKind FileType) { } + /// FileNotFound - This callback is invoked whenever an inclusion directive + /// results in a file-not-found error. + /// + /// \param FileName The name of the file being included, as written in the + /// source code. + /// + /// \param RecoveryPath If this client indicates that it can recover from + /// this missing file, the client should set this as an additional header + /// search patch. + /// + /// \returns true to indicate that the preprocessor should attempt to recover + /// by adding \p RecoveryPath as a header search path. + virtual bool FileNotFound(StringRef FileName, + SmallVectorImpl<char> &RecoveryPath) { + return false; + } + /// \brief This callback is invoked whenever an inclusion directive of /// any kind (\c #include, \c #import, etc.) has been processed, regardless /// of whether the inclusion will actually result in an inclusion. @@ -173,40 +190,49 @@ public: } /// If -- This hook is called whenever an #if is seen. - /// \param Range The SourceRange of the expression being tested. + /// \param Loc the source location of the directive. + /// \param ConditionRange The SourceRange of the expression being tested. // FIXME: better to pass in a list (or tree!) of Tokens. - virtual void If(SourceRange Range) { + virtual void If(SourceLocation Loc, SourceRange ConditionRange) { } /// Elif -- This hook is called whenever an #elif is seen. - /// \param Range The SourceRange of the expression being tested. + /// \param Loc the source location of the directive. + /// \param ConditionRange The SourceRange of the expression being tested. + /// \param IfLoc the source location of the #if/#ifdef/#ifndef directive. // FIXME: better to pass in a list (or tree!) of Tokens. - virtual void Elif(SourceRange Range) { + virtual void Elif(SourceLocation Loc, SourceRange ConditionRange, + SourceLocation IfLoc) { } /// Ifdef -- This hook is called whenever an #ifdef is seen. - /// \param Loc The location of the token being tested. + /// \param Loc the source location of the directive. /// \param II Information on the token being tested. - virtual void Ifdef(const Token &MacroNameTok) { + virtual void Ifdef(SourceLocation Loc, const Token &MacroNameTok) { } /// Ifndef -- This hook is called whenever an #ifndef is seen. - /// \param Loc The location of the token being tested. + /// \param Loc the source location of the directive. /// \param II Information on the token being tested. - virtual void Ifndef(const Token &MacroNameTok) { + virtual void Ifndef(SourceLocation Loc, const Token &MacroNameTok) { } /// Else -- This hook is called whenever an #else is seen. - virtual void Else() { + /// \param Loc the source location of the directive. + /// \param IfLoc the source location of the #if/#ifdef/#ifndef directive. + virtual void Else(SourceLocation Loc, SourceLocation IfLoc) { } /// Endif -- This hook is called whenever an #endif is seen. - virtual void Endif() { + /// \param Loc the source location of the directive. + /// \param IfLoc the source location of the #if/#ifdef/#ifndef directive. + virtual void Endif(SourceLocation Loc, SourceLocation IfLoc) { } }; /// PPChainedCallbacks - Simple wrapper class for chaining callbacks. class PPChainedCallbacks : public PPCallbacks { + virtual void anchor(); PPCallbacks *First, *Second; public: @@ -231,6 +257,12 @@ public: Second->FileSkipped(ParentFile, FilenameTok, FileType); } + virtual bool FileNotFound(StringRef FileName, + SmallVectorImpl<char> &RecoveryPath) { + return First->FileNotFound(FileName, RecoveryPath) || + Second->FileNotFound(FileName, RecoveryPath); + } + virtual void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok, StringRef FileName, @@ -311,39 +343,40 @@ public: } /// If -- This hook is called whenever an #if is seen. - virtual void If(SourceRange Range) { - First->If(Range); - Second->If(Range); + virtual void If(SourceLocation Loc, SourceRange ConditionRange) { + First->If(Loc, ConditionRange); + Second->If(Loc, ConditionRange); } /// Elif -- This hook is called whenever an #if is seen. - virtual void Elif(SourceRange Range) { - First->Elif(Range); - Second->Elif(Range); + virtual void Elif(SourceLocation Loc, SourceRange ConditionRange, + SourceLocation IfLoc) { + First->Elif(Loc, ConditionRange, IfLoc); + Second->Elif(Loc, ConditionRange, IfLoc); } /// Ifdef -- This hook is called whenever an #ifdef is seen. - virtual void Ifdef(const Token &MacroNameTok) { - First->Ifdef(MacroNameTok); - Second->Ifdef(MacroNameTok); + virtual void Ifdef(SourceLocation Loc, const Token &MacroNameTok) { + First->Ifdef(Loc, MacroNameTok); + Second->Ifdef(Loc, MacroNameTok); } /// Ifndef -- This hook is called whenever an #ifndef is seen. - virtual void Ifndef(const Token &MacroNameTok) { - First->Ifndef(MacroNameTok); - Second->Ifndef(MacroNameTok); + virtual void Ifndef(SourceLocation Loc, const Token &MacroNameTok) { + First->Ifndef(Loc, MacroNameTok); + Second->Ifndef(Loc, MacroNameTok); } /// Else -- This hook is called whenever an #else is seen. - virtual void Else() { - First->Else(); - Second->Else(); + virtual void Else(SourceLocation Loc, SourceLocation IfLoc) { + First->Else(Loc, IfLoc); + Second->Else(Loc, IfLoc); } /// Endif -- This hook is called whenever an #endif is seen. - virtual void Endif() { - First->Endif(); - Second->Endif(); + virtual void Endif(SourceLocation Loc, SourceLocation IfLoc) { + First->Endif(Loc, IfLoc); + Second->Endif(Loc, IfLoc); } }; diff --git a/include/clang/Lex/PreprocessingRecord.h b/include/clang/Lex/PreprocessingRecord.h index 53da19e6c296..45e3a5d64730 100644 --- a/include/clang/Lex/PreprocessingRecord.h +++ b/include/clang/Lex/PreprocessingRecord.h @@ -17,8 +17,11 @@ #include "clang/Lex/PPCallbacks.h" #include "clang/Basic/SourceLocation.h" #include "clang/Basic/IdentifierTable.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/Optional.h" #include "llvm/Support/Allocator.h" +#include "llvm/Support/Compiler.h" #include <vector> namespace clang { @@ -85,7 +88,7 @@ namespace clang { /// \brief Retrieve the source range that covers this entire preprocessed /// entity. - SourceRange getSourceRange() const { return Range; } + SourceRange getSourceRange() const LLVM_READONLY { return Range; } /// \brief Returns true if there was a problem loading the preprocessed /// entity. @@ -269,6 +272,13 @@ namespace clang { /// preprocessed entities that \arg Range encompasses. virtual std::pair<unsigned, unsigned> findPreprocessedEntitiesInRange(SourceRange Range) = 0; + + /// \brief Optionally returns true or false if the preallocated preprocessed + /// entity with index \arg Index came from file \arg FID. + virtual llvm::Optional<bool> isPreprocessedEntityInFileID(unsigned Index, + FileID FID) { + return llvm::Optional<bool>(); + } }; /// \brief A record of the steps taken while preprocessing a source file, @@ -276,10 +286,6 @@ namespace clang { /// expanded, etc. class PreprocessingRecord : public PPCallbacks { SourceManager &SourceMgr; - - /// \brief Whether we should include nested macro expansions in - /// the preprocessing record. - bool IncludeNestedMacroExpansions; /// \brief Allocator used to store preprocessing objects. llvm::BumpPtrAllocator BumpAlloc; @@ -295,6 +301,44 @@ namespace clang { /// and are referenced by the iterator using negative indices. std::vector<PreprocessedEntity *> LoadedPreprocessedEntities; + bool RecordCondDirectives; + unsigned CondDirectiveNextIdx; + SmallVector<unsigned, 6> CondDirectiveStack; + + class CondDirectiveLoc { + SourceLocation Loc; + unsigned Idx; + + public: + CondDirectiveLoc(SourceLocation Loc, unsigned Idx) : Loc(Loc), Idx(Idx) {} + + SourceLocation getLoc() const { return Loc; } + unsigned getIdx() const { return Idx; } + + class Comp { + SourceManager &SM; + public: + explicit Comp(SourceManager &SM) : SM(SM) {} + bool operator()(const CondDirectiveLoc &LHS, + const CondDirectiveLoc &RHS) { + return SM.isBeforeInTranslationUnit(LHS.getLoc(), RHS.getLoc()); + } + bool operator()(const CondDirectiveLoc &LHS, SourceLocation RHS) { + return SM.isBeforeInTranslationUnit(LHS.getLoc(), RHS); + } + bool operator()(SourceLocation LHS, const CondDirectiveLoc &RHS) { + return SM.isBeforeInTranslationUnit(LHS, RHS.getLoc()); + } + }; + }; + + typedef std::vector<CondDirectiveLoc> CondDirectiveLocsTy; + /// \brief The locations of conditional directives in source order. + CondDirectiveLocsTy CondDirectiveLocs; + + void addCondDirectiveLoc(CondDirectiveLoc DirLoc); + unsigned findCondDirectiveIdx(SourceLocation Loc) const; + /// \brief Global (loaded or local) ID for a preprocessed entity. /// Negative values are used to indicate preprocessed entities /// loaded from the external source while non-negative values are used to @@ -345,7 +389,7 @@ namespace clang { public: /// \brief Construct a new preprocessing record. - PreprocessingRecord(SourceManager &SM, bool IncludeNestedMacroExpansions); + PreprocessingRecord(SourceManager &SM, bool RecordConditionalDirectives); /// \brief Allocate memory in the preprocessing record. void *Allocate(unsigned Size, unsigned Align = 8) { @@ -386,7 +430,7 @@ namespace clang { iterator() : Self(0), Position(0) { } - iterator(PreprocessingRecord *Self, int Position) + iterator(PreprocessingRecord *Self, PPEntityID Position) : Self(Self), Position(Position) { } value_type operator*() const { @@ -471,6 +515,7 @@ namespace clang { X.Position -= D; return X; } + friend class PreprocessingRecord; }; friend class iterator; @@ -496,11 +541,41 @@ namespace clang { /// \brief Returns a pair of [Begin, End) iterators of preprocessed entities /// that source range \arg R encompasses. + /// + /// \param R the range to look for preprocessed entities. + /// std::pair<iterator, iterator> getPreprocessedEntitiesInRange(SourceRange R); + /// \brief Returns true if the preprocessed entity that \arg PPEI iterator + /// points to is coming from the file \arg FID. + /// + /// Can be used to avoid implicit deserializations of preallocated + /// preprocessed entities if we only care about entities of a specific file + /// and not from files #included in the range given at + /// \see getPreprocessedEntitiesInRange. + bool isEntityInFileID(iterator PPEI, FileID FID); + /// \brief Add a new preprocessed entity to this record. - void addPreprocessedEntity(PreprocessedEntity *Entity); - + PPEntityID addPreprocessedEntity(PreprocessedEntity *Entity); + + /// \brief Returns true if this PreprocessingRecord is keeping track of + /// conditional directives locations. + bool isRecordingConditionalDirectives() const { + return RecordCondDirectives; + } + + /// \brief Returns true if the given range intersects with a conditional + /// directive. if a #if/#endif block is fully contained within the range, + /// this function will return false. + bool rangeIntersectsConditionalDirective(SourceRange Range) const; + + /// \brief Returns true if the given locations are in different regions, + /// separated by conditional directive blocks. + bool areInDifferentConditionalDirectiveRegion(SourceLocation LHS, + SourceLocation RHS) const { + return findCondDirectiveIdx(LHS) != findCondDirectiveIdx(RHS); + } + /// \brief Set the external source for preprocessed entities. void SetExternalSource(ExternalPreprocessingRecordSource &Source); @@ -513,6 +588,7 @@ namespace clang { /// \c MacroInfo. MacroDefinition *findMacroDefinition(const MacroInfo *MI); + private: virtual void MacroExpands(const Token &Id, const MacroInfo* MI, SourceRange Range); virtual void MacroDefined(const Token &Id, const MacroInfo *MI); @@ -525,6 +601,23 @@ namespace clang { SourceLocation EndLoc, StringRef SearchPath, StringRef RelativePath); + virtual void If(SourceLocation Loc, SourceRange ConditionRange); + virtual void Elif(SourceLocation Loc, SourceRange ConditionRange, + SourceLocation IfLoc); + virtual void Ifdef(SourceLocation Loc, const Token &MacroNameTok); + virtual void Ifndef(SourceLocation Loc, const Token &MacroNameTok); + virtual void Else(SourceLocation Loc, SourceLocation IfLoc); + virtual void Endif(SourceLocation Loc, SourceLocation IfLoc); + + /// \brief Cached result of the last \see getPreprocessedEntitiesInRange + /// query. + struct { + SourceRange Range; + std::pair<PPEntityID, PPEntityID> Result; + } CachedRangeQuery; + + std::pair<PPEntityID, PPEntityID> + getPreprocessedEntitiesInRangeSlow(SourceRange R); friend class ASTReader; friend class ASTWriter; diff --git a/include/clang/Lex/Preprocessor.h b/include/clang/Lex/Preprocessor.h index 8b7743316f9c..055008fd44ce 100644 --- a/include/clang/Lex/Preprocessor.h +++ b/include/clang/Lex/Preprocessor.h @@ -33,6 +33,10 @@ #include "llvm/Support/Allocator.h" #include <vector> +namespace llvm { + template<unsigned InternalLen> class SmallString; +} + namespace clang { class SourceManager; @@ -50,15 +54,15 @@ class CodeCompletionHandler; class DirectoryLookup; class PreprocessingRecord; class ModuleLoader; - + /// Preprocessor - This object engages in a tight little dance with the lexer to /// efficiently preprocess tokens. Lexers know only about tokens within a /// single source file, and don't know anything about preprocessor-level issues /// like the #include stack, token expansion, etc. /// -class Preprocessor : public llvm::RefCountedBase<Preprocessor> { +class Preprocessor : public RefCountedBase<Preprocessor> { DiagnosticsEngine *Diags; - LangOptions &Features; + LangOptions &LangOpts; const TargetInfo *Target; FileManager &FileMgr; SourceManager &SourceMgr; @@ -69,10 +73,10 @@ class Preprocessor : public llvm::RefCountedBase<Preprocessor> { /// \brief External source of macros. ExternalPreprocessorSource *ExternalSource; - + /// PTH - An optional PTHManager object used for getting tokens from /// a token cache rather than lexing the original source file. - llvm::OwningPtr<PTHManager> PTH; + OwningPtr<PTHManager> PTH; /// BP - A BumpPtrAllocator object used to quickly allocate and release /// objects internal to the Preprocessor. @@ -107,8 +111,7 @@ class Preprocessor : public llvm::RefCountedBase<Preprocessor> { bool KeepComments : 1; bool KeepMacroComments : 1; bool SuppressIncludeNotFoundError : 1; - bool AutoModuleImport : 1; - + // State that changes while the preprocessor runs: bool InMacroArgs : 1; // True if parsing fn macro invocation args. @@ -121,6 +124,9 @@ class Preprocessor : public llvm::RefCountedBase<Preprocessor> { /// \brief Whether we have already loaded macros from the external source. mutable bool ReadMacrosFromExternalSource : 1; + /// \brief True if we are pre-expanding macro arguments. + bool InMacroArgPreExpansion; + /// Identifiers - This is mapping/lookup information for all identifiers in /// the program, including program keywords. mutable IdentifierTable Identifiers; @@ -145,9 +151,13 @@ class Preprocessor : public llvm::RefCountedBase<Preprocessor> { /// with this preprocessor. std::vector<CommentHandler *> CommentHandlers; + /// \brief True if we want to ignore EOF token and continue later on (thus + /// avoid tearing the Lexer and etc. down). + bool IncrementalProcessing; + /// \brief The code-completion handler. CodeCompletionHandler *CodeComplete; - + /// \brief The file that we're performing code-completion for, if any. const FileEntry *CodeCompletionFile; @@ -163,14 +173,22 @@ class Preprocessor : public llvm::RefCountedBase<Preprocessor> { /// for preprocessing. SourceLocation CodeCompletionFileLoc; - /// \brief The source location of the __import_module__ keyword we just + /// \brief The source location of the 'import' contextual keyword we just /// lexed, if any. SourceLocation ModuleImportLoc; + /// \brief The module import path that we're currently processing. + llvm::SmallVector<std::pair<IdentifierInfo *, SourceLocation>, 2> + ModuleImportPath; + + /// \brief Whether the module import expectes an identifier next. Otherwise, + /// it expects a '.' or ';'. + bool ModuleImportExpectsIdentifier; + /// \brief The source location of the currently-active /// #pragma clang arc_cf_code_audited begin. SourceLocation PragmaARCCFCodeAuditedLoc; - + /// \brief True if we hit the code-completion point. bool CodeCompletionReached; @@ -179,22 +197,22 @@ class Preprocessor : public llvm::RefCountedBase<Preprocessor> { /// with a flag that indicates whether skipping this number of bytes will /// place the lexer at the start of a line. std::pair<unsigned, bool> SkipMainFilePreamble; - + /// CurLexer - This is the current top of the stack that we're lexing from if /// not expanding a macro and we are lexing directly from source code. /// Only one of CurLexer, CurPTHLexer, or CurTokenLexer will be non-null. - llvm::OwningPtr<Lexer> CurLexer; + OwningPtr<Lexer> CurLexer; /// CurPTHLexer - This is the current top of stack that we're lexing from if /// not expanding from a macro and we are lexing from a PTH cache. /// Only one of CurLexer, CurPTHLexer, or CurTokenLexer will be non-null. - llvm::OwningPtr<PTHLexer> CurPTHLexer; + OwningPtr<PTHLexer> CurPTHLexer; /// CurPPLexer - This is the current top of the stack what we're lexing from /// if not expanding a macro. This is an alias for either CurLexer or /// CurPTHLexer. PreprocessorLexer *CurPPLexer; - + /// CurLookup - The DirectoryLookup structure used to find the current /// FileEntry, if CurLexer is non-null and if applicable. This allows us to /// implement #include_next and find directory-specific properties. @@ -202,13 +220,13 @@ class Preprocessor : public llvm::RefCountedBase<Preprocessor> { /// CurTokenLexer - This is the current macro we are expanding, if we are /// expanding a macro. One of CurLexer and CurTokenLexer must be null. - llvm::OwningPtr<TokenLexer> CurTokenLexer; + OwningPtr<TokenLexer> CurTokenLexer; /// \brief The kind of lexer we're currently working with. - enum CurLexerKind { - CLK_Lexer, - CLK_PTHLexer, - CLK_TokenLexer, + enum CurLexerKind { + CLK_Lexer, + CLK_PTHLexer, + CLK_TokenLexer, CLK_CachingLexer, CLK_LexAfterModuleImport } CurLexerKind; @@ -224,10 +242,10 @@ class Preprocessor : public llvm::RefCountedBase<Preprocessor> { TokenLexer *TheTokenLexer; const DirectoryLookup *TheDirLookup; - IncludeStackInfo(enum CurLexerKind K, Lexer *L, PTHLexer* P, + IncludeStackInfo(enum CurLexerKind K, Lexer *L, PTHLexer* P, PreprocessorLexer* PPL, TokenLexer* TL, const DirectoryLookup *D) - : CurLexerKind(K), TheLexer(L), ThePTHLexer(P), ThePPLexer(PPL), + : CurLexerKind(K), TheLexer(L), ThePTHLexer(P), ThePPLexer(PPL), TheTokenLexer(TL), TheDirLookup(D) {} }; std::vector<IncludeStackInfo> IncludeMacroStack; @@ -254,9 +272,9 @@ class Preprocessor : public llvm::RefCountedBase<Preprocessor> { /// reused for quick allocation. MacroArgs *MacroArgCache; friend class MacroArgs; - - /// PragmaPushMacroInfo - For each IdentifierInfo used in a #pragma - /// push_macro directive, we keep a MacroInfo stack used to restore + + /// PragmaPushMacroInfo - For each IdentifierInfo used in a #pragma + /// push_macro directive, we keep a MacroInfo stack used to restore /// previous macro value. llvm::DenseMap<IdentifierInfo*, std::vector<MacroInfo*> > PragmaPushMacroInfo; @@ -286,12 +304,12 @@ class Preprocessor : public llvm::RefCountedBase<Preprocessor> { std::vector<std::pair<TokenLexer *, size_t> > MacroExpandingLexersStack; /// \brief A record of the macro definitions and expansions that - /// occurred during preprocessing. + /// occurred during preprocessing. /// /// This is an optional side structure that can be enabled with /// \c createPreprocessingRecord() prior to preprocessing. PreprocessingRecord *Record; - + private: // Cached tokens state. typedef SmallVector<Token, 1> CachedTokensTy; @@ -325,7 +343,7 @@ private: // Cached tokens state. MacroInfoChain *MICache; MacroInfo *getInfoForMacro(IdentifierInfo *II) const; - + public: Preprocessor(DiagnosticsEngine &diags, LangOptions &opts, const TargetInfo *target, @@ -333,7 +351,8 @@ public: ModuleLoader &TheModuleLoader, IdentifierInfoLookup *IILookup = 0, bool OwnsHeaderSearch = false, - bool DelayInitialization = false); + bool DelayInitialization = false, + bool IncrProcessing = false); ~Preprocessor(); @@ -342,11 +361,11 @@ public: /// /// \param Target Information about the target. void Initialize(const TargetInfo &Target); - + DiagnosticsEngine &getDiagnostics() const { return *Diags; } void setDiagnostics(DiagnosticsEngine &D) { Diags = &D; } - const LangOptions &getLangOptions() const { return Features; } + const LangOptions &getLangOpts() const { return LangOpts; } const TargetInfo &getTargetInfo() const { return *Target; } FileManager &getFileManager() const { return FileMgr; } SourceManager &getSourceManager() const { return SourceMgr; } @@ -371,7 +390,7 @@ public: /// \brief Retrieve the module loader associated with this preprocessor. ModuleLoader &getModuleLoader() const { return TheModuleLoader; } - + /// SetCommentRetentionState - Control whether or not the preprocessor retains /// comments in output. void SetCommentRetentionState(bool KeepComments, bool KeepMacroComments) { @@ -389,11 +408,6 @@ public: return SuppressIncludeNotFoundError; } - /// \brief Specify whether automatic module imports are enabled. - void setAutoModuleImport(bool AutoModuleImport = true) { - this->AutoModuleImport = AutoModuleImport; - } - /// isCurrentLexer - Return true if we are lexing directly from the specified /// lexer. bool isCurrentLexer(const PreprocessorLexer *L) const { @@ -425,13 +439,14 @@ public: MacroInfo *getMacroInfo(IdentifierInfo *II) const { if (!II->hasMacroDefinition()) return 0; - + return getInfoForMacro(II); } /// setMacroInfo - Specify a macro for this identifier. /// - void setMacroInfo(IdentifierInfo *II, MacroInfo *MI); + void setMacroInfo(IdentifierInfo *II, MacroInfo *MI, + bool LoadedFromAST = false); /// macro_iterator/macro_begin/macro_end - This allows you to walk the current /// state of the macro table. This visits every currently-defined macro. @@ -484,29 +499,29 @@ public: void setCodeCompletionHandler(CodeCompletionHandler &Handler) { CodeComplete = &Handler; } - + /// \brief Retrieve the current code-completion handler. CodeCompletionHandler *getCodeCompletionHandler() const { return CodeComplete; } - + /// \brief Clear out the code completion handler. void clearCodeCompletionHandler() { CodeComplete = 0; } - + /// \brief Hook used by the lexer to invoke the "natural language" code /// completion point. void CodeCompleteNaturalLanguage(); - + /// \brief Retrieve the preprocessing record, or NULL if there is no /// preprocessing record. PreprocessingRecord *getPreprocessingRecord() const { return Record; } - - /// \brief Create a new preprocessing record, which will keep track of + + /// \brief Create a new preprocessing record, which will keep track of /// all macro expansions, macro definitions, etc. - void createPreprocessingRecord(bool IncludeNestedMacroExpansions); - + void createPreprocessingRecord(bool RecordConditionalDirectives); + /// EnterMainSourceFile - Enter the specified FileID as the main source file, /// which implicitly adds the builtin defines etc. void EnterMainSourceFile(); @@ -588,7 +603,7 @@ public: } void LexAfterModuleImport(Token &Result); - + /// LexNonComment - Lex a token. If it's a comment, keep lexing until we get /// something not a comment. This is useful in -E -C mode where comments /// would foul up preprocessor directive handling. @@ -681,6 +696,18 @@ public: CachedTokens[CachedLexPos-1] = Tok; } + /// \brief Recompute the current lexer kind based on the CurLexer/CurPTHLexer/ + /// CurTokenLexer pointers. + void recomputeCurLexerKind(); + + /// \brief Returns true if incremental processing is enabled + bool isIncrementalProcessingEnabled() const { return IncrementalProcessing; } + + /// \brief Enables the incremental processing + void enableIncrementalProcessing(bool value = true) { + IncrementalProcessing = value; + } + /// \brief Specify the point at which code-completion will be performed. /// /// \param File the file in which code completion should occur. If @@ -745,11 +772,11 @@ public: /// /// \brief StartOfLine Whether skipping these bytes puts the lexer at the /// start of a line. - void setSkipMainFilePreamble(unsigned Bytes, bool StartOfLine) { + void setSkipMainFilePreamble(unsigned Bytes, bool StartOfLine) { SkipMainFilePreamble.first = Bytes; SkipMainFilePreamble.second = StartOfLine; } - + /// Diag - Forwarding function for diagnostics. This emits a diagnostic at /// the specified Token's location, translating the token's start /// position in the current buffer into a SourcePosition object for rendering. @@ -771,7 +798,7 @@ public: StringRef getSpelling(SourceLocation loc, SmallVectorImpl<char> &buffer, bool *invalid = 0) const { - return Lexer::getSpelling(loc, buffer, SourceMgr, Features, invalid); + return Lexer::getSpelling(loc, buffer, SourceMgr, LangOpts, invalid); } /// getSpelling() - Return the 'spelling' of the Tok token. The spelling of a @@ -782,7 +809,7 @@ public: /// /// \param Invalid If non-null, will be set \c true if an error occurs. std::string getSpelling(const Token &Tok, bool *Invalid = 0) const { - return Lexer::getSpelling(Tok, SourceMgr, Features, Invalid); + return Lexer::getSpelling(Tok, SourceMgr, LangOpts, Invalid); } /// getSpelling - This method is used to get the spelling of a token into a @@ -795,21 +822,21 @@ public: /// 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 getSpelling(const Token &Tok, const char *&Buffer, + unsigned getSpelling(const Token &Tok, const char *&Buffer, bool *Invalid = 0) const { - return Lexer::getSpelling(Tok, Buffer, SourceMgr, Features, Invalid); + return Lexer::getSpelling(Tok, Buffer, SourceMgr, LangOpts, Invalid); } /// 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 /// supplied buffer if a copy can be avoided. StringRef getSpelling(const Token &Tok, - SmallVectorImpl<char> &Buffer, - bool *Invalid = 0) const; + SmallVectorImpl<char> &Buffer, + bool *Invalid = 0) const; /// getSpellingOfSingleCharacterNumericConstant - Tok is a numeric constant /// with length 1, return the character. - char getSpellingOfSingleCharacterNumericConstant(const Token &Tok, + char getSpellingOfSingleCharacterNumericConstant(const Token &Tok, bool *Invalid = 0) const { assert(Tok.is(tok::numeric_constant) && Tok.getLength() == 1 && "Called on unsupported token"); @@ -824,6 +851,17 @@ public: return *SourceMgr.getCharacterData(Tok.getLocation(), Invalid); } + /// \brief Retrieve the name of the immediate macro expansion. + /// + /// This routine starts from a source location, and finds the name of the macro + /// responsible for its immediate expansion. It looks through any intervening + /// macro argument expansions to compute this. It returns a StringRef which + /// refers to the SourceManager-owned buffer of the source where that macro + /// name is spelled. Thus, the result shouldn't out-live the SourceManager. + StringRef getImmediateMacroName(SourceLocation Loc) { + return Lexer::getImmediateMacroName(Loc, SourceMgr, getLangOpts()); + } + /// CreateString - Plop the specified string into a scratch buffer and set the /// specified token's location and length to it. If specified, the source /// location provides a location of the expansion point of the token. @@ -847,19 +885,28 @@ public: /// 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 getLocForEndOfToken(SourceLocation Loc, unsigned Offset = 0) { - return Lexer::getLocForEndOfToken(Loc, Offset, SourceMgr, Features); + return Lexer::getLocForEndOfToken(Loc, Offset, SourceMgr, LangOpts); } /// \brief Returns true if the given MacroID location points at the first /// token of the macro expansion. - bool isAtStartOfMacroExpansion(SourceLocation loc) const { - return Lexer::isAtStartOfMacroExpansion(loc, SourceMgr, Features); + /// + /// \param MacroBegin If non-null and function returns true, it is set to + /// begin location of the macro. + bool isAtStartOfMacroExpansion(SourceLocation loc, + SourceLocation *MacroBegin = 0) const { + return Lexer::isAtStartOfMacroExpansion(loc, SourceMgr, LangOpts, + MacroBegin); } /// \brief Returns true if the given MacroID location points at the last /// token of the macro expansion. - bool isAtEndOfMacroExpansion(SourceLocation loc) const { - return Lexer::isAtEndOfMacroExpansion(loc, SourceMgr, Features); + /// + /// \param MacroBegin If non-null and function returns true, it is set to + /// end location of the macro. + bool isAtEndOfMacroExpansion(SourceLocation loc, + SourceLocation *MacroEnd = 0) const { + return Lexer::isAtEndOfMacroExpansion(loc, SourceMgr, LangOpts, MacroEnd); } /// DumpToken - Print the token to stderr, used for debugging. @@ -872,7 +919,7 @@ public: /// token, return a new location that specifies a character within the token. SourceLocation AdvanceToTokenCharacter(SourceLocation TokStart, unsigned Char) const { - return Lexer::AdvanceToTokenCharacter(TokStart, Char, SourceMgr, Features); + return Lexer::AdvanceToTokenCharacter(TokStart, Char, SourceMgr, LangOpts); } /// IncrementPasteCounter - Increment the counters for the number of token @@ -930,9 +977,18 @@ public: private: /// Identifiers used for SEH handling in Borland. These are only /// allowed in particular circumstances - IdentifierInfo *Ident__exception_code, *Ident___exception_code, *Ident_GetExceptionCode; // __except block - IdentifierInfo *Ident__exception_info, *Ident___exception_info, *Ident_GetExceptionInfo; // __except filter expression - IdentifierInfo *Ident__abnormal_termination, *Ident___abnormal_termination, *Ident_AbnormalTermination; // __finally + // __except block + IdentifierInfo *Ident__exception_code, + *Ident___exception_code, + *Ident_GetExceptionCode; + // __except filter expression + IdentifierInfo *Ident__exception_info, + *Ident___exception_info, + *Ident_GetExceptionInfo; + // __finally + IdentifierInfo *Ident__abnormal_termination, + *Ident___abnormal_termination, + *Ident_AbnormalTermination; public: void PoisonSEHIdentifiers(bool Poison = true); // Borland @@ -976,6 +1032,9 @@ public: unsigned getCounterValue() const { return CounterValue; } void setCounterValue(unsigned V) { CounterValue = V; } + /// \brief Retrieves the module that we're currently building, if any. + Module *getCurrentModule(); + /// AllocateMacroInfo - Allocate a new MacroInfo object with the provide /// SourceLocation. MacroInfo *AllocateMacroInfo(SourceLocation L); @@ -999,7 +1058,8 @@ public: const DirectoryLookup *&CurDir, SmallVectorImpl<char> *SearchPath, SmallVectorImpl<char> *RelativePath, - StringRef *SuggestedModule); + Module **SuggestedModule, + bool SkipCache = false); /// GetCurLookup - The DirectoryLookup structure used to find the current /// FileEntry, if CurLexer is non-null and if applicable. This allows us to @@ -1020,7 +1080,7 @@ public: /// This code concatenates and consumes tokens up to the '>' token. It /// returns false if the > was found, otherwise it returns true if it finds /// and consumes the EOD marker. - bool ConcatenateIncludeName(llvm::SmallString<128> &FilenameBuffer, + bool ConcatenateIncludeName(SmallString<128> &FilenameBuffer, SourceLocation &End); /// LexOnOffSwitch - Lex an on-off-switch (C99 6.10.6p2) and verify that it is @@ -1063,9 +1123,10 @@ private: /// ReadMacroDefinitionArgList - The ( starting an argument list of a macro /// definition has just been read. Lex the rest of the arguments and the - /// closing ), updating MI with what we learn. Return true if an error occurs - /// parsing the arg list. - bool ReadMacroDefinitionArgList(MacroInfo *MI); + /// closing ), updating MI with what we learn and saving in LastTok the + /// last token read. + /// Return true if an error occurs parsing the arg list. + bool ReadMacroDefinitionArgList(MacroInfo *MI, Token& LastTok); /// SkipExcludedConditionalBlock - We just read a #if or related directive and /// decided that the subsequent tokens are in the #if'd out portion of the @@ -1163,7 +1224,7 @@ private: bool InCachingLexMode() const { // If the Lexer pointers are 0 and IncludeMacroStack is empty, it means // that we are past EOF, not that we are in CachingLex mode. - return CurPPLexer == 0 && CurTokenLexer == 0 && CurPTHLexer == 0 && + return CurPPLexer == 0 && CurTokenLexer == 0 && CurPTHLexer == 0 && !IncludeMacroStack.empty(); } void EnterCachingLexMode(); @@ -1182,8 +1243,9 @@ private: void HandleDigitDirective(Token &Tok); void HandleUserDiagnosticDirective(Token &Tok, bool isWarning); void HandleIdentSCCSDirective(Token &Tok); - void HandleMacroExportDirective(Token &Tok); - + void HandleMacroPublicDirective(Token &Tok); + void HandleMacroPrivateDirective(Token &Tok); + // File inclusion. void HandleIncludeDirective(SourceLocation HashLoc, Token &Tok, @@ -1192,6 +1254,7 @@ private: void HandleIncludeNextDirective(SourceLocation HashLoc, Token &Tok); void HandleIncludeMacrosDirective(SourceLocation HashLoc, Token &Tok); void HandleImportDirective(SourceLocation HashLoc, Token &Tok); + void HandleMicrosoftImportDirective(Token &Tok); // Macro handling. void HandleDefineDirective(Token &Tok); @@ -1217,6 +1280,7 @@ public: void HandlePragmaMessage(Token &MessageTok); void HandlePragmaPushMacro(Token &Tok); void HandlePragmaPopMacro(Token &Tok); + void HandlePragmaIncludeAlias(Token &Tok); IdentifierInfo *ParsePragmaPushOrPopMacro(Token &Tok); // Return true and store the first token only if any CommentHandler diff --git a/include/clang/Lex/PreprocessorLexer.h b/include/clang/Lex/PreprocessorLexer.h index e2e30bf87837..b551cd431018 100644 --- a/include/clang/Lex/PreprocessorLexer.h +++ b/include/clang/Lex/PreprocessorLexer.h @@ -24,6 +24,7 @@ class FileEntry; class Preprocessor; class PreprocessorLexer { + virtual void anchor(); protected: Preprocessor *PP; // Preprocessor object controlling lexing. diff --git a/include/clang/Lex/Token.h b/include/clang/Lex/Token.h index e6dd1607e88b..a88f607298e8 100644 --- a/include/clang/Lex/Token.h +++ b/include/clang/Lex/Token.h @@ -75,7 +75,8 @@ public: LeadingSpace = 0x02, // Whitespace exists before this token. DisableExpand = 0x04, // This identifier may never be macro expanded. NeedsCleaning = 0x08, // Contained an escaped newline or trigraph. - LeadingEmptyMacro = 0x10 // Empty macro exists before this token. + LeadingEmptyMacro = 0x10, // Empty macro exists before this token. + HasUDSuffix = 0x20 // This string or character literal has a ud-suffix. }; tok::TokenKind getKind() const { return (tok::TokenKind)Kind; } @@ -263,6 +264,9 @@ public: return (Flags & LeadingEmptyMacro) ? true : false; } + /// \brief Return true if this token is a string or character literal which + /// has a ud-suffix. + bool hasUDSuffix() const { return (Flags & HasUDSuffix) ? true : false; } }; /// PPConditionalInfo - Information about the conditional stack (#if directives) |