diff options
Diffstat (limited to 'include/clang/Lex')
-rw-r--r-- | include/clang/Lex/HeaderSearch.h | 126 | ||||
-rw-r--r-- | include/clang/Lex/HeaderSearchOptions.h | 89 | ||||
-rw-r--r-- | include/clang/Lex/Lexer.h | 127 | ||||
-rw-r--r-- | include/clang/Lex/LiteralSupport.h | 1 | ||||
-rw-r--r-- | include/clang/Lex/MacroArgs.h | 22 | ||||
-rw-r--r-- | include/clang/Lex/MacroInfo.h | 88 | ||||
-rw-r--r-- | include/clang/Lex/ModuleLoader.h | 31 | ||||
-rw-r--r-- | include/clang/Lex/ModuleMap.h | 75 | ||||
-rw-r--r-- | include/clang/Lex/MultipleIncludeOpt.h | 2 | ||||
-rw-r--r-- | include/clang/Lex/PPCallbacks.h | 40 | ||||
-rw-r--r-- | include/clang/Lex/PTHLexer.h | 25 | ||||
-rw-r--r-- | include/clang/Lex/PTHManager.h | 42 | ||||
-rw-r--r-- | include/clang/Lex/Pragma.h | 29 | ||||
-rw-r--r-- | include/clang/Lex/PreprocessingRecord.h | 70 | ||||
-rw-r--r-- | include/clang/Lex/Preprocessor.h | 294 | ||||
-rw-r--r-- | include/clang/Lex/PreprocessorLexer.h | 47 | ||||
-rw-r--r-- | include/clang/Lex/PreprocessorOptions.h | 55 | ||||
-rw-r--r-- | include/clang/Lex/TokenLexer.h | 111 | ||||
-rw-r--r-- | include/clang/Lex/VariadicMacroSupport.h | 226 |
19 files changed, 1044 insertions, 456 deletions
diff --git a/include/clang/Lex/HeaderSearch.h b/include/clang/Lex/HeaderSearch.h index 1b7f80c87ff1..6b9dbfcd1e93 100644 --- a/include/clang/Lex/HeaderSearch.h +++ b/include/clang/Lex/HeaderSearch.h @@ -1,4 +1,4 @@ -//===--- HeaderSearch.h - Resolve Header File Locations ---------*- C++ -*-===// +//===- HeaderSearch.h - Resolve Header File Locations -----------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -14,25 +14,37 @@ #ifndef LLVM_CLANG_LEX_HEADERSEARCH_H #define LLVM_CLANG_LEX_HEADERSEARCH_H +#include "clang/Basic/SourceLocation.h" +#include "clang/Basic/SourceManager.h" #include "clang/Lex/DirectoryLookup.h" #include "clang/Lex/ModuleMap.h" #include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/IntrusiveRefCntPtr.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringSet.h" +#include "llvm/ADT/StringRef.h" #include "llvm/Support/Allocator.h" +#include <cassert> +#include <cstddef> #include <memory> +#include <string> +#include <utility> #include <vector> namespace clang { - -class DiagnosticsEngine; + +class DiagnosticsEngine; +class DirectoryEntry; class ExternalPreprocessorSource; class FileEntry; class FileManager; +class HeaderMap; class HeaderSearchOptions; class IdentifierInfo; +class LangOptions; +class Module; class Preprocessor; +class TargetInfo; /// \brief The preprocessor keeps track of this information for each /// file that is \#included. @@ -76,14 +88,14 @@ struct HeaderFileInfo { unsigned IsValid : 1; /// \brief The number of times the file has been included already. - unsigned short NumIncludes; + unsigned short NumIncludes = 0; /// \brief The ID number of the controlling macro. /// /// This ID number will be non-zero when there is a controlling /// macro whose IdentifierInfo may not yet have been loaded from /// external storage. - unsigned ControllingMacroID; + unsigned ControllingMacroID = 0; /// If this file has a \#ifndef XXX (or equivalent) guard that /// protects the entire contents of the file, this is the identifier @@ -93,17 +105,16 @@ struct HeaderFileInfo { /// the controlling macro of this header, since /// getControllingMacro() is able to load a controlling macro from /// external storage. - const IdentifierInfo *ControllingMacro; + const IdentifierInfo *ControllingMacro = nullptr; /// \brief If this header came from a framework include, this is the name /// of the framework. StringRef Framework; HeaderFileInfo() - : isImport(false), isPragmaOnce(false), DirInfo(SrcMgr::C_User), - External(false), isModuleHeader(false), isCompilingModuleHeader(false), - Resolved(false), IndexHeaderMapHeader(false), IsValid(0), - NumIncludes(0), ControllingMacroID(0), ControllingMacro(nullptr) {} + : isImport(false), isPragmaOnce(false), DirInfo(SrcMgr::C_User), + External(false), isModuleHeader(false), isCompilingModuleHeader(false), + Resolved(false), IndexHeaderMapHeader(false), IsValid(false) {} /// \brief Retrieve the controlling macro for this header file, if /// any. @@ -135,6 +146,8 @@ public: /// \brief Encapsulates the information needed to find the file referenced /// by a \#include or \#include_next, (sub-)framework lookup, etc. class HeaderSearch { + friend class DirectoryLookup; + /// This structure is used to record entries in our framework cache. struct FrameworkCacheEntry { /// The directory entry which should be used for the cached framework. @@ -151,6 +164,7 @@ class HeaderSearch { DiagnosticsEngine &Diags; FileManager &FileMgr; + /// \#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 @@ -158,9 +172,9 @@ class HeaderSearch { /// NoCurDirSearch is true, then the check for the file in the current /// directory is suppressed. std::vector<DirectoryLookup> SearchDirs; - unsigned AngledDirIdx; - unsigned SystemDirIdx; - bool NoCurDirSearch; + unsigned AngledDirIdx = 0; + unsigned SystemDirIdx = 0; + bool NoCurDirSearch = false; /// \brief \#include prefixes for which the 'system header' property is /// overridden. @@ -168,7 +182,7 @@ class HeaderSearch { /// For a \#include "x" or \#include \<x> directive, the last string in this /// list which is a prefix of 'x' determines whether the file is treated as /// a system header. - std::vector<std::pair<std::string, bool> > SystemHeaderPrefixes; + std::vector<std::pair<std::string, bool>> SystemHeaderPrefixes; /// \brief The path to the module cache. std::string ModuleCachePath; @@ -182,15 +196,17 @@ class HeaderSearch { /// Starting index in SearchDirs that the cached search was performed from. /// If there is a hit and this value doesn't match the current query, the /// cache has to be ignored. - unsigned StartIdx; + unsigned StartIdx = 0; + /// The entry in SearchDirs that satisfied the query. - unsigned HitIdx; + unsigned HitIdx = 0; + /// This is non-null if the original filename was mapped to a framework /// include via a headermap. - const char *MappedName; + const char *MappedName = nullptr; /// Default constructor -- Initialize all members with zero. - LookupFileCacheInfo(): StartIdx(0), HitIdx(0), MappedName(nullptr) {} + LookupFileCacheInfo() = default; void reset(unsigned StartIdx) { this->StartIdx = StartIdx; @@ -206,13 +222,13 @@ class HeaderSearch { /// 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; + using IncludeAliasMap = + llvm::StringMap<std::string, llvm::BumpPtrAllocator>; std::unique_ptr<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; + std::vector<std::pair<const FileEntry *, const HeaderMap *>> HeaderMaps; /// \brief The mapping between modules and headers. mutable ModuleMap ModMap; @@ -231,26 +247,23 @@ class HeaderSearch { /// \brief Entity used to resolve the identifier IDs of controlling /// macros into IdentifierInfo pointers, and keep the identifire up to date, /// as needed. - ExternalPreprocessorSource *ExternalLookup; + ExternalPreprocessorSource *ExternalLookup = nullptr; /// \brief Entity used to look up stored header file information. - ExternalHeaderFileInfoSource *ExternalSource; + ExternalHeaderFileInfoSource *ExternalSource = nullptr; // Various statistics we track for performance analysis. - unsigned NumIncluded; - unsigned NumMultiIncludeFileOptzn; - unsigned NumFrameworkLookups, NumSubFrameworkLookups; + unsigned NumIncluded = 0; + unsigned NumMultiIncludeFileOptzn = 0; + unsigned NumFrameworkLookups = 0; + unsigned NumSubFrameworkLookups = 0; - // HeaderSearch doesn't support default or copy construction. - HeaderSearch(const HeaderSearch&) = delete; - void operator=(const HeaderSearch&) = delete; - - friend class DirectoryLookup; - public: HeaderSearch(std::shared_ptr<HeaderSearchOptions> HSOpts, SourceManager &SourceMgr, DiagnosticsEngine &Diags, const LangOptions &LangOpts, const TargetInfo *Target); + HeaderSearch(const HeaderSearch &) = delete; + HeaderSearch &operator=(const HeaderSearch &) = delete; ~HeaderSearch(); /// \brief Retrieve the header-search options with which this header search @@ -282,7 +295,7 @@ public: } /// \brief Set the list of system header prefixes. - void SetSystemHeaderPrefixes(ArrayRef<std::pair<std::string, bool> > P) { + void SetSystemHeaderPrefixes(ArrayRef<std::pair<std::string, bool>> P) { SystemHeaderPrefixes.assign(P.begin(), P.end()); } @@ -310,7 +323,7 @@ public: IncludeAliasMap::const_iterator Iter = IncludeAliases->find(Source); if (Iter != IncludeAliases->end()) return Iter->second; - return StringRef(); + return {}; } /// \brief Set the path to the module cache. @@ -471,29 +484,40 @@ public: /// \brief Get filenames for all registered header maps. void getHeaderMapFileNames(SmallVectorImpl<std::string> &Names) const; - /// \brief Retrieve the name of the module file that should be used to - /// load the given module. + /// \brief Retrieve the name of the cached module file that should be used + /// to load the given module. /// /// \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(Module *Module); + std::string getCachedModuleFileName(Module *Module); + + /// \brief Retrieve the name of the prebuilt module file that should be used + /// to load a module with the given name. + /// + /// \param ModuleName The module whose module file name will be returned. + /// + /// \param FileMapOnly If true, then only look in the explicit module name + // to file name map and skip the directory search. + /// + /// \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 getPrebuiltModuleFileName(StringRef ModuleName, + bool FileMapOnly = false); - /// \brief Retrieve the name of the module file that should be used to - /// load a module with the given name. + /// \brief Retrieve the name of the (to-be-)cached module file that should + /// be used to load a module with the given name. /// /// \param ModuleName The module whose module file name will be returned. /// /// \param ModuleMapPath A path that when combined with \c ModuleName /// uniquely identifies this module. See Module::ModuleMap. /// - /// \param UsePrebuiltPath Whether we should use the prebuilt module path. - /// /// \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, StringRef ModuleMapPath, - bool UsePrebuiltPath); + std::string getCachedModuleFileName(StringRef ModuleName, + StringRef ModuleMapPath); /// \brief Lookup a module Search for a module with the given name. /// @@ -560,7 +584,6 @@ public: void loadTopLevelSystemModules(); private: - /// \brief Lookup a module with the given module name and search-name. /// /// \param ModuleName The name of the module we're looking for. @@ -640,7 +663,8 @@ public: bool WantExternal = true) const; // Used by external tools - typedef std::vector<DirectoryLookup>::const_iterator search_dir_iterator; + using search_dir_iterator = std::vector<DirectoryLookup>::const_iterator; + search_dir_iterator search_dir_begin() const { return SearchDirs.begin(); } search_dir_iterator search_dir_end() const { return SearchDirs.end(); } unsigned search_dir_size() const { return SearchDirs.size(); } @@ -648,6 +672,7 @@ public: search_dir_iterator quoted_dir_begin() const { return SearchDirs.begin(); } + search_dir_iterator quoted_dir_end() const { return SearchDirs.begin() + AngledDirIdx; } @@ -655,6 +680,7 @@ public: search_dir_iterator angled_dir_begin() const { return SearchDirs.begin() + AngledDirIdx; } + search_dir_iterator angled_dir_end() const { return SearchDirs.begin() + SystemDirIdx; } @@ -662,6 +688,7 @@ public: search_dir_iterator system_dir_begin() const { return SearchDirs.begin() + SystemDirIdx; } + search_dir_iterator system_dir_end() const { return SearchDirs.end(); } /// \brief Retrieve a uniqued framework name. @@ -684,10 +711,13 @@ private: 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 @@ -723,6 +753,6 @@ private: bool IsSystem, bool IsFramework); }; -} // end namespace clang +} // namespace clang -#endif +#endif // LLVM_CLANG_LEX_HEADERSEARCH_H diff --git a/include/clang/Lex/HeaderSearchOptions.h b/include/clang/Lex/HeaderSearchOptions.h index ca3a84e75e18..937ad9863db3 100644 --- a/include/clang/Lex/HeaderSearchOptions.h +++ b/include/clang/Lex/HeaderSearchOptions.h @@ -1,4 +1,4 @@ -//===--- HeaderSearchOptions.h ----------------------------------*- C++ -*-===// +//===- HeaderSearchOptions.h ------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -12,35 +12,55 @@ #include "clang/Basic/LLVM.h" #include "llvm/ADT/CachedHashString.h" -#include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/SetVector.h" #include "llvm/ADT/StringRef.h" +#include <cstdint> #include <string> #include <vector> +#include <map> namespace clang { namespace frontend { - /// IncludeDirGroup - Identifies the group an include Entry belongs to, - /// representing its relative positive in the search list. - /// \#include directives whose paths are enclosed by string quotes ("") - /// start searching at the Quoted group (specified by '-iquote'), - /// then search the Angled group, then the System group, etc. - enum IncludeDirGroup { - Quoted = 0, ///< '\#include ""' paths, added by 'gcc -iquote'. - Angled, ///< Paths for '\#include <>' added by '-I'. - IndexHeaderMap, ///< Like Angled, but marks header maps used when - /// building frameworks. - System, ///< Like Angled, but marks system directories. - ExternCSystem, ///< Like System, but headers are implicitly wrapped in - /// extern "C". - CSystem, ///< Like System, but only used for C. - CXXSystem, ///< Like System, but only used for C++. - ObjCSystem, ///< Like System, but only used for ObjC. - ObjCXXSystem, ///< Like System, but only used for ObjC++. - After ///< Like System, but searched after the system directories. - }; -} + +/// IncludeDirGroup - Identifies the group an include Entry belongs to, +/// representing its relative positive in the search list. +/// \#include directives whose paths are enclosed by string quotes ("") +/// start searching at the Quoted group (specified by '-iquote'), +/// then search the Angled group, then the System group, etc. +enum IncludeDirGroup { + /// '\#include ""' paths, added by 'gcc -iquote'. + Quoted = 0, + + /// Paths for '\#include <>' added by '-I'. + Angled, + + /// Like Angled, but marks header maps used when building frameworks. + IndexHeaderMap, + + /// Like Angled, but marks system directories. + System, + + /// Like System, but headers are implicitly wrapped in extern "C". + ExternCSystem, + + /// Like System, but only used for C. + CSystem, + + /// Like System, but only used for C++. + CXXSystem, + + /// Like System, but only used for ObjC. + ObjCSystem, + + /// Like System, but only used for ObjC++. + ObjCXXSystem, + + /// Like System, but searched after the system directories. + After +}; + +} // namespace frontend /// HeaderSearchOptions - Helper class for storing options related to the /// initialization of the HeaderSearch object. @@ -58,8 +78,8 @@ public: Entry(StringRef path, frontend::IncludeDirGroup group, bool isFramework, bool ignoreSysRoot) - : Path(path), Group(group), IsFramework(isFramework), - IgnoreSysRoot(ignoreSysRoot) {} + : Path(path), Group(group), IsFramework(isFramework), + IgnoreSysRoot(ignoreSysRoot) {} }; struct SystemHeaderPrefix { @@ -71,7 +91,7 @@ public: bool IsSystemHeader; SystemHeaderPrefix(StringRef Prefix, bool IsSystemHeader) - : Prefix(Prefix), IsSystemHeader(IsSystemHeader) {} + : Prefix(Prefix), IsSystemHeader(IsSystemHeader) {} }; /// If non-empty, the directory to use as a "virtual system root" for include @@ -94,6 +114,9 @@ public: /// \brief The directory used for a user build. std::string ModuleUserBuildPath; + /// \brief The mapping of module names to prebuilt module files. + std::map<std::string, std::string> PrebuiltModuleFiles; + /// \brief The directories used to load prebuilt module files. std::vector<std::string> PrebuiltModulePaths; @@ -126,7 +149,7 @@ public: /// files. /// /// The default value is large, e.g., the operation runs once a week. - unsigned ModuleCachePruneInterval; + unsigned ModuleCachePruneInterval = 7 * 24 * 60 * 60; /// \brief The time (in seconds) after which an unused module file will be /// considered unused and will, therefore, be pruned. @@ -135,13 +158,13 @@ public: /// accessed in this many seconds will be removed. The default value is /// large, e.g., a month, to avoid forcing infrequently-used modules to be /// regenerated often. - unsigned ModuleCachePruneAfter; + unsigned ModuleCachePruneAfter = 31 * 24 * 60 * 60; /// \brief The time in seconds when the build session started. /// /// This time is used by other optimizations in header search and module /// loading. - uint64_t BuildSessionTimestamp; + uint64_t BuildSessionTimestamp = 0; /// \brief The set of macro names that should be ignored for the purposes /// of computing the module hash. @@ -181,10 +204,8 @@ public: unsigned ModulesHashContent : 1; HeaderSearchOptions(StringRef _Sysroot = "/") - : Sysroot(_Sysroot), ModuleFormat("raw"), DisableModuleHash(0), - ImplicitModuleMaps(0), ModuleMapFileHomeIsCwd(0), - ModuleCachePruneInterval(7 * 24 * 60 * 60), - ModuleCachePruneAfter(31 * 24 * 60 * 60), BuildSessionTimestamp(0), + : Sysroot(_Sysroot), ModuleFormat("raw"), DisableModuleHash(false), + ImplicitModuleMaps(false), ModuleMapFileHomeIsCwd(false), UseBuiltinIncludes(true), UseStandardSystemIncludes(true), UseStandardCXXIncludes(true), UseLibcxx(false), Verbose(false), ModulesValidateOncePerBuildSession(false), @@ -213,6 +234,6 @@ public: } }; -} // end namespace clang +} // namespace clang -#endif +#endif // LLVM_CLANG_LEX_HEADERSEARCHOPTIONS_H diff --git a/include/clang/Lex/Lexer.h b/include/clang/Lex/Lexer.h index 3be733167e5c..d58849654cb8 100644 --- a/include/clang/Lex/Lexer.h +++ b/include/clang/Lex/Lexer.h @@ -1,4 +1,4 @@ -//===--- Lexer.h - C Language Family Lexer ----------------------*- C++ -*-===// +//===- Lexer.h - C Language Family Lexer ------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -15,45 +15,88 @@ #define LLVM_CLANG_LEX_LEXER_H #include "clang/Basic/LangOptions.h" +#include "clang/Basic/SourceLocation.h" +#include "clang/Basic/TokenKinds.h" #include "clang/Lex/PreprocessorLexer.h" +#include "clang/Lex/Token.h" +#include "llvm/ADT/Optional.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" #include <cassert> +#include <cstdint> #include <string> +namespace llvm { + +class MemoryBuffer; + +} // namespace llvm + namespace clang { -class DiagnosticsEngine; -class SourceManager; -class Preprocessor; + class DiagnosticBuilder; +class Preprocessor; +class SourceManager; /// ConflictMarkerKind - Kinds of conflict marker which the lexer might be /// recovering from. enum ConflictMarkerKind { /// Not within a conflict marker. CMK_None, + /// A normal or diff3 conflict marker, initiated by at least 7 "<"s, /// separated by at least 7 "="s or "|"s, and terminated by at least 7 ">"s. CMK_Normal, + /// A Perforce-style conflict marker, initiated by 4 ">"s, /// separated by 4 "="s, and terminated by 4 "<"s. CMK_Perforce }; +/// Describes the bounds (start, size) of the preamble and a flag required by +/// PreprocessorOptions::PrecompiledPreambleBytes. +/// The preamble includes the BOM, if any. +struct PreambleBounds { + /// \brief Size of the preamble in bytes. + unsigned Size; + + /// \brief Whether the preamble ends at the start of a new line. + /// + /// Used to inform the lexer as to whether it's starting at the beginning of + /// a line after skipping the preamble. + bool PreambleEndsAtStartOfLine; + + PreambleBounds(unsigned Size, bool PreambleEndsAtStartOfLine) + : Size(Size), PreambleEndsAtStartOfLine(PreambleEndsAtStartOfLine) {} +}; + /// Lexer - This provides a simple interface that turns a text buffer into a /// stream of tokens. This provides no support for file reading or buffering, /// 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 { + friend class Preprocessor; + void anchor() override; //===--------------------------------------------------------------------===// // 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 LangOpts; // LangOpts enabled by this language (cache). - bool Is_PragmaLexer; // True if lexer for _Pragma handling. - + + // Start of the buffer. + const char *BufferStart; + + // End of the buffer. + const char *BufferEnd; + + // Location for start of file. + SourceLocation FileLoc; + + // LangOpts enabled by this language (cache). + LangOptions LangOpts; + + // True if lexer for _Pragma handling. + bool Is_PragmaLexer; + //===--------------------------------------------------------------------===// // Context-specific lexing flags set by the preprocessor. // @@ -89,13 +132,9 @@ class Lexer : public PreprocessorLexer { // CurrentConflictMarkerState - The kind of conflict marker we are handling. ConflictMarkerKind CurrentConflictMarkerState; - Lexer(const Lexer &) = delete; - void operator=(const Lexer &) = delete; - friend class Preprocessor; - void InitLexer(const char *BufStart, const char *BufPtr, const char *BufEnd); -public: +public: /// Lexer constructor - Create a new lexer object for the specified buffer /// with the specified preprocessor managing the lexing process. This lexer /// assumes that the associated file buffer and Preprocessor objects will @@ -114,6 +153,9 @@ public: Lexer(FileID FID, const llvm::MemoryBuffer *InputBuffer, const SourceManager &SM, const LangOptions &LangOpts); + Lexer(const Lexer &) = delete; + Lexer &operator=(const Lexer &) = delete; + /// Create_PragmaLexer: Lexer constructor - Create a new lexer object for /// _Pragma expansion. This has a variety of magic semantics that this method /// sets up. It returns a new'd Lexer that must be delete'd when done. @@ -122,7 +164,6 @@ public: SourceLocation ExpansionLocEnd, unsigned TokLen, Preprocessor &PP); - /// getLangOpts - Return the language features currently enabled. /// NOTE: this lexer modifies features as a file is parsed! const LangOptions &getLangOpts() const { return LangOpts; } @@ -224,17 +265,16 @@ public: /// \brief Return the current location in the buffer. const char *getBufferLocation() const { return BufferPtr; } - - /// Stringify - Convert the specified string into a C string by escaping '\' - /// and " characters. This does not add surrounding ""'s to the string. + + /// Stringify - Convert the specified string into a C string by i) escaping + /// '\\' and " characters and ii) replacing newline character(s) with "\\n". /// If Charify is true, this escapes the ' character instead of ". static std::string Stringify(StringRef Str, bool Charify = false); - /// Stringify - Convert the specified string into a C string by escaping '\' - /// and " characters. This does not add surrounding ""'s to the string. + /// Stringify - Convert the specified string into a C string by i) escaping + /// '\\' and " characters and ii) replacing newline character(s) with "\\n". static void Stringify(SmallVectorImpl<char> &Str); - /// getSpelling - This method is used to get the spelling of a token into a /// preallocated buffer, instead of as an std::string. The caller is required /// to allocate enough space for the token, which is guaranteed to be at least @@ -245,11 +285,11 @@ 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. - static unsigned getSpelling(const Token &Tok, const char *&Buffer, + static unsigned getSpelling(const Token &Tok, const char *&Buffer, const SourceManager &SourceMgr, const LangOptions &LangOpts, bool *Invalid = nullptr); - + /// getSpelling() - Return the 'spelling' of the Tok token. The spelling of a /// token is the characters used to represent the token in the source file /// after trigraph expansion and escaped-newline folding. In particular, this @@ -257,7 +297,7 @@ public: /// UCNs, etc. static std::string getSpelling(const Token &Tok, const SourceManager &SourceMgr, - const LangOptions &LangOpts, + const LangOptions &LangOpts, bool *Invalid = nullptr); /// getSpelling - This method is used to get the spelling of the @@ -273,7 +313,7 @@ public: const SourceManager &SourceMgr, const LangOptions &LangOpts, bool *invalid = nullptr); - + /// MeasureTokenLength - Relex the token at the specified location and return /// its length in bytes in the input file. If the token needs cleaning (e.g. /// includes a trigraph or an escaped newline) then this count includes bytes @@ -295,7 +335,7 @@ public: static SourceLocation GetBeginningOfToken(SourceLocation Loc, const SourceManager &SM, const LangOptions &LangOpts); - + /// AdvanceToTokenCharacter - If the current SourceLocation specifies a /// location at the start of a token, return a new location that specifies a /// character within the token. This handles trigraphs and escaped newlines. @@ -303,7 +343,7 @@ public: unsigned Character, const SourceManager &SM, const LangOptions &LangOpts); - + /// \brief Computes the source location just past the end of the /// token at this source location. /// @@ -443,11 +483,18 @@ public: /// to fewer than this number of lines. /// /// \returns The offset into the file where the preamble ends and the rest - /// of the file begins along with a boolean value indicating whether + /// 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(StringRef Buffer, - const LangOptions &LangOpts, - unsigned MaxLines = 0); + static PreambleBounds ComputePreamble(StringRef Buffer, + const LangOptions &LangOpts, + unsigned MaxLines = 0); + + /// Finds the token that comes right after the given location. + /// + /// Returns the next token, or none if the location is inside a macro. + static Optional<Token> findNextToken(SourceLocation Loc, + const SourceManager &SM, + const LangOptions &LangOpts); /// \brief Checks that the given token is the first token that occurs after /// the given location (this excludes comments and whitespace). Returns the @@ -463,6 +510,10 @@ public: /// \brief Returns true if the given character could appear in an identifier. static bool isIdentifierBodyChar(char c, const LangOptions &LangOpts); + /// \brief Checks whether new line pointed by Str is preceded by escape + /// sequence. + static bool isNewLineEscaped(const char *BufferStart, const char *Str); + /// getCharAndSizeNoWarn - Like the getCharAndSize method, but does not ever /// emit a warning. static inline char getCharAndSizeNoWarn(const char *Ptr, unsigned &Size, @@ -483,9 +534,9 @@ public: static StringRef getIndentationForLine(SourceLocation Loc, const SourceManager &SM); +private: //===--------------------------------------------------------------------===// // Internal implementation interfaces. -private: /// LexTokenInternal - Internal interface to lex a preprocessing token. Called /// by Lex. @@ -614,7 +665,7 @@ private: //===--------------------------------------------------------------------===// // Other lexer functions. - void SkipBytes(unsigned Bytes, bool StartOfLine); + void SetByteOffset(unsigned Offset, bool StartOfLine); void PropagateLineStartLeadingSpaceInfo(Token &Result); @@ -639,7 +690,7 @@ private: bool SkipBlockComment (Token &Result, const char *CurPtr, bool &TokAtPhysicalStartOfLine); bool SaveLineComment (Token &Result, const char *CurPtr); - + bool IsStartOfConflictMarker(const char *CurPtr); bool HandleEndOfConflictMarker(const char *CurPtr); @@ -658,7 +709,7 @@ private: /// valid), this parameter will be updated to point to the /// character after the UCN. /// \param SlashLoc The position in the source buffer of the '\'. - /// \param Tok The token being formed. Pass \c NULL to suppress diagnostics + /// \param Tok The token being formed. Pass \c nullptr to suppress diagnostics /// and handle token formation in the caller. /// /// \return The Unicode codepoint specified by the UCN, or 0 if the UCN is @@ -687,6 +738,6 @@ private: bool tryConsumeIdentifierUTF8Char(const char *&CurPtr); }; -} // end namespace clang +} // namespace clang -#endif +#endif // LLVM_CLANG_LEX_LEXER_H diff --git a/include/clang/Lex/LiteralSupport.h b/include/clang/Lex/LiteralSupport.h index b66581b428b1..cc9223eb7dbb 100644 --- a/include/clang/Lex/LiteralSupport.h +++ b/include/clang/Lex/LiteralSupport.h @@ -65,6 +65,7 @@ public: bool isHalf : 1; // 1.0h bool isFloat : 1; // 1.0f bool isImaginary : 1; // 1.0i + bool isFloat16 : 1; // 1.0f16 bool isFloat128 : 1; // 1.0q uint8_t MicrosoftInteger; // Microsoft suffix extension i8, i16, i32, or i64. diff --git a/include/clang/Lex/MacroArgs.h b/include/clang/Lex/MacroArgs.h index cfe46ceb0979..a202550da3b3 100644 --- a/include/clang/Lex/MacroArgs.h +++ b/include/clang/Lex/MacroArgs.h @@ -17,6 +17,7 @@ #include "clang/Basic/LLVM.h" #include "clang/Lex/Token.h" #include "llvm/ADT/ArrayRef.h" +#include "llvm/Support/TrailingObjects.h" #include <vector> namespace clang { @@ -26,7 +27,10 @@ namespace clang { /// MacroArgs - An instance of this class captures information about /// the formal arguments specified to a function-like macro invocation. -class MacroArgs { +class MacroArgs final + : private llvm::TrailingObjects<MacroArgs, Token> { + + friend TrailingObjects; /// NumUnexpArgTokens - The number of raw, unexpanded tokens for the /// arguments. All of the actual argument tokens are allocated immediately /// after the MacroArgs object in memory. This is all of the arguments @@ -89,7 +93,7 @@ public: /// getPreExpArgument - Return the pre-expanded form of the specified /// argument. const std::vector<Token> & - getPreExpArgument(unsigned Arg, const MacroInfo *MI, Preprocessor &PP); + getPreExpArgument(unsigned Arg, Preprocessor &PP); /// getStringifiedArgument - Compute, cache, and return the specified argument /// that has been 'stringified' as required by the # operator. @@ -108,6 +112,20 @@ public: /// argument, this returns false. bool isVarargsElidedUse() const { return VarargsElided; } + /// Returns true if the macro was defined with a variadic (ellipsis) parameter + /// AND was invoked with at least one token supplied as a variadic argument. + /// + /// \code + /// #define F(a) a + /// #define V(a, ...) __VA_OPT__(a) + /// F() <-- returns false on this invocation. + /// V(,a) <-- returns true on this invocation. + /// V(,) <-- returns false on this invocation. + /// \endcode + /// + + bool invokedWithVariadicArgument(const MacroInfo *const MI) const; + /// StringifyArgument - Implement C99 6.10.3.2p2, converting a sequence of /// tokens into the literal string token that should be produced by the C # /// preprocessor operator. If Charify is true, then it should be turned into diff --git a/include/clang/Lex/MacroInfo.h b/include/clang/Lex/MacroInfo.h index d25431b55fdc..3029294209ec 100644 --- a/include/clang/Lex/MacroInfo.h +++ b/include/clang/Lex/MacroInfo.h @@ -1,4 +1,4 @@ -//===--- MacroInfo.h - Information about #defined identifiers ---*- C++ -*-===// +//===- MacroInfo.h - Information about #defined identifiers -----*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -6,27 +6,33 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -/// +// /// \file /// \brief Defines the clang::MacroInfo and clang::MacroDirective classes. -/// +// //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_LEX_MACROINFO_H #define LLVM_CLANG_LEX_MACROINFO_H #include "clang/Lex/Token.h" +#include "clang/Basic/LLVM.h" +#include "clang/Basic/SourceLocation.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Support/Allocator.h" +#include <algorithm> #include <cassert> namespace clang { + +class DefMacroDirective; +class IdentifierInfo; class Module; -class ModuleMacro; class Preprocessor; +class SourceManager; /// \brief Encapsulates the data about a macro definition (e.g. its tokens). /// @@ -37,6 +43,7 @@ class MacroInfo { /// \brief The location the macro is defined. SourceLocation Location; + /// \brief The location of the last token in the macro. SourceLocation EndLocation; @@ -46,10 +53,10 @@ class MacroInfo { /// /// This can be empty, for, e.g. "#define X()". In a C99-style variadic /// macro, this includes the \c __VA_ARGS__ identifier on the list. - IdentifierInfo **ParameterList; + IdentifierInfo **ParameterList = nullptr; /// \see ParameterList - unsigned NumParameters; + unsigned NumParameters = 0; /// \brief This is the list of tokens that the macro is defined to. SmallVector<Token, 8> ReplacementTokens; @@ -169,7 +176,7 @@ public: /// Parameters - The list of parameters for a function-like macro. This can /// be empty, for, e.g. "#define X()". - typedef IdentifierInfo *const *param_iterator; + using param_iterator = IdentifierInfo *const *; bool param_empty() const { return NumParameters == 0; } param_iterator param_begin() const { return ParameterList; } param_iterator param_end() const { return ParameterList + NumParameters; } @@ -224,7 +231,6 @@ public: bool isWarnIfUnused() const { return IsWarnIfUnused; } /// \brief Return the number of tokens that this macro expands to. - /// unsigned getNumTokens() const { return ReplacementTokens.size(); } const Token &getReplacementToken(unsigned Tok) const { @@ -232,7 +238,8 @@ public: return ReplacementTokens[Tok]; } - typedef SmallVectorImpl<Token>::const_iterator tokens_iterator; + using tokens_iterator = SmallVectorImpl<Token>::const_iterator; + tokens_iterator tokens_begin() const { return ReplacementTokens.begin(); } tokens_iterator tokens_end() const { return ReplacementTokens.end(); } bool tokens_empty() const { return ReplacementTokens.empty(); } @@ -269,12 +276,10 @@ public: void dump() const; private: - unsigned getDefinitionLengthSlow(const SourceManager &SM) const; - friend class Preprocessor; -}; -class DefMacroDirective; + unsigned getDefinitionLengthSlow(const SourceManager &SM) const; +}; /// \brief Encapsulates changes to the "macros namespace" (the location where /// the macro name became active, the location where it was undefined, etc.). @@ -285,11 +290,15 @@ class DefMacroDirective; /// create additional DefMacroDirectives for the same MacroInfo. class MacroDirective { public: - enum Kind { MD_Define, MD_Undefine, MD_Visibility }; + enum Kind { + MD_Define, + MD_Undefine, + MD_Visibility + }; protected: - /// \brief Previous macro directive for the same identifier, or NULL. - MacroDirective *Previous; + /// \brief Previous macro directive for the same identifier, or nullptr. + MacroDirective *Previous = nullptr; SourceLocation Loc; @@ -306,8 +315,7 @@ protected: unsigned IsPublic : 1; MacroDirective(Kind K, SourceLocation Loc) - : Previous(nullptr), Loc(Loc), MDKind(K), IsFromPCH(false), - IsPublic(true) {} + : Loc(Loc), MDKind(K), IsFromPCH(false), IsPublic(true) {} public: Kind getKind() const { return Kind(MDKind); } @@ -329,13 +337,12 @@ public: void setIsFromPCH() { IsFromPCH = true; } class DefInfo { - DefMacroDirective *DefDirective; + DefMacroDirective *DefDirective = nullptr; SourceLocation UndefLoc; - bool IsPublic; + bool IsPublic = true; public: - DefInfo() : DefDirective(nullptr), IsPublic(true) {} - + DefInfo() = default; DefInfo(DefMacroDirective *DefDirective, SourceLocation UndefLoc, bool isPublic) : DefDirective(DefDirective), UndefLoc(UndefLoc), IsPublic(isPublic) {} @@ -345,6 +352,7 @@ public: inline SourceLocation getLocation() const; inline MacroInfo *getMacroInfo(); + const MacroInfo *getMacroInfo() const { return const_cast<DefInfo *>(this)->getMacroInfo(); } @@ -360,6 +368,7 @@ public: explicit operator bool() const { return isValid(); } inline DefInfo getPreviousDefinition(); + const DefInfo getPreviousDefinition() const { return const_cast<DefInfo *>(this)->getPreviousDefinition(); } @@ -412,6 +421,7 @@ public: static bool classof(const MacroDirective *MD) { return MD->getKind() == MD_Define; } + static bool classof(const DefMacroDirective *) { return true; } }; @@ -426,6 +436,7 @@ public: static bool classof(const MacroDirective *MD) { return MD->getKind() == MD_Undefine; } + static bool classof(const UndefMacroDirective *) { return true; } }; @@ -444,12 +455,13 @@ public: static bool classof(const MacroDirective *MD) { return MD->getKind() == MD_Visibility; } + static bool classof(const VisibilityMacroDirective *) { return true; } }; inline SourceLocation MacroDirective::DefInfo::getLocation() const { if (isInvalid()) - return SourceLocation(); + return {}; return DefDirective->getLocation(); } @@ -462,7 +474,7 @@ inline MacroInfo *MacroDirective::DefInfo::getMacroInfo() { inline MacroDirective::DefInfo MacroDirective::DefInfo::getPreviousDefinition() { if (isInvalid() || DefDirective->getPrevious() == nullptr) - return DefInfo(); + return {}; return DefDirective->getPrevious()->getDefinition(); } @@ -474,23 +486,26 @@ MacroDirective::DefInfo::getPreviousDefinition() { /// /// These are stored in a FoldingSet in the preprocessor. class ModuleMacro : public llvm::FoldingSetNode { + friend class Preprocessor; + /// The name defined by the macro. IdentifierInfo *II; + /// The body of the #define, or nullptr if this is a #undef. MacroInfo *Macro; + /// The module that exports this macro. Module *OwningModule; + /// The number of module macros that override this one. - unsigned NumOverriddenBy; + unsigned NumOverriddenBy = 0; + /// The number of modules whose macros are directly overridden by this one. unsigned NumOverrides; - // ModuleMacro *OverriddenMacros[NumOverrides]; - - friend class Preprocessor; ModuleMacro(Module *OwningModule, IdentifierInfo *II, MacroInfo *Macro, ArrayRef<ModuleMacro *> Overrides) - : II(II), Macro(Macro), OwningModule(OwningModule), NumOverriddenBy(0), + : II(II), Macro(Macro), OwningModule(OwningModule), NumOverrides(Overrides.size()) { std::copy(Overrides.begin(), Overrides.end(), reinterpret_cast<ModuleMacro **>(this + 1)); @@ -504,12 +519,16 @@ public: void Profile(llvm::FoldingSetNodeID &ID) const { return Profile(ID, OwningModule, II); } + static void Profile(llvm::FoldingSetNodeID &ID, Module *OwningModule, IdentifierInfo *II) { ID.AddPointer(OwningModule); ID.AddPointer(II); } + /// Get the name of the macro. + IdentifierInfo *getName() const { return II; } + /// Get the ID of the module that exports this macro. Module *getOwningModule() const { return OwningModule; } @@ -519,13 +538,16 @@ public: /// Iterators over the overridden module IDs. /// \{ - typedef ModuleMacro *const *overrides_iterator; + using overrides_iterator = ModuleMacro *const *; + overrides_iterator overrides_begin() const { return reinterpret_cast<overrides_iterator>(this + 1); } + overrides_iterator overrides_end() const { return overrides_begin() + NumOverrides; } + ArrayRef<ModuleMacro *> overrides() const { return llvm::makeArrayRef(overrides_begin(), overrides_end()); } @@ -544,7 +566,7 @@ class MacroDefinition { ArrayRef<ModuleMacro *> ModuleMacros; public: - MacroDefinition() : LatestLocalAndAmbiguous(), ModuleMacros() {} + MacroDefinition() = default; MacroDefinition(DefMacroDirective *MD, ArrayRef<ModuleMacro *> MMs, bool IsAmbiguous) : LatestLocalAndAmbiguous(MD, IsAmbiguous), ModuleMacros(MMs) {} @@ -583,6 +605,6 @@ public: } }; -} // end namespace clang +} // namespace clang -#endif +#endif // LLVM_CLANG_LEX_MACROINFO_H diff --git a/include/clang/Lex/ModuleLoader.h b/include/clang/Lex/ModuleLoader.h index ee0638b57f87..30ea583b71e0 100644 --- a/include/clang/Lex/ModuleLoader.h +++ b/include/clang/Lex/ModuleLoader.h @@ -1,4 +1,4 @@ -//===--- ModuleLoader.h - Module Loader Interface ---------------*- C++ -*-===// +//===- ModuleLoader.h - Module Loader Interface -----------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -11,23 +11,26 @@ // loading named modules. // //===----------------------------------------------------------------------===// + #ifndef LLVM_CLANG_LEX_MODULELOADER_H #define LLVM_CLANG_LEX_MODULELOADER_H +#include "clang/Basic/LLVM.h" #include "clang/Basic/Module.h" #include "clang/Basic/SourceLocation.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/PointerIntPair.h" +#include "llvm/ADT/StringRef.h" +#include <utility> namespace clang { class GlobalModuleIndex; class IdentifierInfo; -class Module; /// \brief A sequence of identifier/location pairs used to describe a particular /// module or submodule, e.g., std.vector. -typedef ArrayRef<std::pair<IdentifierInfo *, SourceLocation> > ModuleIdPath; +using ModuleIdPath = ArrayRef<std::pair<IdentifierInfo *, SourceLocation>>; /// \brief Describes the result of attempting to load a module. class ModuleLoadResult { @@ -35,16 +38,18 @@ public: enum LoadResultKind { // We either succeeded or failed to load the named module. Normal, + // The module exists, but does not actually contain the named submodule. // This should only happen if the named submodule was inferred from an // umbrella directory, but not actually part of the umbrella header. MissingExpected, + // The module exists but cannot be imported due to a configuration mismatch. ConfigMismatch }; llvm::PointerIntPair<Module *, 2, LoadResultKind> Storage; - ModuleLoadResult() : Storage() { } + ModuleLoadResult() = default; ModuleLoadResult(Module *M) : Storage(M, Normal) {} ModuleLoadResult(LoadResultKind Kind) : Storage(nullptr, Kind) {} @@ -69,10 +74,10 @@ public: class ModuleLoader { // Building a module if true. bool BuildingModule; + public: - explicit ModuleLoader(bool BuildingModule = false) : - BuildingModule(BuildingModule), - HadFatalFailure(false) {} + explicit ModuleLoader(bool BuildingModule = false) + : BuildingModule(BuildingModule) {} virtual ~ModuleLoader(); @@ -80,6 +85,7 @@ public: bool buildingModule() const { return BuildingModule; } + /// \brief Flag indicating whether this instance is building a module. void setBuildingModule(bool BuildingModuleFlag) { BuildingModule = BuildingModuleFlag; @@ -144,7 +150,7 @@ public: virtual bool lookupMissingImports(StringRef Name, SourceLocation TriggerLoc) = 0; - bool HadFatalFailure; + bool HadFatalFailure = false; }; /// A module loader that doesn't know how to load modules. @@ -153,7 +159,7 @@ public: ModuleLoadResult loadModule(SourceLocation ImportLoc, ModuleIdPath Path, Module::NameVisibilityKind Visibility, bool IsInclusionDirective) override { - return ModuleLoadResult(); + return {}; } void loadModuleFromSource(SourceLocation ImportLoc, StringRef ModuleName, @@ -165,12 +171,13 @@ public: GlobalModuleIndex *loadGlobalModuleIndex(SourceLocation TriggerLoc) override { return nullptr; } + bool lookupMissingImports(StringRef Name, SourceLocation TriggerLoc) override { - return 0; + return false; } }; -} +} // namespace clang -#endif +#endif // LLVM_CLANG_LEX_MODULELOADER_H diff --git a/include/clang/Lex/ModuleMap.h b/include/clang/Lex/ModuleMap.h index 11506939f9b1..41ed8e49b6c1 100644 --- a/include/clang/Lex/ModuleMap.h +++ b/include/clang/Lex/ModuleMap.h @@ -1,4 +1,4 @@ -//===--- ModuleMap.h - Describe the layout of modules -----------*- C++ -*-===// +//===- ModuleMap.h - Describe the layout of modules -------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -18,7 +18,6 @@ #include "clang/Basic/LangOptions.h" #include "clang/Basic/Module.h" #include "clang/Basic/SourceLocation.h" -#include "clang/Basic/SourceManager.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/PointerIntPair.h" @@ -28,20 +27,19 @@ #include "llvm/ADT/StringRef.h" #include "llvm/ADT/TinyPtrVector.h" #include "llvm/ADT/Twine.h" -#include <algorithm> +#include <ctime> #include <memory> #include <string> #include <utility> namespace clang { +class DiagnosticsEngine; class DirectoryEntry; class FileEntry; class FileManager; -class DiagnosticConsumer; -class DiagnosticsEngine; class HeaderSearch; -class ModuleMapParser; +class SourceManager; /// \brief A mechanism to observe the actions of the module map parser as it /// reads module map files. @@ -82,33 +80,40 @@ class ModuleMap { /// \brief The directory used for Clang-supplied, builtin include headers, /// such as "stdint.h". - const DirectoryEntry *BuiltinIncludeDir; + const DirectoryEntry *BuiltinIncludeDir = nullptr; /// \brief Language options used to parse the module map itself. /// /// These are always simple C language options. LangOptions MMapLangOpts; - // The module that the main source file is associated with (the module - // named LangOpts::CurrentModule, if we've loaded it). - Module *SourceModule; + /// The module that the main source file is associated with (the module + /// named LangOpts::CurrentModule, if we've loaded it). + Module *SourceModule = nullptr; + + /// The global module for the current TU, if we still own it. (Ownership is + /// transferred if/when we create an enclosing module. + std::unique_ptr<Module> PendingGlobalModule; /// \brief The top-level modules that are known. llvm::StringMap<Module *> Modules; /// \brief The number of modules we have created in total. - unsigned NumCreatedModules; + unsigned NumCreatedModules = 0; public: /// \brief Flags describing the role of a module header. enum ModuleHeaderRole { /// \brief This header is normally included in the module. NormalHeader = 0x0, + /// \brief This header is included but private. PrivateHeader = 0x1, + /// \brief This header is part of the module (for layering purposes) but /// should be textually included. TextualHeader = 0x2, + // Caution: Adding an enumerator needs other changes. // Adjust the number of bits for KnownHeader::Storage. // Adjust the bitfield HeaderFileInfo::HeaderRole size. @@ -119,6 +124,7 @@ public: /// Convert a header kind to a role. Requires Kind to not be HK_Excluded. static ModuleHeaderRole headerKindToRole(Module::HeaderKind Kind); + /// Convert a header role to a kind. static Module::HeaderKind headerRoleToKind(ModuleHeaderRole Role); @@ -128,8 +134,8 @@ public: llvm::PointerIntPair<Module *, 2, ModuleHeaderRole> Storage; public: - KnownHeader() : Storage(nullptr, NormalHeader) { } - KnownHeader(Module *M, ModuleHeaderRole Role) : Storage(M, Role) { } + KnownHeader() : Storage(nullptr, NormalHeader) {} + KnownHeader(Module *M, ModuleHeaderRole Role) : Storage(M, Role) {} friend bool operator==(const KnownHeader &A, const KnownHeader &B) { return A.Storage == B.Storage; @@ -162,11 +168,13 @@ public: } }; - typedef llvm::SmallPtrSet<const FileEntry *, 1> AdditionalModMapsSet; + using AdditionalModMapsSet = llvm::SmallPtrSet<const FileEntry *, 1>; private: - typedef llvm::DenseMap<const FileEntry *, SmallVector<KnownHeader, 1>> - HeadersMap; + friend class ModuleMapParser; + + using HeadersMap = + llvm::DenseMap<const FileEntry *, SmallVector<KnownHeader, 1>>; /// \brief Mapping from each header to the module that owns the contents of /// that header. @@ -174,6 +182,7 @@ private: /// Map from file sizes to modules with lazy header directives of that size. mutable llvm::DenseMap<off_t, llvm::TinyPtrVector<Module*>> LazyHeadersBySize; + /// Map from mtimes to modules with lazy header directives with those mtimes. mutable llvm::DenseMap<time_t, llvm::TinyPtrVector<Module*>> LazyHeadersByModTime; @@ -188,9 +197,6 @@ private: /// \brief The set of attributes that can be attached to a module. struct Attributes { - Attributes() - : IsSystem(), IsExternC(), IsExhaustive(), NoUndeclaredIncludes() {} - /// \brief Whether this is a system module. unsigned IsSystem : 1; @@ -203,12 +209,14 @@ private: /// \brief Whether files in this module can only include non-modular headers /// and headers from used modules. unsigned NoUndeclaredIncludes : 1; + + Attributes() + : IsSystem(false), IsExternC(false), IsExhaustive(false), + NoUndeclaredIncludes(false) {} }; /// \brief A directory for which framework modules can be inferred. struct InferredDirectory { - InferredDirectory() : InferModules() {} - /// \brief Whether to infer modules from this directory. unsigned InferModules : 1; @@ -222,6 +230,8 @@ private: /// \brief The names of modules that cannot be inferred within this /// directory. SmallVector<std::string, 2> ExcludedModules; + + InferredDirectory() : InferModules(false) {} }; /// \brief A mapping from directories to information about inferring @@ -238,8 +248,6 @@ private: /// map. llvm::DenseMap<const FileEntry *, bool> ParsedModuleMap; - friend class ModuleMapParser; - /// \brief Resolve the given export declaration into an actual export /// declaration. /// @@ -341,7 +349,6 @@ public: HeaderSearch &HeaderInfo); /// \brief Destroy the module map. - /// ~ModuleMap(); /// \brief Set the target information. @@ -460,7 +467,7 @@ public: /// \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. + /// or nullptr to indicate that this is a top-level module. /// /// \param IsFramework Whether this is a framework module. /// @@ -472,6 +479,14 @@ public: bool IsFramework, bool IsExplicit); + /// \brief Create a 'global module' for a C++ Modules TS module interface + /// unit. + /// + /// We model the global module as a submodule of the module interface unit. + /// Unfortunately, we can't create the module interface unit's Module until + /// later, because we don't know what it will be called. + Module *createGlobalModuleForInterfaceUnit(SourceLocation Loc); + /// \brief Create a new module for a C++ Modules TS module interface unit. /// The module must not already exist, and will be configured for the current /// compilation. @@ -479,7 +494,8 @@ public: /// Note that this also sets the current module to the newly-created module. /// /// \returns The newly-created module. - Module *createModuleForInterfaceUnit(SourceLocation Loc, StringRef Name); + Module *createModuleForInterfaceUnit(SourceLocation Loc, StringRef Name, + Module *GlobalModule); /// \brief Infer the contents of a framework module map from the given /// framework directory. @@ -492,7 +508,7 @@ public: /// \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. + /// module, or nullptr if the module definition was inferred. const FileEntry *getContainingModuleMapFile(const Module *Module) const; /// \brief Get the module map file that (along with the module name) uniquely @@ -599,11 +615,12 @@ public: /// \brief Dump the contents of the module map, for debugging purposes. void dump(); - typedef llvm::StringMap<Module *>::const_iterator module_iterator; + using module_iterator = llvm::StringMap<Module *>::const_iterator; + module_iterator module_begin() const { return Modules.begin(); } module_iterator module_end() const { return Modules.end(); } }; -} // end namespace clang +} // namespace clang #endif // LLVM_CLANG_LEX_MODULEMAP_H diff --git a/include/clang/Lex/MultipleIncludeOpt.h b/include/clang/Lex/MultipleIncludeOpt.h index 83e6f99078df..3967f8688966 100644 --- a/include/clang/Lex/MultipleIncludeOpt.h +++ b/include/clang/Lex/MultipleIncludeOpt.h @@ -92,7 +92,7 @@ public: TheMacro = nullptr; } - /// getHasReadAnyTokensVal - This is used for the \#ifndef hande-shake at the + /// getHasReadAnyTokensVal - This is used for the \#ifndef handshake at the /// top of the file when reading preprocessor directives. Otherwise, reading /// the "ifndef x" would count as reading tokens. bool getHasReadAnyTokensVal() const { return ReadAnyTokens; } diff --git a/include/clang/Lex/PPCallbacks.h b/include/clang/Lex/PPCallbacks.h index 81c3bd7d14ec..19bce4dd32e8 100644 --- a/include/clang/Lex/PPCallbacks.h +++ b/include/clang/Lex/PPCallbacks.h @@ -235,6 +235,14 @@ public: virtual void PragmaWarningPop(SourceLocation Loc) { } + /// \brief Callback invoked when a \#pragma clang assume_nonnull begin directive + /// is read. + virtual void PragmaAssumeNonNullBegin(SourceLocation Loc) {} + + /// \brief Callback invoked when a \#pragma clang assume_nonnull end directive + /// is read. + virtual void PragmaAssumeNonNullEnd(SourceLocation Loc) {} + /// \brief Called by Preprocessor::HandleMacroExpandedIdentifier when a /// macro invocation is found. virtual void MacroExpands(const Token &MacroNameTok, @@ -266,7 +274,10 @@ public: /// \brief Hook called when a source range is skipped. /// \param Range The SourceRange that was skipped. The range begins at the /// \#if/\#else directive and ends after the \#endif/\#else directive. - virtual void SourceRangeSkipped(SourceRange Range) { + /// \param EndifLoc The end location of the 'endif' token, which may precede + /// the range skipped by the directive (e.g excluding comments after an + /// 'endif'). + virtual void SourceRangeSkipped(SourceRange Range, SourceLocation EndifLoc) { } enum ConditionValueKind { @@ -381,6 +392,12 @@ public: Second->Ident(Loc, str); } + void PragmaDirective(SourceLocation Loc, + PragmaIntroducerKind Introducer) override { + First->PragmaDirective(Loc, Introducer); + Second->PragmaDirective(Loc, Introducer); + } + void PragmaComment(SourceLocation Loc, const IdentifierInfo *Kind, StringRef Str) override { First->PragmaComment(Loc, Kind, Str); @@ -393,6 +410,11 @@ public: Second->PragmaDetectMismatch(Loc, Name, Value); } + void PragmaDebug(SourceLocation Loc, StringRef DebugType) override { + First->PragmaDebug(Loc, DebugType); + Second->PragmaDebug(Loc, DebugType); + } + void PragmaMessage(SourceLocation Loc, StringRef Namespace, PragmaMessageKind Kind, StringRef Str) override { First->PragmaMessage(Loc, Namespace, Kind, Str); @@ -437,6 +459,16 @@ public: Second->PragmaWarningPop(Loc); } + void PragmaAssumeNonNullBegin(SourceLocation Loc) override { + First->PragmaAssumeNonNullBegin(Loc); + Second->PragmaAssumeNonNullBegin(Loc); + } + + void PragmaAssumeNonNullEnd(SourceLocation Loc) override { + First->PragmaAssumeNonNullEnd(Loc); + Second->PragmaAssumeNonNullEnd(Loc); + } + void MacroExpands(const Token &MacroNameTok, const MacroDefinition &MD, SourceRange Range, const MacroArgs *Args) override { First->MacroExpands(MacroNameTok, MD, Range, Args); @@ -462,9 +494,9 @@ public: Second->Defined(MacroNameTok, MD, Range); } - void SourceRangeSkipped(SourceRange Range) override { - First->SourceRangeSkipped(Range); - Second->SourceRangeSkipped(Range); + void SourceRangeSkipped(SourceRange Range, SourceLocation EndifLoc) override { + First->SourceRangeSkipped(Range, EndifLoc); + Second->SourceRangeSkipped(Range, EndifLoc); } /// \brief Hook called whenever an \#if is seen. diff --git a/include/clang/Lex/PTHLexer.h b/include/clang/Lex/PTHLexer.h index f96af665b157..f122a008e4aa 100644 --- a/include/clang/Lex/PTHLexer.h +++ b/include/clang/Lex/PTHLexer.h @@ -1,4 +1,4 @@ -//===--- PTHLexer.h - Lexer based on Pre-tokenized input --------*- C++ -*-===// +//===- PTHLexer.h - Lexer based on Pre-tokenized input ----------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -14,12 +14,15 @@ #ifndef LLVM_CLANG_LEX_PTHLEXER_H #define LLVM_CLANG_LEX_PTHLEXER_H +#include "clang/Basic/SourceLocation.h" +#include "clang/Basic/TokenKinds.h" #include "clang/Lex/PreprocessorLexer.h" +#include "clang/Lex/Token.h" namespace clang { +class Preprocessor; class PTHManager; -class PTHSpellingSearch; class PTHLexer : public PreprocessorLexer { SourceLocation FileStartLoc; @@ -33,7 +36,7 @@ class PTHLexer : public PreprocessorLexer { /// LastHashTokPtr - Pointer into TokBuf of the last processed '#' /// token that appears at the start of a line. - const unsigned char* LastHashTokPtr; + const unsigned char* LastHashTokPtr = nullptr; /// PPCond - Pointer to a side table in the PTH file that provides a /// a concise summary of the preprocessor conditional block structure. @@ -44,11 +47,8 @@ class PTHLexer : public PreprocessorLexer { /// to process when doing quick skipping of preprocessor blocks. const unsigned char* CurPPCondPtr; - PTHLexer(const PTHLexer &) = delete; - void operator=(const PTHLexer &) = delete; - /// ReadToken - Used by PTHLexer to read tokens TokBuf. - void ReadToken(Token& T); + void ReadToken(Token &T); bool LexEndOfFile(Token &Result); @@ -61,10 +61,13 @@ protected: friend class PTHManager; /// Create a PTHLexer for the specified token stream. - PTHLexer(Preprocessor& pp, FileID FID, const unsigned char *D, + PTHLexer(Preprocessor &pp, FileID FID, const unsigned char *D, const unsigned char* ppcond, PTHManager &PM); + public: - ~PTHLexer() override {} + PTHLexer(const PTHLexer &) = delete; + PTHLexer &operator=(const PTHLexer &) = delete; + ~PTHLexer() override = default; /// Lex - Return the next token. bool Lex(Token &Tok); @@ -99,6 +102,6 @@ public: bool SkipBlock(); }; -} // end namespace clang +} // namespace clang -#endif +#endif // LLVM_CLANG_LEX_PTHLEXER_H diff --git a/include/clang/Lex/PTHManager.h b/include/clang/Lex/PTHManager.h index f4e4774429f9..483b69f23a9c 100644 --- a/include/clang/Lex/PTHManager.h +++ b/include/clang/Lex/PTHManager.h @@ -1,4 +1,4 @@ -//===--- PTHManager.h - Manager object for PTH processing -------*- C++ -*-===// +//===- PTHManager.h - Manager object for PTH processing ---------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -17,30 +17,33 @@ #include "clang/Basic/IdentifierTable.h" #include "clang/Basic/SourceLocation.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringRef.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/OnDiskHashTable.h" +#include <memory> namespace llvm { - class MemoryBuffer; -} + +class MemoryBuffer; + +} // namespace llvm namespace clang { -class FileEntry; -class Preprocessor; -class PTHLexer; class DiagnosticsEngine; class FileSystemStatCache; +class Preprocessor; +class PTHLexer; class PTHManager : public IdentifierInfoLookup { friend class PTHLexer; - friend class PTHStatCache; - class PTHStringLookupTrait; class PTHFileLookupTrait; - typedef llvm::OnDiskChainedHashTable<PTHStringLookupTrait> PTHStringIdLookup; - typedef llvm::OnDiskChainedHashTable<PTHFileLookupTrait> PTHFileLookup; + class PTHStringLookupTrait; + + using PTHStringIdLookup = llvm::OnDiskChainedHashTable<PTHStringLookupTrait>; + using PTHFileLookup = llvm::OnDiskChainedHashTable<PTHFileLookupTrait>; /// The memory mapped PTH file. std::unique_ptr<const llvm::MemoryBuffer> Buf; @@ -70,7 +73,7 @@ class PTHManager : public IdentifierInfoLookup { /// PP - The Preprocessor object that will use this PTHManager to create /// PTHLexer objects. - Preprocessor* PP; + Preprocessor* PP = nullptr; /// SpellingBase - The base offset within the PTH memory buffer that /// contains the cached spellings for literals. @@ -89,16 +92,13 @@ class PTHManager : public IdentifierInfoLookup { std::unique_ptr<PTHStringIdLookup> stringIdLookup, unsigned numIds, const unsigned char *spellingBase, const char *originalSourceFile); - PTHManager(const PTHManager &) = delete; - void operator=(const PTHManager &) = delete; - /// getSpellingAtPTHOffset - Used by PTHLexer classes to get the cached /// spelling for a token. unsigned getSpellingAtPTHOffset(unsigned PTHOffset, const char*& Buffer); /// GetIdentifierInfo - Used to reconstruct IdentifierInfo objects from the /// PTH file. - inline IdentifierInfo* GetIdentifierInfo(unsigned PersistentID) { + IdentifierInfo *GetIdentifierInfo(unsigned PersistentID) { // Check if the IdentifierInfo has already been resolved. if (IdentifierInfo* II = PerIDCache[PersistentID]) return II; @@ -110,6 +110,8 @@ public: // The current PTH version. enum { Version = 10 }; + PTHManager(const PTHManager &) = delete; + PTHManager &operator=(const PTHManager &) = delete; ~PTHManager() override; /// getOriginalSourceFile - Return the full path to the original header @@ -120,18 +122,18 @@ public: /// get - Return the identifier token info for the specified named identifier. /// Unlike the version in IdentifierTable, this returns a pointer instead - /// of a reference. If the pointer is NULL then the IdentifierInfo cannot + /// of a reference. If the pointer is nullptr then the IdentifierInfo cannot /// be found. IdentifierInfo *get(StringRef Name) override; /// Create - This method creates PTHManager objects. The 'file' argument - /// is the name of the PTH file. This method returns NULL upon failure. + /// is the name of the PTH file. This method returns nullptr upon failure. static PTHManager *Create(StringRef file, DiagnosticsEngine &Diags); void setPreprocessor(Preprocessor *pp) { PP = pp; } /// CreateLexer - Return a PTHLexer that "lexes" the cached tokens for the - /// specified file. This method returns NULL if no cached tokens exist. + /// specified file. This method returns nullptr if no cached tokens exist. /// It is the responsibility of the caller to 'delete' the returned object. PTHLexer *CreateLexer(FileID FID); @@ -142,6 +144,6 @@ public: std::unique_ptr<FileSystemStatCache> createStatCache(); }; -} // end namespace clang +} // namespace clang -#endif +#endif // LLVM_CLANG_LEX_PTHMANAGER_H diff --git a/include/clang/Lex/Pragma.h b/include/clang/Lex/Pragma.h index 274f0dad3dd0..090ae2a98236 100644 --- a/include/clang/Lex/Pragma.h +++ b/include/clang/Lex/Pragma.h @@ -1,4 +1,4 @@ -//===--- Pragma.h - Pragma registration and handling ------------*- C++ -*-===// +//===- Pragma.h - Pragma registration and handling --------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -17,13 +17,13 @@ #include "clang/Basic/LLVM.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" -#include <cassert> +#include <string> namespace clang { - class Preprocessor; - class Token; - class IdentifierInfo; - class PragmaNamespace; + +class PragmaNamespace; +class Preprocessor; +class Token; /** * \brief Describes how the pragma was introduced, e.g., with \#pragma, @@ -58,9 +58,10 @@ namespace clang { /// pragmas. class PragmaHandler { std::string Name; + public: + PragmaHandler() = default; explicit PragmaHandler(StringRef name) : Name(name) {} - PragmaHandler() {} virtual ~PragmaHandler(); StringRef getName() const { return Name; } @@ -89,8 +90,8 @@ public: class PragmaNamespace : public PragmaHandler { /// Handlers - This is a map of the handlers in this namespace with their name /// as key. - /// - llvm::StringMap<PragmaHandler*> Handlers; + llvm::StringMap<PragmaHandler *> Handlers; + public: explicit PragmaNamespace(StringRef Name) : PragmaHandler(Name) {} ~PragmaNamespace() override; @@ -103,16 +104,13 @@ public: bool IgnoreNull = true) const; /// AddPragma - Add a pragma to this namespace. - /// void AddPragma(PragmaHandler *Handler); /// RemovePragmaHandler - Remove the given handler from the /// namespace. void RemovePragmaHandler(PragmaHandler *Handler); - bool IsEmpty() { - return Handlers.empty(); - } + bool IsEmpty() const { return Handlers.empty(); } void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, Token &FirstToken) override; @@ -120,7 +118,6 @@ public: PragmaNamespace *getIfNamespace() override { return this; } }; +} // namespace clang -} // end namespace clang - -#endif +#endif // LLVM_CLANG_LEX_PRAGMA_H diff --git a/include/clang/Lex/PreprocessingRecord.h b/include/clang/Lex/PreprocessingRecord.h index fc2c50700400..5f7a6efcef10 100644 --- a/include/clang/Lex/PreprocessingRecord.h +++ b/include/clang/Lex/PreprocessingRecord.h @@ -1,4 +1,4 @@ -//===--- PreprocessingRecord.h - Record of Preprocessing --------*- C++ -*-===// +//===- PreprocessingRecord.h - Record of Preprocessing ----------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -11,24 +11,33 @@ // of what occurred during preprocessing. // //===----------------------------------------------------------------------===// + #ifndef LLVM_CLANG_LEX_PREPROCESSINGRECORD_H #define LLVM_CLANG_LEX_PREPROCESSINGRECORD_H -#include "clang/Basic/IdentifierTable.h" +#include "clang/Basic/LLVM.h" #include "clang/Basic/SourceLocation.h" #include "clang/Lex/PPCallbacks.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/None.h" #include "llvm/ADT/Optional.h" +#include "llvm/ADT/PointerUnion.h" +#include "llvm/ADT/StringRef.h" #include "llvm/ADT/iterator.h" +#include "llvm/ADT/iterator_range.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/Compiler.h" +#include <cassert> +#include <cstddef> +#include <iterator> +#include <utility> #include <vector> namespace clang { - class IdentifierInfo; - class MacroInfo; - class PreprocessingRecord; -} + +class PreprocessingRecord; + +} // namespace clang /// \brief Allocates memory within a Clang preprocessing record. void *operator new(size_t bytes, clang::PreprocessingRecord &PR, @@ -39,8 +48,12 @@ void operator delete(void *ptr, clang::PreprocessingRecord &PR, unsigned) noexcept; namespace clang { - class MacroDefinitionRecord; - class FileEntry; + +class FileEntry; +class IdentifierInfo; +class MacroInfo; +class SourceManager; +class Token; /// \brief Base class that describes a preprocessed entity, which may be a /// preprocessor directive or macro expansion. @@ -78,11 +91,11 @@ namespace clang { SourceRange Range; protected: - PreprocessedEntity(EntityKind Kind, SourceRange Range) - : Kind(Kind), Range(Range) { } - friend class PreprocessingRecord; + PreprocessedEntity(EntityKind Kind, SourceRange Range) + : Kind(Kind), Range(Range) {} + public: /// \brief Retrieve the kind of preprocessed entity stored in this object. EntityKind getKind() const { return Kind; } @@ -122,7 +135,7 @@ namespace clang { class PreprocessingDirective : public PreprocessedEntity { public: PreprocessingDirective(EntityKind Kind, SourceRange Range) - : PreprocessedEntity(Kind, Range) { } + : PreprocessedEntity(Kind, Range) {} // Implement isa/cast/dyncast/etc. static bool classof(const PreprocessedEntity *PD) { @@ -199,10 +212,13 @@ namespace clang { enum InclusionKind { /// \brief An \c \#include directive. Include, + /// \brief An Objective-C \c \#import directive. Import, + /// \brief A GNU \c \#include_next directive. IncludeNext, + /// \brief A Clang \c \#__include_macros directive. IncludeMacros }; @@ -316,11 +332,14 @@ namespace clang { /// value 1 corresponds to element 0 in the local entities vector, /// value 2 corresponds to element 1 in the local entities vector, etc. class PPEntityID { - int ID; - explicit PPEntityID(int ID) : ID(ID) {} friend class PreprocessingRecord; + + int ID = 0; + + explicit PPEntityID(int ID) : ID(ID) {} + public: - PPEntityID() : ID(0) {} + PPEntityID() = default; }; static PPEntityID getPPEntityID(unsigned Index, bool isLoaded) { @@ -331,7 +350,7 @@ namespace clang { llvm::DenseMap<const MacroInfo *, MacroDefinitionRecord *> MacroDefinitions; /// \brief External source of preprocessed entities. - ExternalPreprocessingRecordSource *ExternalSource; + ExternalPreprocessingRecordSource *ExternalSource = nullptr; /// \brief Retrieve the preprocessed entity at the given ID. PreprocessedEntity *getPreprocessedEntity(PPEntityID PPID); @@ -371,7 +390,7 @@ namespace clang { } /// \brief Deallocate memory in the preprocessing record. - void Deallocate(void *Ptr) { } + void Deallocate(void *Ptr) {} size_t getTotalMemory() const; @@ -397,11 +416,12 @@ namespace clang { iterator, int, std::random_access_iterator_tag, PreprocessedEntity *, int, PreprocessedEntity *, PreprocessedEntity *> { + friend class PreprocessingRecord; + PreprocessingRecord *Self; iterator(PreprocessingRecord *Self, int Position) : iterator::iterator_adaptor_base(Position), Self(Self) {} - friend class PreprocessingRecord; public: iterator() : iterator(nullptr, 0) {} @@ -451,7 +471,6 @@ namespace clang { /// encompasses. /// /// \param R the range to look for preprocessed entities. - /// llvm::iterator_range<iterator> getPreprocessedEntitiesInRange(SourceRange R); @@ -485,6 +504,9 @@ namespace clang { } private: + friend class ASTReader; + friend class ASTWriter; + void MacroExpands(const Token &Id, const MacroDefinition &MD, SourceRange Range, const MacroArgs *Args) override; void MacroDefined(const Token &Id, const MacroDirective *MD) override; @@ -500,11 +522,13 @@ namespace clang { const MacroDefinition &MD) override; void Ifndef(SourceLocation Loc, const Token &MacroNameTok, const MacroDefinition &MD) override; + /// \brief Hook called whenever the 'defined' operator is seen. void Defined(const Token &MacroNameTok, const MacroDefinition &MD, SourceRange Range) override; - void SourceRangeSkipped(SourceRange Range) override; + void SourceRangeSkipped(SourceRange Range, + SourceLocation EndifLoc) override; void addMacroExpansion(const Token &Id, const MacroInfo *MI, SourceRange Range); @@ -517,11 +541,9 @@ namespace clang { } CachedRangeQuery; std::pair<int, int> getPreprocessedEntitiesInRangeSlow(SourceRange R); - - friend class ASTReader; - friend class ASTWriter; }; -} // end namespace clang + +} // namespace clang inline void *operator new(size_t bytes, clang::PreprocessingRecord &PR, unsigned alignment) noexcept { diff --git a/include/clang/Lex/Preprocessor.h b/include/clang/Lex/Preprocessor.h index dba4b80f6071..485600f12232 100644 --- a/include/clang/Lex/Preprocessor.h +++ b/include/clang/Lex/Preprocessor.h @@ -1,4 +1,4 @@ -//===--- Preprocessor.h - C Language Family Preprocessor --------*- C++ -*-===// +//===- Preprocessor.h - C Language Family Preprocessor ----------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -6,10 +6,10 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -/// +// /// \file /// \brief Defines the clang::Preprocessor interface. -/// +// //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_LEX_PREPROCESSOR_H @@ -18,48 +18,70 @@ #include "clang/Basic/Builtins.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/IdentifierTable.h" +#include "clang/Basic/LLVM.h" +#include "clang/Basic/LangOptions.h" +#include "clang/Basic/Module.h" #include "clang/Basic/SourceLocation.h" +#include "clang/Basic/SourceManager.h" +#include "clang/Basic/TokenKinds.h" #include "clang/Lex/Lexer.h" #include "clang/Lex/MacroInfo.h" +#include "clang/Lex/ModuleLoader.h" #include "clang/Lex/ModuleMap.h" #include "clang/Lex/PPCallbacks.h" #include "clang/Lex/PTHLexer.h" +#include "clang/Lex/Token.h" #include "clang/Lex/TokenLexer.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/IntrusiveRefCntPtr.h" +#include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/None.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/PointerUnion.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" #include "llvm/ADT/TinyPtrVector.h" +#include "llvm/ADT/iterator_range.h" #include "llvm/Support/Allocator.h" +#include "llvm/Support/Casting.h" #include "llvm/Support/Registry.h" +#include <cassert> +#include <cstddef> +#include <cstdint> #include <memory> +#include <map> +#include <string> +#include <utility> #include <vector> namespace llvm { - template<unsigned InternalLen> class SmallString; -} + +template<unsigned InternalLen> class SmallString; + +} // namespace llvm namespace clang { -class SourceManager; +class CodeCompletionHandler; +class CommentHandler; +class DirectoryEntry; +class DirectoryLookup; class ExternalPreprocessorSource; -class FileManager; class FileEntry; +class FileManager; class HeaderSearch; +class MacroArgs; class MemoryBufferCache; -class PragmaNamespace; class PragmaHandler; -class CommentHandler; -class ScratchBuffer; -class TargetInfo; -class PPCallbacks; -class CodeCompletionHandler; -class DirectoryLookup; +class PragmaNamespace; class PreprocessingRecord; -class ModuleLoader; -class PTHManager; +class PreprocessorLexer; class PreprocessorOptions; +class PTHManager; +class ScratchBuffer; +class TargetInfo; /// \brief Stores token information for comparing actual tokens with /// predefined values. Only handles simple tokens and identifiers. @@ -75,7 +97,9 @@ public: assert(!tok::isLiteral(Kind) && "Literals are not supported."); assert(!tok::isAnnotation(Kind) && "Annotations are not supported."); } + TokenValue(IdentifierInfo *II) : Kind(tok::identifier), II(II) {} + bool operator==(const Token &Tok) const { return Tok.getKind() == Kind && (!II || II == Tok.getIdentifierInfo()); @@ -84,9 +108,14 @@ public: /// \brief Context in which macro name is used. enum MacroUse { - MU_Other = 0, // other than #define or #undef - MU_Define = 1, // macro name specified in #define - MU_Undef = 2 // macro name specified in #undef + // other than #define or #undef + MU_Other = 0, + + // macro name specified in #define + MU_Define = 1, + + // macro name specified in #undef + MU_Undef = 2 }; /// \brief Engages in a tight little dance with the lexer to efficiently @@ -96,11 +125,14 @@ enum MacroUse { /// know anything about preprocessor-level issues like the \#include stack, /// token expansion, etc. class Preprocessor { + friend class VAOptDefinitionContext; + friend class VariadicMacroScopeGuard; + std::shared_ptr<PreprocessorOptions> PPOpts; DiagnosticsEngine *Diags; LangOptions &LangOpts; - const TargetInfo *Target; - const TargetInfo *AuxTarget; + const TargetInfo *Target = nullptr; + const TargetInfo *AuxTarget = nullptr; FileManager &FileMgr; SourceManager &SourceMgr; MemoryBufferCache &PCMCache; @@ -111,7 +143,6 @@ class Preprocessor { /// \brief External source of macros. ExternalPreprocessorSource *ExternalSource; - /// An optional PTHManager object used for getting tokens from /// a token cache rather than lexing the original source file. std::unique_ptr<PTHManager> PTH; @@ -130,6 +161,7 @@ class Preprocessor { IdentifierInfo *Ident_Pragma, *Ident__pragma; // _Pragma, __pragma IdentifierInfo *Ident__identifier; // __identifier IdentifierInfo *Ident__VA_ARGS__; // __VA_ARGS__ + IdentifierInfo *Ident__VA_OPT__; // __VA_OPT__ IdentifierInfo *Ident__has_feature; // __has_feature IdentifierInfo *Ident__has_extension; // __has_extension IdentifierInfo *Ident__has_builtin; // __has_builtin @@ -141,10 +173,17 @@ class Preprocessor { IdentifierInfo *Ident__building_module; // __building_module IdentifierInfo *Ident__MODULE__; // __MODULE__ IdentifierInfo *Ident__has_cpp_attribute; // __has_cpp_attribute + IdentifierInfo *Ident__has_c_attribute; // __has_c_attribute IdentifierInfo *Ident__has_declspec; // __has_declspec_attribute + IdentifierInfo *Ident__is_target_arch; // __is_target_arch + IdentifierInfo *Ident__is_target_vendor; // __is_target_vendor + IdentifierInfo *Ident__is_target_os; // __is_target_os + IdentifierInfo *Ident__is_target_environment; // __is_target_environment SourceLocation DATELoc, TIMELoc; - unsigned CounterValue; // Next __COUNTER__ value. + + // Next __COUNTER__ value, starts at 0. + unsigned CounterValue = 0; enum { /// \brief Maximum depth of \#includes. @@ -218,19 +257,19 @@ class Preprocessor { /// \brief True if we want to ignore EOF token and continue later on (thus /// avoid tearing the Lexer and etc. down). - bool IncrementalProcessing; + bool IncrementalProcessing = false; /// The kind of translation unit we are processing. TranslationUnitKind TUKind; /// \brief The code-completion handler. - CodeCompletionHandler *CodeComplete; + CodeCompletionHandler *CodeComplete = nullptr; /// \brief The file that we're performing code-completion for, if any. - const FileEntry *CodeCompletionFile; + const FileEntry *CodeCompletionFile = nullptr; /// \brief The offset in file for the code-completion point. - unsigned CodeCompletionOffset; + unsigned CodeCompletionOffset = 0; /// \brief The location for the code-completion point. This gets instantiated /// when the CodeCompletionFile gets \#include'ed for preprocessing. @@ -250,11 +289,11 @@ class Preprocessor { SmallVector<std::pair<IdentifierInfo *, SourceLocation>, 2> ModuleImportPath; /// \brief Whether the last token we lexed was an '@'. - bool LastTokenWasAt; + bool LastTokenWasAt = false; /// \brief Whether the module import expects an identifier next. Otherwise, /// it expects a '.' or ';'. - bool ModuleImportExpectsIdentifier; + bool ModuleImportExpectsIdentifier = false; /// \brief The source location of the currently-active /// \#pragma clang arc_cf_code_audited begin. @@ -265,16 +304,16 @@ class Preprocessor { SourceLocation PragmaAssumeNonNullLoc; /// \brief True if we hit the code-completion point. - bool CodeCompletionReached; + bool CodeCompletionReached = false; /// \brief The code completion token containing the information /// on the stem that is to be code completed. - IdentifierInfo *CodeCompletionII; + IdentifierInfo *CodeCompletionII = nullptr; /// \brief The directory that the main file should be considered to occupy, /// if it does not correspond to a real file (as happens when building a /// module). - const DirectoryEntry *MainFileDir; + const DirectoryEntry *MainFileDir = nullptr; /// \brief The number of bytes that we will initially skip when entering the /// main file, along with a flag that indicates whether skipping this number @@ -283,6 +322,26 @@ class Preprocessor { /// This is used when loading a precompiled preamble. std::pair<int, bool> SkipMainFilePreamble; +public: + struct PreambleSkipInfo { + SourceLocation HashTokenLoc; + SourceLocation IfTokenLoc; + bool FoundNonSkipPortion; + bool FoundElse; + SourceLocation ElseLoc; + + PreambleSkipInfo(SourceLocation HashTokenLoc, SourceLocation IfTokenLoc, + bool FoundNonSkipPortion, bool FoundElse, + SourceLocation ElseLoc) + : HashTokenLoc(HashTokenLoc), IfTokenLoc(IfTokenLoc), + FoundNonSkipPortion(FoundNonSkipPortion), FoundElse(FoundElse), + ElseLoc(ElseLoc) {} + }; + +private: + friend class ASTReader; + friend class MacroArgs; + class PreambleConditionalStackStore { enum State { Off = 0, @@ -291,7 +350,7 @@ class Preprocessor { }; public: - PreambleConditionalStackStore() : ConditionalStackState(Off) {} + PreambleConditionalStackStore() = default; void startRecording() { ConditionalStackState = Recording; } void startReplaying() { ConditionalStackState = Replaying; } @@ -316,9 +375,15 @@ class Preprocessor { bool hasRecordedPreamble() const { return !ConditionalStack.empty(); } + bool reachedEOFWhileSkipping() const { return SkipInfo.hasValue(); } + + void clearSkipInfo() { SkipInfo.reset(); } + + llvm::Optional<PreambleSkipInfo> SkipInfo; + private: SmallVector<PPConditionalInfo, 4> ConditionalStack; - State ConditionalStackState; + State ConditionalStackState = Off; } PreambleConditionalStack; /// \brief The current top of the stack that we're lexing from if @@ -337,14 +402,14 @@ class Preprocessor { /// if not expanding a macro. /// /// This is an alias for either CurLexer or CurPTHLexer. - PreprocessorLexer *CurPPLexer; + PreprocessorLexer *CurPPLexer = nullptr; /// \brief 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. - const DirectoryLookup *CurDirLookup; + const DirectoryLookup *CurDirLookup = nullptr; /// \brief The current macro we are expanding, if we are expanding a macro. /// @@ -358,11 +423,11 @@ class Preprocessor { CLK_TokenLexer, CLK_CachingLexer, CLK_LexAfterModuleImport - } CurLexerKind; + } CurLexerKind = CLK_Lexer; /// \brief If the current lexer is for a submodule that is being built, this /// is that submodule. - Module *CurLexerSubmodule; + Module *CurLexerSubmodule = nullptr; /// \brief Keeps track of the stack of files currently /// \#included, and macros currently being expanded from, not counting @@ -401,27 +466,31 @@ class Preprocessor { Token Tok; MacroDefinition MD; SourceRange Range; + MacroExpandsInfo(Token Tok, MacroDefinition MD, SourceRange Range) - : Tok(Tok), MD(MD), Range(Range) { } + : Tok(Tok), MD(MD), Range(Range) {} }; SmallVector<MacroExpandsInfo, 2> DelayedMacroExpandsCallbacks; /// Information about a name that has been used to define a module macro. struct ModuleMacroInfo { - ModuleMacroInfo(MacroDirective *MD) - : MD(MD), ActiveModuleMacrosGeneration(0), IsAmbiguous(false) {} - /// The most recent macro directive for this identifier. MacroDirective *MD; + /// The active module macros for this identifier. - llvm::TinyPtrVector<ModuleMacro*> ActiveModuleMacros; + llvm::TinyPtrVector<ModuleMacro *> ActiveModuleMacros; + /// The generation number at which we last updated ActiveModuleMacros. /// \see Preprocessor::VisibleModules. - unsigned ActiveModuleMacrosGeneration; + unsigned ActiveModuleMacrosGeneration = 0; + /// Whether this macro name is ambiguous. - bool IsAmbiguous; + bool IsAmbiguous = false; + /// The module macros that are overridden by this macro. - llvm::TinyPtrVector<ModuleMacro*> OverriddenMacros; + llvm::TinyPtrVector<ModuleMacro *> OverriddenMacros; + + ModuleMacroInfo(MacroDirective *MD) : MD(MD) {} }; /// The state of a macro for an identifier. @@ -456,15 +525,18 @@ class Preprocessor { public: MacroState() : MacroState(nullptr) {} MacroState(MacroDirective *MD) : State(MD) {} + MacroState(MacroState &&O) noexcept : State(O.State) { O.State = (MacroDirective *)nullptr; } + MacroState &operator=(MacroState &&O) noexcept { auto S = O.State; O.State = (MacroDirective *)nullptr; State = S; return *this; } + ~MacroState() { if (auto *Info = State.dyn_cast<ModuleMacroInfo*>()) Info->~ModuleMacroInfo(); @@ -475,6 +547,7 @@ class Preprocessor { return Info->MD; return State.get<MacroDirective*>(); } + void setLatest(MacroDirective *MD) { if (auto *Info = State.dyn_cast<ModuleMacroInfo*>()) Info->MD = MD; @@ -486,6 +559,7 @@ class Preprocessor { auto *Info = getModuleInfo(PP, II); return Info ? Info->IsAmbiguous : false; } + ArrayRef<ModuleMacro *> getActiveModuleMacros(Preprocessor &PP, const IdentifierInfo *II) const { if (auto *Info = getModuleInfo(PP, II)) @@ -498,7 +572,7 @@ class Preprocessor { // FIXME: Incorporate module macros into the result of this. if (auto *Latest = getLatest()) return Latest->findDirectiveAtLoc(Loc, SourceMgr); - return MacroDirective::DefInfo(); + return {}; } void overrideActiveModuleMacros(Preprocessor &PP, IdentifierInfo *II) { @@ -510,11 +584,13 @@ class Preprocessor { Info->IsAmbiguous = false; } } + ArrayRef<ModuleMacro*> getOverriddenMacros() const { if (auto *Info = State.dyn_cast<ModuleMacroInfo*>()) return Info->OverriddenMacros; return None; } + void setOverriddenMacros(Preprocessor &PP, ArrayRef<ModuleMacro *> Overrides) { auto *Info = State.dyn_cast<ModuleMacroInfo*>(); @@ -537,31 +613,33 @@ class Preprocessor { /// the reverse order (the latest one is in the head of the list). /// /// This mapping lives within the \p CurSubmoduleState. - typedef llvm::DenseMap<const IdentifierInfo *, MacroState> MacroMap; - - friend class ASTReader; + using MacroMap = llvm::DenseMap<const IdentifierInfo *, MacroState>; struct SubmoduleState; /// \brief Information about a submodule that we're currently building. struct BuildingSubmoduleInfo { - BuildingSubmoduleInfo(Module *M, SourceLocation ImportLoc, bool IsPragma, - SubmoduleState *OuterSubmoduleState, - unsigned OuterPendingModuleMacroNames) - : M(M), ImportLoc(ImportLoc), IsPragma(IsPragma), - OuterSubmoduleState(OuterSubmoduleState), - OuterPendingModuleMacroNames(OuterPendingModuleMacroNames) {} - /// The module that we are building. Module *M; + /// The location at which the module was included. SourceLocation ImportLoc; + /// Whether we entered this submodule via a pragma. bool IsPragma; + /// The previous SubmoduleState. SubmoduleState *OuterSubmoduleState; + /// The number of pending module macro names when we started building this. unsigned OuterPendingModuleMacroNames; + + BuildingSubmoduleInfo(Module *M, SourceLocation ImportLoc, bool IsPragma, + SubmoduleState *OuterSubmoduleState, + unsigned OuterPendingModuleMacroNames) + : M(M), ImportLoc(ImportLoc), IsPragma(IsPragma), + OuterSubmoduleState(OuterSubmoduleState), + OuterPendingModuleMacroNames(OuterPendingModuleMacroNames) {} }; SmallVector<BuildingSubmoduleInfo, 8> BuildingSubmoduleStack; @@ -569,12 +647,14 @@ class Preprocessor { struct SubmoduleState { /// The macros for the submodule. MacroMap Macros; + /// The set of modules that are visible within the submodule. VisibleModuleSet VisibleModules; + // FIXME: CounterValue? // FIXME: PragmaPushMacroInfo? }; - std::map<Module*, SubmoduleState> Submodules; + std::map<Module *, SubmoduleState> Submodules; /// The preprocessor state for preprocessing outside of any submodule. SubmoduleState NullSubmoduleState; @@ -587,11 +667,11 @@ class Preprocessor { llvm::FoldingSet<ModuleMacro> ModuleMacros; /// The names of potential module macros that we've not yet processed. - llvm::SmallVector<const IdentifierInfo*, 32> PendingModuleMacroNames; + llvm::SmallVector<const IdentifierInfo *, 32> PendingModuleMacroNames; /// The list of module macros, for each identifier, that are not overridden by /// any other module macro. - llvm::DenseMap<const IdentifierInfo *, llvm::TinyPtrVector<ModuleMacro*>> + llvm::DenseMap<const IdentifierInfo *, llvm::TinyPtrVector<ModuleMacro *>> LeafModuleMacros; /// \brief Macros that we want to warn because they are not used at the end @@ -603,25 +683,35 @@ class Preprocessor { /// just so that we can report that they are unused, we just warn using /// the SourceLocations of this set (that will be filled by the ASTReader). /// We are using SmallPtrSet instead of a vector for faster removal. - typedef llvm::SmallPtrSet<SourceLocation, 32> WarnUnusedMacroLocsTy; + using WarnUnusedMacroLocsTy = llvm::SmallPtrSet<SourceLocation, 32>; WarnUnusedMacroLocsTy WarnUnusedMacroLocs; /// \brief A "freelist" of MacroArg objects that can be /// reused for quick allocation. - MacroArgs *MacroArgCache; - friend class MacroArgs; + MacroArgs *MacroArgCache = nullptr; /// For each IdentifierInfo used in a \#pragma push_macro directive, /// we keep a MacroInfo stack used to restore the previous macro value. - llvm::DenseMap<IdentifierInfo*, std::vector<MacroInfo*> > PragmaPushMacroInfo; + llvm::DenseMap<IdentifierInfo *, std::vector<MacroInfo *>> + PragmaPushMacroInfo; // Various statistics we track for performance analysis. - unsigned NumDirectives, NumDefined, NumUndefined, NumPragma; - unsigned NumIf, NumElse, NumEndif; - unsigned NumEnteredSourceFiles, MaxIncludeStackDepth; - unsigned NumMacroExpanded, NumFnMacroExpanded, NumBuiltinMacroExpanded; - unsigned NumFastMacroExpanded, NumTokenPaste, NumFastTokenPaste; - unsigned NumSkipped; + unsigned NumDirectives = 0; + unsigned NumDefined = 0; + unsigned NumUndefined = 0; + unsigned NumPragma = 0; + unsigned NumIf = 0; + unsigned NumElse = 0; + unsigned NumEndif = 0; + unsigned NumEnteredSourceFiles = 0; + unsigned MaxIncludeStackDepth = 0; + unsigned NumMacroExpanded = 0; + unsigned NumFnMacroExpanded = 0; + unsigned NumBuiltinMacroExpanded = 0; + unsigned NumFastMacroExpanded = 0; + unsigned NumTokenPaste = 0; + unsigned NumFastTokenPaste = 0; + unsigned NumSkipped = 0; /// \brief The predefined macros that preprocessor should use from the /// command line etc. @@ -643,17 +733,17 @@ class Preprocessor { /// going to lex in the cache and when it finishes the tokens are removed /// from the end of the cache. SmallVector<Token, 16> MacroExpandedTokens; - std::vector<std::pair<TokenLexer *, size_t> > MacroExpandingLexersStack; + std::vector<std::pair<TokenLexer *, size_t>> MacroExpandingLexersStack; /// \brief A record of the macro definitions and expansions that /// occurred during preprocessing. /// /// This is an optional side structure that can be enabled with /// \c createPreprocessingRecord() prior to preprocessing. - PreprocessingRecord *Record; + PreprocessingRecord *Record = nullptr; /// Cached tokens state. - typedef SmallVector<Token, 1> CachedTokensTy; + using CachedTokensTy = SmallVector<Token, 1>; /// \brief Cached tokens are stored here when we do backtracking or /// lookahead. They are "lexed" by the CachingLex() method. @@ -664,7 +754,7 @@ class Preprocessor { /// /// If it points beyond the CachedTokens vector, it means that a normal /// Lex() should be invoked. - CachedTokensTy::size_type CachedLexPos; + CachedTokensTy::size_type CachedLexPos = 0; /// \brief Stack of backtrack positions, allowing nested backtracks. /// @@ -680,7 +770,7 @@ class Preprocessor { /// MacroInfos are managed as a chain for easy disposal. This is the head /// of that list. - MacroInfoChain *MIChainHead; + MacroInfoChain *MIChainHead = nullptr; void updateOutOfDateIdentifier(IdentifierInfo &II) const; @@ -853,7 +943,7 @@ public: MacroDefinition getMacroDefinition(const IdentifierInfo *II) { if (!II->hasMacroDefinition()) - return MacroDefinition(); + return {}; MacroState &S = CurSubmoduleState->Macros[II]; auto *MD = S.getLatest(); @@ -867,7 +957,7 @@ public: MacroDefinition getMacroDefinitionAtLoc(const IdentifierInfo *II, SourceLocation Loc) { if (!II->hadMacroDefinition()) - return MacroDefinition(); + return {}; MacroState &S = CurSubmoduleState->Macros[II]; MacroDirective::DefInfo DI; @@ -923,6 +1013,7 @@ public: MacroInfo *MI) { return appendDefMacroDirective(II, MI, MI->getDefinitionLoc()); } + /// \brief Set a MacroDirective that was loaded from a PCH file. void setLoadedMacroDirective(IdentifierInfo *II, MacroDirective *ED, MacroDirective *MD); @@ -946,10 +1037,12 @@ public: /// Iterators for the macro history table. Currently defined macros have /// IdentifierInfo::hasMacroDefinition() set and an empty /// MacroInfo::getUndefLoc() at the head of the list. - typedef MacroMap::const_iterator macro_iterator; + using macro_iterator = MacroMap::const_iterator; + macro_iterator macro_begin(bool IncludeExternalMacros = true) const; macro_iterator macro_end(bool IncludeExternalMacros = true) const; llvm::iterator_range<macro_iterator> + macros(bool IncludeExternalMacros = true) const { return llvm::make_range(macro_begin(IncludeExternalMacros), macro_end(IncludeExternalMacros)); @@ -963,6 +1056,7 @@ public: ArrayRef<TokenValue> Tokens) const; const std::string &getPredefines() const { return Predefines; } + /// \brief Set the predefines for this Preprocessor. /// /// These predefines are automatically injected when parsing the main file. @@ -1087,6 +1181,7 @@ public: bool DisableMacroExpansion) { EnterTokenStream(Toks.release(), NumToks, DisableMacroExpansion, true); } + void EnterTokenStream(ArrayRef<Token> Toks, bool DisableMacroExpansion) { EnterTokenStream(Toks.data(), Toks.size(), DisableMacroExpansion, false); } @@ -1605,7 +1700,6 @@ private: llvm::DenseMap<IdentifierInfo*,unsigned> PoisonReasons; public: - /// \brief Specifies the reason for poisoning an identifier. /// /// If that identifier is accessed while poisoned, then this reason will be @@ -1655,7 +1749,6 @@ public: /// lex again. bool HandleIdentifier(Token &Identifier); - /// \brief Callback invoked when the lexer hits the end of the current file. /// /// This either returns the EOF token and returns true, or @@ -1760,6 +1853,8 @@ public: Module *LeaveSubmodule(bool ForPragma); private: + friend void TokenLexer::ExpandFunctionArguments(); + void PushIncludeMacroStack() { assert(CurLexerKind != CLK_CachingLexer && "cannot push a caching lexer"); IncludeMacroStack.emplace_back(CurLexerKind, CurLexerSubmodule, @@ -1818,7 +1913,6 @@ private: /// /// Either returns a pointer to a MacroInfo object OR emits a diagnostic and /// returns a nullptr if an invalid sequence of tokens is encountered. - MacroInfo *ReadOptionalMacroParameterListAndBody( const Token &MacroNameTok, bool ImmediatelyAfterHeaderGuard); @@ -1836,7 +1930,8 @@ private: /// \p FoundElse is false, then \#else directives are ok, if not, then we have /// already seen one so a \#else directive is a duplicate. When this returns, /// the caller can lex the first valid token. - void SkipExcludedConditionalBlock(SourceLocation IfTokenLoc, + void SkipExcludedConditionalBlock(SourceLocation HashTokenLoc, + SourceLocation IfTokenLoc, bool FoundNonSkipPortion, bool FoundElse, SourceLocation ElseLoc = SourceLocation()); @@ -1848,6 +1943,7 @@ private: struct DirectiveEvalResult { /// Whether the expression was evaluated as true or not. bool Conditional; + /// True if the expression contained identifiers that were undefined. bool IncludedUndefinedIds; }; @@ -1877,8 +1973,8 @@ private: /// from the end of the cache. Token *cacheMacroExpandedTokens(TokenLexer *tokLexer, ArrayRef<Token> tokens); + void removeCachedMacroExpandedTokensOfLastLexer(); - friend void TokenLexer::ExpandFunctionArguments(); /// Determine whether the next preprocessor token to be /// lexed is a '('. If so, consume the token and return true, if not, this @@ -1934,17 +2030,21 @@ private: //===--------------------------------------------------------------------===// // Caching stuff. void CachingLex(Token &Result); + 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 && !CurTokenLexer && !CurPTHLexer && !IncludeMacroStack.empty(); } + void EnterCachingLexMode(); + void ExitCachingLexMode() { if (InCachingLexMode()) RemoveTopOfLexerStack(); } + const Token &PeekAhead(unsigned N); void AnnotatePreviousCachedTokens(const Token &Tok); @@ -2015,9 +2115,15 @@ public: PreambleConditionalStack.setStack(s); } - void setReplayablePreambleConditionalStack(ArrayRef<PPConditionalInfo> s) { + void setReplayablePreambleConditionalStack(ArrayRef<PPConditionalInfo> s, + llvm::Optional<PreambleSkipInfo> SkipInfo) { PreambleConditionalStack.startReplaying(); PreambleConditionalStack.setStack(s); + PreambleConditionalStack.SkipInfo = SkipInfo; + } + + llvm::Optional<PreambleSkipInfo> getPreambleSkipInfo() const { + return PreambleConditionalStack.SkipInfo; } private: @@ -2030,16 +2136,18 @@ private: void HandleUndefDirective(); // Conditional Inclusion. - void HandleIfdefDirective(Token &Tok, bool isIfndef, - bool ReadAnyTokensBeforeDirective); - void HandleIfDirective(Token &Tok, bool ReadAnyTokensBeforeDirective); + void HandleIfdefDirective(Token &Tok, const Token &HashToken, + bool isIfndef, bool ReadAnyTokensBeforeDirective); + void HandleIfDirective(Token &Tok, const Token &HashToken, + bool ReadAnyTokensBeforeDirective); void HandleEndifDirective(Token &Tok); - void HandleElseDirective(Token &Tok); - void HandleElifDirective(Token &Tok); + void HandleElseDirective(Token &Tok, const Token &HashToken); + void HandleElifDirective(Token &Tok, const Token &HashToken); // Pragmas. void HandlePragmaDirective(SourceLocation IntroducerLoc, PragmaIntroducerKind Introducer); + public: void HandlePragmaOnce(Token &OnceTok); void HandlePragmaMark(); @@ -2073,8 +2181,8 @@ public: }; /// \brief Registry of pragma handlers added by plugins -typedef llvm::Registry<PragmaHandler> PragmaHandlerRegistry; +using PragmaHandlerRegistry = llvm::Registry<PragmaHandler>; -} // end namespace clang +} // namespace clang -#endif +#endif // LLVM_CLANG_LEX_PREPROCESSOR_H diff --git a/include/clang/Lex/PreprocessorLexer.h b/include/clang/Lex/PreprocessorLexer.h index 5c2e4d41454b..ff71d11b4511 100644 --- a/include/clang/Lex/PreprocessorLexer.h +++ b/include/clang/Lex/PreprocessorLexer.h @@ -1,4 +1,4 @@ -//===--- PreprocessorLexer.h - C Language Family Lexer ----------*- C++ -*-===// +//===- PreprocessorLexer.h - C Language Family Lexer ------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -6,10 +6,10 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -/// +// /// \file /// \brief Defines the PreprocessorLexer interface. -/// +// //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_LEX_PREPROCESSORLEXER_H @@ -17,8 +17,10 @@ #include "clang/Lex/MultipleIncludeOpt.h" #include "clang/Lex/Token.h" +#include "clang/Basic/SourceLocation.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallVector.h" +#include <cassert> namespace clang { @@ -27,25 +29,29 @@ class Preprocessor; class PreprocessorLexer { virtual void anchor(); + protected: - Preprocessor *PP; // Preprocessor object controlling lexing. + friend class Preprocessor; + + // Preprocessor object controlling lexing. + Preprocessor *PP = nullptr; /// The SourceManager FileID corresponding to the file being lexed. const FileID FID; /// \brief Number of SLocEntries before lexing the file. - unsigned InitialNumSLocEntries; + unsigned InitialNumSLocEntries = 0; //===--------------------------------------------------------------------===// // Context-specific lexing flags set by the preprocessor. //===--------------------------------------------------------------------===// /// \brief True when parsing \#XXX; turns '\\n' into a tok::eod token. - bool ParsingPreprocessorDirective; + bool ParsingPreprocessorDirective = false; /// \brief True after \#include; turns \<xx> into a tok::angle_string_literal /// token. - bool ParsingFilename; + bool ParsingFilename = false; /// \brief True if in raw mode. /// @@ -60,7 +66,7 @@ protected: /// 5. No callbacks are made into the preprocessor. /// /// Note that in raw mode that the PP pointer may be null. - bool LexingRawMode; + bool LexingRawMode = false; /// \brief A state machine that detects the \#ifndef-wrapping a file /// idiom for the multiple-include optimization. @@ -70,19 +76,9 @@ protected: /// we are currently in. SmallVector<PPConditionalInfo, 4> ConditionalStack; - PreprocessorLexer(const PreprocessorLexer &) = delete; - void operator=(const PreprocessorLexer &) = delete; - friend class Preprocessor; - + PreprocessorLexer() : FID() {} PreprocessorLexer(Preprocessor *pp, FileID fid); - - PreprocessorLexer() - : PP(nullptr), InitialNumSLocEntries(0), - ParsingPreprocessorDirective(false), - ParsingFilename(false), - LexingRawMode(false) {} - - virtual ~PreprocessorLexer() {} + virtual ~PreprocessorLexer() = default; virtual void IndirectLex(Token& Result) = 0; @@ -128,6 +124,8 @@ protected: unsigned getConditionalStackDepth() const { return ConditionalStack.size(); } public: + PreprocessorLexer(const PreprocessorLexer &) = delete; + PreprocessorLexer &operator=(const PreprocessorLexer &) = delete; //===--------------------------------------------------------------------===// // Misc. lexing methods. @@ -168,12 +166,13 @@ public: /// \brief Iterator that traverses the current stack of preprocessor /// conditional directives (\#if/\#ifdef/\#ifndef). - typedef SmallVectorImpl<PPConditionalInfo>::const_iterator - conditional_iterator; + using conditional_iterator = + SmallVectorImpl<PPConditionalInfo>::const_iterator; conditional_iterator conditional_begin() const { return ConditionalStack.begin(); } + conditional_iterator conditional_end() const { return ConditionalStack.end(); } @@ -184,6 +183,6 @@ public: } }; -} // end namespace clang +} // namespace clang -#endif +#endif // LLVM_CLANG_LEX_PREPROCESSORLEXER_H diff --git a/include/clang/Lex/PreprocessorOptions.h b/include/clang/Lex/PreprocessorOptions.h index d91c665cf1dd..55fc305dc295 100644 --- a/include/clang/Lex/PreprocessorOptions.h +++ b/include/clang/Lex/PreprocessorOptions.h @@ -1,4 +1,4 @@ -//===--- PreprocessorOptions.h ----------------------------------*- C++ -*-===// +//===- PreprocessorOptions.h ------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -10,30 +10,30 @@ #ifndef LLVM_CLANG_LEX_PREPROCESSOROPTIONS_H_ #define LLVM_CLANG_LEX_PREPROCESSOROPTIONS_H_ -#include "clang/Basic/SourceLocation.h" -#include "llvm/ADT/IntrusiveRefCntPtr.h" +#include "clang/Basic/LLVM.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSet.h" -#include <cassert> +#include <memory> #include <set> #include <string> #include <utility> #include <vector> namespace llvm { - class MemoryBuffer; -} -namespace clang { +class MemoryBuffer; + +} // namespace llvm -class Preprocessor; -class LangOptions; +namespace clang { /// \brief Enumerate the kinds of standard library that enum ObjCXXARCStandardLibraryKind { ARCXX_nolib, + /// \brief libc++ ARCXX_libcxx, + /// \brief libstdc++ ARCXX_libstdcxx }; @@ -42,17 +42,17 @@ enum ObjCXXARCStandardLibraryKind { /// used in preprocessor initialization to InitializePreprocessor(). class PreprocessorOptions { public: - std::vector<std::pair<std::string, bool/*isUndef*/> > Macros; + std::vector<std::pair<std::string, bool/*isUndef*/>> Macros; std::vector<std::string> Includes; std::vector<std::string> MacroIncludes; /// \brief Initialize the preprocessor with the compiler and target specific /// predefines. - unsigned UsePredefines : 1; + bool UsePredefines = true; /// \brief Whether we should maintain a detailed record of all macro /// definitions and expansions. - unsigned DetailedRecord : 1; + bool DetailedRecord = false; /// The implicit PCH included at the start of the translation unit, or empty. std::string ImplicitPCHInclude; @@ -62,13 +62,13 @@ public: /// \brief When true, disables most of the normal validation performed on /// precompiled headers. - bool DisablePCHValidation; + bool DisablePCHValidation = false; /// \brief When true, a PCH with compiler errors will not be rejected. - bool AllowPCHWithCompilerErrors; + bool AllowPCHWithCompilerErrors = false; /// \brief Dump declarations that are deserialized from PCH, for testing. - bool DumpDeserializedPCHDecls; + bool DumpDeserializedPCHDecls = false; /// \brief This is a set of names for decls that we do not want to be /// deserialized, and we emit an error if they are; for testing purposes. @@ -86,7 +86,7 @@ public: /// When the lexer is done, one of the things that need to be preserved is the /// conditional #if stack, so the ASTWriter/ASTReader can save/restore it when /// processing the rest of the file. - bool GeneratePreamble; + bool GeneratePreamble = false; /// The implicit PTH input included at the start of the translation unit, or /// empty. @@ -107,7 +107,7 @@ public: /// \brief True if the SourceManager should report the original file name for /// contents of files that were remapped to other files. Defaults to true. - bool RemappedFilesKeepOriginalName; + bool RemappedFilesKeepOriginalName = true; /// \brief The set of file remappings, which take existing files on /// the system (the first part of each pair) and gives them the @@ -126,12 +126,12 @@ public: /// This flag defaults to false; it can be set true only through direct /// manipulation of the compiler invocation object, in cases where the /// compiler invocation and its buffers will be reused. - bool RetainRemappedFileBuffers; + bool RetainRemappedFileBuffers = false; /// \brief The Objective-C++ ARC standard library that we should support, /// by providing appropriate definitions to retrofit the standard library /// with support for lifetime-qualified pointers. - ObjCXXARCStandardLibraryKind ObjCXXARCStandardLibrary; + ObjCXXARCStandardLibraryKind ObjCXXARCStandardLibrary = ARCXX_nolib; /// \brief Records the set of modules class FailedModulesSet { @@ -156,18 +156,11 @@ public: std::shared_ptr<FailedModulesSet> FailedModules; public: - PreprocessorOptions() : UsePredefines(true), DetailedRecord(false), - DisablePCHValidation(false), - AllowPCHWithCompilerErrors(false), - DumpDeserializedPCHDecls(false), - PrecompiledPreambleBytes(0, true), - GeneratePreamble(false), - RemappedFilesKeepOriginalName(true), - RetainRemappedFileBuffers(false), - ObjCXXARCStandardLibrary(ARCXX_nolib) { } + PreprocessorOptions() : PrecompiledPreambleBytes(0, false) {} void addMacroDef(StringRef Name) { Macros.emplace_back(Name, false); } void addMacroUndef(StringRef Name) { Macros.emplace_back(Name, true); } + void addRemappedFile(StringRef From, StringRef To) { RemappedFiles.emplace_back(From, To); } @@ -195,10 +188,10 @@ public: LexEditorPlaceholders = true; RetainRemappedFileBuffers = true; PrecompiledPreambleBytes.first = 0; - PrecompiledPreambleBytes.second = 0; + PrecompiledPreambleBytes.second = false; } }; -} // end namespace clang +} // namespace clang -#endif +#endif // LLVM_CLANG_LEX_PREPROCESSOROPTIONS_H_ diff --git a/include/clang/Lex/TokenLexer.h b/include/clang/Lex/TokenLexer.h index fdeed44d8f9b..b8b0beabf2ba 100644 --- a/include/clang/Lex/TokenLexer.h +++ b/include/clang/Lex/TokenLexer.h @@ -1,4 +1,4 @@ -//===--- TokenLexer.h - Lex from a token buffer -----------------*- C++ -*-===// +//===- TokenLexer.h - Lex from a token buffer -------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -15,29 +15,31 @@ #define LLVM_CLANG_LEX_TOKENLEXER_H #include "clang/Basic/SourceLocation.h" +#include "llvm/ADT/ArrayRef.h" namespace clang { - class MacroInfo; - class Preprocessor; - class Token; - class MacroArgs; + +class MacroArgs; +class MacroInfo; +class Preprocessor; +class Token; +class VAOptExpansionContext; /// TokenLexer - This implements a lexer that returns tokens from a macro body /// or token stream instead of lexing from a character buffer. This is used for /// macro expansion and _Pragma handling, for example. -/// class TokenLexer { + friend class Preprocessor; + /// Macro - The macro we are expanding from. This is null if expanding a /// token stream. - /// - MacroInfo *Macro; + MacroInfo *Macro = nullptr; /// ActualArgs - The actual arguments specified for a function-like macro, or /// null. The TokenLexer owns the pointed-to object. - MacroArgs *ActualArgs; + MacroArgs *ActualArgs = nullptr; /// PP - The current preprocessor object we are expanding for. - /// Preprocessor &PP; /// Tokens - This is the pointer to an array of tokens that the macro is @@ -49,15 +51,12 @@ class TokenLexer { /// Note that if it points into Preprocessor's cache buffer, the Preprocessor /// may update the pointer as needed. const Token *Tokens; - friend class Preprocessor; /// NumTokens - This is the length of the Tokens array. - /// unsigned NumTokens; - /// CurToken - This is the next token that Lex will return. - /// - unsigned CurToken; + /// This is the index of the next token that Lex will return. + unsigned CurTokenIdx; /// ExpandLocStart/End - The source location range where this macro was /// expanded. @@ -73,6 +72,7 @@ class TokenLexer { /// \brief Location of the macro definition. SourceLocation MacroDefStart; + /// \brief Length of the macro definition. unsigned MacroDefLength; @@ -99,8 +99,6 @@ class TokenLexer { /// should not be subject to further macro expansion. bool DisableMacroExpansion : 1; - TokenLexer(const TokenLexer &) = delete; - void operator=(const TokenLexer &) = delete; public: /// Create a TokenLexer for the specified macro with the specified actual /// arguments. Note that this ctor takes ownership of the ActualArgs pointer. @@ -108,26 +106,30 @@ public: /// identifier for an object-like macro. TokenLexer(Token &Tok, SourceLocation ILEnd, MacroInfo *MI, MacroArgs *ActualArgs, Preprocessor &pp) - : Macro(nullptr), ActualArgs(nullptr), PP(pp), OwnsTokens(false) { + : PP(pp), OwnsTokens(false) { Init(Tok, ILEnd, MI, ActualArgs); } - /// Init - Initialize this TokenLexer to expand from the specified macro - /// with the specified argument information. Note that this ctor takes - /// ownership of the ActualArgs pointer. ILEnd specifies the location of the - /// ')' for a function-like macro or the identifier for an object-like macro. - void Init(Token &Tok, SourceLocation ILEnd, MacroInfo *MI, - MacroArgs *ActualArgs); - /// Create a TokenLexer for the specified token stream. If 'OwnsTokens' is /// specified, this takes ownership of the tokens and delete[]'s them when /// the token lexer is empty. TokenLexer(const Token *TokArray, unsigned NumToks, bool DisableExpansion, bool ownsTokens, Preprocessor &pp) - : Macro(nullptr), ActualArgs(nullptr), PP(pp), OwnsTokens(false) { + : PP(pp), OwnsTokens(false) { Init(TokArray, NumToks, DisableExpansion, ownsTokens); } + TokenLexer(const TokenLexer &) = delete; + TokenLexer &operator=(const TokenLexer &) = delete; + ~TokenLexer() { destroy(); } + + /// Init - Initialize this TokenLexer to expand from the specified macro + /// with the specified argument information. Note that this ctor takes + /// ownership of the ActualArgs pointer. ILEnd specifies the location of the + /// ')' for a function-like macro or the identifier for an object-like macro. + void Init(Token &Tok, SourceLocation ILEnd, MacroInfo *MI, + MacroArgs *ActualArgs); + /// Init - Initialize this TokenLexer with the specified token stream. /// This does not take ownership of the specified token vector. /// @@ -136,8 +138,6 @@ public: void Init(const Token *TokArray, unsigned NumToks, bool DisableMacroExpansion, bool OwnsTokens); - ~TokenLexer() { destroy(); } - /// isNextTokenLParen - If the next token lexed will pop this macro off the /// expansion stack, return 2. If the next unexpanded token is a '(', return /// 1, otherwise return 0. @@ -156,15 +156,54 @@ private: /// isAtEnd - Return true if the next lex call will pop this macro off the /// include stack. bool isAtEnd() const { - return CurToken == NumTokens; + return CurTokenIdx == NumTokens; } - /// PasteTokens - Tok is the LHS of a ## operator, and CurToken is the ## - /// operator. Read the ## and RHS, and paste the LHS/RHS together. If there - /// are is another ## after it, chomp it iteratively. Return the result as - /// Tok. If this returns true, the caller should immediately return the + /// Concatenates the next (sub-)sequence of \p Tokens separated by '##' + /// starting with LHSTok - stopping when we encounter a token that is neither + /// '##' nor preceded by '##'. Places the result back into \p LHSTok and sets + /// \p CurIdx to point to the token following the last one that was pasted. + /// + /// Also performs the MSVC extension wide-literal token pasting involved with: + /// \code L #macro-arg. \endcode + /// + /// \param[in,out] LHSTok - Contains the token to the left of '##' in \p + /// Tokens upon entry and will contain the resulting concatenated Token upon + /// exit. + /// + /// \param[in] TokenStream - The stream of Tokens we are lexing from. + /// + /// \param[in,out] CurIdx - Upon entry, \pTokens[\pCurIdx] must equal '##' + /// (with the exception of the MSVC extension mentioned above). Upon exit, it + /// is set to the index of the token following the last token that was + /// concatenated together. + /// + /// \returns If this returns true, the caller should immediately return the /// token. - bool PasteTokens(Token &Tok); + bool pasteTokens(Token &LHSTok, ArrayRef<Token> TokenStream, + unsigned int &CurIdx); + + /// Calls pasteTokens above, passing in the '*this' object's Tokens and + /// CurTokenIdx data members. + bool pasteTokens(Token &Tok); + + + /// Takes the tail sequence of tokens within ReplacementToks that represent + /// the just expanded __VA_OPT__ tokens (possibly zero tokens) and transforms + /// them into a string. \p VCtx is used to determine which token represents + /// the first __VA_OPT__ replacement token. + /// + /// \param[in,out] ReplacementToks - Contains the current Replacement Tokens + /// (prior to rescanning and token pasting), the tail end of which represents + /// the tokens just expanded through __VA_OPT__ processing. These (sub) + /// sequence of tokens are folded into one stringified token. + /// + /// \param[in] VCtx - contains relevent contextual information about the + /// state of the tokens around and including the __VA_OPT__ token, necessary + /// for stringification. + void stringifyVAOPTContents(SmallVectorImpl<Token> &ReplacementToks, + const VAOptExpansionContext &VCtx, + SourceLocation VAOPTClosingParenLoc); /// Expand the arguments of a function-like macro so that we can quickly /// return preexpanded tokens from Tokens. @@ -200,6 +239,6 @@ private: void PropagateLineStartLeadingSpaceInfo(Token &Result); }; -} // end namespace clang +} // namespace clang -#endif +#endif // LLVM_CLANG_LEX_TOKENLEXER_H diff --git a/include/clang/Lex/VariadicMacroSupport.h b/include/clang/Lex/VariadicMacroSupport.h new file mode 100644 index 000000000000..cebaf15187de --- /dev/null +++ b/include/clang/Lex/VariadicMacroSupport.h @@ -0,0 +1,226 @@ +//===- VariadicMacroSupport.h - state machines and scope guards -*- 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 support types to help with preprocessing variadic macro +// (i.e. macros that use: ellipses __VA_ARGS__ ) definitions and +// expansions. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_LEX_VARIADICMACROSUPPORT_H +#define LLVM_CLANG_LEX_VARIADICMACROSUPPORT_H + +#include "clang/Lex/Preprocessor.h" +#include "llvm/ADT/SmallVector.h" + +namespace clang { + class Preprocessor; + + /// An RAII class that tracks when the Preprocessor starts and stops lexing + /// the definition of a (ISO C/C++) variadic macro. As an example, this is + /// useful for unpoisoning and repoisoning certain identifiers (such as + /// __VA_ARGS__) that are only allowed in this context. Also, being a friend + /// of the Preprocessor class allows it to access PP's cached identifiers + /// directly (as opposed to performing a lookup each time). + class VariadicMacroScopeGuard { + const Preprocessor &PP; + IdentifierInfo *const Ident__VA_ARGS__; + IdentifierInfo *const Ident__VA_OPT__; + + public: + VariadicMacroScopeGuard(const Preprocessor &P) + : PP(P), Ident__VA_ARGS__(PP.Ident__VA_ARGS__), + Ident__VA_OPT__(PP.Ident__VA_OPT__) { + assert(Ident__VA_ARGS__->isPoisoned() && "__VA_ARGS__ should be poisoned " + "outside an ISO C/C++ variadic " + "macro definition!"); + assert( + !Ident__VA_OPT__ || + (Ident__VA_OPT__->isPoisoned() && "__VA_OPT__ should be poisoned!")); + } + + /// Client code should call this function just before the Preprocessor is + /// about to Lex tokens from the definition of a variadic (ISO C/C++) macro. + void enterScope() { + Ident__VA_ARGS__->setIsPoisoned(false); + if (Ident__VA_OPT__) + Ident__VA_OPT__->setIsPoisoned(false); + } + + /// Client code should call this function as soon as the Preprocessor has + /// either completed lexing the macro's definition tokens, or an error + /// occured and the context is being exited. This function is idempotent + /// (might be explicitly called, and then reinvoked via the destructor). + void exitScope() { + Ident__VA_ARGS__->setIsPoisoned(true); + if (Ident__VA_OPT__) + Ident__VA_OPT__->setIsPoisoned(true); + } + + ~VariadicMacroScopeGuard() { exitScope(); } + }; + + /// \brief A class for tracking whether we're inside a VA_OPT during a + /// traversal of the tokens of a variadic macro definition. + class VAOptDefinitionContext { + /// Contains all the locations of so far unmatched lparens. + SmallVector<SourceLocation, 8> UnmatchedOpeningParens; + + const IdentifierInfo *const Ident__VA_OPT__; + + + public: + VAOptDefinitionContext(Preprocessor &PP) + : Ident__VA_OPT__(PP.Ident__VA_OPT__) {} + + bool isVAOptToken(const Token &T) const { + return Ident__VA_OPT__ && T.getIdentifierInfo() == Ident__VA_OPT__; + } + + /// Returns true if we have seen the __VA_OPT__ and '(' but before having + /// seen the matching ')'. + bool isInVAOpt() const { return UnmatchedOpeningParens.size(); } + + /// Call this function as soon as you see __VA_OPT__ and '('. + void sawVAOptFollowedByOpeningParens(const SourceLocation LParenLoc) { + assert(!isInVAOpt() && "Must NOT be within VAOPT context to call this"); + UnmatchedOpeningParens.push_back(LParenLoc); + + } + + SourceLocation getUnmatchedOpeningParenLoc() const { + assert(isInVAOpt() && "Must be within VAOPT context to call this"); + return UnmatchedOpeningParens.back(); + } + + /// Call this function each time an rparen is seen. It returns true only if + /// the rparen that was just seen was the eventual (non-nested) closing + /// paren for VAOPT, and ejects us out of the VAOPT context. + bool sawClosingParen() { + assert(isInVAOpt() && "Must be within VAOPT context to call this"); + UnmatchedOpeningParens.pop_back(); + return !UnmatchedOpeningParens.size(); + } + + /// Call this function each time an lparen is seen. + void sawOpeningParen(SourceLocation LParenLoc) { + assert(isInVAOpt() && "Must be within VAOPT context to call this"); + UnmatchedOpeningParens.push_back(LParenLoc); + } + + }; + + /// \brief A class for tracking whether we're inside a VA_OPT during a + /// traversal of the tokens of a macro during macro expansion. + class VAOptExpansionContext : VAOptDefinitionContext { + + Token SyntheticEOFToken; + + // The (spelling) location of the current __VA_OPT__ in the replacement list + // of the function-like macro being expanded. + SourceLocation VAOptLoc; + + // NumOfTokensPriorToVAOpt : when != -1, contains the index *of* the first + // token of the current VAOPT contents (so we know where to start eager + // token-pasting and stringification) *within* the substituted tokens of + // the function-like macro's new replacement list. + int NumOfTokensPriorToVAOpt = -1; + + unsigned LeadingSpaceForStringifiedToken : 1; + + unsigned StringifyBefore : 1; + unsigned CharifyBefore : 1; + + + bool hasStringifyBefore() const { + assert(!isReset() && + "Must only be called if the state has not been reset"); + return StringifyBefore; + } + + bool isReset() const { + return NumOfTokensPriorToVAOpt == -1 || + VAOptLoc.isInvalid(); + } + + public: + VAOptExpansionContext(Preprocessor &PP) + : VAOptDefinitionContext(PP), LeadingSpaceForStringifiedToken(false), + StringifyBefore(false), CharifyBefore(false) { + SyntheticEOFToken.startToken(); + SyntheticEOFToken.setKind(tok::eof); + } + + void reset() { + VAOptLoc = SourceLocation(); + NumOfTokensPriorToVAOpt = -1; + LeadingSpaceForStringifiedToken = false; + StringifyBefore = false; + CharifyBefore = false; + } + + const Token &getEOFTok() const { return SyntheticEOFToken; } + + void sawHashOrHashAtBefore(const bool HasLeadingSpace, + const bool IsHashAt) { + + StringifyBefore = !IsHashAt; + CharifyBefore = IsHashAt; + LeadingSpaceForStringifiedToken = HasLeadingSpace; + } + + + + bool hasCharifyBefore() const { + assert(!isReset() && + "Must only be called if the state has not been reset"); + return CharifyBefore; + } + bool hasStringifyOrCharifyBefore() const { + return hasStringifyBefore() || hasCharifyBefore(); + } + + unsigned int getNumberOfTokensPriorToVAOpt() const { + assert(!isReset() && + "Must only be called if the state has not been reset"); + return NumOfTokensPriorToVAOpt; + } + + bool getLeadingSpaceForStringifiedToken() const { + assert(hasStringifyBefore() && + "Must only be called if this has been marked for stringification"); + return LeadingSpaceForStringifiedToken; + } + + void sawVAOptFollowedByOpeningParens(const SourceLocation VAOptLoc, + const unsigned int NumPriorTokens) { + assert(VAOptLoc.isFileID() && "Must not come from a macro expansion"); + assert(isReset() && "Must only be called if the state has been reset"); + VAOptDefinitionContext::sawVAOptFollowedByOpeningParens(SourceLocation()); + this->VAOptLoc = VAOptLoc; + NumOfTokensPriorToVAOpt = NumPriorTokens; + assert(NumOfTokensPriorToVAOpt > -1 && + "Too many prior tokens"); + } + + SourceLocation getVAOptLoc() const { + assert(!isReset() && + "Must only be called if the state has not been reset"); + assert(VAOptLoc.isValid() && "__VA_OPT__ location must be valid"); + return VAOptLoc; + } + using VAOptDefinitionContext::isVAOptToken; + using VAOptDefinitionContext::isInVAOpt; + using VAOptDefinitionContext::sawClosingParen; + using VAOptDefinitionContext::sawOpeningParen; + + }; +} // end namespace clang + +#endif |